如何在汇编代码中定位所有相对地址?可行方案咨询
问题解答
方案二的可行性
方案二是切实可行的,但无法通过GCC现有通用选项(如-fpatchable-function-entry)直接实现,需要借助编译器的插桩机制或轻量扩展:
- 对于LLVM/Clang:可以编写简单的MachineFunctionPass,遍历生成的机器指令,识别出使用相对寻址的指令(如x86的
jmp/call、ARM的b/bl等),然后在这些指令前后插入nop作为标记。LLVM的Pass框架提供成熟的指令遍历与修改接口,无需深度修改编译器核心代码,门槛相对较低。 - 对于GCC:可通过GCC插件机制,在编译中间阶段(如RTL生成后)识别相对寻址指令并插入
nop,但GCC插件的文档与生态不如LLVM友好,实现难度稍高。
需要注意:插桩时要确保nop的长度与插入位置不破坏指令对齐和执行逻辑,比如x86部分指令对字节对齐有要求,需选择合适长度的nop(1字节、2字节等)。
更高效的替代方法
除了上述两种方案,还有几个更省力且可靠的方法:
1. 解析反汇编工具的结构化输出
无需手动识别指令集,利用专业反汇编工具的结构化输出筛选相对地址:
- 使用
objdump:通过objdump -d -M intel <二进制文件>(x86)或objdump -d -M arm <二进制文件>(ARM)生成汇编,输出中相对寻址指令会明确标注偏移(如x86的jmp 0x123 <func+0x4>),可通过Python等脚本批量提取这类指令的地址与相对偏移。 - 使用radare2:通过
radare2 -q -c 'pd -j' <二进制文件>导出JSON格式的反汇编结果,其中会包含指令寻址类型的字段,直接筛选标记为相对寻址的条目即可,无需手动分析指令集细节。
2. 分析目标文件的重定位表
相对寻址在编译链接阶段会对应特定重定位条目,直接解析重定位表即可定位:
- 对于ELF格式文件:使用
readelf -r <二进制文件>或objdump -r <二进制文件>,其中R_X86_64_PC32(x86_64)、R_ARM_CALL(ARM)这类重定位类型,就是对应相对寻址的位置。若生成PIE(位置无关可执行文件),可执行文件会保留完整重定位信息;普通可执行文件可通过-Wl,-q选项让链接器保留重定位表。
3. 利用编译中间表示(IR)分析
如果能接触到编译中间阶段(如LLVM IR),可直接遍历IR指令识别相对寻址操作:
- LLVM IR中的
br(条件/无条件跳转)、call(函数调用)等指令,生成机器码时会对应相对寻址,通过LLVM的opt等工具可批量提取这些指令的位置,再映射到最终机器码地址。
内容的提问来源于stack exchange,提问作者OrangeGutanus
相关产品推荐
相关产品推荐

