1. 整体介绍

LLVM MC (machine code) 层位于LLVM的底层,主要功能是负责汇编 (assembly)、反汇编 (disassembly)、以及生成二进制文件。作为LLVM的子项目,可以通过llvm-mc、llvm-objudump等工具直接操纵MC层。LLVM MC 的核心是引入了新的'MCInst'类来表示一个带有操作数的指令,这与代码生成器现有的指令概念'MachineInstr'不同。LLVM MC 整体框架如下图所示:

按照输入不同主要分为两条路径:

  • • 输入为汇编文件,经过Assembly Parser将汇编文件中的指令解析成Operand,然后通过MCTargetAsmParser将Operand转换成对应的MCInst,最终进入到MCStreamer,通过Instruction Encoder生成二进制文件。

  • • 输入为二进制文件,经过Instruction Decoder,将二进制代码反汇编生成MCInst, 最终进入到MCStreamer按照需要生成汇编文件。

LLVM MC的主要构成部分包括:

  • • Instruction Encoder

  • • Instruction Decoder

  • • Assembly Parser

其中Instruction Encoder主要提供汇编接口,各个后端 (Target) 需要根据自己需求来实现具体的反汇编功能; Assembly Parser负责对汇编文件中的指令进行解析。

下面以LLVM的后端Cpu0为例介绍这三个组件。

2. LLVM MC 构成部分介绍

(1) Assembly Parser

Cpu0后端的Assembly Parser的作用是将汇编文件中的指令解析为LLVM MCInst,其由一个源文件'Cpu0AsmParser.cpp'组成,该文件包含从'MCTargetAsmParser'继承的‘Cpu0AsmParser’类:

public:Cpu0AsmParser(const MCSubtargetInfo &sti, MCAsmParser &parser,const MCInstrInfo &MII, const MCTargetOptions &Options): MCTargetAsmParser(Options, sti, MII), Parser(parser) {setAvailableFeatures(ComputeAvailableFeatures(getSTI().getFeatureBits()));}MCAsmParser &getParser() const { return Parser; }MCAsmLexer &getLexer() const { return Parser.getLexer(); }

在类声明中出现了以下两行,用于导入TableGen中与汇编的相关指令生成的函数。

#define GET_ASSEMBLER_HEADER
#include "Cpu0GenAsmMatcher.inc"

在'Cpu0AsmParser.cpp'中定义了Cpu0Operand类,包含了需要被解析的机器指令的操作数类型和内容信息。

class Cpu0Operand : public MCParsedAsmOperand {enum KindTy {k_Immediate,k_Memory,k_Register,k_Token} Kind;

(2) Instruction Encoder

Cpu0后端的Instruction encoder的作用是通过Cpu0MCCodeEmitter类将LLVM MCInst编码为二进制码。其具体实现位于'Cpu0MCCodeEmitter.cpp'中:

void Cpu0MCCodeEmitter::encodeInstruction(const MCInst &MI, raw_ostream &OS,SmallVectorImpl<MCFixup> &Fixups,const MCSubtargetInfo &STI) const {uint64_t Binary = getBinaryCodeForInstr(MI, Fixups, STI);// Check for unimplemented opcodes.unsigned Opcode = MI.getOpcode();if ((Opcode != Cpu0::NOP) && !Binary)llvm_unreachable("unimplemented opcode in encodeInstruction()");const MCInstrDesc &Desc = MCII.get(MI.getOpcode());uint64_t TSFlags = Desc.TSFlags;// Pseudo instruction don't get encoded// and shouldn't be here in the first place.if ((TSFlags & Cpu0II::FrmMask) == Cpu0II::Pseudo)llvm_unreachable("Pseudo opcode found in encodeInstruction()");// For now all instruction are 4 bytes or 8 bytesint Size = Desc.getSize(); // FIXME: Have Desc.getSize() return the correct valueEmitInstruction(Binary, Size, OS);
}

(3) Instruction Decoder

Cpu0后端的Instruction Decoder的作用是将一个抽象的字节序列转化成一个'MCInst'和一个'Size',其由一个源文件'Cpu0Disassembler.cpp'组成,扩展了'MCDisassembler'类,并以'getInstruction'函数为中心。此函数对字节序列进行解码,并将此信息储存在提供的'MCInst'中:

DecodeStatus Cpu0Disassembler::getInstruction(MCInst &Instr, uint64_t &Size,ArrayRef<uint8_t> Bytes,uint64_t Address,raw_ostream &VStream,raw_ostream &CStream) const {DecodeStatus Result;const unsigned MaxInstBytesNum = (std::min)((size_t)8, Bytes.size());Bytes_ = Bytes.slice(0, MaxInstBytesNum);do {if (Bytes_.size() >= 8) {uint64_t Insn;Result = readInstruction64(Bytes_, Address, Size, Insn, IsBigEndian);if (Result == MCDisassembler::Fail)return Result;// Calling the auto-generated decoder functionResult = decodeInstruction(DecoderTableCpu064, Instr, Insn, Address, this,STI);if (Result != MCDisassembler::Fail) {Size = 8;break;}}if (Bytes_.size() < 4)break;Bytes_ = Bytes_.slice(0, 4);uint32_t Insn;Result = readInstruction32(Bytes_, Address, Size, Insn, IsBigEndian);if (Result == MCDisassembler::Fail)return Result;// Calling the auto-generated decoder functionResult = decodeInstruction(DecoderTableCpu032, Instr, Insn, Address, this, STI);if (Result != MCDisassembler::Fail) {Size = 4;break;}} while (false);return Result;
}

'Cpu0Disassembler.cpp'提供了获取指令操作数类型、编码的寄存器值、以及内存中可以找到该指令的地址的函数。这些函数的名称由TableGen在构建解码表时定义但遵循'DecodeRegClassRegisterClass'的形式:

static DecodeStatus DecodeGPROutRegisterClass(MCInst &Inst,unsigned RegNo,uint64_t Address,const void *Decoder) {return DecodeCPURegsRegisterClass(Inst, RegNo, Address, Decoder);
}static DecodeStatus DecodeSRRegisterClass(MCInst &Inst,unsigned RegNo,uint64_t Address,const void *Decoder) {return DecodeCPURegsRegisterClass(Inst, RegNo, Address, Decoder);
}
static DecodeStatus DecodeSimm14(MCInst &Inst,unsigned Insn,uint64_t Address,const void *Decoder) {Inst.addOperand(MCOperand::createImm(SignExtend32<14>(Insn)));return MCDisassembler::Success;
}static DecodeStatus DecodeSimm32(MCInst &Inst,unsigned Insn,uint64_t Address,const void *Decoder) {Inst.addOperand(MCOperand::createImm(SignExtend32<32>(Insn)));return MCDisassembler::Success;
}

3. 总结

LLVM MC 引入 MCInst 类,使得能够在合适位置添加指令描述 (instruction description),而同时获得汇编器 (assembler)、反汇编器 (disassembler) 和编译器后端支持 (compiler backend support)。对于新的LLVM后端如果要实现MC层的功能,需要添加与具体后端相关的AsmParser,以及实现与具体后端相关的反汇编功能。

本文针对 LLVM MC做了简单的介绍。受限于笔者知识水平,文中可能会存在某些理解身上的偏差,欢迎批评指正。

LLVM MC 简介相关推荐

  1. 架构编译器框架系统 LLVM 使用简介

    2019独角兽企业重金招聘Python工程师标准>>> LLVM 是什么 LLVM 是 low level virtual machine(底层虚拟机)的简称,它是一个开源的编译器架 ...

  2. LLVM一些语法规则

    LLVM一些语法规则 LLVM文档 LLVM编译器基础架构支持广泛的项目,从工业强度编译器到专门的JIT应用程序,再到小型研究项目. 同样,文档分为几个针对不同受众的高级别分组: LLVM设计概述 几 ...

  3. 编译优化 | LLVM代码生成技术详解及在数据库中的应用

    简介:作者:长别 1. 前言 随着IT基础设施的发展,现代的数据处理系统需要处理更多的数据.支持更为复杂的算法.数据量的增长和算法的复杂化,为数据分析系统带来了严峻的性能挑战.近年来,我们可以在数据库 ...

  4. LLVM每日谈 | 知乎

    llvm是什么? llvm是low level virtual machine的简称,其实是一个编译器框架.llvm随着这个项目的不断的发展,已经无法完全的代表这个项目了,只是这种叫法一直延续下来. ...

  5. 基于LLVM编译器的IDA自动结构体分析插件

    引用 这篇文章旨在介绍一款对基于LLVM的retdec开源反编译器工具进行二次开发的IDA自动结构体识别插件实现原理分析 文章目录 引用 简介 源码分析 LLVM编译器简介 Retdec源码分析 Kl ...

  6. LLVM文档目录框架(索引用)

    注1:主要用于个人学习LLVM查找用,后续会继续更新 注2:加红文字可以ctrl+鼠标点击跳转到对应官方文档 注3:目前大致目录框架如下 概述 LLVM 编译器简介演示文稿 LLVM 简介 LLVM: ...

  7. MC Layer Target

    Target 每种类型的backends在MC成都会有一个对应Target类,位于llvm\include\llvm\MC\TargetRegistry.h文件. Target包含了对应backend ...

  8. 浅谈 iOS Device ID 的修改

    Dark side of the Force 最近有一篇 文章 介绍了如何实现 AppStore App 自动下载,笔者看后收获良多.不过文中只介绍了如何去模拟用户的操作来完成下载,并没有涉及抹机.I ...

  9. NJ大学PA学习记录

    PB学习笔记(7.26) 1.常见问题(7.26) 我总觉得讲义写得不清楚:毕业工作后,不会再有讲义具体地告诉你应该做什么, 总有一天你需要在脱离讲义的情况下完成任务. 我们希望你现在就放弃" ...

最新文章

  1. js计算价格,保留小数
  2. Android攻城狮Gallery和ImageSwitcher制作图片浏览器
  3. MySQL 服务挂了 CPU 消耗接近 100% 你知道怎么回事吗???
  4. Twow ndows,笔者教您syswow64 【设置步骤】 的详细方法_
  5. linux拿虚拟机充当路由,Linux通过虚拟机模拟路由器实现主机跨路由通信
  6. c语言程序设计身高体重测评系统,C语言程序设计验.doc
  7. Maple公式推导教程
  8. java学生管理系统
  9. 计算机科学ppt模板,计算机科学与技术ppt模板
  10. 企业微信开发(1)——整体说明
  11. 对话惠普亚太区高管:绿色智慧的中国战略
  12. linux 默认网关自动消失,route add default gw 添加默认网关,重起后消失
  13. 秦九韶算法介绍及MATLAB实现
  14. 数据分析-北京房价项目
  15. 深度学习 pytorch cifar10数据集训练
  16. python音频加速_python将音频进行变速的操作方法
  17. 第四十一章 贪心算法——排序不等式
  18. 服务器虚拟化 硬件分区 电气隔离,HPE Integrity BL860c i6
  19. 新型发明创造大赛计算机类,关于组织参加成都市第三十三届青少年科技创新大赛的通知...
  20. RHCA-RH436 V1.1.12-PCS集群

热门文章

  1. [UOJ500]任意基DFT
  2. Google优化工具Timeline的使用(Chrome 57已经改为performance(性能模板))
  3. 该进程为关键系统进程,任务管理器无法结束进程
  4. 如何免费旁听Coursera付费课程(申请付费证书,成为全球翻译志愿者)
  5. 故宫屋顶的小动物干嘛用
  6. Bootstrapping算法的过程
  7. 计算机再带word打不开怎么办,小编教你电脑word打不开怎么办
  8. 前端基础之JavaScript
  9. Python opencv调用笔记本电脑摄像头
  10. leetcode刷题(53)——52. N皇后 II