На самом деле это - корректное поведение.
Ниже кавычка отсюда:
Ответ очень интересен. По умолчанию, gcc на Linux связывает программы с библиотеками времени выполнения C динамично. То, что это означает, - то, что одной из первых вещей, которая работает, когда любая программа выполнена, является динамический загрузчик библиотеки, который ищет необходимые общие библиотеки. Это - довольно много кода – и помните, что наш основной трассировщик здесь смотрит на каждую инструкцию, не просто основной функции, а целого процесса.
Можно использовать относительный rpath, используя $ORIGIN
.
Связывание исполняемых файлов с помощью -Wl,-rpath,'$ORIGIN/... /lib'
позволяет исполняемым файлам найти свои библиотеки, устанавливая :
/bin/
/lib/
Продолжая таким образом, можно настроить эту связь только для этих исполняемых файлов, а каталог
может быть любым.
Нелегко. Файлы ld.so.conf
имеют очень простой формат: это просто список путей.
Вы могли бы сделать что-нибудь, собрав свой исполняемый файл с другим интерпретатором ; обычным было бы что-нибудь вроде /lib64/ld-linux-x86-64.so.2
1 и это то, что на самом деле отвечает за выполнение динамического линковки. Так что ваш пользовательский динамический компоновщик может выглядеть в другом ld.so.conf
, или делать что угодно. Но это звучит намного хуже, чем rpath!
Гораздо более простое решение - обертка. Установите бинарник как program.real
, или, что еще лучше, где-нибудь в /usr/local/lib/
(то есть не в $PATH
). Затем поместите простой скрипт оболочки в виде /usr/local/bin/program
:
#!/bin/sh
export LD_LIBRARY_PATH=/path/to/libs
exec /usr/local/lib/program/program.real
Теперь расположение вашей библиотеки не зависит от сборки, но вызывающая программа не требует о ней никаких знаний.
1: Быстрый способ найти то, что обычно находится в вашей системе: читайте /bin/bash -p .interp
. Попробуйте несколько разных исполняемых файлов; вы увидите, что как минимум 32- и 64-битные программы используют разные.
Аргумент filename
для dlopen
может быть абсолютным путем (начинается с ' /
').
Итак, сохраните «частный путь» в конфигурационном файле и создайте из него полное имя библиотеки. Или, если вы знаете, что частная библиотека будет в том же каталоге, что и исполняемый файл, выполните простые строковые операции на пути к исполняемому файлу, чтобы найти его ...
#include <dlfcn.h>
#include <unistd.h>
#include <string.h>
static int (*foo)();
/* ... */
char buf[BUFSIZ];
char *lastslash;
void *handle;
realpath(argv[0],buf);
lastslash = strrchr(buf,'/');
strcpy(lastslash,"foo." VERSION_BUILD ".so");
dlopen(buf,RTLD_LOCAL | RTLD_LAZY);
*(void **)(&foo) = dlsym(handle, "foo");
/* ... */
printf("%d\n",foo());