Получена ошибка «неопределенный символ» при загрузке библиотеки с помощью dlopen - PullRequest
19 голосов
/ 26 января 2009

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

Моя командная строка для создания общих библиотек выглядит так:

cc -shared -fPIC -o module.so -g -Wall module.c

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

Однако я не могу получить доступ к (экспортированным) функциям, которые находятся в самом исполняемом файле (я получаю undefined symbol ошибок).

Мой звонок на dlopen выглядит так:

void *handle = dlopen(plugin, RTLD_NOW);

Может кто-нибудь сообщить, как мой модуль может вызывать мой исполняемый файл без необходимости помещать все служебные функции исполняемого файла в еще одну общую библиотеку?

Ответы [ 3 ]

30 голосов
/ 27 января 2009

Правильным решением является добавление -rdynamic к команде ссылки основного исполняемого файла. Это добавит соответствующую опцию к ld (которая при использовании GNU ld оказывается --export-dynamic).

Добавление --export-dynamic напрямую технически некорректно: это опция компоновщика, поэтому его следует добавить как -Wl,--export-dynamic или -Wl,-E. Это также менее переносимо, чем -rdynamic (другие компоновщики имеют эквивалент, но сама опция отличается).

5 голосов
/ 26 января 2009

Я нашел ответ сам.

Мне пришлось добавить флаги --export-dynamic к параметрам ссылки для основного исполняемого файла.

При создании динамически связанного добавьте все символы в динамическая таблица символов. Динамический таблица символов представляет собой набор символов которые видны из динамических объектов во время выполнения.

Если вы не используете эту опцию, динамическая таблица символов будет нормально содержат только те символы, которые ссылка на какой-то динамический объект упоминается в ссылке.

Если вы используете «dlopen» для загрузки динамического объект, который должен ссылаться на символы, определенные программой, а не какой-то другой динамический объект, тогда вам, вероятно, нужно будет использовать эта опция при связывании программы сам по себе.

4 голосов
/ 30 августа 2009

Когда я столкнулся с той же проблемой, я просто использовал следующее решение. Перед загрузкой любого плагина просто загрузите саму программу, перенеся ее символы в динамические таблицы:

dlopen(NULL,RTLD_NOW|RTLD_GLOBAL);

Я думаю, что решение лучше. Причина в том, что он также решает ту же проблему, если вы

a) ваша программа (или сторонний модуль) связана (не во время выполнения) с общей библиотекой, символы которой должны быть в динамической таблице;

b) не может перекомпилировать этот модуль с флагом -rdynamic.

...