为另一个共享库加载共享库

时间:2018-11-14 15:21:15

标签: c shared-libraries dlopen

我正在开发一个更新应用程序,该应用程序必须能够在现有系统上运行,并且还必须由该现有系统上的另一个应用程序启动。

我正在使用一个共享库,该共享库本身使用OpenSSL,但是没有针对它进行链接。以前,我的更新应用程序与OpenSSL链接以解决此问题。但是现在由于二进制不兼容,我无法再链接到OpenSSL。现在,当我的应用程序在现有系统上启动时,由于没有加载OpenSSL,我收到一个undefined symbol错误。请注意,我无法选择通过LD_PRELOAD加载它,因为我无法更改启动更新应用程序的应用程序。

我曾考虑过通过dlopen加载OpenSSL,希望共享库能够使用它。但是共享库在C构造函数(__attribute__((constructor (101))) void myConstructor()中使用OpenSSL,即使我在另一个具有更高优先级的构造函数中调用dlopen,动态装载程序似乎也已经在OpenSSL中搜索(失败了)。我的构造函数甚至都没有执行。

LD_BIND_NOW未设置,所以我想知道为什么在调用构造函数之前发生undefined symbol错误。

1 个答案:

答案 0 :(得分:0)

我自己找到了解决方法。

问题在于共享库在主应用程序之前被初始化(即,调用了C构造函数)。设置环境变量LD_DEBUG=libs时可以看到顺序。所以我自己创建了一个共享库。我将这个修订库链接到越野车库(-lbuggy -lfix)后面,因为初始化过程大致(我不太了解规则)是按相反的加载顺序进行的。

现在,我能够像这样在我的修订库的C构造函数中加载OpenSSL:

void *p = dlopen("libssl.so.1.0.0", RTLD_LAZY | RTLD_GLOBAL | RTLD_NODELETE);
if(p)
  dlclose(p);

标志RTLD_GLOBAL确保其他库也可以使用OpenSSL。 标志RTLD_NODELETE确保没有在dlclose上卸载该库。

注意:当我的更新应用程序在具有OpenSSL 1.1的较新系统上运行并且可以正确链接到OpenSSL的共享库时,加载libssl.so.1.0.0会失败,因为该系统上不存在旧的OpenSSL版本(嵌入)系统,需要节省磁盘空间)。如果OpenSSL 1.0仍然存在,则可能是一个问题。