DWARF - 如何找到给定二进制文件中的函数的序言结尾/结尾起始地址?

时间:2014-09-18 15:38:45

标签: c assembly objdump dwarf readelf

我有一个ARM二进制文件,我需要准确找到其功能的序言结束的地址和结尾的开头。换句话说,我需要函数体的边界。例如,如果我有一个函数,其汇编类似于:

0x00000320 <+0>:    push    {r7, lr}
0x00000322 <+2>:    sub sp, #16
0x00000324 <+4>:    add r7, sp, #0
0x00000326 <+6>:    str r0, [r7, #4]
0x00000328 <+8>: (Function body starts here)
...
0x0000034c <+44>:   (Function body ends here)
0x0000034e <+46>:   mov sp, r7
0x00000350 <+48>:   pop {r7, pc}

我需要一种快速查找0x000003260x0000034e(序言结束/结语开始)或0x000003280x0000034c(函数体开始/结束)的方法像readelf或objdump。简单地反汇编它并检查代码是不行的(理想情况下我会使用脚本来解析readelf的输出或我用来获取DWARF信息的任何程序)。

根据DWARF 4标准,.debug_line部分应该包含行号信息,其中包含“prologue_end”和“epilogue_begin”,这正是我所需要的。但是,arm-linux-readelf --debug-dump=rawline,decodedline的输出并未向我提供该信息。

我正在使用gcc 4.8.2标记使用-ggdb3进行编译。

编辑:更多信息:objdump和readelf都显示我这样的事情:

Line Number Statements:
[0x00000074]  Extended opcode 2: set Address to 0x100
[0x0000007b]  Advance Line by 302 to 303
[0x0000007e]  Copy
[0x0000007f]  Special opcode 34: advance Address by 4 to 0x104 and Line by 1 to 304
[0x00000080]  Special opcode 34: advance Address by 4 to 0x108 and Line by 1 to 305
[0x00000081]  Special opcode 37: advance Address by 4 to 0x10c and Line by 4 to 309
[0x00000082]  Special opcode 34: advance Address by 4 to 0x110 and Line by 1 to 310
[0x00000083]  Special opcode 20: advance Address by 2 to 0x112 and Line by 1 to 311
[0x00000084]  Special opcode 37: advance Address by 4 to 0x116 and Line by 4 to 315
[0x00000085]  Special opcode 34: advance Address by 4 to 0x11a and Line by 1 to 316
[0x00000086]  Advance Line by -13 to 303
[0x00000088]  Special opcode 19: advance Address by 2 to 0x11c and Line by 0 to 303
[0x00000089]  Special opcode 34: advance Address by 4 to 0x120 and Line by 1 to 304
[0x0000008a]  Advance PC by 4 to 0x124
[0x0000008c]  Extended opcode 1: End of Sequence

查看binutils的dwarf.c的来源,似乎应该在行信息转储中打印类似“Set prologue_end to true”和“set epilogue_begin to true”的内容。但是,所有的操作码似乎都是特殊的而不是标准的。

2 个答案:

答案 0 :(得分:1)

这是一个非常迟到的响应,但是:如果您正在使用 LLVM,那么您可以从 DWARF 行程序状态机中获取此信息:LLV​​M 发出 DW_LNS_set_prologue_end 和 {{ 1}} 作为每个行程序条目的标志。

GCC 显然(还)不支持这些属性,因此其周围的工具(如 DW_LNS_set_epilogue_beginreadelf)很可能也不支持。但是您应该能够使用 pyelftools 解析序言和结语。

答案 1 :(得分:0)

尝试

readelf -wi

查找您正在查看的子程序的DW_AT_low_pc和DW_AT_high_pc。

DWARF规范说:

  

子程序条目可以具有DW_AT_low_pc和DW_AT_high_pc属性对或DW_AT_ranges属性,其值分别编码为子程序生成的机器指令的连续或非连续地址范围(参见第2.17节)。 p>

如果我没记错的话,DW_AT_low_pc就是序言之后的地址,DW_AT_high_pc是结尾之前的最后一个地址。

不要担心操作码是特殊的&#39;这只是意味着他们不会在编码的行号程序中使用参数来节省空间。