自制调试器中如何解析ELF相对地址?
DWARF解析地址转进程实际内存地址的正确方法
问题根源
你错误地将DWARF解析出的地址当作.text节的文件偏移,与加载基址相加导致地址无效——DWARF给出的是ELF文件的虚拟地址(VA),并非磁盘文件里的节偏移。
关键概念区分
- 虚拟地址(VA):链接器为程序段分配的地址,PIE(位置无关可执行文件)下是相对加载基址的偏移(RVA),非PIE下就是进程运行时的实际地址。
- 文件偏移:节在可执行文件磁盘镜像中的位置偏移,和内存地址没有直接加法对应关系。
正确解析步骤
确认可执行文件类型
执行readelf -h <你的可执行文件>,查看Type字段:EXEC:非PIE文件,DWARF中的VA就是进程运行时的实际地址,直接使用即可。DYN:PIE文件,需要结合加载基址计算实际地址。
获取.text节的虚拟起始地址
执行readelf -S <你的可执行文件>,找到.text节的Addr字段(比如示例中可能是0x1000)。获取进程加载基址
查看/proc/<pid>/maps,找到对应可执行文件的r-xp权限段的起始地址(比如0x62313f55e000),注意要选路径匹配你调试的可执行文件的条目,别选共享库的。计算实际内存地址
公式:实际地址 = 加载基址 + (DWARF解析出的VA - .text节虚拟起始地址)
示例:若DWARF地址是0x1140,.text虚拟起始是0x1000,加载基址是0x62313f55e000,则实际地址为0x62313f55e000 + (0x1140 - 0x1000) = 0x62313f55e140验证地址有效性
用ptrace(PEEKDATA, pid, 实际地址, 0)读取,应该能得到正确的指令字节(比如0x55,对应push rbp)。
额外提示
- PIE文件每次启动的加载基址会被ASLR随机化,必须在进程启动后动态从
/proc/<pid>/maps获取,不能硬编码。 - 检查
/proc/<pid>/maps的条目时,确保路径是你的可执行文件路径,避免误取共享库的基址。
内容的提问来源于stack exchange,提问作者franzageek
相关产品推荐
相关产品推荐

