You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android中缺失dlinfo与dladdr1,如何获取link_map及动态段信息?

方案1:解析/proc/self/maps与ELF文件

直接读取/proc/self/maps文件,获取所有加载的共享库、主可执行文件的加载基地址和文件路径:

  • 主可执行文件对应路径为/proc/self/exe,共享库路径则指向系统或应用lib目录下的so文件
  • 拿到基地址和路径后,打开目标ELF文件,解析ELF头找到PT_DYNAMIC类型的程序段,结合加载基地址计算出动态段的虚拟地址,即可读取动态段的所有条目(如DT_HASH、DT_STRTAB等)

注意:需确保进程有读取/proc目录和对应ELF文件的权限,Android高版本SELinux可能限制对系统库的直接读取,但自身进程的文件通常不受影响。

方案2:利用libdl的私有符号(兼容性需验证)

Android的libdl库中存在未公开的link_map链表入口,可通过dlsym尝试获取:

#include <dlfcn.h>

typedef struct link_map link_map;
link_map* g_link_map = dlsym(RTLD_DEFAULT, "__link_map");

拿到链表头后,可遍历每个link_map节点:

  • l_addr:当前共享库/主程序的加载基地址
  • l_name:对应文件的路径
  • l_ld:动态段的虚拟地址(直接指向动态段起始位置)

不过要注意:私有符号在不同Android版本中可能存在变更,Android 11及以上对私有API限制更严格,此方法仅适合特定版本调试或兼容场景。

方案3:使用公开接口dl_iterate_phdr(推荐)

NDK提供的dl_iterate_phdr是最稳定的公开方案,可遍历所有加载的ELF镜像(包括主可执行文件):

#include <link.h>

int callback(struct dl_phdr_info* info, size_t size, void* data) {
    // info->dlpi_addr:加载基地址
    // info->dlpi_name:文件路径
    for (int i = 0; i < info->dlpi_phnum; i++) {
        const ElfW(Phdr)* phdr = &info->dlpi_phdr[i];
        if (phdr->p_type == PT_DYNAMIC) {
            // 动态段的虚拟地址 = info->dlpi_addr + phdr->p_vaddr
            ElfW(Dyn)* dyn = (ElfW(Dyn)*)(info->dlpi_addr + phdr->p_vaddr);
            // 遍历dyn数组,解析动态段条目
            while (dyn->d_tag != DT_NULL) {
                // 处理每个d_tag,如DT_STRTAB、DT_SYMTAB等
                dyn++;
            }
            break;
        }
    }
    return 0;
}

dl_iterate_phdr(callback, NULL);

该接口从Android 4.0(API level 14)开始支持,兼容性好,无需依赖私有符号,是优先推荐的方案。

内容的提问来源于stack exchange,提问作者localacct

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 17:40:04