LLVM Pass 初探

49 篇文章 0 订阅

最近研究了一下用llvm对源代码进行分析, 如在特定的指定中插入函数, 分析函数访存次数等, 下面做一些记录.


1. 首先要配置环境

先到 llvm 官网下载最新版llvm源码. 我下载的是 3.5.0 版本. 解压到用户主目录. 我的文件名是 llvm-3.5.0.src.

cd ~/llvm-3.5.0.src

./configure

./make

编译的时间比较长, 耐心等待.


2.  将源文件编译成bitcode文件

Getting Started with the LLVM System 一文最后的example提供了方法:

假设源文件名为 hello.c编译生成 .bc 文件, 也就是中间代码文件.

% clang -O3 -emit-llvm  -c hello.c -o hello.bc


3. 编写pass文件并编译

这里有一篇官方教程: Writing an LLVM Pass

在源码目录的lib/Transforms/下新建一个文件夹 my_pass.

在my_pass 目录中编写pass文件和Makefile, 

pass文件实际上是一个cpp文件, Writing an LLVM Pass中有一个示例:

#include "llvm/Pass.h"
#include "llvm/IR/Function.h"
#include "llvm/Support/raw_ostream.h"

using namespace llvm;

namespace {
  struct Hello : public FunctionPass {
    static char ID;
    Hello() : FunctionPass(ID) {}

    virtual bool runOnFunction(Function &F) {
      errs() << "Hello: ";
      errs().write_escaped(F.getName()) << '\n';
      return false;
    }
  };
}

char Hello::ID = 0;
static RegisterPass<Hello> X("hello", "Hello World Pass", false, false);

Makefile 文件:

# Makefile for hello pass

# Path to top level of LLVM hierarchy
LEVEL = ../../..

# Name of the library to build
LIBRARYNAME = Hello

# Make the shared library become a loadable module so the tools can
# dlopen/dlsym on the resulting library.
LOADABLE_MODULE = 1

# Include the makefile implementation stuff
include $(LEVEL)/Makefile.common

到了这一步之后, 官方教程出了点问题, 官方教程说直接在my_pass目录执行make命令, 实际上这是错的, 会出现 这个问题. 正确的做法是:

(1) 先修改 llvm-3.5.0.src/lib/Transforms 目录下的Makefile文件, 在变量PARALLEL_DIRS后加入你新建的目录名 my_pass, 不加的话make的时候不会编译你新建的目录.

(2) 再回到源码目录 llvm-3.5.0.src/ 先执行make, 这个时候就会编译你的my_pass目录下的pass文件了. 并在 llvm-3.5.0.src/Release+Asserts/lib 目录下会生成 一个对应的Hello.so文件, 这就是可以被opt命令加载的文件了.


4. run a pass with opt

进入到my_pass目录, 执行

opt -load ../../../Release+Asserts/lib/Hello.so -hello < hello.bc > /dev/null


5. 记录特定指令执行次数的方法

http://llvm.org/docs/ProgrammersManual.html#statistic

Often you may run your pass on some big program, and you’re interested to see how many times it makes a certain transformation. Although you can do this with hand inspection, or some ad-hoc method, this is a real pain and not very useful for big programs. Using the Statistic class makes it very easy to keep track of this information, and the calculated information is presented in a uniform manner with the rest of the passes being executed.

There are many examples of Statistic uses, but the basics of using it are as follows:

  1. Define your statistic like this: s/ProgrammersManual.html#the-statistic-class-stats-option
#define DEBUG_TYPE "mypassname"   // This goes before any #includes.

#include "llvm/ADT/Statistic.h"

STATISTIC(NumXForms, "The # of times I did stuff");

The STATISTIC macro defines a static variable, whose name is specified by the first argument. The pass name is taken from the DEBUG_TYPE macro, and the description is taken from the second argument. The variable defined (“NumXForms” in this case) acts like an unsigned integer.

  1. Whenever you make a transformation, bump the counter:
++NumXForms;   // I did stuff!

That’s all you have to do. To get ‘opt‘ to print out the statistics gathered, use the ‘-stats‘ option:

$ opt -stats -mypassname(这里好像有问题, 加了mypassname参数会报错, 去掉就好了) < program.bc > /dev/null
... statistics output ...


参考:

https://sites.google.com/site/arnamoyswebsite/Welcome/updates-news/llvmpasstoinsertexternalfunctioncalltothebitcode

Writing an LLVM Pass

http://llvm.org/docs/ProgrammersManual.html#the-statistic-class-stats-option

http://llvm.org/doxygen/classllvm_1_1Pass.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值