1 前言

这两天在编写一个插件系统Demo的时候,发现了个很奇怪的问题:插件加载器中已经链接了ld库,但是应用程序在链接插件加载器的时候,却还需要显式的来链接ld库。否则就会报:DSO missing from command line。这个报错翻译过来就是没有在命令行中指定该动态库
这个报错就很搞事了,你说你明明知道需要哪个库,为什么不直接帮我链接呢,非得我显示的在命令行中指定呢?

2 现象描述

问题可以简单描述为:当链接可执行文件时,依赖于libA.so,而libA.so又依赖于libB.so,而且可执行文件中还直接调用了libB.so中的函数,那么此时链接就会出现错误。

2.1 问题发生的前置条件

  • libA.so在编译过程中显式的链接了libB.so
  • 可执行文件中使用了libB.so的函数
  • binuntils版本 ≥ 2.22

2.2 Talk is cheap. Show me the code

话不多说,先看看可以复现改问题的代码吧

libB.so的源码:

#include <stdio.h>int funB1(){printf("in funB1");return 0;
}int funB2(){printf("in funB2");return 0;
}

这里面有两个函数:funB1funB2
其中funB1函数会被libA调用,而funB2会被可执行文件调用。

编译libB.so:

$ gcc libB.cpp -fPIC -shared -o libB.so

libA.so的源码:

#include <stdio.h>int funB1();int funA1(){printf("in funA1 \n");funB1();return 0;
}

该库中只有一个函数funA1,该函数在内部调用了libB中的funB1函数。且该函数会被可执行文件调用。

编译libA.so:

$ gcc libA.cpp -fPIC -shared -o libA.so -Wl,-rpath=./ -L./ -lB

main.cpp的源码:

int funA1();
int funB2();int main(){funA1();funB2();return 0;
}

编译main.cpp:(复现错误的编译方法)

gcc main.cpp -L./ -lA

当我们按照上面的指令编译main.cpp的时候,便报错了。

/usr/bin/ld: /tmp/ccDQXTKy.o: undefined reference to symbol '_Z5funB2v'
.//libB.so: error adding symbols: DSO missing from command line
collect2: error: ld returned 1 exit status

(问号.jpg)这,这GCC不是搞事吗,你明明知道我需要连接libB.so为啥就不帮我链接上去呢?难道我libA.so没有指明要使用libB.so?我们使用下面的指令来看一下

$ ldd libA.so

得到如下信息:

 linux-vdso.so.1 =>  (0x00007ffd09def000)libB.so => ./libB.so (0x00007fc513d7d000)libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fc5139b3000)/lib64/ld-linux-x86-64.so.2 (0x00007fc514181000)

明明libA.so已经显式的指明我要依赖libB.so了,那为啥在编译main.cpp的时候链接了libA.so,GCC却还要我们显式的链接libB.so呢?

3 答案

答案很简单,那就是GCC就是想要你显式链接呗。(你是编译器,你牛好吧。)那这是为啥呢?
官方一点的答案就是,自从binutils 2.22版本以后,如果你在程序中使用了你依赖的动态库所依赖的动态库中的函数时,你就必须显式的指定你依赖的动态库所依赖的动态库。

说那么多,我们更想知道的是,通过修改什么参数可以解决这个问题呢?因为你可能不想在编译程序的时候要把动态库所依赖的所有动态库都显示链接一遍。

4 究极答案

实际上,这是binutils在2.22版本以后,默认把--no-copy-dt-needed-entries这个选项打开了。当打开了这个选项的时候,编译器在链接的时候是不会递归的去获取依赖动态库的依赖项的,于是就会出现上述的问题。关于该配置项的详细说明如下:

   --copy-dt-needed-entries--no-copy-dt-needed-entriesThis option affects the treatment of dynamic libraries referred to by DT_NEEDED tags inside ELF dynamic libraries mentioned on the command line.  Normally the linker won't add a DT_NEEDEDtag to the output binary for each library mentioned in a DT_NEEDED tag in an input dynamic library.  With --copy-dt-needed-entries specified on the command line however any dynamiclibraries that follow it will have their DT_NEEDED entries added.  The default behaviour can be restored with --no-copy-dt-needed-entries.This option also has an effect on the resolution of symbols in dynamic libraries.  With --copy-dt-needed-entries dynamic libraries mentioned on the command line will be recursivelysearched, following their DT_NEEDED tags to other libraries, in order to resolve symbols required by the output binary.  With the default setting however the searching of dynamiclibraries that follow it will stop with the dynamic library itself.  No DT_NEEDED links will be traversed to resolve symbols.

大概意思就是,跟在--no-copy-dt-needed-entries它后面的库都不会遍历其依赖项,使用--copy-dt-needed-entries则相反。也就是使用下面的指令来编译mian.cpp就可以避免该问题了。

$ gcc main.cpp -L./ -Wl,--copy-dt-needed-entries -lA

题外话

在Linux的ELF文件中,如果依赖于其他的动态库,那么改ELF文件会存在一个.dynamic的段,这个段里面会记录其依赖的动态库信息,其标志位为DT_NEEDED。

5 参考文档

1,DSO missing from command line原因及解决办法:https://segmentfault.com/a/1190000002462705
2,折腾gcc/g++链接时.o文件及库的顺序问题: https://www.cnblogs.com/OCaml/archive/2012/06/18/2554086.html#sec-1-4-1

Linux动态库依赖其它动态库的问题相关推荐

  1. Qt动态库静态库的创建、使用、多级库依赖、动态库改成静态库等详细说明

    本文描述的是windows系统下,通过qtcreator在pro文件中添加动态库与静态库的方法: 1.添加动态库(直接添加动态库文件.dll,非子项目) 通过qtcreator创建动态库的方法就不在此 ...

  2. linux库知识,静态库和动态库

    在xmeeting中,关于usb手柄部分,采用动态库调用方式,下面翻译一篇David A. Wheeler写的文章.文章就如何创建和使用静态库,共享库以及动如何动态装载库进行了论述.内容纲要如下:   ...

  3. python画动态爱心-python绘制动态爱心

    CSS布局HTML小编今天和大家分享助用python从数据库取数据动态生成表格的方法 一.可使用的第三方库 python中处理excel表格,常用的库有xlrd(读excel)表.xlwt(写exce ...

  4. linux命令之查看程序动态库依赖-ldd

    一个程序依赖很多的动态库,类似windows下的depends工具可以查看exe程序的依赖库是否找到.在linux下,可以通过ldd命令查看程序是否能找到依赖的动态库,从而排查是缺少库还是由于环境变量 ...

  5. linux下编译自己的静态库时依赖其他的动态库,使用时出现“undefined reference to”

    对于我这个刚入IT行业不就得新手来说,在linux下链接库的时候总是会遇到各种各样奇葩的问题,最多的就是"undefined reference to"和"cannot ...

  6. linux下的共享库(动态库)和静态库

    1.什么是库 在windows平台和linux平台下都大量存在着库. 本质上来说库是一种可执行代码的二进制形式,可以被操作系统载入内存执行. 由于windows和linux的本质不同,因此二者库的二进 ...

  7. Linux下制作和使用静态库和动态库

    写在前面: ldd + 可执行文件 可以查看可执行文件所依赖的库 概述: Linux操作系统支持的函数库分为静态库和动态库,动态库又称共享库.linux系统有几个重要的目录存放相应的函数库,如/lib ...

  8. linux系统下的“静态库和动态库”专题之一:库的概念和规则

    什么是库 在windows平台和linux平台下都大量存在着库. 本质上来说库是一种可执行代码的二进制形式,可以被操作系统载入内存执行. 由于windows和linux的本质不同,因此二者的库也是不兼 ...

  9. linux分文件编程、静态库与动态库

    参考:linux静态库与动态库编程 作者:丶PURSUING 发布时间:2021-02-02 16:51:49 网址:https://blog.csdn.net/weixin_44742824/art ...

  10. [转]Linux下g++编译与使用静态库(.a)和动态库(.os) (+修正与解释)

    在windows环境下,我们通常在IDE如VS的工程中开发C++项目,对于生成和使用静态库(*.lib)与动态库(*.dll)可能都已经比较熟悉,但是,在linux环境下,则是另一套模式,对应的静态库 ...

最新文章

  1. dmmbus地址_dmmbus新地址是多少_动漫台
  2. windows怎么下载安装python-windows下numpy下载与安装图文教程
  3. f12获取网页文本_怎么获取网页源代码中的文件?
  4. EPSON TCP/IP 通信
  5. python列表相关函数_python中列表(list)相关的函数
  6. 简单一致的Log4j2 Logger命名
  7. flutter tab选项卡appbar中的选项卡
  8. 表格中建一个按钮_CAD | CAD和Excel的表格互换教程
  9. 计算机配件模拟,模拟计算机是指什么
  10. 阶段3 2.Spring_06.Spring的新注解_7 spring整合junit问题分析
  11. Android IOS视频录制技术方案
  12. 【JZOJ A组】东风谷早苗
  13. 黑苹果2k显示器开启hidpi_黑苹果无核显开启macOS-ipad随航功能
  14. 科兴新冠疫苗获准紧急用于巴西3至5岁儿童
  15. RuPengWang项目
  16. ssh突然无法登录,报错failed to start openssh daemon
  17. Ubuntu高分屏下Matlab工具栏字体过小
  18. win7 关闭防火墙
  19. LINUX命令(1)-创建文件
  20. 数据中心服务器怎么设置信息点,数据中心服务器机柜内的信息点数

热门文章

  1. QQ登录界面实现代码
  2. 驾照科二科三训练总结
  3. 人民日报申论范文:题目考“时间”你怎么写
  4. 相见恨晚 linux下的c++filt 命令
  5. 守望先锋中的netcode_如何跟踪守望先锋中的化妆品和事件物品
  6. android 菜鸟面单打印_关于菜鸟的圆通电子面单打印
  7. C++ auto类型说明符如for(atuo x : s)
  8. 前阿里P10赵海平被打3.25后离职,加入字节跳动,职级或为4+
  9. Mysql 免安装配置
  10. 【网络安全】企业内网中的横向移动