2

背景

我有一组三个几乎相同的静态库(用 编译-fPIC),我无法重新编译它们。所有库都导出相同的符号,因此我可以将它们捆绑在一起的唯一方法是通过 为每个静态库修改带有前缀的符号objcopy,即:

for i in pineapple coconut banana
do
    objcopy --prefix-symbols=${i}_ lib${i}.a
done

现在,我有三个具有唯一符号的库,并且可以继续编写一个头文件来处理每个库的三个近乎重复的头文件/API 文件。


问题

只是重命名像这样安全的库的导出符号吗?它是否有任何可能导致运行时稳定性问题的“陷阱”或不可预见的后果?库本身中对符号的所有引用是否都会自动更正,或者是否有一些库代码(除了dlsym()调用之类的东西)会尝试引用旧符号和段错误?

4

2 回答 2

4

只是重命名像这样安全的库的导出符号吗?

取决于“安全反对什么”。

它是否有任何“陷阱”或不可预见的后果

是的,见下文。

这可能会导致运行时的稳定性问题?

不,如果你设法链接最终的二进制文件(一个大的 IF),那么生成的二进制文件就可以工作。

库本身中对符号的所有引用是否自动更正

对,他们是。该--prefix-symbols标志同时更改了定义和未解析的引用(这将导致问题,正如您稍后会看到的那样)。

IFF 库是完全独立的(不引用除它自己定义的符号以外的任何符号),然后为所有符号添加前缀将起作用:新重命名的未解析引用现在将调用pineapple_foo而不是foo,并且此引用将在链接时解析为使用新名称重命名的定义,就像需要的那样。

当目标库调用自身外部的东西(例如来自 的任何东西libc)时,麻烦就来了。这些调用将带有前缀,因此您将获得对pineapple_open, 或之类的未解析引用pineapple_printf

您可能在想:我将在其他地方提供替代品:

int pineapple_open(const char *filename, int flag, int mode)
{
   return open(filename, flag, mode);
}

这很乏味,但适用于功能。它中断的地方是全局变量:errno,h_errno等。

既然你提到-fPIC了,请注意动态库支持取决于_GLOBAL_OFFSET_TABLE_你也不想重命名。

于 2017-11-24T03:32:18.107 回答
0

假设库是由多个源文件构建的,从库中导出的符号几乎肯定会被库中的其他位置引用。所以更改符号的名称会导致以后出现链接问题。

于 2017-11-23T22:35:52.070 回答