【发布时间】:2012-05-28 03:46:54
【问题描述】:
我正在编写一个工具。该工具的一部分将是它能够记录系统调用的参数。好吧,我可以为此使用ptrace,但ptrace 非常慢。我想到的一个更快的方法是修改 glibc。但这变得越来越困难,因为 gcc 神奇地插入了自己的内置函数作为系统调用包装器,而不是使用 glibc 中定义的代码。使用-fno-builtin 也无济于事。
所以我想到了编写一个共享库的想法,其中包括每个系统调用包装器,例如mmap,然后在调用实际的系统调用包装器函数之前执行日志记录。例如,我的mmap 的伪代码如下所示。
int mmap(...)
{
log_parameters(...);
call_original_mmap(...);
...
}
然后我可以使用 LD_PRELOAD 先加载这个库。你认为这个想法会奏效吗,还是我错过了什么?
【问题讨论】:
-
它可能不适用于静态链接的可执行文件。而且它不适用于执行系统调用而不通过 libc 的可执行文件。
-
您想在每次执行实际的系统调用时(在每个
int 0x80),还是在每次调用库处理函数时进行拦截? -
我认为它可能会很慢。这基本上正是 valgrind 对其仪器所做的事情,尽管它是一个非常知名和开发的工具,但它仍然会影响性能。我认为如果有更快的方法,它就会在那里使用。我的猜测是你低估了日志记录功能的成本,而且没有办法解决这个问题。
-
看看
fakeroot,它使用了一个共享库,里面有一堆libc函数包装器,里面加载了LD_PRELOAD。 -
@jthill,正是我的观点。我经常为此目的使用
strace。我刚刚检查了在使用opendir()和fstatat()时最终调用了哪些系统调用libc6-2.15,以及使用了哪些参数。