GNU 链接器:适应名称修改算法的更改

GNU linker: Adapt to change of name mangling algorithm

我正在尝试重新编译现有的 C++ 应用程序。 不幸的是,我必须依赖一个专有库,我只有一个预编译的静态存档。

我使用的是 g++ 7.3.0 版和 ld 2.30 版。
无论用什么 GCC 版本编译,它都是古老的。

头文件定义方法:

class foo {
    int bar(int & i);
}

nm lib.a所示,库存档包含相应的导出函数:

T bar__4fooRi

nm app.o 显示我最近的编译器使用了不同类型的名称修改:

U _ZN4foo9barERi

因此链接器无法解析库提供的符号。

是否有选择名称修改算法的选项?
我可以引入映射或明确定义错位名称吗?

@Botje 的建议让我编写了一个这样的链接描述文件(PROVIDE 节中的空格很重要):

EXTERN(bar__4fooRi);
PROVIDE(_ZN4foo9barERi = bar__4fooRi);

据我了解,这会将 bar__4fooRi 视为外部定义的符号(它是)。如果搜索 _ZN4foo9barERi 但未定义,bar__4fooRi 将取而代之。

我这样从 GNU 工具链调用链接器(注意顺序——脚本需要在依赖对象之后但在定义库之前):

g++ -o application application.o script.ld -lfoo

看起来这可行。
至少理论上是这样。
链接器现在考虑库的其他部分,这些部分又依赖于其他无法解析的符号,包括(但不限于)__throw__cp_pop_exception__builtin_delete。我不知道现在这些功能在哪里定义。 Joxean Koret 根据猜测显示了 this blog post 中的一些位置(__builtin_new 可能是 malloc)——但我没有那么自信。

这些发现使我得出结论,该库依赖于不同风格的异常处理,也可能依赖于内存管理。

编辑: 由于 @eukaryota 指出的 ABI 变化,结果可能纯粹是学术性的,链接描述文件确实可以用于 "alias" 符号。这是一个完整的最小示例:

foo.h:

class Foo {
    public:
    int bar(int);
};

foo.cpp:

#include "foo.h"
int Foo::bar(int i) {
    return i+21;
}

main.cpp:

class Foo {
    public:
    int baa(int); // use in-place "header" to simulate different name mangling algorithm
};

int main(int, char**) {
    Foo f;
    return f.baa(21);
}

script.ld:

EXTERN(_ZN3Foo3barEi);
PROVIDE(_ZN3Foo3baaEi = _ZN3Foo3barEi); /* declare "alias" */

构建过程:

g++ -o libfoo.o -c foo.c
ar rvs libfoo.a libfoo.o # simulate building a library
g++ -o app main.o -L. script.ld -lfoo

app已编译,可以执行,returns预期结果。