如何在Linux上重新实现(或包装)系统调用功能?

时间:2010-09-07 21:19:05

标签: c linux system-calls libc

假设我想完全接管open()系统调用,可能包装实际的系统调用并执行一些日志记录。 One way to do this is to use LD_PRELOAD加载一个(用户自制的)共享对象库,它接管open()入口点。

用户自定义的open()例程然后通过open()获取指向glibc函数dlsym()的指针并调用它。

然而,上面提出的解决方案是动态解决方案。假设我想静态链接我自己的open()包装器。我该怎么办?我想机制是相同的,但我也猜测用户定义的open()和libc open()之间会有一个符号冲突。

请分享任何其他技术以实现相同的目标。

2 个答案:

答案 0 :(得分:60)

您可以使用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

答案 1 :(得分:2)

链接器按照您在命令行中列出的顺序解析符号,因此如果您在标准库之前列出了库,则可以预先确定符号。对于gcc,您需要指定

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

这样,您的图书馆将首先被搜索和找到。