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 ,不管做什么操作也稍微更容易一些
来源:https://www.cnblogs.com/suanguade/p/12174308.html