三、llvm各种格式文件转换图、定义个pass 将指令部分  a+b 替换成 a-(-b)

 

一、基础知识: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
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

江西省遂川县常驻深圳大使

喜欢本文,打赏下作者吧~

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

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

打赏作者

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

抵扣说明:

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

余额充值