我试图了解静态链接的过程,加载GCC:
我有以下玩具计划
#include "stdio.h"
int main() {
fprintf(stdout, "Hello World \n");
return 0 ;
}
我可以编译它并按如下方式运行文件:
gcc -static -std=gnu99 -Wall -Wno-unused -g test.c -o test;
但是一旦我尝试将编译和链接过程分开如下:
gcc -static -std=gnu99 -Wall -Wno-unused -g test.c -c;
ld -o test -T link.lds test.o
其中link.lds是
SECTIONS
{
. = 0x10000;
.text : { *(.text) }
. = 0x8000000;
.data : { *(.data) }
.bss : { *(.bss) }
}
我收到错误"对stdouttest.o的未定义引用:在函数`main':
test.c:(.text+0x7): undefined reference to `stdout'
test.c:(.text+0x1e): undefined reference to `fwrite'
如果我尝试将标志-lc添加到ld,它会告诉我它没有找到。我尝试用-lc运行gcc 和/或-static-libgcc,但我遇到了同样的问题。
我做错了什么?
答案 0 :(得分:2)
做
gcc -v -static -std=gnu99 -Wall -Wno-unused -g test.c
并查找collect2
代码。
就我而言,它是
collect2 --sysroot = / --build-id -m elf_x86_64 --hash-style = gnu --as-needed -static -z relro -o test / usr / lib / gcc / x86_64-linux-gnu / 4.8 /../../../ x86_64-linux-gnu / crt1.o /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/ crti.o /usr/lib/gcc/x86_64-linux-gnu/4.8/crtbeginT.o -L / usr / lib / gcc / x86_64-linux-gnu / 4.8 -L / usr / lib / gcc / x86_64-linux- gnu / 4.8 /../../../ x86_64-linux-gnu -L / usr / lib / gcc / x86_64-linux-gnu / 4.8 /../../../../ lib -L / lib / x86_64-linux-gnu -L / lib /../ lib -L / usr / lib / x86_64-linux-gnu -L / usr / lib /../ lib -L / usr / lib / gcc / x86_64 -linux-gnu / 4.8 /../../ ../tmp/ccoR98Xr.o --start-group -lgcc -lgcc_eh -lc --end-group / usr / lib / gcc / x86_64-linux-gnu / 4.8 / crtend.o /usr/lib/gcc/x86_64-linux-gnu/4.8 /../../../ x86_64-linux-gnu / crtn.o
您必须替换临时对象文件。就我而言,我将/tmp/ccoR98Xr.o
替换为test.o
。然后做
gcc -c -std=gnu99 -Wall -Wno-unused -g test.c
ld --sysroot = / --build-id -m elf_x86_64 --hash-style = gnu --as-needed -static -z relro -o test / usr / lib / gcc / x86_64-linux-gnu / 4.8 /../../../ x86_64-linux-gnu / crt1.o /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/ crti.o /usr/lib/gcc/x86_64-linux-gnu/4.8/crtbeginT.o -L / usr / lib / gcc / x86_64-linux-gnu / 4.8 -L / usr / lib / gcc / x86_64-linux- gnu / 4.8 /../../../ x86_64-linux-gnu -L / usr / lib / gcc / x86_64-linux-gnu / 4.8 /../../../../ lib -L / lib / x86_64-linux-gnu -L / lib /../ lib -L / usr / lib / x86_64-linux-gnu -L / usr / lib /../ lib -L / usr / lib / gcc / x86_64 -linux-gnu / 4.8 /../../ .. test.o --start-group -lgcc -lgcc_eh -lc --end-group /usr/lib/gcc/x86_64-linux-gnu/4.8/crtend .o /usr/lib/gcc/x86_64-linux-gnu/4.8 /../../../ x86_64-linux-gnu / crtn.o
crt1.o
,crti.o
,crtbeginT.o
,crtend.o
和crtn.o
。 libgcc.a
,libgcc_eh.a
和libc.a
。 --start-group -lgcc -lgcc_eh -lc --end-group
替换为-lgcc -lc -lgcc_eh -lc
。 知道了这一点,我们可以简单地这样做
ln -s `gcc -print-file-name=crt1.o`
ln -s `gcc -print-file-name=crti.o`
ln -s `gcc -print-file-name=crtn.o`
ln -s `gcc -print-file-name=libgcc_eh.a`
ln -s `gcc -print-file-name=libc.a`
gcc -c -std=gnu99 -Wall -Wno-unused -g test.c
ld -m elf_x86_64 -o test crt1.o crti.o test.o libc.a libgcc_eh.a libc.a crtn.o
我没有使用crtbeginT.o
,crtend.o
和libgcc.a
,因为它没有使用它们。
答案 1 :(得分:0)
看看this,strace完成这项工作(告诉你秘密),但你很快就会意识到它有很多选择......你需要把几个东西连在一起(来自GNU C) lib)获取可执行文件,而不仅仅是你的对象...你可以添加grep' exec'最终使它更清洁。
呃,你也需要这样做:
as obj.s -o obj.o
使用GNU汇编程序将.s转换为.o,然后与ld链接。