LD_PRELOAD для переопределения функций из динамически загружаемой библиотеки

Я использую библиотеку-оболочку для трассировки функций с помощью LD_PRELOAD, которая работает, когда в приложении есть ссылки на отслеживаемые функции.

Библиотека-обертка использует dlsym для заполнения символов, которые она обертывает.

Но это не работает, если приложение не ссылается на функции напрямую, а через dlopen. Должна ли библиотека-оболочка работать с динамически загружаемыми библиотеками? Если нет, то есть ли способ заставить его работать?


person kanna    schedule 15.11.2020    source источник
comment
Может быть, некоторые подробности о флагах, переданных в dlopen() и dlsym(), помогут сузить pb? Поделитесь, пожалуйста, примером переноса символов.   -  person Rachid K.    schedule 15.11.2020


Ответы (1)


Но это не работает, если приложение не ссылается на функции напрямую, а через dlopen.

Если приложение выполняет:

void *h = dlopen("libfoo.so", ...);
void *sym = dlsym(h, "symbol");

тогда symbol будет преобразовано в libfoo.so независимо от каких-либо LD_PRELOAD (и действительно независимо от любых других экземпляров symbol в других уже загруженных библиотеках). Это работает по назначению.

Должна ли библиотека-оболочка работать с динамически загружаемыми библиотеками?

No.

Если нет, то есть ли способ заставить его работать?

Да, вы можете заставить его работать. Вам нужно будет предоставить replacement.so, который предоставляет все символы, которые приложение ищет в libfoo.so, а затем сделать так, чтобы replacement.so было dlopend()ed приложением.

Один из способов сделать это — переименовать libfoo.so -> libfoo.so.orig, скопировать replacement.so -> libfoo.so и получить replacement.so dlopen("libfoo.so.orig", ...).

Если приложение dlopens libfoo.so без абсолютного пути, вы можете организовать так, чтобы replacement.so было раньше в пути поиска, например.

mkdir /tmp/replacement
ln -s /path/to/replacement.so /tmp/replacement/liboo.so
LD_LIBRARY_PATH=/tmp/replacement /path/to/a.out

Если вы пойдете по этому пути, replacement.so все равно нужно будет знать, как dlopen исходный libfoo.so (для этого можно использовать жестко закодированный абсолютный путь).

person Employed Russian    schedule 16.11.2020