GNU/Linux >> Belajar Linux >  >> Linux

5 tips untuk GNU Debugger

GNU Debugger (gdb) adalah alat yang sangat berharga untuk memeriksa proses yang berjalan dan memperbaiki masalah saat Anda mengembangkan program.

Anda dapat menyetel breakpoint di lokasi tertentu (berdasarkan nama fungsi, nomor baris, dan sebagainya), mengaktifkan dan menonaktifkan breakpoint tersebut, menampilkan dan mengubah nilai variabel, dan melakukan semua hal standar yang Anda harapkan dari debugger. Tetapi ia memiliki banyak fitur lain yang mungkin belum Anda coba. Berikut adalah lima untuk Anda coba.

Titik putus bersyarat

Menyetel breakpoint adalah salah satu hal pertama yang akan Anda pelajari dengan GNU Debugger. Program berhenti saat mencapai breakpoint, dan Anda dapat menjalankan perintah gdb untuk memeriksanya atau mengubah variabel sebelum mengizinkan program untuk melanjutkan.

Misalnya, Anda mungkin mengetahui bahwa fungsi yang sering dipanggil terkadang mogok, tetapi hanya jika fungsi tersebut mendapatkan nilai parameter tertentu. Anda dapat mengatur breakpoint di awal fungsi itu dan menjalankan program. Parameter fungsi ditampilkan setiap kali mencapai titik henti sementara, dan jika nilai parameter yang memicu kerusakan tidak diberikan, Anda dapat melanjutkan hingga fungsi dipanggil lagi. Saat parameter bermasalah memicu error, Anda dapat menelusuri kode untuk melihat apa yang salah.

(gdb) break kadang-kadang_crashes
Breakpoint 1 pada 0x40110e:file prog.c, baris 5.
(gdb) run
[...]
Breakpoint 1, kadang-kadang_crashes (f=0x7fffffffd1bc) di prog.c:5
5      fprintf(stderr,
(gdb) lanjutkan
Breakpoint 1, terkadang_crash (f=0x7ffffffd1bc) di prog.c:5
5      fprintf(stderr,
(gdb) lanjutkan

Untuk membuatnya lebih berulang, Anda dapat menghitung berapa kali fungsi dipanggil sebelum panggilan spesifik yang Anda minati, dan mengatur penghitung pada breakpoint itu (misalnya, "lanjutkan 30" untuk membuatnya mengabaikan 29 kali berikutnya mencapai titik putus).

Tetapi di mana breakpoint menjadi sangat kuat adalah kemampuannya untuk mengevaluasi ekspresi saat runtime, yang memungkinkan Anda untuk mengotomatiskan pengujian semacam ini. Masukkan:breakpoint bersyarat.

break [LOCATION] if CONDITION

(gdb) break kadang-kadang_crashes jika !f
Breakpoint 1 pada 0x401132:file prog.c, baris 5.
(gdb) run
[...]
Breakpoint 1, terkadang_crash (f=0x0) di prog.c:5
5      fprintf(stderr,
(gdb)

Alih-alih meminta gdb menanyakan apa yang harus dilakukan setiap kali fungsi dipanggil, breakpoint bersyarat memungkinkan Anda membuat gdb berhenti di lokasi itu hanya ketika ekspresi tertentu dievaluasi sebagai true. Jika eksekusi mencapai lokasi titik henti sementara bersyarat, tetapi ekspresi dievaluasi sebagai salah,

Lebih banyak sumber daya Linux

  • Lembar contekan perintah Linux
  • Lembar contekan perintah Linux tingkat lanjut
  • Kursus online gratis:Ikhtisar Teknis RHEL
  • Lembar contekan jaringan Linux
  • Lembar contekan SELinux
  • Lembar contekan perintah umum Linux
  • Apa itu container Linux?
  • Artikel Linux terbaru kami

debugger secara otomatis membiarkan program melanjutkan tanpa menanyakan apa yang harus dilakukan pengguna.

Perintah breakpoint

Fitur breakpoint yang lebih canggih di GNU Debugger adalah kemampuan untuk membuat skrip respons untuk mencapai breakpoint. Perintah breakpoint memungkinkan Anda untuk menulis daftar perintah Debugger GNU untuk dijalankan setiap kali mencapai breakpoint.

Kami dapat menggunakan ini untuk mengatasi bug yang sudah kami ketahui di kadang-kadang_crashes fungsi dan membuatnya kembali dari fungsi itu tanpa bahaya ketika memberikan pointer nol.

Kita bisa menggunakan diam sebagai baris pertama untuk mendapatkan kontrol lebih besar atas output. Tanpa ini, bingkai tumpukan akan ditampilkan setiap kali breakpoint terkena, bahkan sebelum perintah breakpoint kita dijalankan.

(gdb) break kadang-kadang_crashes
Breakpoint 1 pada 0x401132:file prog.c, baris 5.
(gdb) perintah 1
Ketik perintah untuk breakpoint 1, satu per baris .
Akhiri dengan baris yang mengatakan "akhiri".
>diam
>if !f
 >frame
 >printf "Melewatkan panggilan\n"
 >kembalikan 0
 >lanjutkan
 >akhir
>printf "Lanjutkan\n"
>lanjutkan
>akhiri
(gdb) jalankan
Memulai program:/home/twaugh/Documents/GDB/prog
peringatan:Bagian yang dapat dimuat ".note.gnu.property" di luar segmen ELF
Melanjutkan
Melanjutkan
Melanjutkan
#0  kadang-kadang_crashes (f=0x0) di prog.c:5
5      fprintf(stderr,
Melewatkan panggilan
[Inferior 1 (proses 9373) keluar secara normal]
(gdb)

Buang memori biner

GNU Debugger memiliki dukungan bawaan untuk memeriksa memori menggunakan x perintah dalam berbagai format, termasuk oktal, heksadesimal, dan sebagainya. Tapi saya suka melihat dua format berdampingan:byte heksadesimal di sebelah kiri, dan karakter ASCII yang diwakili oleh byte yang sama di sebelah kanan.

Ketika saya ingin melihat isi file byte-by-byte, saya sering menggunakan hexdump -C (hexdump berasal dari paket util-linux). Ini x g gdb perintah yang menampilkan byte heksadesimal:

 (gdb) x / 33xb mydata 
0x404040 :0x02 0x01 0x00 0x02 0x00 0x00 0x00 0x01
0x404048 :0x01 0x47 0x00 0x12 0x61 0x74 0x74 0x72
0x404050 :0x69 0x62 0x75 0x74 0x73 0x2D 0x63
0x404058 0x61 0x61 0x72 0x73 0x65 0x05
0x40606 <32>:0x00

Bagaimana jika Anda bisa mengajari gdb untuk menampilkan memori seperti yang dilakukan hexdump? Anda dapat, dan bahkan, Anda dapat menggunakan metode ini untuk format apa pun yang Anda inginkan.

Dengan menggabungkan buangan perintah untuk menyimpan byte dalam file, shell perintah untuk menjalankan hexdump pada file, dan define perintah, kita dapat membuat hexdump baru kita sendiri perintah untuk menggunakan hexdump untuk menampilkan isi memori.

(gdb) define hexdump
Ketik perintah untuk definisi "hexdump".
Akhiri dengan baris yang mengatakan "end".
>dump binary memory /tmp/dump.bin $ arg0 $arg0+$arg1
>shell hexdump -C /tmp/dump.bin
>end

Perintah-perintah itu bahkan bisa masuk ~/.gdbinit file untuk mendefinisikan perintah hexdump secara permanen. Ini dia beraksi:

(gdb) hexdump mydata sizeof(mydata)
00000000  02 01 00 02 00 00 00 01  01 47 00 12 61 74 74 72  |.........G..attr|
00000010  69 62 75 74 65 73 2d 63  68 61 72 73 65 75 00 05  |ibutes-charseu..|
00000020  00                                >      >      

Pembongkaran sebaris

Kadang-kadang Anda ingin memahami lebih lanjut tentang apa yang terjadi sebelum crash, dan kode sumber saja tidak cukup. Anda ingin melihat apa yang terjadi di tingkat instruksi CPU.

membongkar perintah memungkinkan Anda melihat instruksi CPU yang mengimplementasikan suatu fungsi. Namun terkadang hasilnya sulit untuk diikuti. Biasanya, saya ingin melihat instruksi apa yang sesuai dengan bagian tertentu dari kode sumber dalam fungsi. Untuk mencapai ini, gunakan /s pengubah untuk menyertakan baris kode sumber dengan pembongkaran.

(gdb) disassemble/s main
Buang kode assembler untuk fungsi utama:
prog.c:
11    {
   0x0000000000401158 <+0>:   push   %rbp
   0x0000000000401159 <+1>:   mov      %rsp,%rbp
   0x000000000040115c <+4>:   sub      $0x10,%rsp

12      int n =  0;
:   movl   $0x0,-0x4(%rbp)

13      kadang-kadang_crashes(&n);
   0x0000000000401167 <+15>:   lea     -0x4(%rbp),%rax
   0x0000000000040116b <+19>:   mov     %rax,%rdi
   0x000000000040116e <+22>:   callq  0x401126
[...dipotong...]

Ini, bersama dengan register info untuk melihat nilai saat ini dari semua register CPU dan perintah seperti stepi untuk langkah satu instruksi pada satu waktu, memungkinkan Anda untuk memiliki pemahaman yang lebih rinci tentang program ini.

Debug terbalik

Terkadang Anda berharap bisa memutar kembali waktu. Bayangkan Anda telah mencapai titik pengawasan pada suatu variabel. Sebuah watchpoint seperti breakpoint, tetapi alih-alih disetel di lokasi dalam program, ia disetel pada ekspresi (menggunakan watch memerintah). Setiap kali nilai ekspresi berubah, eksekusi berhenti, dan debugger mengambil kendali.

Jadi bayangkan Anda telah mencapai titik pengawasan ini, dan memori yang digunakan oleh variabel telah berubah nilainya. Ini bisa saja disebabkan oleh sesuatu yang terjadi jauh sebelumnya; misalnya, memori dibebaskan dan sekarang digunakan kembali. Tapi kapan dan mengapa itu dibebaskan?

Debugger GNU bahkan dapat memecahkan masalah ini karena Anda dapat menjalankan program Anda secara terbalik!

Hal ini dicapai dengan secara hati-hati merekam status program pada setiap langkah sehingga dapat memulihkan status yang direkam sebelumnya, memberikan ilusi waktu yang mengalir mundur.

Untuk mengaktifkan perekaman status ini, gunakan target record-full memerintah. Kemudian Anda dapat menggunakan perintah yang terdengar mustahil, seperti:

  • langkah mundur , yang memundurkan ke baris sumber sebelumnya
  • mundur-berikutnya , yang memundurkan ke baris sumber sebelumnya, melangkah mundur melewati panggilan fungsi
  • selesai terbalik , yang memundurkan ke titik ketika fungsi saat ini akan dipanggil
  • lanjutkan-balik , yang memundurkan ke status sebelumnya dalam program yang akan (sekarang) memicu breakpoint (atau apa pun yang menyebabkannya berhenti)

Berikut adalah contoh aksi debugging terbalik:

(gdb) b main
Breakpoint 1 pada 0x401160:file prog.c, baris 12.
(gdb) r
Memulai program:/home/twaugh/Documents/GDB/prog
[...]

Breakpoint 1, main () di prog.c:12
12      int n =0;
(gdb) target record-full
(gdb) c
Melanjutkan.

Program menerima sinyal SIGSEGV, Kesalahan segmentasi.
0x0000000000401154 di kadang-kadang_crash (f=0x0) pada prog.c:7
7      return *f;
(gdb) reverse-finish
Jalankan kembali ke panggilan #0  0x0000000000401154 di kadang-kadang_crashes (f=0x0)
        di prog.c:7
0x0000000000401190 di main () di prog.c:16
16      kadang-kadang_crashes(0);

Ini hanyalah beberapa hal berguna yang dapat dilakukan oleh GNU Debugger. Ada banyak lagi yang bisa ditemukan. Fitur gdb yang tersembunyi, kurang diketahui, atau sekadar menakjubkan mana yang menjadi favorit Anda? Silakan bagikan di komentar.


Linux
  1. Tips dan trik untuk curl dan wget

  2. 5 tips rsync tingkat lanjut untuk sysadmin Linux

  3. Kiat cepat untuk klien oc OpenShift

  1. Contoh Breakpoint GDB untuk C – Setel, Lihat, Lanjutkan, dan Hapus Breakpoints

  2. Depends.exe untuk GNU/Linux

  3. Tetapkan breakpoint dalam kode C atau C++ secara terprogram untuk gdb di Linux

  1. Kiat Linux untuk menggunakan cron untuk menjadwalkan tugas

  2. 3 tips untuk mencetak dengan Linux

  3. Ubah milidetik menjadi spesifikasi waktu untuk port GNU