这就是问题所在:
当我用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()行见。
看起来像您的主机GCC环境(可能是Ubuntu 16.04+或Debian 9+之类的更新版本)正在生成与位置无关的代码。当你用_GCC_编译时,你可能想用'-fno-pic'编译所有的文件。这是使用GCC交叉编译器进行操作系统开发的一个很好的理由。你可以阅读关于创建一个在这里:http://wiki.osdev.org/GCC_Cross-Compiler –
谢谢,我将建立交叉编译器 – Rottenheimer2
在旁注 - 为什么你生成一个二进制文件?我知道你以前使用的是一个多引导兼容加载器。使用二进制文件可能会导致你的问题,除非你现在正在编写你自己的引导程序,或者你改变了你的多引导头来支持a.out kludge。 –