2017-07-31 336 views
2

這就是問題所在:
當我用C鏈接到我的腳本,使用LD,當我產生ELF32-I386文件在LD輸出格式,把它作爲OUTPUT_FORMAT()在ld腳本中,我沒有任何錯誤,但是如果我嘗試放入這最後一個OUTPUT_FORMAT()「二進制文件」或嘗試輸出帶.bin擴展名的文件,我會得到如下錯誤的混合:未定義參考_GLOBAL_OFFSET_TABLE_(僅當生成的二進制文件)

kernel.o: In function `k_main': 
kernel.c:(.text+0xe): undefined reference to `_GLOBAL_OFFSET_TABLE_' 
kernelutils.o: In function `k_clear_screen': 
kernelutils.c:(.text+0xc): undefined reference to `_GLOBAL_OFFSET_TABLE_' 
kernelutils.o: In function `k_clear_screen_front': 
kernelutils.c:(.text+0x56): undefined reference to `_GLOBAL_OFFSET_TABLE_' 
kernelutils.o: In function `k_printf': 
kernelutils.c:(.text+0xa0): undefined reference to `_GLOBAL_OFFSET_TABLE_' 
kernelutils.o: In function `k_sleep_3sec': 
kernelutils.c:(.text+0x152): undefined reference to `_GLOBAL_OFFSET_TABLE_' 
kernelmalloc.o:kernelmalloc.c:(.text+0xc): more undefined references to `_GLOBAL_OFFSET_TABLE_' follow 

這不僅發生在編譯特定腳本,所有嘗試使用ld鏈接的腳本或gcc(因爲這會調用ld),而是在嘗試獲取擴展名爲.bin的二進制文件時發生。
當顯示其中一個可執行文件(在上面的輸出中的kernel.o)的符號時,我看到符號_GLOBAL_OFFSET_TABLE_未定義,並且是最可怕的部分,所有在上面的錯誤輸出中返回錯誤的函數都有它們的符號消失,這是nm輸出:

[email protected]:~/Desktop/kernel/0.0.3/Archivos$ nm kernel.o 
     U _GLOBAL_OFFSET_TABLE_ 
     U k_clear_screen 
     U k_clear_screen_front 
00000000 T k_main 
     U k_malloc 
     U k_printf 
     U k_sleep_3sec 
00000000 T __x86.get_pc_thunk.bx 

我該如何解決這個問題?我將在下面保留鏈接器腳本,以確保它不是.ld文件的問題,同時包含「獲取elf」和「獲取二進制」版本。提前致謝!

Ld的腳本:
爲了得到二進制:

ENTRY(loader) 
OUTPUT_FORMAT(binary) 

SECTIONS { 
    /* The kernel will live at 3GB + 1MB in the virtual 
     address space, which will be mapped to 1MB in the 
     physical address space. */ 
    . = 0xC0100000; 

    .text : AT(ADDR(.text) - 0xC0000000) { 
     *(.text) 
     *(.rodata*) 
    } 

    .data ALIGN (0x1000) : AT(ADDR(.data) - 0xC0000000) { 
     *(.data) 
    } 

    .bss : AT(ADDR(.bss) - 0xC0000000) { 
     _sbss = .; 
     *(COMMON) 
     *(.bss) 
     _ebss = .; 
    } 
} 

要獲取ELF:

ENTRY(loader) 
OUTPUT_FORMAT(elf32-i386) 

SECTIONS { 
    /* The kernel will live at 3GB + 1MB in the virtual 
     address space, which will be mapped to 1MB in the 
     physical address space. */ 
    . = 0xC0100000; 

    .text : AT(ADDR(.text) - 0xC0000000) { 
     *(.text) 
     *(.rodata*) 
    } 

    .data ALIGN (0x1000) : AT(ADDR(.data) - 0xC0000000) { 
     *(.data) 
    } 

    .bss : AT(ADDR(.bss) - 0xC0000000) { 
     _sbss = .; 
     *(COMMON) 
     *(.bss) 
     _ebss = .; 
    } 
} 

由於喲天亞社之間都只有改變OUTPUT_FORMAT()行見。

+0

看起來像您的主機GCC環境(可能是Ubuntu 16.04+或Debian 9+之類的更新版本)正在生成與位置無關的代碼。當你用_GCC_編譯時,你可能想用'-fno-pic'編譯所有的文件。這是使用GCC交叉編譯器進行操作系統開發的一個很好的理由。你可以閱讀關於創建一個在這裏:http://wiki.osdev.org/GCC_Cross-Compiler –

+0

謝謝,我將建立交叉編譯器 – Rottenheimer2

+0

在旁註 - 爲什麼你生成一個二進制文件?我知道你以前使用的是一個多引導兼容加載器。使用二進制文件可能會導致你的問題,除非你現在正在編寫你自己的引導程序,或者你改變了你的多引導頭來支持a.out kludge。 –

回答

1

您的工具鏈可能默認爲生成與位置無關的可執行文件(PIE)。嘗試使用gcc -fno-pie編譯。

如果您出於安全原因想要保留PIE,您需要一個更復雜的鏈接器腳本,並執行初始重定位(例如動態鏈接器,但更簡單的構造也是可能的)。

+0

解決了這個問題,謝謝。 – Rottenheimer2