1 /*
2 This file is part of solidity.
3
4 solidity is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation, either version 3 of the License, or
7 (at your option) any later version.
8
9 solidity is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with solidity. If not, see <http://www.gnu.org/licenses/>.
16 */
17 // SPDX-License-Identifier: GPL-3.0
18 /** @file Instruction.cpp
19 * @author Gav Wood <i@gavwood.com>
20 * @date 2014
21 */
22
23 #include <libevmasm/Instruction.h>
24
25 #include <libsolutil/Common.h>
26 #include <libsolutil/CommonIO.h>
27 #include <functional>
28
29 using namespace std;
30 using namespace solidity;
31 using namespace solidity::util;
32 using namespace solidity::evmasm;
33
34 std::map<std::string, Instruction> const solidity::evmasm::c_instructions =
35 {
36 { "STOP", Instruction::STOP },
37 { "ADD", Instruction::ADD },
38 { "SUB", Instruction::SUB },
39 { "MUL", Instruction::MUL },
40 { "DIV", Instruction::DIV },
41 { "SDIV", Instruction::SDIV },
42 { "MOD", Instruction::MOD },
43 { "SMOD", Instruction::SMOD },
44 { "EXP", Instruction::EXP },
45 { "NOT", Instruction::NOT },
46 { "LT", Instruction::LT },
47 { "GT", Instruction::GT },
48 { "SLT", Instruction::SLT },
49 { "SGT", Instruction::SGT },
50 { "EQ", Instruction::EQ },
51 { "ISZERO", Instruction::ISZERO },
52 { "AND", Instruction::AND },
53 { "OR", Instruction::OR },
54 { "XOR", Instruction::XOR },
55 { "BYTE", Instruction::BYTE },
56 { "SHL", Instruction::SHL },
57 { "SHR", Instruction::SHR },
58 { "SAR", Instruction::SAR },
59 { "ADDMOD", Instruction::ADDMOD },
60 { "MULMOD", Instruction::MULMOD },
61 { "SIGNEXTEND", Instruction::SIGNEXTEND },
62 { "KECCAK256", Instruction::KECCAK256 },
63 { "ADDRESS", Instruction::ADDRESS },
64 { "BALANCE", Instruction::BALANCE },
65 { "ORIGIN", Instruction::ORIGIN },
66 { "CALLER", Instruction::CALLER },
67 { "CALLVALUE", Instruction::CALLVALUE },
68 { "CALLDATALOAD", Instruction::CALLDATALOAD },
69 { "CALLDATASIZE", Instruction::CALLDATASIZE },
70 { "CALLDATACOPY", Instruction::CALLDATACOPY },
71 { "CODESIZE", Instruction::CODESIZE },
72 { "CODECOPY", Instruction::CODECOPY },
73 { "GASPRICE", Instruction::GASPRICE },
74 { "EXTCODESIZE", Instruction::EXTCODESIZE },
75 { "EXTCODECOPY", Instruction::EXTCODECOPY },
76 { "RETURNDATASIZE", Instruction::RETURNDATASIZE },
77 { "RETURNDATACOPY", Instruction::RETURNDATACOPY },
78 { "EXTCODEHASH", Instruction::EXTCODEHASH },
79 { "BLOCKHASH", Instruction::BLOCKHASH },
80 { "COINBASE", Instruction::COINBASE },
81 { "TIMESTAMP", Instruction::TIMESTAMP },
82 { "NUMBER", Instruction::NUMBER },
83 { "DIFFICULTY", Instruction::DIFFICULTY },
84 { "GASLIMIT", Instruction::GASLIMIT },
85 { "CHAINID", Instruction::CHAINID },
86 { "SELFBALANCE", Instruction::SELFBALANCE },
87 { "BASEFEE", Instruction::BASEFEE },
88 { "POP", Instruction::POP },
89 { "MLOAD", Instruction::MLOAD },
90 { "MSTORE", Instruction::MSTORE },
91 { "MSTORE8", Instruction::MSTORE8 },
92 { "SLOAD", Instruction::SLOAD },
93 { "SSTORE", Instruction::SSTORE },
94 { "JUMP", Instruction::JUMP },
95 { "JUMPI", Instruction::JUMPI },
96 { "PC", Instruction::PC },
97 { "MSIZE", Instruction::MSIZE },
98 { "GAS", Instruction::GAS },
99 { "JUMPDEST", Instruction::JUMPDEST },
100 { "PUSH1", Instruction::PUSH1 },
101 { "PUSH2", Instruction::PUSH2 },
102 { "PUSH3", Instruction::PUSH3 },
103 { "PUSH4", Instruction::PUSH4 },
104 { "PUSH5", Instruction::PUSH5 },
105 { "PUSH6", Instruction::PUSH6 },
106 { "PUSH7", Instruction::PUSH7 },
107 { "PUSH8", Instruction::PUSH8 },
108 { "PUSH9", Instruction::PUSH9 },
109 { "PUSH10", Instruction::PUSH10 },
110 { "PUSH11", Instruction::PUSH11 },
111 { "PUSH12", Instruction::PUSH12 },
112 { "PUSH13", Instruction::PUSH13 },
113 { "PUSH14", Instruction::PUSH14 },
114 { "PUSH15", Instruction::PUSH15 },
115 { "PUSH16", Instruction::PUSH16 },
116 { "PUSH17", Instruction::PUSH17 },
117 { "PUSH18", Instruction::PUSH18 },
118 { "PUSH19", Instruction::PUSH19 },
119 { "PUSH20", Instruction::PUSH20 },
120 { "PUSH21", Instruction::PUSH21 },
121 { "PUSH22", Instruction::PUSH22 },
122 { "PUSH23", Instruction::PUSH23 },
123 { "PUSH24", Instruction::PUSH24 },
124 { "PUSH25", Instruction::PUSH25 },
125 { "PUSH26", Instruction::PUSH26 },
126 { "PUSH27", Instruction::PUSH27 },
127 { "PUSH28", Instruction::PUSH28 },
128 { "PUSH29", Instruction::PUSH29 },
129 { "PUSH30", Instruction::PUSH30 },
130 { "PUSH31", Instruction::PUSH31 },
131 { "PUSH32", Instruction::PUSH32 },
132 { "DUP1", Instruction::DUP1 },
133 { "DUP2", Instruction::DUP2 },
134 { "DUP3", Instruction::DUP3 },
135 { "DUP4", Instruction::DUP4 },
136 { "DUP5", Instruction::DUP5 },
137 { "DUP6", Instruction::DUP6 },
138 { "DUP7", Instruction::DUP7 },
139 { "DUP8", Instruction::DUP8 },
140 { "DUP9", Instruction::DUP9 },
141 { "DUP10", Instruction::DUP10 },
142 { "DUP11", Instruction::DUP11 },
143 { "DUP12", Instruction::DUP12 },
144 { "DUP13", Instruction::DUP13 },
145 { "DUP14", Instruction::DUP14 },
146 { "DUP15", Instruction::DUP15 },
147 { "DUP16", Instruction::DUP16 },
148 { "SWAP1", Instruction::SWAP1 },
149 { "SWAP2", Instruction::SWAP2 },
150 { "SWAP3", Instruction::SWAP3 },
151 { "SWAP4", Instruction::SWAP4 },
152 { "SWAP5", Instruction::SWAP5 },
153 { "SWAP6", Instruction::SWAP6 },
154 { "SWAP7", Instruction::SWAP7 },
155 { "SWAP8", Instruction::SWAP8 },
156 { "SWAP9", Instruction::SWAP9 },
157 { "SWAP10", Instruction::SWAP10 },
158 { "SWAP11", Instruction::SWAP11 },
159 { "SWAP12", Instruction::SWAP12 },
160 { "SWAP13", Instruction::SWAP13 },
161 { "SWAP14", Instruction::SWAP14 },
162 { "SWAP15", Instruction::SWAP15 },
163 { "SWAP16", Instruction::SWAP16 },
164 { "LOG0", Instruction::LOG0 },
165 { "LOG1", Instruction::LOG1 },
166 { "LOG2", Instruction::LOG2 },
167 { "LOG3", Instruction::LOG3 },
168 { "LOG4", Instruction::LOG4 },
169 { "CREATE", Instruction::CREATE },
170 { "CALL", Instruction::CALL },
171 { "CALLCODE", Instruction::CALLCODE },
172 { "STATICCALL", Instruction::STATICCALL },
173 { "RETURN", Instruction::RETURN },
174 { "DELEGATECALL", Instruction::DELEGATECALL },
175 { "CREATE2", Instruction::CREATE2 },
176 { "REVERT", Instruction::REVERT },
177 { "INVALID", Instruction::INVALID },
178 { "SELFDESTRUCT", Instruction::SELFDESTRUCT }
179 };
180
181 static std::map<Instruction, InstructionInfo> const c_instructionInfo =
182 { // Add, Args, Ret, SideEffects, GasPriceTier
183 { Instruction::STOP, { "STOP", 0, 0, 0, true, Tier::Zero } },
184 { Instruction::ADD, { "ADD", 0, 2, 1, false, Tier::VeryLow } },
185 { Instruction::SUB, { "SUB", 0, 2, 1, false, Tier::VeryLow } },
186 { Instruction::MUL, { "MUL", 0, 2, 1, false, Tier::Low } },
187 { Instruction::DIV, { "DIV", 0, 2, 1, false, Tier::Low } },
188 { Instruction::SDIV, { "SDIV", 0, 2, 1, false, Tier::Low } },
189 { Instruction::MOD, { "MOD", 0, 2, 1, false, Tier::Low } },
190 { Instruction::SMOD, { "SMOD", 0, 2, 1, false, Tier::Low } },
191 { Instruction::EXP, { "EXP", 0, 2, 1, false, Tier::Special } },
192 { Instruction::NOT, { "NOT", 0, 1, 1, false, Tier::VeryLow } },
193 { Instruction::LT, { "LT", 0, 2, 1, false, Tier::VeryLow } },
194 { Instruction::GT, { "GT", 0, 2, 1, false, Tier::VeryLow } },
195 { Instruction::SLT, { "SLT", 0, 2, 1, false, Tier::VeryLow } },
196 { Instruction::SGT, { "SGT", 0, 2, 1, false, Tier::VeryLow } },
197 { Instruction::EQ, { "EQ", 0, 2, 1, false, Tier::VeryLow } },
198 { Instruction::ISZERO, { "ISZERO", 0, 1, 1, false, Tier::VeryLow } },
199 { Instruction::AND, { "AND", 0, 2, 1, false, Tier::VeryLow } },
200 { Instruction::OR, { "OR", 0, 2, 1, false, Tier::VeryLow } },
201 { Instruction::XOR, { "XOR", 0, 2, 1, false, Tier::VeryLow } },
202 { Instruction::BYTE, { "BYTE", 0, 2, 1, false, Tier::VeryLow } },
203 { Instruction::SHL, { "SHL", 0, 2, 1, false, Tier::VeryLow } },
204 { Instruction::SHR, { "SHR", 0, 2, 1, false, Tier::VeryLow } },
205 { Instruction::SAR, { "SAR", 0, 2, 1, false, Tier::VeryLow } },
206 { Instruction::ADDMOD, { "ADDMOD", 0, 3, 1, false, Tier::Mid } },
207 { Instruction::MULMOD, { "MULMOD", 0, 3, 1, false, Tier::Mid } },
208 { Instruction::SIGNEXTEND, { "SIGNEXTEND", 0, 2, 1, false, Tier::Low } },
209 { Instruction::KECCAK256, { "KECCAK256", 0, 2, 1, true, Tier::Special } },
210 { Instruction::ADDRESS, { "ADDRESS", 0, 0, 1, false, Tier::Base } },
211 { Instruction::BALANCE, { "BALANCE", 0, 1, 1, false, Tier::Balance } },
212 { Instruction::ORIGIN, { "ORIGIN", 0, 0, 1, false, Tier::Base } },
213 { Instruction::CALLER, { "CALLER", 0, 0, 1, false, Tier::Base } },
214 { Instruction::CALLVALUE, { "CALLVALUE", 0, 0, 1, false, Tier::Base } },
215 { Instruction::CALLDATALOAD,{ "CALLDATALOAD", 0, 1, 1, false, Tier::VeryLow } },
216 { Instruction::CALLDATASIZE,{ "CALLDATASIZE", 0, 0, 1, false, Tier::Base } },
217 { Instruction::CALLDATACOPY,{ "CALLDATACOPY", 0, 3, 0, true, Tier::VeryLow } },
218 { Instruction::CODESIZE, { "CODESIZE", 0, 0, 1, false, Tier::Base } },
219 { Instruction::CODECOPY, { "CODECOPY", 0, 3, 0, true, Tier::VeryLow } },
220 { Instruction::GASPRICE, { "GASPRICE", 0, 0, 1, false, Tier::Base } },
221 { Instruction::EXTCODESIZE, { "EXTCODESIZE", 0, 1, 1, false, Tier::ExtCode } },
222 { Instruction::EXTCODECOPY, { "EXTCODECOPY", 0, 4, 0, true, Tier::ExtCode } },
223 { Instruction::RETURNDATASIZE, {"RETURNDATASIZE", 0, 0, 1, false, Tier::Base } },
224 { Instruction::RETURNDATACOPY, {"RETURNDATACOPY", 0, 3, 0, true, Tier::VeryLow } },
225 { Instruction::EXTCODEHASH, { "EXTCODEHASH", 0, 1, 1, false, Tier::Balance } },
226 { Instruction::BLOCKHASH, { "BLOCKHASH", 0, 1, 1, false, Tier::Ext } },
227 { Instruction::COINBASE, { "COINBASE", 0, 0, 1, false, Tier::Base } },
228 { Instruction::TIMESTAMP, { "TIMESTAMP", 0, 0, 1, false, Tier::Base } },
229 { Instruction::NUMBER, { "NUMBER", 0, 0, 1, false, Tier::Base } },
230 { Instruction::DIFFICULTY, { "DIFFICULTY", 0, 0, 1, false, Tier::Base } },
231 { Instruction::GASLIMIT, { "GASLIMIT", 0, 0, 1, false, Tier::Base } },
232 { Instruction::CHAINID, { "CHAINID", 0, 0, 1, false, Tier::Base } },
233 { Instruction::SELFBALANCE, { "SELFBALANCE", 0, 0, 1, false, Tier::Low } },
234 { Instruction::BASEFEE, { "BASEFEE", 0, 0, 1, false, Tier::Base } },
235 { Instruction::POP, { "POP", 0, 1, 0, false, Tier::Base } },
236 { Instruction::MLOAD, { "MLOAD", 0, 1, 1, true, Tier::VeryLow } },
237 { Instruction::MSTORE, { "MSTORE", 0, 2, 0, true, Tier::VeryLow } },
238 { Instruction::MSTORE8, { "MSTORE8", 0, 2, 0, true, Tier::VeryLow } },
239 { Instruction::SLOAD, { "SLOAD", 0, 1, 1, false, Tier::Special } },
240 { Instruction::SSTORE, { "SSTORE", 0, 2, 0, true, Tier::Special } },
241 { Instruction::JUMP, { "JUMP", 0, 1, 0, true, Tier::Mid } },
242 { Instruction::JUMPI, { "JUMPI", 0, 2, 0, true, Tier::High } },
243 { Instruction::PC, { "PC", 0, 0, 1, false, Tier::Base } },
244 { Instruction::MSIZE, { "MSIZE", 0, 0, 1, false, Tier::Base } },
245 { Instruction::GAS, { "GAS", 0, 0, 1, false, Tier::Base } },
246 { Instruction::JUMPDEST, { "JUMPDEST", 0, 0, 0, true, Tier::Special } },
247 { Instruction::PUSH1, { "PUSH1", 1, 0, 1, false, Tier::VeryLow } },
248 { Instruction::PUSH2, { "PUSH2", 2, 0, 1, false, Tier::VeryLow } },
249 { Instruction::PUSH3, { "PUSH3", 3, 0, 1, false, Tier::VeryLow } },
250 { Instruction::PUSH4, { "PUSH4", 4, 0, 1, false, Tier::VeryLow } },
251 { Instruction::PUSH5, { "PUSH5", 5, 0, 1, false, Tier::VeryLow } },
252 { Instruction::PUSH6, { "PUSH6", 6, 0, 1, false, Tier::VeryLow } },
253 { Instruction::PUSH7, { "PUSH7", 7, 0, 1, false, Tier::VeryLow } },
254 { Instruction::PUSH8, { "PUSH8", 8, 0, 1, false, Tier::VeryLow } },
255 { Instruction::PUSH9, { "PUSH9", 9, 0, 1, false, Tier::VeryLow } },
256 { Instruction::PUSH10, { "PUSH10", 10, 0, 1, false, Tier::VeryLow } },
257 { Instruction::PUSH11, { "PUSH11", 11, 0, 1, false, Tier::VeryLow } },
258 { Instruction::PUSH12, { "PUSH12", 12, 0, 1, false, Tier::VeryLow } },
259 { Instruction::PUSH13, { "PUSH13", 13, 0, 1, false, Tier::VeryLow } },
260 { Instruction::PUSH14, { "PUSH14", 14, 0, 1, false, Tier::VeryLow } },
261 { Instruction::PUSH15, { "PUSH15", 15, 0, 1, false, Tier::VeryLow } },
262 { Instruction::PUSH16, { "PUSH16", 16, 0, 1, false, Tier::VeryLow } },
263 { Instruction::PUSH17, { "PUSH17", 17, 0, 1, false, Tier::VeryLow } },
264 { Instruction::PUSH18, { "PUSH18", 18, 0, 1, false, Tier::VeryLow } },
265 { Instruction::PUSH19, { "PUSH19", 19, 0, 1, false, Tier::VeryLow } },
266 { Instruction::PUSH20, { "PUSH20", 20, 0, 1, false, Tier::VeryLow } },
267 { Instruction::PUSH21, { "PUSH21", 21, 0, 1, false, Tier::VeryLow } },
268 { Instruction::PUSH22, { "PUSH22", 22, 0, 1, false, Tier::VeryLow } },
269 { Instruction::PUSH23, { "PUSH23", 23, 0, 1, false, Tier::VeryLow } },
270 { Instruction::PUSH24, { "PUSH24", 24, 0, 1, false, Tier::VeryLow } },
271 { Instruction::PUSH25, { "PUSH25", 25, 0, 1, false, Tier::VeryLow } },
272 { Instruction::PUSH26, { "PUSH26", 26, 0, 1, false, Tier::VeryLow } },
273 { Instruction::PUSH27, { "PUSH27", 27, 0, 1, false, Tier::VeryLow } },
274 { Instruction::PUSH28, { "PUSH28", 28, 0, 1, false, Tier::VeryLow } },
275 { Instruction::PUSH29, { "PUSH29", 29, 0, 1, false, Tier::VeryLow } },
276 { Instruction::PUSH30, { "PUSH30", 30, 0, 1, false, Tier::VeryLow } },
277 { Instruction::PUSH31, { "PUSH31", 31, 0, 1, false, Tier::VeryLow } },
278 { Instruction::PUSH32, { "PUSH32", 32, 0, 1, false, Tier::VeryLow } },
279 { Instruction::DUP1, { "DUP1", 0, 1, 2, false, Tier::VeryLow } },
280 { Instruction::DUP2, { "DUP2", 0, 2, 3, false, Tier::VeryLow } },
281 { Instruction::DUP3, { "DUP3", 0, 3, 4, false, Tier::VeryLow } },
282 { Instruction::DUP4, { "DUP4", 0, 4, 5, false, Tier::VeryLow } },
283 { Instruction::DUP5, { "DUP5", 0, 5, 6, false, Tier::VeryLow } },
284 { Instruction::DUP6, { "DUP6", 0, 6, 7, false, Tier::VeryLow } },
285 { Instruction::DUP7, { "DUP7", 0, 7, 8, false, Tier::VeryLow } },
286 { Instruction::DUP8, { "DUP8", 0, 8, 9, false, Tier::VeryLow } },
287 { Instruction::DUP9, { "DUP9", 0, 9, 10, false, Tier::VeryLow } },
288 { Instruction::DUP10, { "DUP10", 0, 10, 11, false, Tier::VeryLow } },
289 { Instruction::DUP11, { "DUP11", 0, 11, 12, false, Tier::VeryLow } },
290 { Instruction::DUP12, { "DUP12", 0, 12, 13, false, Tier::VeryLow } },
291 { Instruction::DUP13, { "DUP13", 0, 13, 14, false, Tier::VeryLow } },
292 { Instruction::DUP14, { "DUP14", 0, 14, 15, false, Tier::VeryLow } },
293 { Instruction::DUP15, { "DUP15", 0, 15, 16, false, Tier::VeryLow } },
294 { Instruction::DUP16, { "DUP16", 0, 16, 17, false, Tier::VeryLow } },
295 { Instruction::SWAP1, { "SWAP1", 0, 2, 2, false, Tier::VeryLow } },
296 { Instruction::SWAP2, { "SWAP2", 0, 3, 3, false, Tier::VeryLow } },
297 { Instruction::SWAP3, { "SWAP3", 0, 4, 4, false, Tier::VeryLow } },
298 { Instruction::SWAP4, { "SWAP4", 0, 5, 5, false, Tier::VeryLow } },
299 { Instruction::SWAP5, { "SWAP5", 0, 6, 6, false, Tier::VeryLow } },
300 { Instruction::SWAP6, { "SWAP6", 0, 7, 7, false, Tier::VeryLow } },
301 { Instruction::SWAP7, { "SWAP7", 0, 8, 8, false, Tier::VeryLow } },
302 { Instruction::SWAP8, { "SWAP8", 0, 9, 9, false, Tier::VeryLow } },
303 { Instruction::SWAP9, { "SWAP9", 0, 10, 10, false, Tier::VeryLow } },
304 { Instruction::SWAP10, { "SWAP10", 0, 11, 11, false, Tier::VeryLow } },
305 { Instruction::SWAP11, { "SWAP11", 0, 12, 12, false, Tier::VeryLow } },
306 { Instruction::SWAP12, { "SWAP12", 0, 13, 13, false, Tier::VeryLow } },
307 { Instruction::SWAP13, { "SWAP13", 0, 14, 14, false, Tier::VeryLow } },
308 { Instruction::SWAP14, { "SWAP14", 0, 15, 15, false, Tier::VeryLow } },
309 { Instruction::SWAP15, { "SWAP15", 0, 16, 16, false, Tier::VeryLow } },
310 { Instruction::SWAP16, { "SWAP16", 0, 17, 17, false, Tier::VeryLow } },
311 { Instruction::LOG0, { "LOG0", 0, 2, 0, true, Tier::Special } },
312 { Instruction::LOG1, { "LOG1", 0, 3, 0, true, Tier::Special } },
313 { Instruction::LOG2, { "LOG2", 0, 4, 0, true, Tier::Special } },
314 { Instruction::LOG3, { "LOG3", 0, 5, 0, true, Tier::Special } },
315 { Instruction::LOG4, { "LOG4", 0, 6, 0, true, Tier::Special } },
316 { Instruction::CREATE, { "CREATE", 0, 3, 1, true, Tier::Special } },
317 { Instruction::CALL, { "CALL", 0, 7, 1, true, Tier::Special } },
318 { Instruction::CALLCODE, { "CALLCODE", 0, 7, 1, true, Tier::Special } },
319 { Instruction::RETURN, { "RETURN", 0, 2, 0, true, Tier::Zero } },
320 { Instruction::DELEGATECALL, { "DELEGATECALL", 0, 6, 1, true, Tier::Special } },
321 { Instruction::STATICCALL, { "STATICCALL", 0, 6, 1, true, Tier::Special } },
322 { Instruction::CREATE2, { "CREATE2", 0, 4, 1, true, Tier::Special } },
323 { Instruction::REVERT, { "REVERT", 0, 2, 0, true, Tier::Zero } },
324 { Instruction::INVALID, { "INVALID", 0, 0, 0, true, Tier::Zero } },
325 { Instruction::SELFDESTRUCT, { "SELFDESTRUCT", 0, 1, 0, true, Tier::Special } }
326 };
327
eachInstruction(bytes const & _mem,function<void (Instruction,u256 const &)> const & _onInstruction)328 void solidity::evmasm::eachInstruction(
329 bytes const& _mem,
330 function<void(Instruction,u256 const&)> const& _onInstruction
331 )
332 {
333 for (auto it = _mem.begin(); it < _mem.end(); ++it)
334 {
335 auto instr = Instruction(*it);
336 int additional = 0;
337 if (isValidInstruction(instr))
338 additional = instructionInfo(instr).additional;
339
340 u256 data;
341
342 // fill the data with the additional data bytes from the instruction stream
343 while (additional > 0 && std::next(it) < _mem.end())
344 {
345 data <<= 8;
346 data |= *++it;
347 --additional;
348 }
349
350 // pad the remaining number of additional octets with zeros
351 data <<= 8 * additional;
352
353 _onInstruction(instr, data);
354 }
355 }
356
disassemble(bytes const & _mem,string const & _delimiter)357 string solidity::evmasm::disassemble(bytes const& _mem, string const& _delimiter)
358 {
359 stringstream ret;
360 eachInstruction(_mem, [&](Instruction _instr, u256 const& _data) {
361 if (!isValidInstruction(_instr))
362 ret << "0x" << std::uppercase << std::hex << static_cast<int>(_instr) << _delimiter;
363 else
364 {
365 InstructionInfo info = instructionInfo(_instr);
366 ret << info.name;
367 if (info.additional)
368 ret << " 0x" << std::uppercase << std::hex << _data;
369 ret << _delimiter;
370 }
371 });
372 return ret.str();
373 }
374
instructionInfo(Instruction _inst)375 InstructionInfo solidity::evmasm::instructionInfo(Instruction _inst)
376 {
377 try
378 {
379 return c_instructionInfo.at(_inst);
380 }
381 catch (...)
382 {
383 return InstructionInfo({"<INVALID_INSTRUCTION: " + toString((unsigned)_inst) + ">", 0, 0, 0, false, Tier::Invalid});
384 }
385 }
386
isValidInstruction(Instruction _inst)387 bool solidity::evmasm::isValidInstruction(Instruction _inst)
388 {
389 return !!c_instructionInfo.count(_inst);
390 }
391