好的,我已经使用Linux Dwarf ldw 库将 backtrace_symbols 输出转换为源代码和行号,但我遇到了麻烦。 backtrace_symbols 给出了内存中的偏移量,在用作Dwarf的输入之前,我从中减去基地址(使用 dladdr()获得)。但似乎对于父可执行文件,我不应该减去基址,因为矮人偏移似乎包含它。
那么我如何区分我的代码中的EXE和SO(我希望有更好的东西比寻找结束.so')或者是否有不同的功能我可以调用它来获取父EXE的基址或零吗?
答案 0 :(得分:2)
不确定这是否是最好的方法,但是 ldw 有一个函数 dwarf_getelf(),它可以让你获得ELF信息,从那里使用 elf32 / 64_getehdr(),然后查看 e_type 字段。如果 e_type 是 ET_DYN ,则它是共享对象,您应该继续使用 dladdr 来查找要从其他地址删除的偏移量只需直接使用 backtrace 生成的地址。
答案 1 :(得分:1)
是的,你是对的。如果可执行文件是ET_EXEC
(不是DT_DYN
,即它不是与位置无关的可执行文件),则DWARF中的虚拟地址是程序映像中的真实虚拟地址。对于DT_DYN
,DWARF中的地址是模块基址的偏移量。
这在DWARF规范的7.3中有解释:
可执行文件的调试信息中的重定位地址 对象是虚拟地址和重定位的地址 调试信息对于共享对象是偏移相对 到那个加载的最低内存区域的开头 共享内存。
您应该在ELF标题中使用e_type
来区分它们。