Komut satırı parametreleri olduğunda bir programın çekirdek döküm dosyasını GDB ile nasıl analiz edebilirim?


156

Programım şu şekilde çalışıyor:

exe -p param1 -i param2 -o param3

Çöktü ve bir çekirdek döküm dosyası oluşturdu core.pid.

Çekirdek döküm dosyasını analiz etmek istiyorum

gdb ./exe -p param1 -i param2 -o param3 core.pid

Ancak GDB, EXE dosyasının parametrelerini GDB'nin girdisi olarak tanır.

Bu durumda bir çekirdek döküm dosyasını nasıl analiz edebilirim?


1
Linux exegibi bir kabuk betiği olmadığından (bazı değişkenleri ayarlamak vb.) Emin değil misiniz firefox?
Basile Starynkevitch

Yanıtlar:


182

Çekirdeği GDB ile birçok şekilde kullanabilirsiniz, ancak çalıştırılabilir dosyaya GDB'ye geçirilecek parametreleri iletmek çekirdek dosyayı kullanmanın yolu değildir. Bu hatayı almanızın nedeni de bu olabilir. Çekirdek dosyayı aşağıdaki şekillerde kullanabilirsiniz:

gdb <executable> <core-file>veya gdb <executable> -c <core-file>veya

gdb <executable>
...
(gdb) core <core-file>

Çekirdek dosyayı kullanırken argüman iletmeniz gerekmez. Çökme senaryosu GDB'de gösterilir (Ubuntu'da GDB sürüm 7.1 ile kontrol edilir).

Örneğin:

$ ./crash -p param1 -o param2
Segmentation fault (core dumped)
$ gdb ./crash core
GNU gdb (GDB) 7.1-ubuntu
...
Core was generated by `./crash -p param1 -o param2'. <<<<< See this line shows crash scenario
Program terminated with signal 11, Segmentation fault.
#0  __strlen_ia32 () at ../sysdeps/i386/i686/multiarch/../../i586/strlen.S:99
99    ../sysdeps/i386/i686/multiarch/../../i586/strlen.S: No such file or directory.
    in ../sysdeps/i386/i686/multiarch/../../i586/strlen.S
(gdb)

Parametreleri GDB'de hata ayıklanacak yürütülebilir dosyaya geçirmek istiyorsanız, --args .

Örneğin:

$ gdb --args ./crash -p param1 -o param2
GNU gdb (GDB) 7.1-ubuntu
...
(gdb) r
Starting program: /home/@@@@/crash -p param1 -o param2

Program received signal SIGSEGV, Segmentation fault.
__strlen_ia32 () at ../sysdeps/i386/i686/multiarch/../../i586/strlen.S:99
99    ../sysdeps/i386/i686/multiarch/../../i586/strlen.S: No such file or directory.
    in ../sysdeps/i386/i686/multiarch/../../i586/strlen.S
(gdb)

Man sayfaları diğer GDB seçeneklerini görmek için yardımcı olacaktır.


38

Karma döküm dosyalarında hata ayıklamak için GDB'nin basit kullanımı:

gdb <executable_path> <coredump_file_path>

"İşlem" için bir coredump dosyası "core.pid" dosyası olarak oluşturulur.

GDB istemine girdikten sonra (yukarıdaki komutun yürütülmesinde), şunu yazın:

...
(gdb) where

Bu, çökmenin / hatanın nedenini analiz edebileceğiniz yığının bilgisini size verecektir. Aynı amaçlar için diğer komutlar :

...
(gdb) bt full

Bu yukarıdakiyle aynıdır. Kural olarak, tüm yığın bilgilerini listeler (sonuçta çökme konumuna yol açar).


22

Sadece parametreleri atla. GDB'nin bunlara ihtiyacı yok:

gdb ./exe core.pid

Ama bu işe yaramıyor. Gdb çıkış uyarısı: çekirdek dosya belirtilen yürütülebilir dosyayla eşleşmeyebilir. Bellekten geçerli bir nesne dosyası görüntüsü okunamadı.
Treper

6
msgstr "çekirdek dosya belirtilen yürütülebilir dosya ile eşleşmeyebilir". Çekirdeği ürettikten sonra exe'yi değiştirdiniz mi? Belki de farklı komut satırı seçenekleriyle yeniden oluşturdunuz mu? GDB vermek çok önemlidir kesin çekirdeğini üretti aynı ikili. Eğer yapmazsan çöp çıkarırsın.
Rus

2
Ayrıca gdb'ye aktarılan ikili dosyanın soyulmadığından emin olun. Soyulup soyulmadığını gösteren 'file <binary name>' dosyasını çalıştırabilirsiniz.
Diwakar Sharma

12

objdump+ gdbminimum çalıştırılabilir örnek

TL; DR:

Şimdi tam eğitim testi kurulumu için:

main.c

#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int myfunc(int i) {
    *(int*)(NULL) = i; /* line 7 */
    return i - 1;
}

int main(int argc, char **argv) {
    /* Setup some memory. */
    char data_ptr[] = "string in data segment";
    char *mmap_ptr;
    char *text_ptr = "string in text segment";
    (void)argv;
    mmap_ptr = (char *)malloc(sizeof(data_ptr) + 1);
    strcpy(mmap_ptr, data_ptr);
    mmap_ptr[10] = 'm';
    mmap_ptr[11] = 'm';
    mmap_ptr[12] = 'a';
    mmap_ptr[13] = 'p';
    printf("text addr: %p\n", text_ptr);
    printf("data addr: %p\n", data_ptr);
    printf("mmap addr: %p\n", mmap_ptr);

    /* Call a function to prepare a stack trace. */
    return myfunc(argc);
}

Derleme ve çekirdek oluşturmak için çalıştırın:

gcc -ggdb3 -std=c99 -Wall -Wextra -pedantic -o main.out main.c
ulimit -c unlimited
rm -f core
./main.out

Çıktı:

text addr: 0x4007d4
data addr: 0x7ffec6739220
mmap addr: 0x1612010
Segmentation fault (core dumped)

GDB, segmentasyon hatasının gerçekleştiği tam satıra işaret ediyor, bu da çoğu kullanıcının hata ayıklama sırasında istediği şey:

gdb -q -nh main.out core

sonra:

Reading symbols from main.out...done.
[New LWP 27479]
Core was generated by `./main.out'.
Program terminated with signal SIGSEGV, Segmentation fault.
#0  0x0000000000400635 in myfunc (i=1) at main.c:7
7           *(int*)(NULL) = i;
(gdb) bt
#0  0x0000000000400635 in myfunc (i=1) at main.c:7
#1  0x000000000040072b in main (argc=1, argv=0x7ffec6739328) at main.c:28

bizi doğrudan buggy hattına yönlendiriyor 7.

CLI bağımsız değişkenleri çekirdek dosyada saklanır ve tekrar iletilmesine gerek yoktur

Belirli CLI bağımsız değişken sorularını yanıtlamak için, cli bağımsız değişkenlerini örneğin:

rm -f core
./main.out 1 2

bu, komutlarımızda herhangi bir değişiklik yapılmadan önceki koşulda yansıtılır:

Reading symbols from main.out...done.
[New LWP 21838]
Core was generated by `./main.out 1 2'.
Program terminated with signal SIGSEGV, Segmentation fault.
#0  0x0000564583cf2759 in myfunc (i=3) at main.c:7
7           *(int*)(NULL) = i; /* line 7 */
(gdb) bt
#0  0x0000564583cf2759 in myfunc (i=3) at main.c:7
#1  0x0000564583cf2858 in main (argc=3, argv=0x7ffcca4effa8) at main.c:2

Şimdi nasıl olduğuna dikkat edin argc=3. Bu nedenle bu, çekirdek dosyanın bu bilgileri sakladığı anlamına gelmelidir. Sanırım sadece argüman olarak saklıyormain diğer işlevlerin argümanlarını sakladığı gibi, argümanları olarak saklıyor.

Çekirdek dökümünün tüm hafızayı saklaması ve programın kayıt durumunu kaydetmesi gerektiğini düşünüyorsanız, bu nedenle geçerli yığındaki işlev bağımsız değişkenlerinin değerini belirlemek için gereken tüm bilgilere sahiptir.

Çevre değişkenlerinin nasıl denetleneceği daha az açıktır: Bir çekirdek dökümünden ortam değişkeni nasıl elde edilir Çevre değişkenleri de bellekte bulunur, bu nedenle objdump bu bilgileri içerir, ancak hepsini tek bir seferde nasıl listeleyeceğinizden emin değilim , aşağıdaki gibi tek tek testlerim üzerinde çalıştı:

p __environ[0]

Binutils analizi

Gibi binutils'ler araçlarını kullanarak readelfve objdumpbiz toplu dökümü bilgileri içerdiği olabilircore böyle hafıza devlet olarak dosyaya.

Çoğunluğu / tümü de GDB aracılığıyla görünür olmalıdır, ancak bu binutils araçları belirli kullanım durumları için daha toplu bir yaklaşım sunarken GDB daha etkileşimli bir keşif için daha uygundur.

İlk:

file core

bize coredosyanın aslında bir ELF dosyası olduğunu söyler :

core: ELF 64-bit LSB core file x86-64, version 1 (SYSV), SVR4-style, from './main.out'

bu yüzden her zamanki binutils araçlarıyla daha doğrudan inceleyebiliyoruz.

ELF standardına hızlı bir bakış , aslında kendisine ayrılmış bir ELF tipi olduğunu gösterir:

Elf32_Ehd.e_type == ET_CORE

Daha fazla format bilgisi şu adreste bulunabilir:

man 5 core

Sonra:

readelf -Wa core

dosya yapısı hakkında bazı ipuçları verir. Bellek, normal program başlıklarında yer alıyor gibi görünüyor:

Program Headers:
  Type           Offset   VirtAddr           PhysAddr           FileSiz  MemSiz   Flg Align
  NOTE           0x000468 0x0000000000000000 0x0000000000000000 0x000b9c 0x000000     0
  LOAD           0x002000 0x0000000000400000 0x0000000000000000 0x001000 0x001000 R E 0x1000
  LOAD           0x003000 0x0000000000600000 0x0000000000000000 0x001000 0x001000 R   0x1000
  LOAD           0x004000 0x0000000000601000 0x0000000000000000 0x001000 0x001000 RW  0x1000

ve notlar alanında daha fazla meta veri var, özellikle prstatusde PC'yi içeriyor :

Displaying notes found at file offset 0x00000468 with length 0x00000b9c:
  Owner                 Data size       Description
  CORE                 0x00000150       NT_PRSTATUS (prstatus structure)
  CORE                 0x00000088       NT_PRPSINFO (prpsinfo structure)
  CORE                 0x00000080       NT_SIGINFO (siginfo_t data)
  CORE                 0x00000130       NT_AUXV (auxiliary vector)
  CORE                 0x00000246       NT_FILE (mapped files)
    Page size: 4096
                 Start                 End         Page Offset
    0x0000000000400000  0x0000000000401000  0x0000000000000000
        /home/ciro/test/main.out
    0x0000000000600000  0x0000000000601000  0x0000000000000000
        /home/ciro/test/main.out
    0x0000000000601000  0x0000000000602000  0x0000000000000001
        /home/ciro/test/main.out
    0x00007f8d939ee000  0x00007f8d93bae000  0x0000000000000000
        /lib/x86_64-linux-gnu/libc-2.23.so
    0x00007f8d93bae000  0x00007f8d93dae000  0x00000000000001c0
        /lib/x86_64-linux-gnu/libc-2.23.so
    0x00007f8d93dae000  0x00007f8d93db2000  0x00000000000001c0
        /lib/x86_64-linux-gnu/libc-2.23.so
    0x00007f8d93db2000  0x00007f8d93db4000  0x00000000000001c4
        /lib/x86_64-linux-gnu/libc-2.23.so
    0x00007f8d93db8000  0x00007f8d93dde000  0x0000000000000000
        /lib/x86_64-linux-gnu/ld-2.23.so
    0x00007f8d93fdd000  0x00007f8d93fde000  0x0000000000000025
        /lib/x86_64-linux-gnu/ld-2.23.so
    0x00007f8d93fde000  0x00007f8d93fdf000  0x0000000000000026
        /lib/x86_64-linux-gnu/ld-2.23.so
  CORE                 0x00000200       NT_FPREGSET (floating point registers)
  LINUX                0x00000340       NT_X86_XSTATE (x86 XSAVE extended state)

objdump ile kolayca tüm bellek dökümü:

objdump -s core

içeren:

Contents of section load1:

 4007d0 01000200 73747269 6e672069 6e207465  ....string in te
 4007e0 78742073 65676d65 6e740074 65787420  xt segment.text 

Contents of section load15:

 7ffec6739220 73747269 6e672069 6e206461 74612073  string in data s
 7ffec6739230 65676d65 6e740000 00a8677b 9c6778cd  egment....g{.gx.

Contents of section load4:

 1612010 73747269 6e672069 6e206d6d 61702073  string in mmap s
 1612020 65676d65 6e740000 11040000 00000000  egment..........

ki bu, koşumuzdaki stdout değeriyle tam olarak eşleşiyor.

Bu, Ubuntu 16.04 amd64, GCC 6.4.0 ve binutils 2.26.1'de test edildi.


10

Gönderen RMS en GDB ayıklayıcı öğretici :

prompt > myprogram
Segmentation fault (core dumped)
prompt > gdb myprogram
...
(gdb) core core.pid
...

Dosyanızın gerçekten bir coreresim olduğundan emin olun - kullanarak kontrol edin file.


9

Biraz farklı bir yaklaşım GDB'yi tamamen atlamanızı sağlayacaktır. İstediğiniz tek şey bir geri izleme ise, Linux'a özgü 'catchsegv' yardımcı programı SIGSEGV'yi yakalar ve bir geri izleme görüntüler.


3

Yürütülebilir dosyanın argümanları olup olmadığı önemli değildir. Oluşturulan bir çekirdek dosyası olan herhangi bir ikili dosya üzerinde GDB çalıştırmak için sözdizimi aşağıdadır.

Syntax:
gdb <binary name> <generated core file>
Eg:
gdb l3_entity 6290-corefile

Daha fazla anlayış için aşağıdaki örneği alalım.

bash-4.1$ **gdb l3_entity 6290-corefile**

**Core was generated** by `/dir1/dir2/dir3/l3_entity **Program terminated with signal SIGABRT, Aborted.**
#0
#1
#2
#3
#4
#5
#6
#7
#8
#9
#10
(gdb)

Yukarıdaki çıktıdan, NULL erişim, SIGABORT vb.Gibi çekirdek hakkında bir şey tahmin edebilirsiniz.

Bu # 0 ila # 10 sayıları GDB'nin yığın kareleridir. Bu yığın çerçeveleri ikili dosyadan değildir. Yukarıdaki 0-10 karede yanlış bir şey olduğundan şüpheleniyorsanız o kareyi seçin

(gdb) frame 8

Şimdi bununla ilgili daha fazla ayrıntı görmek için:

(gdb) list +

Sorunu daha ayrıntılı incelemek için, şüphelenilen değişken değerlerini bu noktada buraya yazdırabilirsiniz.

(gdb) print thread_name

0

Sadece komutu yazın:

$ gdb <Binary> <codeDump>

Veya

$ gdb <binary>

$ gdb) core <coreDump>

Herhangi bir komut satırı argümanı sağlamaya gerek yoktur. Daha önceki bir alıştırma nedeniyle oluşturulan kod dökümü.


-1

Çekirdek döküm dosyasını "gdb" komutunu kullanarak analiz edebilirsiniz.

 gdb - The GNU Debugger

 syntax:

 # gdb executable-file core-file

 example: # gdb out.txt core.xxx 

1
out.txt yürütülebilir bir dosya mı? Bu yanıltıcı bir dosya uzantısı gibi görünüyor.
Alan
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.