2014-03-31 125 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'