对_GLOBAL_OFFSET_TABLE_的未定义引用(仅在生成二进制文件时)



这就是问题所在
:当我使用 ld 在 C 中链接我的脚本时,当我在 ld 中生成 elf32-i386 文件作为输出格式时,将其作为 OUTPUT_FORMAT(( 放入 ld 脚本中,我没有任何错误,但是如果我尝试输入最后一个 OUTPUT_FORMAT(( "二进制"或尝试输出扩展名为 .bin 的文件, 我收到混合错误,例如:

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输出:

cristian@mymethodman:~/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(( 行。

您的工具链可能默认为生成与位置无关的可执行文件 (PIE(。 尝试使用gcc -fno-pie进行编译。

如果出于安全原因想要保留 PIE,则需要更复杂的链接器脚本和执行初始重定位的内容(例如动态链接器,但也可以使用更简单的构造(。

相关内容

最新更新