Расхождение в поведении загрузчиков Linux (ld-linux-x86-64) между Glibc 2.12 и Glibc 2.17 - PullRequest
0 голосов
/ 11 октября 2018

Я пытаюсь скомпилировать одну и ту же библиотеку на двух разных машинах x86.Оба используют один и тот же набор инструментов (точно такой же набор файлов), но имеют разные версии Glibc.

Когда я запускаю команду LD_DEBUG=libs /lib64/ld-linux-x86-64.so.2 --list ./libl2ps.so, я замечаю следующее расхождение между двумя загрузчиками Linux:

Машина 1 (с Glibc 2.12):

 19943: find library=libm.so.6 [0]; searching
 19943:  search path=/ebs/frperies/repo/gnb/uplane/build/prefix-root/asik-x86_64-ps_lfs-dynamic-linker-on/toolchain/sysroots/core2-64-pc-linux-gnu/usr/lib64:...:/ebs/frperies/repo/gnb/uplane/build_bbp/l2_ps/build/.      (RPATH from file ./libl2ps.so)
 19943:   trying file=/ebs/frperies/repo/gnb/uplane/build/prefix-root/asik-x86_64-ps_lfs-dynamic-linker-on/toolchain/sysroots/core2-64-pc-linux-gnu/usr/lib64/libm.so.6
 19943: 
 19943: find library=libgcc_s.so.1 [0]; searching
 ...

В этом случае загрузчик Linux выбирает lib libm.so.6 из пути цепочки инструментов на основе RPATH lib libl2ps.so.

Машина 2 (с Glibc 2.17):

 10699: find library=libm.so.6 [0]; searching
 10699:  search path=/home/frperies/repo/gnb/uplane/build/prefix-root/asik-x86_64-ps_lfs-dynamic-linker-on/toolchain/sysroots/core2-64-pc-linux-gnu/usr/lib64:/home/frperies/repo/gnb/uplane/build/prefix-root/asik-x86_64-ps_lfs-dynamic-linker-on/toolchain/sysroots/core2-64-pc-linux-gnu/lib64:/home/frperies/repo/gnb/uplane/build/prefix-root/asik-x86_64-ps_lfs-dynamic-linker-on/toolchain/sysroots/core2-64-pc-linux-gnu/usr/lib:/home/frperies/repo/gnb/uplane/build_bbp/l2_ps/build/.        (RPATH from file ./libl2ps.so)
 10699:   trying file=/home/frperies/repo/gnb/uplane/build/prefix-root/asik-x86_64-ps_lfs-dynamic-linker-on/toolchain/sysroots/core2-64-pc-linux-gnu/usr/lib64/libm.so.6
 10699:   trying file=/home/frperies/repo/gnb/uplane/build/prefix-root/asik-x86_64-ps_lfs-dynamic-linker-on/toolchain/sysroots/core2-64-pc-linux-gnu/lib64/libm.so.6
 10699:   trying file=/home/frperies/repo/gnb/uplane/build/prefix-root/asik-x86_64-ps_lfs-dynamic-linker-on/toolchain/sysroots/core2-64-pc-linux-gnu/usr/lib/libm.so.6
 10699:   trying file=/home/frperies/repo/gnb/uplane/build_bbp/l2_ps/build/./libm.so.6
 10699:  search cache=/etc/ld.so.cache
 10699:   trying file=/lib64/libm.so.6

Что касается Машины 1, загрузчик пытается с RPATH libl2ps.so выбрать lib libm.so.6 изпуть цепочки инструментов, но по какой-то причине пропустите его и попробуйте другие пути.Наконец, он выбирает libm.so.6 из системного пути /lib64/.

RPATH 2 библиотек lib2ps.so абсолютно одинаковы.Два файла libm.so.6 также абсолютно одинаковы на обеих машинах (проверено с помощью md5sum).

Я не понимаю этих различий в поведении между двумя загрузчиками Linux.Видите ли вы причину, объясняющую это несоответствие?

Большое спасибо за ваши ответы.

Обновление:

Спасибо yugr для вашего ответа.

Вывод readelf -h дает только различия в полях " Адрес точки входа " и " Начало заголовков секций " и тамдругих отличий нет, поэтому я думаю, что это не поможет.

Что касается использования dlopen() / dlerror(), я выполнил небольшой исполняемый файл со следующим оператором:

dlopen("/home/frperies/repo/gnb/uplane/build/prefix-root/asik-x86_64-ps_lfs-dynamic-linker-on/toolchain/sysroots/core2-64-pc-linux-gnu/usr/lib64/libm-2.28.so", RTLD_LAZY);

Вкл.на машине 1 он работает как положено:

C++ dlopen demo

Opening libm-2.28.so...
Closing library...

На машине 2 происходит сбой, и dlerror () выдает следующий вывод:

Cannot open library: /home/frperies/repo/gnb/uplane/build/prefix-root/asik-x86_64-ps_lfs-dynamic-linker-on/toolchain/sysroots/core2-64-pc-linux-gnu/usr/lib64/libm-2.28.so: cannot open shared object file: No such file or directory

, но файл libm-2-28.so действительно существует в моей файловой системе:

$ ls -l /home/frperies/repo/gnb/uplane/build/prefix-root/asik-x86_64-ps_lfs-dynamic-linker-on/toolchain/sysroots/core2-64-pc-linux-gnu/usr/lib64/libm-2.28.so
-rwxr-xr-x 1 frperies linseeusers_lte_espoo 1682944 Oct  5 13:50 /home/frperies/repo/gnb/uplane/build/prefix-root/asik-x86_64-ps_lfs-dynamic- linker-on/toolchain/sysroots/core2-64-pc-linux-gnu/usr/lib64/libm-2.28.so

Это очень странно, что может привести к такой ситуации ???

Спасибо

Обновление 2:

Это правда, что я не указал, что машина 1 является дистрибутивом RHEL6.8, а машина 2 - дистрибутивом RHEL7.4.Я (наивно?) Не думал, что это действительно имеет значение ...

На машине 1:

$ cat /proc/sys/kernel/osrelease
4.4.115-1.NSN.el6.x86_64

$ uname -a
Linux sq24-3 4.4.115-1.NSN.el6.x86_64 #1 SMP Mon Feb 12 12:35:46 CET 2018 x86_64 x86_64 x86_64 GNU/Linux

$ readelf -n libl2ps.so 

Notes at offset 0x00000270 with length 0x00000024:
  Owner                 Data size   Description
  GNU                  0x00000014   NT_GNU_BUILD_ID (unique build ID bitstring)
  Build ID: b598468830fdf2f61eda25553b9a367c4d28cdc9

На машине 2:

$ cat /proc/sys/kernel/osrelease
3.10.0-693.el7.x86_64

$ uname -a
Linux localhost.localdomain 3.10.0-693.el7.x86_64 #1 SMP Thu Jul 6 19:56:57 EDT 2017 x86_64 x86_64 x86_64 GNU/Linux

$ readelf -n libl2ps.so 

Displaying notes found at file offset 0x00000270 with length 0x00000024:
  Owner                 Data size   Description 
  GNU                  0x00000014   NT_GNU_BUILD_ID (unique build ID bitstring)
  Build ID: 5829181bc0502233748149369108915ea7b10e8f

Помогает ли это?

Спасибо

Обновление 3:

$ readelf -n libm.so.6 

Notes at offset 0x00000238 with length 0x00000024:
  Owner                 Data size   Description
  GNU                  0x00000014   NT_GNU_BUILD_ID (unique build ID bitstring)
  Build ID: 0d84c7247dd76008c096719043e5592735a1c4bd

Notes at offset 0x0000025c with length 0x00000020:
  Owner                 Data size   Description
  GNU                  0x00000010   NT_GNU_ABI_TAG (ABI version tag)
  OS: Linux, ABI: 4.4.0

Итак, как интерпретировать этот номер версии ABI, установленный на 4.4.0 ??

Спасибо

Спасибо, югр и Занятый русский за ваши ответы !!Я попробую обновить мою версию ядра на компьютере 2.

С уважением

1 Ответ

0 голосов
/ 12 октября 2018

Сообщение об ошибке, которое вы видите, является печально запутанным ENOENT errno.Я вижу два случая этого в dl-load.c:

Я подозреваю, что первый сбой в вашем случае означает, что ядро ​​ОС несовместимо между двумя машинами.ld.so manpage действительно говорит, что

Каждый общий объект может информировать динамический компоновщик о минимальной версии ABI ядра, которая ему требуется.(Это требование закодировано в разделе примечаний ELF, который можно просмотреть через readelf -n как раздел, помеченный как NT_GNU_ABI_TAG.) Во время выполнения динамический компоновщик определяет версию ABI работающего ядра и будет отклонять загрузку общих объектов, которые указывают минимальные версии ABI.это превышает ту версию ABI.

NT_GNU_ABI_TAG равно 4.4.0, что означает, что вы запускаете программу, ожидающую минимум 4.4 ядра на ядре 3.10.Теоретически более новый Glibc должен работать и на старых ядрах, но в вашем случае Glibc, вероятно, был собран с явным флагом --enable-kernel, который запрещает его использование в ядрах до 4.4 (см., Например, это объяснение из --enable-kernel).

В качестве обходного пути вы можете попытаться обмануть Glibc, переопределив версию ядра на компьютере 2 с помощью

export LD_ASSUME_KERNEL=4.4.0

, но это может не сработать, если libm создает специфичные для 4.4 системные вызовы, которые на самом деле не являютсяподарок на 3.10.

...