当与共享库链接时,将添加到可执行文件中的内容

What is added to an executable when linking with a shared library?

本文关键字:可执行文件 添加 共享 链接      更新时间:2023-10-16

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

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

当您链接到动态库时,链接器将在程序的动态部分添加NEEDED条目。然后,动态加载器将使用这些来定位库,并使用库来求解任何未定义的动态符号。

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

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

  • 如果存在SONAME,则其内容将被复制到程序
  • NEEDED中。
  • 如果没有SONAME,则存储linkker命令中使用的库的文件名。

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

$ 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符号链接,但将SONAME记录为libfoo.so.1。当程序运行时,它会找到另一个符号链接并加载库。

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

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