GDB Tips
这篇博客旨在记录日常工作中遇到的GDB的基本调试功能,以供日后参考。
1 set sysroot [rootfs]
由于工作于嵌入式环境,因此不免经常需要调试目标系统(target)的crash问题,这时候一般需要以下几步:
- 在host上安装一个可以分析target文件格式的GDB (例如:
gdb-multiarch
) - 将target的rootfs解压缩到host上(例如:
/tmp/rootfs
) - 由于大部分嵌入式系统为了节省空间,其二进制文件都是去debug信息的(stripped, 一般通过
strip
完成),因此需要找到与crash相关的带debug信息的文件(一般通过objcopy --only-keep-debug
生成),在对应的二进制的同目录下的创建一个.debug目录,然后将debug信息文件名改为和对应二进制文件相同,并置于.debug目录 - 打开gdb,加载core文件,然后在gdb shell中输入
set sysroot /tmp/rootfs
, 然后输入bt
. 如果core文件是完整的并且所有相关文件的debug版都已经放在相应位置,那么此时你应该可以看到完整的调用信息
2 add-symbol-file [file] [address]
接着上一节,如果core是不完整的,那么在加载core文件以后,会看到如下信息:
Warning: xxx/core is truncated: expected core file size >= 412385280, found: 287272960.
此时,上面的方法你可能就会得到一堆问号:
#0 0x2861bac4 in ?? ()
#1 0x2861bab0 in ?? ()
#2 0x2861bab0 in ?? ()
- 找到最后的调用地址: 0x2861bab0
- 找到记录了core发生时记录了内存地址映射的文件(例如,cortex.dump),在其中找到0x2861bab0这个地址是在哪个二进制文件中的, 并且找到该文件的起始地址(假设是0x28610000)
-
找到该二进制文件,找到它的.text段的偏移地址。例如:
Address Offset Size EntSize Flag Link Info Align [10] .text PROGBITS 0002ce90 02ce90 059cd4 00 AX 0 0 8 ^
- 两个地址相加,计算得到该二进制文件的.text在内存中的起始地址:
0x2ce90 + 0x28610000 = 0x2863ce90
- 执行[1]中的步骤,在执行
set sysroot
之后,再执行add-symbol-file [带debug信息的二进制文件] [0x2863ce90]
。然后,执行bt
3 Print Real Class
Given a base class pointer(ptr
), which actually points to the derived class. One can try following method to see the real class of this pointer:
-
Method 1 (this doesn’t work for me in GDB 7.11.1):
- Run
set print object on
- Run
ptype ptr
- Run
-
Method 2 (make use of vtable to check the real type)
- Run
p /a (*(void ***)ptr)[0]
- Run
4 添加文件搜索路径
有时候要加断点的时候需要指定某个文件中的某一行,此时gdb会去搜索这个文件,搜索的路径(source path) 可以通过 show dir
看到。
如果文件所在的路径不在source path里,要通过 dir <path>
加入进去。
详见这里
Comments