我正在學習如何將C文件編譯爲機器碼。我知道我可以使用-S
標誌從gcc
生成程序集,但是它也會產生很多代碼,我現在不感興趣的main()
和printf()
。有沒有辦法單獨輸出單個函數的彙編?
有沒有辦法讓gcc
或clang
爲「」編譯「一個獨立的函數並輸出程序集?
即,獲得大會下面的C隔離:
int add(int a, int b) {
return a + b;
}
我正在學習如何將C文件編譯爲機器碼。我知道我可以使用-S
標誌從gcc
生成程序集,但是它也會產生很多代碼,我現在不感興趣的main()
和printf()
。有沒有辦法單獨輸出單個函數的彙編?
有沒有辦法讓gcc
或clang
爲「」編譯「一個獨立的函數並輸出程序集?
即,獲得大會下面的C隔離:
int add(int a, int b) {
return a + b;
}
有兩種方法爲特定對象文件做到這一點:
-ffunction-sections
選項gcc
指示它創建一個單獨的ELF段在每個的資源文件功能正在編制。--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
的信息是在目標文件中,但與代碼分開(它在所謂的重定位部分列出了要由鏈接器「修補」的目標文件中的位置);反彙編不能解決這個問題。
我明白了,對於其他人來說,你可以使用「gcc -ffunction-sections -c test.c」將源文件編譯成目標文件。謝謝〜 – ashleysmithgpu 2013-05-01 09:08:29
去會複製你的函數在一個temp.c
C文件,並與-c
標誌這樣編譯它,最好的辦法:gcc -c -S temp.c -o temp.s
它應該產生更緊密的彙編代碼,沒有其他干擾(除了頁眉和頁腳)。
一些IDE可以讓你設置斷點並查看該函數生成的彙編代碼。它被稱爲*反彙編窗口*。這應該做你正在尋找的東西 - 你在使用IDE嗎? – Aaron 2013-04-30 14:09:20
我寧願編譯(有優化)然後反彙編,你必須明白,編譯器會留下一些對外部地址等不完整的指令,但比使用-S更容易讀取IMO。 gcc -O2 -c hello.c -o hello.o,objdump -D hello.o – 2013-04-30 17:12:43
去這裏:http://gcc.godbolt.org/粘貼功能,選擇編譯器,非常有用。 – harold 2013-04-30 17:41:44