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 ,不管做什么操作也稍微更容易一些

posted @ 2020-01-10 01:45  穷到底  阅读(866)  评论(0编辑  收藏  举报