简体   繁体   English

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

[英]How does gcc `-shared` option affect the output?

Technically, in terms of file content, what is the difference between the output of gcc -fPIC -shared src.c and gcc -fPIC src.c ?从技术上讲,就文件内容而言, gcc -fPIC -shared src.cgcc -fPIC src.c的输出有什么区别?

Assume that int main(int, char**) is defined in src.c so that both compilations succeed.假设在src.c定义了int main(int, char**)以便两个编译都成功。 But executing the a.out generated by gcc -shared src.c , as expected, gave the following error:但是按预期执行由gcc -shared src.c生成的a.out会出现以下错误:

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

Even if there is a main function it it.就算有一个main函数吧。

Also, how can I inspect the difference in the output files using tools like otool or objdump ?另外,如何使用otoolobjdump等工具检查输出文件中的差异?

Thanks a lot.非常感谢。

Shared libraries and executables use the same format: they are both loadable images.共享库和可执行文件使用相同的格式:它们都是可加载的图像。 However,然而,

  1. Shared libraries are usually position-independent, executables are often not.共享库通常与位置无关,可执行文件通常不是。 This affects code generation: for position-independent, you have to load globals or jump to functions using relative addresses.这会影响代码生成:对于位置无关,您必须使用相对地址加载全局变量或跳转到函数。

  2. Executables have an "entry point" which is where execution starts.可执行文件有一个“入口点”,它是执行开始的地方。 This is usually not main() , because main() is a function, and functions return, but execution should never return from the entry point.这通常不是main() ,因为main()是一个函数,函数返回,但执行永远不应该从入口点返回。

Now, this doesn't answer the question about what -shared does.现在,这并没有回答关于-shared做什么的问题。 You can ask GCC by using the -v flag.您可以使用-v标志询问 GCC。 Here are the differences on my system between an invocation without and with -shared .以下是我的系统上不带和带-shared的调用之间的差异。

Parameters for collect2 without -shared :参数collect2-shared

-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

Parameters for collect2 with -shared :对于参数collect2-shared

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

Observations观察

It looks like code generation is not affected: you still have to use -fpic or -fPIC .看起来代码生成不受影响:您仍然必须使用-fpic-fPIC

You can see that crt1.o (the "C runtime") is only included when linking the executable.您可以看到crt1.o (“C 运行时”)仅在链接可执行文件时包含在内。 Using nm , we can find out what it contains:使用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

So you can see it seems to define something to do with stdin , as well as _start (which is the entry point), and it has an undefined reference to main .所以你可以看到它似乎定义了一些与stdin以及_start (它是入口点)有关的东西,并且它有一个对main的未定义引用。

I'm not sure what the rest of the files are, but at least you know how to find them and you can poke around, or look at the source code if you like.我不确定其余的文件是什么,但至少您知道如何找到它们,并且可以随意浏览,或者如果您愿意,可以查看源代码。

As per https://gcc.gnu.org/onlinedocs/gcc/Link-Options.html#Link-Options -shared option does the following根据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.对于可预测的结果,您还必须在指定此链接器选项时指定用于编译的相同选项集(-fpic、-fPIC 或模型子选项)。

As per Difference between -shared and -Wl,-shared of the GCC options Passing -shared to GCC may enable or disable other flags at link time.按照-shared和轮候册的区别,-shared的GCC选项传递到-shared GCC可以启用或链接时禁止其他标志。

As per my understanding if an executable has shared library, size of executable is very less .根据我的理解,如果可执行文件具有共享库,则可执行文件的大小非常小 The executable will not run until the shared library is present and correctly linked.在共享库存在并正确链接之前,可执行文件不会运行。 Advantage of using shared library is that if we have a very big code base, we need not build the entire code always every time.使用共享库的好处是如果我们有一个非常大的代码库,我们不需要每次都构建整个代码 We just need to rebuild the .so file and link it to executable.我们只需要重建 .so 文件并将其链接到可执行文件。 This saves a lot of time .节省了大量时间

And in case for an executabe without shared library , executable size will be very large .对于没有共享库的可执行文件,可执行文件的大小将非常大 For every code change entire code needs to be builded , which can be very time consuming .对于每次代码更改,都需要构建完整的代码,这可能非常耗时

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM