LLVM一个简单的Pass
1 // Before : 2 // entry 3 // | 4 // ______v______ 5 // | switch | 6 // |_____________| 7 // | 8 // +---------------+ 9 // | _____________ 10 // +------->| case1 |-------+ 11 // | |_____________| | 12 // +------->| case2 |-------+ 13 // | |_____________| | 14 // +------->| case3 |-------+ 15 // | |_____________| | 16 // +------->| case4 |-------+ 17 // | |_____________| | 18 // +------->| case5 |-------+ 19 // | |_____________| | 20 // +------->| default |-------+ 21 // |_____________| | 22 // | 23 // +--------------+ 24 // | 25 // v 26 // return 27 // 28 // After : 29 // entry 30 // | 31 // ______v______ 32 // +-------(true)--| if1 | 33 // | +----(false)--|_____________| 34 // | | _____________ 35 // | | | else | 36 // | | +---------->|_____________|------------------+ 37 // | | | _____________ | 38 // | | +--(false)--| if5 | | 39 // | | +---------->|_____________|--(true)--------+ | 40 // | | | _____________ | | 41 // | | +--(false)--| if4 | | | 42 // | | +---------->|_____________|--(true)------+ | | 43 // | | | _____________ | | | 44 // | | +--(false)--| if3 | | | | 45 // | | +---------->|_____________|--(true)----+ | | | 46 // | | | _____________ | | | | 47 // | | +--(false)--| if2 | | | | | 48 // | +------------>|_____________|--(true)--+ | | | | 49 // | _____________ | | | | | 50 // +-------------->| run1 | | | | | | 51 // +---------------|_____________| | | | | | 52 // | _____________ | | | | | 53 // +---------------| run2 |<---------+ | | | | 54 // | |_____________| | | | | 55 // | _____________ | | | | 56 // +---------------| run3 |<-----------+ | | | 57 // | |_____________| | | | 58 // | _____________ | | | 59 // +---------------| run4 |<-------------+ | | 60 // | |_____________| | | 61 // | _____________ | | 62 // +---------------| run5 |<---------------+ | 63 // | |_____________| | 64 // | _____________ | 65 // +---------------| run6 |<-----------------+ 66 // | |_____________| 67 // | 68 // +----------------------+ 69 // | 70 // v 71 // return 72 // 73 // 当前模块执行后的整体流程图如上 74 // 当前模块仅支持将LLVM识别的switch 语句修改成 if else 格式, 75 // 但是这种改动对IDA 没有太大影响 76 77 #include "stdafx.h" 78 79 #include "LowerSwitchInst.h" 80 81 82 static llvm::zoo::cl::opt_bool _lsi("LowerSwitchInst", "lsi", false, "改变Switch 语句成if else 格式"); 83 84 static llvm::zoo::cl::opt_str _lsi_name("LowerSwitchInst", "lsi_name", "", "要替换的函数名字"); 85 86 87 namespace zoollvm 88 { 89 LowerSwitchInst::LowerSwitchInst() 90 { 91 _bWorked = false; 92 } 93 94 void LowerSwitchInst::ClearWork() 95 { 96 _bWorked = false; 97 } 98 99 bool LowerSwitchInst::IsWorked() 100 { 101 return _bWorked; 102 } 103 104 bool LowerSwitchInst::Run(llvm::Module &M, llvm::Function &F) 105 { 106 std::vector<llvm::BasicBlock*> _vecDelete; 107 std::vector<llvm::SwitchInst*> _vecDeleteInst; 108 // 删除列表 109 110 ZooPrint("Function Name = [%s] \n", zoollvm::module::function::GetFunctionName(F).c_str()); 111 for (llvm::Function::iterator I = F.begin(), E = F.end(); I != E; I++) 112 { 113 llvm::BasicBlock &Cur = *I; 114 auto i = Cur.getTerminator(); 115 if (i == NULL) 116 { 117 continue; 118 } 119 if (llvm::SwitchInst *SI = llvm::dyn_cast<llvm::SwitchInst>(i)) 120 { 121 _bWorked = true; 122 _vecDelete.push_back(&*I); 123 _vecDeleteInst.push_back(SI); 124 125 ZooPrint("SI = %p \n", SI); 126 ZooPrint(" getOpcodeName : [%s] \n", SI->getOpcodeName()); 127 128 Lower(M, F, Cur, *SI); 129 ZooPrint("\n"); 130 } 131 } 132 ZooPrint("Write Pass Success \n"); 133 for (auto it : _vecDeleteInst) 134 { 135 zoollvm::module::function::block::RemoveBlockSelf(it); 136 } 137 ZooPrint("Delete Inst Success \n"); 138 return true; 139 } 140 141 bool LowerSwitchInst::Lower(llvm::Module &M, llvm::Function &F, llvm::BasicBlock &B, llvm::SwitchInst &S) 142 { 143 llvm::Value *Val = S.getCondition(); 144 struct CaseRange 145 { 146 llvm::ConstantInt* cValue; // 147 llvm::BasicBlock* BB; // 处理块 148 CaseRange(llvm::ConstantInt *low, llvm::BasicBlock *bb) : cValue(low), BB(bb) {} 149 }; 150 std::vector<CaseRange> Cases; 151 ZooPrint(" Value = [%s] \n", Val->getName().str().c_str()); 152 ULONG NumSimpleCases = 0; 153 // 找到所有case 块 154 for (auto Case : S.cases()) 155 { 156 if (Case.getCaseSuccessor() == S.getDefaultDest()) 157 { 158 continue; 159 } 160 Cases.push_back(CaseRange(Case.getCaseValue(), Case.getCaseSuccessor())); 161 ++NumSimpleCases; 162 } 163 ZooPrint(" NumSimpleCases = [%d] \n", NumSimpleCases); 164 165 // 修改所有case 块 166 llvm::BasicBlock *bb = &B; 167 for (auto it : Cases) 168 { 169 int64_t nextValue = it.cValue->getSExtValue(); 170 171 // 创建一个基本块,目前这个基本块位置未知,只是先要有,用它占位 172 auto ba = zoollvm::module::function::block::Create(B.getContext()); 173 174 // 创建一个逻辑指令 175 // v = (Val == nextValue ) 176 // 这个逻辑指令的位置,放在当前块的最后一条指令的位置,即 (llvm::BinaryOperator *)&*(bb->end() --) 177 auto v = zoollvm::op_code::compare::CreateICmpEQ(Val, zoollvm::value::const_value::CreateInt64(M, nextValue), (llvm::BinaryOperator *)&*(bb->end() --)); 178 179 // if v then exec else 空block end 180 // 这个比较指令的位置,放在当前块的最后一条指令,结合上下文,就是放到上面的逻辑指令的下一条处,就是 bb 的 end 处 181 zoollvm::op_code::branch::CreateCondBr(v, it.BB, ba, bb); 182 183 // 插入刚才创建的基本块,位置是当前基本块的下一个位置,即顺序向下执行的话,就是当前新的基本块跟在上面的比较指令后面 184 ba->insertInto(&F, B.getNextNode()); 185 186 // 修改要操作的基本块,下一个循环,下一条指令,都从这个新的基本块里面添加 187 bb = ba; 188 189 ZooPrint(" nextValue = [%I64d] \n", nextValue); 190 } 191 // 最后补一个跳到default 的指令,位置是在最初第一个基本块后面的第一个基本块中 192 // 上面由于添加指令是从上往下加,而添加基本块是从下往上加,所以最后一个新的基本块在第一条指令的下面,这也是最后一个跳转的块 193 zoollvm::op_code::branch::CreateBr(S.getDefaultDest(), B.getNextNode()); 194 195 196 return true; 197 } 198 199 200 class LowerSwitchInstPass : public llvm::ModulePass, public zoollvm::frame::Base 201 { 202 public: 203 static char ID; // pass identification 204 LowerSwitchInstPass() : ModulePass(ID), zoollvm::frame::Base("LowerSwitchInstPass") 205 { 206 zoollvm::opt::GetFunctionNameList(_lsi_name, _vec); 207 } 208 209 210 // 启动当前Pass 211 virtual bool runOnModule(llvm::Module &M) 212 { 213 if (_lsi == false) 214 { 215 return true; 216 } 217 218 LowerSwitchInst lsi; 219 220 for (auto it = M.begin(); it != M.end(); it++) 221 { 222 if (zoollvm::opt::IsFunctionInList(_vec, *it)) 223 { 224 lsi.Run(M, *it); 225 } 226 } 227 228 return true; 229 } 230 231 private: 232 std::vector<std::string> _vec; 233 }; 234 } 235 236 char zoollvm::LowerSwitchInstPass::ID = 0; 237 llvm::Pass * createLowerSwitchInst() 238 { 239 return new zoollvm::LowerSwitchInstPass(); 240 }
由于新版LLVM(9.0.0),无法直接调用Util 自带的 LowerSwitch 了,所以这里,我自己弄了一个,
主要功能是展开Switch,把它变成if else,理论上其实没啥区别,但是实际上在LLVM的角度上看,区别很大,
switch 实际上是一条 instruction ,后面的 case 是和switch 在一起的一条 instruction,
这就导致,如果不对它做处理,那么这个 instruction 是非常大的,由于这一条指令是在一个 block 里面的,所以结构也清晰,
if else 则不同,一片 if else 实际上是一片 block ,不管做什么操作也稍微更容易一些