Как сделать функцию C динамически экспортируемой

Мое приложение работает со статической библиотекой, которая имеет API расширений. API может вызывать функцию инициализации расширения из внешней общей библиотеки или из «локального» двоичного файла. То есть я могу статически включить функцию инициализации расширения в основной исполняемый файл.

Локальная функция ищется вызовом dlsym, а функция инициализации должна динамически экспортироваться из основного бинарного файла. Это следующий вызов nm:

nm -CD <binary>

должен перечислить мою функцию инициализации.

Предположим, что функция инициализации имеет такую ​​подпись:

int init_func(INIT_STRUCT *);

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

Итак, у меня есть два связанных вопроса:

  1. как заставить компоновщика не исключать эту функцию из сгенерированного бинарника?
  2. как заставить компилятор/компоновщик динамически экспортировать эту функцию?

(Я использую gcc для компиляции и компоновки моей программы)


person igor.sol    schedule 21.06.2018    source источник


Ответы (2)


К сожалению, по умолчанию набор инструментов GNU не экспортирует символы из исполняемых файлов по умолчанию (в отличие от общих библиотек, которые по умолчанию экспортируют все свои символы). Вы можете использовать флаг -rdynamic большого молота, который указывает компоновщику экспортировать все символы из вашего исполняемого файла. Менее навязчивым решением было бы предоставить явный файл экспорта через -Wl,--dynamic-list при связывании (см. пример использования в Исходники Clang).

person yugr    schedule 21.06.2018
comment
Спасибо Вам за информацию. Теперь я использую -rdynamic. К сожалению, чтобы избежать исключения функции инициализации линкером, мне нужно явно указать ее в коде. Что-то вроде этого: void* unused = &extension_init; (void)(unused); Было бы здорово иметь лучший способ. - person igor.sol; 22.06.2018
comment
@igor.sol Вы связываете extension_init со статической библиотекой? В этом случае компоновщик не будет связывать объектный файл, если нет ссылки, если вы не окружите -lxyz -Wl,--start-group и -Wl,--end-group. - person yugr; 22.06.2018
comment
@yugr Окружение -lxyz с помощью --{start,end}-group не влияет на то, втягивается ли объект в ссылку или нет. Вам нужны --whole-archive и --no-whole-archive. - person Employed Russian; 24.06.2018
comment
Для одной функции более простым решением является добавление -uextension_init к строке ссылки. - person Employed Russian; 24.06.2018
comment
@EmployedRussian Спасибо, исправлено. Можете ли вы сделать свое последнее предложение ответом, чтобы мы могли +1 к нему? - person yugr; 25.06.2018

Хорошо, я отправлю ответ на основе предыдущих комментариев.

Чтобы все функции экспортировались динамически: -rdynamic.

Чтобы одна функция всегда была связана (даже если на нее не ссылались), вам нужно добавить -u<function> в строку ссылки.

Чтобы связать все функции (даже без ссылок), используйте --whole-archive. Чтобы вернуться к обычному связыванию, используйте --no-whole-archive

person igor.sol    schedule 02.08.2018