LLVM MC 简介

LLVM - 学习笔记一 1. 工具和库 LLVM中的独立工具: opt:在IR级对程序进行优化的工具,输入必须是LLVM的bitcode,生成的输出文件必须具有相同的类型。 llc:通过特定后端将LLVM bitcode转换成目标汇编或目标问价的工具。 llvm-mc:能够汇编指令并生成像ELF、MachO、PE等对象格式的目标文件,也可以反汇编相同的对象,从而转存这些指令的相应汇编信息和内部LLVM机器指令数据结构。 lli:LLVM IP的解释器和JIT编译器。 llvm-link:将几个LLVM bitcode链接在一起, 阅读详情

1. 整体介绍

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

ca4be6e95a1209d57871c16849220ad6.png

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

  • • 输入为汇编文件,经过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 bytes
  int Size = Desc.getSize(); // FIXME: Have Desc.getSize() return the correct value

  EmitInstruction(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 function
      Result = 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 function
    Result = 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做了简单的介绍。受限于笔者知识水平,文中可能会存在某些理解身上的偏差,欢迎批评指正。

56eebd8ff64db934d5f95bcc23af5dd4.png

LLVM实战之将LLVM bitcode转回为LLVM汇编码 本文将介绍如何通过反汇编工具llvm-dis把LLVM bitcode转回为LLVM IR。前提是已经安装llvm-dis工具(在LLVM工具链中)。 阅读详情

相关推荐

LLVM的编译链工具

通常我们在命令行上调用的clang工具,是Clang驱动程序,因为LLVM本质上只是一个编译器框架,所以需要一个驱动程序把整个编译器的功能串起来,clang能够监控整个编译器的流程,即能够调用到Clang和LLVM的各种库,最终实现编译的功能。来指定输出是汇编文件还是目标文件,若生成是目标文件,llc会调用LLVM中的汇编输出的代码库来工作(注意这个汇编器和gcc的汇编器也不同,它输入的是MI,是一种后端的中间表示)。clang能够调用起来整个编译器的流程,也就是上边其他工具调用的库,它很多都同样会调用。

panpan_jiang1的博客 1776

LLVM(使用独立的工具)

它也可以反汇编相同的对象,从而转储这些指令的相应的汇编信息和内部LLVM机器指令数据结构。它结合了解释器和静态编译器的优点,可以提高程序的性能。输入必须是LLVM位码文件(编码的LLVM IR),并且生成的输出文件必须具有相同类型。-emit-llvm标志告诉clang根据是否存在-c或-S标志生成LLVM 位码或LLVM汇编码文件。-emit-llvm和-c标志一起使用,告诉clang以LLVM位码格式生成一个目标文件。:该工具将人工可读的LLVM IR 文件(称为LLVM汇编码)转换位LLVM位码。

m0_72827793的博客 1298

LLVM的源码目录结构

这是从我《一份关于各种安装LLVM的方法的总结》中分支出来的。因为这个内容写进那一篇会太杂乱。 还是以翻译+自己总结的形式写出来,官网上介绍的东西太好了。 还不完善,会持续更新其中的内容,欢迎大家指正。 目录层次结构Directory Layout 一个很有用的LLVM源码信息的来源是LLVM的doxygen文档http://llvm.org/doxygen/ llvm/examples...

chikey的博客 3699

LLVM基本概念入门

LLVM基本概念入门_c/c++_SiberiaBear的专栏-优快云博客​LLVM目前的更新很活跃,请注意跟踪项目最新变更。

luoganttcc的博客 1570

LLVM MC layer框架说明

LLVM MC(machine code) 层是整个LLVM low level 较为底层一层,主要功能是负责汇编asm,反汇编disassembly以及生成obj 和汇编功能。不管是输入类型是什么,首先第一步就需要将其输入转换到MCInst,MCInst为MC layer层对指令抽象统一处理,是MC层整个处理都是围绕MCInst进行处理。具体各个层解释会有详细说明,后续会根据AMDGPU 后端详细说明各个步骤过程。上述文档说明了MC层各个部件,但是缺乏从整体角度进行说明。

weixin_42730667的博客 2026

MC Layer Target

每种类型的backends在MC成都会有一个对应Target类,位于llvm\include\llvm\MC\TargetRegistry.h文件。Target 成员主要分为两个部分:基本信息成员以及各种回调函数XXXXFn 需要在启动时调用相应registerXXX函数进行注册,TargetRegistry.h文件中提供了各种register函数 提供XXXFn注册功能。TargetRegistry.h文件中还提供了各种creareXXXX函数,用于创建MC中各种组件。所有注册的backend Targe

weixin_42730667的博客 1114

Intro to the LLVM MC Project

Friday, April 9, 2010 Intro to the LLVM MC Project The LLVM Machine Code (aka MC) sub-project of LLVM was created to solve a number of problems in the realm of assembly, disassembly, object file form...

ronnie88597的博客 757

[QDS]从零开始,写第一个Qt Design Studio到程序调用的项目

最近在使用Qt Design Studio进行开发,但是简中网上要不就是只搜得到Qt Designer(Qt Creator内部库),要不就只搜得到一点营销号不知道从哪里搬来的账号,鉴于Qt Design Studio是一个这么强大的软件,自然是需要来进行一下小小的实践的。所以开了这篇文章,方便没有使用过Qt Design Studio 和 QML的开发者也可以快速上手QDS(Qt Design Studio)。在本文中,你将学会如何使用QDS开发一个简单的QML程序,与你的C++后端代码进行交流。

Andius的博客 8211

LLVM编译器流程——从C源码到ELF的9种中间流程

LLVM编译器流程——从C源码到ELF的9种中间流程

liteng890116的博客 1182

脆弱的冗余:链路聚合(LACP)中单条链路故障引发的网络震荡

show etherchannel summary# 查看聚合组中所有端口的标志位,健康状态应为 ‘P’ (Port-channel) 或 ‘SU’(Stand-up)。本次故障的核心教训是:网络系统对“部分故障”的容忍度和自愈能力,远比应对“完全故障”要重要和复杂得多。3.加强监控:部署网管系统,监控聚合端口的包错误计数、LACP状态变化频率,并设置阈值告警。标签: #链路聚合 #LACP故障 #网络冗余 #排障案例 #网络高可用性。修复链路:更换光模块、清洁光纤接口、检查物理线路。

danyth的博客 1983

告别F5失灵!手把手教你为Cursor配置.Net Core控制台项目专属调试环境

本文详细指导如何在Cursor编辑器中为.Net Core控制台项目配置专属调试环境,解决F5失灵等常见问题。从调试器选择到launch.json配置,再到高级调试技巧,帮助开发者高效搭建完整的调试工具链,提升开发效率。

weixin_28834765的博客 285

LLVM工具链的使用

LLVM编译工具链中较常用到的有前端和编译驱动工具clang、后端工具llc、链接器lld、中端优化器opt、汇编器llvm-mc、ELF解读工具llvm-readelf、反汇编工具llvm-objdump。后续在相关章节,还会有对TableGen代码编译器llvm-tblegen、IR链接器llvm-link等更多工具的介绍,以及用这些工具来进行各中间形态的可视化等用途的介绍。llc是LLVM的独立后端编译工具,负责由IR代码(.ll文本或.bc二进制)生成asm汇编文件,也可以生成目标文件.o。

liteng890116的博客 474

Hcaptcha验证码的‘免浏览器’破解思路:协议分析与N值算法逆向

本文深入解析Hcaptcha验证码的‘免浏览器’破解思路,通过协议分析与N值算法逆向,实现高效自动识别。文章详细拆解Hcaptcha的API交互流程,揭示关键参数`req`和`n`的生成机制,并提供轻量级实现方案,显著降低资源消耗,适用于大规模数据采集等场景。

weixin_30838873的博客 535

[转]LLVM MC Project

Intro to the LLVM MC Project The LLVM Machine Code (aka MC) sub-project of LLVM was created to solve a number of problems in the realm of assembly, disassembly, object file format handling, and a num...

weixin_30617737的博客 473

ros2 humble中使用realsense t265与d435

前提,安装realsense SDK 2.51.1版本并且能成功启动realsense-viewer V2.51.1想要在ros2中使用realsense t265,必须配合realsense SDK v2.51.1使用realsense-ros 4.51.1版本,因为新版本realsense ros2不再对t265支持下面记录源码编译安装 realsense-ros 4.51.1版本。

m0_72797388的博客 952

深入Luckfox Pico的Web界面:从Angular前端到CGI后端的RV1106 IPCWeb全栈解析

本文深入解析了基于瑞芯微RV1106芯片的Luckfox Pico设备上,IPCWeb全栈解决方案的架构与部署。详细介绍了如何通过SDK编译配置,将现代Angular前端框架与高效的C++ CGI后端结合,并利用nginx和FastCGI在嵌入式环境中构建稳定、高性能的Web管理界面,为物联网设备开发提供了完整的实战参考。

3a9bq4r8t2y的博客 275

Fuzzing llvm

目录 1.概述 2.可用的Fuzzers 2.1.clang-fuzzer 2.2.clang-proto-fuzzer 2.3.clang-format-fuzzer 2.4.llvm-as-fuzzer 2.5.llvm-dwarfdump-fuzzer 2.6.llvm-demangle-fuzzer 2.7.llvm-isel-fuzzer 2.8.llvm-op...

zhang14916的博客 1395

利用ADS设计射频功率放大器

利用ADS设计射频功率放大器 任务: 用飞思卡尔公司的功率放大器芯片ATF27s006NT1设计射频功放,芯片频率范围可达450MHz-3.6GHz。 功放指标: (1) 工作频率:500MHz (2) 增益:G>20dB (3) 电源:+28V (4) 最大输出功率:2W(33dBm) 设计思路 (1)安装DesignKit模型; (2)直流DC扫描; (3)稳定性分析; (4)偏置电路设计及整...

UVM频率 3万+

LLVM:The LLVM Target-Independent Code Generator

https://llvm.org/docs/CodeGenerator.html Introduction Required components in the code generator The high-level design of the code generator Using TableGen for target description Target description classes The TargetMachine class The DataLay.

Lifelong Learning Pan 1941

【CicadaPlayer】av_rescale_q 学习:转换PTS和Duration

参考 av_rescale_q()理解 大神时间基准的总结: AVPacket下的pts和dts以AVStream->time_base为单位(数值比较大),时间间隔就是AVStream->time_base。 大神:多种转换的总结 av_rescale_q用于计算Packet的PTS 如: if (pkt->pts != AV_NOPTS_VALUE) { pkt->pts = av_rescale_q(pkt->pts, m

突围 841

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

Folia 全屏歌词播放器教程:零基础到十分钟播出一首歌

先说你要得到什么:躺着看全屏歌词动画,手不离开键盘就能切歌。Folia 是一款全屏沉浸式歌词播放器,支持本地曲库、Navidrome 自建服务,也接网易云、QQ 音乐、酷狗等在线平台。这篇教程从目标倒着走:装好 Folia 播放器,导入音乐,十来分钟就能听到第一首歌,歌词铺满整块屏幕。 ## Folia 播放器安装方法:官方安装包与本地 Web 版 两种方式,选一种就行。 - 桌面版(推荐)

gitblog_00005的博客 472

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

llvm 编译器学习笔记

Clang c/c++ 编译器, 这里生成的clang并不是一个单独的前端,集成了中后端汇编器的所有功能,和gcc存在区别,clang不需要依赖其他二进制可以单独完成从源文件到目标文件的所有功能 lld llvm自己开发的链接器,在早期版本,llvm没有自己的链接器,是默认使用gnu binutils,后续开发了自己的链接器lld,现在版本已经默认使用lld。 我们可以看到,产物中有4个lld,其中lld是唯一二进制,其他三个均是软连接。 我们无法运行lld,如果需要链接的话,就必须根据环境运行不同的软连

~ 飞 扬 的 天 空 ~ 1913

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

LLVM测试框架

LLVM测试框架 LLVM测试框架简介 在LLVM编译器后端开发过程中,针对特定平台必然要定义特定指令集及其指令格式,并对后端流程的各个阶段或pass做相应修改。根据需求编写“测试用例”的测试驱动开发(Test-DrivenDevelopment,简称TDD)是推动开发进行的有效方法,可以在出现问题时实现可回溯,有助于编写简洁可用和高质量的代码。LLVM测试框架是在LLVM编译器后端开发过程中实现测试驱动开发的有效手段,有很高的灵活性和健壮性,可保证加速开发过程稳步进行。 本文涵盖LLVM测试框架,需

大头蚂蚁的窝 2023

如何在Ubuntu中安装llvm并进行测试

本文档适用于希望安装最新版的同学们,需要从官方下载,可从源码编译可以获取最新版本的LLVM,并支持自定义配置。

2403_86837279的博客 1734

LLVM每日谈之四十七 LLVM后端文档解析

去年在HelloLLVM杭州站的活动中,我做了一个分享:LLVM后端简介。主要是从LLVM后端的几大环节上展开,简单介绍了LLVM后端。在新的芯片和指令集大火的今天,为LLVM添加一个新的后端,也成了大家比较关注的热点。 LLVM官方提供了两个关于后端的官方文档: 1、The LLVM Target-Independent Code Generator 2、Writing an LLVM...

SHINING的博客 1568
上一篇: 致力人工智能应用落地 推动数字经济技术创新——Adlik荣获两个开源奖项
下一篇: 论文解读 | 自动编译框架AMOS
Linux基金会AI&Data基金会
博客等级 码龄6年 100粉丝 47原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Linux基金会AI&Data基金会

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值