Получать ошибку "undefined" при загрузке библиотеки с помощью dlopen
Я пишу код, который использует динамические общие библиотеки в качестве плагинов.
Моя командная строка для создания разделяемых библиотек выглядит так:
cc -shared -fPIC -o module.so -g -Wall module.c
Внутри модуля я могу вызывать функции, которые находятся в любой другой разделяемой библиотеке, загруженной в основной исполняемый файл.
Однако я не могу получить (экспортированные) функции, которые находятся в самом исполняемом файле (я получаю ошибки undefined symbol
).
Мой вызов dlopen
выглядит следующим образом:
void *handle = dlopen(plugin, RTLD_NOW);
Кто-нибудь может посоветовать, как мой модуль может вернуться к моему исполняемому файлу, без необходимости включать все исполняемые служебные функции в еще одну общую библиотеку?
Ответы
Ответ 1
Я сам нашел ответ.
Мне пришлось добавить флаги --export-dynamic
к параметрам ссылок для основного исполняемого файла.
При создании динамически связанных исполняемый файл, добавьте все символы в динамическая таблица символов. Динамический таблица символов - это набор символов которые видны из динамических объектов во время выполнения.
Если вы не используете эту опцию, таблица динамических символов обычно содержат только те символы, которые ссылка на какой-либо динамический объект упомянутых в ссылке.
Если вы используете "dlopen" для загрузки динамического объект, который должен символы, определенные программой, а не какой-либо другой динамический объект, то вам, вероятно, понадобится использовать этот параметр при связывании программы сам по себе.
Ответ 2
Правильное решение - добавить -rdynamic
в команду связи основного исполняемого файла. Это добавит соответствующую опцию ld
(которая при использовании GNU ld
оказывается --export-dynamic
).
Добавление --export-dynamic
напрямую технически неверно: это вариант компоновщика, и поэтому его следует добавить как -Wl,--export-dynamic
или -Wl,-E
. Это также менее переносимо, чем -rdynamic
(другие линкеры имеют эквивалент, но сам вариант отличается).
Ответ 3
Когда я столкнулся с той же проблемой, я просто использовал следующее решение. Перед загрузкой любого плагина просто загрузите саму программу, приведя ее символы в динамические таблицы:
dlopen(NULL,RTLD_NOW|RTLD_GLOBAL);
Я думаю, что решение лучше. Причина в том, что он также решает ту же проблему, если вы
a) ваша программа (или модуль третьей стороны) связана (не во время выполнения) с общей библиотекой, какие символы должны быть в динамической таблице;
b) не может перекомпилировать этот модуль с флагом -rdynamic.