可执行文件如果包含了debug信息,会变得很大,这样在资源受限的嵌入式系统里是不允许的,所以,一种解决方案是, 编译代码的时候,输出两个文件,一个是没有debug信息的文件,另一个是包含debug信息的文件。 前一个放到目标板上,后一个则是放在开发机器上,用来在debug的时候用。
下面通过一个例子说名如何这样做。
先写个简单的程序:
$ cat test20.c
int main(void)
{
int a = 0x12345678;
*(int *)a = 10;
return 0;
}
用下面的命令编出可执行文件:
gcc -g test20.c -o test20
生成debug信息文件:
objcopy --only-keep-debug test20 test20.debug
strip test20
关联两个文件:
objcopy --add-gnu-debuglink=test20.debug test20
上述明明在test20文件里加入了一个名为".gnu_debuglink"的section:
$ readelf -a test20 | grep "debuglink"
[27] .gnu_debuglink PROGBITS 00000000 00103a 000014 00 0 0 1
执行 test20,会产生一个 core 文件, 下面用 gdb调试这个文件:
$ gdb -q
(gdb) file test20
Reading symbols from /home/charles/test20...Reading symbols from /home/charles/test20.debug...done.
done.
(gdb) core-file core
[New LWP 3237]
warning: Can't read pathname for load map: Input/output error.
Core was generated by `./test20'.
Program terminated with signal 11, Segmentation fault.
#0 0x080483c4 in main () at test20.c:4
4 *(int *)a = 10;
可以看到,gdb自动读取了 test20.debug文件。
gdb查找debug文件(和可执行文件同名,以.debug结尾)遵循下面的规则:
1)到可执行文件所在的目录查找
2) 到可执行文件所在目录的以 .debug命名的目录查找
3) 使用 debug-file-directory来设置查找目录。此时,会查找它所设置的目录下的一个子目录:这个子目录是可执行文件的绝对路径名(去掉开始的 /).
举例说,使用 gdb调试 /usr/bin/ls, 对应的debug文件为 ls.debug, debug-file-directory 设置的目录为 /usr/lib/debug, 那么 gdb会依次查找:
/usr/bin/ls.debug
/usr/bin/.debug/ls.debug
/usr/lib/debug/usr/bin/ls.debug
下面把test20.debug从test20所在的目录移走,移到当前目录下的 home/charles/下,
~$ ls /home/charles/home/charles/test20.debug
/home/charles/home/charles/test20.debug
然后,建一个连接:
sudo ln -s /home/charles/home /usr/lib/debug/home
/usr/lib/debug是
debug-file-directory的默认目录。
下面重新用 gdb调试:
(gdb) file test20
Reading symbols from /home/charles/test20...Reading symbols from /home/charles/home/charles/test20.debug...done.
done.
(gdb) core-file core
[New LWP 3324]
warning: Can't read pathname for load map: Input/output error.
Core was generated by `/home/charles/test20'.
Program terminated with signal 11, Segmentation fault.
#0 0x080483c4 in main () at test20.c:4
4 *(int *)a = 10;
(gdb) show debug-file-directory
The directory where separate debug symbols are searched for is "/usr/lib/debug".
可以看到,gdb自动从 /home/lib/debug/home/charles/下读取了debug文件。
然后,删除廉洁 /usr/lib/debug/home.
再作如下调试:
(gdb) set debug-file-directory /home/charles/
(gdb) file test20
Reading symbols from /home/charles/test20...Reading symbols from /home/charles/home/charles/test20.debug...done.
done.
(gdb) core-file core
[New LWP 3324]
warning: Can't read pathname for load map: Input/output error.
Core was generated by `/home/charles/test20'.
Program terminated with signal 11, Segmentation fault.
#0 0x080483c4 in main () at test20.c:4
4 *(int *)a = 10;
可见,设置set-debug-directory是有效果的(网上有些人说这个没有效果)。
参考:
1. http://www.sourceware.org/gdb/current/onlinedocs/gdb/Separate-Debug-Files.html