Як може динамічний зв’язок / завантажувач сам динамічно пов'язаний, як повідомляється у файлі?


12

Розглянемо спільні об'єктні залежності /bin/bash, що включає /lib64/ld-linux-x86-64.so.2(динамічний лінкер / завантажувач):

ldd /bin/bash
    linux-vdso.so.1 (0x00007fffd0887000)
    libtinfo.so.6 => /lib/x86_64-linux-gnu/libtinfo.so.6 (0x00007f57a04e3000)
    libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f57a04de000)
    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f57a031d000)
    /lib64/ld-linux-x86-64.so.2 (0x00007f57a0652000)

Перевірка /lib64/ld-linux-x86-64.so.2показує, що це символьне посилання на /lib/x86_64-linux-gnu/ld-2.28.so:

ls -la /lib64/ld-linux-x86-64.so.2 
lrwxrwxrwx 1 root root 32 May  1 19:24 /lib64/ld-linux-x86-64.so.2 -> /lib/x86_64-linux-gnu/ld-2.28.so

Крім того, fileзвіти /lib/x86_64-linux-gnu/ld-2.28.soдля себе динамічно пов'язані:

file -L /lib64/ld-linux-x86-64.so.2
/lib64/ld-linux-x86-64.so.2: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, BuildID[sha1]=f25dfd7b95be4ba386fd71080accae8c0732b711, stripped

Я хотів би знати:

  1. Як можна /lib64/ld-linux-x86-64.so.2динамічно пов'язати сам динамічний лінкер / завантажувач ( )? Це пов'язує себе під час виконання?
  2. /lib/x86_64-linux-gnu/ld-2.28.soдокументовано для обробки a.out бінарних файлів ( man ld.so), але /bin/bashчи виконується ELF?

Програма ld.so обробляє a.out бінарні файли, формат, що використовується давно; ld-linux.so * (/lib/ld-linux.so.1 для libc5, /lib/ld-linux.so.2 для glibc2) використовує ELF, яким всі користуються вже роками.


Ядро не піклується про такі тонкі таксономічні тонкощі (і вам також не варто ;-)). Ядро робить різницю лише між ELF, яким потрібен перекладач, і тими, які не мають. І AFAIK, ви не можете використовувати перекладача, який сам потрібен.
mosvy

@StephenKitt міна не ( /lib/x86_64-linux-gnu/ld-2.28.so, debian 10 buster)
mosvy

@mosvy Так, вибачте, я змішався між fileпомилковим коментарем про те, як він визначає статичні двійкові файли, і реальністю ld-2.28.so... Диференціатор є PT_DYNAMIC.
Стівен Кітт

Відповіді:


17
  1. Так, він пов'язує себе, коли ініціалізується. Технічно динамічний лінкер не потребує роздільної здатності об'єкта та переїзду для себе, оскільки він повністю вирішений як є, але він визначає символи, і він повинен подбати про тих, коли розв’язує двійковий, що його "інтерпретує", і ці символи оновлюються щоб вказати на їх реалізацію в завантажених бібліотеках. Зокрема, це впливає malloc- у лінкера є вбудована мінімальна версія з відповідним символом, але його замінюють версією бібліотеки С після її завантаження та переміщення (або навіть заміщеної версії, якщо така є), з деякою обережністю щоб переконатися, що цього не відбувається в момент, коли це може зламати лінкер.

    Закривавлені деталі знаходяться в rtld.c, в dl_mainфункції.

    Зауважте, що ld.soце не має зовнішніх залежностей. Ви можете бачити символи, з якими пов'язано nm -D; жоден з них не визначений.

  2. Роздільна сторінка стосується записів безпосередньо під /lib, тобто /lib/ld.so (динамічний лінкер libc 5, який підтримує a.out) та /lib*/ld-linux*.so*(динамічний лінкер libc 6, який підтримує ELF). Сторінка дуже конкретна, і ld.soні ld-2.28.so.

    Динамічний лінкер, знайдений на переважній більшості сучасних систем, не a.outпідтримує.

fileі lddповідомляти про різні речі для динамічного лінкера, оскільки вони мають різні визначення того, що являє собою статично пов'язаний двійковий файл. Бо lddдвійковий файл є статично пов'язаним, якщо він не має DT_NEEDEDсимволів, тобто не визначених символів. Наприклад file, бінарний файл ELF є статично пов'язаним, якщо він не має PT_DYNAMICрозділу (це зміниться у випуску fileнаступного 5.37; тепер він використовує наявність PT_INTERPрозділу як індикатор динамічно пов'язаного бінарного файлу, який відповідає коментарю в код).

Динамічний лінкер бібліотеки GNU C не містить DT_NEEDEDсимволів, але в ньому є PT_DYNAMICрозділ (оскільки технічно це спільна бібліотека). Як результат, ldd(який є динамічним лінкером) вказує, що він статично пов'язаний, але fileвказує, що він динамічно пов'язаний. У ньому немає PT_INTERPрозділу, тому наступний випуск fileтакож вказуватиме на те, що він статично пов'язаний.

$ ldd /lib64/ld-linux-x86-64.so.2
        statically linked

$ file $(readlink /lib64/ld-linux-x86-64.so.2)
/lib/x86_64-linux-gnu/ld-2.28.so: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, BuildID[sha1]=f25dfd7b95be4ba386fd71080accae8c0732b711, stripped

file5.35)

$ file $(readlink /lib64/ld-linux-x86-64.so.2)
/lib/x86_64-linux-gnu/ld-2.28.so: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), statically linked, BuildID[sha1]=f25dfd7b95be4ba386fd71080accae8c0732b711, stripped

(з версією, що наразі розробляється file).


Чому слово "інтерпретація" використовується в контексті динамічного зв'язку? Це слово зазвичай використовується в контексті мов програмування.
Shuzheng

Що ви маєте на увазі під динамічним зв’язком бібліотеки GNU C? Ви маєте на увазі /lib*/ld-linux*.so*або третій динамічний лінкер?
Shuzheng

Де ви можете бачити lddзвіти про динамічний лінкер як статично пов'язаний? Оскільки список спільних залежностей об'єкта порожній?
Shuzheng

Програми, що динамічно пов'язані, потребують певної роботи перед виконанням; ця робота проводиться динамічним лінкером, який в кінцевому підсумку відіграє аналогічну роль інтерпретатора - він інтерпретує таблиці переміщення тощо, щоб створити те, що може працювати комп'ютер.
Стівен Кітт

Коли я кажу "Динамічний лінкер бібліотеки GNU C", я маю на увазі реалізацію, включену в бібліотеку GNU C, яка зазвичай постачається як /lib*/ld-linux*.so*. Я вказав походження динамічного лінкера, оскільки для Linux існують інші реалізації.
Стівен Кітт

0
  1. Я підозрюю, що fileпрограма помиляється з приводу того, що динамічний зв’язок / завантажувач динамічно пов'язаний між собою. lddПрограма не згоден. Принаймні, не в моїй системі (Debian Stretch):

    ldd /lib/x86_64-linux-gnu/ld-2.24.so
        statically linked
    
  2. man ld.soтакож читає: "ld-linux.so * обробляє ELF" . У вашій системі (і в мене теж до речі) обидва є символьними посиланнями на один і той же двійковий код, який я вважаю, здатний обробляти як ELF, так і (старий застарілий) формат a.out.


яку інформацію ви додаєте до прийнятої відповіді?
чудо173

2
@ miracle173 ця відповідь старша за прийняту відповідь ;-).
Стівен Кітт

ти правий. Я пропустив це. Я думав, що питання і прийнята відповідь дуже старі, і ця відповідь була розміщена в останні години. Я не можу скасувати свою позицію, поки хтось не змінить публікацію.
чудо173
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.