Mengapa GDB membutuhkan executable dan juga core dump?

11

Saya sedang debug menggunakan core dumps, dan perhatikan bahwa gdb mengharuskan Anda untuk memasok file executable dan juga core dump. Kenapa ini? Jika core dump berisi semua memori yang digunakan proses, bukankah file executable terdapat di dalam core dump? Mungkin tidak ada jaminan bahwa seluruh exe dimuat ke dalam memori (executable individual biasanya tidak sebesar itu) atau mungkin core dump tidak mengandung semua memori yang relevan? Apakah itu untuk simbol (mungkin mereka tidak dimuat ke memori secara normal)?


sumber
1
Yang dapat dieksekusi berisi informasi simbol, seperti yang tercantum dalam dokumentasi gdb ...
Thomas Dickey
1
Anehnya, tidak ada jawaban (kecuali yang baru saya tambahkan) menyebutkan format DWARF
Basile Starynkevitch

Jawaban:

15

Core dump hanyalah dump dari jejak memori program Anda, jika Anda tahu di mana semuanya berada maka Anda bisa menggunakannya.

Anda menggunakan executable karena itu menjelaskan di mana (dalam hal alamat logis) hal-hal berada di memori, yaitu file inti.

Jika Anda menggunakan perintah, objdumpitu akan membuang data meta tentang objek yang dapat dieksekusi yang Anda selidiki. Menggunakan objek yang dapat dieksekusi bernama a.out sebagai contoh.

objdump -h a.outhanya membuang informasi tajuk, Anda akan melihat bagian bernama mis. DATA atau .bss atau .text (masih banyak lagi). Ini menginformasikan kernel loader di mana dalam objek berbagai bagian dapat ditemukan dan di mana dalam ruang alamat proses bagian harus dimuat, dan untuk beberapa bagian (misalnya. Data .text) apa yang harus dimuat. (Bagian .bss tidak mengandung data apa pun dalam file tetapi mengacu pada jumlah memori yang akan disimpan dalam proses untuk data yang tidak diinisialisasi, itu diisi dengan nol).

Tata letak file objek yang dapat dieksekusi sesuai dengan standar, ELF.

objdump -x a.out - kesedihan segalanya

Jika objek yang dapat dieksekusi masih berisi tabel simbolnya (belum dilucuti - man stripdan Anda digunakan -guntuk menghasilkan generasi debug dengan gcc asumsi kompilasi sumber ac), maka Anda dapat memeriksa konten inti dengan nama simbol, misalnya jika Anda memiliki variabel / buffer bernama inputLine di kode sumber Anda, Anda bisa menggunakan nama itu gdbuntuk melihat kontennya. yaitu gdbakan mengetahui offset dari awal program Anda menginisialisasi segmen data di mana inputLine dimulai dan panjang variabel itu.

Bacaan lebih lanjut Article1 , Pasal 2 , dan untuk spesifikasi Executable and Linking Format (ELF) yang sangat diperlukan .


Perbarui setelah komentar @mirabilos di bawah ini.

Tetapi jika menggunakan tabel simbol seperti pada

$ gdb --batch -s a.out -c core -q -ex "x buf1"

Menghasilkan

 0x601060 <buf1>:    0x72617453

dan kemudian tidak menggunakan tabel simbol dan memeriksa alamat langsung di,

$ gdb --batch -c core -q -ex "x 0x601060"

Menghasilkan

0x601060:   0x72617453

Saya telah memeriksa memori secara langsung tanpa menggunakan tabel simbol pada perintah ke-2.


Saya juga melihat, jawaban @ user580082 menambah penjelasan lebih lanjut, dan akan dimutakhirkan.

X Tian
sumber
6
Tidak pernah mendengar "bagian tumpukan dasar". .bs adalah (secara historis) "blok yang dimulai dengan simbol" dan praktis, "data yang disatukan", sedangkan .data adalah "data yang diinisialisasi" dan teks (bukan. kode) digunakan untuk menyimpan kode mesin. Tidak ada bagian tumpukan dalam biner, karena tumpukan dibuat pada saat dijalankan.
jlliagre
"Jika Anda tahu di mana semuanya berada maka Anda bisa menggunakannya" juga tidak benar karena tidak semua yang ada dalam program harus dimasukkan ke dalam footprint.
mirabilos
1
@ jlliagre Anda benar, saya keliru memanggil .text .code (karena saya sedang memikirkan penjelasan sambil menulis jawaban) - diperbarui. Saya keliru memikirkan bss dengan nama yang salah, dan telah memperbarui jawaban saya, tetapi menghindari * Blok Dimulai oleh Simbol karena saya tidak berpikir itu benar-benar menambah persamaan, dan telah menjelaskan itu digunakan sebagai data yang tidak diinisialisasi, yang kami pemahaman bersama. Terima kasih - Saya menghargai komentar Anda untuk memperbaiki posting ini.
X Tian
4

File inti adalah snapshot dari gambar tumpukan, pemetaan memori dan register pada saat penghentian proses. Konten yang dapat dimanipulasi seperti yang diberikan dalam halaman manual inti . Secara default pemetaan pribadi, pemetaan bersama dan informasi header ELF dibuang ke file inti.

Datang ke pertanyaan Anda , alasan bahwa gdb memerlukan executable adalah karena ia tidak mensimulasikan eksekusi, dengan membaca dan menafsirkan instruksi biner seperti valgrind yang sebaliknya menjadi induk dari proses sehingga untuk mengontrol perilaku proses selama menjalankan waktu. Ini menggunakan file inti untuk menentukan pemetaan memori dan keadaan proses prosesor selama crash.

Dalam Linux induk proses dapat memperoleh informasi tambahan tentang anak-anak mereka, khususnya kemampuan untuk melacak mereka yang memungkinkan debugger untuk mengakses informasi tingkat proses yang rendah seperti membaca / menulis ingatannya, register, mengubah pemetaan sinyal, menghentikan pelaksanaannya dll.

Anda akan memahami persyaratan yang dapat dieksekusi walaupun memiliki file inti lebih banyak setelah Anda membaca cara kerja setiap debugger.

enzim
sumber
1

(selain jawaban bagus lainnya)

Pada sistem Linux modern (dan banyak yang mirip Unix), informasi debug (termasuk meta-data tentang jenis simbol, lokasi kode sumber, jenis variabel, dll.) Dalam format DWARF dan duduk di dalam ELF yang dapat dieksekusi ( atau pustaka bersama ELF) saat dikompilasi dengan beberapa -gopsi. Saya merekomendasikan untuk mengkompilasi program yang akan di-debug -g3 -O0dan mungkin -fno-inlinejika menggunakan GCC baru-baru ini ; namun, dengan GCC Anda bahkan dapat mengkompilasi dengan kedua informasi pengoptimalan & debugging, mis. dengan -O2 -g1, meskipun info debug dalam kasus itu mungkin sedikit "kabur" (ini mungkin sedikit membantu untuk menangkap beberapa Heisenbugs nakal ).

Sangat masuk akal untuk menghindari menempatkan informasi itu dalam file inti , karena Anda mungkin memiliki banyak file inti yang berbeda (bayangkan perangkat lunak yang banyak digunakan dengan banyak pengguna membuat laporan bug, kebanyakan dari mereka dengan coredump) untuk dieksekusi yang sama. Juga file inti (5) dibuang oleh kernel, yang seharusnya tidak peduli tentang keberadaan bagian DWARF di elf (5) yang dapat dieksekusi (karena bagian ini tidak dipetakan ke dalam ruang alamat virtual dari proses kesalahan yang membuang inti pada beberapa sinyal ( 7) ). Bahkan ada kemungkinan untuk memiliki informasi debug yang dimasukkan ke dalam file terpisah (di luar yang dapat dieksekusi).

BTW, GDB dapat digunakan dengan menyakitkan untuk men-debug dump inti untuk executable tanpa informasi debug. Tetapi kemudian Anda secara praktis melakukan debug pada level kode mesin (bukan pada level simbolik yang disediakan oleh bahasa pemrograman dan kompilernya).

Basile Starynkevitch
sumber