Repository: bytecodealliance/wasm-tools
Pull request #1540 (2024-05-08 18:31:15)

Handle more custom sections in `wasm-tools dump`
Hook up a few more custom section parsers to get more useful information in dumps.


Patch:
diff --git a/src/bin/wasm-tools/dump.rs b/src/bin/wasm-tools/dump.rs
index 14a7c3c4..71ccb91b 100644
--- a/src/bin/wasm-tools/dump.rs
+++ b/src/bin/wasm-tools/dump.rs
@@ -446,23 +446,58 @@ impl<'a> Dump<'a> {
                     self.color_print(c.range().start)?;
                     write!(self.state, "name: {:?}", c.name())?;
                     self.print(c.data_offset())?;
-                    if c.name() == "name" {
-                        let iter = NameSectionReader::new(c.data(), c.data_offset());
-                        self.print_custom_name_section(iter, |me, item, pos| {
-                            me.print_core_name(item, pos)
-                        })?;
-                    } else if c.name() == "component-name" {
-                        let iter = ComponentNameSectionReader::new(c.data(), c.data_offset());
-                        self.print_custom_name_section(iter, |me, item, pos| {
-                            me.print_component_name(item, pos)
-                        })?;
-                    } else {
-                        self.print_byte_header()?;
-                        for _ in 0..NBYTES {
-                            write!(self.dst, "---")?;
+                    match c.name() {
+                        "name" => {
+                            let iter = NameSectionReader::new(c.data(), c.data_offset());
+                            self.print_subsections(iter, |me, item, pos| {
+                                me.print_core_name(item, pos)
+                            })?;
+                        }
+                        "component-name" => {
+                            let iter = ComponentNameSectionReader::new(c.data(), c.data_offset());
+                            self.print_subsections(iter, |me, item, pos| {
+                                me.print_component_name(item, pos)
+                            })?;
+                        }
+                        "producers" => {
+                            let iter = ProducersSectionReader::new(c.data(), c.data_offset())?;
+                            self.print_iter(iter, |me, _pos, item| {
+                                write!(me.state, "field: {}", item.name)?;
+                                me.print(item.values.range().start)?;
+
+                                me.print_iter(item.values, |me, pos, item| {
+                                    write!(me.state, "{item:?}")?;
+                                    me.print(pos)
+                                })
+                            })?;
+                        }
+                        "dylink.0" => {
+                            let iter = Dylink0SectionReader::new(c.data(), c.data_offset());
+                            self.print_subsections(iter, |me, item, pos| {
+                                write!(me.state, "{item:?}")?;
+                                me.print(pos)
+                            })?;
+                        }
+                        "metadata.code.branch_hint" => {
+                            let iter = BranchHintSectionReader::new(c.data(), c.data_offset())?;
+                            self.print_iter(iter, |me, _pos, item| {
+                                write!(me.state, "func: {}", item.func)?;
+                                me.print(item.hints.range().start)?;
+
+                                me.print_iter(item.hints, |me, pos, item| {
+                                    write!(me.state, "{item:?}")?;
+                                    me.print(pos)
+                                })
+                            })?;
+                        }
+                        _ => {
+                            self.print_byte_header()?;
+                            for _ in 0..NBYTES {
+                                write!(self.dst, "---")?;
+                            }
+                            writeln!(self.dst, "-| ... {} bytes of data", c.data().len())?;
+                            self.cur += c.data().len();
                         }
-                        writeln!(self.dst, "-| ... {} bytes of data", c.data().len())?;
-                        self.cur += c.data().len();
                     }
                 }
                 Payload::UnknownSection {
@@ -510,7 +545,7 @@ impl<'a> Dump<'a> {
         })
     }
 
-    fn print_custom_name_section<'b, T>(
+    fn print_subsections<'b, T>(
         &mut self,
         mut section: Subsections<'b, T>,
         print_item: impl Fn(&mut Self, T, usize) -> Result<()>,


Test patch:
diff --git a/tests/cli/dump-branch-hints.wat b/tests/cli/dump-branch-hints.wat
new file mode 100644
index 00000000..feb72a12
--- /dev/null
+++ b/tests/cli/dump-branch-hints.wat
@@ -0,0 +1,14 @@
+;; RUN: dump %
+
+(module
+  (func
+    i32.const 0
+    (@metadata.code.branch_hint "\00")
+    if
+    end
+
+    (@metadata.code.branch_hint "\01")
+    if
+    end
+  )
+)
diff --git a/tests/cli/dump-branch-hints.wat.stdout b/tests/cli/dump-branch-hints.wat.stdout
new file mode 100644
index 00000000..7fe75765
--- /dev/null
+++ b/tests/cli/dump-branch-hints.wat.stdout
@@ -0,0 +1,33 @@
+  0x0 | 00 61 73 6d | version 1 (Module)
+      | 01 00 00 00
+  0x8 | 01 04       | type section
+  0xa | 01          | 1 count
+--- rec group 0 (implicit) ---
+  0xb | 60 00 00    | [type 0] SubType { is_final: true, supertype_idx: None, composite_type: Func(FuncType { params: [], results: [] }) }
+  0xe | 03 02       | func section
+ 0x10 | 01          | 1 count
+ 0x11 | 00          | [func 0] type 0
+ 0x12 | 00 23       | custom section
+ 0x14 | 19 6d 65 74 | name: "metadata.code.branch_hint"
+      | 61 64 61 74
+      | 61 2e 63 6f
+      | 64 65 2e 62
+      | 72 61 6e 63
+      | 68 5f 68 69
+      | 6e 74      
+ 0x2e | 01          | 1 count
+ 0x2f | 00          | func: 0
+ 0x30 | 02          | 2 count
+ 0x31 | 03 01 00    | BranchHint { func_offset: 3, taken: false }
+ 0x34 | 06 01 01    | BranchHint { func_offset: 6, taken: true }
+ 0x37 | 0a 0c       | code section
+ 0x39 | 01          | 1 count
+============== func 0 ====================
+ 0x3a | 0a          | size of function
+ 0x3b | 00          | 0 local blocks
+ 0x3c | 41 00       | i32_const value:0
+ 0x3e | 04 40       | if blockty:Empty
+ 0x40 | 0b          | end
+ 0x41 | 04 40       | if blockty:Empty
+ 0x43 | 0b          | end
+ 0x44 | 0b          | end
diff --git a/tests/cli/dump-dylink0.wat b/tests/cli/dump-dylink0.wat
new file mode 100644
index 00000000..04c9c780
--- /dev/null
+++ b/tests/cli/dump-dylink0.wat
@@ -0,0 +1,11 @@
+;; RUN: dump %
+
+(module
+  (@dylink.0
+    (needed "a" "b")
+    (mem-info (memory 1 1) (table 1 1))
+    (export-info "a" 0)
+    (import-info "a" "a" 0)
+    (export-info "a" 2 binding-local binding-weak 0 undefined)
+  )
+)
diff --git a/tests/cli/dump-dylink0.wat.stdout b/tests/cli/dump-dylink0.wat.stdout
new file mode 100644
index 00000000..ae6e2c7e
--- /dev/null
+++ b/tests/cli/dump-dylink0.wat.stdout
@@ -0,0 +1,16 @@
+  0x0 | 00 61 73 6d | version 1 (Module)
+      | 01 00 00 00
+  0x8 | 00 2a       | custom section
+  0xa | 08 64 79 6c | name: "dylink.0"
+      | 69 6e 6b 2e
+      | 30         
+ 0x13 | 02 05 02 01 | Needed(["a", "b"])
+      | 61 01 62   
+ 0x1a | 01 04 01 01 | MemInfo(MemInfo { memory_size: 1, memory_alignment: 1, table_size: 1, table_alignment: 1 })
+      | 01 01      
+ 0x20 | 03 04 01 01 | ExportInfo([ExportInfo { name: "a", flags: SymbolFlags(0x0) }])
+      | 61 00      
+ 0x26 | 04 06 01 01 | ImportInfo([ImportInfo { module: "a", field: "a", flags: SymbolFlags(0x0) }])
+      | 61 01 61 00
+ 0x2e | 03 04 01 01 | ExportInfo([ExportInfo { name: "a", flags: SymbolFlags(BINDING_WEAK | BINDING_LOCAL | UNDEFINED) }])
+      | 61 13      
diff --git a/tests/cli/dump-producers-section.wat b/tests/cli/dump-producers-section.wat
new file mode 100644
index 00000000..ac0e04b9
--- /dev/null
+++ b/tests/cli/dump-producers-section.wat
@@ -0,0 +1,10 @@
+;; RUN: dump %
+
+(module
+  (@producers
+    (language "foo" "bar")
+    (language "foo" "bar")
+    (sdk "foo" "bar")
+    (processed-by "foo" "bar")
+  )
+)
diff --git a/tests/cli/dump-producers-section.wat.stdout b/tests/cli/dump-producers-section.wat.stdout
new file mode 100644
index 00000000..f26b4770
--- /dev/null
+++ b/tests/cli/dump-producers-section.wat.stdout
@@ -0,0 +1,26 @@
+  0x0 | 00 61 73 6d | version 1 (Module)
+      | 01 00 00 00
+  0x8 | 00 48       | custom section
+  0xa | 09 70 72 6f | name: "producers"
+      | 64 75 63 65
+      | 72 73      
+ 0x14 | 03          | 3 count
+ 0x15 | 08 6c 61 6e | field: language
+      | 67 75 61 67
+      | 65         
+ 0x1e | 02          | 2 count
+ 0x1f | 03 66 6f 6f | ProducersFieldValue { name: "foo", version: "bar" }
+      | 03 62 61 72
+ 0x27 | 03 66 6f 6f | ProducersFieldValue { name: "foo", version: "bar" }
+      | 03 62 61 72
+ 0x2f | 03 73 64 6b | field: sdk
+ 0x33 | 01          | 1 count
+ 0x34 | 03 66 6f 6f | ProducersFieldValue { name: "foo", version: "bar" }
+      | 03 62 61 72
+ 0x3c | 0c 70 72 6f | field: processed-by
+      | 63 65 73 73
+      | 65 64 2d 62
+      | 79         
+ 0x49 | 01          | 1 count
+ 0x4a | 03 66 6f 6f | ProducersFieldValue { name: "foo", version: "bar" }
+      | 03 62 61 72