Невозможно получить список библиотек, необходимых для разрешения неопределенных символов в общем объекте, из самого общего объекта. Такой список может существовать или не существовать. Легко создать библиотеку с неопределенным символом, который не может быть разрешен ни одной из существующих в мире библиотек.
# cat test.c
extern void foo99988776543quzzu();
void test() {
foo99988776543quzzu();
}
# gcc -fPIC -shared -o libtest.so test.c
Здесь мы создали библиотеку с неопределенным символом, который не может удовлетворить ни одна другая библиотека в мире - пока мы не создадим ее.
# cat foo.c
void foo99988776543quzzu() {}
# gcc -fPIC -shared -o libfoo.so foo.c
Никакая магия в мире не может помочь ldd libtest.so
найти libfoo.so. Но легко создать загружаемую, запускаемую программу из libtest.so и libfoo.so.
# cat main.c
extern void test();
int main() { test(); }
# gcc main.c -lfoo -ltest -L. -Wl,-rpath=.
# ./a.out
ldd не пытается создать невозможный список библиотекарей, необходимых для разрешения неопределенных символов. Он делает именно то, что говорит на банке:
ldd печатает общие объекты (общие библиотеки), необходимые для каждой программы или общего объекта, указанного в командной строке.
Слово «требуется» здесь не означает «требуется для разрешения неопределенных символов». Как уже было сказано, список объектов, необходимых для разрешения неопределенных символов, не может быть создан. Вместо этого «требуется» означает набор динамических зависимостей, a.k.a. «разделяемые объекты, необходимые для рекурсивного DT_NEEDED», как подробно описано в ldd (1) и ld.so (8).
какая польза от ldd вообще?
DT_NEEDED разделы содержат sonames . ldd рекурсивно собирает эти сонамы и сопоставляет их с путями к файлам , используя информацию в DT_RUNPATH, DT_RPATH, LD_LIBRARY_PATH, /etc/ld.so.conf и в любых местах, которые мы ищем на этой неделе. Таким образом, вывод ldd
содержит список путей к файлам для общих объектов, которые будут загружены при загрузке общего объекта в командной строке ldd
. Вот пример:
#ldd ./test
linux-vdso.so.1 (0x00007fff0593f000)
libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007fe7e6776000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fe7e6385000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007fe7e5fe7000)
/lib64/ld-linux-x86-64.so.2 (0x00007fe7e6d01000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007fe7e5dcf000)
Это довольно полезная информация даже для самых случайных наблюдателей. Мы видим, что test
представляется 64-битной программой C ++ для x86 Linux, созданной, например, с относительно недавней версией gcc
или совместимым компилятором. Мы также видим, что у него нет сторонних зависимостей.
С другой стороны,
# ldd /usr/bin/kdiff3
linux-vdso.so.1 (0x00007ffeeed79000)
libkparts.so.4 => /usr/lib/libkparts.so.4 (0x00007f801a14d000)
libkio.so.5 => /usr/lib/libkio.so.5 (0x00007f8019c9b000)
libkdeui.so.5 => /usr/lib/libkdeui.so.5 (0x00007f8019637000)
libkdecore.so.5 => /usr/lib/libkdecore.so.5 (0x00007f801916b000)
libQtCore.so.4 => /usr/lib/x86_64-linux-gnu/libQtCore.so.4 (0x00007f8018c79000)
libQtGui.so.4 => /usr/lib/x86_64-linux-gnu/libQtGui.so.4 (0x00007f8017f84000)
libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f8017bfb000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f801785d000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f801746c000)
libQtXml.so.4 => /usr/lib/x86_64-linux-gnu/libQtXml.so.4 (0x00007f8017226000)
libQtNetwork.so.4 => /usr/lib/x86_64-linux-gnu/libQtNetwork.so.4 (0x00007f8016ed1000)
libQtSvg.so.4 => /usr/lib/x86_64-linux-gnu/libQtSvg.so.4 (0x00007f8016c78000)
libX11.so.6 => /usr/lib/x86_64-linux-gnu/libX11.so.6 (0x00007f8016940000)
... many more lines ...
перечисляет много зависимостей. Если он не загружается, мы можем использовать список, чтобы выяснить причину. Например, любая строка с надписью => not found
будет очень полезна.