Получить указатель функции для работы в общей библиотеке, которую я не загружал напрямую - PullRequest
3 голосов
/ 05 января 2011

Мое приложение Linux (A) ссылается на стороннюю совместно используемую библиотеку (B), к которой у меня нет исходного кода. Эта библиотека использует другую стороннюю разделяемую библиотеку, к которой у меня нет исходного кода (C). Я считаю, что (B) использует dlopen для доступа к (C) вместо прямой связи. Я считаю, что «ldd» на (B) не показывает (C), а objdump -X (B) показывает ссылки на dlopen / dlclose / dlsym.

Мое требование заключается в том, что мне нужно в моем коде для (A) получить указатель на функцию foo (), расположенную в (C). Обычно для этого я использовал бы dlsym, но мне нужно передать его дескриптору, возвращенному из dlopen, которого у меня нет, поскольку (B) этого не раскрывает.

-

Для более широкого контекста: мне нужно изменить функцию в (C) так, чтобы каждый раз, когда она вызывала свою вспомогательную функцию bar () (также расположенную в (C)), она также вызывала функцию с той же сигнатурой, расположенной в ( A) с теми же параметрами (в основном, мой код вводится в путь кода (C) foo () -> bar (). Я считаю, что я нашел способ сделать это с помощью gdb, но для того, чтобы перенести мой список команд gdb , но я застрял на шаге получения указателя на функцию.Я также открыт для альтернатив для выполнения той же задачи, а не для точной задачи, как указано выше

Редактировать: После написания этого я понял, что, возможно, я могу просто сделать еще один dlopen для файла в моем коде, и символы, возвращаемые через dlsym на этом дескрипторе, должны быть такими же, как полученные через оригинальный dlopen, если Я правильно читаю справочную страницу dlopen. Однако я все еще заинтересован в совете или помощи в моем более широком контексте, если есть лучший способ сделать это

Ответы [ 2 ]

2 голосов
/ 05 января 2011

Если вам известен прототип для функций foo и bar, вы можете использовать LD_PRELOAD (созданную вами библиотеку) в среде вашего приложения и вызывать следующую доступную функцию (либо foo, либо bar после выполнения ваших действий.требуемая задача.

/*
 * gcc -shared -fPIC my_lib.c -ldl -Wl,-init,init_lib -o lib_my_name.so
 *
 * LD_PRELOAD this library in the environment of the target executable
 *
 */

#include <stdio.h>
#include <dlfcn.h>
#include <stdlib.h>

#ifndef RTLD_NEXT
#define RTLD_NEXT ((void *)-1)
#endif

int init_lib(void)
{
    return 0;
}

void *foo (params here...)
{
    /* your required task here */

    return ((void* (*)(size_t))(dlsym(RTLD_NEXT, "foo")))(params here);
}

(я предполагаю, что вы делаете это для какой-то цели отладки, поскольку вы использовали для этого gdb, иначе это не хороший способ изменить некоторые функции на компьютере клиента)

1 голос
/ 05 января 2011

Вы можете легко достать ручку для (С);просто скопируйте нужный файл.Либо вы уже знаете, какой файл создавать (поскольку вам нужен символ "foo"), либо вы запускаете strace -e open,mmap,mmap2 на (A) и смотрите, какие общие библиотеки открываются.

Когда был создан (C)любые ссылки на "bar" (например, из инструкции jmp в "foo") обычно частично разрешаются уже во время создания, поскольку (C) действительно имеет "bar".Таким образом, вызов bar не будет проходить через PLT, иными словами, переопределение bar с помощью простых хаков является недействительным, и требуется наказание на уровне asm, как это делает GDB.Напрашивается вопрос: стоит ли это работать или может быть лучше выбросить компоненты с закрытым исходным кодом?

...