比使用LD_PRELOAD的细粒度控件?

问题描述 投票:0回答:2

我在Linux上有一个动态链接的ELF可执行文件,我想在与其链接的库中交换一个函数。使用LD_PRELOAD,我当然可以提供一个小的库来代替我自己编译的函数。但是,如果在替换中我想调用原始库函数怎么办?例如,该函数可能是srand(),我想用自己的种子选择劫持它,否则让srand()正常执行操作。

如果要进行链接以使所述可执行文件,我将使用链接器的wrap选项,但是在这里,我只有编译的二进制文件。

我看到的一个简单的解决方案是将原始库函数的源代码剪切并粘贴到替换文件中-但是当源不可用时,我想处理更一般的情况。或者,我可以将所需的额外代码十六进制编辑为二进制文件,但这特定于二进制文件,而且很耗时。有什么比这两个更优雅的呢?像是装载机有魔力吗?

(抱歉,如果我没有完全使用术语...)

shared-libraries elf ld-preload
2个回答
0
投票

规范的答案是使用dlsym(RTLD_NEXT, ...)

man page

RTLD_NEXT
          Find the next occurrence of the desired symbol in the search
          order after the current object.  This allows one to provide a
          wrapper around a function in another shared object, so that,
          for example, the definition of a function in a preloaded
          shared object (see LD_PRELOAD in ld.so(8)) can find and invoke
          the "real" function provided in another shared object (or for
          that matter, the "next" definition of the function in cases
          where there are multiple layers of preloading).

另请参见this article


-1
投票

这里是包装malloc的示例:

// LD_PRELOAD will cause the process to call this instead of malloc(3)
// report malloc(size) calls
void *malloc(size_t size)
    {
    // on first call, get a function pointer for malloc(3)
    static void *(*real_malloc)(size_t) = NULL;
    static int malloc_signal = 0;
    if(!real_malloc)
        {
        // real_malloc = (void *(*)(size_t))dlsym(RTLD_NEXT, "malloc");
        *(void **) (&real_malloc) = dlsym(RTLD_NEXT, "malloc");
        }
    assert(real_malloc);
    if (malloc_signal == 0)
        {
        char *string = getenv("MW_MALLOC_SIGNAL");
        if (string != NULL)
            {
            malloc_signal = 1;
            }
        }

    // call malloc(3)
    void *retval = real_malloc(size);
    fprintf(stderr, "MW! %f malloc size %zu, address %p\n", get_seconds(), size, retval);
    if (malloc_signal == 1)
        {
        send_signal(SIGUSR1);
        }
    return retval;
    }
© www.soinside.com 2019 - 2024. All rights reserved.