开发和调试第一个 LLVM Pass
1. 下载和编译 LLVM
LLVM 下载地址 http://releases.llvm.org/download.html,
目前最新版是 6.0.0,下载完成之后,执行 tar 解压 llvm 包:
|
1
2
|
tar -xzvf llvm-6.0.0.src.tar.xz
|
再下载 Clang 解压:
|
1
2
|
tar -xzvf cfe-6.0.0.src.tar.xz
|
将 cfe-6.0.0.src 目录复制到 llvm-6.0.0.src/tools,重命名为 clang。通过 brew 安装 cmake:
|
1
2
|
brew install cmake
|
然后在命令行下切换到 llvm-6.0.0.src 目录,新建 build 目录,切换到 build 目录执行 cmake 生成配置文件,命令如下:
|
1
2
3
4
|
mkdir build
cd build
cmake -G Xcode CMAKE_BUILD_TYPE="Debug" ..
|
执行完成之后,可以看到 Xcode 的工程文件 LLVM.xcodeproj,打开工程文件,会提示是否自动创建 Schemes,如图所示:

点击 Manually Manage Schemes 手动创建,添加 ALL_BUILD,如图所示:

然后在 Xcode 上进行编译,编译过程比如慢,可能得二十分钟到半小时左右,全部编译完文件会在 11G 左右。
2. 编写 Pass 代码
我们编写第一个 Pass 的功能很简单,只是输出程序中的每个方法名,操作步骤如下:
(1) 在 lib/Transforms 目录下新建一个文件夹,文件夹名称为 FirstPass,在 FirstPass 目录下创建文件 FirstPass.cpp,代码如下:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
//导入头文件
#include "llvm/ADT/Statistic.h"
#include "llvm/IR/Function.h"
#include "llvm/Pass.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm; //指定所使用的 LLVM 命名空间
namespace {
//定义 First 类继承自 FunctionPass
struct First : public FunctionPass {
static char ID; // Pass ID
First() : FunctionPass(ID) {}
//定义 runOnFunction 重载继承父类的抽象虚函数
bool runOnFunction(Function &F) override {
//打印每个函数的名字
errs() << "First: ";
errs().write_escaped(F.getName()) << '\n';
return false;
}
};
}
char First::ID = 0; //初始化 Pass ID
//最后注册 FirstPass, 指定命令行参数为 First
static RegisterPass X("First", "First Pass");
|
(2) 然后再在 lib/Transforms/TestPass 下新建 CMakeList.txt,编辑内容如下:
|
1
2
3
4
5
6
7
8
9
|
add_llvm_loadable_module( LLVMFirstPass
FirstPass.cpp
DEPENDS
intrinsics_gen
PLUGIN_TOOL
opt
)
|
(3) 在 lib/Transforms/CMakeLists.txt 添加 add_subdirectory(FirstPass)
(4) 重新编译整个工程,添加 LLVMFirstPass 到 Scheme,如图:

编译 LLVMFirstPass 成功之后,动态库保存在 build/Debug/lib/LLVMFirstPass.dylib。
3. 使用 opt 加载和调试 Pass
(1) 编写一段测试代码:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
#include <stdio.h>
int test() {
printf("test\n");
return 0;
}
int main(){
int num = 1;
printf("main %d\n", num);
test();
return 0;
}
|
编译源文件,生成 Bitcode:
|
1
2
|
clang -emit-llvm -c test.c -o test.bc
|
(2) 在 Xcode 中将 opt 添加到 scheme,编辑 scheme 的启动参数,-load 参数指向 LLVMFirstPass.dylib,-First 参数就是刚才在源代码里注册的参数,如图所示:

编译 opt 并运行起来,可以看到输出了程序的每个函数名称,并且前面还打印了 First 字符串,效果如下:
|
1
2
3
4
|
First: test
First: main
Program ended with exit code: 0
|
opt 编译成功保存在 build/Debug/bin/opt。也可以给 pass 的代码下断点,在 Xcode 上运行 opt 就可以调试 pass,效果如图:

开发和调试第一个 LLVM Pass的更多相关文章
- tomcat开发远程调试端口以及利用eclipse进行远程调试
一.tomcat开发远程调试端口 方法1 WIN系统 在catalina.bat里: SET CATALINA_OPTS=-server -Xdebug -Xnoagent -Djava.compi ...
- 使用VS Code 从零开始开发并调试.NET Core 应用程序
最新文章:http://www.cnblogs.com/linezero/p/VSCodeNETCore.html 使用VS Code 从零开始开发并调试.NET Core 应用程序,C#调试. 上一 ...
- Asp.net Mvc模块化开发之“开启模块开发、调试的简单愉快之旅”
整个世界林林种种,把所有的事情都划分为对立的两个面. 每个人都渴望的财富划分为富有和贫穷,身高被划分为高和矮,身材被划分为胖和瘦,等等. 我们总是感叹,有钱人的生活我不懂;有钱人又何尝能懂我们每天起早 ...
- Web程序员开发App系列 - 开发我的第一个App,源码下载
Web程序员开发App系列 Web程序员开发App系列 - 认识HBuilder Web程序员开发App系列 - 申请苹果开发者账号 Web程序员开发App系列 - 调试Android和iOS手机代码 ...
- Nginx 模块开发(1)—— 一个稍稍能说明问题模块开发 Step By Step 过程
1. Nginx 介绍 Nginx是俄罗斯人编写的十分轻量级的HTTP服务器,它的发音为“engine X”, 是一个高性能的HTTP和反向代理服务器,同时也是一个IMAP/POP3/S ...
- 搭建Go开发及调试环境(LiteIDE + GoClipse)
搭建Go开发及调试环境(LiteIDE + GoClipse) -- Windows篇 这里以Windows7 64位为例,如果是32位环境需安装对应版本程序. 一.安装golang1.2.2 1.3 ...
- 开发并调试 Mail Add-in
开发并调试 Mail Add-in (mail app for Outlook) 准备工作 如果你的邮箱搭建在 Exchange Server 上,则可以创建邮件应用程序(Mail Add-in)来扩 ...
- Xcode开发和调试总结
Xcode是iOS开发主要的工具.IDE.关于Xcode的细枝末节,可以参考苹果的官方文档或者众多的说明.此文档主要涉及常用开发和调试注意事项,参考版本为Xcode 5.1.1. 目标设置: 在此,我 ...
- vue.js拓展篇(8):测试开发与调试
内容 第15章:测试开发与调试 任何实际项目的开发,除了功能性代码的完成,规范的开发流程和严谨的测试都是不可或缺的.合理使用工具将事半功倍. 1.ESLint ESLint是Lint语法检查工具,避免 ...
随机推荐
- Android SQLite与AutoCompleteTextView
读取SQLite中的数据显示在AutoCompleteTextView中,支持动态加入SQLite中不存在的数据. package zhang.ya; import java.io.File; imp ...
- WPF&Silverlight5 常用功能差异
一晃从Wpf转到sl也有半年多了,总想总结一下wpf和sl的差异,今天终于下笔. 首先来个整体图: 通过上图可以发现其实sl只是使用了wpf的一小部分,只是sl依赖的freamwork有很大部分都一样 ...
- c# 修改winform中app.config的配置值
public bool ChangeConfig(string AppKey,string AppValue) { bool result = true; try { XmlDocument xDoc ...
- mobile webiste 中的css的font-size em及line-height等换算
在mobile web设计 中,我们常常需要使用em这个字体大小的单位.em到底是多少呢? em到底应该设置为多少个em呢?通常换算成方法是1em=target fontsize we want/fo ...
- js中公有方法、特权方法、静态方法
1.公有属性和公有方法 1 2 3 4 5 6 7 8 9 function User(name,age){ this.name = name;//公有属性 this.age = age; } ...
- 阿里云免费ssl,https证书的申请和校验
其实写这个之前一直在考虑要不要写出来 ,真的官方文档实在太强大了,连视频都给你录好了,配不好的,是不是可以考虑不用写程序了, 忽然想到第一次使用微信测试号,进行域名认证的时候,因为后台返回“echar ...
- [转]ubuntu下整合eclipse和javah生成jni头文件开发android的native程序
转载自:http://blog.csdn.net/jiuyueguang/article/details/9404237 本文介绍两种利用javah命令生成jni头文件的方法,第一种为大众所知的jav ...
- Webpack笔记(一)——从这里入门Webpack
准备了挺久,一直想要好好深入了解一下Webpack,之前一直嫌弃Webpack麻烦,偏向于Parcel这种零配置的模块打包工具一些,但是实际上还是Webpack比较靠谱,并且Webpack功能更加强大 ...
- 折腾apt源的时候发生的错误
在折腾Ubuntu源的时候,把新的源替换进去,然后 sudo apt-get update 之后报错: W: Unknown Multi-Arch type 'no' for package 'com ...
- 如何创建.gitignore文件
为什么要创建.gitignore文件? 因为.gitignore可以排除提交时携带的不必要文件,比如Java中的.class文件.同时还可以排除其他不想提交或者提交没这个必要的文件等等. 创建步骤如下 ...