31

假设我想完全接管 open() 系统调用,也许是为了包装实际的系统调用并执行一些日志记录。一种方法是使用 LD_PRELOAD加载接管 open() 入口点的(用户制作的)共享对象库。

open()然后,用户创建的 open() 例程通过dlsym()ing 和调用glibc 函数来获得指向 glibc 函数的指针。

然而,上面提出的解决方案是动态解决方案。假设我想open()静态链接我自己的包装器。我该怎么做?open()我猜机制是一样的,但我也猜想 user-defined和 libc之间会有符号冲突open()

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

4

2 回答 2

62

您可以使用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
于 2010-09-07T21:35:30.197 回答
3

符号由链接器按照您在命令行上列出它们的顺序进行解析,因此如果您在标准库之前列出您的库,那么您将拥有优先权。对于 gcc,您需要指定

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

这样,您的库将首先被搜索和找到。

于 2010-09-07T21:39:46.957 回答