让我们来看看这个基本的c程序:
#include <stdio.h>
int myadd(int a, int b);
int myadd(int a, int b)
{
return a+b;
}
int main(int argc, char *argv[])
{
int res = myadd(argc,3);
printf("%d\n",res);
return 0;
}
我想要的是了解调试符号文件的工作原理。
如果我这样编译:
gcc test.c
我可以在gdb中看到调试符号:
gdb ./a.out
(gdb) disassemble myadd
Dump of assembler code for function myadd:
0x00000000000006b0 <+0>: push %rbp
那很好!
现在,如果我跑:
gcc -s test.c
这是我在gdb中得到的:
(gdb) disassemble myadd
No symbol table is loaded. Use the "file" command.
那也很好,因为我用-s gcc选项剥离了符号。
现在,我想&#34;分裂&#34;我的elf可执行文件包含2个文件: - 剥离的精灵可执行文件 - 外部调试符号文件。
这是我在一些教程中读到的内容:
gcc test.c
objcopy --only-keep-debug a.out a.dbg
strip ./a.out
但是,现在,如果我想运行gdb,我会告诉gdb查看./a.dbg中的调试符号
gdb -s ./a.dbg a.out
gdb无法解析myadd函数:
(gdb) disassemble myadd
No symbol table is loaded. Use the "file" command.
这就是我不明白的原因:为什么gdb不会解析myadd函数?
由于
答案 0 :(得分:5)
如果我这样编译:{{1}}我可以在gdb中看到调试符号
你不在这里看到调试符号,只看到符号表(与调试符号不同)。
要查看调试符号,请使用-=
进行编译。
gcc test.c
这里的问题是,当GDB看到&#34; unadorned&#34; gcc -g test.c
,它抛弃先前指定的符号文件(gdb -s a.dbg a.out
),用(完全剥离)a.out
替换。你想要:
a.dbg
<强>更新强>
什么意味着&#34;剥离&#34; file:这是否意味着这是一个没有符号表的文件或者没有debuging信息?
在ELF平台上,关于&#34; strip&#34; -ness的文件状态不是二进制文件:您可以删除文件的各个部分,并且根据您删除的确切内容,您的调试体验将是受到不同程度的影响。
此命令:a.out
删除所有gdb -s a.dbg -e a.out
部分,使您没有指令地址到源文件和行映射,没有堆栈地址到局部变量映射。但是,符号表保留在二进制文件中,可用于为函数名称映射提供指令地址。
此命令:strip -g a.out
删除所有.debug_*
部分,以及strip a.out
和.debug_*
(它们共同构成符号表)。这种二进制文件通常被称为&#34;完全剥离&#34;。
还可以使用.symtab
删除单个部分。可以删除源文件/行信息(.strtab
部分)而不删除变量信息,反之亦然。
我尝试过eu-unstrip ./a.out ./a.dbg但是./a.out结果文件不包含调试信息。
您可能会遇到obcopy
中的错误,可能是this one。