summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSam Clegg <sbc@chromium.org>2022-03-11 17:52:44 +0000
committerGitHub <noreply@github.com>2022-03-11 09:52:44 -0800
commitd0e5fe79a0a330ff77e18e2d154d48a24ee4077e (patch)
tree015fef843cbbedeecda31dd271eb1ca3839029a2
parent92c59402eb4e52cf1e1021a407b23c449d7fbe39 (diff)
downloadwabt-d0e5fe79a0a330ff77e18e2d154d48a24ee4077e.tar.gz
wabt-d0e5fe79a0a330ff77e18e2d154d48a24ee4077e.tar.bz2
wabt-d0e5fe79a0a330ff77e18e2d154d48a24ee4077e.zip
wasm-objdump: support extended const expressions (#1859)
-rw-r--r--src/binary-reader-objdump.cc217
-rw-r--r--test/dump/extended-const.txt197
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 ;;)