Linux 中不使用 dlsym 的函数插入

发布于 2024-07-24 18:42:10 字数 472 浏览 11 评论 0原文

我目前正在开发一个项目,需要跟踪多个系统调用和低级函数(例如 mmapbrksbrk。 到目前为止,我一直在使用函数插入来完成此操作:我编写了一个与要替换的函数同名的包装函数(例如 mmap),然后将其加载到程序中设置LD_PRELOAD环境变量。 我通过使用 dlsym 加载的指针调用实际函数。

不幸的是,我想要包装的函数之一 sbrkdlsym 在内部使用,因此当我尝试加载该符号时程序崩溃。 sbrk 不是 Linux 中的系统调用,因此我不能简单地使用 syscall 来间接调用它。

所以我的问题是,如何在不使用 dlsym 的情况下从同名的包装函数调用库函数? 是否有任何编译器技巧(使用 gcc)让我引用原始函数?

I'm currently working on a project where I need to track the usage of several system calls and low-level functions like mmap, brk, sbrk. So far, I've been doing this using function interposition: I write a wrapper function with the same name as the function I'm replacing (mmap for example), and I load it in a program by setting the LD_PRELOAD environment variable. I call the real function through a pointer that I load with dlsym.

Unfortunately, one of the functions I want to wrap, sbrk, is used internally by dlsym, so the program crashes when I try to load the symbol. sbrk is not a system call in Linux, so I can't simply use syscall to call it indirectly.

So my question is, how can I call a library function from a wrapper function of the same name without using dlsym? Is there any compiler trick (using gcc) that lets me refer to the original function?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

恬淡成诗 2024-07-31 18:42:11

truss 在您的系统上不起作用吗? 它在 Solaris 上非常适合此类事情。

Does truss not work on your system? It works perfectly for this kind of things here on Solaris.

半世蒼涼 2024-07-31 18:42:10

请参阅 ld 的选项--wrap symbol。 从手册页:

--wrap symbol 对符号使用包装函数。 任何未定义的
对符号的引用将得到解决
到“__wrap_symbol”。 任何未定义的
对“__real_symbol”的引用将
被解析为符号。

这可以用来提供
系统函数的包装器。 这
应该调用包装函数
__wrap_symbol”。 如果它想打电话
系统函数,它应该调用
__real_symbol”。

这是一个简单的例子:

void *
__wrap_malloc (size_t c)
{
    printf ("malloc called with %zu\n", c);
    return __real_malloc (c);
}

如果您将其他代码与此链接
使用 --wrap malloc 文件,然后全部
调用“malloc”将调用
函数“__wrap_malloc”代替。 这
调用
中的“__real_malloc”
__wrap_malloc”会调用真正的
malloc”函数。

您可能希望提供
__real_malloc”函数也是如此,所以
没有 --wrap 选项的链接
将会成功。 如果你这样做,你
不应该把定义
__real_malloc”在同一文件中
__wrap_malloc”; 如果你这样做,
汇编器可能会先解析调用
链接器有机会将其包装到
“malloc”。

另一种选择是可能查看 ltrace 的源代码,它或多或少做了同样的事情:-P。

不过,这里有一个想法。 您可以让 LD_PRELOAD 编辑的库更改 PLT 条目以指向您的代码。 从技术上讲,您仍然可以从代码中调用 sbrk() 函数。

see ld's option --wrap symbol. From the man page:

--wrap symbol Use a wrapper function for symbol. Any undefined
reference to symbol will be resolved
to "__wrap_symbol". Any undefined
reference to "__real_symbol" will
be resolved to symbol.

This can be used to provide a
wrapper for a system function. The
wrapper function should be called
"__wrap_symbol". If it wishes to call
the system function, it should call
"__real_symbol".

Here is a trivial example:

void *
__wrap_malloc (size_t c)
{
    printf ("malloc called with %zu\n", c);
    return __real_malloc (c);
}

If you link other code with this
file using --wrap malloc, then all
calls to "malloc" will call the
function "__wrap_malloc" instead. The
call to "__real_malloc" in
"__wrap_malloc" will call the real
"malloc" function.

You may wish to provide a
"__real_malloc" function as well, so
that links without the --wrap option
will succeed. If you do this, you
should not put the definition of
"__real_malloc" in the same file as
"__wrap_malloc"; if you do, the
assembler may resolve the call before
the linker has a chance to wrap it to
"malloc".

The other option is to possibly look at the source for ltrace, it is more or less does the same thing :-P.

Here's an idea though. You could have your LD_PRELOAD'ed library change the PLT entries to point to your code. This you technically the sbrk() function is still callable from your code nativly.

著墨染雨君画夕 2024-07-31 18:42:10

您可以使用以下工具以不显眼的方式检查函数调用:

  • gdb
  • ltrace
  • systemtap

这些工具允许监视程序在调用函数时通知您,并允许您询问参数。

主要区别是:

  • gdb 是交互式的,但功能强大
  • ltrace 使用简单,但只能打印函数名
  • systemtap 不是交互式的,但它可以非常快,而且功能强大。

You can examine function invocation unobtrusively using tools such as:

  • gdb
  • ltrace
  • systemtap

These tools allow a monitor program to inform you when a function is called, and allow you to interrogate the arguments.

The main differences are:

  • gdb is interactive, but powerful
  • ltrace simple to use, but you can only print the function name
  • systemtap is not interactive, but it can be very fast, and is powerful.
病毒体 2024-07-31 18:42:10

如果您正在使用 glibc 运行主机系统,则 libc 有一些我之前使用过的运行时动态链接器的内部后端。 如果我没记错的话,我认为它叫做“__libc_dlsym”。 (要检查,“$ readelf -s /usr/lib/libc.a | grep dlsym”应该有所帮助。)将其声明为具有与 dlsym 相同的参数和返回值的外部链接函数,并使用它来包装 dlsym 本身。

If you are running a host system with glibc, the libc has some internal back end to the runtime dynamic linker that I used some time ago. If I recall correctly, I think it's called '__libc_dlsym'. (To check, "$ readelf -s /usr/lib/libc.a | grep dlsym" should help.) Declare it as an externally linked function with the same arguments and return value that dlsym has and use it to wrap dlsym itself.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文