2017-09-05 95 views
0

我有一个作为第三方应用程序(app.exe)的一部分运行的solaris共享对象(common.so文件)。我无法访问应用程序的源代码。为此,我需要添加一个发布http请求的功能。我的计划是在openssl中使用libcurl。棘手的部分是app.exe已经依赖于旧版本的curl(7.14),它不支持tls v1.2的ssl。使用同一个库的多个版本时的符号分辨率

我下载了源代码并构建了curl(7.55.1)和openssl.a文件。我也能够建立common.so静态依赖这些档案文件。 ldd不显示对curl或ssl .so文件的依赖性,也不会报告任何“找不到符号”错误。

有了这个结果,我期待我的curl版本被调用,当它作为应用程序的一部分运行,但它没有。相反curl_version()显示旧版本,我得到错误未知的ssl协议错误

我正在使用solaris studio编译器。应用程序不直接依赖于curl库,而是依赖于一个不同的.so文件,该文件导出与curl具有相同名称的符号。我意识到从nm,我假设这个.so文件也链接静态卷曲。

+0

你说你没有访问应用程序的源代码。但是,你至少可以重新编译或者编辑二进制文件以依赖更新的'libcurl'吗?这是什么平台? –

+0

这是在solaris SunOS版本5.10上。我无法重建或编辑二进制文件。我可以使用外部工具(如objcopy)并在外部修改共享对象的符号,但这可能会产生一些意想不到的后果。 –

回答

0

当app.exe加载有问题的两个SO时,它将每个函数添加到它的符号表中。现在必须出现的两种可能情形之一(其中一个实际上是操作系统的细节,但这里无关紧要......):

  1. 较新版本旧版本之前加载与老一个覆盖较新的一个人条目。
  2. 较新的版本在之后加载,而且由于表中已有条目,因此不会再更新。

现在最干净的解决方案–如果适用,我。即如果您有权访问源–将更新其他SO以使用较新版本的curl。如果这样做,考虑将curl创建为新的SO,而不是将其静态链接到common.so和其他SO中。

否则,要直接解决问题,您必须切换应用程序加载SO的顺序,这很可能意味着要反编译app.exe并使用SO的链接顺序进行重新构建。问题是:那时可能会有两个版本的app.exe,并且您必须确保只有正确的一个随common.so发布。麻烦的潜在来源,太...

除此之外,最好我能想出一个解决方法:

您可能会修改卷曲前缀从curl_到E。 G。 curl_755_。不要手动尝试,尽管如此,你很可能会这样疯狂......用脚本(例如perl或python)代替。如果你更新卷曲源,你可以再次运行它,然后...

更快的版本,但可能不安全:只需更换任何发生。更安全:在第一次运行中识别外部可见函数(可能是全局对象),并将它们保存在地图中,然后将映射中包含的任何字符串替换为相应的值。

后一种方法(图)将另外允许以产生以下形式的头文件宏:

#define curl_xyz curl_755_xyz 

这些宏允许的common.so只是源看起来像仿佛原始来源的卷曲被使用...

+0

是的:/我用过这个重命名的技巧来解决过去这样的问题,但这太可怕了。您确实需要更改_everything_ - 每个导出的符号 - 或者仍然可以引用旧版本。我猜测你可以通过构建一个测试程序来检查这个问题,该程序与libcurl的黑客版本链接,并且根本不参考“真正的”(旧的)libcurl。但讨厌,真的很讨厌。 –

+0

这就是为什么这个任务应该通过一些脚本完成。首先,它可以节省大量的工作,其次,可以在源代码更新时再次调用,如果正确实施,可以更好地捕获所有必要的事件,而不是用手做事情......如果幸运的话,在互联网上甚至已经存在一些脚本... – Aconcagua

+0

谢谢。我会试一试,让你知道。如果我使用libcurl.a静态链接而不是libcurl.so,它有什么区别吗?我期望当我静态链接时,common.so包含它自己需要的所有定义,并且它们将取代来自其他依赖so文件的任何定义。 –