2014-03-31 509 views
46

我已经在我的系统上安装了一个二进制文件,并希望查看给定函数的反汇编。最好使用objdump,但其他解决方案也是可以接受的。使用objdump反汇编一个函数

From this questions我知道如果我只知道边界地址,我可能会反汇编部分代码。从this answer我学会了如何将我的拆分调试符号恢复为单个文件。但即使在单个文件上运行,甚至拆卸所有代码(即没有开始或停止地址,但参数为objdump),我仍然没有在任何地方看到该符号。这是有意义的,因为所讨论的函数是静态的,所以它不会被导出。尽管如此,valgrind将报告函数名称,所以它必须存储在某个地方。

看看调试部分的细节,我发现在.debug_str部分提到的名称,但我不知道一个工具,它可以把它变成一个地址范围。

+0

A小调侧面说明:如果一个函数标记为'static',它可能会被编译器内联到其呼叫站点。这可能意味着实际上可能没有任何功能可以进行反汇编。如果您可以找到其他功能的符号,但找不到您正在查找的功能,这是一个强烈暗示该功能已被内联的提示。 Valgrind可能仍然引用原始的预先内置函数,因为ELF文件调试信息存储每个单独指令源自的位置,即使指令移动到别处。 – davidg

+0

@davidg:是的,但是由于汤姆在这种情况下的回答,似乎并非如此。尽管如此,你是否知道一种方法,例如用每条指令来自哪里的信息来注释汇编代码? – MvG

+1

好听! 'addr2line'将接受来自'stdin'的PC/IP并打印出相应的源代码行。同样,'objdump -l'会混合objdump和源代码行;尽管对于高度优化的内联代码,两个程序的结果并不总是特别有用。 – davidg

回答

47

我会建议使用gdb作为最简单的方法。你甚至可以做到这一点作为一个班轮,如:

gdb -batch -ex 'file /bin/ls' -ex 'disassemble main' 
+2

+1无证件功能! '-ex'command''不在['man gdb'](http://linux.die.net/man/1/gdb)!但实际上列在[gdb文档](http://sourceware.org/gdb/current/onlinedocs/gdb/gdb-man.html#gdb-man)中。对于其他人,像'/ bin/ls'这样的东西可能会被剥离,所以如果这个确切的命令什么都不显示,请尝试另一个对象!也可以将文件/对象指定为裸号参数;例如'gdb -batch -ex'反汇编main'/ bin/ls' –

+1

手册页不是确定性的。很长一段时间它没有真正维护,但现在我认为它是从主要文档生成的。此外,“gdb --help”现在也更完整。 –

+2

gdb/bin/ls -batch -ex'disassemble main''也可以工作 – stefanct

7

awk的变通方法

打印的段落在提到:https://unix.stackexchange.com/questions/82944/how-to-grep-for-text-in-a-file-and-display-the-paragraph-that-has-the-text

objdump -d a.out | awk -v RS= '/^[[:xdigit:]].*<FUNCTION>/' 

当使用-S,我不我认为这是一种不可靠的方法,因为代码注释可能包含任何可能的序列......但以下几乎所有的时间都可以使用:

改编自:How to select lines between two marker patterns which may occur multiple times with awk/sed

邮件列表回复

有一个2010线的邮件列表,它说,它是不可能的:https://sourceware.org/ml/binutils/2010-04/msg00445.html

除了由汤姆提议的gdb解决方法,他们还评论了另一个(更糟糕的)编译-ffunction-section的解决方法,该解决方案为每个部分添加一个函数,然后转储该部分。

Nicolas Clifton给了它一个WONTFIX https://sourceware.org/ml/binutils/2015-07/msg00004.html,可能是因为GDB的解决方法覆盖了该用例。

+0

gdb方法可以在共享库和对象文件上正常工作。 –

+0

@TomTromey谢谢你指出,修正。 –

3

这个作品就像gdb的解决方案(因为它向零转变的偏移量),除了它不是laggy(获取5ms左右做我的电脑上工作,而gdb的解决方案大约需要150毫秒):

objdump_func:

#!/bin/sh 
# $1 -- function name; rest -- object files 
fn=$1; shift 1 
exec objdump -d "[email protected]" | 
awk " /^[[:xdigit:]].*<$fn>/,/^\$/ { print \$0 }" | 
awk -F: -F' ' 'NR==1 { offset=strtonum("0x"$1); print $0; } 
       NR!=1 { split($0,a,":"); rhs=a[2]; n=strtonum("0x"$1); $1=sprintf("%x", n-offset); printf "%4s:%s\n", $1,rhs }' 
+0

我现在无法测试,但我期待着我能够了解到这一点。你能否详细介绍一下“向零偏移”方面?我没有在gdb的答案中看到这一点,我希望更多地了解实际发生的情况以及原因。 – MvG

+0

它基本上使得它看起来好像你的目标函数(这是第一个'awk'所做的)是目标文件中唯一的函数,也就是说,即使函数开始于'0x2d',第二个awk将它转向'0x00'(通过从每条指令的地址中减去'0x2d'),这很有用,因为汇编代码通常会引用相对于函数开始的引用,并且如果函数从0开始,必须做你脑海中的减法。 awk代码可能会更好,但至少它可以完成这项工作,并且效率很高。 – PSkocik

1

为了简化AWK的使用从objdump的输出相对于其他答案解析:

objdump -d filename | sed '/<functionName>:/,/^$/!d'