一、基础知识:llvm各种格式文件转换图
llvm主要具有以下几种格式的文件,其转换和关系图图中所示。
1) a.c,源代码。
2) a.bc,llvm的字节码的二进制形式。
3) a.ll,llvm字节码的文本形式。
4) a.s,机器汇编码表示的汇编文件。
5) a.out,可执行的二进制文件。
使用clang可以直接把源代码(a.c)编译为本机可执行文件(a.out)。
使用clang -emit-llvm -c可以把源代码(a.c)转换为llvm字节码的二进制格式文件(a.bc),并可以使用lli解释执行。
使用clang -emit-llvm -S可以把源代码(a.c)转换为llvm字节码的文本格式文件(a.ll)。
使用llc可以把字节码的二进制格式文件(a.bc)转换为本地的汇编文件(a.s)。
a.ll和a.bc之间可以通过llvm-as和llvm-dis命令相互转换。
原文链接:https://blog.csdn.net/softee/article/details/41128667
--------------------------------------------------
.bc 转 .ll
llvm-dis AAA.bc -o AAA.ll
另外,调用opt执行我们自定义的PASS,希望最后输出的.ll文件,那么
llvm-obfuscator/build/bin/opt -load LLVMMyPass.so -mypass <Test.ll> change_Test.ll -S
如果希望最后输出.bc文件
llvm-obfuscator/build/bin/opt -load LLVMMyPass.so -mypass <Test.ll> change_Test.bc
二、实战演练。定义个pass 将指令部分 a+b 替换成 a-(-b) ,代码还是基于第二篇的,没有的话请先回去看第二篇https://blog.csdn.net/tabactivity/article/details/81358247。
MyPass.cpp源代码如下:
#include"llvm/IR/Function.h"
#include "llvm/Pass.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/Instructions.h"
using namespace llvm;
#define DEBUG_TAG "MyPass"
namespace{
struct MyPass : public FunctionPass{
static char ID;
MyPass():FunctionPass(ID){
}
// a+b === a-(-b)
bool ob_add(BinaryOperator *bo) {
BinaryOperator *op = NULL;
if (bo->getOpcode() == Instruction::Add) {
// 生成 (-b)
op = BinaryOperator::CreateNeg(bo->getOperand(1), "", bo);
// 生成 a-(-b)
op = BinaryOperator::Create(Instruction::Sub, bo->getOperand(0), op, "", bo);
op->setHasNoSignedWrap(bo->hasNoSignedWrap());
op->setHasNoUnsignedWrap(bo->hasNoUnsignedWrap());
}
// 替换所有出现该指令的地方
bo->replaceAllUsesWith(op);
}
bool runOnFunction(Function &F) override{
errs() << DEBUG_TAG<<": ";
errs() << F.getName() << "\n";
Function *pF = &F;
// 遍历函数中的所有基本块
for(Function::iterator bb = pF->begin(); bb != pF->end(); bb++){
// 遍历基本块中的每条指令
for(BasicBlock::iterator inst = bb->begin(); inst != bb->end(); inst++){
if(inst->isBinaryOp()){
int opCode = inst->getOpcode();
if(opCode == Instruction::Add){
errs()<<"find add instruction !";
ob_add(cast<BinaryOperator>(inst));
}
}
}
}
return true;
}
};
}
char MyPass::ID = 0;
static RegisterPass<MyPass> TTT("mypass", "this is mypass!");
然后编译下llvm,并调用opt。类同第二篇。略
原来的Test.ll:
; Function Attrs: noinline nounwind uwtable
define i32 @add(i32, i32) #0 {
%3 = alloca i32, align 4
%4 = alloca i32, align 4
store i32 %0, i32* %3, align 4
store i32 %1, i32* %4, align 4
%5 = load i32, i32* %3, align 4
%6 = load i32, i32* %4, align 4
%7 = add nsw i32 %5, %6
ret i32 %7
}
新生成的change_Test.ll:
; Function Attrs: noinline nounwind uwtable
define i32 @add(i32, i32) #0 {
%3 = alloca i32, align 4
%4 = alloca i32, align 4
store i32 %0, i32* %3, align 4
store i32 %1, i32* %4, align 4
%5 = load i32, i32* %3, align 4
%6 = load i32, i32* %4, align 4
%7 = sub i32 0, %6
%8 = sub nsw i32 %5, %7
%9 = add nsw i32 %5, %6
ret i32 %8
}