确定矮人中的内联函数地址

Determine inlined function address in dwarf

我有一个函数的虚拟地址(指令指针),从 backtrace 调用中获得。我需要找出关于它的调试信息。

例如,我需要有关attach_backtraces函数的信息。

nm -a Backtrace.so | grep attach_backtraces
000000000002cdfe t _ZN2xsL17attach_backtracesENS_3RefE

偏移量0x2cdfe 可以通过从PC (IP) 中减去.so 加载地址来确定。它与 nm 的输出匹配。

以下是我从readelf -w Backtrace.so

得到的信息
<3><3a14f>: Abbrev Number: 0
<2><3a150>: Abbrev Number: 161 (DW_TAG_subprogram)
  <3a152>   DW_AT_name        : (indirect string, offset: 0x21bf5): attach_backtraces
  <3a156>   DW_AT_decl_file   : 22
  <3a157>   DW_AT_decl_line   : 201
  <3a158>   DW_AT_decl_column : 13
  <3a159>   DW_AT_declaration : 1
  <3a159>   DW_AT_sibling     : <0x3a163>
<3><3a15d>: Abbrev Number: 1 (DW_TAG_formal_parameter)
  <3a15e>   DW_AT_type        : <0x36aac>
<3><3a162>: Abbrev Number: 0

为什么它的偏移量是 0x21bf5 而不是预期的 0x2cdfe?我错过了什么?我的下一步是查询 DWARF-info 以获取偏移 0x2cdfe 处的函数以获取调试信息。

PS。我正在收集完整的回溯,其中应显示符号名称、文件和行。 C/C++ 库更适合用于 parse/get 来自 DWARF 的信息?

插件:

不,readelf -w 输出中没有其他 attach_backtraces。我发现

DW_AT_sibling : <0x3a163>

它的定义:

不,readelf -w 输出中没有其他 attach_backtraces。我发现

DW_AT_sibling     : <0x3a163>

它的定义:

<1><3f9f5>: Abbrev Number: 27 (DW_TAG_subprogram)
   <3f9f6>   DW_AT_specification: <0x3a163>
   <3f9fa>   DW_AT_low_pc      : 0x2c59e
   <3fa02>   DW_AT_high_pc     : 0x860
   <3fa0a>   DW_AT_frame_base  : 1 byte block: 9c      (DW_OP_call_frame_cfa)
   <3fa0c>   DW_AT_GNU_all_tail_call_sites: 1
   <3fa0c>   DW_AT_sibling     : <0x3fb21>

0x2c59e (DW_AT_low_pc) - 0x860 (DW_AT_high_pc) = 0x2cdfe(目标函数地址)。

这个计算正确吗?

Why it's offset is 0x21bf5 and not the expected 0x2cdfe?

偏移量0x21bf5是符号name.debug_str段(这里是"attach_backtraces")的偏移量(其中收集所有类型、参数、变量和函数的名称。

该偏移量与所表示符号的 完全没有关系(此处为0x2cdfe)。这些偏移量恰好彼此接近以混淆你。

What a piece do I miss?

通常,一个函数应该有 DW_AT_low_pc 属性来表示它的起始地址(并且输出描述的 attach_backtraces 例程的该属性的值将是 0x2cdfe)。

我不确定你为什么在这里缺少 low_pchigh_pc

一种可能性是 xs::attach_backtraces(xs::Ref) 例程实际上有很多实例(如果它在 header 文件中声明为 inline),并且您正在查看的实例readelf -w 输出被链接器丢弃(该函数将出现在 #included 到 header 的所有 object 文件中,但链接器将只保留该函数的一个实例).如果是这种情况,请在 readelf -w 输出中查找 another attach_backtraces,其中存在 low_pchigh_pc

在 DWARF 转储的第一个块 <3a150>(我们可以看到函数名称的偏移量 0x21bf5)中,我们还看到 DW_AT_declaration 标志,表示声明此 DIE 中的功能未完成(请参阅 DWARF 5 文档的第 2.13 节)。

要找到声明的完成,您应该找到具有 DW_AT_specification 属性的 DIE,该值是对它完成的 DIE 的引用(如在第二个块中, <3f9f5>) 并且在您的案例中应该有值 <3a150>.

注意上面提到的,我想你的第二个块不是你想要找到的,因为它引用了另一个 DIE <0x3a163>。

当你找到正确的块时,你应该使用 DW_AT_low_pc 作为你需要的参数(从进程基地址偏移到 'attach_backtraces')。

希望对您有所帮助。

此外,从我的角度来看,dwarfdump 工具显示的输出比 readelf 更好。