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

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

Issue 2404253002: [wasm] Provide better stack traces for asm.js code (Closed)
Patch Set: Address titzer's comments 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
« no previous file with comments | « src/wasm/module-decoder.h ('k') | src/wasm/wasm-debug.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
70 } 70 }
71 71
72 inline WasmSectionCode section_code() const { return section_code_; } 72 inline WasmSectionCode section_code() const { return section_code_; }
73 73
74 inline const byte* section_start() const { return section_start_; } 74 inline const byte* section_start() const { return section_start_; }
75 75
76 inline uint32_t section_length() const { 76 inline uint32_t section_length() const {
77 return static_cast<uint32_t>(section_end_ - section_start_); 77 return static_cast<uint32_t>(section_end_ - section_start_);
78 } 78 }
79 79
80 inline const byte* payload_start() const { return payload_start_; }
81
82 inline uint32_t payload_length() const {
83 return static_cast<uint32_t>(section_end_ - payload_start_);
84 }
85
80 inline const byte* section_end() const { return section_end_; } 86 inline const byte* section_end() const { return section_end_; }
81 87
82 // Advances to the next section, checking that decoding the current section 88 // Advances to the next section, checking that decoding the current section
83 // stopped at {section_end_}. 89 // stopped at {section_end_}.
84 void advance() { 90 void advance() {
85 if (decoder_.pc() != section_end_) { 91 if (decoder_.pc() != section_end_) {
86 const char* msg = decoder_.pc() < section_end_ ? "shorter" : "longer"; 92 const char* msg = decoder_.pc() < section_end_ ? "shorter" : "longer";
87 decoder_.error(decoder_.pc(), decoder_.pc(), 93 decoder_.error(decoder_.pc(), decoder_.pc(),
88 "section was %s than expected size " 94 "section was %s than expected size "
89 "(%u bytes expected, %zu decoded)", 95 "(%u bytes expected, %zu decoded)",
90 msg, section_length(), 96 msg, section_length(),
91 static_cast<size_t>(decoder_.pc() - section_start_)); 97 static_cast<size_t>(decoder_.pc() - section_start_));
92 } 98 }
93 next(); 99 next();
94 } 100 }
95 101
96 private: 102 private:
97 Decoder& decoder_; 103 Decoder& decoder_;
98 WasmSectionCode section_code_; 104 WasmSectionCode section_code_;
99 const byte* section_start_; 105 const byte* section_start_;
106 const byte* payload_start_;
100 const byte* section_end_; 107 const byte* section_end_;
101 108
102 // Reads the section code/name at the current position and sets up 109 // Reads the section code/name at the current position and sets up
103 // the internal fields. 110 // the internal fields.
104 void next() { 111 void next() {
105 while (true) { 112 while (true) {
106 if (!decoder_.more()) { 113 if (!decoder_.more()) {
107 section_code_ = kUnknownSectionCode; 114 section_code_ = kUnknownSectionCode;
108 return; 115 return;
109 } 116 }
110 uint8_t section_code = decoder_.consume_u8("section code"); 117 uint8_t section_code = decoder_.consume_u8("section code");
111 // Read and check the section size. 118 // Read and check the section size.
112 uint32_t section_length = decoder_.consume_u32v("section length"); 119 uint32_t section_length = decoder_.consume_u32v("section length");
113 section_start_ = decoder_.pc(); 120 section_start_ = decoder_.pc();
121 payload_start_ = section_start_;
114 if (decoder_.checkAvailable(section_length)) { 122 if (decoder_.checkAvailable(section_length)) {
115 // Get the limit of the section within the module. 123 // Get the limit of the section within the module.
116 section_end_ = section_start_ + section_length; 124 section_end_ = section_start_ + section_length;
117 } else { 125 } else {
118 // The section would extend beyond the end of the module. 126 // The section would extend beyond the end of the module.
119 section_end_ = section_start_; 127 section_end_ = section_start_;
120 } 128 }
121 129
122 if (section_code == kUnknownSectionCode) { 130 if (section_code == kUnknownSectionCode) {
123 // Check for the known "names" section. 131 // Check for the known "name" section.
124 uint32_t string_length = decoder_.consume_u32v("section name length"); 132 uint32_t string_length = decoder_.consume_u32v("section name length");
125 const byte* section_name_start = decoder_.pc(); 133 const byte* section_name_start = decoder_.pc();
126 decoder_.consume_bytes(string_length, "section name"); 134 decoder_.consume_bytes(string_length, "section name");
127 if (decoder_.failed() || decoder_.pc() > section_end_) { 135 if (decoder_.failed() || decoder_.pc() > section_end_) {
128 TRACE("Section name of length %u couldn't be read\n", string_length); 136 TRACE("Section name of length %u couldn't be read\n", string_length);
129 section_code_ = kUnknownSectionCode; 137 section_code_ = kUnknownSectionCode;
130 return; 138 return;
131 } 139 }
140 payload_start_ = decoder_.pc();
132 141
133 TRACE(" +%d section name : \"%.*s\"\n", 142 TRACE(" +%d section name : \"%.*s\"\n",
134 static_cast<int>(section_name_start - decoder_.start()), 143 static_cast<int>(section_name_start - decoder_.start()),
135 string_length < 20 ? string_length : 20, section_name_start); 144 string_length < 20 ? string_length : 20, section_name_start);
136 145
137 if (string_length == kNameStringLength && 146 if (string_length == kNameStringLength &&
138 strncmp(reinterpret_cast<const char*>(section_name_start), 147 strncmp(reinterpret_cast<const char*>(section_name_start),
139 kNameString, kNameStringLength) == 0) { 148 kNameString, kNameStringLength) == 0) {
140 section_code = kNameSectionCode; 149 section_code = kNameSectionCode;
141 } else { 150 } else {
(...skipping 441 matching lines...) Expand 10 before | Expand all | Expand 10 after
583 functions_count, module->num_declared_functions); 592 functions_count, module->num_declared_functions);
584 } 593 }
585 594
586 for (uint32_t i = 0; ok() && i < functions_count; ++i) { 595 for (uint32_t i = 0; ok() && i < functions_count; ++i) {
587 WasmFunction* function = 596 WasmFunction* function =
588 &module->functions[i + module->num_imported_functions]; 597 &module->functions[i + module->num_imported_functions];
589 function->name_offset = consume_string(&function->name_length, false); 598 function->name_offset = consume_string(&function->name_length, false);
590 599
591 uint32_t local_names_count = consume_u32v("local names count"); 600 uint32_t local_names_count = consume_u32v("local names count");
592 for (uint32_t j = 0; ok() && j < local_names_count; j++) { 601 for (uint32_t j = 0; ok() && j < local_names_count; j++) {
593 uint32_t unused = 0; 602 skip_string();
594 uint32_t offset = consume_string(&unused, false);
595 USE(unused);
596 USE(offset);
597 } 603 }
598 } 604 }
599 section_iter.advance(); 605 section_iter.advance();
600 } 606 }
601 607
602 // ===== Remaining sections ============================================== 608 // ===== Remaining sections ==============================================
603 if (section_iter.more() && ok()) { 609 if (section_iter.more() && ok()) {
604 error(pc(), pc(), "unexpected section: %s", 610 error(pc(), pc(), "unexpected section: %s",
605 SectionName(section_iter.section_code())); 611 SectionName(section_iter.section_code()));
606 } 612 }
(...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after
792 const byte* string_start = pc_; 798 const byte* string_start = pc_;
793 // Consume bytes before validation to guarantee that the string is not oob. 799 // Consume bytes before validation to guarantee that the string is not oob.
794 if (*length > 0) consume_bytes(*length, "string"); 800 if (*length > 0) consume_bytes(*length, "string");
795 if (ok() && validate_utf8 && 801 if (ok() && validate_utf8 &&
796 !unibrow::Utf8::Validate(string_start, *length)) { 802 !unibrow::Utf8::Validate(string_start, *length)) {
797 error(string_start, "no valid UTF-8 string"); 803 error(string_start, "no valid UTF-8 string");
798 } 804 }
799 return offset; 805 return offset;
800 } 806 }
801 807
808 // Skips over a length-prefixed string, but checks that it is within bounds.
809 void skip_string() {
810 uint32_t length = consume_u32v("string length");
811 consume_bytes(length, "string");
812 }
813
802 uint32_t consume_sig_index(WasmModule* module, FunctionSig** sig) { 814 uint32_t consume_sig_index(WasmModule* module, FunctionSig** sig) {
803 const byte* pos = pc_; 815 const byte* pos = pc_;
804 uint32_t sig_index = consume_u32v("signature index"); 816 uint32_t sig_index = consume_u32v("signature index");
805 if (sig_index >= module->signatures.size()) { 817 if (sig_index >= module->signatures.size()) {
806 error(pos, pos, "signature index %u out of bounds (%d signatures)", 818 error(pos, pos, "signature index %u out of bounds (%d signatures)",
807 sig_index, static_cast<int>(module->signatures.size())); 819 sig_index, static_cast<int>(module->signatures.size()));
808 *sig = nullptr; 820 *sig = nullptr;
809 return 0; 821 return 0;
810 } 822 }
811 *sig = module->signatures[sig_index]; 823 *sig = module->signatures[sig_index];
(...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after
1022 explicit FunctionError(const char* msg) { 1034 explicit FunctionError(const char* msg) {
1023 error_code = kError; 1035 error_code = kError;
1024 size_t len = strlen(msg) + 1; 1036 size_t len = strlen(msg) + 1;
1025 char* result = new char[len]; 1037 char* result = new char[len];
1026 strncpy(result, msg, len); 1038 strncpy(result, msg, len);
1027 result[len - 1] = 0; 1039 result[len - 1] = 0;
1028 error_msg.reset(result); 1040 error_msg.reset(result);
1029 } 1041 }
1030 }; 1042 };
1031 1043
1044 // Find section with given section code. Return Vector of the payload, or null
1045 // Vector if section is not found or module bytes are invalid.
1032 Vector<const byte> FindSection(const byte* module_start, const byte* module_end, 1046 Vector<const byte> FindSection(const byte* module_start, const byte* module_end,
1033 WasmSectionCode code) { 1047 WasmSectionCode code) {
1034 Decoder decoder(module_start, module_end); 1048 Decoder decoder(module_start, module_end);
1035 1049
1036 uint32_t magic_word = decoder.consume_u32("wasm magic"); 1050 uint32_t magic_word = decoder.consume_u32("wasm magic");
1037 if (magic_word != kWasmMagic) decoder.error("wrong magic word"); 1051 if (magic_word != kWasmMagic) decoder.error("wrong magic word");
1038 1052
1039 uint32_t magic_version = decoder.consume_u32("wasm version"); 1053 uint32_t magic_version = decoder.consume_u32("wasm version");
1040 if (magic_version != kWasmVersion) decoder.error("wrong wasm version"); 1054 if (magic_version != kWasmVersion) decoder.error("wrong wasm version");
1041 1055
1042 WasmSectionIterator section_iter(decoder); 1056 WasmSectionIterator section_iter(decoder);
1043 while (section_iter.more()) { 1057 while (section_iter.more()) {
1044 if (section_iter.section_code() == code) { 1058 if (section_iter.section_code() == code) {
1045 return Vector<const uint8_t>(section_iter.section_start(), 1059 return Vector<const uint8_t>(section_iter.payload_start(),
1046 section_iter.section_length()); 1060 section_iter.payload_length());
1047 } 1061 }
1048 decoder.consume_bytes(section_iter.section_length(), "section payload"); 1062 decoder.consume_bytes(section_iter.payload_length(), "section payload");
1049 section_iter.advance(); 1063 section_iter.advance();
1050 } 1064 }
1051 1065
1052 return Vector<const uint8_t>(); 1066 return Vector<const uint8_t>();
1053 } 1067 }
1054 1068
1055 } // namespace 1069 } // namespace
1056 1070
1057 ModuleResult DecodeWasmModule(Isolate* isolate, Zone* zone, 1071 ModuleResult DecodeWasmModule(Isolate* isolate, Zone* zone,
1058 const byte* module_start, const byte* module_end, 1072 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. 1125 // Find and decode the code section.
1112 Vector<const byte> code_section = 1126 Vector<const byte> code_section =
1113 FindSection(module_start, module_end, kCodeSectionCode); 1127 FindSection(module_start, module_end, kCodeSectionCode);
1114 Decoder decoder(code_section.start(), code_section.end()); 1128 Decoder decoder(code_section.start(), code_section.end());
1115 FunctionOffsets table; 1129 FunctionOffsets table;
1116 if (!code_section.start()) { 1130 if (!code_section.start()) {
1117 decoder.error("no code section"); 1131 decoder.error("no code section");
1118 return decoder.toResult(std::move(table)); 1132 return decoder.toResult(std::move(table));
1119 } 1133 }
1120 1134
1121 // Reserve entries for the imported functions. 1135 uint32_t functions_count = decoder.consume_u32v("functions count");
1122 table.reserve(num_imported_functions); 1136 // Reserve space for the entries, taking care of invalid input.
1123 for (uint32_t i = 0; i < num_imported_functions; i++) { 1137 if (functions_count < static_cast<unsigned>(code_section.length()) / 2) {
1124 table.push_back(std::make_pair(0, 0)); 1138 table.reserve(num_imported_functions + functions_count);
1125 } 1139 }
1126 1140
1127 uint32_t functions_count = decoder.consume_u32v("functions count"); 1141 // Add null entries for the imported functions.
1128 // Take care of invalid input here. 1142 table.resize(num_imported_functions);
1129 if (functions_count < static_cast<unsigned>(code_section.length()) / 2) 1143
1130 table.reserve(num_imported_functions + functions_count);
1131 int section_offset = static_cast<int>(code_section.start() - module_start); 1144 int section_offset = static_cast<int>(code_section.start() - module_start);
1132 DCHECK_LE(0, section_offset); 1145 DCHECK_LE(0, section_offset);
1133 for (uint32_t i = 0; i < functions_count && decoder.ok(); ++i) { 1146 for (uint32_t i = 0; i < functions_count && decoder.ok(); ++i) {
1134 uint32_t size = decoder.consume_u32v("body size"); 1147 uint32_t size = decoder.consume_u32v("body size");
1135 int offset = static_cast<int>(section_offset + decoder.pc_offset()); 1148 int offset = static_cast<int>(section_offset + decoder.pc_offset());
1136 table.push_back(std::make_pair(offset, static_cast<int>(size))); 1149 table.push_back(std::make_pair(offset, static_cast<int>(size)));
1137 DCHECK(table.back().first >= 0 && table.back().second >= 0); 1150 DCHECK(table.back().first >= 0 && table.back().second >= 0);
1138 decoder.consume_bytes(size); 1151 decoder.consume_bytes(size);
1139 } 1152 }
1140 if (decoder.more()) decoder.error("unexpected additional bytes"); 1153 if (decoder.more()) decoder.error("unexpected additional bytes");
1141 1154
1142 return decoder.toResult(std::move(table)); 1155 return decoder.toResult(std::move(table));
1143 } 1156 }
1144 1157
1158 AsmJsOffsetsResult DecodeAsmJsOffsets(const byte* tables_start,
1159 const byte* tables_end,
1160 uint32_t num_imported_functions) {
1161 AsmJsOffsets table;
1162
1163 Decoder decoder(tables_start, tables_end);
1164 uint32_t functions_count = decoder.consume_u32v("functions count");
1165 // Reserve space for the entries, taking care of invalid input.
1166 if (functions_count < static_cast<unsigned>(tables_end - tables_start)) {
1167 table.reserve(num_imported_functions + functions_count);
1168 }
1169
1170 // Add null entries for the imported functions.
1171 table.resize(num_imported_functions);
1172
1173 for (uint32_t i = 0; i < functions_count && decoder.ok(); ++i) {
1174 uint32_t size = decoder.consume_u32v("table size");
1175 if (size == 0) {
1176 table.push_back(std::vector<std::pair<int, int>>());
1177 continue;
1178 }
1179 if (!decoder.checkAvailable(size)) {
1180 decoder.error("illegal asm function offset table size");
1181 }
1182 const byte* table_end = decoder.pc() + size;
1183 uint32_t locals_size = decoder.consume_u32("locals size");
1184 int last_byte_offset = locals_size;
1185 int last_asm_position = 0;
1186 std::vector<std::pair<int, int>> func_asm_offsets;
1187 func_asm_offsets.reserve(size / 4); // conservative estimation
1188 while (decoder.ok() && decoder.pc() < table_end) {
1189 last_byte_offset += decoder.consume_u32v("byte offset delta");
1190 last_asm_position += decoder.consume_i32v("asm position delta");
1191 func_asm_offsets.push_back({last_byte_offset, last_asm_position});
1192 }
1193 if (decoder.pc() != table_end) {
1194 decoder.error("broken asm offset table");
1195 }
1196 table.push_back(std::move(func_asm_offsets));
1197 }
1198 if (decoder.more()) decoder.error("unexpected additional bytes");
1199
1200 return decoder.toResult(std::move(table));
1201 }
1202
1145 } // namespace wasm 1203 } // namespace wasm
1146 } // namespace internal 1204 } // namespace internal
1147 } // namespace v8 1205 } // namespace v8
OLDNEW
« no previous file with comments | « src/wasm/module-decoder.h ('k') | src/wasm/wasm-debug.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698