Debugging 确定dwarf中的内联函数地址

Debugging 确定dwarf中的内联函数地址,debugging,elf,dwarf,Debugging,Elf,Dwarf,我有一个函数的虚拟地址(指令指针),从调用中获得。我需要找出关于它的调试信息 例如,我需要有关attach\u backtraces函数的信息 nm -a Backtrace.so | grep attach_backtraces 000000000002cdfe t _ZN2xsL17attach_backtracesENS_3RefE 偏移量0x2cdfe可以通过从PC(IP)中减去.so加载的地址来确定。它与nm的输出相匹配 我从readelf-w Backtrace.so <3&

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

例如,我需要有关
attach\u 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
它的定义是:

<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>
:缩写编号:27(DW_标记_子程序)
DW_AT_规格:
DW_在_低_pc:0x2c59e
DW_在_高_pc:0x860
在帧基上的数据块:1字节块:9c(数据块操作调用帧cfa)
DW_AT_GNU_所有_tail_call_站点:1
DW_在_同级:
0x2c59e(
DW\u位于低电平pc
)-0x860(
DW\u位于高电平pc
)=0x2cdfe(目标函数地址)

这个计算正确吗

为什么它的偏移量是0x21bf5而不是预期的0x2cdfe

偏移量
0x21bf5
.debug\u str
部分(收集所有类型、参数、变量和函数的名称)中符号名称的偏移量(
“attach\u backtraces”

该偏移量与所表示符号的值绝对没有关系(
0x2cdfe
)。这些偏移正好彼此接近,让你感到困惑

我错过了什么

通常,函数应具有表示其起始地址的
DW\u AT\u low\u pc
属性(输出描述的
attach\u backtraces
例程的该属性值应为
0x2cdfe

我不知道您为什么在这里缺少
low\u pc
high\u pc


一种可能性是,实际上有许多
xs::attach_backtraces(xs::Ref)
例程的实例(如果它在头文件中声明为
inline
),并且链接器丢弃了您在
readelf-w
输出中查看的实例(该函数将出现在包含该头的所有对象文件中,但链接器仅保留该函数的一个实例)。如果是这种情况,请在
readelf-w
输出中查找另一个
attach_backtraces
,并显示
low_pc
high_pc

在矮人转储的第一个块中(我们可以看到函数名的偏移量,0x21bf5)我们还可以看到DW_AT_声明标志,它表明函数的声明没有在这个骰子中完成(参见DWARF 5文档的第2.13节)

要查找声明的完成情况,您应该查找具有DW_AT_specification属性的DIE,该值是对它完成的DIE的引用(如在第二个块中),并且应该在case值中包含该值

注意上面提到的,我想你的第二块不是你想要找到的,因为它引用了另一个模具

当找到正确的块时,应该使用DW_AT_low_pc作为所需的参数(从进程基址到“附加回溯”的偏移量)

希望这有帮助

另外,在我看来,dwarfdump工具显示出比readelf更好的输出

<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>