假设我想完全接管open()系统调用,可能是 Package 实际的系统调用并执行一些日志记录。One way to do this is to use LD_PRELOAD加载一个(用户创建的)共享对象库,它接管open()入口点。
然后,用户创建的open()例程通过dlsym()
操作并调用它来获得指向glibc函数open()
的指针。
然而,上面提出的解决方案是动态解决方案。假设我想静态地链接我自己的open()
Package 器。我该怎么做?我猜机制是相同的,但我也猜在用户定义的open()
和libc open()
之间会有符号冲突。
请分享任何其他技术来实现同样的目标。
3条答案
按热度按时间5sxhfpxr1#
您可以使用
ld
提供的换行功能。从man ld
:--wrap symbol
使用一个封装函数来封装符号。对symbol
的任何未定义引用都将解析为__wrap_symbol
。对
__real_symbol
的任何未定义引用都将解析为symbol
。所以你只需要为你的 Package 函数使用前缀
__wrap_
,当你想调用真实的函数时使用前缀__real_
。一个简单的例子是:malloc_wrapper.c
:测试应用
testapp.c
:然后编译应用程序:
结果应用程序的输出将是:
px9o7tmv2#
链接器按照你在命令行中列出的顺序解析符号,所以如果你在标准库之前列出你的库,你会有优先权。对于gcc,您需要指定
这样,您的库将首先被搜索和找到。
jk9hmnmh3#
对于Linux和GNU libc,该库内置了对拦截和重新实现库中任何函数的支持。
如果你定义了自己版本的任何libc函数,并将其链接到libc之前(因此将其作为可执行文件的一部分,或者在链接命令的-lc之前链接到库中,或者如果libc是动态链接的,甚至使用
LD_PRELOAD
加载),它将被调用而不是libc版本(甚至在libc本身的其他函数中调用)。然后,您可以使用__libc_
前缀调用函数以获取库中的实际版本(尽管您需要自己声明该符号)。例如: