2

我正在尝试挂钩 glibc 的一些功能,例如 fopen、fread 等。但是在挂钩功能中,我必须使用与 glibc 中相同的功能。像这样:

// this is my fopen
FILE *fopen(.....)
{
    fopen(....);// this is glibc fopen
}

我找到了一种使用 dlsym 执行此操作的方法,但是通过这种方式,我必须将所有 glibc 函数调用替换为使用 dlsym 调用 glibc 函数的包装器。我很好奇在没有编码包装函数的情况下是否还有另一种方法可以完成相同的工作。我曾经试过这个:

fopen.c

....fopen(..)
{
  myfopen(..);
}

我的fopen.c

myfopen(..)
{
  fopen(...);// glibc version
}

主程序

int main()
{
  fopen(...);
}

$ gcc -c *.c
$ gcc -shared -o libmyopen.so myopen.o
$ gcc -o test main.o fopen.o libmyopen.so

在我的理解中,gcc 会按照命令行中的规定从左到右链接,所以 main.o 会在 fopen.o 中使用 fopen,fopen.o 会在 libmyfopen.so 中使用 myfopen,libmyfopen.so 会在 glibc 中使用 fopen。但是在运行时,我遇到了段错误,gdb 显示有 fopen 和 myfopen 的递归调用。我有点困惑。谁能解释为什么?

4

1 回答 1

3

我的理解,gcc会按照命令行的规定从左到右链接,所以main.o会在fopen.o中使用fopen,fopen.o会在libmyfopen.so中使用myfopen,libmyfopen.so会在glibc中使用fopen

你的理解是不正确的。myfopenfromlibmyfopen.so将使用可用的第一个定义fopen。在您的设置中,该定义将来自fopen.o链接到test程序中,您最终会遇到无限递归,并且由于堆栈耗尽而崩溃。

gdb ./test您可以通过运行、运行直到崩溃和使用来观察这一点backtrace。您将看到无休止的fopenmyfopen调用序列。

编译时符号 fopen 与 libc 中的符号不​​绑定

这是正确的:在ELF格式中,库记录它需要fopen定义符号(在这种情况下),但它不“记住”或关心哪个其他模块定义了该符号。

你可以通过运行看到这一点readelf -Wr libmyfopen.so | grep fopen

这与 Windows DLL 不同。

是的。

于 2012-05-15T05:25:18.137 回答