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" | 5 #include "src/wasm/module-decoder.h" |
6 | 6 |
7 #include "src/base/functional.h" | 7 #include "src/base/functional.h" |
8 #include "src/base/platform/platform.h" | 8 #include "src/base/platform/platform.h" |
9 #include "src/flags.h" | 9 #include "src/flags.h" |
10 #include "src/macro-assembler.h" | 10 #include "src/macro-assembler.h" |
(...skipping 13 matching lines...) Expand all Loading... |
24 } while (false) | 24 } while (false) |
25 #else | 25 #else |
26 #define TRACE(...) | 26 #define TRACE(...) |
27 #endif | 27 #endif |
28 | 28 |
29 namespace { | 29 namespace { |
30 | 30 |
31 const char* kNameString = "name"; | 31 const char* kNameString = "name"; |
32 const size_t kNameStringLength = 4; | 32 const size_t kNameStringLength = 4; |
33 | 33 |
| 34 const char* kAsmOffsetsString = "asm_offsets"; |
| 35 const size_t kAsmOffsetsLength = 11; |
| 36 |
34 LocalType TypeOf(const WasmModule* module, const WasmInitExpr& expr) { | 37 LocalType TypeOf(const WasmModule* module, const WasmInitExpr& expr) { |
35 switch (expr.kind) { | 38 switch (expr.kind) { |
36 case WasmInitExpr::kNone: | 39 case WasmInitExpr::kNone: |
37 return kAstStmt; | 40 return kAstStmt; |
38 case WasmInitExpr::kGlobalIndex: | 41 case WasmInitExpr::kGlobalIndex: |
39 return expr.val.global_index < module->globals.size() | 42 return expr.val.global_index < module->globals.size() |
40 ? module->globals[expr.val.global_index].type | 43 ? module->globals[expr.val.global_index].type |
41 : kAstStmt; | 44 : kAstStmt; |
42 case WasmInitExpr::kI32Const: | 45 case WasmInitExpr::kI32Const: |
43 return kAstI32; | 46 return kAstI32; |
(...skipping 26 matching lines...) Expand all Loading... |
70 } | 73 } |
71 | 74 |
72 inline WasmSectionCode section_code() const { return section_code_; } | 75 inline WasmSectionCode section_code() const { return section_code_; } |
73 | 76 |
74 inline const byte* section_start() const { return section_start_; } | 77 inline const byte* section_start() const { return section_start_; } |
75 | 78 |
76 inline uint32_t section_length() const { | 79 inline uint32_t section_length() const { |
77 return static_cast<uint32_t>(section_end_ - section_start_); | 80 return static_cast<uint32_t>(section_end_ - section_start_); |
78 } | 81 } |
79 | 82 |
| 83 inline const byte* payload_start() const { return payload_start_; } |
| 84 |
| 85 inline uint32_t payload_length() const { |
| 86 return static_cast<uint32_t>(section_end_ - payload_start_); |
| 87 } |
| 88 |
80 inline const byte* section_end() const { return section_end_; } | 89 inline const byte* section_end() const { return section_end_; } |
81 | 90 |
82 // Advances to the next section, checking that decoding the current section | 91 // Advances to the next section, checking that decoding the current section |
83 // stopped at {section_end_}. | 92 // stopped at {section_end_}. |
84 void advance() { | 93 void advance() { |
85 if (decoder_.pc() != section_end_) { | 94 if (decoder_.pc() != section_end_) { |
86 const char* msg = decoder_.pc() < section_end_ ? "shorter" : "longer"; | 95 const char* msg = decoder_.pc() < section_end_ ? "shorter" : "longer"; |
87 decoder_.error(decoder_.pc(), decoder_.pc(), | 96 decoder_.error(decoder_.pc(), decoder_.pc(), |
88 "section was %s than expected size " | 97 "section was %s than expected size " |
89 "(%u bytes expected, %zu decoded)", | 98 "(%u bytes expected, %zu decoded)", |
90 msg, section_length(), | 99 msg, section_length(), |
91 static_cast<size_t>(decoder_.pc() - section_start_)); | 100 static_cast<size_t>(decoder_.pc() - section_start_)); |
92 } | 101 } |
93 next(); | 102 next(); |
94 } | 103 } |
95 | 104 |
96 private: | 105 private: |
97 Decoder& decoder_; | 106 Decoder& decoder_; |
98 WasmSectionCode section_code_; | 107 WasmSectionCode section_code_; |
99 const byte* section_start_; | 108 const byte* section_start_; |
| 109 const byte* payload_start_; |
100 const byte* section_end_; | 110 const byte* section_end_; |
101 | 111 |
102 // Reads the section code/name at the current position and sets up | 112 // Reads the section code/name at the current position and sets up |
103 // the internal fields. | 113 // the internal fields. |
104 void next() { | 114 void next() { |
105 while (true) { | 115 while (true) { |
106 if (!decoder_.more()) { | 116 if (!decoder_.more()) { |
107 section_code_ = kUnknownSectionCode; | 117 section_code_ = kUnknownSectionCode; |
108 return; | 118 return; |
109 } | 119 } |
110 uint8_t section_code = decoder_.consume_u8("section code"); | 120 uint8_t section_code = decoder_.consume_u8("section code"); |
111 // Read and check the section size. | 121 // Read and check the section size. |
112 uint32_t section_length = decoder_.consume_u32v("section length"); | 122 uint32_t section_length = decoder_.consume_u32v("section length"); |
113 section_start_ = decoder_.pc(); | 123 section_start_ = decoder_.pc(); |
| 124 payload_start_ = section_start_; |
114 if (decoder_.checkAvailable(section_length)) { | 125 if (decoder_.checkAvailable(section_length)) { |
115 // Get the limit of the section within the module. | 126 // Get the limit of the section within the module. |
116 section_end_ = section_start_ + section_length; | 127 section_end_ = section_start_ + section_length; |
117 } else { | 128 } else { |
118 // The section would extend beyond the end of the module. | 129 // The section would extend beyond the end of the module. |
119 section_end_ = section_start_; | 130 section_end_ = section_start_; |
120 } | 131 } |
121 | 132 |
122 if (section_code == kUnknownSectionCode) { | 133 if (section_code == kUnknownSectionCode) { |
123 // Check for the known "names" section. | 134 // Check for the known "name" or "asm_offsets" section. |
124 uint32_t string_length = decoder_.consume_u32v("section name length"); | 135 uint32_t string_length = decoder_.consume_u32v("section name length"); |
125 const byte* section_name_start = decoder_.pc(); | 136 const byte* section_name_start = decoder_.pc(); |
126 decoder_.consume_bytes(string_length, "section name"); | 137 decoder_.consume_bytes(string_length, "section name"); |
127 if (decoder_.failed() || decoder_.pc() > section_end_) { | 138 if (decoder_.failed() || decoder_.pc() > section_end_) { |
128 TRACE("Section name of length %u couldn't be read\n", string_length); | 139 TRACE("Section name of length %u couldn't be read\n", string_length); |
129 section_code_ = kUnknownSectionCode; | 140 section_code_ = kUnknownSectionCode; |
130 return; | 141 return; |
131 } | 142 } |
| 143 payload_start_ = decoder_.pc(); |
132 | 144 |
133 TRACE(" +%d section name : \"%.*s\"\n", | 145 TRACE(" +%d section name : \"%.*s\"\n", |
134 static_cast<int>(section_name_start - decoder_.start()), | 146 static_cast<int>(section_name_start - decoder_.start()), |
135 string_length < 20 ? string_length : 20, section_name_start); | 147 string_length < 20 ? string_length : 20, section_name_start); |
136 | 148 |
137 if (string_length == kNameStringLength && | 149 if (string_length == kNameStringLength && |
138 strncmp(reinterpret_cast<const char*>(section_name_start), | 150 memcmp(reinterpret_cast<const char*>(section_name_start), |
139 kNameString, kNameStringLength) == 0) { | 151 kNameString, kNameStringLength) == 0) { |
140 section_code = kNameSectionCode; | 152 section_code = kNameSectionCode; |
| 153 } else if (string_length == kAsmOffsetsLength && |
| 154 memcmp(reinterpret_cast<const char*>(section_name_start), |
| 155 kAsmOffsetsString, kAsmOffsetsLength) == 0) { |
| 156 section_code = kAsmOffsetsSectionCode; |
141 } else { | 157 } else { |
142 section_code = kUnknownSectionCode; | 158 section_code = kUnknownSectionCode; |
143 } | 159 } |
144 } else if (!IsValidSectionCode(section_code)) { | 160 } else if (!IsValidSectionCode(section_code)) { |
145 decoder_.error(decoder_.pc(), decoder_.pc(), | 161 decoder_.error(decoder_.pc(), decoder_.pc(), |
146 "unknown section code #0x%02x", section_code); | 162 "unknown section code #0x%02x", section_code); |
147 section_code = kUnknownSectionCode; | 163 section_code = kUnknownSectionCode; |
148 } | 164 } |
149 section_code_ = static_cast<WasmSectionCode>(section_code); | 165 section_code_ = static_cast<WasmSectionCode>(section_code); |
150 | 166 |
(...skipping 432 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
583 functions_count, module->num_declared_functions); | 599 functions_count, module->num_declared_functions); |
584 } | 600 } |
585 | 601 |
586 for (uint32_t i = 0; ok() && i < functions_count; ++i) { | 602 for (uint32_t i = 0; ok() && i < functions_count; ++i) { |
587 WasmFunction* function = | 603 WasmFunction* function = |
588 &module->functions[i + module->num_imported_functions]; | 604 &module->functions[i + module->num_imported_functions]; |
589 function->name_offset = consume_string(&function->name_length, false); | 605 function->name_offset = consume_string(&function->name_length, false); |
590 | 606 |
591 uint32_t local_names_count = consume_u32v("local names count"); | 607 uint32_t local_names_count = consume_u32v("local names count"); |
592 for (uint32_t j = 0; ok() && j < local_names_count; j++) { | 608 for (uint32_t j = 0; ok() && j < local_names_count; j++) { |
593 uint32_t unused = 0; | 609 skip_string(); |
594 uint32_t offset = consume_string(&unused, false); | |
595 USE(unused); | |
596 USE(offset); | |
597 } | 610 } |
598 } | 611 } |
599 section_iter.advance(); | 612 section_iter.advance(); |
600 } | 613 } |
601 | 614 |
| 615 // ===== Wasm to asm.js offset table ===================================== |
| 616 if (section_iter.section_code() == kAsmOffsetsSectionCode) { |
| 617 const byte* pos = pc_; |
| 618 uint32_t functions_count = consume_u32v("functions count"); |
| 619 if (functions_count != module->num_declared_functions) { |
| 620 error(pos, pos, "function name count %u mismatch (%u expected)", |
| 621 functions_count, module->num_declared_functions); |
| 622 } |
| 623 |
| 624 for (uint32_t i = 0; ok() && i < functions_count; ++i) { |
| 625 // Do not store anything yet. Data will be decoded on-demand in |
| 626 // WasmDebugInfo. |
| 627 skip_string(); |
| 628 } |
| 629 section_iter.advance(); |
| 630 } |
| 631 |
602 // ===== Remaining sections ============================================== | 632 // ===== Remaining sections ============================================== |
603 if (section_iter.more() && ok()) { | 633 if (section_iter.more() && ok()) { |
604 error(pc(), pc(), "unexpected section: %s", | 634 error(pc(), pc(), "unexpected section: %s", |
605 SectionName(section_iter.section_code())); | 635 SectionName(section_iter.section_code())); |
606 } | 636 } |
607 | 637 |
608 if (ok()) { | 638 if (ok()) { |
609 CalculateGlobalOffsets(module); | 639 CalculateGlobalOffsets(module); |
610 PreinitializeIndirectFunctionTables(module); | 640 PreinitializeIndirectFunctionTables(module); |
611 } | 641 } |
(...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
792 const byte* string_start = pc_; | 822 const byte* string_start = pc_; |
793 // Consume bytes before validation to guarantee that the string is not oob. | 823 // Consume bytes before validation to guarantee that the string is not oob. |
794 if (*length > 0) consume_bytes(*length, "string"); | 824 if (*length > 0) consume_bytes(*length, "string"); |
795 if (ok() && validate_utf8 && | 825 if (ok() && validate_utf8 && |
796 !unibrow::Utf8::Validate(string_start, *length)) { | 826 !unibrow::Utf8::Validate(string_start, *length)) { |
797 error(string_start, "no valid UTF-8 string"); | 827 error(string_start, "no valid UTF-8 string"); |
798 } | 828 } |
799 return offset; | 829 return offset; |
800 } | 830 } |
801 | 831 |
| 832 // Skips over a length-prefixed string, but checks that it is within bounds. |
| 833 void skip_string() { |
| 834 uint32_t length = consume_u32v("string length"); |
| 835 consume_bytes(length, "string"); |
| 836 } |
| 837 |
802 uint32_t consume_sig_index(WasmModule* module, FunctionSig** sig) { | 838 uint32_t consume_sig_index(WasmModule* module, FunctionSig** sig) { |
803 const byte* pos = pc_; | 839 const byte* pos = pc_; |
804 uint32_t sig_index = consume_u32v("signature index"); | 840 uint32_t sig_index = consume_u32v("signature index"); |
805 if (sig_index >= module->signatures.size()) { | 841 if (sig_index >= module->signatures.size()) { |
806 error(pos, pos, "signature index %u out of bounds (%d signatures)", | 842 error(pos, pos, "signature index %u out of bounds (%d signatures)", |
807 sig_index, static_cast<int>(module->signatures.size())); | 843 sig_index, static_cast<int>(module->signatures.size())); |
808 *sig = nullptr; | 844 *sig = nullptr; |
809 return 0; | 845 return 0; |
810 } | 846 } |
811 *sig = module->signatures[sig_index]; | 847 *sig = module->signatures[sig_index]; |
(...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1022 explicit FunctionError(const char* msg) { | 1058 explicit FunctionError(const char* msg) { |
1023 error_code = kError; | 1059 error_code = kError; |
1024 size_t len = strlen(msg) + 1; | 1060 size_t len = strlen(msg) + 1; |
1025 char* result = new char[len]; | 1061 char* result = new char[len]; |
1026 strncpy(result, msg, len); | 1062 strncpy(result, msg, len); |
1027 result[len - 1] = 0; | 1063 result[len - 1] = 0; |
1028 error_msg.reset(result); | 1064 error_msg.reset(result); |
1029 } | 1065 } |
1030 }; | 1066 }; |
1031 | 1067 |
| 1068 // Find section with given section code. Return Vector of the payload, or null |
| 1069 // Vector if section is not found or module bytes are invalid. |
1032 Vector<const byte> FindSection(const byte* module_start, const byte* module_end, | 1070 Vector<const byte> FindSection(const byte* module_start, const byte* module_end, |
1033 WasmSectionCode code) { | 1071 WasmSectionCode code) { |
1034 Decoder decoder(module_start, module_end); | 1072 Decoder decoder(module_start, module_end); |
1035 | 1073 |
1036 uint32_t magic_word = decoder.consume_u32("wasm magic"); | 1074 uint32_t magic_word = decoder.consume_u32("wasm magic"); |
1037 if (magic_word != kWasmMagic) decoder.error("wrong magic word"); | 1075 if (magic_word != kWasmMagic) decoder.error("wrong magic word"); |
1038 | 1076 |
1039 uint32_t magic_version = decoder.consume_u32("wasm version"); | 1077 uint32_t magic_version = decoder.consume_u32("wasm version"); |
1040 if (magic_version != kWasmVersion) decoder.error("wrong wasm version"); | 1078 if (magic_version != kWasmVersion) decoder.error("wrong wasm version"); |
1041 | 1079 |
1042 WasmSectionIterator section_iter(decoder); | 1080 WasmSectionIterator section_iter(decoder); |
1043 while (section_iter.more()) { | 1081 while (section_iter.more()) { |
1044 if (section_iter.section_code() == code) { | 1082 if (section_iter.section_code() == code) { |
1045 return Vector<const uint8_t>(section_iter.section_start(), | 1083 return Vector<const uint8_t>(section_iter.payload_start(), |
1046 section_iter.section_length()); | 1084 section_iter.payload_length()); |
1047 } | 1085 } |
1048 decoder.consume_bytes(section_iter.section_length(), "section payload"); | 1086 decoder.consume_bytes(section_iter.payload_length(), "section payload"); |
1049 section_iter.advance(); | 1087 section_iter.advance(); |
1050 } | 1088 } |
1051 | 1089 |
1052 return Vector<const uint8_t>(); | 1090 return Vector<const uint8_t>(); |
1053 } | 1091 } |
1054 | 1092 |
1055 } // namespace | 1093 } // namespace |
1056 | 1094 |
1057 ModuleResult DecodeWasmModule(Isolate* isolate, Zone* zone, | 1095 ModuleResult DecodeWasmModule(Isolate* isolate, Zone* zone, |
1058 const byte* module_start, const byte* module_end, | 1096 const byte* module_start, const byte* module_end, |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1111 // Find and decode the code section. | 1149 // Find and decode the code section. |
1112 Vector<const byte> code_section = | 1150 Vector<const byte> code_section = |
1113 FindSection(module_start, module_end, kCodeSectionCode); | 1151 FindSection(module_start, module_end, kCodeSectionCode); |
1114 Decoder decoder(code_section.start(), code_section.end()); | 1152 Decoder decoder(code_section.start(), code_section.end()); |
1115 FunctionOffsets table; | 1153 FunctionOffsets table; |
1116 if (!code_section.start()) { | 1154 if (!code_section.start()) { |
1117 decoder.error("no code section"); | 1155 decoder.error("no code section"); |
1118 return decoder.toResult(std::move(table)); | 1156 return decoder.toResult(std::move(table)); |
1119 } | 1157 } |
1120 | 1158 |
1121 // Reserve entries for the imported functions. | |
1122 table.reserve(num_imported_functions); | |
1123 for (uint32_t i = 0; i < num_imported_functions; i++) { | |
1124 table.push_back(std::make_pair(0, 0)); | |
1125 } | |
1126 | |
1127 uint32_t functions_count = decoder.consume_u32v("functions count"); | 1159 uint32_t functions_count = decoder.consume_u32v("functions count"); |
1128 // Take care of invalid input here. | 1160 // Reserve space for the entries, taking care of invalid input. |
1129 if (functions_count < static_cast<unsigned>(code_section.length()) / 2) | 1161 if (functions_count < static_cast<unsigned>(code_section.length()) / 2) |
1130 table.reserve(num_imported_functions + functions_count); | 1162 table.reserve(num_imported_functions + functions_count); |
| 1163 |
| 1164 // Add null entries for the imported functions. |
| 1165 table.resize(num_imported_functions); |
| 1166 |
1131 int section_offset = static_cast<int>(code_section.start() - module_start); | 1167 int section_offset = static_cast<int>(code_section.start() - module_start); |
1132 DCHECK_LE(0, section_offset); | 1168 DCHECK_LE(0, section_offset); |
1133 for (uint32_t i = 0; i < functions_count && decoder.ok(); ++i) { | 1169 for (uint32_t i = 0; i < functions_count && decoder.ok(); ++i) { |
1134 uint32_t size = decoder.consume_u32v("body size"); | 1170 uint32_t size = decoder.consume_u32v("body size"); |
1135 int offset = static_cast<int>(section_offset + decoder.pc_offset()); | 1171 int offset = static_cast<int>(section_offset + decoder.pc_offset()); |
1136 table.push_back(std::make_pair(offset, static_cast<int>(size))); | 1172 table.push_back(std::make_pair(offset, static_cast<int>(size))); |
1137 DCHECK(table.back().first >= 0 && table.back().second >= 0); | 1173 DCHECK(table.back().first >= 0 && table.back().second >= 0); |
1138 decoder.consume_bytes(size); | 1174 decoder.consume_bytes(size); |
1139 } | 1175 } |
1140 if (decoder.more()) decoder.error("unexpected additional bytes"); | 1176 if (decoder.more()) decoder.error("unexpected additional bytes"); |
1141 | 1177 |
1142 return decoder.toResult(std::move(table)); | 1178 return decoder.toResult(std::move(table)); |
1143 } | 1179 } |
1144 | 1180 |
| 1181 AsmJsOffsetsResult DecodeAsmJsOffsets(const byte* module_start, |
| 1182 const byte* module_end, |
| 1183 uint32_t num_imported_functions) { |
| 1184 // Find and decode the code section. |
| 1185 Vector<const byte> asm_offset_section = |
| 1186 FindSection(module_start, module_end, kAsmOffsetsSectionCode); |
| 1187 Decoder decoder(asm_offset_section.start(), asm_offset_section.end()); |
| 1188 AsmJsOffsets table; |
| 1189 if (!asm_offset_section.start()) { |
| 1190 decoder.error("no asm.js offsets section"); |
| 1191 return decoder.toResult(std::move(table)); |
| 1192 } |
| 1193 |
| 1194 uint32_t functions_count = decoder.consume_u32v("functions count"); |
| 1195 // Reserve space for the entries, taking care of invalid input. |
| 1196 if (functions_count < static_cast<unsigned>(asm_offset_section.length())) |
| 1197 table.reserve(num_imported_functions + functions_count); |
| 1198 |
| 1199 // Add null entries for the imported functions. |
| 1200 table.resize(num_imported_functions); |
| 1201 |
| 1202 for (uint32_t i = 0; i < functions_count && decoder.ok(); ++i) { |
| 1203 uint32_t size = decoder.consume_u32v("table size"); |
| 1204 if (size == 0) { |
| 1205 table.push_back(std::vector<std::pair<int, int>>()); |
| 1206 continue; |
| 1207 } |
| 1208 if (!decoder.checkAvailable(size)) { |
| 1209 decoder.error("illegal asm function offset table size"); |
| 1210 } |
| 1211 const byte* table_end = decoder.pc() + size; |
| 1212 uint32_t locals_size = decoder.consume_u32("locals size"); |
| 1213 int last_byte_offset = locals_size; |
| 1214 int last_asm_position = 0; |
| 1215 std::vector<std::pair<int, int>> func_asm_offsets; |
| 1216 func_asm_offsets.reserve(size / 4); // conservative estimation |
| 1217 while (decoder.ok() && decoder.pc() < table_end) { |
| 1218 last_byte_offset += decoder.consume_u32v("byte offset delta"); |
| 1219 last_asm_position += decoder.consume_i32v("asm position delta"); |
| 1220 func_asm_offsets.push_back({last_byte_offset, last_asm_position}); |
| 1221 } |
| 1222 if (decoder.pc() != table_end) { |
| 1223 decoder.error("broken asm offset table"); |
| 1224 } |
| 1225 table.push_back(std::move(func_asm_offsets)); |
| 1226 } |
| 1227 if (decoder.more()) decoder.error("unexpected additional bytes"); |
| 1228 |
| 1229 return decoder.toResult(std::move(table)); |
| 1230 } |
| 1231 |
1145 } // namespace wasm | 1232 } // namespace wasm |
1146 } // namespace internal | 1233 } // namespace internal |
1147 } // namespace v8 | 1234 } // namespace v8 |
OLD | NEW |