链接共享库时,可执行文件会添加什么?

5
如果我想创建一个与静态库链接的C ++程序,那么最终的可执行文件将包含来自我的程序和库的代码(我想是这样的...!),但是当我链接共享库时会发生什么还不太确定。
假设我链接名为libfoo.so的库,通过在我的CMakeLists.txt文件中指定target_link_libraries(${PROJECT_NAME} foo)一行。我假设最终的可执行文件将包含有关此库的某些信息,但不包含完整的代码。这个其他信息是什么?此外,用户系统上的库必须被称为libfoo.so吗?

注意:C++标准通常不支持动态库。最接近明确支持的是关于命名空间范围变量初始化可能延迟到main的第一条语句之后的声明。标准中的措辞同样具有误导性,我想唯一合理的解释是“在main的第一条语句开始之后”。 - Cheers and hth. - Alf
1
可执行文件具有包含不同部分信息的头。如果您有兴趣探索头文件,可以使用Linux实用程序readelf读取ELF可执行文件的头文件。特别是,您需要使用-d-s开关来分别显示动态部分和符号表。 - alvits
1个回答

6
当您链接到动态库时,连接器将在程序的动态部分中添加一个“NEEDED”条目。然后动态加载器将使用这些条目来定位库并使用该库来解决任何未定义的动态符号。
请注意,未定义的动态符号与它们应该被找到的动态库之间没有关联。有时它们被发现在另一个库中,可能会发生一些有趣的事情。
存储在“NEEDED”条目中的特定名称取决于库是否在其动态部分中具有“SONAME”条目:
- 如果存在“SONAME”,则其内容将被复制到程序的“NEEDED”中。 - 如果没有“SONAME”,则存储链接器命令中使用的库文件名。
您可以使用以下命令检查库或程序的动态部分的内容:
$ objdump -p program

这在实际中如何使用?嗯,大多数(全部?)Linux发行版都使用以下方案,系统库(例如libfoo.so):

  • 将库安装为/usr/lib/libfoo.so.1.2或其版本。
  • 有指向该库的符号链接,命名为/usr/lib/libfoo.so.1/usr/lib/libfoo.so
  • 库的SONAMElibfoo.so.1
  • 路径/usr/lib设置为动态库路径。

这样,当您使用-lfoo进行链接时,它将找到符号链接libfoo.so,但会记录SONAMElibfoo.so.1。程序运行时,它将找到其他符号链接并加载库。

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

还要注意,环境变量LD_PRELOADLD_LIBRARY_PATH和其他影响运行时行为。有关更多详细信息,请阅读man ld.so


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