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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM