diff options
author | Sam Clegg <sbc@chromium.org> | 2022-03-11 17:52:44 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-03-11 09:52:44 -0800 |
commit | d0e5fe79a0a330ff77e18e2d154d48a24ee4077e (patch) | |
tree | 015fef843cbbedeecda31dd271eb1ca3839029a2 | |
parent | 92c59402eb4e52cf1e1021a407b23c449d7fbe39 (diff) | |
download | wabt-d0e5fe79a0a330ff77e18e2d154d48a24ee4077e.tar.gz wabt-d0e5fe79a0a330ff77e18e2d154d48a24ee4077e.tar.bz2 wabt-d0e5fe79a0a330ff77e18e2d154d48a24ee4077e.zip |
wasm-objdump: support extended const expressions (#1859)
-rw-r--r-- | src/binary-reader-objdump.cc | 217 | ||||
-rw-r--r-- | test/dump/extended-const.txt | 197 |
2 files changed, 330 insertions, 84 deletions
diff --git a/src/binary-reader-objdump.cc b/src/binary-reader-objdump.cc index 0a8b7dc8..adae0761 100644 --- a/src/binary-reader-objdump.cc +++ b/src/binary-reader-objdump.cc @@ -50,6 +50,7 @@ class BinaryReaderObjdumpBase : public BinaryReaderNop { BinarySection section_type, Offset size) override; + Result OnOpcode(Opcode Opcode) override; Result OnRelocCount(Index count, Index section_index) override; protected: @@ -78,6 +79,7 @@ class BinaryReaderObjdumpBase : public BinaryReaderNop { std::vector<BinarySection> section_types_; bool section_found_ = false; std::string module_name_; + Opcode current_opcode = Opcode::Unreachable; std::unique_ptr<FileStream> err_stream_; }; @@ -211,6 +213,11 @@ Offset BinaryReaderObjdumpBase::GetPrintOffset(Offset offset) const { : offset; } +Result BinaryReaderObjdumpBase::OnOpcode(Opcode opcode) { + current_opcode = opcode; + return Result::Ok; +} + Result BinaryReaderObjdumpBase::OnRelocCount(Index count, Index section_index) { if (section_index >= section_types_.size()) { err_stream_->Writef("invalid relocation section index: %" PRIindex "\n", @@ -529,7 +536,6 @@ class BinaryReaderObjdumpDisassemble : public BinaryReaderObjdumpBase { private: void LogOpcode(const char* fmt, ...); - Opcode current_opcode = Opcode::Unreachable; Offset current_opcode_offset = 0; Offset last_opcode_end = 0; int indent_level = 0; @@ -550,6 +556,7 @@ std::string BinaryReaderObjdumpDisassemble::BlockSigToString(Type type) const { } Result BinaryReaderObjdumpDisassemble::OnOpcode(Opcode opcode) { + BinaryReaderObjdumpBase::OnOpcode(opcode); if (!in_function_body) { return Result::Ok; } @@ -573,7 +580,6 @@ Result BinaryReaderObjdumpDisassemble::OnOpcode(Opcode opcode) { } current_opcode_offset = state->offset; - current_opcode = opcode; return Result::Ok; } @@ -921,8 +927,8 @@ enum class InitExprType { NullRef, }; -struct InitExpr { - InitExprType type; +struct InitInst { + Opcode opcode; union { Index index; uint32_t i32; @@ -931,7 +937,12 @@ struct InitExpr { uint64_t f64; v128 v128_v; Type type; - } value; + } imm; +}; + +struct InitExpr { + InitExprType type; + std::vector<InitInst> insts; }; class BinaryReaderObjdump : public BinaryReaderObjdumpBase { @@ -1023,35 +1034,31 @@ class BinaryReaderObjdump : public BinaryReaderObjdumpBase { Result OnElemSegmentElemExpr_RefFunc(Index segment_index, Index func_index) override; + void BeginInitExpr() { current_init_expr_.insts.clear(); } + Result BeginElemSegmentInitExpr(Index index) override { reading_elem_init_expr_ = true; + BeginInitExpr(); return Result::Ok; } - Result EndElemSegmentInitExpr(Index index) override { - reading_elem_init_expr_ = false; - return Result::Ok; - } + Result EndElemSegmentInitExpr(Index index) override { return EndInitExpr(); } Result BeginDataSegmentInitExpr(Index index) override { reading_data_init_expr_ = true; + BeginInitExpr(); return Result::Ok; } - Result EndDataSegmentInitExpr(Index index) override { - reading_data_init_expr_ = false; - return Result::Ok; - } + Result EndDataSegmentInitExpr(Index index) override { return EndInitExpr(); } Result BeginGlobalInitExpr(Index index) override { reading_global_init_expr_ = true; + BeginInitExpr(); return Result::Ok; } - Result EndGlobalInitExpr(Index index) override { - reading_global_init_expr_ = false; - return Result::Ok; - } + Result EndGlobalInitExpr(Index index) override { return EndInitExpr(); } Result OnDataSegmentCount(Index count) override; Result BeginDataSegment(Index index, @@ -1134,6 +1141,7 @@ class BinaryReaderObjdump : public BinaryReaderObjdumpBase { Result OnTagCount(Index count) override; Result OnTagType(Index index, Index sig_index) override; + Result OnOpcode(Opcode Opcode) override; Result OnI32ConstExpr(uint32_t value) override; Result OnI64ConstExpr(uint64_t value) override; Result OnF32ConstExpr(uint32_t value) override; @@ -1145,8 +1153,7 @@ class BinaryReaderObjdump : public BinaryReaderObjdumpBase { Address size) override; private: - Result InitExprToConstOffset(const InitExpr& expr, uint64_t* out_offset); - Result HandleInitExpr(const InitExpr& expr); + Result EndInitExpr(); bool ShouldPrintDetails(); void PrintDetails(const char* fmt, ...); Result PrintSymbolFlags(uint32_t flags); @@ -1161,8 +1168,7 @@ class BinaryReaderObjdump : public BinaryReaderObjdumpBase { bool reading_elem_init_expr_ = false; bool reading_data_init_expr_ = false; bool reading_global_init_expr_ = false; - InitExpr data_init_expr_; - InitExpr elem_init_expr_; + InitExpr current_init_expr_; uint8_t data_flags_ = 0; uint8_t elem_flags_ = 0; Index data_mem_index_ = 0; @@ -1621,7 +1627,7 @@ Result BinaryReaderObjdump::OnElemSegmentElemExprCount(Index index, if (elem_flags_ & SegPassive) { PrintDetails("\n"); } else { - PrintInitExpr(elem_init_expr_); + PrintInitExpr(current_init_expr_); } return Result::Ok; } @@ -1641,34 +1647,85 @@ Result BinaryReaderObjdump::BeginGlobal(Index index, Type type, bool mutable_) { } void BinaryReaderObjdump::PrintInitExpr(const InitExpr& expr) { + assert(expr.insts.size() > 0); + + // We have two different way to print init expressions. One for + // extended expressions involving more than one instruction, and + // a short form for the more traditional single instruction form. + if (expr.insts.size() > 1) { + PrintDetails(" - init ("); + bool first = true; + for (auto& inst : expr.insts) { + if (!first) { + PrintDetails(", "); + } + first = false; + PrintDetails("%s", inst.opcode.GetName()); + switch (inst.opcode) { + case Opcode::I32Const: + PrintDetails(" %d", inst.imm.i32); + break; + case Opcode::I64Const: + PrintDetails(" %" PRId64, inst.imm.i64); + break; + case Opcode::F32Const: { + char buffer[WABT_MAX_FLOAT_HEX]; + WriteFloatHex(buffer, sizeof(buffer), inst.imm.f32); + PrintDetails(" %s\n", buffer); + break; + } + case Opcode::F64Const: { + char buffer[WABT_MAX_DOUBLE_HEX]; + WriteDoubleHex(buffer, sizeof(buffer), inst.imm.f64); + PrintDetails(" %s\n", buffer); + break; + } + case Opcode::GlobalGet: { + PrintDetails(" %" PRIindex, inst.imm.index); + std::string_view name = GetGlobalName(inst.imm.index); + if (!name.empty()) { + PrintDetails(" <" PRIstringview ">", + WABT_PRINTF_STRING_VIEW_ARG(name)); + } + break; + } + default: + break; + } + } + PrintDetails(")\n"); + return; + } + switch (expr.type) { case InitExprType::I32: - PrintDetails(" - init i32=%d\n", expr.value.i32); + PrintDetails(" - init i32=%d\n", expr.insts[0].imm.i32); break; case InitExprType::I64: - PrintDetails(" - init i64=%" PRId64 "\n", expr.value.i64); + PrintDetails(" - init i64=%" PRId64 "\n", expr.insts[0].imm.i64); break; case InitExprType::F64: { char buffer[WABT_MAX_DOUBLE_HEX]; - WriteDoubleHex(buffer, sizeof(buffer), expr.value.f64); + WriteDoubleHex(buffer, sizeof(buffer), expr.insts[0].imm.f64); PrintDetails(" - init f64=%s\n", buffer); break; } case InitExprType::F32: { char buffer[WABT_MAX_FLOAT_HEX]; - WriteFloatHex(buffer, sizeof(buffer), expr.value.f32); + WriteFloatHex(buffer, sizeof(buffer), expr.insts[0].imm.f32); PrintDetails(" - init f32=%s\n", buffer); break; } case InitExprType::V128: { - PrintDetails(" - init v128=0x%08x 0x%08x 0x%08x 0x%08x \n", - expr.value.v128_v.u32(0), expr.value.v128_v.u32(1), - expr.value.v128_v.u32(2), expr.value.v128_v.u32(3)); + PrintDetails( + " - init v128=0x%08x 0x%08x 0x%08x 0x%08x \n", + expr.insts[0].imm.v128_v.u32(0), expr.insts[0].imm.v128_v.u32(1), + expr.insts[0].imm.v128_v.u32(2), expr.insts[0].imm.v128_v.u32(3)); break; } case InitExprType::Global: { - PrintDetails(" - init global=%" PRIindex, expr.value.index); - std::string_view name = GetGlobalName(expr.value.index); + PrintDetails(" - init global=%" PRIindex, expr.insts[0].imm.index); + std::string_view name = GetGlobalName(expr.insts[0].imm.index); if (!name.empty()) { PrintDetails(" <" PRIstringview ">", WABT_PRINTF_STRING_VIEW_ARG(name)); } @@ -1676,106 +1733,98 @@ void BinaryReaderObjdump::PrintInitExpr(const InitExpr& expr) { break; } case InitExprType::FuncRef: { - PrintDetails(" - init ref.func:%" PRIindex, expr.value.index); - std::string_view name = GetFunctionName(expr.value.index); + PrintDetails(" - init ref.func:%" PRIindex, expr.insts[0].imm.index); + std::string_view name = GetFunctionName(expr.insts[0].imm.index); if (!name.empty()) { PrintDetails(" <" PRIstringview ">", WABT_PRINTF_STRING_VIEW_ARG(name)); } PrintDetails("\n"); break; } - case InitExprType::NullRef: { + case InitExprType::NullRef: PrintDetails(" - init null\n"); break; - } + break; } } -Result BinaryReaderObjdump::InitExprToConstOffset(const InitExpr& expr, - uint64_t* out_offset) { - switch (expr.type) { - case InitExprType::I32: - *out_offset = expr.value.i32; - break; - case InitExprType::I64: - *out_offset = expr.value.i64; - break; - case InitExprType::Global: - *out_offset = 0; - break; - case InitExprType::F32: - case InitExprType::F64: - case InitExprType::V128: - case InitExprType::FuncRef: - case InitExprType::NullRef: - err_stream_->Writef("Invalid init expr for segment/elem offset"); - return Result::Error; - break; +static void InitExprToConstOffset(const InitExpr& expr, uint64_t* out_offset) { + if (expr.insts.size() == 1) { + switch (expr.type) { + case InitExprType::I32: + *out_offset = expr.insts[0].imm.i32; + break; + case InitExprType::I64: + *out_offset = expr.insts[0].imm.i64; + break; + default: + break; + } } - return Result::Ok; } -Result BinaryReaderObjdump::HandleInitExpr(const InitExpr& expr) { +Result BinaryReaderObjdump::EndInitExpr() { if (reading_data_init_expr_) { - data_init_expr_ = expr; - return InitExprToConstOffset(expr, &data_offset_); + reading_data_init_expr_ = false; + InitExprToConstOffset(current_init_expr_, &data_offset_); } else if (reading_elem_init_expr_) { - elem_init_expr_ = expr; - return InitExprToConstOffset(expr, &elem_offset_); + reading_elem_init_expr_ = false; + InitExprToConstOffset(current_init_expr_, &elem_offset_); } else if (reading_global_init_expr_) { - PrintInitExpr(expr); - return Result::Ok; + reading_global_init_expr_ = false; + PrintInitExpr(current_init_expr_); } else { WABT_UNREACHABLE; } + return Result::Ok; } Result BinaryReaderObjdump::OnI32ConstExpr(uint32_t value) { if (ReadingInitExpr()) { - InitExpr expr; - expr.type = InitExprType::I32; - expr.value.i32 = value; - return HandleInitExpr(expr); + current_init_expr_.type = InitExprType::I32; + current_init_expr_.insts.back().imm.i32 = value; } return Result::Ok; } Result BinaryReaderObjdump::OnI64ConstExpr(uint64_t value) { if (ReadingInitExpr()) { - InitExpr expr; - expr.type = InitExprType::I64; - expr.value.i64 = value; - return HandleInitExpr(expr); + current_init_expr_.type = InitExprType::I64; + current_init_expr_.insts.back().imm.i64 = value; } return Result::Ok; } Result BinaryReaderObjdump::OnF32ConstExpr(uint32_t value) { if (ReadingInitExpr()) { - InitExpr expr; - expr.type = InitExprType::F32; - expr.value.f32 = value; - return HandleInitExpr(expr); + current_init_expr_.type = InitExprType::F32; + current_init_expr_.insts.back().imm.f32 = value; } return Result::Ok; } Result BinaryReaderObjdump::OnF64ConstExpr(uint64_t value) { if (ReadingInitExpr()) { - InitExpr expr; - expr.type = InitExprType::F64; - expr.value.f64 = value; - return HandleInitExpr(expr); + current_init_expr_.type = InitExprType::F64; + current_init_expr_.insts.back().imm.f64 = value; + } + return Result::Ok; +} + +Result BinaryReaderObjdump::OnOpcode(Opcode opcode) { + BinaryReaderObjdumpBase::OnOpcode(opcode); + if (ReadingInitExpr() && opcode != Opcode::End) { + InitInst i; + i.opcode = current_opcode; + current_init_expr_.insts.push_back(i); } return Result::Ok; } Result BinaryReaderObjdump::OnGlobalGetExpr(Index global_index) { if (ReadingInitExpr()) { - InitExpr expr; - expr.type = InitExprType::Global; - expr.value.index = global_index; - return HandleInitExpr(expr); + current_init_expr_.type = InitExprType::Global; + current_init_expr_.insts.back().imm.index = global_index; } return Result::Ok; } @@ -1845,7 +1894,7 @@ Result BinaryReaderObjdump::OnDataSegmentData(Index index, if (data_flags_ & SegPassive) { PrintDetails("\n"); } else { - PrintInitExpr(data_init_expr_); + PrintInitExpr(current_init_expr_); } out_stream_->WriteMemoryDump(src_data, size, data_offset_, PrintChars::Yes, diff --git a/test/dump/extended-const.txt b/test/dump/extended-const.txt new file mode 100644 index 00000000..cafd2dd5 --- /dev/null +++ b/test/dump/extended-const.txt @@ -0,0 +1,197 @@ +;;; TOOL: run-objdump +;;; ARGS0: -v --debug-names --enable-extended-const +;;; ARGS1: -x +(type $type1 (func (param i32))) +(global $g_import (import "foo" "bar") i32) +(table 1 funcref) +(memory 1 1) +(data (i32.add (global.get $g_import) (i32.const 42)) "hello") +(elem (i32.mul (i32.const 4) (global.get $g_import)) func 0) +(global (mut i32) (i32.sub (i32.const 44) (i32.const 3))) +(global i32 (i32.const 45)) +(func) +(;; STDERR ;;; +0000000: 0061 736d ; WASM_BINARY_MAGIC +0000004: 0100 0000 ; WASM_BINARY_VERSION +; section "Type" (1) +0000008: 01 ; section code +0000009: 00 ; section size (guess) +000000a: 02 ; num types +; func type 0 +000000b: 60 ; func +000000c: 01 ; num params +000000d: 7f ; i32 +000000e: 00 ; num results +; func type 1 +000000f: 60 ; func +0000010: 00 ; num params +0000011: 00 ; num results +0000009: 08 ; FIXUP section size +; section "Import" (2) +0000012: 02 ; section code +0000013: 00 ; section size (guess) +0000014: 01 ; num imports +; import header 0 +0000015: 03 ; string length +0000016: 666f 6f foo ; import module name +0000019: 03 ; string length +000001a: 6261 72 bar ; import field name +000001d: 03 ; import kind +000001e: 7f ; i32 +000001f: 00 ; global mutability +0000013: 0c ; FIXUP section size +; section "Function" (3) +0000020: 03 ; section code +0000021: 00 ; section size (guess) +0000022: 01 ; num functions +0000023: 01 ; function 0 signature index +0000021: 02 ; FIXUP section size +; section "Table" (4) +0000024: 04 ; section code +0000025: 00 ; section size (guess) +0000026: 01 ; num tables +; table 0 +0000027: 70 ; funcref +0000028: 00 ; limits: flags +0000029: 01 ; limits: initial +0000025: 04 ; FIXUP section size +; section "Memory" (5) +000002a: 05 ; section code +000002b: 00 ; section size (guess) +000002c: 01 ; num memories +; memory 0 +000002d: 01 ; limits: flags +000002e: 01 ; limits: initial +000002f: 01 ; limits: max +000002b: 04 ; FIXUP section size +; section "Global" (6) +0000030: 06 ; section code +0000031: 00 ; section size (guess) +0000032: 02 ; num globals +0000033: 7f ; i32 +0000034: 01 ; global mutability +0000035: 41 ; i32.const +0000036: 2c ; i32 literal +0000037: 41 ; i32.const +0000038: 03 ; i32 literal +0000039: 6b ; i32.sub +000003a: 0b ; end +000003b: 7f ; i32 +000003c: 00 ; global mutability +000003d: 41 ; i32.const +000003e: 2d ; i32 literal +000003f: 0b ; end +0000031: 0e ; FIXUP section size +; section "Elem" (9) +0000040: 09 ; section code +0000041: 00 ; section size (guess) +0000042: 01 ; num elem segments +; elem segment header 0 +0000043: 00 ; segment flags +0000044: 41 ; i32.const +0000045: 04 ; i32 literal +0000046: 23 ; global.get +0000047: 00 ; global index +0000048: 6c ; i32.mul +0000049: 0b ; end +000004a: 01 ; num elems +000004b: 00 ; elem function index +0000041: 0a ; FIXUP section size +; section "DataCount" (12) +000004c: 0c ; section code +000004d: 00 ; section size (guess) +000004e: 01 ; data count +000004d: 01 ; FIXUP section size +; section "Code" (10) +000004f: 0a ; section code +0000050: 00 ; section size (guess) +0000051: 01 ; num functions +; function body 0 +0000052: 00 ; func body size (guess) +0000053: 00 ; local decl count +0000054: 0b ; end +0000052: 02 ; FIXUP func body size +0000050: 04 ; FIXUP section size +; move data: [4f, 55) -> [4c, 52) +; truncate to 82 (0x52) +; section "Data" (11) +0000052: 0b ; section code +0000053: 00 ; section size (guess) +0000054: 01 ; num data segments +; data segment header 0 +0000055: 00 ; segment flags +0000056: 23 ; global.get +0000057: 00 ; global index +0000058: 41 ; i32.const +0000059: 2a ; i32 literal +000005a: 6a ; i32.add +000005b: 0b ; end +000005c: 05 ; data segment size +; data segment data 0 +000005d: 6865 6c6c 6f ; data segment data +0000053: 0e ; FIXUP section size +; section "name" +0000062: 00 ; section code +0000063: 00 ; section size (guess) +0000064: 04 ; string length +0000065: 6e61 6d65 name ; custom section name +0000069: 02 ; local name type +000006a: 00 ; subsection size (guess) +000006b: 01 ; num functions +000006c: 00 ; function index +000006d: 00 ; num locals +000006a: 03 ; FIXUP subsection size +000006e: 04 ; name subsection type +000006f: 00 ; subsection size (guess) +0000070: 01 ; num names +0000071: 00 ; elem index +0000072: 05 ; string length +0000073: 7479 7065 31 type1 ; elem name 0 +000006f: 08 ; FIXUP subsection size +0000078: 07 ; name subsection type +0000079: 00 ; subsection size (guess) +000007a: 01 ; num names +000007b: 00 ; elem index +000007c: 08 ; string length +000007d: 675f 696d 706f 7274 g_import ; elem name 0 +0000079: 0b ; FIXUP subsection size +0000063: 21 ; FIXUP section size +;;; STDERR ;;) +(;; STDOUT ;;; + +extended-const.wasm: file format wasm 0x1 + +Section Details: + +Type[2]: + - type[0] (i32) -> nil + - type[1] () -> nil +Import[1]: + - global[0] i32 mutable=0 <- foo.bar +Function[1]: + - func[0] sig=1 +Table[1]: + - table[0] type=funcref initial=1 +Memory[1]: + - memory[0] pages: initial=1 max=1 +Global[2]: + - global[1] i32 mutable=1 - init (i32.const 44, i32.const 3, i32.sub) + - global[2] i32 mutable=0 - init i32=45 +Elem[1]: + - segment[0] flags=0 table=0 count=1 - init (i32.const 4, global.get 0 <g_import>, i32.mul) + - elem[0] = func[0] +Code[1]: + - func[0] size=2 +Data[1]: + - segment[0] memory=0 size=5 - init (global.get 0 <g_import>, i32.const 42, i32.add) + - 0000000: 6865 6c6c 6f hello +Custom: + - name: "name" + - type[0] <type1> + - global[0] <g_import> + +Code Disassembly: + +000050 func[0]: + 000051: 0b | end +;;; STDOUT ;;) |