【问题标题】:gnu ld fail to link .c programgnu ld 无法链接 .c 程序
【发布时间】:2018-08-12 08:00:27
【问题描述】:

为了理解编译过程,我试图得到一个简单程序的可执行文件,分别编译和链接。

#include<stdio.h>

int main(void)
{
  printf("Hello! This is a test prgoram.\n");
  return 0;
}

gcc -o hello hello.c

一切正常,并生成了具有预期输出的所需可执行文件。

你好

制作:

linux-vdso.so.1 =>  (0x00007ffce53ee000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f923498b000)
/lib64/ld-linux-x86-64.so.2 (0x00007f9234d55000)

然后分别尝试每个步骤:

cpp -v hello.c > hello.i

为了得到预处理后的输出,那么,

gcc -S hello.i

然后,要获得汇编代码,

as -o hello.o hello.s

获取目标代码。直到这一步看起来一切正常,但是,

ld --verbose -o hello hello.o -lc -l:ld-linux-x86-64.so.2

我明白了:

attempt to open hello.o succeeded
hello.o
attempt to open //usr/local/lib/x86_64-linux-gnu/libc.so failed
attempt to open //usr/local/lib/x86_64-linux-gnu/libc.a failed
attempt to open //lib/x86_64-linux-gnu/libc.so failed
attempt to open //lib/x86_64-linux-gnu/libc.a failed
attempt to open //usr/lib/x86_64-linux-gnu/libc.so succeeded
opened script file //usr/lib/x86_64-linux-gnu/libc.so
opened script file //usr/lib/x86_64-linux-gnu/libc.so
attempt to open /lib/x86_64-linux-gnu/libc.so.6 succeeded
/lib/x86_64-linux-gnu/libc.so.6
attempt to open /usr/lib/x86_64-linux-gnu/libc_nonshared.a succeeded
attempt to open /lib/x86_64-linux-gnu/ld-linux-x86-64.so.2 succeeded
/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
attempt to open //usr/local/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2 failed
attempt to open //usr/local/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2 failed
attempt to open //lib/x86_64-linux-gnu/ld-linux-x86-64.so.2 succeeded
-l:ld-linux-x86-64.so.2 (//lib/x86_64-linux-gnu/ld-linux-x86-64.so.2)
ld: warning: cannot find entry symbol _start; defaulting to 0000000000400280

显然它成功打开了库和目标文件,但未能将它们全部链接。

版本:

gcc 版本 5.4.0 20160609 (Ubuntu 5.4.0-6ubuntu1~16.04.9) GNU ld(Ubuntu 的 GNU Binutils)2.26.1

我是否在此架构中遗漏了某些东西(库、选项等)?

问候。

【问题讨论】:

  • 试试gcc -v hello.c看看它能做什么。

标签: c gcc linker-errors ld


【解决方案1】:

您必须使用stubstart.S 构建和链接您的程序,它提供_start 入口点,如下所示

.globl _start

_start:
    call main
    movl $1, %eax
    xorl %ebx, %ebx
    int $0x80
$ gcc -c stubstart.S -o stubstart.o
$ ld --verbose -o hello hello.o stubstart.o -lc -l:ld-linux-x86-64.so.2

【讨论】:

  • 不完全正确。真正需要的是一些crt0,它比您上面的代码更多
  • @BasileStarynkevitch 也许你是对的。我已经为发布的 OP 等简单示例提供了最低要求。
  • 我喜欢这个答案,因为它显示了更“低级别”的问题所在,并暗示了对 为什么 GCC 链接其他“魔术”文件的更深入解释。我认为如果更详细地说明它为什么会这样工作可能会更好(操作系统实际上调用_start而不是main,并且gcc/libc在这些特殊文件中实现了常见的运行时初始化和拆卸逻辑),并且为您何时可能想要或更喜欢编写自己的 _start 存根与仅链接编译器提供的通用运行时文件提供一些指导。
【解决方案2】:

我使用@melpomene 提到的详细信息,最后使用 collect2 包装器获得了预期的结果:

/usr/lib/gcc/x86_64-linux-gnu/5/collect2 -plugin /usr/lib/gcc/x86_64-linux-gnu/5/liblto_plugin.so -plugin-opt=/usr/lib/gcc/x86_64-linux-gnu/5/lto-wrapper -plugin-opt=-fresolution=/tmp/ccVm3XOm.res -plugin-opt=-pass-through=-lgcc - plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lc -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lgcc_s --sysroot =/ --build-id --eh-frame-hdr -m elf_x86_64 --hash-style=gnu --as-needed -dynamic-linker /lib64/ld-linux-x86-64.so.2 -z relro -o 你好 /usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/crt1.o /usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/crti.o /usr/lib/gcc/x86_64-linux-gnu/5/crtbegin.o -L/usr/lib/gcc/x86_64-linux-gnu/5 -L/usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu -L/ usr/lib/gcc/x86_64-linux-gnu/5/../../../../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/5/../../.. hello.o -lgcc - -as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s --no-as-needed /usr/lib/gcc/x86_64-linux-gnu/5/crtend.o / usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/crtn.o --详细

需要后面提到的crt库。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-09
    • 2023-03-12
    • 2019-08-14
    • 1970-01-01
    • 2011-10-20
    相关资源
    最近更新 更多