diff options
-rw-r--r-- | src/binary-reader-logging.cc | 4 | ||||
-rw-r--r-- | src/binary-reader-logging.h | 4 | ||||
-rw-r--r-- | src/binary-reader-nop.h | 5 | ||||
-rw-r--r-- | src/binary-reader-objdump.cc | 15 | ||||
-rw-r--r-- | src/binary-reader.cc | 33 | ||||
-rw-r--r-- | src/binary-reader.h | 5 | ||||
-rw-r--r-- | src/binary-writer.cc | 6 | ||||
-rw-r--r-- | src/binary-writer.h | 12 | ||||
-rw-r--r-- | src/binary.cc | 24 | ||||
-rw-r--r-- | src/binary.h | 21 | ||||
-rw-r--r-- | src/tools/wast2json.cc | 1 | ||||
-rw-r--r-- | src/tools/wat2wasm.cc | 1 | ||||
-rw-r--r-- | test/binary/bad-data-count-mismatch.txt | 23 | ||||
-rw-r--r-- | test/binary/bad-data-count-order-after-code.txt | 11 | ||||
-rw-r--r-- | test/binary/bad-data-count-order-before-elem.txt | 11 | ||||
-rw-r--r-- | test/dump/bulk-memory.txt | 52 | ||||
-rw-r--r-- | test/dump/data-count-section.txt | 36 | ||||
-rwxr-xr-x | test/gen-wasm.py | 1 | ||||
-rw-r--r-- | test/spec/custom.txt | 2 |
19 files changed, 220 insertions, 47 deletions
diff --git a/src/binary-reader-logging.cc b/src/binary-reader-logging.cc index bb89fb9d..9a383584 100644 --- a/src/binary-reader-logging.cc +++ b/src/binary-reader-logging.cc @@ -738,6 +738,10 @@ DEFINE_INDEX(EndDataSegmentInitExpr) DEFINE_INDEX(EndDataSegment) DEFINE_END(EndDataSection) +DEFINE_BEGIN(BeginDataCountSection) +DEFINE_INDEX(OnDataCount) +DEFINE_END(EndDataCountSection) + DEFINE_BEGIN(BeginNamesSection) DEFINE_INDEX(OnFunctionNamesCount) DEFINE_INDEX(OnLocalNameFunctionCount) diff --git a/src/binary-reader-logging.h b/src/binary-reader-logging.h index 0f2c509a..edb6132e 100644 --- a/src/binary-reader-logging.h +++ b/src/binary-reader-logging.h @@ -233,6 +233,10 @@ class BinaryReaderLogging : public BinaryReaderDelegate { Result EndDataSegment(Index index) override; Result EndDataSection() override; + Result BeginDataCountSection(Offset size) override; + Result OnDataCount(Index count) override; + Result EndDataCountSection() override; + Result BeginNamesSection(Offset size) override; Result OnModuleNameSubsection(Index index, uint32_t name_type, diff --git a/src/binary-reader-nop.h b/src/binary-reader-nop.h index bfab11d8..20ac7158 100644 --- a/src/binary-reader-nop.h +++ b/src/binary-reader-nop.h @@ -307,6 +307,11 @@ class BinaryReaderNop : public BinaryReaderDelegate { Result EndDataSegment(Index index) override { return Result::Ok; } Result EndDataSection() override { return Result::Ok; } + /* DataCount section */ + Result BeginDataCountSection(Offset size) override { return Result::Ok; } + Result OnDataCount(Index count) override { return Result::Ok; } + Result EndDataCountSection() override { return Result::Ok; } + /* Names section */ Result BeginNamesSection(Offset size) override { return Result::Ok; } Result OnModuleNameSubsection(Index index, diff --git a/src/binary-reader-objdump.cc b/src/binary-reader-objdump.cc index 94ed487d..64cdaef0 100644 --- a/src/binary-reader-objdump.cc +++ b/src/binary-reader-objdump.cc @@ -717,6 +717,7 @@ class BinaryReaderObjdump : public BinaryReaderObjdumpBase { string_view name) override; Result OnStartFunction(Index func_index) override; + Result OnDataCount(Index count) override; Result OnFunctionBodyCount(Index count) override; Result BeginFunctionBody(Index index, Offset size) override; @@ -866,9 +867,10 @@ Result BinaryReaderObjdump::BeginSection(BinarySection section_code, case ObjdumpMode::Details: if (section_match) { printf("%s", name); - // All known section types except the start section have a count - // in which case this line gets completed in OnCount(). + // All known section types except the Start and DataCount sections have + // a count in which case this line gets completed in OnCount(). if (section_code == BinarySection::Start || + section_code == BinarySection::DataCount || section_code == BinarySection::Custom) { printf(":\n"); } @@ -994,6 +996,15 @@ Result BinaryReaderObjdump::OnStartFunction(Index func_index) { return Result::Ok; } +Result BinaryReaderObjdump::OnDataCount(Index count) { + if (options_->mode == ObjdumpMode::Headers) { + printf("count: %" PRIindex "\n", count); + } else { + PrintDetails(" - data count: %" PRIindex "\n", count); + } + return Result::Ok; +} + Result BinaryReaderObjdump::OnImportCount(Index count) { return OnCount(count); } diff --git a/src/binary-reader.cc b/src/binary-reader.cc index 089927cc..c01216e4 100644 --- a/src/binary-reader.cc +++ b/src/binary-reader.cc @@ -137,6 +137,7 @@ class BinaryReader { Result ReadElemSection(Offset section_size) WABT_WARN_UNUSED; Result ReadCodeSection(Offset section_size) WABT_WARN_UNUSED; Result ReadDataSection(Offset section_size) WABT_WARN_UNUSED; + Result ReadDataCountSection(Offset section_size) WABT_WARN_UNUSED; Result ReadExceptionSection(Offset section_size) WABT_WARN_UNUSED; Result ReadSections() WABT_WARN_UNUSED; Result ReportUnexpectedOpcode(Opcode opcode, const char* message = nullptr); @@ -166,6 +167,7 @@ class BinaryReader { Index num_exports_ = 0; Index num_function_bodies_ = 0; Index num_exceptions_ = 0; + Index data_count_ = kInvalidIndex; using ReadEndRestoreGuard = ValueRestoreGuard<size_t, &BinaryReader::read_end_>; @@ -2071,6 +2073,9 @@ Result BinaryReader::ReadDataSection(Offset section_size) { CALLBACK(OnDataSegmentCount, num_data_segments); ERROR_UNLESS(num_data_segments == 0 || NumTotalMemories() > 0, "data section without memory section"); + // If the DataCount section is not present, then data_count_ will be invalid. + ERROR_UNLESS(data_count_ == kInvalidIndex || data_count_ == num_data_segments, + "data segment count does not equal count in DataCount section"); for (Index i = 0; i < num_data_segments; ++i) { uint32_t flags_u32; CHECK_RESULT(ReadU32Leb128(&flags_u32, "data segment flags")); @@ -2098,6 +2103,16 @@ Result BinaryReader::ReadDataSection(Offset section_size) { return Result::Ok; } +Result BinaryReader::ReadDataCountSection(Offset section_size) { + CALLBACK(BeginDataCountSection, section_size); + Index data_count; + CHECK_RESULT(ReadIndex(&data_count, "data count")); + CALLBACK(OnDataCount, data_count); + CALLBACK0(EndDataCountSection); + data_count_ = data_count; + return Result::Ok; +} + Result BinaryReader::ReadSections() { Result result = Result::Ok; @@ -2109,8 +2124,7 @@ Result BinaryReader::ReadSections() { ReadEndRestoreGuard guard(this); read_end_ = state_.offset + section_size; if (section_code >= kBinarySectionCount) { - PrintError("invalid section code: %u; max is %u", section_code, - kBinarySectionCount - 1); + PrintError("invalid section code: %u", section_code); return Result::Error; } @@ -2119,10 +2133,11 @@ Result BinaryReader::ReadSections() { ERROR_UNLESS(read_end_ <= state_.size, "invalid section size: extends past end"); - ERROR_UNLESS(last_known_section_ == BinarySection::Invalid || - section == BinarySection::Custom || - section > last_known_section_, - "section %s out of order", GetSectionName(section)); + ERROR_UNLESS( + last_known_section_ == BinarySection::Invalid || + section == BinarySection::Custom || + GetSectionOrder(section) > GetSectionOrder(last_known_section_), + "section %s out of order", GetSectionName(section)); ERROR_UNLESS(!did_read_names_section_ || section == BinarySection::Custom, "%s section can not occur after Name section", @@ -2185,6 +2200,12 @@ Result BinaryReader::ReadSections() { section_result = ReadDataSection(section_size); result |= section_result; break; + case BinarySection::DataCount: + ERROR_UNLESS(options_.features.bulk_memory_enabled(), + "invalid section code: %u", section); + section_result = ReadDataCountSection(section_size); + result |= section_result; + break; case BinarySection::Invalid: WABT_UNREACHABLE; } diff --git a/src/binary-reader.h b/src/binary-reader.h index 9b100038..9fe0a17a 100644 --- a/src/binary-reader.h +++ b/src/binary-reader.h @@ -293,6 +293,11 @@ class BinaryReaderDelegate { virtual Result EndDataSegment(Index index) = 0; virtual Result EndDataSection() = 0; + /* DataCount section */ + virtual Result BeginDataCountSection(Offset size) = 0; + virtual Result OnDataCount(Index count) = 0; + virtual Result EndDataCountSection() = 0; + /* Names section */ virtual Result BeginNamesSection(Offset size) = 0; virtual Result OnModuleNameSubsection(Index index, diff --git a/src/binary-writer.cc b/src/binary-writer.cc index b8fa1702..b6c33ccc 100644 --- a/src/binary-writer.cc +++ b/src/binary-writer.cc @@ -993,6 +993,12 @@ Result BinaryWriter::WriteModule() { EndSection(); } + if (options_.features.bulk_memory_enabled()) { + BeginKnownSection(BinarySection::DataCount); + WriteU32Leb128(stream_, module_->data_segments.size(), "data count"); + EndSection(); + } + if (num_funcs) { BeginKnownSection(BinarySection::Code); WriteU32Leb128(stream_, num_funcs, "num functions"); diff --git a/src/binary-writer.h b/src/binary-writer.h index dc571f46..41e86ff1 100644 --- a/src/binary-writer.h +++ b/src/binary-writer.h @@ -18,6 +18,7 @@ #define WABT_BINARY_WRITER_H_ #include "src/common.h" +#include "src/feature.h" #include "src/opcode.h" #include "src/stream.h" @@ -27,6 +28,17 @@ struct Module; struct Script; struct WriteBinaryOptions { + WriteBinaryOptions() = default; + WriteBinaryOptions(const Features& features, + bool canonicalize_lebs, + bool relocatable, + bool write_debug_names) + : features(features), + canonicalize_lebs(canonicalize_lebs), + relocatable(relocatable), + write_debug_names(write_debug_names) {} + + Features features; bool canonicalize_lebs = true; bool relocatable = false; bool write_debug_names = false; diff --git a/src/binary.cc b/src/binary.cc index b0cd32a2..6e993ab6 100644 --- a/src/binary.cc +++ b/src/binary.cc @@ -18,10 +18,28 @@ namespace wabt { -const char* g_section_name[] = { -#define V(NAME, name, code) #NAME, +BinarySectionOrder GetSectionOrder(BinarySection sec) { + switch (sec) { +#define V(Name, name, code) \ + case BinarySection::Name: \ + return BinarySectionOrder::Name; WABT_FOREACH_BINARY_SECTION(V) #undef V -}; + default: + WABT_UNREACHABLE; + } +} + +const char* GetSectionName(BinarySection sec) { + switch (sec) { +#define V(Name, name, code) \ + case BinarySection::Name: \ + return #Name; + WABT_FOREACH_BINARY_SECTION(V) +#undef V + default: + WABT_UNREACHABLE; + } +} } // namespace wabt diff --git a/src/binary.h b/src/binary.h index eee09f66..747c28e2 100644 --- a/src/binary.h +++ b/src/binary.h @@ -41,6 +41,7 @@ V(Export, export, 7) \ V(Start, start, 8) \ V(Elem, elem, 9) \ + V(DataCount, data_count, 12) \ V(Code, code, 10) \ V(Data, data, 11) @@ -51,14 +52,23 @@ enum class BinarySection { #define V(Name, name, code) Name = code, WABT_FOREACH_BINARY_SECTION(V) #undef V - Invalid, + Invalid = ~0, First = Custom, - Last = Data, + Last = DataCount, }; /* clang-format on */ static const int kBinarySectionCount = WABT_ENUM_COUNT(BinarySection); +enum class BinarySectionOrder { +#define V(Name, name, code) Name, + WABT_FOREACH_BINARY_SECTION(V) +#undef V +}; + +BinarySectionOrder GetSectionOrder(BinarySection); +const char* GetSectionName(BinarySection); + enum class NameSectionSubsection { Module = 0, Function = 1, @@ -71,13 +81,6 @@ enum class SegmentFlags : uint8_t { IndexOther = 2, }; -extern const char* g_section_name[]; - -static WABT_INLINE const char* GetSectionName(BinarySection sec) { - assert(static_cast<int>(sec) < kBinarySectionCount); - return g_section_name[static_cast<size_t>(sec)]; -} - } // namespace wabt #endif /* WABT_BINARY_H_ */ diff --git a/src/tools/wast2json.cc b/src/tools/wast2json.cc index 5f5d211f..d48dcb1f 100644 --- a/src/tools/wast2json.cc +++ b/src/tools/wast2json.cc @@ -120,6 +120,7 @@ int ProgramMain(int argc, char** argv) { std::string module_filename_noext = StripExtension(s_outfile ? s_outfile : s_infile).to_string(); + s_write_binary_options.features = s_features; result = WriteBinarySpecScript( &json_stream, script.get(), s_infile, module_filename_noext, s_write_binary_options, &module_streams, s_log_stream.get()); diff --git a/src/tools/wat2wasm.cc b/src/tools/wat2wasm.cc index fe41d49f..c8e04d4d 100644 --- a/src/tools/wat2wasm.cc +++ b/src/tools/wat2wasm.cc @@ -148,6 +148,7 @@ int ProgramMain(int argc, char** argv) { if (Succeeded(result)) { MemoryStream stream(s_log_stream.get()); + s_write_binary_options.features = s_features; result = WriteBinaryModule(&stream, module.get(), s_write_binary_options); if (Succeeded(result)) { diff --git a/test/binary/bad-data-count-mismatch.txt b/test/binary/bad-data-count-mismatch.txt new file mode 100644 index 00000000..90f196d8 --- /dev/null +++ b/test/binary/bad-data-count-mismatch.txt @@ -0,0 +1,23 @@ +;;; TOOL: run-gen-wasm-bad +;;; ARGS1: --enable-bulk-memory +;;; ARGS2: --enable-bulk-memory +magic +version +section(MEMORY) { + count[1] + has_max[0] + initial[1] +} +section(DATACOUNT) { + count[2] +} +section(DATA) { + count[1] + memory_index[0] + offset[i32.const 0 end] + data[str("whoops")] +} +(;; STDERR ;;; +0000013: error: data segment count does not equal count in DataCount section +0000013: error: data segment count does not equal count in DataCount section +;;; STDERR ;;) diff --git a/test/binary/bad-data-count-order-after-code.txt b/test/binary/bad-data-count-order-after-code.txt new file mode 100644 index 00000000..6af64f24 --- /dev/null +++ b/test/binary/bad-data-count-order-after-code.txt @@ -0,0 +1,11 @@ +;;; TOOL: run-gen-wasm-bad +;;; ARGS1: --enable-bulk-memory +;;; ARGS2: --enable-bulk-memory +magic +version +section(CODE) { count[0] } +section(DATACOUNT) { count[0] } +(;; STDERR ;;; +000000d: error: section DataCount out of order +000000d: error: section DataCount out of order +;;; STDERR ;;) diff --git a/test/binary/bad-data-count-order-before-elem.txt b/test/binary/bad-data-count-order-before-elem.txt new file mode 100644 index 00000000..226b2c71 --- /dev/null +++ b/test/binary/bad-data-count-order-before-elem.txt @@ -0,0 +1,11 @@ +;;; TOOL: run-gen-wasm-bad +;;; ARGS1: --enable-bulk-memory +;;; ARGS2: --enable-bulk-memory +magic +version +section(DATACOUNT) { count[0] } +section(ELEM) { count[0] } +(;; STDERR ;;; +000000d: error: section Elem out of order +000000d: error: section Elem out of order +;;; STDERR ;;) diff --git a/test/dump/bulk-memory.txt b/test/dump/bulk-memory.txt index be06dba5..a3cdae98 100644 --- a/test/dump/bulk-memory.txt +++ b/test/dump/bulk-memory.txt @@ -25,30 +25,30 @@ bulk-memory.wasm: file format wasm 0x1 Code Disassembly: -000028 func[0]: - 000029: 41 00 | i32.const 0 - 00002b: 41 00 | i32.const 0 - 00002d: 41 00 | i32.const 0 - 00002f: fc 08 00 00 | memory.init 0 0 - 000033: fc 09 00 | memory.drop 0 - 000036: 41 00 | i32.const 0 - 000038: 41 00 | i32.const 0 - 00003a: 41 00 | i32.const 0 - 00003c: fc 0a 00 | memory.copy 0 - 00003f: 41 00 | i32.const 0 - 000041: 41 00 | i32.const 0 - 000043: 41 00 | i32.const 0 - 000045: fc 0b 00 | memory.fill 0 - 000048: 0b | end -00004a func[1]: - 00004b: 41 00 | i32.const 0 - 00004d: 41 00 | i32.const 0 - 00004f: 41 00 | i32.const 0 - 000051: fc 0c 00 00 | table.init 0 0 - 000055: fc 0d 00 | table.drop 0 - 000058: 41 00 | i32.const 0 - 00005a: 41 00 | i32.const 0 - 00005c: 41 00 | i32.const 0 - 00005e: fc 0e 00 | table.copy 0 - 000061: 0b | end +00002b func[0]: + 00002c: 41 00 | i32.const 0 + 00002e: 41 00 | i32.const 0 + 000030: 41 00 | i32.const 0 + 000032: fc 08 00 00 | memory.init 0 0 + 000036: fc 09 00 | memory.drop 0 + 000039: 41 00 | i32.const 0 + 00003b: 41 00 | i32.const 0 + 00003d: 41 00 | i32.const 0 + 00003f: fc 0a 00 | memory.copy 0 + 000042: 41 00 | i32.const 0 + 000044: 41 00 | i32.const 0 + 000046: 41 00 | i32.const 0 + 000048: fc 0b 00 | memory.fill 0 + 00004b: 0b | end +00004d func[1]: + 00004e: 41 00 | i32.const 0 + 000050: 41 00 | i32.const 0 + 000052: 41 00 | i32.const 0 + 000054: fc 0c 00 00 | table.init 0 0 + 000058: fc 0d 00 | table.drop 0 + 00005b: 41 00 | i32.const 0 + 00005d: 41 00 | i32.const 0 + 00005f: 41 00 | i32.const 0 + 000061: fc 0e 00 | table.copy 0 + 000064: 0b | end ;;; STDOUT ;;) diff --git a/test/dump/data-count-section.txt b/test/dump/data-count-section.txt new file mode 100644 index 00000000..0c995d58 --- /dev/null +++ b/test/dump/data-count-section.txt @@ -0,0 +1,36 @@ +;;; TOOL: run-objdump +;;; ARGS0: --enable-bulk-memory +;;; ARGS1: -hx +(module + (memory 1) + (data (i32.const 0) "hi") + (data (i32.const 2) "world") + (data (i32.const 7) "goodbye") +) +(;; STDOUT ;;; + +data-count-section.wasm: file format wasm 0x1 + +Sections: + + Memory start=0x0000000a end=0x0000000d (size=0x00000003) count: 1 +DataCount start=0x0000000f end=0x00000010 (size=0x00000001) count: 3 + Data start=0x00000012 end=0x00000030 (size=0x0000001e) count: 3 + +Section Details: + +Memory[1]: + - memory[0] pages: initial=1 +DataCount: + - data count: 3 +Data[3]: + - segment[0] size=2 - init i32=0 + - 0000000: 6869 hi + - segment[1] size=5 - init i32=2 + - 0000002: 776f 726c 64 world + - segment[2] size=7 - init i32=7 + - 0000007: 676f 6f64 6279 65 goodbye + +Code Disassembly: + +;;; STDOUT ;;) diff --git a/test/gen-wasm.py b/test/gen-wasm.py index 0e076c46..5e5467ea 100755 --- a/test/gen-wasm.py +++ b/test/gen-wasm.py @@ -62,6 +62,7 @@ NAMED_VALUES = { 'ELEM': 9, 'CODE': 10, 'DATA': 11, + 'DATACOUNT': 12, # name subsection codes 'NAME_MODULE': 0, diff --git a/test/spec/custom.txt b/test/spec/custom.txt index 2e962408..9d74b871 100644 --- a/test/spec/custom.txt +++ b/test/spec/custom.txt @@ -10,7 +10,7 @@ out/test/spec/custom.wast:77: assert_malformed passed: out/test/spec/custom.wast:85: assert_malformed passed: 000000a: error: invalid section size: extends past end out/test/spec/custom.wast:93: assert_malformed passed: - 0000031: error: invalid section code: 36; max is 11 + 0000031: error: invalid section code: 36 out/test/spec/custom.wast:102: assert_malformed passed: 000003e: error: function signature count != function body count out/test/spec/custom.wast:115: assert_malformed passed: |