当debug信息单独存放为一个文件时使用gdb调试CoreDump

为了便于开发,现在经常把可执行文件里的debug信息取出来单独作为一个文件,这样,可以使得可执行文件体积变小很多。比如,rpm包普遍采用这样的方法。

这种情况下,如果要对产生的 coredump进行调试,需要做一些特殊的设置。

下面以一个简单的例子来说明这种方法。

1. 先写几个测试文件:

$ cat lib1.c 
#include <stdio.h>

void fun1(void)
{
	printf("This is func1\n");
	int a = 1234;
	*(int*)a = 100;
}

$ cat lib2.c 
#include <stdio.h>
void fun2(void)
{
	printf("This is lib2\n");
}

$ cat test-build-id.c 
#include <stdio.h>
extern void fun1(void);
extern void fun2(void);

int main(void)
{
	fun1();
	fun2();
	return 0;
}

2.编译,取出每个文件的debug信息。

arm-linux-gnueabi-gcc -g -fpic -shared -Wl,--build-id lib2.c  -o libtest2.so
arm-linux-gnueabi-gcc -g -fpic -shared -Wl,--build-id lib1.c  -o libtest1.so 
arm-linux-gnueabi-gcc -g -Wl,--build-id test-build-id.c  -o test-build-id -ltest1 -ltest2 -L.
arm-linux-gnueabi-objcopy --only-keep-debug libtest1.so libtest1.so.debug
arm-linux-gnueabi-objcopy --only-keep-debug libtest2.so libtest2.so.debug
arm-linux-gnueabi-objcopy --only-keep-debug test-build-id test-build-id.debug
arm-linux-gnueabi-strip -g libtest1.so
arm-linux-gnueabi-strip -g libtest2.so
arm-linux-gnueabi-strip -g test-build-id

3. 到 ARM系统上运行编出的程序,会产生一个 coredump文件。

下面对coredump文件进行调试

首先要把动态库放到合适的位置,以便gdb能找到。

我把两个动态库放到了 

/home/charles/code/build-id/mnt/code/build-id

下面,  /mnt/code/build-id 对应着在 ARM目标系统上动态库的位置。

然后,设置 sysroot 为 /home/charles/code/build-id

(gdb) set sysroot  /home/charles/code/build-id
Reading symbols from /home/charles/code/build-id/mnt/code/build-id/libtest1.so...(no debugging symbols found)...done.
Reading symbols from /home/charles/code/build-id/mnt/code/build-id/libtest2.so...(no debugging symbols found)...done.
Reading symbols from /home/charles/code/build-id/lib/libc.so.6...done.
Reading symbols from /home/charles/code/build-id/lib/ld-linux.so.3...done.
(gdb) info locals 
No symbol table info available.
(gdb) bt full
#0  0xb6ee65e8 in fun1 () from /home/charles/code/build-id/mnt/code/build-id/libtest1.so
No symbol table info available.
#1  0x00010640 in main ()
No symbol table info available.

可以看到,因为动态库没有包含 debug信息,gdb有些信息是查不到。


4. 配置 debug文件。

先查看 libtest1.so.debug的 build-id:

 file libtest1.so.debug 
libtest1.so.debug: ELF 32-bit LSB  shared object, ARM, EABI5 version 1 (SYSV), dynamically linked, BuildID[sha1]=c383d3b680a398ba033e9d3793f1ed70f8c4790b, not stripped

先创建目录:

/home/charles/code/debug_files/.build-id
在这个目录下创建目录 c3.

c3为 libtest1.so.debug的 build id的前两个字符。

然后把文件libtest1.so.debug 名字改为 其 build-d的其余的字符:

mv libtest1.so.debug 83d3b680a398ba033e9d3793f1ed70f8c4790b.debug
把这个文件放到 c3目录下:

mv 83d3b680a398ba033e9d3793f1ed70f8c4790b.debug  c3/
同理,对另外一个动态库的debug文件做类似的操作。

5. 重新进入到 gdb里面,重新设置debug信息:

(gdb) set debug-file-directory /home/charles/code/debug_files
(gdb) set sysroot  /home/charles/code/build-id
Reading symbols from /home/charles/code/build-id/mnt/code/build-id/libtest1.so...Reading symbols from /home/charles/code/debug_files/.build-id/c3/83d3b680a398ba033e9d3793f1ed70f8c4790b.debug...done.
done.
Reading symbols from /home/charles/code/build-id/mnt/code/build-id/libtest2.so...Reading symbols from /home/charles/code/debug_files/.build-id/d1/39eaafb3d70487679e222d5a2e548543ab4dae.debug...done.
done.
Reading symbols from /home/charles/code/build-id/lib/libc.so.6...done.
Reading symbols from /home/charles/code/build-id/lib/ld-linux.so.3...done.
可以看到,现在 gdb找到了动态库的debug文件,并且load进来了。

(gdb) info locals 
a = 1234
(gdb) bt
#0  0xb6ee65e8 in fun1 () at lib1.c:7
#1  0x00010640 in main ()
(gdb) info sharedlibrary 
From        To          Syms Read   Shared Object Library
0xb6ee6438  0xb6ee65f8  Yes         /home/charles/code/build-id/mnt/code/build-id/libtest1.so
0xb6ed5438  0xb6ed55dc  Yes         /home/charles/code/build-id/mnt/code/build-id/libtest2.so
0xb6dadc40  0xb6e9f9f8  Yes         /home/charles/code/build-id/lib/libc.so.6
0xb6ef77c0  0xb6f124b8  Yes         /home/charles/code/build-id/lib/ld-linux.so.3
(gdb) 
现在能看到具体的信息了。

在把debug信息单独存放的时候,有两种方法:一种是 debug link的方法,另外一种就是 build-id,即是本文提到的方法。

在使用 build-id的时候,gdb 会到 debug-file-directories 设置的目录下检查有没有 .build-id目录,如果有,就到这个目录下查找

nn/nnnnnnnn.debug这样的文件, 其中 nn为文件的 build-id的前两个字符, nnnnn为剩余的字符。


P.S.

debug-file-directories 也可以设置多个不同的目录,之间用 冒号(:)隔开就行。

References:

1. https://sourceware.org/gdb/current/onlinedocs/gdb/Separate-Debug-Files.html


  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值