GNU linker: Adapt to change of name mangling algorithm

喜夏-厌秋 提交于 2019-12-23 18:52:40

问题


I am trying to re-compile an existing C++ application. Unfortunately, I must rely on a proprietary library I only have a pre-compiled static archive of.

I use g++ version 7.3.0 and ld version 2.30.
Whatever GCC version it was compiled with, it is ancient.

The header file defines the method:

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

As nm lib.a shows, the library archive contains the corresponding exported function:

T bar__4fooRi

nm app.o shows my recent compiler employing a different kind of name mangling:

U _ZN4foo9barERi

Hence the linker cannot resolve the symbols provided by the library.

Is there any option to chose the name mangling algorithm?
Can I introduce a map or define the mangled names explicitly?


回答1:


@Botje's suggestion lead me to writing a linker script like this (the spaces in the PROVIDE stanza are significant):

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

As far as I understood, this will regard bar__4fooRi as an externally defined symbol (which it is). If _ZN4foo9barERi is searched for, but not defined, bar__4fooRi will take its place.

I am calling the linker from the GNU toolchain like this (mind the order – the script needs to be after the dependant object but before the defining library):

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

It looks like this could work.
At least in theory.
The linker now regards other parts of the library, which in turn depends on other unresolvable symbols including (but not limited to) __throw, __cp_pop_exception, and __builtin_delete. I have no idea where these functions are defined nowadays. Joxean Koret shows some locations in this blog post based on guesswork (__builtin_new probably is malloc) – but I am not that confident.

These findings lead me to the conclusion that the library relies on a different style of exception handling and probably memory management, too.

EDIT: The result may be purely academical due to ABI changes as pointed out by @eukaryota, a linker script can indeed be used to "alias" symbols. Here is a complete minimal example:

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" */

Build process:

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 is compiled, can be executed and returns expected result.



来源:https://stackoverflow.com/questions/53541789/gnu-linker-adapt-to-change-of-name-mangling-algorithm

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!