Saya memasang biner di sistem saya, dan ingin melihat pembongkaran fungsi yang diberikan. Lebih disukai menggunakan objdump
, tetapi solusi lain juga dapat diterima.
Dari pertanyaan ini saya telah belajar bahwa saya mungkin dapat membongkar sebagian kode jika saya hanya mengetahui alamat batasnya. Dari jawaban ini saya telah belajar bagaimana mengubah simbol debug saya yang terpisah kembali menjadi satu file.
Tetapi bahkan beroperasi pada file tunggal itu, dan bahkan membongkar semua kode (yaitu tanpa alamat start atau stop, tetapi -d
parameter biasa ke objdump
), saya masih tidak melihat simbol itu di mana pun. Yang masuk akal sejauh fungsi yang dimaksud adalah statis, jadi tidak diekspor. Namun demikian, valgrind
akan melaporkan nama fungsi, sehingga harus disimpan di suatu tempat.
Melihat detail bagian debug, saya menemukan nama itu disebutkan di .debug_str
bagian tersebut, tetapi saya tidak tahu alat yang dapat mengubahnya menjadi rentang alamat.
static
, itu mungkin dimasukkan oleh kompilator ke dalam situs panggilannya. Ini mungkin berarti sebenarnya tidak ada fungsi untuk dibongkar, per se . Jika Anda dapat melihat simbol untuk fungsi lain, tetapi tidak untuk fungsi yang Anda cari, ini adalah petunjuk kuat bahwa fungsi tersebut telah sebaris. Valgrind mungkin masih mereferensikan fungsi pre-inline asli karena informasi debugging file ELF menyimpan dari mana setiap instruksi berasal, bahkan jika instruksi dipindahkan ke tempat lain.addr2line
akan menerima PC / IP daristdin
dan mencetak baris kode sumber yang sesuai. Demikian pula,objdump -l
akan mencampur objdump dengan baris sumber; meskipun untuk kode yang sangat dioptimalkan dengan inlining yang berat, hasil dari salah satu program tidak selalu sangat membantu.Jawaban:
Saya akan menyarankan menggunakan gdb sebagai pendekatan yang paling sederhana. Anda bahkan dapat melakukannya sebagai satu baris, seperti:
sumber
-ex 'command'
tidak masukman gdb
!? Namun sebenarnya tercantum dalam dokumen gdb . Juga untuk yang lain, hal-hal seperti/bin/ls
mungkin dilucuti, jadi jika perintah yang sama persis tidak menampilkan apa-apa, coba objek lain! Bisa juga menentukan file / objek sebagai argumen bareword; misalnya,gdb -batch -ex 'disassemble main' /bin/ls
gdb /bin/ls -batch -ex 'disassemble main'
bekerja jugacolumn -ts$'\t'
untuk memfilter keluaran GDB, Anda akan memiliki byte mentah dan kolom sumber selaras dengan baik. Juga,-ex 'set disassembly-flavor intel'
sebelum-ex
s lain akan menghasilkan sintaks perakitan Intel.disassemble fn
menggunakan metode di atas. Tetapi tampaknya ketika ada beberapa fungsi dengan nama yang sama di file biner, hanya satu yang dibongkar. Apakah mungkin untuk membongkar semuanya atau saya harus membongkar berdasarkan alamat mentah?gdb
disassemble/rs
untuk menunjukkan sumber dan byte mentah jugaDengan format ini, itu menjadi sangat dekat dengan
objdump -S
keluaran:main.c
Kompilasi dan bongkar
Membongkar:
Diuji pada Ubuntu 16.04, GDB 7.11.1.
objdump + solusi awk
Cetak paragraf seperti yang disebutkan di: /unix/82944/how-to-grep-for-text-in-a-file-and-display-the-paragraph-that-has-the -teks
misalnya:
memberikan hanya:
Saat menggunakan
-S
, saya rasa tidak ada cara yang terbukti gagal, karena komentar kode dapat berisi urutan yang mungkin ... Tetapi yang berikut ini berfungsi hampir sepanjang waktu:Diadaptasi dari: Bagaimana memilih garis antara dua pola penanda yang mungkin muncul beberapa kali dengan awk / sed
Balasan milis
Ada utas 2010 di milis yang mengatakan itu tidak mungkin: https://sourceware.org/ml/binutils/2010-04/msg00445.html
Selain
gdb
solusi yang diusulkan oleh Tom, mereka juga mengomentari solusi lain (lebih buruk) dari kompilasi-ffunction-section
yang menempatkan satu fungsi per bagian dan kemudian membuang bagian tersebut.Nicolas Clifton memberikan WONTFIX https://sourceware.org/ml/binutils/2015-07/msg00004.html , kemungkinan karena solusi GDB mencakup kasus penggunaan tersebut.
sumber
Bongkar Satu Fungsi Tunggal menggunakan Objdump
Saya punya dua solusi:
1. Berbasis Commandline
Metode ini bekerja dengan sempurna dan tambahan yang sederhana. Saya menggunakan objdump dengan -d flag dan menyalurkannya melalui awk . Output yang dibongkar terlihat seperti
Untuk memulainya, saya mulai dengan deskripsi output objdump. Sebuah bagian atau fungsi dipisahkan oleh baris kosong. Oleh karena itu, mengubah FS (Pemisah Bidang) menjadi baris baru dan RS (Pemisah Rekaman) menjadi dua kali baris baru memungkinkan Anda dengan mudah mencari fungsi yang direkomendasikan, karena ini hanya untuk menemukan dalam bidang $ 1!
Tentu saja Anda dapat mengganti main dengan fungsi lain yang ingin Anda cetak.
2. Skrip Bash
Saya telah menulis skrip bash kecil untuk masalah ini. Tempel dan salin dan simpan sebagai misalnya file dasm .
Ubah x-access dan panggil dengan misalnya:
Ini jauh lebih cepat daripada menjalankan gdb dengan sebuah skrip. Selain cara menggunakan objdump tidak akan memuat perpustakaan ke dalam memori dan karena itu lebih aman!
Vitaly Fadeev memprogram pelengkapan otomatis untuk skrip ini, yang merupakan fitur bagus dan mempercepat pengetikan.
Scriptnya dapat ditemukan di sini .
sumber
objdump
ataugdb
lebih cepat. Untuk biner yang sangat besar (Firefox 'libxul.so)objdump
membutuhkan waktu lama, saya membatalkannya setelah satu jam, sementaragdb
membutuhkan waktu kurang dari satu menit.Jika Anda memiliki binutils terbaru (2.32+), ini sangat sederhana.
Meneruskan
--disassemble=SYMBOL
ke objdump hanya akan membongkar fungsi yang ditentukan. Tidak perlu memasukkan alamat awal dan alamat akhir.Objdump LLVM juga memiliki opsi serupa (
--disassemble-symbols
).sumber
Untuk menyederhanakan penggunaan awk untuk mengurai keluaran objdump relatif terhadap jawaban lain:
sumber
Ini berfungsi seperti solusi gdb (karena itu menggeser offset ke nol) kecuali itu tidak lamban (menyelesaikan pekerjaan dalam waktu sekitar 5ms di PC saya sedangkan solusi gdb membutuhkan waktu sekitar 150ms):
objdump_func:
sumber
awk
) adalah satu-satunya fungsi dalam file objek, yaitu, bahkan jika fungsi dimulai pada, katakanlah0x2d
, awk kedua akan menggesernya ke arah0x00
(dengan mengurangi0x2d
dari alamat setiap instruksi), yang berguna karena kode assembly sering membuat referensi relatif terhadap awal fungsi dan jika fungsi dimulai dari 0, Anda tidak perlu melakukan pengurangan di kepala Anda. Kode awk bisa lebih baik tetapi setidaknya berfungsi dan cukup efisien.-ffunction-sections
adalah cara yang lebih mudah untuk memastikan setiap fungsi dimulai pada 0.Penyelesaian pesta untuk
./dasm
Lengkapi nama simbol untuk solusi ini (versi D lang):
dasm test
dan kemudian menekan TabTab, Anda akan mendapatkan daftar semua fungsi.dasm test m
dan kemudian menekan TabTab semua fungsi yang dimulai dengan m akan ditampilkan, atau jika hanya ada satu fungsi, maka akan diselesaikan secara otomatis.File
/etc/bash_completion.d/dasm
:sumber