为什么LD_PRELOAD技巧在fopen()调用时不会捕获open()?

时间:2016-03-03 11:49:07

标签: linux ld-preload

我使用LD_PRELOAD技巧来捕获open64()次调用,我想我知道如何正确地执行此操作:使用从

编译的程序foobar
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

int main() {
  open64("foobar.txt", 0);
  return 0;
}

我按照我的期望抓住了open64

>LD_PRELOAD=$PWD/catch.so ./foobar
open64 called

但是,当open64替换为fopen64时:

#include <stdio.h>

int main() {
  fopen64("foobar.txt", "r");
  return 0;
}

现在open64没有被捕获。为什么呢?

如果fopen64调用open,我会截获openopen64,但没有一个被捕获。

程序foobar的两个版本在使用strace执行时都会显示open被调用,这意味着fopen64会在内部调用openopen64

我认为也许某些东西是静态链接的,但事实并非如此:

>ldd foobar

显示

libc.so.6 => /lib64/libc.so.6 

这是一个共享库,

>nm /lib64/libc.so.6

显示open64fopen64已定义(但不是fopen,这就是为什么在问题中,我使用“64”版本作为参数;也许{{1是fopen或类似的东西的宏,无关紧要,因为问题发生在有或没有64)。

2 个答案:

答案 0 :(得分:6)

我认为它的工作原理如下:用户空间程序在libc中调用库函数,而libc在内核中调用系统调用。使用LD_PRELOAD,可以拦截程序和libc之间的libc调用。您无法拦截系统调用。如果glibc在内部调用另一个函数(例如fopen调用open),则无法拦截它。

在这种情况下,最好使用strace,而不是使用ltrace,因为它显示了哪些库调用已完成。这些是你可以拦截的电话。

enter image description here

答案 1 :(得分:0)

您需要ptracePTRACE_SYSCALL。这是一个blog on it