OLD | NEW |
1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2015 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
| 5 #include "src/wasm/module-decoder.h" |
| 6 |
| 7 #include "src/base/functional.h" |
| 8 #include "src/base/platform/platform.h" |
5 #include "src/macro-assembler.h" | 9 #include "src/macro-assembler.h" |
6 #include "src/objects.h" | 10 #include "src/objects.h" |
7 #include "src/v8.h" | 11 #include "src/v8.h" |
8 | 12 |
9 #include "src/wasm/decoder.h" | 13 #include "src/wasm/decoder.h" |
10 #include "src/wasm/module-decoder.h" | |
11 | 14 |
12 namespace v8 { | 15 namespace v8 { |
13 namespace internal { | 16 namespace internal { |
14 namespace wasm { | 17 namespace wasm { |
15 | 18 |
16 #if DEBUG | 19 #if DEBUG |
17 #define TRACE(...) \ | 20 #define TRACE(...) \ |
18 do { \ | 21 do { \ |
19 if (FLAG_trace_wasm_decoder) PrintF(__VA_ARGS__); \ | 22 if (FLAG_trace_wasm_decoder) PrintF(__VA_ARGS__); \ |
20 } while (false) | 23 } while (false) |
(...skipping 12 matching lines...) Expand all Loading... |
33 if (limit_ < start_) { | 36 if (limit_ < start_) { |
34 error(start_, "end is less than start"); | 37 error(start_, "end is less than start"); |
35 limit_ = start_; | 38 limit_ = start_; |
36 } | 39 } |
37 } | 40 } |
38 | 41 |
39 virtual void onFirstError() { | 42 virtual void onFirstError() { |
40 pc_ = limit_; // On error, terminate section decoding loop. | 43 pc_ = limit_; // On error, terminate section decoding loop. |
41 } | 44 } |
42 | 45 |
| 46 static void DumpModule(WasmModule* module, ModuleResult result) { |
| 47 std::string path; |
| 48 if (FLAG_dump_wasm_module_path) { |
| 49 path = FLAG_dump_wasm_module_path; |
| 50 if (path.size() && |
| 51 !base::OS::isDirectorySeparator(path[path.size() - 1])) { |
| 52 path += base::OS::DirectorySeparator(); |
| 53 } |
| 54 } |
| 55 // File are named `HASH.{ok,failed}.wasm`. |
| 56 size_t hash = base::hash_range(module->module_start, module->module_end); |
| 57 char buf[32] = {'\0'}; |
| 58 #if V8_OS_WIN && _MSC_VER < 1900 |
| 59 #define snprintf sprintf_s |
| 60 #endif |
| 61 snprintf(buf, sizeof(buf) - 1, "%016zx.%s.wasm", hash, |
| 62 result.ok() ? "ok" : "failed"); |
| 63 std::string name(buf); |
| 64 if (FILE* wasm_file = base::OS::FOpen((path + name).c_str(), "wb")) { |
| 65 fwrite(module->module_start, module->module_end - module->module_start, 1, |
| 66 wasm_file); |
| 67 fclose(wasm_file); |
| 68 } |
| 69 } |
| 70 |
43 // Decodes an entire module. | 71 // Decodes an entire module. |
44 ModuleResult DecodeModule(WasmModule* module, bool verify_functions = true) { | 72 ModuleResult DecodeModule(WasmModule* module, bool verify_functions = true) { |
45 pc_ = start_; | 73 pc_ = start_; |
46 module->module_start = start_; | 74 module->module_start = start_; |
47 module->module_end = limit_; | 75 module->module_end = limit_; |
48 module->min_mem_pages = 0; | 76 module->min_mem_pages = 0; |
49 module->max_mem_pages = 0; | 77 module->max_mem_pages = 0; |
50 module->mem_export = false; | 78 module->mem_export = false; |
51 module->mem_external = false; | 79 module->mem_external = false; |
52 module->origin = origin_; | 80 module->origin = origin_; |
53 | 81 |
54 bool sections[(size_t)WasmSection::Code::Max] = {false}; | 82 bool sections[(size_t)WasmSection::Code::Max] = {false}; |
55 | 83 |
56 const byte* pos = pc_; | 84 const byte* pos = pc_; |
57 uint32_t magic_word = consume_u32("wasm magic"); | 85 uint32_t magic_word = consume_u32("wasm magic"); |
58 #define BYTES(x) (x & 0xff), (x >> 8) & 0xff, (x >> 16) & 0xff, (x >> 24) & 0xff | 86 #define BYTES(x) (x & 0xff), (x >> 8) & 0xff, (x >> 16) & 0xff, (x >> 24) & 0xff |
59 if (magic_word != kWasmMagic) { | 87 if (magic_word != kWasmMagic) { |
60 error(pos, pos, | 88 error(pos, pos, |
61 "expected magic word %02x %02x %02x %02x, " | 89 "expected magic word %02x %02x %02x %02x, " |
62 "found %02x %02x %02x %02x", | 90 "found %02x %02x %02x %02x", |
63 BYTES(kWasmMagic), BYTES(magic_word)); | 91 BYTES(kWasmMagic), BYTES(magic_word)); |
64 return toResult(module); | 92 goto done; |
65 } | 93 } |
66 | 94 |
67 pos = pc_; | 95 pos = pc_; |
68 uint32_t magic_version = consume_u32("wasm version"); | 96 { |
69 if (magic_version != kWasmVersion) { | 97 uint32_t magic_version = consume_u32("wasm version"); |
70 error(pos, pos, | 98 if (magic_version != kWasmVersion) { |
71 "expected version %02x %02x %02x %02x, " | 99 error(pos, pos, |
72 "found %02x %02x %02x %02x", | 100 "expected version %02x %02x %02x %02x, " |
73 BYTES(kWasmVersion), BYTES(magic_version)); | 101 "found %02x %02x %02x %02x", |
74 return toResult(module); | 102 BYTES(kWasmVersion), BYTES(magic_version)); |
| 103 goto done; |
| 104 } |
75 } | 105 } |
76 | 106 |
77 // Decode the module sections. | 107 // Decode the module sections. |
78 while (pc_ < limit_) { | 108 while (pc_ < limit_) { |
79 TRACE("DecodeSection\n"); | 109 TRACE("DecodeSection\n"); |
80 pos = pc_; | 110 pos = pc_; |
81 | 111 |
82 int length; | 112 int length; |
83 uint32_t section_length = consume_u32v(&length, "section size"); | 113 uint32_t section_length = consume_u32v(&length, "section size"); |
84 | 114 |
(...skipping 274 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
359 exp->func_index = consume_func_index(module, &func); | 389 exp->func_index = consume_func_index(module, &func); |
360 exp->name_offset = consume_string(&exp->name_length, "export name"); | 390 exp->name_offset = consume_string(&exp->name_length, "export name"); |
361 } | 391 } |
362 break; | 392 break; |
363 } | 393 } |
364 case WasmSection::Code::Max: | 394 case WasmSection::Code::Max: |
365 UNREACHABLE(); // Already skipped unknown sections. | 395 UNREACHABLE(); // Already skipped unknown sections. |
366 } | 396 } |
367 } | 397 } |
368 | 398 |
369 return toResult(module); | 399 done: |
| 400 ModuleResult result = toResult(module); |
| 401 if (FLAG_dump_wasm_module) { |
| 402 DumpModule(module, result); |
| 403 } |
| 404 return result; |
370 } | 405 } |
371 | 406 |
372 uint32_t SafeReserve(uint32_t count) { | 407 uint32_t SafeReserve(uint32_t count) { |
373 // Avoid OOM by only reserving up to a certain size. | 408 // Avoid OOM by only reserving up to a certain size. |
374 const uint32_t kMaxReserve = 20000; | 409 const uint32_t kMaxReserve = 20000; |
375 return count < kMaxReserve ? count : kMaxReserve; | 410 return count < kMaxReserve ? count : kMaxReserve; |
376 } | 411 } |
377 | 412 |
378 void CheckForFunctions(WasmModule* module, WasmSection::Code section) { | 413 void CheckForFunctions(WasmModule* module, WasmSection::Code section) { |
379 if (module->functions.size() == 0) { | 414 if (module->functions.size() == 0) { |
(...skipping 12 matching lines...) Expand all Loading... |
392 } else { | 427 } else { |
393 error(pc_ - 1, nullptr, "%s section already present", | 428 error(pc_ - 1, nullptr, "%s section already present", |
394 WasmSection::getName(section)); | 429 WasmSection::getName(section)); |
395 } | 430 } |
396 } | 431 } |
397 | 432 |
398 // Decodes a single anonymous function starting at {start_}. | 433 // Decodes a single anonymous function starting at {start_}. |
399 FunctionResult DecodeSingleFunction(ModuleEnv* module_env, | 434 FunctionResult DecodeSingleFunction(ModuleEnv* module_env, |
400 WasmFunction* function) { | 435 WasmFunction* function) { |
401 pc_ = start_; | 436 pc_ = start_; |
402 function->sig = consume_sig(); // read signature | 437 function->sig = consume_sig(); // read signature |
403 function->name_offset = 0; // ---- name | 438 function->name_offset = 0; // ---- name |
404 function->name_length = 0; // ---- name length | 439 function->name_length = 0; // ---- name length |
405 function->code_start_offset = off(pc_); // ---- code start | 440 function->code_start_offset = off(pc_); // ---- code start |
406 function->code_end_offset = off(limit_); // ---- code end | 441 function->code_end_offset = off(limit_); // ---- code end |
407 function->exported = false; // ---- exported | 442 function->exported = false; // ---- exported |
408 function->external = false; // ---- external | 443 function->external = false; // ---- external |
409 | 444 |
410 if (ok()) VerifyFunctionBody(0, module_env, function); | 445 if (ok()) VerifyFunctionBody(0, module_env, function); |
411 | 446 |
412 FunctionResult result; | 447 FunctionResult result; |
413 result.CopyFrom(result_); // Copy error code and location. | 448 result.CopyFrom(result_); // Copy error code and location. |
414 result.val = function; | 449 result.val = function; |
415 return result; | 450 return result; |
416 } | 451 } |
417 | 452 |
418 // Decodes a single function signature at {start}. | 453 // Decodes a single function signature at {start}. |
(...skipping 337 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
756 if (function_start > function_end) return FunctionError("start > end"); | 791 if (function_start > function_end) return FunctionError("start > end"); |
757 if (size > kMaxFunctionSize) | 792 if (size > kMaxFunctionSize) |
758 return FunctionError("size > maximum function size"); | 793 return FunctionError("size > maximum function size"); |
759 WasmFunction* function = new WasmFunction(); | 794 WasmFunction* function = new WasmFunction(); |
760 ModuleDecoder decoder(zone, function_start, function_end, kWasmOrigin); | 795 ModuleDecoder decoder(zone, function_start, function_end, kWasmOrigin); |
761 return decoder.DecodeSingleFunction(module_env, function); | 796 return decoder.DecodeSingleFunction(module_env, function); |
762 } | 797 } |
763 } // namespace wasm | 798 } // namespace wasm |
764 } // namespace internal | 799 } // namespace internal |
765 } // namespace v8 | 800 } // namespace v8 |
OLD | NEW |