Получена ошибка "неопределенный символ" при загрузке библиотеки с помощью 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.