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

从技术上讲,就文件内容而言, 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

即使它有一个mainfunction。

另外,如何使用otoolobjdump等工具检查输出文件的差异?

非常感谢。

共享库和可执行文件使用相同的格式:它们都是可加载的图像。 然而,

  1. 共享库通常与位置无关,可执行文件通常不是。 这会影响代码生成:对于与位置无关的,您必须加载全局变量或使用相对地址跳转到函数。

  2. 可执行文件有一个“入口点”,即执行开始的地方。 这通常不是 main() ,因为main()是一个函数,函数返回,但执行不应该从入口点返回。

现在,这并没有回答关于什么是-shared问题。 您可以使用-v标志询问GCC。 以下是我的系统在没有和使用-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 

带有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引用。

我不确定其余的文件是什么,但至少你知道如何找到它们,你可以四处寻找,或者如果你愿意,可以查看源代码。

根据https://gcc.gnu.org/onlinedocs/gcc/Link-Options.html#Link-Options-shared选项执行以下操作

 Produce a shared object which can then be linked with other objects to form an executable. Not all systems support this option. For predictable results, you must also specify the same set of options used for compilation (-fpic, -fPIC, or model suboptions) when you specify this linker option. 

根据-shared和-Wl之间的差异,GCC选项的 共享传递-shared到GCC可以在链接时启用或禁用其他标志。

根据我的理解,如果可执行文件具有共享库,则可执行文件的大小非常小 。 在共享库存在并正确链接之前,可执行文件不会运行。 使用共享库的好处是,如果我们有一个非常大的代码库, 我们不需要每次都构建整个代码 。 我们只需要重建.so文件并将其链接到可执行文件。 这节省了大量时间

如果没有共享库的可执行文件,可执行文件的大小将非常大 。 对于每个代码更改, 需要构建整个代码 ,这可能非常耗时