【问题标题】:ld -shared success but got a segmentation fault when runld -shared 成功,但运行时出现分段错误
【发布时间】:2020-09-25 03:17:42
【问题描述】:

我是学习基本编译的初学者。我创建了一个非常简单的 c 文件,如下所示

#include <stdio.h>

int main (void) {
  printf("Hello World!\n");
  return 0;
}

然后我运行命令,

cpp -E helloworld.c -o helloworld.i
gcc -S helloworld.i -o helloworld.s
as helloworld.s -o helloworld.o
ld -shared -o helloworld /usr/lib64/libc.so helloworld.o

在这里,我收到了这样的错误消息,

ld -shared -o helloworld /usr/lib64/libc.so helloworld.o
ld: helloworld.o: relocation R_X86_64_32 against `.rodata' can not be used when making a shared object; recompile with -fPIC
ld: final link failed: Nonrepresentable section on output

所以我重新运行上层,但使用 -fPIC

cpp -E helloworld.c -o helloworld.i
gcc -S helloworld.i -o helloworld.s -fPIC
as helloworld.s -o helloworld.o
ld -shared -o helloworld /usr/lib64/libc.so helloworld.o

最后,我得到了我的 helloworld,但是当我尝试 ./helloworld 时,我遇到了分段错误。

有人可以帮忙吗?提前致谢!

【问题讨论】:

  • 您是否有理由尝试单独执行构建的每个部分而不是使用gcc 来构建所有命令?那是gcc -o helloworld helloworld.c?您的命令还不够,因为需要链接的不仅仅是 libc。运行 gcc -v helloworld.c 以查看 gcc 执行的确切步骤并与您所拥有的进行比较。
  • 是的,gcc -o helloworld helloworld.c 有效,但我尝试了解 ld 命令的工作原理,这就是我这样做的原因。 gcc -v 输出对我来说有点复杂。能否请您提供更多细节?非常感谢!
  • 那么是的,请查看gcc -v 输出以更好地了解命令详细信息。它不像你现在做的那么简单。
  • 好的,感谢任何解释 gcc -v 输出的网络链接!

标签: linux gcc ld


【解决方案1】:

我尝试使用 gcc helloworld.c -Wl,--verbose | grep 成功并得到如下输出,

attempt to open /usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../lib64/crt1.o succeeded
attempt to open /usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../lib64/crti.o succeeded
attempt to open /usr/lib/gcc/x86_64-redhat-linux/4.8.5/crtbegin.o succeeded
attempt to open /tmp/ccSuIvy2.o succeeded
attempt to open /usr/lib/gcc/x86_64-redhat-linux/4.8.5/libgcc.a succeeded
attempt to open /usr/lib/gcc/x86_64-redhat-linux/4.8.5/libgcc_s.so succeeded
attempt to open /usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../lib64/libc.so succeeded
attempt to open /lib64/libc.so.6 succeeded
attempt to open /usr/lib64/libc_nonshared.a succeeded
attempt to open /lib64/ld-linux-x86-64.so.2 succeeded
attempt to open /usr/lib/gcc/x86_64-redhat-linux/4.8.5/libgcc.a succeeded
attempt to open /usr/lib/gcc/x86_64-redhat-linux/4.8.5/libgcc_s.so succeeded
attempt to open /usr/lib/gcc/x86_64-redhat-linux/4.8.5/crtend.o succeeded
attempt to open /usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../lib64/crtn.o succeeded

但我还是不知道怎么做链接,我试试这个

ld -shared -o helloworld /usr/lib64/libc.so /usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../lib64/crti.o /usr/lib/gcc/x86_64-redhat-linux/4.8.5/libgcc_s.so /usr/lib/gcc/x86_64-redhat-linux/4.8.5/crtend.o /usr/lib64/crtn.o helloworld.o /usr/lib/gcc/x86_64-redhat-linux/4.8.5/libgcc.a /usr/lib64/libc_nonshared.a /usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../lib64/crt1.o 

但收到错误消息,

ld: /usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../lib64/crt1.o: relocation R_X86_64_32S against undefined symbol `__libc_csu_fini' can not be used when making a shared object; recompile with -fPIC
ld: final link failed: Nonrepresentable section on output

【讨论】:

  • 您必须使用-fPIC(或-fpic)为共享库生成位置无关代码,因为必须通过全局偏移量而不是相对于地址的地址来访问共享库加载库的程序 - 否则每次加载库时相对偏移量将引用不同的位置。请参阅-fpic 选项下的man gcc
  • 但是crtl.o不是我创建的,是ubuntu提供的吧?
  • 没错,如果你想要任何东西,包括加载你的 helloworld 的 c-runtime,那么它必须有全局偏移量。更大的问题是你试图完成什么。您没有将代码用作共享库。为什么不使用打印 helloworld 的函数创建单独的源并将其编译为共享库,然后将其与 main() 链接并调用打印 helloworld 的函数?
猜你喜欢
  • 1970-01-01
  • 2017-02-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-10-24
相关资源
最近更新 更多