使用LD_PRELOAD重载调用共享库的C函数

时间:2013-04-25 14:31:01

标签: c gcc ld dynamic-linking

我正在关注this answer以覆盖对C库的C函数的调用。

我认为我做的一切都正确,但它不起作用:

我想覆盖“DibOpen”功能。这是我在运行应用程序时传递给LD_PRELOAD环境变量的库的代码:

DIBSTATUS DibOpen(void **ctx, enum Board b)
{
    printf("look at me, I wrapped\n");

    static DIBSTATUS (*func)(void **, enum Board) = NULL;
    if(!func)
        func = dlsym(RTLD_NEXT, "DibOpen");
    printf("Overridden!\n");
    return func(pContextAddr, BoardType, BoardHdl);
}

nm lib.so | grep DibOpen的输出显示

000000000001d711 T DibOpen

当我像这样运行我的程序时

LD_PRELOAD=libPreload.so ./program

我将program与-ldl相关联,但ldd program未显示指向libdl.so的链接

停止

 symbol lookup error: libPreload.so: undefined symbol: dlsym

。我该怎么做才能进一步调试?我的错误在哪里?

1 个答案:

答案 0 :(得分:5)

创建共享库时(无论是否在LD_PRELOAD中使用),您需要命名 it 所需的所有库来解析其依赖关系。 (在某些情况下,dlopen ed共享对象可以依赖可执行文件为其提供符号,但最好不要依赖它。)在这种情况下,您需要链接libPreload.so反对libdl。在Makefile-ese中:

libPreload.so: x.o y.o z.o
        $(CC) -shared -Wl,-z,defs -Wl,--as-needed -o $@ $^ -ldl

选项-Wl,-z,defs告诉链接器,如果共享库具有未解析的未定义符号,它应该发出错误,因此将来会捕获此类型的未来问题。选项-Wl,--as-needed告诉链接器不要记录对实际上不满足任何未定义符号的库的依赖性。默认情况下,这两个都应该,但由于历史原因,它们不是。