【问题标题】:Force specified function to be linked to a specified lib when compiling/linking编译/链接时强制指定函数链接到指定库
【发布时间】:2017-07-21 06:27:28
【问题描述】:

我想知道是否可以在编译/链接时强制链接器使用某些指定的函数来链接。

我正在使用 LD_PRELOAD 环境变量来挂钩一些指定的函数,但我对链接器不太熟悉,所以有些麻烦。我正在挂钩标准的open() 系统调用以添加一些功能,以便当用户使用open() 系统调用时,我可以收集一些数据。基本上,我正在做这样的事情:

int open(int fd, int flags, ...)  //(1)
{
    // add some functionalities here

    return open(...); // (2), return the original open system call
}

显然,这不起作用,因为它会调用无限循环......所以我想知道我是否可以强制链接器将某些函数链接到某个指定的动态库,这样它就不会导致无限循环。在上面的示例中,将 (2) 处的“open()”系统调用链接到标准库是完美的。

至于现在,因为我将 LD_PRELOAD 设置为:

export LD_PRELOAD=/path/to/my_open.so

只要加载了内部具有open() 函数的程序,动态链接器就会将该open() 链接到我的my_open.so。我的open() 也是如此:当链接器尝试在 (2) 处链接 open() 时,它也会尝试在 (1) 处将其链接到我的 open(),从而导致无限循环。

有什么想法吗?

【问题讨论】:

    标签: c compilation linker binutils


    【解决方案1】:

    链接动态符号的详细算法见man ld.so

    ELF 格式允许插入符号open@@VERSION。这对于同时保存不同版本的 libc 很有用。可能您想在LD_LIBRARY_PATH 中保留自己的.so 库。

    See here for details.

    【讨论】:

    • 如果使用不同的版本,这个open函数将不会抢占原来的open函数,所以不能用它来hook函数(如这里所想)。
    • @FlorianWeimer 是的......也许他可以使用 dlsym(open@@VERSION) 来确保他能找到正确的版本,我不知道。但是这个方法是在想保留多个/lib/libc的时候使用的。
    • @alinsoar 插入符号open@@VERSION 正是我想要的。更多提示?
    • @walkerlala 我告诉过你。 ELF 格式允许为每个符号添加@@VERSION。你可以按照 Ian Lance 的教程学习这个(最好的教程,他也是黄金链接器的创建者)http://www.airs.com/blog/archives/38 这个教程教你链接器是如何工作的,以及如何编写你自己的链接器。 .
    • @walkerlala Ian 的这个教程有 20 个部分。我记得在其中一个部分他解释了如何使用@@VERSION。
    【解决方案2】:

    您可以使用dlsym (RTLD_NEXT, "open") 检索open 的原始实现。没有其他可靠的方法可以从 LD_PRELOAD 库中获得 open 的原始定义。

    查看fakerootcwrap 等项目可能会有所启发,看看它们是如何处理这个问题的。

    【讨论】:

    • AFAIK,使用dlsym() 需要来自dlopen() 的句柄,它在内部调用open(),现在您有无限循环...您的解决方案适用于某些libc 函数,例如malloc() ,但不适用于open()
    • RTLD_NEXT 是这里的句柄。这是一个神奇的值,它指示dlsym 查看调用者地址并根据调用 DSO(不是调用函数,唉)确定下一个符号。这确实有效;请看fakeroot。 (此外,dlopen 不会再次重新打开共享对象,因此没有循环,这就是为什么 fakeroot 中旧且长期未使用的回退代码最初起作用的原因。)
    • 你说得对,RTLD_NEXT 正是我想要的。谢谢。
    猜你喜欢
    • 2012-09-14
    • 1970-01-01
    • 2013-02-23
    • 2017-10-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多