Записывается внутри самого двоичного файла приложения (указывается во время компиляции, точнее на шаге соединения, выполняется с помощью 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.