使用dl_iterate_phdr获取共享对象大小的相关技术疑问
dl_iterate_phdr相关问题解答
1. 如何在使用dl_iterate_phdr时获取共享对象的大小?
通过遍历struct dl_phdr_info中的程序头数组(dlpi_phdr),筛选出类型为PT_LOAD的段,计算每个LOAD段的结束地址(基址dlpi_addr + 段偏移p_vaddr + 段内存大小p_memsz),最终取所有PT_LOAD段结束地址的最大值,减去共享对象的加载基址dlpi_addr,得到的就是整个共享对象的内存占用大小。
2. 为什么struct dl_phdr_info结构体中没有size成员?
原因主要有两点:
- 共享对象的“大小”没有统一定义:不同场景下需要的大小统计范围不同——有的仅需统计可加载段的总大小,有的可能要包含非加载段,动态链接器无法预设一个满足所有需求的“标准大小”。
- 设计理念导向:
dl_iterate_phdr的核心是暴露程序头原始信息,把具体计算逻辑交给调用者,既保持了结构体的简洁性,又能让用户根据自身需求灵活处理,避免冗余。
3. 是否必须解析/proc/self/maps来实现该需求?
不需要。通过dl_iterate_phdr遍历程序头的方式就能直接计算出大小,而且这种方法不依赖/proc文件系统(部分嵌入式Linux环境可能没有/proc),比解析/proc/self/maps更直接高效。解析/proc/self/maps是另一种可行方案,但绝非必须。
修改后的示例代码
#define _GNU_SOURCE #include <link.h> #include <stdio.h> #include <stdint.h> int iterate(struct dl_phdr_info *info, size_t size, void *data) { if (info->dlpi_name[0] == '\0') { // 可选择跳过主程序,不需要则删除此判断 return 0; } uintptr_t max_end = 0; for (int i = 0; i < info->dlpi_phnum; ++i) { const ElfW(Phdr) *phdr = &info->dlpi_phdr[i]; if (phdr->p_type == PT_LOAD) { uintptr_t seg_end = info->dlpi_addr + phdr->p_vaddr + phdr->p_memsz; if (seg_end > max_end) { max_end = seg_end; } } } size_t so_size = max_end - info->dlpi_addr; printf("lib '%s' was loaded at %lx and the size is %zu bytes\n", info->dlpi_name, (unsigned long)info->dlpi_addr, so_size); return 0; } int main() { dl_iterate_phdr(&iterate, NULL); return 0; }
内容的提问来源于stack exchange,提问作者zomega
相关产品推荐
相关产品推荐

