如何使用objdump反汇编一个函数?

MvG*_*MvG 71 elf debug-symbols objdump disassembly dwarf

我的系统上安装了二进制文件,并希望查看给定函数的反汇编.优选使用objdump,但其他解决方案也是可以接受的.

这些问题我已经了解到,如果我只知道边界地址,我可能能够反汇编部分代码.从这个答案我已经学会了如何将我的拆分调试符号转换回单个文件.

但即使在单个文件上运行,甚至反汇编所有代码(即没有启动或停止地址,但只是简单的-d参数objdump),我仍然没有在任何地方看到该符号.这是有道理的,因为有问题的函数是静态的,所以它不会被导出.然而,valgrind将报告函数名称,因此它必须存储在某处.

查看调试部分的详细信息,我找到了本.debug_str节中提到的名称,但我不知道可以将其转换为地址范围的工具.

Tom*_*mey 68

我建议使用gdb作为最简单的方法.你甚至可以做一个单行,如:

gdb -batch -ex 'file /bin/ls' -ex 'disassemble main'
Run Code Online (Sandbox Code Playgroud)

  • +1无证件功能!`-ex'命令'`不在[`man gdb`]中(http://linux.die.net/man/1/gdb)!? 但事实上列在[gdb docs](http://sourceware.org/gdb/current/onlinedocs/gdb/gdb-man.html#gdb-man)中.另外对于其他人来说,像`/ bin/ls`这样的东西可能会被剥离,所以如果那个确切的命令什么也没显示,那么试试另一个对象!也可以将文件/对象指定为裸字参数; 例如,``gdb -batch -ex'反汇编主'/ bin/ls` (4认同)
  • `gdb/bin/ls -batch -ex'反汇编主'也适用 (4认同)
  • 手册页不是确定的.很长一段时间它没有真正维护,但现在我认为它是从主要文档生成的.此外,"gdb --help"现在也更加完整. (3认同)
  • 如果您使用 `column -ts$'\t'` 来过滤 GDB 输出,您将很好地对齐原始字节和源列。此外,在其他 `-ex` 之前的 `-ex 'set disassembly-flavor intel'` 将导致 Intel 汇编语法。 (2认同)

Cir*_*四事件 18

gdb disassemble/rs也显示源和原始字节

使用这种格式,它非常接近objdump -S输出:

gdb -batch -ex "disassemble/rs $FUNCTION" "$EXECUTABLE"
Run Code Online (Sandbox Code Playgroud)

main.c中

#include <assert.h>

int myfunc(int i) {
    i = i + 2;
    i = i * 2;
    return i;
}

int main(void) {
    assert(myfunc(1) == 6);
    assert(myfunc(2) == 8);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

编译和反汇编

gcc -O0 -ggdb3 -std=c99 -Wall -Wextra -pedantic -o main.out main.c
gdb -batch -ex "disassemble/rs myfunc" main.out
Run Code Online (Sandbox Code Playgroud)

拆卸:

Dump of assembler code for function myfunc:
main.c:
3       int myfunc(int i) {
   0x0000000000001135 <+0>:     55      push   %rbp
   0x0000000000001136 <+1>:     48 89 e5        mov    %rsp,%rbp
   0x0000000000001139 <+4>:     89 7d fc        mov    %edi,-0x4(%rbp)

4           i = i + 2;
   0x000000000000113c <+7>:     83 45 fc 02     addl   $0x2,-0x4(%rbp)

5           i = i * 2;
   0x0000000000001140 <+11>:    d1 65 fc        shll   -0x4(%rbp)

6           return i;
   0x0000000000001143 <+14>:    8b 45 fc        mov    -0x4(%rbp),%eax

7       }
   0x0000000000001146 <+17>:    5d      pop    %rbp
   0x0000000000001147 <+18>:    c3      retq   
End of assembler dump.
Run Code Online (Sandbox Code Playgroud)

在Ubuntu 16.04,GDB 7.11.1上测试.

objdump + awk变通办法

打印如下所述的段落:https://unix.stackexchange.com/questions/82944/how-to-grep-for-text-in-a-file-and-display-the-paragraph-that-has-the -文本

objdump -d main.out | awk -v RS= '/^[[:xdigit:]]+ <FUNCTION>/'
Run Code Online (Sandbox Code Playgroud)

例如:

objdump -d main.out | awk -v RS= '/^[[:xdigit:]]+ <myfunc>/'
Run Code Online (Sandbox Code Playgroud)

只给出:

0000000000001135 <myfunc>:
    1135:   55                      push   %rbp
    1136:   48 89 e5                mov    %rsp,%rbp
    1139:   89 7d fc                mov    %edi,-0x4(%rbp)
    113c:   83 45 fc 02             addl   $0x2,-0x4(%rbp)
    1140:   d1 65 fc                shll   -0x4(%rbp)
    1143:   8b 45 fc                mov    -0x4(%rbp),%eax
    1146:   5d                      pop    %rbp
    1147:   c3                      retq   
Run Code Online (Sandbox Code Playgroud)

在使用时-S,我认为没有防止故障的方式,因为代码注释可能包含任何可能的顺序......但以下几乎一直在起作用:

objdump -S main.out | awk '/^[[:xdigit:]]+ <FUNCTION>:$/{flag=1;next}/^[[:xdigit:]]+ <.*>:$/{flag=0}flag'
Run Code Online (Sandbox Code Playgroud)

改编自:如何选择两个标记图案之间的线条,这些线条可能会出现awk/sed多次

邮件列表回复

邮件列表上有一个2010线程,表示不可能:https://sourceware.org/ml/binutils/2010-04/msg00445.html

除了gdbTom提出的解决方法之外,他们还评论了另一个(更糟糕的)编译方法,-ffunction-section每个部分放置一个函数然后转储该部分.

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


abu*_*bua 11

使用Objdump拆卸一个单一功能

我有两个解决方案:

1.基于命令行

这种方法效果很好,也很短.我用objdump的-d选项和的awk.反汇编输出看起来像

000000000000068a <main>:
68a:    55                      push   %rbp
68b:    48 89 e5                mov    %rsp,%rbp
68e:    48 83 ec 20             sub    $0x20,%rsp
Run Code Online (Sandbox Code Playgroud)

部分功能由一个空行分隔.因此,将FS(Field Seperator)更改为换行符并将RS(Record Seperator)更改为两行换行符,可以轻松搜索推荐的函数,因为它只是在$ 1字段内找到!

objdump -d name_of_your_obj_file | awk -F"\n" -v RS="\n\n" '$1 ~ /main/'
Run Code Online (Sandbox Code Playgroud)

当然,您可以将main替换为您想要输出的任何函数.

2. Bash脚本

我已经为这个问题写了一个小的bash脚本.只需将其复制并保存为例如dasm文件即可.

#!/bin/bash
# Author: abu
# Description: puts disassembled objectfile to std-out

if [ $# = 2 ]; then
        sstrg="^[[:xdigit:]]{2,}+.*<$2>:$"
        objdump -d $1 | awk -F"\n" -v RS="\n\n" '$1 ~ /'"$sstrg"'/'
elif [ $# = 1 ]; then
        objdump -d $1 | awk -F"\n" -v RS="\n\n" '{ print $1 }'
else
    echo "You have to add argument(s)"
    echo "Usage:   "$0 " arg1 arg2"  
    echo "Description: print disassembled label to std-out"
    echo "             arg1: name of object file"
    echo "             arg2: name of function to be disassembled"
    echo "         "$0 " arg1    ... print labels and their rel. addresses" 
fi
Run Code Online (Sandbox Code Playgroud)

更改x-access并使用eg调用它:

chmod +x dasm
./dasm test main
Run Code Online (Sandbox Code Playgroud)

这比使用脚本调用gdb 快得多.除了使用objdump的方式不会将库加载到内存中,因此更安全!


Vitaly Fadeev为这个脚本编写了自动完成功能,这是一个很好的功能,可以加快打字速度.

脚本可以在这里找到.


Léo*_*Lam 11

如果你有一个最新的 binutils (2.32+),这很简单。

传递--disassemble=SYMBOL给 objdump 将仅反汇编指定的函数。无需传递起始地址和结束地址。

LLVM objdump 也有一个类似的选项 ( --disassemble-symbols)。


小智 5

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

objdump -d filename | sed '/<functionName>:/,/^$/!d'
Run Code Online (Sandbox Code Playgroud)