gdb调试tips

small tips:

set print element 0  # 打印所有字符串,默认长度200

1、内存查看命令x.

x/x 以十六进制输出

x/d 以十进制输出

x/c 以单字符输出

x/i  反汇编 – 通常,我们会使用 x/10i $ip-20 来查看当前的汇编($ip是指令寄存器)

x/s 以字符串输出

(gdb) x/10i main
   0x80483bb <main>:    push   %ebp
   0x80483bc <main+1>:    mov    %esp,%ebp
   0x80483be <main+3>:    and    $0xfffffff0,%esp
   0x80483c1 <main+6>:    sub    $0x20,%esp
   0x80483c4 <main+9>:    movl   $0x0,0x1c(%esp)
   0x80483cc <main+17>:    movl   $0x5,(%esp)
=> 0x80483d3 <main+24>:    call   0x8048394 <fact>
   0x80483d8 <main+29>:    mov    %eax,0x1c(%esp)
   0x80483dc <main+33>:    mov    0x1c(%esp),%eax
   0x80483e0 <main+37>:    leave  

2、内存断点break

break *addr 表示在地址addr处打断点.

(gdb) disassemble main
Dump of assembler code for function main:
   0x080483bb <+0>:    push   %ebp
   0x080483bc <+1>:    mov    %esp,%ebp
   0x080483be <+3>:    and    $0xfffffff0,%esp
   0x080483c1 <+6>:    sub    $0x20,%esp
   0x080483c4 <+9>:    movl   $0x0,0x1c(%esp)
   0x080483cc <+17>:    movl   $0x5,(%esp)
   0x080483d3 <+24>:    call   0x8048394 <fact>
   0x080483d8 <+29>:    mov    %eax,0x1c(%esp)
   0x080483dc <+33>:    mov    0x1c(%esp),%eax
   0x080483e0 <+37>:    leave  
   0x080483e1 <+38>:    ret    
End of assembler dump.
(gdb) b *0x080483d3
Breakpoint 1 at 0x80483d3: file test.c, line 14.
(gdb) run
Starting program: /mnt/hgfs/Share/csapp/a.out 

Breakpoint 1, 0x080483d3 in main () at test.c:14
14        c = fact(5);

3、打印寄存器

可以使用 info registers查看所有寄存器:

(gdb) info registers 
eax            0xbffff6c4    -1073744188
ecx            0x6400d69f    1677776543
edx            0x1    1
ebx            0x288ff4    2658292
esp            0xbffff5f0    0xbffff5f0
ebp            0xbffff618    0xbffff618
esi            0x0    0
edi            0x0    0
eip            0x80483c4    0x80483c4 <main+9>
eflags         0x286    [ PF SF IF ]
cs             0x73    115
ss             0x7b    123
ds             0x7b    123
es             0x7b    123
fs             0x0    0
gs             0x33    51

或者使用 p/x $ebp打印ebp寄存器的值

(gdb) p/x $ebp
$2 = 0xbffff618

4、设置观察点

 当我们需要关注每次执行后ebp的值,可以用display设置观察点

(gdb) display $ebp
1: $ebp = (void *) 0xbffff618
(gdb) si
14        c = fact(5);
1: $ebp = (void *) 0xbffff618
(gdb) si
0x080483d3    14        c = fact(5);
1: $ebp = (void *) 0xbffff618

5、多线程

info thread
显示gdb为每个线程分配的ID,前面有*的是当前调试的线程。

thread <ID>
切换到指定ID

set scheduler-locking off|on|step
off 不锁定任何线程,也就是所有线程都执行,这是默认值
on 只有当前被调试程序会执行
step 在单步的时候,除了next过一个函数的情况以外,只有当前线程会执行

6、条件断点

break  [where] if [condition]

7、fork调试

follow-fork-mode

在2.5.60版Linux内核及以后,GDB对使用fork/vfork创建子进程的程序提供了follow-fork-mode选项来支持多进程调试。

follow-fork-mode的用法为:

set follow-fork-mode [parent|child]

  • parent: fork之后继续调试父进程,子进程不受影响。
  • child: fork之后调试子进程,父进程不受影响。

因此如果需要调试子进程,在启动gdb后:

(gdb) set follow-fork-mode child

并在子进程代码设置断点。

此外还有detach-on-fork参数,指示GDB在fork之后是否断开(detach)某个进程的调试,或者都交由GDB控制:

set detach-on-fork [on|off]

  • on: 断开调试follow-fork-mode指定的进程。
  • off: gdb将控制父进程和子进程。follow-fork-mode指定的进程将被调试,另一个进程置于暂停(suspended)状态。
原文地址:https://www.cnblogs.com/ym65536/p/4264731.html