2016-09-12 33 views
3

我想要遵循this教程創建一個二進制文件,但鏈接程序似乎在程序集的末尾附加額外的說明。我認爲這是操作系統的拆卸過程。說明追加到程序集尾


教程試圖編譯Linux上的裸露的骨頭32位C程序:使用這些命令

int main() { 
} 

gcc -c test.c 
ld -o test -Ttext 0x0 -e main test.o 
objcopy -R .note -R .comment -S -O binary test test.bin 
ndisasm -b 32 test.bin 

我運行64位Linux,和因此將彙編步驟修改爲如下:

gcc -m32 -c test.c 
ld -m elf_i386 -o test -Ttext 0x0 -e main test.o 
objcopy -R .note -R .comment -S -O binary test test.bin 
ndisasm -b 32 test.bin 

預期的輸出是:

00000000 55   push ebp 
00000001 89E5   mov ebp,esp 
00000003 C9   leave 
00000004 C3   ret 

我的輸出如下:

;; START expected output 
00000000 55    push bp 
00000001 89E5    mov bp,sp 
00000003 5D    pop bp 
00000004 C3    ret 
;; END expected output 
00000005 0000    add [eax],al 
00000007 001400   add [eax+eax],dl 
0000000A 0000    add [eax],al 
0000000C 0000    add [eax],al 
0000000E 0000    add [eax],al 
00000010 017A52   add [edx+0x52],edi 
00000013 0001    add [ecx],al 
00000015 7C08    jl 0x1f 
00000017 011B    add [ebx],ebx 
00000019 0C04    or al,0x4 
0000001B 0488    add al,0x88 
0000001D 0100    add [eax],eax 
0000001F 001C00   add [eax+eax],bl 
00000022 0000    add [eax],al 
00000024 1C00    sbb al,0x0 
00000026 0000    add [eax],al 
00000028 D8FF    fdivr st7 
0000002A FF    db 0xff 
0000002B FF0500000000  inc dword [dword 0x0] 
00000031 41    inc ecx 
00000032 0E    push cs 
00000033 088502420D05  or [ebp+0x50d4202],al 
00000039 41    inc ecx 
0000003A C50C04   lds ecx,[esp+eax] 
0000003D 0400    add al,0x0 
0000003F 00    db 0x00 

什麼是附加說明的目的,我怎麼可以從目標文件帶他們和二進制?

編輯:

  • 錯字在objcopy ARGS(commet - >註釋)。更新了反彙編輸出。
+0

@ IgnacioVazquez-Abrams我試圖找到關於'.comment'部分的信息,但它並沒有太多提高。這是什麼,爲什麼你認爲這是該節? – sdsmith

+1

如果你用'objdump -x test.o'來轉儲出所有的elf標題/部分,你可能會發現你有'.eh_frame'部分。既然你不排除它佔用文件中的空間。如果你不打算使用異常處理,那麼把它添加到你的GCC命令行'-fno-exceptions -fno-asynchronous-unwind-tables'中。因此'gcc -m32 -c test.c -fno-exceptions -fno-asynchronous-unwind-tables'應該可能解決你的問題。 –

+1

它們實際上不是指令,它們是異常幀數據,它們在轉換爲二進制平面文件時直接放在代碼後面。 「ndisasm」碰巧正在將數據解碼爲指令,因爲它不知道差異。 –

回答

3

通常,當您在輸出文件中看到其他數據/指令時,問題的根源可能是出現在您的預期代碼之後的部分。解決這個問題的方法是查詢可執行文件以查看它定義的部分。可以只查詢-x參數爲OBJDUMP的部分。在最現代的版本

objdump -x test 

應該產生類似的輸出(不準確),這一GCC使用默認參數:使用此命令

test:  file format elf32-i386 
test 
architecture: i386, flags 0x00000112: 
EXEC_P, HAS_SYMS, D_PAGED 
start address 0x00000000 

Program Header: 
    LOAD off 0x00001000 vaddr 0x00000000 paddr 0x00000000 align 2**12 
     filesz 0x00000040 memsz 0x00000040 flags r-x 
    STACK off 0x00000000 vaddr 0x00000000 paddr 0x00000000 align 2**4 
     filesz 0x00000000 memsz 0x00000000 flags rw- 

Sections: 
Idx Name   Size  VMA  LMA  File off Algn 
    0 .text   00000005 00000000 00000000 00001000 2**0 
        CONTENTS, ALLOC, LOAD, READONLY, CODE 
    1 .eh_frame  00000038 00000008 00000008 00001008 2**2 
        CONTENTS, ALLOC, LOAD, READONLY, DATA 
    2 .comment  0000001d 00000000 00000000 00001040 2**0 
        CONTENTS, READONLY 
SYMBOL TABLE: 
00000000 l d .text 00000000 .text 
00000008 l d .eh_frame  00000000 .eh_frame 
00000000 l d .comment  00000000 .comment 
00000000 l df *ABS* 00000000 test.c 
00001040 g  .eh_frame  00000000 __bss_start 
00000000 g  F .text 00000005 main 
00001040 g  .eh_frame  00000000 _edata 
00001040 g  .eh_frame  00000000 _end 

每個人都應該首先尋找意外部分。在輸出到文件test.bin之前,您的OBJCOPY命令使用-R刪除ELF對象中的部分。你們這樣做:

objcopy -R .note -R .comment -S -O binary test test.bin 

如果我們排除.note.comment部分明顯的一個留在上面的objdump的輸出.eh_frame.eh_frame被放入您的檔案test.bin之後.text部分。這包含異常展開信息。這不是實際的指示。 NDISASM將非代碼轉儲爲指令,因爲二進制文件不區分代碼和數據。 NDISASM盲目地將所有數據轉換爲指令。

有幾種解決方法。您可以像其他兩個一樣排除.eh_frame部分。你可以使用:

objcopy -R .note -R .comment -R .eh_frame -S -O binary test test.bin 

你也可以告訴GCC不產生代碼異步異常展開表。這可以通過GCC選項來完成:

gcc -m32 -c test.c -fno-asynchronous-unwind-tables 

這從我的意見有些不同,我建議禁用所有異常。您只需要禁用異步展開表來取消.eh_frame部分。這部分的用處(或缺乏)在Stackoverflow answer中討論。該名男子頁(man gcc)爲GCC討論的選項-fasynchronous-unwind-tables

-fasynchronous-unwind-tables 
     Generate unwind table in DWARF 2 format, if supported by target machine. The table is exact at each 
     instruction boundary, so it can be used for stack unwinding from asynchronous events (such as debugger or 
     garbage collector). 

,這是大多數GCC這幫天的默認值。使用-fno-asynchronous-unwind-tables可關閉此功能。


tutorial您鏈接到2000年GCC及其選項(通過發行使用的默認值)製作已經改變了多年來。可能在創建該教程時,異步展開表不存在。這可以解釋爲什麼你觀察到的輸出與教程不同。

+1

你是對的教程。我不得不做許多標記修改,以表現出與示例中顯示的相同的一般行爲。我知道'__start'部分,但是在遇到本教程之前並未注意到注入到目標文件中的所有其他部分。 – sdsmith