获取动态加载库的地址space

Get the address space of a dynamic loaded library

任何人都可以帮助我找出如何获取动态加载库的地址 space 吗?

上下文: 我正在使用 dlopen 加载一个共享库,在其他时候我想追踪 malloc 调用,但仅限于由该库触发的调用。

我现在正在做的是在我拥有的 malloc 钩子中,我正在遍历整个调用堆栈(由 backtrace 获得)并使用 dladdr 我'我正在检查每个函数指针以查看它是否来自我的共享库,但它非常慢。

我想也许如果我只关心我手动加载的一个库,我就可以得到它的地址 space,就像它在内存映射输出中一样:

$ cat /proc/2049/maps | head
00400000-007a8000 r-xp 00000000 08:01 526896    /usr/bin/python3.5
009a8000-009aa000 r--p 003a8000 08:01 526896    /usr/bin/python3.5
...

并查看调用堆栈中的函数地址是否包含在该地址中space?我想它应该快得多......我该怎么做?也许我可以使用 dlsym 获得库的 .text 符号地址(因为我只关心可执行代码的地址),但是如何计算大小呢?

在你的插入函数中,你可以使用uintptr_t caller_address = (uintptr_t)__builtin_extract_return_addr(__builtin_return_address(0));来获取调用者的地址。

要找出哪些地址来自哪些 ELF 文件,请解析 /proc/self/maps,或使用 dl_iterate_phdr()。例如:

#define _POSIX_C_SOURCE 200809L
#define _GNU_SOURCE
#include <stdlib.h>
#include <link.h>
#include <string.h>
#include <stdio.h>

static int iterator(struct dl_phdr_info *info, size_t size, void *data)
{
    const char  *name;
    size_t       headers, h;

    /* Empty name refers to the binary itself. */
    if (!info->dlpi_name || !info->dlpi_name[0])
        name = (const char *)data;
    else
        name = info->dlpi_name;

    headers = info->dlpi_phnum;
    for (h = 0; h < headers; h++)
        if ((info->dlpi_phdr[h].p_type == PT_LOAD) &&
            (info->dlpi_phdr[h].p_memsz > 0) &&
            (info->dlpi_phdr[h].p_flags)) {
            const uintptr_t  first = info->dlpi_addr + info->dlpi_phdr[h].p_vaddr;
            const uintptr_t  last  = first + info->dlpi_phdr[h].p_memsz - 1;

            /* Addresses first .. last, inclusive, belong to binary 'name'. */
            printf("%s: %lx .. %lx\n", name, (unsigned long)first, (unsigned long)last);
        }

    return 0;
}

int main(int argc, char *argv[])
{
    if (dl_iterate_phdr(iterator, argv[0])) {
        fprintf(stderr, "dl_iterate_phdr() failed.\n");
        exit(EXIT_FAILURE);
    }

    ...