GCC静态链接和分离装载机

时间:2014-10-22 02:24:25

标签: gcc static linker libc

我试图了解静态链接的过程,加载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,但我遇到了同样的问题。

我做错了什么?

2 个答案:

答案 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.ocrti.ocrtbeginT.ocrtend.ocrtn.o
  • 它链接到图书馆:libgcc.alibgcc_eh.alibc.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.ocrtend.olibgcc.a,因为它没有使用它们。

答案 1 :(得分:0)

看看this,strace完成这项工作(告诉你秘密),但你很快就会意识到它有很多选择......你需要把几个东西连在一起(来自GNU C) lib)获取可执行文件,而不仅仅是你的对象...你可以添加grep' exec'最终使它更清洁。

呃,你也需要这样做:

as obj.s -o obj.o

使用GNU汇编程序将.s转换为.o,然后与ld链接。