GNU linker: адаптироваться к изменению алгоритма искажения имени - PullRequest
0 голосов
/ 29 ноября 2018

Я пытаюсь пересобрать существующее приложение 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

Следовательно, компоновщик не может разрешить символы, предоставляемые библиотекой.

Можно ли выбрать алгоритм искажения имени?
Можно ли ввести карту или определить искаженные имена явно?

1 Ответ

0 голосов
/ 29 ноября 2018

@ Предложение Ботье привело меня к написанию сценария компоновщика, как этот (пробелы в разделе 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 показывает некоторые места в этом сообщении в блоге на основе догадок (__builtin_new, вероятно, malloc) - но я не настолько уверен.

Эти выводы приводят меня к выводу, чтобиблиотека опирается на другой стиль обработки исключений и, возможно, управления памятью.

РЕДАКТИРОВАТЬ: Результат может быть чисто академическим из-за изменений ABI, на что указывает @eukaryota, компоновщикСкрипт действительно может быть использован для «псевдонима» символов.Вот полный минимальный пример:

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 скомпилирован, может быть выполнен и возвращает ожидаемый результат.

...