Получена ошибка "неопределенный символ" при загрузке библиотеки с помощью dlopen

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

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

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

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

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

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

void *handle = dlopen(plugin, RTLD_NOW);

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

3 ответа

Решение

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

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

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

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

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

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

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

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

dlopen(NULL,RTLD_NOW|RTLD_GLOBAL);

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

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

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

Другие вопросы по тегам