链接共享库时添加到可执行文件的内容是什么?

Kar*_*rus 5 c++ unix linux

如果我想创建一个与静态库链接的C++程序,那么最终的可执行文件将包含我程序中的代码和库中的代码(我认为......!).但是我不确定当我与共享库链接时会发生什么.

假设我libfoo.so通过在我的CMakeLists.txt文件中指定行来链接一个被调用的库target_link_libraries(${PROJECT_NAME} foo).我假设最终的可执行文件将包含有关此库的一些信息,但不包含完整的代码.这是什么其他信息?此外,是否必须libfoo.so在用户的系统上完全调用库?

rod*_*igo 6

链接到动态库时,链接器将NEEDED在程序的动态部分中添加一个条目.然后动态加载器将使用它们来定位库并使用库来解决任何未定义的动态符号.

请注意,未定义的动态符号与期望找到它们的动态库之间没有任何关联.有时他们会被发现在另一个图书馆,有趣的事情可能发生.

存储在NEEDED条目中的特定名称取决于库是否SONAME在其动态部分中有一个条目:

  • 如果有SONAME,则将其内容复制到NEEDED程序中
  • 如果不存在SONAME,则将存储链接器命令中使用的库的文件名.

您可以使用以下命令检查库或程序的动态部分的内容:

$ objdump -p program
Run Code Online (Sandbox Code Playgroud)

这在实践中如何使用?那么,大多数(所有?)linux发行版使用以下方案,系统库(take libfoo.so):

  • 该库安装为/usr/lib/libfoo.so.1.2或任何版本.
  • 这是名为/usr/lib/libfoo.so.1和的图书馆的符号链接/usr/lib/libfoo.so.
  • SONAME图书馆是libfoo.so.1.
  • 路径/usr/lib设置为动态库路径.

这样,当你链接-lfoo它时会找到符号链接libfoo.so,但会记录SONAMElibfoo.so.1.当程序运行时,它将找到另一个符号链接并加载库.

使用此技巧以便您可以安装ABI兼容,改进libfoo.so.1.3和ABI不兼容的新版本libfoo.so.2.1,旧程序将加载旧库,而新编译将使用新库.

还要注意的是环境变量LD_PRELOAD,LD_LIBRARY_PATH以及其它影响运行时行为.有关详细信息,请阅读man ld.so