2.gdb 的常用命令 表 1-4 常用的 gdb 命令 命令 解释 break NUM 在指定的行上设置断点。 BT 显示所有的调用栈帧。该命令可用来显示函数的调用顺序。 clear 删除设置在特定源文件、特定行上的断点。其用法为:clear FILENAME:NUM。 continue 继续执行正在调试的程序。该命令用在程序由于处理信号或断点而 导致停止运行时。 display EXPR 每次程序停止后显示表达式的值。表达式由程序定义的变量组成。 file FILE 装载指定的可执行文件进行调试。 help NAME 显示指定命令的帮助信息。 info break 显示当前断点清单,包括到达断点处的次数等。 info files 显示被调试文件的具体信息。 info func 显示所有的函数名称。 info local 显示当函数中的局部变量信息。 info prog 显示被调试程序的执行状态。 info var 显示所有的全局和静态变量名称。 kill 终止正被调试的程序。 list 显示源代码段。 make 在不退出 gdb 的情况下运行 make 工具。 next 在不单步执行进入其他函数的情况下,向前执行一行源代码。 print EXPR 显示表达式 EXPR 的值。
★ -O 编译选项 With `-O', the compiler tries to redUCe code size and execution time. When you specify `-O', the two options `-fthread-jumps' and `-fdefer-pop' are turned on 优化,减少代码大小和执行的时间 [alert7@redhat62 alert7]$ gcc -O -o test test.c [alert7@redhat62 alert7]$ wc -c test 11757 test [alert7@redhat62 alert7]$ gdb -q test (gdb) disass main Dump of assembler code for function main: 0x80483d8 : push %ebp 0x80483d9 : mov %esp,%ebp 0x80483db : call 0x80483c8 0x80483e0 : xor %eax,%eax 0x80483e2 : leave 0x80483e3 : ret 0x80483e4 : nop ... End of assembler dump. (gdb) disass hi Dump of assembler code for function hi:
★ -O2 编译选项 -O2 Optimize even more. Nearly all supported optimizations that do not involve a space-speed tradeoff are performed. Loop unrolling and function inlining are not done, for example. As compared to -O, this option increases both compilation time and the performance of the generated code. [alert7@redhat62 alert7]$ gcc -O2 -o test test.c [alert7@redhat62 alert7]$ wc -c test 11757 test [alert7@redhat62 alert7]$ gdb -q test (gdb) disass main Dump of assembler code for function main: 0x80483d8 : push %ebp 0x80483d9 : mov %esp,%ebp 0x80483db : call 0x80483c8 0x80483e0 : xor %eax,%eax 0x80483e2 : leave 0x80483e3 : ret ... 0x80483ef : nop End of assembler dump. (gdb) disass hi Dump of assembler code for function hi: 0x80483c8 : push %ebp 0x80483c9 : mov %esp,%ebp 0x80483cb : push $0x8048440 0x80483d0 : call 0x8048308 0x80483d5 : leave 0x80483d6 : ret 0x80483d7 : nop End of assembler dump. 由于程序比较简单,再优化也没有好优化的了,所以跟-O出来的一样。
★ -fomit-frame-pointer 编译选项 -fomit-frame-pointer Don't keep the frame pointer in a register for functions that don't need one. This avoids the instructions to save, set up and restore frame pointers; it also makes an extra register available in many functions. It also makes debugging impossible on most machines. 忽略帧指针。这样在程序就不需要保存,安装,和恢复ebp了。这样ebp也就是一个free的register了,在函数中就可以随便使用了。
[alert7@redhat62 alert7]$ gcc -fomit-frame-pointer -o test test.c [alert7@redhat62 alert7]$ wc -c test 11773 test [alert7@redhat62 alert7]$ gdb -q test (gdb) disass main Dump of assembler code for function main: 0x80483e0 : call 0x80483d0 0x80483e5 : xor %eax,%eax 0x80483e7 : jmp 0x80483f0 0x80483e9 : lea 0x0(%esi,1),%esi 0x80483f0 : ret .... End of assembler dump. (gdb) disass hi Dump of assembler code for function hi: 0x80483d0 : push $0x8048450 0x80483d5 : call 0x8048308 0x80483da : add $0x4,%esp 0x80483dd : ret 0x80483de : mov %esi,%esi End of assembler dump. 在main()和hi()中都去掉了以下指令 push %ebp mov %esp,%ebp//这两条指令安装 leave//这条指令恢复 来看看部分的内存映象 (内存高址) +--------+ bffffbc4 argv的地址(即argv[0]的地址) 0xbffffb84 +--------+ 00000001 argc的值 0xbffffb80 +--------+ 400309cbmain的返回地址 0xbffffb7c +--------+ 080483e5 hi()的返回地址 0xbffffb78 +--------+ 08048450 "hi"字符串的地址 0xbffffb74 +--------+ ...... (内存低址) 没有保存上层执行环境的ebp.
★ -static 编译选项 -static On systems that support dynamic linking, this prevents linking with the shared libraries. On other systems, this option has no effect. 把一些函数都静态的编译到程序中,而无需动态链接了。 [alert7@redhat62 alert7]$ gcc -o test -static test.c [alert7@redhat62 alert7]$ wc -c test 962808 test [alert7@redhat62 alert7]$ gdb -q test (gdb) disass main Dump of assembler code for function main: 0x80481b4 : push %ebp 0x80481b5 : mov %esp,%ebp 0x80481b7 : call 0x80481a0 0x80481bc : xor %eax,%eax 0x80481be : jmp 0x80481c0 0x80481c0 : leave 0x80481c1 : ret ... End of assembler dump. (gdb) disass hi Dump of assembler code for function hi:
0x80481a0 : push %ebp 0x80481a1 : mov %esp,%ebp 0x80481a3 : push $0x8071528 0x80481a8 : call 0x804865c 0x80481ad : add $0x4,%esp 0x80481b0 : leave 0x80481b1 : ret 0x80481b2 : mov %esi,%esi End of assembler dump. [alert7@redhat62 alert7]$ ldd test not a dynamic executable -static出来的代码已经没有PLT了,GOT虽然有,已经全部为0了。