2010-09-07 3 views
28

Предположим, я хочу полностью взять на себя системный вызов open(), возможно, чтобы обернуть фактический системный вызов и выполнить некоторые протоколирования. One way to do this is to use LD_PRELOAD, чтобы загрузить (пользовательскую) библиотеку общих объектов, которая принимает точку входа open().Как переопределить (или обернуть) функцию syscall в Linux?

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

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

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

+0

Как насчет того, чтобы вы просто вставляли функцию/макрос в ваш код? –

+0

@Seamus: Я предпочитаю не использовать макросы. У меня действительно нет проблем. Я прошу только увеличить знания SO и изучить новый трюк. –

ответ

56

Вы можете использовать функцию обертки, предоставленную 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 
+3

+1 это soooo cool: D –

+1

Похоже, что функция, вызывающая malloc, не может быть динамически связана. Например, я написал tool.c, который содержит функцию perform_alloc(), которая вызывает malloc. Затем, если я сначала создаю libtools.so и динамически свяжу его с помощью '-ltools',' -Wl, -wrap, malloc' не будет работать. – xanpeng

+1

Как указано в http: // stackoverflow.com/questions/3826108/has-any-a-example-for-wrapping-a-function-in-c требуется префикс определения функций с помощью 'extern 'C" 'при использовании этого кода в программе на C++. – MKroehnert

2

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

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

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

Смежные вопросы