gdb 詳解

環境:gcc (OpenWrt/Linaro GCC 4.8)sass

以以下的簡單代碼爲例,說明gdb的使用。函數

 1 void func1(int a, int b)
 2 {
 3     int c;
 4     c = a + b;
 5 }
 6 
 7 int main(void)
 8 {
 9 
10     func1(11,22);
11     return 100;
12 }

 

1. gdb 下一步的命令spa

a.執行下一行語句(語句級別)
  next(或n) 執行下一行語句,若是是函數調用則直接將函數執行完;至關於visual studio調試器中的"Step Over (單步跟蹤)"
  step(或s) 執行下一行語句,若是是函數調用則進入函數中。即常說的單步調試,至關於visual studio調試器中的"Step Into (單步跟蹤進入)"
  這兩個命令必須在有源代碼調試信息的狀況下才可使用(GCC編譯時使用「-g」參數)
b.執行下一條指令(指令級)
  si 相似於s;
  ni 相似於n;
  這兩個命令(si/ni)所針對的是彙編指令指針

2. disassemble調試

能夠反彙編當前函數或者指定的函數,
單獨用disassemble命令是反彙編當前函數,
若是disassemble命令後面跟函數名或地址,則反彙編指定的函數.日誌

(gdb) disassemble
Dump of assembler code for function main:
   0x00008440 <+0>:     push    {r11, lr}
   0x00008444 <+4>:     add     r11, sp, #4
=> 0x00008448 <+8>:     mov     r0, #11
   0x0000844c <+12>:    mov     r1, #22
   0x00008450 <+16>:    bl      0x8410 <func1>
   0x00008454 <+20>:    mov     r3, #100        ; 0x64
   0x00008458 <+24>:    mov     r0, r3
   0x0000845c <+28>:    pop     {r11, pc}
End of assembler dump.

(gdb) disassemble
Dump of assembler code for function func1:
   0x00008410 <+0>:     push    {r11}           ; (str r11, [sp, #-4]!)
   0x00008414 <+4>:     add     r11, sp, #0
   0x00008418 <+8>:     sub     sp, sp, #20
   0x0000841c <+12>:    str     r0, [r11, #-16]
   0x00008420 <+16>:    str     r1, [r11, #-20]
=> 0x00008424 <+20>:    ldr     r2, [r11, #-16]
   0x00008428 <+24>:    ldr     r3, [r11, #-20]
   0x0000842c <+28>:    add     r3, r2, r3
   0x00008430 <+32>:    str     r3, [r11, #-8]
   0x00008434 <+36>:    sub     sp, r11, #0
   0x00008438 <+40>:    pop     {r11}           ; (ldr r11, [sp], #4)
   0x0000843c <+44>:    bx      lr
End of assembler dump.

3. 顯示寄存器的信息code

info registers能夠顯示全部寄存器的當前值(不包括浮點寄存器)blog

info all-registers(包括浮點寄存器)
簡寫: i r內存

 1 (gdb) info registers
 2 r0             0xb      11
 3 r1             0x16     22
 4 r2             0xbefffe2c       3204447788
 5 r3             0x8440   33856
 6 r4             0xbeffff14       3204448020
 7 r5             0x8304   33540
 8 r6             0xbefffc80       3204447360
 9 r7             0x8      8
10 r8             0x0      0
11 r9             0x0      0
12 r10            0xb6ffef7c       3070226300
13 r11            0xbefffc64       3204447332
14 r12            0xbefffd68       3204447592
15 sp             0xbefffc50       0xbefffc50
16 lr             0x8454   33876
17 pc             0x8424   0x8424 <func1+20>
18 cpsr           0x60000010       1610612752
19 (gdb) i r
20 r0             0xb      11
21 r1             0x16     22
22 r2             0xbefffe2c       3204447788
23 r3             0x8440   33856
24 r4             0xbeffff14       3204448020
25 r5             0x8304   33540
26 r6             0xbefffc80       3204447360
27 r7             0x8      8
28 r8             0x0      0
29 r9             0x0      0
30 r10            0xb6ffef7c       3070226300
31 r11            0xbefffc64       3204447332
32 r12            0xbefffd68       3204447592
33 sp             0xbefffc50       0xbefffc50
34 lr             0x8454   33876
35 pc             0x8424   0x8424 <func1+20>
36 cpsr           0x60000010       1610612752

4.查看內存的值:ci

gdb中使用"x"命令來打印內存的值,格式爲"x/nfu addr"。含義爲以f格式打印從addr開始的n個長度單元爲u的內存值。參數具體含義以下:

a)n:輸出單元的個數。
b)f:是輸出格式。好比x是以16進制形式輸出,o是以8進制形式輸出,等等。
  x(hex) 按十六進制格式顯示變量。
  d(decimal) 按十進制格式顯示變量。
  u(unsigned decimal) 按十進制格式顯示無符號整型。
  o(octal) 按八進制格式顯示變量。
  t(binary) 按二進制格式顯示變量。
  a(address) 按十六進制格式顯示變量。
  c(char) 按字符格式顯示變量。
  f(float) 按浮點數格式顯示變量
c)u:標明一個單元的長度。b是一個byte,h是兩個byte(halfword),w是四個byte(word),g是八個byte(giant word)

1 舉例:
2 以16進制格式打印從add開始的16個byte的值:
3 (gdb) x/16xb $r11
4 0xbefffc64:     0x6c    0xfc    0xff    0xbe    0x00    0x00    0x00    0x00
5 0xbefffc6c:     0xc4    0xcc    0xfc    0xb6    0x00    0x90    0xfd    0xb6

5.打印棧幀信息:

frame 打印當前棧幀的簡要信息。

1 (gdb) frame
2 #0  func1 (a=11, b=22) at hello.c:17
3 17      in hello.c

6.info frame 打印當前棧幀的詳細信息。

1 (gdb) info frame
2 Stack level 0, frame at 0xbefffc68:
3  pc = 0x8434 in func1 (hello.c:17); saved pc 0x8454
4  called by frame at 0xbefffc70
5  source language c.
6  Arglist at 0xbefffc64, args: a=11, b=22
7  Locals at 0xbefffc64, Previous frame's sp is 0xbefffc68
8  Saved registers:
9   r11 at 0xbefffc64

7.info frame args 打印指定棧幀的詳細信息

1 (gdb) i f 1
2 Stack frame at 0xbefffc70:
3  pc = 0x8454 in main (hello.c:22); saved pc 0xb6fcccc4
4  caller of frame at 0xbefffc68
5  source language c.
6  Arglist at 0xbefffc6c, args:
7  Locals at 0xbefffc6c, Previous frame's sp is 0xbefffc70
8  Saved registers:
9   r11 at 0xbefffc68, lr at 0xbefffc6c

8.info args 打印函數參數信息

1 (gdb) info args
2 a = 11
3 b = 22

9.info locals 打印當前可訪問的局部變量的信息。

1 (gdb) info locals
2 c = 0

10.怎樣知道一個棧幀的大小?

fp和sp之間的區域就是一個函數的棧幀的大小。
fp通常是指r11寄存器。
sp通常是指r13寄存器。

 1 (gdb) i r
 2 r0             0xb      11
 3 r1             0x16     22
 4 r2             0xb      11
 5 r3             0x8440   33856
 6 r4             0xbeffff14       3204448020
 7 r5             0x8304   33540
 8 r6             0xbefffc80       3204447360
 9 r7             0x8      8
10 r8             0x0      0
11 r9             0x0      0
12 r10            0xb6ffef7c       3070226300
13 r11            0xbefffc64       3204447332
14 r12            0xbefffd68       3204447592
15 sp             0xbefffc50       0xbefffc50
16 lr             0x8454   33876
17 pc             0x8428   0x8428 <func1+24>
18 cpsr           0x60000010       1610612752
19 
20 (gdb) disassemble
21 Dump of assembler code for function func1:
22    0x00008410 <+0>:     push    {r11}           ; (str r11, [sp, #-4]!)
23 => 0x00008414 <+4>:     add     r11, sp, #0        ;將sp中的內存地址放入r11,即設置fp
24    0x00008418 <+8>:     sub     sp, sp, #20        ;將sp中的內存地址減少20,即設置func1的棧頂指針,如上兩條指令執行完後,該函數的棧幀的大小就肯定了,20 bytes
25    0x0000841c <+12>:    str     r0, [r11, #-16]    ;函數參數賦值,將r0中的值存入[r11, #-16]內存地址,即函數實參入棧
26    0x00008420 <+16>:    str     r1, [r11, #-20]    ;函數參數賦值,將r1中的值存入[r11, #-16]內存地址
27    0x00008424 <+20>:    ldr     r2, [r11, #-16]
28    0x00008428 <+24>:    ldr     r3, [r11, #-20]
29    0x0000842c <+28>:    add     r3, r2, r3
30    0x00008430 <+32>:    str     r3, [r11, #-8]
31    0x00008434 <+36>:    sub     sp, r11, #0
32    0x00008438 <+40>:    pop     {r11}           ; (ldr r11, [sp], #4)
33    0x0000843c <+44>:    bx      lr
34 End of assembler dump.

 

有時在調試過程當中,想記錄下來操做的過程及相關信息,那麼 執行set logging on便可打卡記錄,默認存在gdb.txt。

固然也能夠本身指定log文件,set logging file logname

set logging overwrite on命令可讓輸出覆蓋以前的日誌文件;而 「set logging redirect on」命令會讓gdb的日誌不會打印在終端

相關文章
相關標籤/搜索