2017-07-31 338 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