我正在寻找核心文件回溯中有关如何解释地址的任何参考或指南。 例如典型的回溯看起来像:
(gdb) where
#0 [0x000012345] in func1 + 123 (a.out + 0xABC)
#1 [0x000034345] in func2 + 567 (a.out + 0xea7)
..
我可以使用-g
进行编译并获取确切的行号。但是生产环境中的可执行文件不会使用-g
进行编译,在这种情况下,我会得到如上的堆栈。
我想知道:
地址和偏移量 [0x000012345],+ 123和0xABC表示如何解释它们以及如何将它们映射到源代码中的行号。
感谢任何帮助。
答案 0 :(得分:1)
在大多数体系结构上,如果没有调试信息就无法从核心文件中获取良好的数据。即使像堆栈展开之类的简单操作也将不起作用。熟悉处理器体系结构和ABI的专家将能够从中确定许多事情,但这是一个繁琐的手动过程。
对于其余的答案,我假设您正在使用GCC。如果您使用优化和 -g
编译可执行文件,则GCC将使用调试信息创建可用于生产环境的二进制文件。除非存在编译器错误(很少见),否则-g
不会影响生成的代码。调试信息由侧面的数据表组成(这会引起调试问题,因为机器代码和原始代码在各个语句的执行顺序等方面可能相距很远)。
如果您不想分发带有调试信息的生产二进制文件,则应该使用-g
still 进行编译,但是在分发二进制文件之前,请使用strip
删除调试信息,同时保留未剥离的二进制文件供您自己记录。稍后在分析核心文件时,将使用这些未剥离的二进制文件,而不是您提供的已剥离的二进制文件。您引用的内存偏移量在剥离的和未剥离的二进制文件中是相同的,这就是为什么这样做的原因。
对于更高级的用法,您还可以使用诸如eu-strip -f
之类的工具来分隔调试信息,但这在您看来并不是必需的。