Instruction Decoder
MC Instruction Decoder属于MC层LLVM中反汇编模块,主要功能是将输入的二进制文件读写成Bytes形式,输出为对应Target 机器指令MCInst,是反汇编中不可或缺的模块:
MCDisassembler类MCDisassembler类是MC Instruction Decoder中对外提高的接口类,属于所有target disassembler的superclass,
该类位于:llvmincludellvmMCMCDisassemblerMCDisassembler.h文件
该类所接口比较少,其中最重要的一个接口:getInstruction:
virtual DecodeStatus getInstruction(MCInst &Instr, uint64_t &Size,
ArrayRef Bytes, uint64_t Address,
raw_ostream &CStream)
该接口将可执行的二进制文件以Bytes作为输入,通过反汇编输入MCInst 机器指令。
该接口是一个虚拟函数,每个target机器指令都不同,新编写一个后端都需要以MCDisassembler为基类,派生出target 对应的disassembler,实现getInstruction接口。
AMDGPU 派生关系如下:
AMDGPUDisassembler 位于llvmlibTargetAMDGPUDisassemblerAMDGPUDisassembler.h
Disassembler使用方法disassembler使用方法通常分为以下几个步骤:
RegisterMCDisassembler()当新添加一个后端,需要调用RegisterMCDisassembler向Target中注册所属disassemble, AMDGPU注册位于llvmlibTargetAMDGPUDisassembleAMDGPUDisassembler.cpp:
extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeAMDGPUDisassembler() {
TargetRegistry::RegisterMCDisassembler(getTheGCNTarget(),
createAMDGPUDisassembler);
TargetRegistry::RegisterMCSymbolizer(getTheGCNTarget(),
createAMDGPUSymbolizer);
}
RegisterMCDisassembler主要注册对应 创建disassamble回调函数createAMDGPUDisassembler。
static void RegisterMCDisassembler(Target &T,
Target::MCDisassemblerCtorTy Fn) {
T.MCDisassemblerCtorFn = Fn;
}
创建disassembler回调函数注册到MCDisassemblerCtorFn。
createMCDisassembler
createMCDisassembler创建对应MCDisassembler:
MCDisassembler *createMCDisassembler(const MCSubtargetInfo &STI,
MCContext &Ctx) const {
if (!MCDisassemblerCtorFn)
return nullptr;
return MCDisassemblerCtorFn(*this, STI, Ctx);
}
调用注册的createAMDGPUDisassemble回调函数,创建AMDGPUDisassembler。
getInstruction
将解析的二进制文件中Text 代码段中,转成ArrayRef
MCInst Inst;
bool Disassembled =
DisAsm->getInstruction(Inst, Size, Bytes.slice(Index),
SectionAddr + Index, CommentStream);
AMDGPU getInstruction()
AMDGPU 反汇编实现位于llvmlibTargetAMDGPUDisassemblerAMDGPUDisassembler.cpp文件:
实现过程思路比较清晰,反汇编主要分为两个部分:
- 首先对二进制进行反汇编,查找各种DecoderTable表,查找二进制所属指令。这一步骤的特点就是查DecoderTable表,AMDGPU按照不同架构指令以及指令类型划分成了多个DecoderTable表,需要进行逐步进行匹配。
- 匹配完成之后,针对一些特殊指令进一步处理。
DecoderTable
AMDGPU后端为了支持反汇编,内部将命令划分成了多个DecoderTable,getInstruction会依次匹配查询各个DecoderTable表进行匹配,目前存在DecoderTable主要有:
- DecoderTableGFX10_B64
- DecoderTableDPP864
- DecoderTableDPP64
- DecoderTableSDWA64
- DecoderTableSDWA964
- DecoderTableSDWA1064
- DecoderTableGFX80_UNPACKED64
- DecoderTableGFX832
- DecoderTableAMDGPU32
- DecoderTableGFX932
- DecoderTableGFX90A32
- DecoderTableGFX10_B32
- DecoderTableGFX1032
- DecoderTableGFX90A64
- DecoderTableGFX864
- DecoderTableAMDGPU64
- DecoderTableGFX964
- DecoderTableGFX1064
以上DecoderTable有TableGen在编译阶段自动生成到build/lib/Target/AMDGPU/AMDGPUGenDisassemblerTables.inc文件中,手动生成命令:
llvm-tblgen -gen-disassembler./AMDGPU.td -I ../../../include
以DecoderTableGFX932为例说明GFX 32位 DecoderTable表:
每行开头MCD::OPC_XXXX为对应状态,以及决定后续数字值意义
例如开头 MCD::OPC_ExtractField 后续25,7为下一步跳转匹配的起始和结束位置,start=25, end=31.
decodeInstruction
decodeInstruction为根据传入的DecoderTable 表,进行反汇编解码,位于build/lib/Target/AMDGPU/AMDGPUGenDisassemblerTables.inc文件中,
根据匹配表中MCD::OPC_XXXX进行匹配操作,直到MCD::OPC_Decode 状态说明在该DecoderTable表匹配成功,否则 MCD::OPC_Fail匹配失败,尝试使用下一个DecoderTable表进行匹配
以下为例:
MCD::OPC_Decode, 236, 127, 46, // Opcode: V_ADDC_CO_U32_e32_gfx9
236,127为对应求解出对应的opcode, 最高第8个bit位标志位,当置位代表该opcode大于128 需要拆分成多个,直到最高位不是1为止,计算方法如下:
(236&~128)+ 127<<7
46对应DecodeIdx,decodeToMCInst决定后续operand 寄存器解析操作:
最终将反汇编出机器指令MCInst.



