Unix程序使用共享库中错误的函数

3
我正在重构一套旧的实用程序,并创建一个新的服务器,该服务器将使用它们所有的共同代码来统一它们的功能,并允许远程客户端进行外部访问。对于每个实用程序,我正在提取出我需要用于服务器的代码,并将其重构为一个共享库,以便实用程序和服务器现在都可以链接到该共享库。由于这些实用程序的前任实现者的做法,他们几乎只是在需要创建新实用程序时复制并粘贴了所有内容,因此有大量具有相同签名(即XML解析器的回调)但内部执行不同操作的函数。
当我运行已经重构为链接到共享代码的独立实用程序时,它们完美地工作。但是,当我尝试使用与给定实用程序相同功能的服务器时,服务器使用的是第一个链接库中的代码,而不是应该获取功能的库。
例如,我有针对设备A、B、C的XML,这些XML会被一个通用的XML库解析,但是每个设备都有自己的共享库libA、libB、libC供服务器使用。当我调用服务器发送设备C的XML时,它使用的是libA中的“HandleStartElement”函数,而不是libC中同名且带有相同签名的函数,即使共享库仅在内部声明这些函数,而没有共享任何头文件来提及这些解析XML的内部回调。
请问有人能够解释一下为什么它没有读取正确的函数,以及如何避免这种情况发生?
我的服务器makefile具有以下编译主程序的标志:
-I../include -L../lib -lA -lB -lC

每个共享库仅使用了与共享库相邻的标志,并且未使用-fPIC。

1个回答

7
当使用-l标志时,共享库应该像非共享库一样工作,并且特别地,不支持存在多个具有相同名称的函数。你已经有点幸运了,因为服务器总体上还是可以运行的。
如果我正确理解您的问题,那么具有相同名称的函数不打算在共享库之外“可见”。共享库具有“动态符号表”,其中列出了由共享库导入和导出的符号。对于GNU工具,您可以使用nm -D libfoo.so查看其内容。传统的Unix链接器通过使用对象文件中的所有公共实体(即非static函数和全局变量)来填充该符号表。在这里,您想要的是更受控制的符号表构造。如果您的代码使用GNU工具(例如,您正在Linux上运行),则需要阅读本文,特别是第2.2节。简而言之:ELF格式支持您所需的内容,并且有几种工具/方法可以实现它。
然而,在您的位置上,我会使用一些基于sed的脚本来重命名冲突的函数,使它们具有唯一的名称。对原始复制粘贴者采取一些报复性行动也许是必要的。
您应该使用-fPIC。在某些体系结构上,对于共享库不使用-fPIC是致命错误。由于您的代码没有崩溃,我认为您正在x86硬件上运行。

你确实正确理解了问题,我希望符号表的构建更加可控。我正在从运行Gentoo和2.6内核的x86机器交叉编译到运行2.4内核的PPC 405嵌入式机器。我会阅读这篇文章,看看能否操纵符号表的构建,否则我只能重命名一堆东西了。非常感谢。 - Alex Marshall
看完了这篇文章。只需将我的内部模块函数重新声明为静态(这是我一开始就应该知道的)就足以防止它们在符号表中被公开访问。再次感谢您。 - Alex Marshall

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