【问题标题】:GCC Static Linking And Separate LoaderGCC 静态链接和单独的加载器
【发布时间】:2014-10-22 02:24:25
【问题描述】:

我正在尝试了解静态链接、加载 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 但我有同样的问题。

我做错了什么?

【问题讨论】:

  • 我用 gcc-4.4.7 运行gcc -static -std=gnu99 -Wall -Wno-unused -g test.c -c && gcc test.o -o test 没有问题
  • 这可以正常工作。但我特别关注将它与加载器(ld)一起使用
  • 然后你会链接到-lc,添加其他员工,如crt1.o、crtn.o、crtbegin.o、crtend.o等,它们与你的gcc相伴。你可以运行gcc -v test.o 来检查gcc 是如何完成这项工作的。
  • 我设法做到了这一点: gcc -static test.c -lc -static-libgcc -c ; ld test.o -o test -lc --entry main --section-start=.txt=0x30000 --section-start=.bss=0x400000 --section-start=.data=0x500000 但是现在我得到了./test : 找不到二进制文件。它说当我将文件指定为静态时,该文件是动态链接的。关于复制 ld 输出,它依赖于 /tmp/...o 中的目标文件,当我重新运行 ld 命令时,该文件不存在 这是为什么我不重用 -v 的输出
  • 避免使用test 作为可执行文件名,因为它是一个内置的shell。将-v 添加到您的gcc 命令以了解正在发生的事情,例如编译gcc -v -static -std=gnu99 -Wall -Wno-unused -g test.c -o mytest

标签: gcc static linker libc


【解决方案1】:

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

您必须替换临时对象文件。就我而言,我用test.o 替换了/tmp/ccoR98Xr.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,因为没有它们也能正常工作。

【讨论】:

    【解决方案2】:

    看看this,strace 可以完成这项工作(向您展示秘密),但您很快就会意识到其中有很多选项...您需要将一些东西链接在一起(来自 GNU C lib)获取您的可执行文件,而不仅仅是您的对象...您可以在最后添加 grep 'exec' 以使其更清洁。

    呃,你也需要这样做:

    as obj.s -o obj.o
    

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

    【讨论】:

      猜你喜欢
      • 2021-09-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多