| Index: src/wasm/module-decoder.cc
|
| diff --git a/src/wasm/module-decoder.cc b/src/wasm/module-decoder.cc
|
| index 0f8637f32eeb1785c8a45bad1f585510d13e1f64..b5fcf766bc9ca76dcdfd31b7cc39942a55061f86 100644
|
| --- a/src/wasm/module-decoder.cc
|
| +++ b/src/wasm/module-decoder.cc
|
| @@ -31,6 +31,9 @@ namespace {
|
| const char* kNameString = "name";
|
| const size_t kNameStringLength = 4;
|
|
|
| +const char* kAsmOffsetsString = "asm_offsets";
|
| +const size_t kAsmOffsetsLength = 11;
|
| +
|
| LocalType TypeOf(const WasmModule* module, const WasmInitExpr& expr) {
|
| switch (expr.kind) {
|
| case WasmInitExpr::kNone:
|
| @@ -77,6 +80,12 @@ class WasmSectionIterator {
|
| return static_cast<uint32_t>(section_end_ - section_start_);
|
| }
|
|
|
| + inline const byte* payload_start() const { return payload_start_; }
|
| +
|
| + inline uint32_t payload_length() const {
|
| + return static_cast<uint32_t>(section_end_ - payload_start_);
|
| + }
|
| +
|
| inline const byte* section_end() const { return section_end_; }
|
|
|
| // Advances to the next section, checking that decoding the current section
|
| @@ -97,6 +106,7 @@ class WasmSectionIterator {
|
| Decoder& decoder_;
|
| WasmSectionCode section_code_;
|
| const byte* section_start_;
|
| + const byte* payload_start_;
|
| const byte* section_end_;
|
|
|
| // Reads the section code/name at the current position and sets up
|
| @@ -111,6 +121,7 @@ class WasmSectionIterator {
|
| // Read and check the section size.
|
| uint32_t section_length = decoder_.consume_u32v("section length");
|
| section_start_ = decoder_.pc();
|
| + payload_start_ = section_start_;
|
| if (decoder_.checkAvailable(section_length)) {
|
| // Get the limit of the section within the module.
|
| section_end_ = section_start_ + section_length;
|
| @@ -120,7 +131,7 @@ class WasmSectionIterator {
|
| }
|
|
|
| if (section_code == kUnknownSectionCode) {
|
| - // Check for the known "names" section.
|
| + // Check for the known "name" or "asm_offsets" section.
|
| uint32_t string_length = decoder_.consume_u32v("section name length");
|
| const byte* section_name_start = decoder_.pc();
|
| decoder_.consume_bytes(string_length, "section name");
|
| @@ -129,15 +140,20 @@ class WasmSectionIterator {
|
| section_code_ = kUnknownSectionCode;
|
| return;
|
| }
|
| + payload_start_ = decoder_.pc();
|
|
|
| TRACE(" +%d section name : \"%.*s\"\n",
|
| static_cast<int>(section_name_start - decoder_.start()),
|
| string_length < 20 ? string_length : 20, section_name_start);
|
|
|
| if (string_length == kNameStringLength &&
|
| - strncmp(reinterpret_cast<const char*>(section_name_start),
|
| - kNameString, kNameStringLength) == 0) {
|
| + memcmp(reinterpret_cast<const char*>(section_name_start),
|
| + kNameString, kNameStringLength) == 0) {
|
| section_code = kNameSectionCode;
|
| + } else if (string_length == kAsmOffsetsLength &&
|
| + memcmp(reinterpret_cast<const char*>(section_name_start),
|
| + kAsmOffsetsString, kAsmOffsetsLength) == 0) {
|
| + section_code = kAsmOffsetsSectionCode;
|
| } else {
|
| section_code = kUnknownSectionCode;
|
| }
|
| @@ -590,15 +606,29 @@ class ModuleDecoder : public Decoder {
|
|
|
| uint32_t local_names_count = consume_u32v("local names count");
|
| for (uint32_t j = 0; ok() && j < local_names_count; j++) {
|
| - uint32_t unused = 0;
|
| - uint32_t offset = consume_string(&unused, false);
|
| - USE(unused);
|
| - USE(offset);
|
| + skip_string();
|
| }
|
| }
|
| section_iter.advance();
|
| }
|
|
|
| + // ===== Wasm to asm.js offset table =====================================
|
| + if (section_iter.section_code() == kAsmOffsetsSectionCode) {
|
| + const byte* pos = pc_;
|
| + uint32_t functions_count = consume_u32v("functions count");
|
| + if (functions_count != module->num_declared_functions) {
|
| + error(pos, pos, "function name count %u mismatch (%u expected)",
|
| + functions_count, module->num_declared_functions);
|
| + }
|
| +
|
| + for (uint32_t i = 0; ok() && i < functions_count; ++i) {
|
| + // Do not store anything yet. Data will be decoded on-demand in
|
| + // WasmDebugInfo.
|
| + skip_string();
|
| + }
|
| + section_iter.advance();
|
| + }
|
| +
|
| // ===== Remaining sections ==============================================
|
| if (section_iter.more() && ok()) {
|
| error(pc(), pc(), "unexpected section: %s",
|
| @@ -799,6 +829,12 @@ class ModuleDecoder : public Decoder {
|
| return offset;
|
| }
|
|
|
| + // Skips over a length-prefixed string, but checks that it is within bounds.
|
| + void skip_string() {
|
| + uint32_t length = consume_u32v("string length");
|
| + consume_bytes(length, "string");
|
| + }
|
| +
|
| uint32_t consume_sig_index(WasmModule* module, FunctionSig** sig) {
|
| const byte* pos = pc_;
|
| uint32_t sig_index = consume_u32v("signature index");
|
| @@ -1029,6 +1065,8 @@ class FunctionError : public FunctionResult {
|
| }
|
| };
|
|
|
| +// Find section with given section code. Return Vector of the payload, or null
|
| +// Vector if section is not found or module bytes are invalid.
|
| Vector<const byte> FindSection(const byte* module_start, const byte* module_end,
|
| WasmSectionCode code) {
|
| Decoder decoder(module_start, module_end);
|
| @@ -1042,10 +1080,10 @@ Vector<const byte> FindSection(const byte* module_start, const byte* module_end,
|
| WasmSectionIterator section_iter(decoder);
|
| while (section_iter.more()) {
|
| if (section_iter.section_code() == code) {
|
| - return Vector<const uint8_t>(section_iter.section_start(),
|
| - section_iter.section_length());
|
| + return Vector<const uint8_t>(section_iter.payload_start(),
|
| + section_iter.payload_length());
|
| }
|
| - decoder.consume_bytes(section_iter.section_length(), "section payload");
|
| + decoder.consume_bytes(section_iter.payload_length(), "section payload");
|
| section_iter.advance();
|
| }
|
|
|
| @@ -1118,16 +1156,14 @@ FunctionOffsetsResult DecodeWasmFunctionOffsets(
|
| return decoder.toResult(std::move(table));
|
| }
|
|
|
| - // Reserve entries for the imported functions.
|
| - table.reserve(num_imported_functions);
|
| - for (uint32_t i = 0; i < num_imported_functions; i++) {
|
| - table.push_back(std::make_pair(0, 0));
|
| - }
|
| -
|
| uint32_t functions_count = decoder.consume_u32v("functions count");
|
| - // Take care of invalid input here.
|
| + // Reserve space for the entries, taking care of invalid input.
|
| if (functions_count < static_cast<unsigned>(code_section.length()) / 2)
|
| table.reserve(num_imported_functions + functions_count);
|
| +
|
| + // Add null entries for the imported functions.
|
| + table.resize(num_imported_functions);
|
| +
|
| int section_offset = static_cast<int>(code_section.start() - module_start);
|
| DCHECK_LE(0, section_offset);
|
| for (uint32_t i = 0; i < functions_count && decoder.ok(); ++i) {
|
| @@ -1142,6 +1178,57 @@ FunctionOffsetsResult DecodeWasmFunctionOffsets(
|
| return decoder.toResult(std::move(table));
|
| }
|
|
|
| +AsmJsOffsetsResult DecodeAsmJsOffsets(const byte* module_start,
|
| + const byte* module_end,
|
| + uint32_t num_imported_functions) {
|
| + // Find and decode the code section.
|
| + Vector<const byte> asm_offset_section =
|
| + FindSection(module_start, module_end, kAsmOffsetsSectionCode);
|
| + Decoder decoder(asm_offset_section.start(), asm_offset_section.end());
|
| + AsmJsOffsets table;
|
| + if (!asm_offset_section.start()) {
|
| + decoder.error("no asm.js offsets section");
|
| + return decoder.toResult(std::move(table));
|
| + }
|
| +
|
| + uint32_t functions_count = decoder.consume_u32v("functions count");
|
| + // Reserve space for the entries, taking care of invalid input.
|
| + if (functions_count < static_cast<unsigned>(asm_offset_section.length()))
|
| + table.reserve(num_imported_functions + functions_count);
|
| +
|
| + // Add null entries for the imported functions.
|
| + table.resize(num_imported_functions);
|
| +
|
| + for (uint32_t i = 0; i < functions_count && decoder.ok(); ++i) {
|
| + uint32_t size = decoder.consume_u32v("table size");
|
| + if (size == 0) {
|
| + table.push_back(std::vector<std::pair<int, int>>());
|
| + continue;
|
| + }
|
| + if (!decoder.checkAvailable(size)) {
|
| + decoder.error("illegal asm function offset table size");
|
| + }
|
| + const byte* table_end = decoder.pc() + size;
|
| + uint32_t locals_size = decoder.consume_u32("locals size");
|
| + int last_byte_offset = locals_size;
|
| + int last_asm_position = 0;
|
| + std::vector<std::pair<int, int>> func_asm_offsets;
|
| + func_asm_offsets.reserve(size / 4); // conservative estimation
|
| + while (decoder.ok() && decoder.pc() < table_end) {
|
| + last_byte_offset += decoder.consume_u32v("byte offset delta");
|
| + last_asm_position += decoder.consume_i32v("asm position delta");
|
| + func_asm_offsets.push_back({last_byte_offset, last_asm_position});
|
| + }
|
| + if (decoder.pc() != table_end) {
|
| + decoder.error("broken asm offset table");
|
| + }
|
| + table.push_back(std::move(func_asm_offsets));
|
| + }
|
| + if (decoder.more()) decoder.error("unexpected additional bytes");
|
| +
|
| + return decoder.toResult(std::move(table));
|
| +}
|
| +
|
| } // namespace wasm
|
| } // namespace internal
|
| } // namespace v8
|
|
|