gcc exmp.c -o exmp gdb ./exmp (gdb) b bar Breakpoint 1 at 0x401135 (gdb) r Starting program: /home/ahajkova/exmp Breakpoint 1, 0x0000000000401135 in bar () (gdb) step Single stepping until exit from function bar, which has no line number information. i = 2 0x0000000000401168 in main ()
(gdb) b bar Breakpoint 1 at 0x401135 (gdb) r Starting program: /home/ahajkova/exmp Breakpoint 1, 0x0000000000401135 in bar () (gdb) display/i $pc 1: x/i $pc => 0x401135 <bar+4>: sub $0x10,%rsp
在上述的 display 命令中,i 代表机器指令,$pc 表示程序计数器寄存器(即 PC 寄存器)。
在带调试符号的 -g 选项,重新编译示例程序后,你可以使用行号在 main 中 bar 调用上设置断点,然后再单步执行 bar 函数的语句:
1 2 3 4 5 6 7 8 9
gcc -g exmp.c -o exmp gdb ./exmp (gdb) b exmp.c:14 Breakpoint 1 at 0x401157: file exmp.c, line 14. (gdb) r Starting program: /home/ahajkova/exmp Breakpoint 1, main () at exmp.c:14 14bar(num());
(gdb) finish Run till exit from #0 num () at exmp.c:4 0x0000000000401161 in main () at exmp.c:14 14 bar(num()); Value returned is $1 = 2 (gdb) step bar (i=2) at exmp.c:9 9 printf("i = %d\n", i);
4、tbreak 命令
tbreak 命令会设置一个临时断点。如果你不想设置永久断点,那么这个命令是很有用的。举个例子?,你想进入一个复杂的函数调用,例如 f(g(h()), i(j()), ...),在这种情况下,你需要一个很长的 step/finish/step 序列,才能到达 f 函数。如果你设置一个临时断点,然后再使用 continue 命令,这样就不需要以上的序列了。为了证明这一点,你需要像以前一样将断点设置在 main 的 bar 调用上。然后在 bar 上设置临时断点。当到达该临时断点后,临时断点会被自动删除。
1 2 3 4 5 6 7
(gdb) r Starting program: /home/ahajkova/exmp Breakpoint 1, main () at exmp.c:14 14bar(num()); (gdb) tbreak bar Temporary breakpoint 2 at 0x40113c: file exmp.c, line 9.
在调用 bar 的时候遇到断点,并在 bar 上设置临时断点后,你只需要使用 continue 继续运行直到 bar 结束。
1 2 3 4 5
(gdb) continue Continuing. Temporary breakpoint 2, bar (i=2) at exmp.c:9 9 printf("i = %d\n", i);
5、disable 命令
类似地,你也可以在 bar 上设置一个正常的断点,然后执行 continue,然后在不再需要第二个断点时,使用 disable 命令禁用这个断点,这样也能达到与 tbreak 相同的效果。
1 2 3 4 5 6 7 8 9 10 11 12 13 14
(gdb) b exmp.c:14 Breakpoint 1 at 0x401157: file exmp.c, line 14. (gdb) r Starting program: /home/ahajkova/exmp Breakpoint 1, main () at exmp.c:14 14bar(num()); (gdb) b bar Breakpoint 2 at 0x40113c: file exmp.c, line 9. (gdb) c Continuing. Breakpoint 2, bar (i=2) at exmp.c:9 9printf("i = %d\n", i); (gdb) disable 2
(gdb) info breakpoints Num Type Disp Enb Address What 1breakpoint keep y 0x0000000000401157 in main at exmp.c:14 breakpoint already hit 1 time 2breakpoint keep n 0x000000000040113c in bar at exmp.c:9 breakpoint already hit 1 time (gdb) enable 2 (gdb) info breakpoints Num Type Disp Enb Address What 1breakpoint keep y 0x000000000040116a in main at exmp.c:19 breakpoint already hit 1 time 2breakpoint keep y 0x0000000000401158 in bar at exmp.c:14 breakpoint already hit 1 time
6、advance 命令运行程序到指定的位置
另一个进入函数内部的方法是 advance 命令。你可以简单地用 advance bar,来代替 tbreak bar ; continue。这一命令会将程序继续运行到指定的位置。
Breakpoint 1at0x401157: file exmp.c, line 14. (gdb) r Starting program: /home/ahajkova/exmp Breakpoint 1, main () at exmp.c:14 14 bar(num()); (gdb) advance bar bar (i=2) at exmp.c:9 9printf("i = %d\n", i);
7、skip 命令
进入 bar 函数的另一种方式是使用 skip num 命令:
1 2 3 4 5 6 7 8 9 10 11 12
(gdb) b exmp.c:14 Breakpoint 1at0x401157: file exmp.c, line 14. (gdb) skip num Function num will be skipped when stepping. (gdb) r Starting program: /home/ahajkova/exmp Breakpoint 1, main () at exmp.c:14 14 bar(num()); (gdb) step bar (i=2) at exmp.c:9 9printf("i = %d\n", i);
请使用 info skip 命令,来了解 GDB 跳过了哪些函数。num() 函数被标记为 y,表示跳过了 num() 函数:
1 2 3 4
(gdb) info skip Num Enb Glob File RE Function 1 y n <none> n num
(gdb) skip bar (gdb) skip disable 1 (gdb) info skip Num Enb Glob File RE Function 1 n n <none> n num 2 y n <none> n bar (gdb) skipdelete (gdb) info skip Not skipping any files or functions.