如何在Linux上重新实现(或 Package )syscall函数?

krcsximq  于 2023-10-16  发布在  Linux
关注(0)|答案(3)|浏览(183)

假设我想完全接管open()系统调用,可能是 Package 实际的系统调用并执行一些日志记录。One way to do this is to use LD_PRELOAD加载一个(用户创建的)共享对象库,它接管open()入口点。
然后,用户创建的open()例程通过dlsym()操作并调用它来获得指向glibc函数open()的指针。
然而,上面提出的解决方案是动态解决方案。假设我想静态地链接我自己的open() Package 器。我该怎么做?我猜机制是相同的,但我也猜在用户定义的open()和libc open()之间会有符号冲突。
请分享任何其他技术来实现同样的目标。

5sxhfpxr

5sxhfpxr1#

您可以使用ld提供的换行功能。从man ld
--wrap symbol使用一个封装函数来封装符号。对symbol的任何未定义引用都将解析为__wrap_symbol
__real_symbol的任何未定义引用都将解析为symbol
所以你只需要为你的 Package 函数使用前缀__wrap_,当你想调用真实的函数时使用前缀__real_。一个简单的例子是:
malloc_wrapper.c

  1. #include <stdio.h>
  2. void *__real_malloc (size_t);
  3. /* This function wraps the real malloc */
  4. void * __wrap_malloc (size_t size)
  5. {
  6. void *lptr = __real_malloc(size);
  7. printf("Malloc: %lu bytes @%p\n", size, lptr);
  8. return lptr;
  9. }

测试应用testapp.c

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. int main()
  4. {
  5. free(malloc(1024)); // malloc will resolve to __wrap_malloc
  6. return 0;
  7. }

然后编译应用程序:

  1. gcc -c malloc_wrapper.c
  2. gcc -c testapp.c
  3. gcc -Wl,-wrap,malloc testapp.o malloc_wrapper.o -o testapp

结果应用程序的输出将是:

  1. $ ./testapp
  2. Malloc: 1024 bytes @0x20d8010
展开查看全部
px9o7tmv

px9o7tmv2#

链接器按照你在命令行中列出的顺序解析符号,所以如果你在标准库之前列出你的库,你会有优先权。对于gcc,您需要指定

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

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

jk9hmnmh

jk9hmnmh3#

对于Linux和GNU libc,该库内置了对拦截和重新实现库中任何函数的支持。
如果你定义了自己版本的任何libc函数,并将其链接到libc之前(因此将其作为可执行文件的一部分,或者在链接命令的-lc之前链接到库中,或者如果libc是动态链接的,甚至使用LD_PRELOAD加载),它将被调用而不是libc版本(甚至在libc本身的其他函数中调用)。然后,您可以使用__libc_前缀调用函数以获取库中的实际版本(尽管您需要自己声明该符号)。例如:

  1. #include <sys/types.h>
  2. #include <sys/stat.h>
  3. #include <fcntl.h>
  4. extern int __libc_open(const char *pathname, int flags, mode_t mode);
  5. int open(const char *pathname, int flags, mode_t mode) {
  6. return __libc_open(pathname, flags, mode);
  7. }

相关问题