linux gdb快速入門教程

前言

對於想要學習gdb調試的童鞋,網上搜一下就是一大堆資料,信息太多而不知道該如何篩選了,當然最有效的方式是去看gdb的手冊,但是對於想快速上手的我,需要掌握最常用的一些指令和一些技巧,期間,我找到了一個很全很強大的教材,感覺就是gdb bible——100-gdb-tips100-gdb-tips-gitbook;強烈推薦參考這個文檔。文檔裏已經基本涵蓋了gdb使用的各種操作和技巧,但是都相互比較獨立和分散,沒有一個完整的使用流程,下面我會總結一下整體使用的一個流程。

使用gdb

通常我們編寫一個程序,具體程序如下所示;並且編譯成帶調試信息的可執行文件,然後在用gdb加載調試;

/*
 * demo learning gdb
 * gdb-sample.c
 */
 #include <stdio.h>
 void func_a(int *p){
     printf("%s:p is %d  | valuse is %d \n",__func__,p,*p);
 }
 void func_b(int *p){
     *p = 12345;
     func_a(p);
 }
 void func_c(int *p){
     p = NULL;
     func_b(p);
 }
 int main(void) {
     int i = 0,j=0;
     int *p = &j;
     for(; i<6; i++){
         if(i<2){
             func_a(p);
         }else if(i<4){
             func_b(p);
         }else{
             func_c(p);
         }
     }
     return 0;
 }

gcc -g gdb-sample.c -o gdb-sample

記得帶上-g選項,最後編譯成功並生成可執行文件gdb-sample

一個完整流程一般所需步驟

1 加載程序

gdb -q gdb-sample

2 查看

2.1 查看函數

使用i functions或者info functions可以查看當前的可執行文件的函數接口;

(gdb) i functions
All defined functions:

File gdb-sample.c:
void func_a(int *);
void func_b(int *);
void func_c(int *);
int main(void);

Non-debugging symbols:
0x0000000000400460  _init
0x0000000000400490  puts@plt
0x00000000004004a0  __stack_chk_fail@plt
0x00000000004004b0  printf@plt
0x00000000004004c0  __libc_start_main@plt
0x00000000004004e0  _start
0x0000000000400510  deregister_tm_clones
0x0000000000400550  register_tm_clones
0x0000000000400590  __do_global_dtors_aux
0x00000000004005b0  frame_dummy
0x00000000004006f0  __libc_csu_init
0x0000000000400760  __libc_csu_fini
0x0000000000400764  _fini

3 設置斷點

斷點使用

3.1 根據函數名設置斷點
(gdb) b main
Breakpoint 1 at 0x400658: file gdb-sample.c, line 19.
3.2 根據程序位置(第幾行)
(gdb) l
1       #include <stdio.h>
2
3       void func_a(int *p){
4           printf("%s:p is %d  | valuse is %d \n",__func__,p,*p);
5       }
6
7       void func_b(int *p){
8           *p = 12345;
9           func_a(p);
10      }
(gdb)
11
12      void func_c(int *p){
13          p = NULL;
14          func_b(p);
15      }
16
17
18
19      int main(void) {
20          int i = 0,j=0;
(gdb)
21          int *p = &j;
22          for(; i<6; i++){
23              if(i<2){
24                  func_a(p);
25              }else if(i<4){
26                  func_b(p);
27              }else{
28                  func_c(p);
29              }
30          }
(gdb) b 19
Breakpoint 3 at 0x400618: file gdb-sample.c, line 19.

刪除斷點

(gdb) d
刪除所有斷點嗎? (y or n) y

4 運行程序

使用runr運行程序,如果被斷點中斷,可以使用c繼續運行程序;

(gdb) r
Starting program: /home/thinkpad/code/gdb-tips/core_dump/gdb-sample

Breakpoint 1, main () at gdb-sample.c:19
19      int main(void) {

使用next或者n可以進行單步調試;不會進入到子函數內部;
使用step或者s可以進行單步調試;會進入到子函數內部;

5 查看變量

查看變量可以使用printp

(gdb) b main
Breakpoint 6 at 0x400618: file gdb-sample.c, line 19.
(gdb) r
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /home/zhaojh/code/gdb-tips/core_dump/gdb-sample

Breakpoint 6, main () at gdb-sample.c:19
19      int main(void) {
(gdb) n
20          int i = 0,j=0;
(gdb) p i
$1 = 0
(gdb) n
21          int *p = &j;
(gdb) n
22          for(; i<6; i++){
(gdb) p p
$2 = (int *) 0x7fffffffe2f8
(gdb) p *p
$3 = 0
(gdb)

6 查看寄存器

使用i rinfo registeri registerinfo r可以查看寄存器;

(gdb) i r
rax            0x7fffffffe2f8   140737488347896
rbx            0x0      0
rcx            0x0      0
rdx            0x7fffffffe408   140737488348168
rsi            0x7fffffffe3f8   140737488348152
rdi            0x1      1
rbp            0x7fffffffe310   0x7fffffffe310
rsp            0x7fffffffe2f0   0x7fffffffe2f0
r8             0x400710 4196112
r9             0x7ffff7de7ac0   140737351940800
r10            0x846    2118
r11            0x7ffff7a2d740   140737348032320
r12            0x4004a0 4195488
r13            0x7fffffffe3f0   140737488348144
r14            0x0      0
r15            0x0      0
rip            0x40063f 0x40063f <main+47>
eflags         0x293    [ CF AF SF IF ]
cs             0x33     51
ss             0x2b     43
ds             0x0      0
es             0x0      0
fs             0x0      0
gs             0x0      0

總結

記錄了一些比較簡單並且會被普遍用到的gdb指令,作爲入門使用還是比較好的,更多高級的調試參考gdb bible——100-gdb-tips100-gdb-tips-gitbook

參考

https://github.com/hellogcc/100-gdb-tips
https://wizardforcel.gitbooks.io/100-gdb-tips/content/

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章