GDB调试
gdb基本命令汇总
command | |
---|---|
file <文件名> | 加载被调试的可执行程序文件 |
run | 单步执行,运行程序,停在第一执行语句如果可执行程序需要传参,可写在run后面 |
list | 查看源代码,简写l |
set | 设置变量的值 |
next | 单步调试(不进入的单步执行,函数直接执行),简写n |
step | 单步调试(跳入自定义函数内部执行,使用finish退出该函数的调用函数),简写s |
backtrace | 查看函数的调用的栈和层级关系,简写bt |
frame | 切换函数的栈帧,简写f |
info | 查看函数内部局部变量的数值,简写i |
finish | 结束当前函数,返回到函数调用点 |
continue | 继续运行,简写c |
打印值及地址,简写p | |
quit | 退出gdb,简写q |
delete | 删除断点 |
调试可执行文件
-
文件是否可以被gdb调试,判断二进制文件编译时是否带有-g参数
- 方法一:要调试C/C++的程序,首先在编译源代码时加上-g参数(如果没有-g参数编译程序会报No debugging symbols found in)
- 方法二:读取可执行程序头部信息(看是否含有debug调试信息)readelf -S test_out | grep debug
[28] .debug_aranges PROGBITS 0000000000000000 00003039
[29] .debug_info PROGBITS 0000000000000000 00003069
[30] .debug_abbrev PROGBITS 0000000000000000 00003378
[31] .debug_line PROGBITS 0000000000000000 00003444
[32] .debug_str PROGBITS 0000000000000000 00003556
调试core文件
core dump:core的意思是内存,dump意思是扔出来(段错误)。开发和使用Unix程序时会出现程序down掉,有时会提示(core dumped),通过gdb分析core文件,方便我们快速定位问题
-
如何生成core文件
首先在当前终端输入ulimit -c,若为0,则不会生成core文件;若不为0,则会生成最大为这个数的core文件(数值可能会小了);我们需要必须让core文件生成,设置core大小为无限ulimit -c unlimited
-
如何指定存储core文件
%t:core dump产生的时间
%e:产生core dump的程序名称
%p:产生core dump的进程ID
-
方法一:终端设置临时修改
root模式下修改/proc/sys/kernel/core_pattern文件,/home/cjj/gdb-test/coredump/为存放core文件的目录
cjj@ubuntu:~/gdb-test$ su Password:
root@ubuntu:/home/cjj/gdb-test# echo /home/cjj/gdb-test/coredump/coredump.%t.%e.%p> /proc/sys/kernel/core_pattern
-
方法二:系统配置文件设置
修改linux内核配置文件==/etc/sysctl.conf==,添加如下:
kernel.core_pattern = /home/cjj/gdb-test/coredump/coredump.%t.%e.%p
kernel.core_uses_pid = 1
使能配置文件:
sysctl -p /etc/sysctl.conf
-
-
如何调试core文件,定位问题
- 方法一:gdb <可执行文件> <core文件>
cjj@ubuntu:~/gdb-test/coredump$ gdb ../test_out coredump.test_out.37006 GNU gdb (Ubuntu 9.1-0ubuntu1) 9.1 Copyright (C) 2020 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 "x86_64-linux-gnu". Type "show configuration" for configuration details. For bug reporting instructions, please see: <http://www.gnu.org/software/gdb/bugs/>. Find the GDB manual and other documentation resources online at: <http://www.gnu.org/software/gdb/documentation/>. For help, type "help". Type "apropos word" to search for commands related to "word"... Reading symbols from ../test_out... [New LWP 37006] Core was generated by `./test_out'. Program terminated with signal SIGSEGV, Segmentation fault. #0 __memset_avx2_unaligned_erms () at ../sysdeps/x86_64/multiarch/memset-vec-unaligned-erms.S:190 190 ../sysdeps/x86_64/multiarch/memset-vec-unaligned-erms.S: No such file or directory. (gdb) (gdb) bt #0 __memset_avx2_unaligned_erms () at ../sysdeps/x86_64/multiarch/memset-vec-unaligned-erms.S:190 #1 0x00005614d22c419f in main () at test.c:10 (gdb)
-
方法二:gdb <可执行文件>
cjj@ubuntu:~/gdb-test/coredump$ gdb ../test_out GNU gdb (Ubuntu 9.1-0ubuntu1) 9.1 Copyright (C) 2020 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 "x86_64-linux-gnu". Type "show configuration" for configuration details. For bug reporting instructions, please see: <http://www.gnu.org/software/gdb/bugs/>. Find the GDB manual and other documentation resources online at: <http://www.gnu.org/software/gdb/documentation/>. For help, type "help". Type "apropos word" to search for commands related to "word"... Reading symbols from ../test_out... (gdb) core-file coredump.test_out.37006 [New LWP 37006] Core was generated by `./test_out'. Program terminated with signal SIGSEGV, Segmentation fault. #0 __memset_avx2_unaligned_erms () at ../sysdeps/x86_64/multiarch/memset-vec-unaligned-erms.S:190 190 ../sysdeps/x86_64/multiarch/memset-vec-unaligned-erms.S: No such file or directory. (gdb) bt #0 __memset_avx2_unaligned_erms () at ../sysdeps/x86_64/multiarch/memset-vec-unaligned-erms.S:190 #1 0x00005614d22c419f in main () at test.c:10 (gdb)
注:gdb内部执行bt(back trance查看函数的调用的栈帧和层级关系)后,打印段错误产生原因memset和产生位置test.c:10
gdb断点调试
在开始断点调试前,我有三个疑问,我们带着这三个疑问展开下面的学习:
1. 什么是设置断点调试?
2. 设置断点调试,在实际开发中有什么作用?
3. 如何设置断点调试?
-
1. 什么是设置断点调试?
通过设置代码行、函数名、条件语句、指定例程入口位置暂停,然后分析变量值和堆栈信息。
-
单文件断点设置
command break line-number 使程序巧好在给定行之前停止 break function-name 使程序恰好在进入给定函数之前停止 break line or function if condition 如何condition条件为真,则程序会到达指定line或function之前停止 break routine 在指定例程入口处设置断点 -
多文件断点设置
command break file-name:line-number 使程序巧好在给定行之前停止
-
-
2. 设置断点调试,在实际开发中有什么作用?
16 //================用户传入方法====================== 17 void active_func() 18 { 19 printf("%s\n", __func__); 20 printf("go to home\n"); (gdb) 21 sleep(100); 22 } 23 24 void pthread_handler(void *value) 25 { 26 char *name = (char *)value; 27 28 if (0 == strcmp("cat", name)) 29 animal_active_handle(name, active_func); 30 (gdb) b 21 Breakpoint 1 at 0x12aa: file test.c, line 21. (gdb) run Starting program: /home/cjj/gdb-test/test_out [Thread debugging using libthread_db enabled] Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1". [New Thread 0x7ffff7d96700 (LWP 40777)] #########name=cat########## active_func go to home [New Thread 0x7ffff7595700 (LWP 40778)] [140737343215360]dog [New Thread 0x7ffff6d94700 (LWP 40779)] [Switching to Thread 0x7ffff7d96700 (LWP 40777)] Thread 2 "test_out" hit Breakpoint 1, active_func () at test.c:21 21 sleep(100); (gdb) bt #0 active_func () at test.c:21 #1 0x000055555555527b in animal_active_handle (name=0x555555556041 "cat", func=0x55555555528a <active_func>) at test.c:12 #2 0x00005555555552f9 in pthread_handler (value=0x555555556041) at test.c:29 #3 0x00007ffff7f94609 in start_thread (arg=<optimized out>) at pthread_create.c:477 #4 0x00007ffff7eb9163 in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:95 (gdb) info b Num Type Disp Enb Address What 1 breakpoint keep y 0x00005555555552aa in active_func at test.c:21 breakpoint already hit 1 time (gdb) info frame Stack level 0, frame at 0x7ffff7d95eb0: rip = 0x5555555552aa in active_func (test.c:21); saved rip = 0x55555555527b called by frame at 0x7ffff7d95ed0 source language c. Arglist at 0x7ffff7d95e98, args: Locals at 0x7ffff7d95e98, Previous frame's sp is 0x7ffff7d95eb0 Saved registers: rbp at 0x7ffff7d95ea0, rip at 0x7ffff7d95ea8 (gdb) info threads Id Target Id Frame 1 Thread 0x7ffff7d97740 (LWP 40773) "test_out" clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:78 * 2 Thread 0x7ffff7d96700 (LWP 40777) "test_out" active_func () at test.c:21 3 Thread 0x7ffff7595700 (LWP 40778) "test_out" 0x00007ffff7e7726f in __GI___clock_nanosleep ( clock_id=clock_id@entry=0, flags=flags@entry=0, req=req@entry=0x7ffff7594e90, rem=rem@entry=0x7ffff7594e90) at ../sysdeps/unix/sysv/linux/clock_nanosleep.c:78 4 Thread 0x7ffff6d94700 (LWP 40779) "test_out" clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:78 (gdb)
注:当代码量比较大,并且代码的调用比较复杂时候,可以在某个函数内添加断点,然后根据bt指令打印出函数调用的堆栈信息,可以清晰的知道这个函数是被谁调用的,方便分析函数的调用关系
-
3. 如何设置断点调试?
断点调试常用指令:r(run执行程序)、b(break trance设置断点)、n(next单步调试,运行到下一个断点)、p(print打印变量值)、l(list查看源码)、s(step单步调试,进入子函数内部)、d(delete删除断点)
设置断点后,可以在断点处查看堆栈信息及变量值,可以一步一步的看到变量和堆栈信息的变化,