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

Как 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)

Ответы

Ответ 1

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

$ readelf -d /bin/echo

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

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

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

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

Чтобы найти, как компоновщик находит библиотеку (это делается на последнем этапе компиляции), используйте gcc option -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

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

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

$ 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 ) )

Итак, script /usr/lib/libc.so найден раньше, чем фактическая библиотека, и этот script говорит, какой файл будет связан, 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 двоичного файла.

Ответ 2

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 union valid и ищет смещение, указанное членом thi union в таблице DT_STRTAB, чтобы найти имя библиотеки, от которой зависит этот двоичный файл/SO.