/src/capstonev5/arch/EVM/EVMDisassembler.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* Capstone Disassembly Engine */ |
2 | | /* By Nguyen Anh Quynh, 2018 */ |
3 | | |
4 | | #include <string.h> |
5 | | #include <stddef.h> // offsetof macro |
6 | | // alternatively #include "../../utils.h" like everyone else |
7 | | |
8 | | #include "EVMDisassembler.h" |
9 | | #include "EVMMapping.h" |
10 | | |
11 | | static const short opcodes[256] = { |
12 | | EVM_INS_STOP, |
13 | | EVM_INS_ADD, |
14 | | EVM_INS_MUL, |
15 | | EVM_INS_SUB, |
16 | | EVM_INS_DIV, |
17 | | EVM_INS_SDIV, |
18 | | EVM_INS_MOD, |
19 | | EVM_INS_SMOD, |
20 | | EVM_INS_ADDMOD, |
21 | | EVM_INS_MULMOD, |
22 | | EVM_INS_EXP, |
23 | | EVM_INS_SIGNEXTEND, |
24 | | -1, |
25 | | -1, |
26 | | -1, |
27 | | -1, |
28 | | EVM_INS_LT, |
29 | | EVM_INS_GT, |
30 | | EVM_INS_SLT, |
31 | | EVM_INS_SGT, |
32 | | EVM_INS_EQ, |
33 | | EVM_INS_ISZERO, |
34 | | EVM_INS_AND, |
35 | | EVM_INS_OR, |
36 | | EVM_INS_XOR, |
37 | | EVM_INS_NOT, |
38 | | EVM_INS_BYTE, |
39 | | -1, |
40 | | -1, |
41 | | -1, |
42 | | -1, |
43 | | -1, |
44 | | EVM_INS_SHA3, |
45 | | -1, |
46 | | -1, |
47 | | -1, |
48 | | -1, |
49 | | -1, |
50 | | -1, |
51 | | -1, |
52 | | -1, |
53 | | -1, |
54 | | -1, |
55 | | -1, |
56 | | -1, |
57 | | -1, |
58 | | -1, |
59 | | -1, |
60 | | EVM_INS_ADDRESS, |
61 | | EVM_INS_BALANCE, |
62 | | EVM_INS_ORIGIN, |
63 | | EVM_INS_CALLER, |
64 | | EVM_INS_CALLVALUE, |
65 | | EVM_INS_CALLDATALOAD, |
66 | | EVM_INS_CALLDATASIZE, |
67 | | EVM_INS_CALLDATACOPY, |
68 | | EVM_INS_CODESIZE, |
69 | | EVM_INS_CODECOPY, |
70 | | EVM_INS_GASPRICE, |
71 | | EVM_INS_EXTCODESIZE, |
72 | | EVM_INS_EXTCODECOPY, |
73 | | EVM_INS_RETURNDATASIZE, |
74 | | EVM_INS_RETURNDATACOPY, |
75 | | -1, |
76 | | EVM_INS_BLOCKHASH, |
77 | | EVM_INS_COINBASE, |
78 | | EVM_INS_TIMESTAMP, |
79 | | EVM_INS_NUMBER, |
80 | | EVM_INS_DIFFICULTY, |
81 | | EVM_INS_GASLIMIT, |
82 | | -1, |
83 | | -1, |
84 | | -1, |
85 | | -1, |
86 | | -1, |
87 | | -1, |
88 | | -1, |
89 | | -1, |
90 | | -1, |
91 | | -1, |
92 | | EVM_INS_POP, |
93 | | EVM_INS_MLOAD, |
94 | | EVM_INS_MSTORE, |
95 | | EVM_INS_MSTORE8, |
96 | | EVM_INS_SLOAD, |
97 | | EVM_INS_SSTORE, |
98 | | EVM_INS_JUMP, |
99 | | EVM_INS_JUMPI, |
100 | | EVM_INS_PC, |
101 | | EVM_INS_MSIZE, |
102 | | EVM_INS_GAS, |
103 | | EVM_INS_JUMPDEST, |
104 | | -1, |
105 | | -1, |
106 | | -1, |
107 | | -1, |
108 | | EVM_INS_PUSH1, |
109 | | EVM_INS_PUSH2, |
110 | | EVM_INS_PUSH3, |
111 | | EVM_INS_PUSH4, |
112 | | EVM_INS_PUSH5, |
113 | | EVM_INS_PUSH6, |
114 | | EVM_INS_PUSH7, |
115 | | EVM_INS_PUSH8, |
116 | | EVM_INS_PUSH9, |
117 | | EVM_INS_PUSH10, |
118 | | EVM_INS_PUSH11, |
119 | | EVM_INS_PUSH12, |
120 | | EVM_INS_PUSH13, |
121 | | EVM_INS_PUSH14, |
122 | | EVM_INS_PUSH15, |
123 | | EVM_INS_PUSH16, |
124 | | EVM_INS_PUSH17, |
125 | | EVM_INS_PUSH18, |
126 | | EVM_INS_PUSH19, |
127 | | EVM_INS_PUSH20, |
128 | | EVM_INS_PUSH21, |
129 | | EVM_INS_PUSH22, |
130 | | EVM_INS_PUSH23, |
131 | | EVM_INS_PUSH24, |
132 | | EVM_INS_PUSH25, |
133 | | EVM_INS_PUSH26, |
134 | | EVM_INS_PUSH27, |
135 | | EVM_INS_PUSH28, |
136 | | EVM_INS_PUSH29, |
137 | | EVM_INS_PUSH30, |
138 | | EVM_INS_PUSH31, |
139 | | EVM_INS_PUSH32, |
140 | | EVM_INS_DUP1, |
141 | | EVM_INS_DUP2, |
142 | | EVM_INS_DUP3, |
143 | | EVM_INS_DUP4, |
144 | | EVM_INS_DUP5, |
145 | | EVM_INS_DUP6, |
146 | | EVM_INS_DUP7, |
147 | | EVM_INS_DUP8, |
148 | | EVM_INS_DUP9, |
149 | | EVM_INS_DUP10, |
150 | | EVM_INS_DUP11, |
151 | | EVM_INS_DUP12, |
152 | | EVM_INS_DUP13, |
153 | | EVM_INS_DUP14, |
154 | | EVM_INS_DUP15, |
155 | | EVM_INS_DUP16, |
156 | | EVM_INS_SWAP1, |
157 | | EVM_INS_SWAP2, |
158 | | EVM_INS_SWAP3, |
159 | | EVM_INS_SWAP4, |
160 | | EVM_INS_SWAP5, |
161 | | EVM_INS_SWAP6, |
162 | | EVM_INS_SWAP7, |
163 | | EVM_INS_SWAP8, |
164 | | EVM_INS_SWAP9, |
165 | | EVM_INS_SWAP10, |
166 | | EVM_INS_SWAP11, |
167 | | EVM_INS_SWAP12, |
168 | | EVM_INS_SWAP13, |
169 | | EVM_INS_SWAP14, |
170 | | EVM_INS_SWAP15, |
171 | | EVM_INS_SWAP16, |
172 | | EVM_INS_LOG0, |
173 | | EVM_INS_LOG1, |
174 | | EVM_INS_LOG2, |
175 | | EVM_INS_LOG3, |
176 | | EVM_INS_LOG4, |
177 | | -1, |
178 | | -1, |
179 | | -1, |
180 | | -1, |
181 | | -1, |
182 | | -1, |
183 | | -1, |
184 | | -1, |
185 | | -1, |
186 | | -1, |
187 | | -1, |
188 | | -1, |
189 | | -1, |
190 | | -1, |
191 | | -1, |
192 | | -1, |
193 | | -1, |
194 | | -1, |
195 | | -1, |
196 | | -1, |
197 | | -1, |
198 | | -1, |
199 | | -1, |
200 | | -1, |
201 | | -1, |
202 | | -1, |
203 | | -1, |
204 | | -1, |
205 | | -1, |
206 | | -1, |
207 | | -1, |
208 | | -1, |
209 | | -1, |
210 | | -1, |
211 | | -1, |
212 | | -1, |
213 | | -1, |
214 | | -1, |
215 | | -1, |
216 | | -1, |
217 | | -1, |
218 | | -1, |
219 | | -1, |
220 | | -1, |
221 | | -1, |
222 | | -1, |
223 | | -1, |
224 | | -1, |
225 | | -1, |
226 | | -1, |
227 | | -1, |
228 | | -1, |
229 | | -1, |
230 | | -1, |
231 | | -1, |
232 | | -1, |
233 | | -1, |
234 | | -1, |
235 | | -1, |
236 | | -1, |
237 | | -1, |
238 | | -1, |
239 | | -1, |
240 | | -1, |
241 | | -1, |
242 | | -1, |
243 | | -1, |
244 | | -1, |
245 | | -1, |
246 | | -1, |
247 | | -1, |
248 | | -1, |
249 | | -1, |
250 | | -1, |
251 | | -1, |
252 | | EVM_INS_CREATE, |
253 | | EVM_INS_CALL, |
254 | | EVM_INS_CALLCODE, |
255 | | EVM_INS_RETURN, |
256 | | EVM_INS_DELEGATECALL, |
257 | | EVM_INS_CALLBLACKBOX, |
258 | | -1, |
259 | | -1, |
260 | | -1, |
261 | | -1, |
262 | | EVM_INS_STATICCALL, |
263 | | -1, |
264 | | -1, |
265 | | EVM_INS_REVERT, |
266 | | -1, |
267 | | EVM_INS_SUICIDE, |
268 | | }; |
269 | | |
270 | | bool EVM_getInstruction(csh ud, const uint8_t *code, size_t code_len, |
271 | | MCInst *MI, uint16_t *size, uint64_t address, void *inst_info) |
272 | 21.3k | { |
273 | 21.3k | unsigned char opcode; |
274 | | |
275 | 21.3k | if (code_len == 0) |
276 | 0 | return false; |
277 | | |
278 | 21.3k | opcode = code[0]; |
279 | 21.3k | if (opcodes[opcode] == -1) { |
280 | | // invalid opcode |
281 | 126 | return false; |
282 | 126 | } |
283 | | |
284 | | // valid opcode |
285 | 21.1k | MI->address = address; |
286 | 21.1k | MI->OpcodePub = MI->Opcode = opcode; |
287 | | |
288 | 21.1k | if (opcode >= EVM_INS_PUSH1 && opcode <= EVM_INS_PUSH32) { |
289 | 1.50k | unsigned char len = (opcode - EVM_INS_PUSH1 + 1); |
290 | 1.50k | if (code_len < 1 + len) { |
291 | | // not enough data |
292 | 65 | return false; |
293 | 65 | } |
294 | | |
295 | 1.43k | *size = 1 + len; |
296 | 1.43k | memcpy(MI->evm_data, code + 1, len); |
297 | 1.43k | } else |
298 | 19.6k | *size = 1; |
299 | | |
300 | 21.1k | if (MI->flat_insn->detail) { |
301 | 21.1k | memset(MI->flat_insn->detail, 0, offsetof(cs_detail, evm)+sizeof(cs_evm)); |
302 | 21.1k | EVM_get_insn_id((cs_struct *)ud, MI->flat_insn, opcode); |
303 | | |
304 | 21.1k | if (MI->flat_insn->detail->evm.pop) { |
305 | 17.1k | MI->flat_insn->detail->groups[MI->flat_insn->detail->groups_count] = EVM_GRP_STACK_READ; |
306 | 17.1k | MI->flat_insn->detail->groups_count++; |
307 | 17.1k | } |
308 | | |
309 | 21.1k | if (MI->flat_insn->detail->evm.push) { |
310 | 12.8k | MI->flat_insn->detail->groups[MI->flat_insn->detail->groups_count] = EVM_GRP_STACK_WRITE; |
311 | 12.8k | MI->flat_insn->detail->groups_count++; |
312 | 12.8k | } |
313 | | |
314 | | // setup groups |
315 | 21.1k | switch(opcode) { |
316 | 4.15k | default: |
317 | 4.15k | break; |
318 | 4.15k | case EVM_INS_ADD: |
319 | 982 | case EVM_INS_MUL: |
320 | 1.33k | case EVM_INS_SUB: |
321 | 1.99k | case EVM_INS_DIV: |
322 | 2.67k | case EVM_INS_SDIV: |
323 | 3.41k | case EVM_INS_MOD: |
324 | 4.54k | case EVM_INS_SMOD: |
325 | 4.95k | case EVM_INS_ADDMOD: |
326 | 5.36k | case EVM_INS_MULMOD: |
327 | 5.72k | case EVM_INS_EXP: |
328 | 6.28k | case EVM_INS_SIGNEXTEND: |
329 | 6.28k | MI->flat_insn->detail->groups[MI->flat_insn->detail->groups_count] = EVM_GRP_MATH; |
330 | 6.28k | MI->flat_insn->detail->groups_count++; |
331 | 6.28k | break; |
332 | | |
333 | 618 | case EVM_INS_MSTORE: |
334 | 972 | case EVM_INS_MSTORE8: |
335 | 1.35k | case EVM_INS_CALLDATACOPY: |
336 | 1.68k | case EVM_INS_CODECOPY: |
337 | 2.13k | case EVM_INS_EXTCODECOPY: |
338 | 2.13k | MI->flat_insn->detail->groups[MI->flat_insn->detail->groups_count] = EVM_GRP_MEM_WRITE; |
339 | 2.13k | MI->flat_insn->detail->groups_count++; |
340 | 2.13k | break; |
341 | | |
342 | 705 | case EVM_INS_MLOAD: |
343 | 1.17k | case EVM_INS_CREATE: |
344 | 1.47k | case EVM_INS_CALL: |
345 | 1.76k | case EVM_INS_CALLCODE: |
346 | 2.18k | case EVM_INS_RETURN: |
347 | 3.06k | case EVM_INS_DELEGATECALL: |
348 | 3.54k | case EVM_INS_REVERT: |
349 | 3.54k | MI->flat_insn->detail->groups[MI->flat_insn->detail->groups_count] = EVM_GRP_MEM_READ; |
350 | 3.54k | MI->flat_insn->detail->groups_count++; |
351 | 3.54k | break; |
352 | | |
353 | 417 | case EVM_INS_SSTORE: |
354 | 417 | MI->flat_insn->detail->groups[MI->flat_insn->detail->groups_count] = EVM_GRP_STORE_WRITE; |
355 | 417 | MI->flat_insn->detail->groups_count++; |
356 | 417 | break; |
357 | | |
358 | 460 | case EVM_INS_SLOAD: |
359 | 460 | MI->flat_insn->detail->groups[MI->flat_insn->detail->groups_count] = EVM_GRP_STORE_READ; |
360 | 460 | MI->flat_insn->detail->groups_count++; |
361 | 460 | break; |
362 | | |
363 | 371 | case EVM_INS_JUMP: |
364 | 762 | case EVM_INS_JUMPI: |
365 | 762 | MI->flat_insn->detail->groups[MI->flat_insn->detail->groups_count] = EVM_GRP_JUMP; |
366 | 762 | MI->flat_insn->detail->groups_count++; |
367 | 762 | break; |
368 | | |
369 | 2.04k | case EVM_INS_STOP: |
370 | 3.34k | case EVM_INS_SUICIDE: |
371 | 3.34k | MI->flat_insn->detail->groups[MI->flat_insn->detail->groups_count] = EVM_GRP_HALT; |
372 | 3.34k | MI->flat_insn->detail->groups_count++; |
373 | 3.34k | break; |
374 | | |
375 | 21.1k | } |
376 | 21.1k | } |
377 | | |
378 | 21.1k | return true; |
379 | 21.1k | } |