gcc的`-shared`选项如何影响输出?

15

gcc -fPIC -shared src.cgcc -fPIC src.c的文件内容技术上有什么区别?

假设src.c中定义了int main(int, char**),以使两种编译成功。但是执行由gcc -shared src.c生成的a.out时,会出现以下错误:

-bash: ./a_shared.out: cannot execute binary file

即使其中有一个main函数。

此外,我怎样使用诸如otoolobjdump之类的工具检查输出文件的差异呢?

非常感谢。

2个回答

16
共享库和可执行文件使用相同的格式:它们都是可加载的映像。但是,
  1. 共享库通常是位置无关的,而可执行文件通常不是。这会影响代码生成:对于位置无关的情况,您必须使用相对地址加载全局变量或跳转到函数。
  2. 可执行文件有一个“入口点”,这是执行开始的地方。这通常不是main(),因为main()是一个函数,函数会返回,但执行从入口点永远不应该返回。
现在,这并没有回答关于-shared的问题。您可以使用-v标志询问GCC。以下是在我的系统上调用时没有和有-shared的区别。

没有-shared参数的collect2

-dynamic-linker
/lib64/ld-linux-x86-64.so.2
/usr/lib/gcc/x86_64-linux-gnu/4.7/../../../x86_64-linux-gnu/crt1.o
/usr/lib/gcc/x86_64-linux-gnu/4.7/crtbegin.o
/usr/lib/gcc/x86_64-linux-gnu/4.7/crtend.o

-shared选项下collect2的参数:

-shared
/usr/lib/gcc/x86_64-linux-gnu/4.7/crtbeginS.o
/usr/lib/gcc/x86_64-linux-gnu/4.7/crtendS.o

观察

看起来代码生成没有受影响:您仍然需要使用-fpic-fPIC

可以看到只有在链接可执行文件时才包含crt1.o(“C运行时”)。使用nm,我们可以找出它包含了什么:

$ nm /usr/lib/x86_64-linux-gnu/crt1.o
0000000000000000 R _IO_stdin_used
0000000000000000 D __data_start
                 U __libc_csu_fini
                 U __libc_csu_init
                 U __libc_start_main
0000000000000000 T _start
0000000000000000 W data_start
                 U main

因此,您可以看到它似乎定义了与 stdin 以及 _start(入口点)有关的某些内容,并且它对 main 存在未定义的引用。

我不确定其他文件是什么,但至少您知道如何找到它们并且可以浏览或查看源代码(如果您愿意的话)。


太棒了 - 谢谢@dietrich。关于crt1.o的部分让区别变得清晰明了。 - Dale Z

4
根据https://gcc.gnu.org/onlinedocs/gcc/Link-Options.html#Link-Options-shared选项的作用如下:
  • 生成一个共享对象,可以与其他对象链接以形成可执行文件。

  • 并非所有系统都支持此选项。

  • 为了获得可预测的结果,在指定此链接器选项时,必须同时指定编译时使用的相同选项集(-fpic、-fPIC或模型子选项)。

根据Difference between -shared and -Wl,-shared of the GCC options,向GCC传递-shared可能会在链接时启用或禁用其他标志。
据我理解,如果可执行文件有共享库,则可执行文件的大小很小。只有在存在并正确链接共享库时,可执行文件才能运行。使用共享库的优点是,如果我们有一个非常大的代码库,我们不需要每次都构建整个代码。我们只需重建.so文件并将其链接到可执行文件中。这样可以节省大量时间
而对于没有共享库的可执行文件,可执行文件的大小将非常大。每次更改代码都需要构建整个代码,这可能非常耗时。

谢谢回复,@rohit。我知道-share会生成一个共享对象,但是我想知道它的内容与使用gcc不带-shared选项生成的可执行文件有何不同。 - Dale Z
1
这是一个共享对象,因此它不是可执行文件。这就是为什么你会收到错误信息。你是在问共享对象和可执行文件之间的区别吗? - Ross Ridge
谢谢,@RossRidge。Dietrich的回答正是我感兴趣的——在相同格式下,可执行文件与共享对象有何不同。 - Dale Z

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接