LINUX.ORG.RU

Странное поведение so (она же dll) на linux-е

 ,


0

3

Есть OS Fedora на виртуалке. Собираю свой проект, который использует библиотеку freetype. Сам freetype установлен, но мне надо, чтобы использовалась именно libfreetype.so, которая помещена мною в каталог проекта. Проблема в том, что когда проект собирается, то линковщик действительно ищет эту библиотеку в папке проекта, но при запуске собранного файла ему мой libfreetype.so становится не нужен. Я пробовал переименовывать эту свою libfreetype.so в 1.so и тогда проект не собирается, т.е. надо внести изменения и в проект, т.е. тоже там вписать 1.so. Тогда сборка проходит, но после этого 1.so можно вообще удалять - программа всё равно запускается. И я не понимаю, в чем тут дело. Конечно есть варианты: либо у меня эта so каким-то образом является статической, либо она-таки «смотрит» на установленную версию freetype-а.

Если кто-то знает, как это всё в тонкостях работает на linux-ах, то буду рад послушать. Кстати, если кто-то знает, как корректно удалить установленный freetype с Fedor-ы, то это тоже полезная информация.

Нужно при запуске задавать переменную LD_LIBRARY_PATH (см. man ld-linux). Либо при линковке указавывать параметр -Wl,-rpath,<путь к .so> (см. man gcc, man ld).

annulen ★★★★★
()

алгоритм поиска зависимостей у runtime линковщика на юниксах отличается от винды

lovesan ★★
()
Ответ на: комментарий от annulen

Выполнил ldd . В списке вижу: libfreetype.so.6 => /lib64/libfreetype.so.6 (0x00007f34e6f6c000) Это явно оно. Да, связывается библиотека, установленная в системе. Я пробовал добавить в Code::blocks в область дополнительных настроек линкера строчку: -Wl,-rpath=.,libfreetype.so (там было множество вариантов, но этот последний и тоже ничего не меняет). Или надо к библиотеке указывать абсолютный путь ? Ну… это уж совсем невесело.

Odin_KG
() автор топика
Ответ на: комментарий от Odin_KG

Я пробовал добавить в Code::blocks в область дополнительных настроек линкера строчку: -Wl,-rpath=.,libfreetype.so (там было множество вариантов, но этот последний и тоже ничего не меняет). Или надо к библиотеке указывать абсолютный путь

Если под точкой имеется в виду тот же каталог, где лежит бинарник, то вместо точки надо использовать $ORIGIN

Пример: -Wl,-rpath,$ORIGIN. Как это правильно делать в Code::blocks я понятия не имею, привожу, как это должно выглядеть в команде вызова gcc/g++, которую наверняка можно увидеть в логе сборки где-то в конце.

Если посмотреть на бинарник с помощью objdump -p, то в заголовке RUNPATH после этого должен стоять $ORIGIN.

annulen ★★★★★
()
Ответ на: комментарий от annulen

Удалось добиться того, чтобы objdump -p выдавал в RPATH значение $ORIGIN.На Code::blocks для этого используется странная конструкция:-Wl,–rpath=\$$$ORIGIN Но вроде теперь сработало.

Проблема в том, что опять это ни на что не повлияло - связь идет с системной версией freetype. Может быть проблема в том, что я использую ещё и wxWidgets, который уже именно установлен, а не в виде отдельной библиотеки ?

Odin_KG
() автор топика
Ответ на: комментарий от annulen

Ещё такой вопрос… этот RPATH=$ORIGIN указывает запускаемой программе, что первым делом надо искать so в своей папке ? Получается, что потом поиск будет происходить уже в системных папках, поэтому удаляй/не удаляй я эту so всё равно программа запуститься. Я правильно понимаю этот момент ? Если да, то как можно удалить freetype, ну или хотя бы временно отключить, чтобы он подставлял свои so ?

Odin_KG
() автор топика
Ответ на: комментарий от Odin_KG

А можно для вашей версии freetype посмотреть objdump -p libfreetype.so | grep SONAME?

Может быть проблема в том, что я использую ещё и wxWidgets, который уже именно установлен, а не в виде отдельной библиотеки ?

Это не очень здорово, и может даже всё сломать, если wxWidgets линкуется с бинарно несовместимой версией freetype. Но загружаться должна ваша версия, если она раньше идёт в путях поиска (что обеспечивает RUNPATH) и у неё подходящий SONAME.

annulen ★★★★★
()
Ответ на: комментарий от Odin_KG

Ещё такой вопрос… этот RPATH=$ORIGIN указывает запускаемой программе, что первым делом надо искать so в своей папке ?

Да, прямо как в Windows.

Получается, что потом поиск будет происходить уже в системных папках, поэтому удаляй/не удаляй я эту so всё равно программа запуститься. Я правильно понимаю этот момент ?

Да.

Если да, то как можно удалить freetype, ну или хотя бы временно отключить, чтобы он подставлял свои so ?

Если удалить системный freetype, то у вас развалится весь графический интерфейс. Оно точно вам надо?

annulen ★★★★★
()
Ответ на: комментарий от Odin_KG

Если прям так хочется убедиться, что именно ваш freetype загружается, то можете воспользоваться переменной LD_PRELOAD

annulen ★★★★★
()

so (она же dll)

Да ладно! А то мы не знали.

intelfx ★★★★★
()
Ответ на: комментарий от annulen

А можно для вашей версии freetype посмотреть objdump -p libfreetype.so | grep SONAME?

Да, конечно: libfreetype.so.6

«Если удалить системный freetype, то у вас развалится весь графический интерфейс.»

О как… похоже я чего-то не понимаю. Т.е. вы хотите сказать, что этот freetype стоит на всех Unix-ах ? Если это так, то вопрос можно вообще снять, потому что у меня как раз проблема в том, чтобы этот freetype предоставить пользователю, и решаю я эту проблему способами из Windows, т.е. через таскание его с собой в виде библиотеки.

Я только понятия не имею, какая версия freetype-а для меня является минимальной.

Odin_KG
() автор топика
Ответ на: комментарий от Odin_KG

Т.е. вы хотите сказать, что этот freetype стоит на всех Unix-ах ?

Ну если мы говорим про современные (из этого тысячелетия) системы с графическим интерфейсом, то да — его использует и Xorg, и все популярные GUI-тулкиты.

Но если речь зашла про Unix, то про $ORIGIN лучше забыть, это линуксизм. Единственный портабельный способ грузить свои библиотеки на любой ELF-системе — делать скрипт для запуска, в котором задавать LD_LIBRARY_PATH в абсолютном виде.

Ну и макось во все эти рассуждения не входит, она хоть и Юникс, но не ELF-система, и freetype в ней из коробки нет, и rpath немного по-другому работает

annulen ★★★★★
()
Ответ на: комментарий от annulen

$ORIGIN описан в System V ABI, это не линуксизм.

iliyap ★★★★★
()
Ответ на: комментарий от annulen

Меня устраивает, что в linux-ах можно предполагать наличие freetype по умолчанию. Тогда я просто выкину свою библиотеку из папки проекта и, собственно, всё. Правда, мне видимо придется ещё разбираться с пакетами установки. Насчет MAC-а я в курсе. Но там реально можно библиотеку класть в папку проекта. Правда, насколько я помню, там какое-то странное решение… внутри библиотеки есть путь, по которому она должна лежать и работать (иначе она просто игнорируется). Но этот путь, по счастью, можно поменять на вариант «там где сейчас лежит». Кто этот «полёт инженерной мысли» изобрёл, я не знаю, но вот так оно есть. И тоже просто так это не сообразить, потому что логики в этом особой не видно.

Я благодарю вас за советы и помощь! Мне самому было бы куда труднее сообразить, что всё гораздо проще.

Odin_KG
() автор топика
Ответ на: комментарий от annulen

в заголовке RUNPATH после этого должен стоять $ORIGIN

Llama3: «описание атрибута RUNPATH и использования переменной $ORIGIN можно найти в документе «System V Application Binary Interface» (также известном как «System V ABI»), в разделе «5.2 Dynamic Section», пункт 5.2.5. Этот документ является основной спецификацией ELF и описывает формат исполняемых файлов и динамических библиотек для Unix-подобных систем. В этом документе описаны общие требования к формату ELF, которые применяются ко всем архитектурам»

документ
2024-06-03, System V Application Binary Interface. AMD64 ABI 1.0
такого пункта не содержит

https://wiki.osdev.org/System_V_ABI
https://www.sco.com/developers/gabi/latest/contents.html
А этот документ ненумерованный.

DT_RUNPATH
This element holds the string table offset of a null-terminated library search path string discussed in «Shared Object Dependencies». The offset is an index into the table recorded in the DT_STRTAB entry.

DF_ORIGIN
This flag signifies that the object being loaded may make reference to the $ORIGIN substitution string (see «Substitution Sequences»). The dynamic linker must determine the pathname of the object containing this entry when the object is loaded.

«Within a string provided by dynamic array entries with the DT_NEEDED or DT_RUNPATH tags and in pathnames passed as parameters to the dlopen() routine, a dollar sign ($) introduces a substitution sequence. This sequence consists of the dollar sign immediately followed by either the longest name sequence or a name contained within left and right braces ({) and (}). A name is a sequence of bytes that start with either a letter or an underscore followed by zero or more letters, digits or underscores. If a dollar sign is not immediately followed by a name or a brace-enclosed name, the behavior of the dynamic linker is unspecified.»

If the name is ORIGIN, then the substitution sequence is replaced by the dynamic linker with the absolute pathname of the directory in which the object containing the substitution sequence originated. Moreover, the pathname will contain no symbolic links or use of . or .. components. Otherwise (when the name is not ORIGIN) the behavior of the dynamic linker is unspecified.

Shushundr ★★★
()
Последнее исправление: Shushundr (всего исправлений: 1)

Поведение не странное. Странно то что вы пытаетесь делать пытаясь подменять библиотеку.

anonymous
()

patchelf –add-rpath

anonymous
()

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

anonymous2 ★★★★★
()
Для того чтобы оставить комментарий войдите или зарегистрируйтесь.