如何在 Linux 上重新实现(或包装)系统调用函数?
假设我想完全接管 open() 系统调用,也许要包装实际的系统调用并执行一些日志记录。 一种方法这是使用 LD_PRELOAD 加载一个(用户制作的)共享对象库,该库接管 open() 入口点。
然后,用户编写的 open() 例程通过dlsym()
调用并获取指向 glibc 函数 open()
的指针。
然而,上面提出的解决方案是动态解决方案。假设我想静态链接我自己的 open()
包装器。我该怎么做呢?我猜想机制是一样的,但我也猜想用户定义的 open() 和 libc open() 之间会存在符号冲突。
请分享任何其他技术来实现相同的目标。
Suppose I want to completely take over the open() system call, maybe to wrap the actual syscall and perform some logging. One way to do this is to use LD_PRELOAD to load a (user-made) shared object library that takes over the open() entry point.
The user-made open() routine then obtains the pointer to the glibc function open()
by dlsym()
ing it, and calling it.
The solution proposed above is a dynamic solution, however. Suppose I want to link my own open()
wrapper statically. How would I do it? I guess the mechanism is the same, but I also guess there will be a symbol clash between the user-defined open()
and the libc open()
.
Please share any other techniques to achieve the same goal.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
您可以使用
ld
提供的换行功能。来自man ld
:因此,您只需为包装函数使用前缀
__wrap_
,并在想要调用实际函数时使用__real_
。一个简单的示例是:malloc_wrapper.c
:测试应用程序
testapp.c
:然后编译应用程序:
生成的应用程序的输出将是:
You can use the wrap feature provided by
ld
. Fromman ld
:So you just have to use the prefix
__wrap_
for your wrapper function and__real_
when you want to call the real function. A simple example is:malloc_wrapper.c
:Test application
testapp.c
:Then compile the application:
The output of the resulting application will be:
链接器按照您在命令行上列出符号的顺序解析符号,因此如果您在标准库之前列出您的库,则您将具有优先权。对于 gcc,您需要指定
这样您的库将首先被搜索和找到。
Symbols are resolved by the linker in the order you list them on the command line so if you listed your library before the standard library you'd have precidence. For gcc you'd need to specify
This way your libraries would be searched and found first.
对于 linux 和 GNU libc,该库内置了对拦截和重新实现库中任何函数的支持。
如果您定义自己的任何 libc 函数版本,并将其链接在 libc 之前(因此将其作为可执行文件的一部分,或者在链接命令上的 -lc 之前链接的库中,甚至使用
LD_PRELOAD
加载,如果libc 是动态链接的),它将被调用而不是 libc 版本(甚至调用 libc 本身的其他函数)。然后,您可以使用__libc_
前缀调用该函数,以获取库中的实际版本(尽管您需要自己声明该符号。)例如:For linux and GNU libc, the library has built-in support for intercepting and reimplementing any function in the library.
If you define you own version of ANY libc function, and link it before libc (so have it part of your executable, or in a library linked before -lc on the link command or even loaded with
LD_PRELOAD
if libc is dynamically linke), it will be called instead of the libc version (even calls in other function in libc itself). You can then call the function with a__libc_
prefix to get the actual version in the library (though you will need to declare that symbol yourself.) For example: