參考
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);
暫時寫到這