从 ELF 二进制文件中提取调试符号信息

6

让我们来看一下这个基本的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选项去掉了符号。

现在,我想要将我的elf可执行文件“拆分”成两个文件: - 一个去掉符号的elf可执行文件 - 一个外部调试符号文件。

以下是我在一些教程中看到的内容:

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无法解析我的add函数?
谢谢。
1个回答

8
如果我以这种方式编译:gcc test.c,我可以在gdb中看到调试符号。
但是,这里你并没有看到调试符号,只有符号表(与调试符号不同)。
要查看调试符号,请使用gcc -g test.c进行编译。
问题在于,当GDB看到“未装饰”的a.out时,它会丢弃先前指定的符号文件(a.dbg),并将其替换为(完全剥离的)a.out。你需要执行以下命令:gdb -s a.dbg a.out
gdb -s a.dbg -e a.out

更新:

"stripped"文件是什么意思: 这是指没有符号表或没有调试信息的文件吗?

在ELF平台上,关于“strip”文件的状态并不是二进制的:你可以删除文件的单个部分,并且取决于您删除了什么内容,您的调试体验将受到不同程度的影响。

这条命令: strip -g a.out 删除所有 .debug_* 部分,使您无法获得指令地址到源文件和行映射,以及堆栈地址到本地变量映射。但是,符号表仍然存在于二进制文件中,并且可以用来提供指令地址到函数名称的映射。

这条命令: strip a.out 删除所有 .debug_* 部分,以及 .symtab.strtab (二者一起形成符号表)。此类二进制文件通常称为"完全剥离"。

也可以使用 obcopy 删除单个部分。可以删除源文件/行信息(.debug_line 部分),而不删除变量信息,反之亦然。

我尝试过运行 eu-unstrip ./a.out ./a.dbg 但是 ./a.out 结果文件不包含调试信息。

您可能遇到了 eu-unstrip 的一个错误,也许是这个


谢谢。什么是“stripped”文件:这是否意味着这是一个没有符号表或调试信息的文件?我尝试了eu-unstrip ./a.out ./a.dbg,但./a.out结果文件不包含调试信息。谢谢。 - Bob5421

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接