分析core文件
加载符号表
生成符号表文件(.debug)
一般来说,为了避免可执行文件或者库文件过大,会采用分离调试信息的编译方式。前提是gcc编译的时候需要带上-g选项,以生成调试信息。通过objcopy实现:
objcopy --only-keep-debug test test.debug
&& objcopy --strip-debug test
&& objcopy --add-gnu-debuglink=test.debug test
&& chmod -x test.debug
Qt可以通过qmake的CONFIG语法实现:
qmake CONFIG+=release CONFIG+=force_debug_info CONFIG+=separate_debug_info test.pro
查看符号表是否加载成功
将生成的.debug文件放在库和可执行文件同一目录下,或者是同一目录下.debug目录下。gdb 可执行文件 coreFile 就会自动加载相关的符号表文件。可以通过info sharedlibrary查看加载是否成功
-
不成功的情况:
Yes旁边是一个星号,而且只能定位到调用堆栈的哪个调用函数崩溃了 -
加载成功的情况
Yes旁边没有星号,而且能够定位到代码的哪个文件哪一行语句执行出错了,并且可以查看到相关的入参、变量等。
分析core文件
- gdb [产生core文件的程序] [core文件]
生成core文件后,使用gdb [可执行程序] [core文件] 分析core文件,在gdb中输入bt,即可查看到崩溃时的堆栈,输入quit则退出gdb.
查看stl容器内容
当 GDB(即 GNU Project Debugger)启动时,它在当前用户的主目录中寻找一个名为 .gdbinit 的文件;如果该文件存在,则 GDB 就可以执行该文件中的所有命令。添加.gdbinit文件到用户目录下即可。
(gdb) pmap
Prints std::map<TLeft and TRight> or std::multimap<TLeft and TRight> information. Works for std::multimap as well.
Syntax: pmap <map> <TtypeLeft> <TypeRight> <valLeft> <valRight>: Prints map size, if T defined all elements or just element(s) with val(s)
Examples:
pmap m - prints map size and definition
pmap m int int - prints all elements and map size
pmap m int int 20 - prints the element(s) with left-value = 20 (if any) and map size
pmap m int int 20 200 - prints the element(s) with left-value = 20 and right-value = 200 (if any) and map size
(gdb) q
调试正在运行的程序
sudo gdb -p PID
多线程调试
-
info threads 显示当前可调试的所有线程,每个线程会有一个GDB为其分配的ID,后面操作线程的时候会用到这个ID。 前面有*的是当前调试的线程。
-
thread ID 切换当前调试的线程为指定ID的线程。
-
break thread_test.c:123 thread all 在所有线程中相应的行上设置断点
-
thread apply ID1 ID2 command 让一个或者多个线程执行GDB命令command。
-
thread apply all command 让所有被调试线程执行GDB命令command。
-
set scheduler-locking off|on|step: 估计是实际使用过多线程调试的人都可以发现,在使用step或者continue命令调试当前被调试线程的时候,其他线程也是同时执行的,怎么只让被调试程序执行呢?通过这个命令就可以实现这个需求。off 不锁定任何线程,也就是所有线程都执行,这是默认值。 on 只有当前被调试程序会执行。 step 在单步的时候,除了next过一个函数的情况(熟悉情况的人可能知道,
查看内存值
使用examine命令(简写是x)来查看内存地址中的值。x命令的语法如下:
x/<n/f/u> <addr>
-
n 是一个正整数, 输出单元的个数 ,也就是说从当前地址向后显示几个地址的内容。
-
f 是输出格式。如果地址所指的是 字符串 ,那么格式可以是 s ,如果 地址是指令 地址 ,那么格式可以是 i 。x是以16进制形式输出,o是以8进制形式输出,u是无符号10进制格式。
-
u 表明一个单元的长度,如果不指定的话,GDB默认是4个bytes 。 u 参数可以用下面的字符来代替, b 表示单字节, h 表示双字节, w 表示四字 节, g 表示八字节。当我们指定了字节长度后, GDB 会从指内存定的内存地址开始,读写指定字节,并把其当作一个值取出来。
-
addr 表示一个内存地址。