Как переопределить (или обернуть) функцию системного вызова в Linux? - PullRequest
31 голосов
/ 08 сентября 2010

Предположим, я хочу полностью перехватить системный вызов open (), возможно, чтобы обернуть фактический системный вызов и выполнить некоторую регистрацию. Один из способов сделать это - использовать LD_PRELOAD для загрузки (созданной пользователем) библиотеки общих объектов, которая принимает точку входа open ().

Затем пользовательская процедура open () получает указатель на функцию glibc open(), dlsym() вызывая ее и вызывая ее.

Однако предложенное решение является динамическим решением. Предположим, я хочу статически связать свою собственную open() оболочку. Как бы я это сделал? Я предполагаю, что механизм тот же, но я также предполагаю, что между пользовательским open() и libc open().

произойдет столкновение символов.

Пожалуйста, поделитесь любыми другими методами для достижения той же цели.

Ответы [ 2 ]

60 голосов
/ 08 сентября 2010

Вы можете использовать функцию обтекания, предоставляемую ld.От man ld:

--wrap symbol Использовать функцию обертки для символа.Любая неопределенная ссылка на symbol будет преобразована в __wrap_symbol.

Любая неопределенная ссылка на __real_symbol будет преобразована в symbol.

Так что вам просто нужноиспользуйте префикс __wrap_ для вашей функции-оболочки и __real_, когда вы хотите вызвать реальную функцию.Простой пример:

malloc_wrapper.c:

#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;
}

Тестовое приложение testapp.c:

#include <stdio.h>
#include <stdlib.h>
int main()
{
    free(malloc(1024)); // malloc will resolve to __wrap_malloc
    return 0;
}

Затем скомпилируйте приложение:

gcc -c malloc_wrapper.c
gcc -c testapp.c
gcc -Wl,-wrap,malloc testapp.o malloc_wrapper.o -o testapp

Вывод полученного приложения будет:

$ ./testapp
Malloc: 1024 bytes @0x20d8010
2 голосов
/ 08 сентября 2010

Символы разрешаются компоновщиком в том порядке, в котором вы их перечислили в командной строке, поэтому, если вы перечислили свою библиотеку раньше, чем стандартная библиотека, у вас будет прецедент.Для gcc вам нужно указать

gcc <BLAH> -nodefaultlibs <BLAH BLAH> -lYOUR_LIB <OTHER_LIBS>

Таким образом, ваши библиотеки будут сначала найдены и найдены.

...