2013-04-30 69 views
6

我正在學習如何將C文件編譯爲機器碼。我知道我可以使用-S標誌從gcc生成程序集,但是它也會產生很多代碼,我現在不感興趣的main()printf()有沒有辦法單獨輸出單個函數的彙編?

有沒有辦法讓gccclang爲「」編譯「一個獨立的函數並輸出程序集?

即,獲得大會下面的C隔離:

int add(int a, int b) { 
    return a + b; 
} 
+0

一些IDE可以讓你設置斷點並查看該函數生成的彙編代碼。它被稱爲*反彙編窗口*。這應該做你正在尋找的東西 - 你在使用IDE嗎? – Aaron 2013-04-30 14:09:20

+0

我寧願編譯(有優化)然後反彙編,你必須明白,編譯器會留下一些對外部地址等不完整的指令,但比使用-S更容易讀取IMO。 gcc -O2 -c hello.c -o hello.o,objdump -D hello.o – 2013-04-30 17:12:43

+3

去這裏:http://gcc.godbolt.org/粘貼功能,選擇編譯器,非常有用。 – harold 2013-04-30 17:41:44

回答

7

有兩種方法爲特定對象文件做到這一點:

  1. -ffunction-sections選項gcc指示它創建一個單獨的ELF段在每個的資源文件功能正在編制。
  2. 符號表包含給定函數的段名稱,起始地址和大小;可以通過參數--start-address/--stop-address將其輸入objdump

第一個例子:

$ readelf -S t.o | grep ' .text.' 
    [ 1] .text    PROGBITS   0000000000000000 00000040 
    [ 4] .text.foo   PROGBITS   0000000000000000 00000040 
    [ 6] .text.bar   PROGBITS   0000000000000000 00000060 
    [ 9] .text.foo2  PROGBITS   0000000000000000 000000c0 
    [11] .text.munch  PROGBITS   0000000000000000 00000110 
    [14] .text.startup.mai PROGBITS   0000000000000000 00000180

這已經編有-ffunction-sections和有四大功能,foo()bar(),在我的目標文件foo2()munch()。我可以分別拆卸它們像這樣:

$ objdump -w -d --section=.text.foo t.o 

t.o:  file format elf64-x86-64 

Disassembly of section .text.foo: 

0000000000000000 <foo>: 
    0: 48 83 ec 08    sub $0x8,%rsp 
    4: 8b 3d 00 00 00 00  mov 0(%rip),%edi  # a <foo+0xa> 
    a: 31 f6     xor %esi,%esi 
    c: 31 c0     xor %eax,%eax 
    e: e8 00 00 00 00   callq 13 <foo+0x13> 
    13: 85 c0     test %eax,%eax 
    15: 75 01     jne 18 <foo+0x18> 
    17: 90      nop 
    18: 48 83 c4 08    add $0x8,%rsp 
    1c: c3      retq

另一種選擇,可以使用這樣的(nm轉儲符號表條目):

$ nm -f sysv t.o | grep bar 
bar  |0000000000000020| T | FUNC|0000000000000026|  |.text 
$ objdump -w -d --start-address=0x20 --stop-address=0x46 t.o --section=.text 

t.o:  file format elf64-x86-64 

Disassembly of section .text: 

0000000000000020 <bar>: 
    20: 48 83 ec 08    sub $0x8,%rsp 
    24: 8b 3d 00 00 00 00  mov 0(%rip),%edi  # 2a <bar+0xa> 
    2a: 31 f6     xor %esi,%esi 
    2c: 31 c0     xor %eax,%eax 
    2e: e8 00 00 00 00   callq 33 <bar+0x13> 
    33: 85 c0     test %eax,%eax 
    35: 75 01     jne 38 <bar+0x18> 
    37: 90      nop 
    38: bf 3f 00 00 00   mov $0x3f,%edi 
    3d: 48 83 c4 08    add $0x8,%rsp 
    41: e9 00 00 00 00   jmpq 46 <bar+0x26>

在這種情況下,-ffunction-sections選項具有不因此函數的起始偏移不爲零,它不在其單獨部分中(但在.text中)。

拆卸目標文件時,要小心的是......

這不正是你想要什麼,因爲,對於目標文件時,call目標(以及全局變量的地址)都沒有解決 - 在這裏您不能看到foo調用printf,因爲二進制級別的分辨率僅在鏈接時發生。儘管如此,裝配源中將有call printf。這個callq實際上是到printf的信息是在目標文件中,但與代碼分開(它在所謂的重定位部分列出了要由鏈接器「修補」的目標文件中的位置);反彙編不能解決這個問題。

+0

我明白了,對於其他人來說,你可以使用「gcc -ffunction-sections -c test.c」將源文件編譯成目標文件。謝謝〜 – ashleysmithgpu 2013-05-01 09:08:29

0

去會複製你的函數在一個temp.c C文件,並與-c標誌這樣編譯它,最好的辦法:gcc -c -S temp.c -o temp.s

它應該產生更緊密的彙編代碼,沒有其他干擾(除了頁眉和頁腳)。

相關問題