参考
http://beej.us/guide/bggdb/#compiling
https://blog.csdn.net/liigo/article/details/582231/
http://blog.jobbole.com/107759/
gdb 最直观的作用就是能快速的定位到段错误的位置,前提是编译的时候有加上 -g,如果遇到开源的代码,那。。只能反汇编慢慢找了
常用的gdb指令
执行 gdb test
run
回溯 bt (backtrace的简写)
反汇编 disas (disassemble的简写)
查看寄存器 i r (info registers 的简写)
内存映射 i proc m (info proc mappings 的简写)
打断点
b mod_search.c:39 () //源文件行数
b *load_module +173 () //反汇编的行数
单步调试 si (stepi的简写)
显示文件 list kscore.c:10
显示断点信息 i b (info breakpoints的简写)
命令 | 解释 | 示例 |
file <文件名> | 加载被调试的可执行程序文件。 因为一般都在被调试程序所在目录下执行GDB,因而文本名不需要带路径。 | (gdb) file test 或者 gdb test |
r | Run的简写,运行被调试的程序。 如果此前没有下过断点,则执行完整个程序;如果有断点,则程序暂停在第一个可用断点处。 | (gdb) r |
bt | 栈回溯显示我们是如何到达失败点的,通常足够帮助我们确定常见的问题。 | (gdb) bt |
c | Continue的简写,继续执行被调试程序,直至下一个断点或程序结束。 | (gdb) c |
b <行号> b <函数名称> b *<函数名称> b *<代码地址> d [编号] | b: Breakpoint的简写,设置断点。两可以使用“行号”“函数名称”“执行地址”等方式指定断点位置。 d: Delete breakpoint的简写,删除指定编号的某个断点,或删除所有断点。断点编号从1开始递增。 | (gdb) b 8 (gdb) b main (gdb) b *main (gdb) b *0x804835c (gdb) d |
s, n | s: 执行一行源程序代码,如果此行代码中有函数调用,则进入该函数; s 相当于其它调试器中的“Step Into (单步跟踪进入)”; 这两个命令必须在有源代码调试信息的情况下才可以使用(GCC编译时使用“-g”参数)。 | (gdb) s (gdb) n |
si, ni | si命令类似于s命令,ni命令类似于n命令。所不同的是,这两个命令(si/ni)所针对的是汇编指令,而s/n针对的是源代码。 | (gdb) si (gdb) ni |
p <变量名称> | Print的简写,显示指定变量(临时变量或全局变量)的值。 | (gdb) p i (gdb) p nGlobalVar |
display ... undisplay <编号> | display,设置程序中断后欲显示的数据及其格式。 undispaly,取消先前的display设置,编号从1开始递增。 | (gdb) display /i $pc (gdb) undisplay 1 |
i | Info的简写,用于显示各类信息,详情请查阅“help i”。 | (gdb) i r |
q | Quit的简写,退出GDB调试环境。 | (gdb) q |
help [命令名称] | GDB帮助命令,提供对GDB名种命令的解释说明。 如果指定了“命令名称”参数,则显示该命令的详细说明;如果没有指定参数,则分类显示所有GDB命令,供用户进一步浏览和查询。 | (gdb) help display |
实际应用,编译可执行文件
运行方式1:gdb test
root@IT-PC-135:/home/user1/hong/smdd/demo/05-kscore# gdb test
GNU gdb (Ubuntu/Linaro 7.4-2012.04-0ubuntu2) 7.4-2012.04
Copyright (C) 2012 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "i686-linux-gnu".
For bug reporting instructions, please see:
<http://bugs.launchpad.net/gdb-linaro/>...
Reading symbols from /home/user1/hong/smdd/demo/05-kscore/test...done.
(gdb)
运行方式2
先进入gdb后运行test
root@IT-PC-135:/home/user1/hong/smdd/demo/05-kscore# gdb
GNU gdb (Ubuntu/Linaro 7.4-2012.04-0ubuntu2) 7.4-2012.04
Copyright (C) 2012 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "i686-linux-gnu".
For bug reporting instructions, please see:
<http://bugs.launchpad.net/gdb-linaro/>.
(gdb) file test
Reading symbols from /home/user1/hong/smdd/demo/05-kscore/test...done.
(gdb)
运行
root@IT-PC-135:/home/user1/hong/smdd/demo/05-kscore# gdb test
GNU gdb (Ubuntu/Linaro 7.4-2012.04-0ubuntu2) 7.4-2012.04
Copyright (C) 2012 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "i686-linux-gnu".
For bug reporting instructions, please see:
<http://bugs.launchpad.net/gdb-linaro/>...
Reading symbols from /home/user1/hong/smdd/demo/05-kscore/test...done.
(gdb) run
Starting program: /home/user1/hong/smdd/demo/05-kscore/test
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/i386-linux-gnu/libthread_db.so.1".
[2019-02-28 20:41:24 18428==func:main file:main.c line:66]==hello world!
[2019-02-28 20:41:24 18428==func:load_module file:mod_failover.c line:37]======load module:failover====
[2019-02-28 20:41:24 18428==func:load_module file:mod_sysconf.c line:37]======load module:sysconf====
[2019-02-28 20:41:24 18428==func:load_module file:mod_search.c line:37]======load module:search====
[2019-02-28 20:41:24 18428==func:load_module file:mod_log.c line:37]======load module:log====
栈回溯
root@IT-PC-135:/home/user1/hong/smdd/demo/05-kscore# gdb test
GNU gdb (Ubuntu/Linaro 7.4-2012.04-0ubuntu2) 7.4-2012.04
Copyright (C) 2012 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "i686-linux-gnu".
For bug reporting instructions, please see:
<http://bugs.launchpad.net/gdb-linaro/>...
Reading symbols from /home/user1/hong/smdd/demo/05-kscore/test...done.
(gdb) run
Starting program: /home/user1/hong/smdd/demo/05-kscore/test
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/i386-linux-gnu/libthread_db.so.1".
[2019-02-28 20:57:15 18506==func:main file:main.c line:66]==hello world!
[2019-02-28 20:57:15 18506==func:load_module file:mod_failover.c line:37]======load module:failover====
[2019-02-28 20:57:15 18506==func:load_module file:mod_sysconf.c line:37]======load module:sysconf====
[2019-02-28 20:57:15 18506==func:load_module file:mod_search.c line:37]======load module:search====
Program received signal SIGSEGV, Segmentation fault.
0x08049d17 in load_module () at mod_search.c:39
39 *x = 1;
(gdb) bt
#0 0x08049d17 in load_module () at mod_search.c:39
#1 0x08048b28 in load_modules () at kscore.c:28
#2 0x08048bd8 in ks_core_start (verify=1) at kscore.c:55
#3 0x08049672 in main (argc=1, argv=0xbffff6f4) at main.c:67
#0、#1、#2、#3显示了段错误出现前的函数
从下往上,按照从父函数到子函数的顺序看。main.c -> ks_core_staart -> load_modules -> load_module -> *x = 1;
这是最理想的情况,直接定位到触发段错误代码的具体行数
打断点
打断点的方式有很多种,比较方便的有
1.函数断点 ,比如在main函数打断点, break main
2.某个.c文件某一行 比如在mod_search.c 的38行 break mod_search.c :38
3.当崩溃之后,可以反汇编查看具体的代码地址,根据地址打断点
//在mod_search 的load_module()函数里,故意设置一个空指针,赋值导致段错误
static int load_module(void)
{
if(g_search_conf.loaded)
return 1;
ksprintf("====load module:%s====", MD_NAME_SEARCH);
int *x = NULL;//空指针
*x = 1;//空指针赋值,段错误
g_search_conf.loaded = 1;
g_search_conf.debug = 0;
if(init_module() != 0)
{
ksdebug(DEBUG_WRN, "load module:%s failed.", MD_NAME_SEARCH);
g_search_conf.loaded = 0;
return -1;
}
return 0;
}
root@IT-PC-135:/home/user1/hong/smdd/demo/05-kscore# gdb test
GNU gdb (Ubuntu/Linaro 7.4-2012.04-0ubuntu2) 7.4-2012.04
Copyright (C) 2012 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "i686-linux-gnu".
For bug reporting instructions, please see:
<http://bugs.launchpad.net/gdb-linaro/>...
Reading symbols from /home/user1/hong/smdd/demo/05-kscore/test...done.
(gdb) run
Starting program: /home/user1/hong/smdd/demo/05-kscore/test
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/i386-linux-gnu/libthread_db.so.1".
[2019-02-28 20:48:55 18486==func:main file:main.c line:66]==hello world!
[2019-02-28 20:48:55 18486==func:load_module file:mod_failover.c line:37]======load module:failover====
[2019-02-28 20:48:55 18486==func:load_module file:mod_sysconf.c line:37]======load module:sysconf====
[2019-02-28 20:48:55 18486==func:load_module file:mod_search.c line:37]======load module:search====
Program received signal SIGSEGV, Segmentation fault.
0x08049d17 in load_module () at mod_search.c:39
39 *x = 1;
(gdb)
(gdb) disa
disable disassemble
(gdb) disassemble
Dump of assembler code for function load_module:
0x08049c64 <+0>: push %ebp
0x08049c65 <+1>: mov %esp,%ebp
0x08049c67 <+3>: push %ebx
0x08049c68 <+4>: sub $0x4d4,%esp
0x08049c6e <+10>: mov %gs:0x14,%eax
0x08049c74 <+16>: mov %eax,-0xc(%ebp)
0x08049c77 <+19>: xor %eax,%eax
0x08049c79 <+21>: mov 0x804d13c,%eax
0x08049c7e <+26>: test %eax,%eax
0x08049c80 <+28>: je 0x8049c8c <load_module+40>
0x08049c82 <+30>: mov $0x1,%eax
0x08049c87 <+35>: jmp 0x8049e28 <load_module+452>
0x08049c8c <+40>: lea -0x2c(%ebp),%edx
0x08049c8f <+43>: mov $0x0,%ecx
0x08049c94 <+48>: mov $0x20,%eax
0x08049c99 <+53>: mov %eax,%ebx
0x08049c9b <+55>: and $0xfffffffc,%ebx
0x08049c9e <+58>: mov $0x0,%eax
0x08049ca3 <+63>: mov %ecx,(%edx,%eax,1)
0x08049ca6 <+66>: add $0x4,%eax
0x08049ca9 <+69>: cmp %ebx,%eax
0x08049cab <+71>: jb 0x8049ca3 <load_module+63>
0x08049cad <+73>: add %eax,%edx
0x08049caf <+75>: movl $0x0,(%esp)
0x08049cb6 <+82>: call 0x8048610 <time@plt>
0x08049cbb <+87>: lea -0x2c(%ebp),%edx
0x08049cbe <+90>: mov %edx,0x4(%esp)
0x08049cc2 <+94>: mov %eax,(%esp)
0x08049cc5 <+97>: call 0x8049018 <time_to_string>
0x08049cca <+102>: call 0x80486a0 <getpid@plt>
0x08049ccf <+107>: mov $0x804a888,%edx
0x08049cd4 <+112>: movl $0x804a8c2,0x18(%esp)
0x08049cdc <+120>: movl $0x25,0x14(%esp)
0x08049ce4 <+128>: movl $0x804a8c9,0x10(%esp)
0x08049cec <+136>: movl $0x804a97c,0xc(%esp)
0x08049cf4 <+144>: mov %eax,0x8(%esp)
0x08049cf8 <+148>: lea -0x2c(%ebp),%eax
0x08049cfb <+151>: mov %eax,0x4(%esp)
0x08049cff <+155>: mov %edx,(%esp)
0x08049d02 <+158>: call 0x80485e0 <printf@plt>
0x08049d07 <+163>: movl $0x0,-0x4b0(%ebp)
0x08049d11 <+173>: mov -0x4b0(%ebp),%eax
=> 0x08049d17 <+179>: movl $0x1,(%eax)
0x08049d1d <+185>: movl $0x1,0x804d13c
0x08049d27 <+195>: movl $0x0,0x804d140
0x08049d31 <+205>: call 0x8049c50 <init_module>
0x08049d36 <+210>: test %eax,%eax
0x08049d38 <+212>: je 0x8049e23 <load_module+447>
0x08049d3e <+218>: mov 0x804d05c,%eax
0x08049d43 <+223>: and $0x2,%eax
0x08049d46 <+226>: test %eax,%eax
0x08049d48 <+228>: je 0x8049e11 <load_module+429>
0x08049d4e <+234>: lea -0x2c(%ebp),%edx
0x08049d51 <+237>: mov $0x0,%ecx
0x08049d56 <+242>: mov $0x20,%eax
---Type <return> to continue, or q <return> to quit---
0x08049d5b <+247>: mov %eax,%ebx
0x08049d5d <+249>: and $0xfffffffc,%ebx
0x08049d60 <+252>: mov $0x0,%eax
0x08049d65 <+257>: mov %ecx,(%edx,%eax,1)
0x08049d68 <+260>: add $0x4,%eax
0x08049d6b <+263>: cmp %ebx,%eax
0x08049d6d <+265>: jb 0x8049d65 <load_module+257>
0x08049d6f <+267>: add %eax,%edx
0x08049d71 <+269>: lea -0x2c(%ebp),%eax
0x08049d74 <+272>: mov %eax,(%esp)
0x08049d77 <+275>: call 0x8049090 <time_to_string_ks>
0x08049d7c <+280>: call 0x80486a0 <getpid@plt>
0x08049d81 <+285>: mov $0x804a8d8,%edx
0x08049d86 <+290>: movl $0x804a8c2,0x1c(%esp)
0x08049d8e <+298>: movl $0x2d,0x18(%esp)
0x08049d96 <+306>: movl $0x804a8c9,0x14(%esp)
0x08049d9e <+314>: movl $0x804a97c,0x10(%esp)
0x08049da6 <+322>: mov %eax,0xc(%esp)
0x08049daa <+326>: lea -0x2c(%ebp),%eax
0x08049dad <+329>: mov %eax,0x8(%esp)
0x08049db1 <+333>: movl $0x804a928,0x4(%esp)
0x08049db9 <+341>: mov %edx,(%esp)
0x08049dbc <+344>: call 0x80485e0 <printf@plt>
0x08049dc1 <+349>: mov 0x804d124,%eax
0x08049dc6 <+354>: test %eax,%eax
0x08049dc8 <+356>: je 0x8049e11 <load_module+429>
0x08049dca <+358>: mov 0x804d124,%ebx
0x08049dd0 <+364>: call 0x80486a0 <getpid@plt>
0x08049dd5 <+369>: movl $0x804a8c2,0x1c(%esp)
0x08049ddd <+377>: movl $0x2d,0x18(%esp)
0x08049de5 <+385>: movl $0x804a8c9,0x14(%esp)
0x08049ded <+393>: movl $0x804a97c,0x10(%esp)
0x08049df5 <+401>: mov %eax,0xc(%esp)
0x08049df9 <+405>: lea -0x2c(%ebp),%eax
0x08049dfc <+408>: mov %eax,0x8(%esp)
0x08049e00 <+412>: movl $0x804a928,0x4(%esp)
0x08049e08 <+420>: movl $0x804a8d8,(%esp)
0x08049e0f <+427>: call *%ebx
0x08049e11 <+429>: nop
0x08049e12 <+430>: movl $0x0,0x804d13c
0x08049e1c <+440>: mov $0xffffffff,%eax
0x08049e21 <+445>: jmp 0x8049e28 <load_module+452>
0x08049e23 <+447>: mov $0x0,%eax
0x08049e28 <+452>: mov -0xc(%ebp),%edx
0x08049e2b <+455>: xor %gs:0x14,%edx
0x08049e32 <+462>: je 0x8049e39 <load_module+469>
0x08049e34 <+464>: call 0x8048650 <__stack_chk_fail@plt>
0x08049e39 <+469>: add $0x4d4,%esp
0x08049e3f <+475>: pop %ebx
0x08049e40 <+476>: pop %ebp
0x08049e41 <+477>: ret
End of assembler dump.
(gdb) break *load_module <+179>
A syntax error in expression, near `'.
(gdb) break *load_module +179
Breakpoint 1 at 0x8049d17: file mod_search.c, line 39.
(gdb)
运行结果如上,打印显示Program received signal SIGSEGV, Segmentation fault. 段错误
disassemble 反汇编
=> 0x08049d17 <+179>: movl $0x1,(%eax) 表示段错误出现的地方,大概意思就是把0x01 这个值赋给寄存器eax
打断点 break *load_module +179 就是在指这行代码
查看寄存器
(gdb) i r
eax 0x0 0
ecx 0x0 0
edx 0xbfffeb58 -1073747112
ebx 0x20 32
esp 0xbfffebf0 0xbfffebf0
ebp 0xbffff0c8 0xbffff0c8
esi 0x0 0
edi 0x0 0
eip 0x8049d17 0x8049d17 <load_module+179>
eflags 0x210286 [ PF SF IF RF ID ]
cs 0x73 115
ss 0x7b 123
ds 0x7b 123
es 0x7b 123
fs 0x0 0
gs 0x33 51
通过反汇编得知=> 0x08049d17 <+179>: movl $0x1,(%eax) 表示段错误出现的地方
查看寄存器后,能看到
eax 0x0 0
eax地址是0,零不太可能是有效地址,并且解引用一个未初始化的指针或空指针引起的段错误是常见的软件 bug。
我们也可以通过内存映射来查看地址是不是有效
(gdb) i proc m
process 18506
Mapped address spaces:
Start Addr End Addr Size Offset objfile
0x8048000 0x804c000 0x4000 0x0 /home/user1/hong/smdd/demo/05-kscore/test
0x804c000 0x804d000 0x1000 0x3000 /home/user1/hong/smdd/demo/05-kscore/test
0x804d000 0x804e000 0x1000 0x4000 /home/user1/hong/smdd/demo/05-kscore/test
0x804e000 0x806f000 0x21000 0x0 [heap]
0xb7dfd000 0xb7dff000 0x2000 0x0
0xb7dff000 0xb7fa5000 0x1a6000 0x0 /lib/i386-linux-gnu/libc-2.15.so
0xb7fa5000 0xb7fa7000 0x2000 0x1a6000 /lib/i386-linux-gnu/libc-2.15.so
0xb7fa7000 0xb7fa8000 0x1000 0x1a8000 /lib/i386-linux-gnu/libc-2.15.so
0xb7fa8000 0xb7fab000 0x3000 0x0
0xb7fab000 0xb7fc2000 0x17000 0x0 /lib/i386-linux-gnu/libpthread-2.15.so
0xb7fc2000 0xb7fc3000 0x1000 0x16000 /lib/i386-linux-gnu/libpthread-2.15.so
0xb7fc3000 0xb7fc4000 0x1000 0x17000 /lib/i386-linux-gnu/libpthread-2.15.so
0xb7fc4000 0xb7fc6000 0x2000 0x0
0xb7fda000 0xb7fdd000 0x3000 0x0
0xb7fdd000 0xb7fde000 0x1000 0x0 [vdso]
0xb7fde000 0xb7ffe000 0x20000 0x0 /lib/i386-linux-gnu/ld-2.15.so
0xb7ffe000 0xb7fff000 0x1000 0x1f000 /lib/i386-linux-gnu/ld-2.15.so
0xb7fff000 0xb8000000 0x1000 0x20000 /lib/i386-linux-gnu/ld-2.15.so
0xbffdf000 0xc0000000 0x21000 0x0 [stack]
(gdb)
第一个有效的虚拟地址是 0x8048000。任何小于它的地址都是非法的,这些地址如果被引用,就会引起段错误。
单步调试 si
root@IT-PC-135:/home/user1/hong/smdd/demo/05-kscore# gdb test
GNU gdb (Ubuntu/Linaro 7.4-2012.04-0ubuntu2) 7.4-2012.04
Copyright (C) 2012 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "i686-linux-gnu".
For bug reporting instructions, please see:
<http://bugs.launchpad.net/gdb-linaro/>...
Reading symbols from /home/user1/hong/smdd/demo/05-kscore/test...done.
(gdb) break main
Breakpoint 1 at 0x80495e4: file main.c, line 65.
(gdb) run
Starting program: /home/user1/hong/smdd/demo/05-kscore/test
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/i386-linux-gnu/libthread_db.so.1".
Breakpoint 1, main (argc=1, argv=0xbffff6f4) at main.c:65
65 {
(gdb) si
0x080495ea 65 {
(gdb) si
0x080495ee 65 {
(gdb) si
66 ksprintf("hello world!");
(gdb) si
0x080495f4 66 ksprintf("hello world!");
(gdb) si
0x080495f9 66 ksprintf("hello world!");
(gdb) si
0x080495fe 66 ksprintf("hello world!");
(gdb) si
0x08049600 66 ksprintf("hello world!");
(gdb) si
0x08049603 66 ksprintf("hello world!");
(gdb) si
0x08049608 66 ksprintf("hello world!");
(gdb) si
0x0804960b 66 ksprintf("hello world!");
显示断点信息 i b
(gdb) i b
Num Type Disp Enb Address What
1 breakpoint keep y 0x080495e4 in main at main.c:65
2 breakpoint keep y 0x08049d07 in load_module at mod_search.c:38
删除断点, d 2 把Num为2的断点删除
(gdb) d 2
(gdb) i b
Num Type Disp Enb Address What
1 breakpoint keep y 0x080495e4 in main at main.c:65
(gdb)
gdb还可以用来查看代码,显示main.c文件
ch:l "文件名.后缀名":行号
(gdb) l mod_failover.c :20
15 {
16 int loaded;
17 int debug;
18 };
19 static struct md_failover_conf g_failover_conf = {0};
20
21 static int init_module()
22 {
23 return 0;
24 }
(gdb)
25
26 static int uninit_module()
27 {
28 return 0;
29 }
30
31
32 static int load_module(void)
33 {
34 if(g_failover_conf.loaded)
(gdb)
35 return 1;
36
37 ksprintf("====load module:%s====", MD_NAME_FAILOVER);
38
39 g_failover_conf.loaded = 1;
40 g_failover_conf.debug = 0;
41
42 if(init_module() != 0)
43 {
44 ksdebug(DEBUG_WRN, "load module:%s failed.", MD_NAME_FAILOVER);
暂时写到这