获取动态加载库的地址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);
}
...
任何人都可以帮助我找出如何获取动态加载库的地址 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);
}
...