LLVM是Low Level Virtual Machine(低级虚拟机)的简称,是一款编译器框架。但是它本质上并不是虚拟机,核心其实准确点应该是编译器相关支持。主要是支持代码优化、链接、代码生成、机器码生成。当然有的时候内部llc给人感觉确实是类似解释型语言。现在LLVM已经集成非常多的优点,模块化设计让程序员可以绕开繁琐的操作,可以快速实现一个编译器并且运行。
图:LLVM Logo
一. 编译器架构
1.0 gcc
先看看编译器结构:
图:传统编译器结构
Frontend:前端,将高级语言的代码转换成编译器所对应的中间代码。其中操作有词法分析、语法分析、语义分析、中间代码生成
Optimizer:中端,对中间代码进行优化。(代码优化其实就是编译器对代码进行简介,整洁等等的操作。)
Backend:后端,对中间代码进行转换成机器码Opcode进行运行。本质上编译器到这里已经结束了。
Linker:链接:后续还要对机器码进行链接操作,本质上就是将机器码的文件进行打包与合并成可执行文件也就是经常所说的EXE与ELF。当然这是链接器的问题了。(其实可以与后端进行合并)
图:编译器架构
但是这种架构的编译器比如GCC有很多缺点:
后端太统一
不能支持新的语言
因为后端,在新设备(处理器架构)需要重新开发后端包括中端
因为GCC前后端都是耦合在一起,想支持新的语言和处理器架构开发起来非常非常困难。
1.1 LLVM
为止LLVM以上问题得到很好解决,而且LLVM编译器使用CLANG作为前端速度是GCC速度的三倍。
LLVM与GCC对比,它统一了LLVM IR(中端),如果需要开发新的处理器架构后端,那么只需要开发后端即可。
LLVM,除了后端模块化,连前端也实现了模块化。开发者可以自定义前端规则等等,开发一门自己的编程语言。
该编译器框架被Apple、FaceBook、Google广泛应用,甚至Apple为该编译器框架开发了Clang。
图:LLVM架构
前端:LLVM前后端实现了模块化,并不进行耦合。这样子,如果需要开发一门编程语言或者把Python从解释型转换成编译型。那么只需要对应Python的前端进行开发,开发出将Python转换成LLVM IR的前端即可。这样子可以让Python的性能超越目前的编程语言。当然由于Python的设计,这种想法还是算了。
后端:这个目前市面上的芯片架构,在LLVM上均可实现运行,如果进行二开也可以通过原有的基础进行二次开发,而且过程并不繁琐,或者如果发明了新的CPU架构,
中端:中端主要是对IR进行代码优化,实现性能上的效率提高。当然可以将IR独立出来,作为解释型来使用。这样子可以实现高性能解释型语言了(滑稽 速度怎样不清楚,但是个人感觉肯定起飞)
LLVM IR/Bitcode:LLVM IR本质上是LLVM可视化的代码形式,而Bitcode是以二进制数据形式的IR代码。IR是LLVM中端的中间代码,是前端到后端的过渡代码,其功能是为了更好实现一个模块化,并且前端转换为统一格式规定的IR,然后IR转换为
1.2 Clang
Clang本质上是LLVM衍生出来的前端项目,由Apple开发。它是直接支持了C/C++/ObC++作为LLVM前端将其转化为LLVM IR,再从IR转换为后端机器码。这样子可以一个前端实现多个后端支持。(饶了),这个编译器框架我就不多描述。
二. LLVM的编译
LLVM的编译,其实非常简单。当然LLVM因为非常庞大,我不进行本地编译了,其实就是CMAKE Ninja 一键编译。LLVM可以直接下载,已经编译好的二进制文件更为推荐,要是真的对LLVM进行开刀,那么需要编译,储存需要10G-40G (我编译花了30g)。 编译时间也非常漫长。
当然LLVM-Project默认使用Clang,如果不包含CLang 那么LLVM只有中端与后端。前端需要自己重新编译,一般使用Clang即可。
三. 编译一个Helloworld
首先写一组HelloWorld的C代码
图:Helloworld代码
然后使用Clang前端进行编译,编译成IR代码,不加-S会编译成bc代码。
图:
编译IR代码
使用llvm-as 将IR代码进行转化为bc代码。并且使用llvm-bcanalyzer进行bc代码分析
图:bc代码生成
最后使用lli进行后端运行,这是属于“解释型”的。可以使用llc转换为汇编文件或者对象文件。
图:后端运行
并且使用gcc将对象文件编译成ELF。(因为LLVM链接器并不完善,所以使用gcc可以方便快捷。)
推荐站内搜索:最好用的开发软件、免费开源系统、渗透测试工具云盘下载、最新渗透测试资料、最新黑客工具下载……
还没有评论,来说两句吧...