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

Her*_*ann 5 c++ name-mangling ld

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

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

头文件定义了方法:

class foo {
    int bar(int & i);
}
Run Code Online (Sandbox Code Playgroud)

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

T bar__4fooRi
Run Code Online (Sandbox Code Playgroud)

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

U _ZN4foo9barERi
Run Code Online (Sandbox Code Playgroud)

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

是否有任何选项可以选择名称修饰算法?
我可以引入地图或明确定义损坏的名称吗?

Her*_*ann 2

@Botje\ 的建议引导我编写这样的链接器脚本(PROVIDE 节中的空格很重要):

\n\n
EXTERN(bar__4fooRi);\nPROVIDE(_ZN4foo9barERi = bar__4fooRi);\n
Run Code Online (Sandbox Code Playgroud)\n\n

据我了解,这将被视为bar__4fooRi外部定义的符号(确实如此)。如果_ZN4foo9barERi已搜索但未定义,bar__4fooRi则将取代它。

\n\n

我像这样从 GNU 工具链调用链接器(注意脚本需要位于依赖对象之后但定义库之前的顺序 \xe2\x80\x93):

\n\n
g++ -o application application.o script.ld -lfoo\n
Run Code Online (Sandbox Code Playgroud)\n\n

看来这可行。
\n至少在理论上是这样。
\n链接器现在考虑库的其他部分,而库的其他部分又依赖于其他不可解析的符号,包括(但不限于)__throw__cp_pop_exception__builtin_delete。我现在不知道这些函数是在哪里定义的。Joxean Koret 在这篇博文中显示了一些基于猜测的位置(__builtin_new可能是malloc) \xe2\x80\x93 但我不太有信心。

\n\n

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

\n\n

编辑:由于@eukaryota 指出的 ABI 更改,结果可能纯粹是学术性的,链接器脚本确实可以用于“别名”符号。这是一个完整的最小示例:

\n\n

foo.h:

\n\n
class Foo {\n    public:\n    int bar(int);\n};\n
Run Code Online (Sandbox Code Playgroud)\n\n

foo.cpp:

\n\n
#include "foo.h"\nint Foo::bar(int i) {\n    return i+21;\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

主要.cpp:

\n\n
class Foo {\n    public:\n    int baa(int); // use in-place "header" to simulate different name mangling algorithm\n};\n\nint main(int, char**) {\n    Foo f;\n    return f.baa(21);\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

脚本.ld:

\n\n
EXTERN(_ZN3Foo3barEi);\nPROVIDE(_ZN3Foo3baaEi = _ZN3Foo3barEi); /* declare "alias" */\n
Run Code Online (Sandbox Code Playgroud)\n\n

构建过程:

\n\n
g++ -o libfoo.o -c foo.c\nar rvs libfoo.a libfoo.o # simulate building a library\ng++ -o app main.o -L. script.ld -lfoo\n
Run Code Online (Sandbox Code Playgroud)\n\n

app已编译,可以执行并返回预期结果。

\n