Как уже упоминалось в других ответах SO, я использую механизм обертывания GNU ld для перехвата вызовов malloc
в Linux (см. Вот для примера).
Используемый флаг компоновщика -Wl,--wrap=malloc
и соответствующие void __wrap_malloc(size_t)
также определяется.
Это прекрасно работает в тестовом приложении, где все модули компиляции связаны в один двоичный файл.
Теперь мне нужно изменить динамически связанную библиотеку, которая загружается в основную программу через dlopen()
,
Связывание библиотеки успешно, но загрузка в основную программу завершается неудачно с undefined symbol: __real_malloc
,
Бег nm
в библиотеке видно, что __wrap_malloc
определяется, но __real_malloc
не является.
Но, согласно man ld
а также этот ТАК ответь, malloc
должен быть заменен на __wrap_malloc
а также __real_malloc
следует указать на malloc
при использовании этой техники.
В тестовом приложении я вижу, что __real_malloc
не определено в скомпилированных объектных файлах, но разрешается после получения ссылки на исполняемый файл.
Итак, почему символ разрешается в тестовом приложении, а не в динамической библиотеке?
В обоих случаях выполняется последний шаг ссылки, который должен разрешить этот символ.
Или требуется добавить другую библиотеку во время шага ссылки динамической библиотеки, чтобы получить __real_malloc
решены?
На всякий случай невозможно изменить целевое приложение, которое загружает динамическую библиотеку через dlopen
,
Это должно работать и требует лишь небольших изменений в коде в вопросе, который вы связали.
testapp.c
#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>
typedef void f_t(void);
int main()
{
void* h = dlopen("./malloc_wrapper.so", RTLD_NOW);
if (h == NULL)
{
puts(dlerror());
exit(1);
}
f_t* f = (f_t*)dlsym(h, "test");
if (f == NULL)
{
puts(dlerror());
exit(1);
}
(*f)();
return 0;
}
malloc_wrapper.c
#include <stdlib.h> /* added */
#include <stdio.h>
void *__real_malloc (size_t);
/* This function wraps the real malloc */
void *__wrap_malloc(size_t size)
{
void *lptr = __real_malloc(size);
printf("Malloc: %lu bytes @%p\n", size, lptr);
return lptr;
}
void test(void) /* added */
{
free(malloc(1024));
}
Скомпилируйте и запустите.
gcc -Wl,-wrap,malloc -shared -fpic malloc_wrapper.c -o malloc_wrapper.so
gcc testapp.c -o testapp -ldl
./testapp
Malloc: 1024 bytes @0x1d44680
Подобная компиляция malloc_wrapper.so воспроизводит ошибку, которую вы описали:
gcc -shared -fpic malloc_wrapper.c -o malloc_wrapper.so
./testapp
./malloc_wrapper.so: undefined symbol: __real_malloc
Возможно, вы использовали wrap при компиляции и компоновке исполняемого файла вместо общего объекта?