未定义对“ __GLOBAL_OFFSET_TABLE”的引用

时间:2020-02-24 16:40:47

标签: c gcc

我在CFLAGS中添加了-fno-pie,但是它仍然显示此错误:

ld -melf_i386 -T linker.ld -o kernel.bin start.o kernel.o console.o utils.o
kernel.o: In function `_main':
kernel.C:(.text+0x16): undefined reference to `__GLOBAL_OFFSET_TABLE_'
makefile:30: recipe for target 'kernel.bin' failed
make: *** [kernel.bin] Error 1

make文件如下所示:

GCC_OPTIONS = -m32 -fno-pie -nostdlib -fno-builtin -nostartfiles -nodefaultlibs -fno-exceptions -fno-rtti -fno-stack-protector -fleading-underscore -fno-asynchronous-unwind-tables

all: kernel.bin

clean:
    rm -f *.o *.bin

# ==== KERNEL ENTRY POINT ====

start.o: start.asm
    nasm -f aout -o start.o start.asm

# ==== UTILITIES ====

utils.o: utils.H utils.C
    gcc $(GCC_OPTIONS) -c -o utils.o utils.C

# ==== DEVICES ====

console.o: console.H console.C
    gcc $(GCC_OPTIONS) -c -o console.o console.C

# ==== KERNEL MAIN FILE ====

kernel.o: kernel.C
    gcc $(GCC_OPTIONS) -c -o kernel.o kernel.C


kernel.bin: start.o kernel.o console.o utils.o linker.ld
    ld -melf_i386 -T linker.ld -o kernel.bin start.o kernel.o console.o utils.o

我可以为这个问题寻求帮助吗?

谢谢。

1 个答案:

答案 0 :(得分:0)

让我震惊的第一件事是“为什么要对.c文件使用.C(大写)扩展名,但保留给C ++使用?”。 所以我做了一个测试:

# with `-fno-rtti'
$ export CFLAGS1="-m32 -fno-pie -nostdlib -fno-builtin -nostartfiles -nodefaultlibs -fno-exceptions -fno-rtti -fno-stack-protector -fleading-underscore -fno-asynchronous-unwind-tables"
# without `-fno-rtti'
$ export CFLAGS2="-m32 -fno-pie -nostdlib -fno-builtin -nostartfiles -nodefaultlibs -fno-exceptions  -fno-stack-protector -fleading-underscore -fno-asynchronous-unwind-tables"
$ mv kernel.C kernel1.C
$ cp kernel.C kernel2.c
$ gcc $CFLAGS1 -c -o kernel1.C.o kernel1.C

$ gcc $CFLAGS1 -c -o kernel2.c.o kernel2.c
cc1: warning: command line option '-fno-rtti' is valid for C++/ObjC++ but not for C
$ gcc $CFLAGS2 -c -o kernel2.c.o kernel2.c

因此,我敢打赌,如果您将扩展名.C改成.c并将.H改成.h的首字母大写,将会得到更好的结果。 GCC在这方面很挑剔。如果要C代码使用 gcc .c扩展名,如果要C ++使用 g ++ .C.cc或{{ 1}}或.cpp


我还认为您应该使用.cxx而不是gcc作为链接命令。 Ld通常是“愚蠢的”,ld知道的更好。


PS。让我知道哪一个是/不正确的。如果有误,我将删除答案,以免混淆观众。