Pengembangan tindanan debugger Linux!
Pengenalan | Kadangkala maklumat paling penting yang perlu anda ketahui ialah bagaimana keadaan program semasa anda sampai ke sana. Terdapat arahan jejak belakang, yang memberikan anda rangkaian panggilan fungsi semasa program anda. Siaran ini akan menunjukkan kepada anda cara melaksanakan penyalahan tindanan pada x86_64 untuk menjana jejak balik sedemikian. |
Pautan ini akan disiarkan secara langsung apabila siaran lain diterbitkan.
- Sediakan persekitaran
- Titik putus
- Daftar dan Memori
- DIRI dan KEDIRI
- Kod sumber dan isyarat
- Pelaksanaan langkah demi langkah pada tahap kod sumber
- Titik putus tahap sumber
- Peluasan tindanan
- Baca pembolehubah
- Langkah seterusnya
Gunakan program berikut sebagai contoh:
void a() { //stopped here } void b() { a(); } void c() { a(); } int main() { b(); c(); }
Jika penyahpepijat berhenti di baris //berhenti di sini', terdapat dua cara untuk mencapainya: main->b->a atau main->c->a`. Jika kami menetapkan titik putus dengan LLDB, teruskan pelaksanaan dan minta jejak balik, maka kami mendapat perkara berikut:
* frame #0: 0x00000000004004da a.out`a() + 4 at bt.cpp:3 frame #1: 0x00000000004004e6 a.out`b() + 9 at bt.cpp:6 frame #2: 0x00000000004004fe a.out`main + 9 at bt.cpp:14 frame #3: 0x00007ffff7a2e830 libc.so.6`__libc_start_main + 240 at libc-start.c:291 frame #4: 0x0000000000400409 a.out`_start + 41
Ini bermakna kita sedang dalam fungsi a, a melompat dari fungsi b, b melompat dari utama, dsb. Dua bingkai terakhir ialah cara pengkompil membongkar fungsi utama.
Persoalannya sekarang ialah bagaimana kami melaksanakannya pada x86_64. Pendekatan yang paling mantap ialah menghuraikan bahagian .eh_frame bagi fail ELF dan memikirkan cara untuk melepaskan timbunan dari sana, tetapi itu akan menyusahkan. Anda boleh melakukannya menggunakan libunwind atau serupa, tetapi itu membosankan. Sebaliknya, kami menganggap bahawa pengkompil telah menyediakan timbunan dalam beberapa cara dan kami akan melintasinya secara manual. Untuk melakukan ini, kita perlu memahami susun atur timbunan terlebih dahulu.
High | ... | +---------+ +24| Arg 1 | +---------+ +16| Arg 2 | +---------+ + 8| Return | +---------+ EBP+--> |Saved EBP| +---------+ - 8| Var 1 | +---------+ ESP+--> | Var 2 | +---------+ | ... | Low
Seperti yang anda lihat, penuding bingkai bingkai tindanan terakhir disimpan pada permulaan bingkai tindanan semasa, mencipta senarai penuding yang dipautkan. Tindanan dibongkar berdasarkan senarai terpaut ini. Kita boleh mencari fungsi untuk bingkai seterusnya dalam senarai dengan mencari alamat pemulangan dalam mesej DWARF. Sesetengah penyusun akan mengabaikan penjejakan alamat asas bingkai EBP kerana ini boleh dinyatakan sebagai offset daripada ESP dan membebaskan daftar tambahan. Walaupun dengan pengoptimuman didayakan, menghantar -fno-omit-frame-pointer kepada GCC atau Clang akan memaksanya untuk mengikut konvensyen yang kami bergantung kepada.
Kami akan melakukan semua kerja dalam fungsi print_backtrace:
void debugger::print_backtrace() {
Perkara pertama yang perlu diputuskan ialah format yang hendak digunakan untuk mencetak maklumat bingkai. Saya menggunakan lambda untuk melancarkan kaedah ini:
auto output_frame = [frame_number = 0] (auto&& func) mutable { std::cout << "frame #" << frame_number++ << ": 0x" << dwarf::at_low_pc(func) << ' ' << dwarf::at_name(func) << std::endl; };
Bingkai pertama yang dicetak ialah bingkai yang sedang dilaksanakan. Kita boleh mendapatkan maklumat tentang bingkai ini dengan mencari kaunter program semasa dalam DWARF:
auto current_func = get_function_from_pc(get_pc()); output_frame(current_func);
Seterusnya kita perlu mendapatkan penunjuk bingkai dan alamat pemulangan fungsi semasa. Penunjuk bingkai disimpan dalam daftar rbp dan alamat pemulangan ialah 8 bait yang disusun daripada penuding bingkai.
auto frame_pointer = get_register_value(m_pid, reg::rbp); auto return_address = read_memory(frame_pointer+8);
Kini kami mempunyai semua maklumat yang kami perlukan untuk mengembangkan timbunan. Saya terus berehat sehingga penyahpepijat mencecah utama, tetapi anda juga boleh memilih untuk berhenti apabila penuding bingkai ialah 0x0, iaitu fungsi yang anda panggil sebelum memanggil fungsi utama. Kami akan mengambil penunjuk bingkai dan alamat pemulangan dari setiap bingkai dan mencetak maklumat tersebut.
while (dwarf::at_name(current_func) != "main") { current_func = get_function_from_pc(return_address); output_frame(current_func); frame_pointer = read_memory(frame_pointer); return_address = read_memory(frame_pointer+8); } }
Itu sahaja! Inilah keseluruhan fungsi:
void debugger::print_backtrace() { auto output_frame = [frame_number = 0] (auto&& func) mutable { std::cout << "frame #" << frame_number++ << ": 0x" << dwarf::at_low_pc(func) << ' ' << dwarf::at_name(func) << std::endl; }; auto current_func = get_function_from_pc(get_pc()); output_frame(current_func); auto frame_pointer = get_register_value(m_pid, reg::rbp); auto return_address = read_memory(frame_pointer+8); while (dwarf::at_name(current_func) != "main") { current_func = get_function_from_pc(return_address); output_frame(current_func); frame_pointer = read_memory(frame_pointer); return_address = read_memory(frame_pointer+8); } }
Sudah tentu, kita mesti mendedahkan arahan ini kepada pengguna.
else if(is_prefix(command, "backtrace")) { print_backtrace(); }
Salah satu cara untuk menguji fungsi ini ialah dengan menulis program ujian dengan sekumpulan fungsi kecil yang memanggil satu sama lain. Tetapkan beberapa titik putus, lompat sekeliling kod dan pastikan jejak balik anda adalah tepat.
Kami telah melangkah jauh dari program yang hanya boleh melahirkan dan melekat pada program lain. Artikel terakhir dalam siri ini akan melengkapkan pelaksanaan penyahpepijat dengan menyokong pembolehubah membaca dan menulis. Sehingga itu, anda boleh mencari kod untuk siaran ini di sini.
Atas ialah kandungan terperinci Pengembangan tindanan debugger Linux!. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Alat AI Hot

Undresser.AI Undress
Apl berkuasa AI untuk mencipta foto bogel yang realistik

AI Clothes Remover
Alat AI dalam talian untuk mengeluarkan pakaian daripada foto.

Undress AI Tool
Gambar buka pakaian secara percuma

Clothoff.io
Penyingkiran pakaian AI

AI Hentai Generator
Menjana ai hentai secara percuma.

Artikel Panas

Alat panas

Notepad++7.3.1
Editor kod yang mudah digunakan dan percuma

SublimeText3 versi Cina
Versi Cina, sangat mudah digunakan

Hantar Studio 13.0.1
Persekitaran pembangunan bersepadu PHP yang berkuasa

Dreamweaver CS6
Alat pembangunan web visual

SublimeText3 versi Mac
Perisian penyuntingan kod peringkat Tuhan (SublimeText3)

Topik panas



Sebab utama mengapa anda tidak boleh log masuk ke MySQL sebagai akar adalah masalah kebenaran, ralat fail konfigurasi, kata laluan tidak konsisten, masalah fail soket, atau pemintasan firewall. Penyelesaiannya termasuk: periksa sama ada parameter pengikat di dalam fail konfigurasi dikonfigurasi dengan betul. Semak sama ada kebenaran pengguna root telah diubahsuai atau dipadam dan ditetapkan semula. Sahkan bahawa kata laluan adalah tepat, termasuk kes dan aksara khas. Semak tetapan dan laluan kebenaran fail soket. Semak bahawa firewall menyekat sambungan ke pelayan MySQL.

C Language Conditional Compilation adalah mekanisme untuk selektif menyusun blok kod berdasarkan keadaan kompilasi masa. Kaedah pengenalan termasuk: menggunakan arahan #if dan #Else untuk memilih blok kod berdasarkan syarat. Ekspresi bersyarat yang biasa digunakan termasuk STDC, _WIN32 dan LINUX. Kes praktikal: Cetak mesej yang berbeza mengikut sistem operasi. Gunakan jenis data yang berbeza mengikut bilangan digit sistem. Fail header yang berbeza disokong mengikut pengkompil. Penyusunan bersyarat meningkatkan kebolehgunaan dan fleksibiliti kod, menjadikannya boleh disesuaikan dengan pengkompil, sistem operasi, dan perubahan seni bina CPU.

1.0.1 Preface Projek ini (termasuk kod dan komen) telah direkodkan semasa karat saya yang diajar sendiri. Mungkin ada kenyataan yang tidak tepat atau tidak jelas, sila minta maaf. Jika anda mendapat manfaat daripadanya, ia lebih baik. 1.0.2 Mengapa Rustrust boleh dipercayai dan cekap? Karat boleh menggantikan C dan C, dengan prestasi yang sama tetapi keselamatan yang lebih tinggi, dan tidak memerlukan rekompilasi yang kerap untuk memeriksa kesilapan seperti C dan C. Kelebihan utama termasuk: Keselamatan Memori (mencegah penunjuk null dari dereferences, penunjuk menggantung, dan perbalahan data). Thread-safe (pastikan kod multi-threaded selamat sebelum pelaksanaan). Elakkan tingkah laku yang tidak ditentukan (mis., Arus dari batas, pembolehubah yang tidak diinisialisasi, atau akses kepada memori yang dibebaskan). Karat menyediakan ciri bahasa moden seperti generik

Lima komponen asas Linux adalah: 1. Kernel, menguruskan sumber perkakasan; 2. Perpustakaan sistem, menyediakan fungsi dan perkhidmatan; 3. Shell, antara muka pengguna untuk berinteraksi dengan sistem; 4. Sistem fail, menyimpan dan menganjurkan data; 5. Aplikasi, menggunakan sumber sistem untuk melaksanakan fungsi.

Terdapat banyak sebab mengapa permulaan MySQL gagal, dan ia boleh didiagnosis dengan memeriksa log ralat. Penyebab umum termasuk konflik pelabuhan (periksa penghunian pelabuhan dan ubah suai konfigurasi), isu kebenaran (periksa keizinan pengguna yang menjalankan perkhidmatan), ralat fail konfigurasi (periksa tetapan parameter), rasuah direktori data (memulihkan data atau membina semula ruang meja), isu ruang jadual InnoDB (semak fail ibdata1) Apabila menyelesaikan masalah, anda harus menganalisisnya berdasarkan log ralat, cari punca utama masalah, dan mengembangkan tabiat sandaran data secara teratur untuk mencegah dan menyelesaikan masalah.

Perpustakaan Fungsi Bahasa C adalah kotak alat yang mengandungi pelbagai fungsi, yang dianjurkan dalam fail perpustakaan yang berbeza. Menambah perpustakaan memerlukan menyatakannya melalui pilihan baris perintah pengkompil, contohnya, pengkompil GCC menggunakan pilihan -L diikuti dengan singkatan nama perpustakaan. Jika fail perpustakaan tidak berada di bawah laluan carian lalai, anda perlu menggunakan pilihan -L untuk menentukan laluan fail perpustakaan. Perpustakaan boleh dibahagikan kepada perpustakaan statik dan perpustakaan dinamik. Perpustakaan statik secara langsung dikaitkan dengan program pada masa kompilasi, manakala perpustakaan dinamik dimuatkan semasa runtime.

MySQL tidak boleh berjalan secara langsung di Android, tetapi ia boleh dilaksanakan secara tidak langsung dengan menggunakan kaedah berikut: menggunakan pangkalan data ringan SQLite, yang dibina di atas sistem Android, tidak memerlukan pelayan yang berasingan, dan mempunyai penggunaan sumber kecil, yang sangat sesuai untuk aplikasi peranti mudah alih. Sambungkan jauh ke pelayan MySQL dan sambungkan ke pangkalan data MySQL pada pelayan jauh melalui rangkaian untuk membaca dan menulis data, tetapi terdapat kelemahan seperti kebergantungan rangkaian yang kuat, isu keselamatan dan kos pelayan.

Penyelesaian kepada ralat pemasangan MySQL adalah: 1. Berhati -hati memeriksa persekitaran sistem untuk memastikan keperluan perpustakaan ketergantungan MySQL dipenuhi. Sistem operasi dan keperluan versi yang berbeza adalah berbeza; 2. Berhati -hati membaca mesej ralat dan mengambil langkah -langkah yang sepadan mengikut arahan (seperti fail perpustakaan yang hilang atau kebenaran yang tidak mencukupi), seperti memasang kebergantungan atau menggunakan arahan sudo; 3 Jika perlu, cuba pasang kod sumber dan periksa dengan teliti log kompilasi, tetapi ini memerlukan pengetahuan dan pengalaman Linux tertentu. Kunci untuk menyelesaikan masalah akhirnya adalah dengan teliti memeriksa persekitaran sistem dan maklumat ralat, dan merujuk kepada dokumen rasmi.
