在Linux中查找共享库的加载地址

11

在运行时,我需要打印出一个地址,并找出该地址所在的函数。这些函数位于共享库中,因此不在固定地址上。我的映射文件只显示每个共享库函数的相对偏移量。在运行时是否可以查询加载了哪个库,以便我可以从我的地址中减去该值,以获得正确的映射文件偏移量?

目前,我正在使用一种略微不规范的方法,即同时打印出库中一个函数的地址,然后在映射文件中找到该函数,以确定加载地址必须在哪里。我宁愿有一种通用的方法,不需要您命名引用函数。

(在我的设置中没有GDB可用)。 谢谢。

5个回答

8
在最近的Linux系统中,您可以使用dl_iterate_phdr函数来查找共享库的地址。

8

dladdr是这样做的,完了。:-)

更全面地说,dladdr会获取一个地址并确定它对应的库和符号...然后它会给你每个库的名称、每个符号的名称以及它们的基址。我个人认为这很棒,也让我的当前调试工作变得更容易。

希望这能帮到你!


4

请查看/proc/[PID]/maps文件。其中包含了进程内存地址空间中库映射的地址。

如果您想访问可执行部分,请在库上使用readelf,并查找.text部分的偏移量。


2

请查看System V ABI第5章,对于懒惰的人,以下是支持ELF二进制格式系统的标准方法:

#include <link.h>

off_t load_offset;
for (Elf64_Dyn *dyn = _DYNAMIC; dyn->d_tag != DT_NULL; ++dyn) {
    if (dyn->d_tag == DT_DEBUG) {
        struct r_debug *r_debug = (struct r_debug *) dyn->d_un.d_ptr;
        struct link_map *link_map = r_debug->r_map;
        while (link_map) {
            if (strcmp(link_map->l_name, libname) == 0) {
                load_offset = (off_t)link_map->l_addr;
                break;
            }
            link_map = link_map->l_next;
        }
        break;
    }
}

这不依赖于任何GNU扩展。

在GNU系统上,宏ElfW(Dyn)将返回方便的Elf64_Dyn或Elf32_Dyn。


0

GNU backtrace库?

对于这样的事情,我不会依赖于hacky方法。我认为没有任何保证库的内容被加载到连续的内存中。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接