Bagaimana cara menganalisis file dump inti program dengan GDB ketika memiliki parameter baris perintah?


156

Program saya beroperasi seperti ini:

exe -p param1 -i param2 -o param3

Itu crash dan menghasilkan file dump inti core.pid,.

Saya ingin menganalisis file dump inti

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

Tetapi GDB mengenali parameter dari file EXE sebagai input GDB.

Bagaimana cara menganalisis file dump inti dalam situasi ini?


1
Apakah Anda yakin Anda exebukan skrip shell (untuk mengatur beberapa variabel, dll.) Seperti misalnya firefoxdi Linux?
Basile Starynkevitch

Jawaban:


182

Anda dapat menggunakan inti dengan GDB dalam banyak cara, tetapi melewati parameter yang akan diteruskan ke dieksekusi ke GDB bukan cara untuk menggunakan file inti. Ini juga bisa menjadi alasan Anda mendapatkan kesalahan itu. Anda dapat menggunakan file inti dengan cara berikut:

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

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

Saat menggunakan file inti Anda tidak harus memberikan argumen. Skenario kerusakan ditampilkan di GDB (diperiksa dengan GDB versi 7.1 di Ubuntu).

Sebagai contoh:

$ ./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)

Jika Anda ingin meneruskan parameter ke executable untuk didebug di GDB, gunakan --args.

Sebagai contoh:

$ 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)

Halaman manual akan sangat membantu untuk melihat opsi GDB lainnya.


38

Penggunaan sederhana GDB, untuk men-debug file coredump:

gdb <executable_path> <coredump_file_path>

File coredump untuk "proses" akan dibuat sebagai file "core.pid".

Setelah Anda masuk ke dalam prompt GDB (pada pelaksanaan perintah di atas), ketik:

...
(gdb) where

Ini akan memberi Anda informasi, tentang tumpukan, di mana Anda dapat menganalisis penyebab crash / kesalahan. Perintah lain, untuk tujuan yang sama adalah:

...
(gdb) bt full

Ini sama dengan di atas. Dengan konvensi, ini mencantumkan seluruh informasi tumpukan (yang akhirnya mengarah ke lokasi macet).


22

Lewati saja parameternya. GDB tidak membutuhkannya:

gdb ./exe core.pid

Tetapi ini tidak berhasil. Peringatan keluaran gdb: file inti mungkin tidak cocok dengan file yang dapat dieksekusi yang ditentukan. Gagal membaca gambar file objek yang valid dari memori.
Treper

6
+ msgstr "file inti mungkin tidak cocok dengan eksekusi yang ditentukan". Apakah Anda memodifikasi exe setelah menghasilkan inti? Apakah Anda mungkin membangunnya kembali dengan opsi baris perintah yang berbeda? Sangat penting untuk memberikan GDB biner yang sama persis yang menghasilkan inti. Jika tidak, Anda akan mendapatkan sampah.
Dipekerjakan Rusia

2
Pastikan juga biner yang diteruskan ke gdb tidak dilucuti. Anda dapat menjalankan 'file <binary name>' yang menunjukkan itu dilucuti atau tidak.
Diwakar Sharma

12

objdump+ gdbcontoh runnable minimal

TL; DR:

Sekarang untuk pengaturan tes pendidikan penuh:

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);
}

Kompilasi, dan jalankan untuk menghasilkan inti:

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

Keluaran:

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

GDB mengarahkan kami ke baris yang tepat di mana kesalahan segmentasi terjadi, yang merupakan hal yang diinginkan sebagian besar pengguna saat melakukan debug:

gdb -q -nh main.out core

kemudian:

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

yang mengarahkan kita langsung ke buggy line 7.

Argumen CLI disimpan dalam file inti dan tidak perlu diteruskan lagi

Untuk menjawab pertanyaan argumen CLI tertentu, kita melihat bahwa jika kita mengubah argumen cli misalnya dengan:

rm -f core
./main.out 1 2

maka ini tercermin dalam bactrace sebelumnya tanpa perubahan pada perintah kami:

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

Jadi perhatikan bagaimana sekarang argc=3. Karena itu, ini harus berarti bahwa file inti menyimpan informasi itu. Saya kira itu hanya menyimpannya sebagai argumenmain , sama seperti menyimpan argumen dari fungsi lain.

Ini masuk akal jika Anda mempertimbangkan bahwa dump inti harus menyimpan seluruh memori dan mendaftar keadaan program, dan karena itu memiliki semua informasi yang diperlukan untuk menentukan nilai argumen fungsi pada tumpukan saat ini.

Yang kurang jelas adalah bagaimana memeriksa variabel lingkungan: Cara mendapatkan variabel lingkungan dari dump inti. Variabel lingkungan juga ada dalam memori sehingga objdump memang berisi informasi itu, tapi saya tidak yakin bagaimana mendaftar semuanya dalam sekali jalan dengan mudah , satu per satu sebagai berikut berhasil pada tes saya:

p __environ[0]

Analisis binutils

Dengan menggunakan alat-alat binutils seperti readelfdanobjdump , kita dapat membuang informasi yang terkandung dalam filecore file seperti keadaan memori.

Kebanyakan / semua itu juga harus terlihat melalui GDB, tetapi alat-alat binutils menawarkan pendekatan yang lebih massal yang nyaman untuk kasus penggunaan tertentu, sementara GDB lebih nyaman untuk eksplorasi yang lebih interaktif.

Pertama:

file core

memberi tahu kami bahwa corefile tersebut sebenarnya adalah file ELF :

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

itulah sebabnya kami dapat memeriksanya lebih langsung dengan alat binutils biasa.

Pandangan cepat pada standar ELF menunjukkan bahwa sebenarnya ada tipe ELF yang didedikasikan untuknya:

Elf32_Ehd.e_type == ET_CORE

Informasi format lebih lanjut dapat ditemukan di:

man 5 core

Kemudian:

readelf -Wa core

memberikan beberapa petunjuk tentang struktur file. Memori tampaknya terkandung dalam tajuk program reguler:

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

dan ada beberapa metadata yang ada di area catatan, terutama prstatusberisi PC :

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 dapat dengan mudah membuang semua memori dengan:

objdump -s core

yang mengandung:

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..........

yang cocok persis dengan nilai stdout dalam menjalankan kami.

Ini diuji pada Ubuntu 16.04 amd64, GCC 6.4.0, dan binutils 2.26.1.


10

Dari tutorial debugger GDB RMS :

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

Pastikan file Anda benar-benar coregambar - periksa menggunakan file.


9

Pendekatan yang sedikit berbeda akan memungkinkan Anda untuk melewati GDB sepenuhnya. Jika yang Anda inginkan adalah backtrace, utilitas khusus Linux 'catchsegv' akan menangkap SIGSEGV dan menampilkan backtrace.


3

Tidak masalah jika executable memiliki argumen atau tidak. Untuk menjalankan GDB pada sembarang biner dengan file inti yang dihasilkan, sintaksinya ada di bawah.

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

Biarkan saya mengambil contoh di bawah ini untuk lebih memahami.

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)

Dari output di atas, Anda dapat menebak sesuatu tentang inti, apakah itu akses NULL, SIGABORT, dll.

Angka-angka ini # 0 hingga # 10 adalah susunan bingkai GDB. Frame tumpukan ini bukan dari biner Anda. Dalam 0 - 10 bingkai di atas jika Anda mencurigai ada yang salah pilih bingkai itu

(gdb) frame 8

Sekarang untuk melihat detail lebih lanjut tentang itu:

(gdb) list +

Untuk menyelidiki masalah lebih lanjut, Anda dapat mencetak nilai-nilai variabel yang dicurigai di sini pada saat ini.

(gdb) print thread_name

0

Cukup ketik perintah:

$ gdb <Binary> <codeDump>

Atau

$ gdb <binary>

$ gdb) core <coreDump>

Tidak perlu memberikan argumen baris perintah. Dump kode yang dihasilkan karena latihan sebelumnya.


-1

Anda dapat menganalisis file dump inti menggunakan perintah "gdb".

 gdb - The GNU Debugger

 syntax:

 # gdb executable-file core-file

 example: # gdb out.txt core.xxx 

1
out.txt adalah file yang dapat dieksekusi? Itu sepertinya ekstensi file yang menyesatkan.
Alan
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.