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

Bob*_*421 6 debugging gcc gdb

我们来看看这个基本的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;
}
Run Code Online (Sandbox Code Playgroud)

我想要的是了解调试符号文件的工作原理.

如果我这样编译:

gcc test.c 
Run Code Online (Sandbox Code Playgroud)

我可以在gdb中看到调试符号:

gdb ./a.out
(gdb) disassemble myadd
Dump of assembler code for function myadd:
   0x00000000000006b0 <+0>: push   %rbp
Run Code Online (Sandbox Code Playgroud)

没关系 !

现在,如果我跑:

gcc -s test.c 
Run Code Online (Sandbox Code Playgroud)

这是我在gdb中得到的:

(gdb) disassemble myadd
No symbol table is loaded.  Use the "file" command.
Run Code Online (Sandbox Code Playgroud)

那也没关系,因为我用-s gcc选项剥离了符号.

现在,我想在两个文件中"拆分"我的elf可执行文件: - 剥离的精灵可执行文件 - 外部调试符号文件.

这是我在一些教程中读到的内容:

gcc test.c
objcopy --only-keep-debug a.out a.dbg
strip ./a.out 
Run Code Online (Sandbox Code Playgroud)

但是,现在,如果我想运行gdb,我会告诉gdb查看./a.dbg中的调试符号

gdb -s ./a.dbg a.out
Run Code Online (Sandbox Code Playgroud)

并且gdb无法解析myadd函数:

(gdb) disassemble myadd
No symbol table is loaded.  Use the "file" command.
Run Code Online (Sandbox Code Playgroud)

这是我不明白的:为什么gdb不解析myadd函数?

谢谢

Emp*_*ian 7

如果我这样编译:gcc test.c我可以在gdb中看到调试符号

不会看到调试符号在这里,只有符号表(这是从调试符号不同).

要查看调试符号,请使用gcc -g test.c.

gdb -s a.dbg a.out

这里的问题是,当GDB看到"unadorned"时a.out,它抛弃先前指定的符号文件(a.dbg)并用(完全剥离)替换a.out.你要:

gdb -s a.dbg -e a.out
Run Code Online (Sandbox Code Playgroud)

更新:

什么意思是"剥离"文件:这是否意味着这是一个没有符号表或没有debuging信息的文件?

在ELF平台上,与"strip"-ness相关的文件状态不是二进制文件:您可以删除文件的各个部分,并且根据您删除的确切内容,您的调试体验将受到不同程度的影响.

此命令:strip -g a.out删除所有.debug_*部分,使您没有指令地址到源文件和行映射,并且没有堆栈地址到局部变量映射.但是,符号表保留在二进制文件中,可用于为函数名称映射提供指令地址.

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

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

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

你可能会遇到一个bug eu-unstrip,也许就是这个.