Выборочное статическое подключение библиотечных функций в общей библиотеке

Я не знаю, назвал ли я его готовым к производству, но существует jGABL.

7
задан KlaxSmashing 7 December 2009 в 19:34
поделиться

3 ответа

Следующие пункты пытаются ответить на поставленные мной вопросы:

  • ld не кажется чтобы вы могли не связывать определенные символы из статической библиотеки. Использование - just-symbols или - undefined (или команды сценария компоновщика EXTERN ) не препятствует связыванию ld символы.
  • Для преобразования статической библиотеки, libfoobar.a , в общую, libfoobar.so.1.0 , и экспорта всех видимых символов. Вы также можете использовать - version-script и другие методы для экспорта только подмножества символов.

    ld -shared -soname libfoobar.so.1 -o libfoobar.so.1.0 --whole- архив libfoobar.a --no-whole-archive

  • Лучше удалить членов архива из копии вашей статической библиотеки, чем извлекать их, потому что они могут быть внутренние зависимости, которыми вы должны управлять. Например, если вы экспортируете все символы, вы можете создать файл карты из основного исполняемого файла. Затем вы можете использовать grep для всех членов архива, которые исполняемый файл извлек из копии статической библиотеки, и удалить их из копии. Поэтому, когда ваш DSO связывается со статической библиотекой, он оставит те же символы неразрешенными.

  • Можно указать ваш основной исполняемый файл как разделяемую библиотеку для вашего DSO, если вы скомпилируете исполняемый файл с - pie вариант. Ваш DSO сначала свяжется с вашим исполняемым файлом, если он предшествует статической библиотеке в команде связывания. Предостережение: основной исполняемый файл должен быть доступен через LD_LIBRARY_PATH или -rpath . Кроме того, использование strace показывает, что, поскольку исполняемый файл является зависимостью вашей библиотеки, он загружается снова при загрузке вашего DSO.

    ld -shared -rpath ' $ ORIGIN '-L. -lc -ldl -o DSO.so DSO.o app libfoobar.a

  • Динамический компоновщик сначала будет использовать версию исполняемого файла foo , если только вы не вызовете dlopen () с Флаг RTLD_DEEPBIND . Использование strace показывает, что весь DSO является файлом, отображаемым mmap2 () в память. Однако Википедия утверждает, что для mmap «фактическое чтение с диска выполняется« ленивым »способом после обращения к определенному месту». Если это правда, то дубликат foo не будет загружен. Обратите внимание, что переопределение происходит только в том случае, если ваш DSO экспортировал функцию foo . В противном случае функция foo , которая была статически связана с вашим DSO, будет использоваться всякий раз, когда ваш DSO вызывает foo .

4
ответ дан 7 December 2019 в 10:03
поделиться

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

Если я правильно угадаю, что вы пытаетесь сделать, просто свяжите свой общий lib против libc.so. Вы не хотите, чтобы в вашу библиотеку была встроена дополнительная копия sscanf.

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

Есть ли способ указать ld разрешать только определенные символы при построении разделяемой библиотеки?

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

Когда вы создаете свою общую библиотеку, любые символы, не найденные в объекты в командной строке компоновщика останутся неразрешенными. Если компоновщик жалуется на это, возможно, вам нужно связать вашу общую библиотеку с общей libc. У вас есть настроенная версия sprintf / sscanf, или будет ли ваша общая библиотека использовать реализацию в -lc? Если -lc в порядке, то мой ответ, вероятно, решит вашу проблему. Если нет, то вам нужно построить свою общую библиотеку из объектов, которые имеют только необходимые вам функции. т.е. не связывайте его с /usr/lib/libc.a.

Может быть, меня смущает ваша

libc.a (на самом деле не "настоящая" libc) линия. /usr/lib/libc.a - это действительно glibc (в Linux). Это статически связанная копия того же кода в libc.so. Если вы не говорите о вашей собственной libc.a (о чем я думал сначала) ...

Превратить libc.a в общую библиотеку? Вы, вероятно, можете, но не можете, потому что он, вероятно, не скомпилирован как независимый от позиции код, поэтому ld.so потребует много перемещений во время выполнения.

Извлеките sscanf из libc.a и укажите это в Линия компоновщика?

Может быть. ar t /usr/lib/libc.a, чтобы просмотреть содержимое. (args похожи на tar. tar был ar для лент ... Старая школа Unix здесь.) Наверное, не так просто, потому что sscanf, вероятно, зависит от символов в других файлах .o в .a.

1
ответ дан 7 December 2019 в 10:03
поделиться

Отвечая на ваш исправленный более ясный вопрос.

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

Если это всего лишь пара небольших функций, возможно, вам стоит оставить это в покое. Вы, вероятно, получите две копии кода для функций, одну в вашей shlib и одну в основной программе. Если они маленькие (или, по крайней мере, не огромные) или вызываются не часто и не критичны к производительности, то попадание в размер кода / I-кеш из-за наличия двух копий не является поводом для беспокойства. (перевод: я не знаю, как этого избежать, это слетело с моей головы, так что я мог бы не тратить время на то, чтобы найти его и сделать более сложный Makefile, чтобы избежать этого.)

См. мой другой ответ для некоторых комментариев о том, как возиться с ar для извлечения материалов из статической библиотеки. Резюме: вероятно, нетривиально, поскольку вы не знаете зависимости между различными файлами .o в .a.

Возможно, удастся сделать то, на что вы надеетесь, если ваша общая библиотека будет экспортировать символы, которые он извлекается из статической библиотеки. Затем, когда вы связываете основное приложение, поместите вашу общую библиотеку перед статической библиотекой в ​​командной строке компоновщика. ld найдет "foo" в вашей shlib и будет использовать эту копию (если этот трюк с повторным экспортом возможен), но для "bar" он должен будет включить копию из статической библиотеки.

ld --export- dynamic может быть тем, что вам нужно для экспорта всех символов в динамической таблице символов. Попробуй это. И найдите «экспорт» на странице документации / руководства. «экспорт» - это жаргон, обозначающий отображение символа в библиотеке. --export-all-symbols находится в разделе i386 PE (Windows DLL), иначе это, вероятно, помогло бы.

1
ответ дан 7 December 2019 в 10:03
поделиться
Другие вопросы по тегам:

Похожие вопросы: