Совместно используемая библиотека Linux, в которой используется символ общей библиотеки undefined

две общие библиотеки liba.so и libb.so. liba.so использует libb.so. Все c файлы скомпилированы с помощью -fPIC. Связывание использует -shared. Когда мы вызываем dlopen на liba.so, он не может найти символы в libb.so... мы получаем ошибку "undefined". Мы можем dlopen libb.so без ошибок. Мы знаем, что liba находит libb, потому что мы не получаем ошибку, не найденную в файле. Мы удалили файл, не найденный при удалении libb.so. Мы попробовали -любили и не повезло.

Любые идеи????

О да. gcc 4.1.2

update: мы используем rpath при связывании liba, чтобы он мог найти libb.

ldd liba.so возвращает:

linux-gate.so.1 => (0xffffe000)  
libb.so => ./libb.so (0xf6ef9000)  <-------- LIBB 
libutil.so.1 => /lib/libutil.so.1 (0xf6ef5000)  
libdl.so.2 => /lib/libdl.so.2 (0xf6ef1000)  
libm.so.6 => /lib/libm.so.6 (0xf6ec9000)  
libpthread.so.0 => /lib/libpthread.so.0 (0xf6eb1000)  
librt.so.1 => /lib/librt.so.1 (0xf6ea8000)  
libc.so.6 => /lib/libc.so.6 (0xf6d62000)  
/lib/ld-linux.so.2 (0x007d0000)   

Это значит, что в конце libb нет. #

Ответ 1

Вы можете легко проверить, где libb.so ожидается с командой ldd:

 $ ldd liba.so
    linux-gate.so.1 =>  (0xb77b0000)
    libb.so.1 => not found
    libstdc++.so.6 => /usr/lib/libstdc++.so.6 (0xb75b6000)
    libgcc_s.so.1 => /lib/libgcc_s.so.1 (0xb7572000)
    libc.so.6 => /lib/i686/cmov/libc.so.6 (0xb742b000)
    /lib/ld-linux.so.2 (0xb77b1000)

Если он not found, путь libb.so должен быть добавлен в /etc/ld.so.conf или переменную оболочки LD_LIBRARY_PATH.

Другой способ - установить rpath в самом liba.so - он в основном жестко кодирует свой путь, поэтому при запуске двоичного файла динамический компоновщик будет знать, где искать общие библиотеки.

Если rpath не задано, он сначала будет искать в LD_LIBRARY_PATH, затем пути, указанные в /etc/ld.so.conf (или/etc/ld.so.conf.d/). После добавления в ls.so.conf не забудьте выполнить /sbin/ldconfig

Динамический компоновщик ищет зависимые разделяемые библиотеки по их soname (если он установлен) - если soname не установлен (например, с -Wl, -soname, libb.so.1), он будет искать по имя библиотеки.

Пример: libb.so.1.0 - это ваша фактическая библиотека, имеющая soname - libb.so.1. Обычно у вас будет следующая структура файлов:

libb.so -> libb.so.1
libb.so.1 -> libb.so.1.0
libb.so.1.0

где libb.so и libb.so.1 являются символическими ссылками.

Обычно вы создаете ссылку на libb.so при создании какого-либо приложения или другой библиотеки, в зависимости от libb.so.

gcc -shared -Wl,-soname,liba.so.1 -o liba.so.1.2 -L/libb/path -lb

Когда приложение запускается (или выполняется dlopen - ваш случай) - динамический компоновщик будет искать файл с именем libb.so.1 - soname зависимой библиотеки, если установлен soname, а не libb.so.

Для этого вам нужна эта символическая ссылка libb.so.1, указывающая на фактическую библиотеку.

Если вы используете ld.so.conf и ldconfig, он создаст символическую ссылку с именем soname, указывая на файл библиотеки, если эта символическая ссылка отсутствует.

Вы можете увидеть ld-linux справочную страницу для более полезной информации.


Если библиотека найдена, но некоторые из символов отсутствуют, попробуйте создать libb.so с опцией -Wl,--no-undefined
gcc -shared -Wl,-soname,libb.so.1 -Wl,--no-undefined -o libb.so.1.2

Он должен дать вам сообщение об ошибке, если вы пропустили определение какого-либо символа.

Ответ 2

Не забывайте, что порядок libs (все аргументы -lxxx) важны (по крайней мере, в gcc) при связывании всех ваших объектов и библиотек для генерации вашего исполняемого файла.

Краткий пример:

ЛИЭС = -L. -ltest1 -ltest2

OBJS = code1.o code2.o

gcc $(LIBS) $(OBJS) -o mysoft

который может быть неудачен в некоторых случаях, тогда как

gcc $(OBJS) -o mysoft $(LIBS)

не будет