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的日志不会打印在终端

相关文章
相关标签/搜索