如何将ELF文件中单个文件/函数转汇编?定位内核ELF指定指令
嘿,这两个问题都是内核ELF调试里很常见的场景,我给你一步步讲清楚解决方案:
1. 仅反汇编单个函数
如果已经知道函数的符号名,直接用objdump指定要反汇编的函数即可,不用处理整个ELF:
# 针对C函数(直接用函数名) objdump -d --disassemble=my_target_function file.elf # 如果是C++函数,需要先获取 mangled 后的符号名 nm file.elf | grep my_target_function # 然后用mangled后的名字替换,比如: objdump -d --disassemble=_Z17my_target_functionv file.elf
这个命令只会输出目标函数的汇编代码,干净利落。
2. 仅反汇编单个源文件对应的汇编
ELF的调试信息(.debug_info段)里记录了源文件和编译单元的对应关系,你可以借助这个来定位地址范围:
- 先通过
readelf找到目标文件对应的编译单元地址范围:
readelf -wL file.elf | grep -B 5 -A 5 "my_source_file.c"
输出里会包含该文件对应的起始和结束地址(比如Low pc和High pc)。
2. 然后用objdump反汇编这个地址范围:
objdump -d --start-address=0xSTART_ADDR --stop-address=0xEND_ADDR file.elf
如果觉得readelf的输出太繁琐,也可以用gdb更直观:
gdb file.elf (gdb) list my_source_file.c:1 # 定位到目标文件 (gdb) disassemble /m # 反汇编当前文件对应的所有函数,同时显示源码对应关系
你之前用objdump -b binary -m i386 -D file.elf的问题在于:把ELF当成纯二进制文件反汇编了,它会忽略ELF的段结构,从文件开头一直反汇编到结尾,包括所有非代码段(比如数据段、调试信息、符号表等),内核ELF本身就很大,自然会生成海量数据。
正确的做法是利用ELF的结构,只反汇编目标地址附近的代码,这里有几个高效的方法:
方法1:用objdump直接定位目标地址
先计算目标指令的绝对地址:target_addr = 函数基地址 + 指令偏移,然后用objdump只反汇编这个地址前后的范围:
# 比如查看目标地址前后共10条指令(数值可以根据需要调整) objdump -d file.elf --start-address=$((target_addr - 8)) --stop-address=$((target_addr + 32))
这个命令只会输出你关心的一小段汇编,不会生成冗余数据。
方法2:用gdb精准查看指令
gdb是处理这类问题的神器,操作更直观:
gdb file.elf # 先设置对应架构(比如x86_64就用下面的命令,i386就换成set architecture i386) (gdb) set architecture i386:x86-64 # 查看目标地址的指令 (gdb) x/i 0xTARGET_ADDR # 查看目标地址前后5条指令(共10条) (gdb) x/10i 0xTARGET_ADDR - 4*5
x/i是“examine as instruction”的意思,直接输出指定地址的汇编指令,完全不会冗余。
方法3:先确认目标地址在代码段
如果不确定目标地址是否在代码段,可以先用readelf查看.text段的范围:
readelf -S file.elf | grep .text
输出里的Addr是代码段起始地址,Size是代码段大小,确认target_addr在[Addr, Addr+Size]范围内,再进行反汇编,避免无效操作。
内容的提问来源于stack exchange,提问作者Aparna Kumari

