если разделяемая библиотека связана с двоичным файлом, и разделяемая библиотека также зависит от других библиотек, каковы приоритеты (порядок поиска компоновщика) для RPATH разделяемой библиотеки и RPATH для двоичного файла? Может ли RPATH двоичного файла переопределить значение в общей библиотеке? и $ ORIGIN, который я установил в общей библиотеке RPATH, относится к расположению lib или расположению двоичного файла?
Заранее спасибо.
По моим наблюдениям, если есть приложение main
который динамически загружает библиотеку first.so
а последний в свою очередь динамически загружает библиотеку second.so
и оба main
а также first.so
содержит RPATH, тогда динамический компоновщик будет искать second.so
сначала используя first.so
RPATH, решая $ ORIGIN как first.so
каталог, и только в случае сбоя компоновщик перейдет к main
RPATH теперь разрешает $ ORIGIN как main
каталог
Это не противоречит документ динамического компоновщика (ищите расширение токена Rpath):
$ ORIGIN (или эквивалентно $ {ORIGIN}): расширяется до каталога, содержащего программу или общий объект. …
Чтобы проверить это, я создал тестовое приложение и две библиотеки: main
, liba
а также libb
соответственно. main
связано с liba
, а также liba
связано с libb
:
main -> liba.so -> libb.so
Встроенные двоичные файлы расположены так:
/cwd/main
/cwd/lib/liba.so
/cwd/lib/libb.so
И то и другое main
а также liba
построены с --rpath=\$ORIGIN/lib
флаг компоновщика:
~$ readelf -a /cwd/main | grep ORIGIN
0x000000000000000f (RPATH) Library rpath: [$ORIGIN/lib]
~$ readelf -a /cwd/lib/liba.so | grep ORIGIN
0x000000000000000f (RPATH) Library rpath: [$ORIGIN/lib]
С помощью LD_DEBUG
переменная окружения Я проверил, как динамический компоновщик обрабатывает RPATH:
~$ LD_DEBUG=libs /cwd/main
: find library=liba.so [0]; searching
: search path=/cwd/lib/tls/x86_64:/cwd/lib/tls:/cwd/lib/x86_64:/cwd/lib (RPATH from file /cwd/main)
: trying file=/cwd/lib/tls/x86_64/liba.so
: trying file=/cwd/lib/tls/liba.so
: trying file=/cwd/lib/x86_64/liba.so
: trying file=/cwd/lib/liba.so
94313:
: find library=libc.so.6 [0]; searching
: search path=/cwd/lib (RPATH from file /cwd/main)
: trying file=/cwd/lib/libc.so.6
: search cache=/etc/ld.so.cache
: trying file=/lib/x86_64-linux-gnu/libc.so.6
94313:
: find library=libb.so [0]; searching
: search path=/cwd/lib/lib/tls/x86_64:/cwd/lib/lib/tls:/cwd/lib/lib/x86_64:/cwd/lib/lib (RPATH from file /cwd/lib/liba.so)
: trying file=/cwd/lib/lib/tls/x86_64/libb.so
: trying file=/cwd/lib/lib/tls/libb.so
: trying file=/cwd/lib/lib/x86_64/libb.so
: trying file=/cwd/lib/lib/libb.so
: search path=/cwd/lib (RPATH from file /cwd/main)
: trying file=/cwd/lib/libb.so
Из этого видно, что компоновщик первым сталкивается с необходимостью загрузки liba.so
и использует main
RPATH двоичного файла, чтобы решить эту проблему. Тогда он сталкивается с необходимостью загрузки libb.so
и сначала он использует liba.so
RPATH библиотеки, чтобы решить эту проблему. Но так как RPATH $ORIGIN/lib
а также libb.so
находится в том же каталоге, что и liba.so
компоновщик не может найти libb.so
с помощью liba.so
RPATH. После этого он возвращается к main
RPATH и только используя последний, он может найти libb.so
,
Тестовая среда: Linux Ubuntu 4.15.0-34-generic # 37 ~ 16.04.1-Ubuntu (64-разрядная версия), /lib/x86_64-linux-gnu/ld-2.23.so.
Других решений пока нет …