Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(18)

Side by Side Diff: src/wasm/module-decoder.cc

Issue 2404253002: [wasm] Provide better stack traces for asm.js code (Closed)
Patch Set: Rebase & fix paths for windows Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698