objcopy 对静态库的不可预见的后果

Unforeseen consequences of objcopy on static libraries

背景

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

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

现在,我有三个具有独特符号的库,可以继续编写一个 header 来处理每个库的三个 near-duplicate header/API 文件。


问题

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

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

Is just renaming the exported symbols of a library like this safe?

取决于 "safe against what".

Does it have any "gotchas" or unforeseen consequences

是的,见下文。

that could lead to stability problems at runtime?

没有。如果您设法 link 最终的二进制文件(一个大 IF),那么生成的二进制文件将起作用。

Are all references to the symbol within the library itself automagically corrected

是的,他们是。 --prefix-symbols 标志更改了定义和未解析的引用(这会导致问题,您很快就会看到)。

IFF 库是 完全 自包含的(不引用除它自己定义的符号之外的任何符号),然后为所有符号添加前缀将起作用:新重命名的未解析引用将现在调用 pineapple_foo 而不是 foo,此引用将在 link 时根据需要解析为具有新名称的重命名定义。

当目标库调用自身之外的东西(例如来自 libc 的任何东西)时,问题就来了。这些调用将 加上前缀,所以你会得到一个未解析的引用,比如 pineapple_openpineapple_printf.

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

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

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

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