Понимание вывода ldd - PullRequest
       65

Понимание вывода ldd

13 голосов
/ 05 апреля 2011

Как ldd узнает, что это зависит от libc.so.6, а не libc.so.5 или libc.so.7?

libc.so.6 => /lib64/libc.so.6 (0x00000034f4000000)
/lib64/ld-linux-x86-64.so.2 (0x00000034f3c00000)

Ответы [ 2 ]

17 голосов
/ 05 апреля 2011

Записывается внутри самого двоичного файла приложения (указывается во время компиляции, точнее на шаге соединения, выполняется с помощью ld):

$ readelf -d /bin/echo

Dynamic section at offset 0x5f1c contains 21 entries:
  Tag        Type                         Name/Value
 0x00000001 (NEEDED)                     Shared library: [libc.so.6]
...

(есть некоторые дополнительные столбцы для того, как elf хранит информацию в динамическом разделе. Но вы можете видеть, что libc.so.6 жестко закодирован суффиксом .6 из-за SONAME )

или даже без знания формата файла ELF:

$ strings /bin/echo |grep libc.so
libc.so.6

Чтобы узнать, как компоновщик находит библиотеку (это делается на последнем этапе компиляции), используйте gcc параметр -Wl,--verbose (при этом gcc просит передать параметр --verbose в ld):

$ gcc a.c -Wl,--verbose

...
attempt to open /usr/lib/gcc/i686-pc-linux-gnu/4.4.4/libc.so failed
attempt to open /usr/lib/gcc/i686-pc-linux-gnu/4.4.4/libc.a failed
attempt to open /usr/lib/gcc/i686-pc-linux-gnu/4.4.4/libc.so failed
attempt to open /usr/lib/gcc/i686-pc-linux-gnu/4.4.4/libc.a failed
attempt to open /usr/lib/gcc/i686-pc-linux-gnu/4.4.4/../../../libc.so succeeded
opened script file /usr/lib/gcc/i686-pc-linux-gnu/4.4.4/../../../libc.so
opened script file /usr/lib/gcc/i686-pc-linux-gnu/4.4.4/../../../libc.so
attempt to open /lib/libc.so.6 succeeded
/lib/libc.so.6

Линкер не знает ничего о суффиксе .digit, он просто перебирает все каталоги поиска библиотеки, пытаясь открыть libLIBNAME.so и libLIBNAME.a, где LIBNAME - строка после опции -l. (-lc опция добавлена ​​по умолчанию).

Первый успех - /usr/lib/libc.so, который сам по себе не библиотека, а скрипт компоновщика (текстовый файл). Вот содержимое типичного libc.so скрипта:

$ cat /usr/lib/libc.so
/* GNU ld script
   Use the shared library, but some functions are only in
   the static library, so try that secondarily.  */
OUTPUT_FORMAT(elf32-i386)
GROUP ( /lib/libc.so.6 /usr/lib/libc_nonshared.a  AS_NEEDED ( /lib/ld-linux.so.2 ) )

Итак, скрипт /usr/lib/libc.so найден раньше, чем фактическая библиотека, и этот скрипт говорит, какой файл будет связан, libc.so.6 в данном случае.

В более общем случае lib___.so является символической ссылкой на некоторую версию, такую ​​как lib___.so.3.4.5, и есть поле SONAME, заполненное в lib___.so.3.4.5, которое говорит ld ссылку не на lib___.so, а на lib___.so.3.4, что является другим символическая ссылка на lib___.so.3.4.5. Имя .3.4 будет записано в двоичном поле NEEDED.

4 голосов
/ 06 апреля 2012

http://www.sco.com/developers/gabi/latest/ch5.dynamic.html#dynamic_section

Имеет значение каждого динамического тега.1 указывает, что это тег DT_NEEDED, означающий, что в этом случае структура

typedef struct {
    Elf32_Sword d_tag;
    union {
        Elf32_Word  d_val;
        Elf32_Addr  d_ptr;
    } d_un;
} Elf32_Dyn;

имеет допустимое объединение d_val и ищет смещение, указанное этим членом объединения в таблице DT_STRTAB, чтобы найти имя библиотеки, в которой находится этот двоичный файл/ SO зависит от.

...