Repository: bytecodealliance/wasm-tools
Pull request #2075 (2025-02-26 14:41:56)

[wasm-metadata] print relationships
Sibling to #2074, this adds child relationships to the printed output of `wasm-metadata`. This should make it easier to understand what the relationship is between the various payloads in the binary.

On a quick aside here: together with https://github.com/bytecodealliance/wasm-tools/issues/2058 and https://github.com/bytecodealliance/wasm-tools/issues/1924 we're on track to significantly increase the amount of data printed by `wasm-metadata`. I don't think this is a bad thing per se - all of this info is useful. But we may want to rethink exactly how we're printing that data in the longer term. Perhaps by providing summary tables, or separate commands to drill down into specifics, and so on. Nothing to do here now, but I wanted to acknowledge that this will eventually become a concern.

Thanks!

## Example

```text
╭──────────────┬───────────────────────────────────────────────────────╮
│ KIND         ┆ VALUE                                                 │
╞══════════════╪═══════════════════════════════════════════════════════╡
│ kind         ┆ component                                             │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
│ range        ┆ 0x0..0x2c9f9b                                         │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
│ name         ┆ <unknown>                                             │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
│ processed-by ┆ wit-component [0.216.0]                               │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
│ child        ┆ rust_wasi_hello.wasm [module]                         │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
│ child        ┆ wit-component:adapter:wasi_snapshot_preview1 [module] │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
│ child        ┆ wit-component:shim [module]                           │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
│ child        ┆ wit-component:fixups [module]                         │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
│ child        ┆ <unknown> [component]                                 │
╰──────────────┴───────────────────────────────────────────────────────╯
╭──────────────┬───────────────────────────────────────────────────────────────╮
│ KIND         ┆ VALUE                                                         │
╞══════════════╪═══════════════════════════════════════════════════════════════╡
│ kind         ┆ module                                                        │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
│ range        ┆ 0x117c..0x2c5813                                              │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
│ name         ┆ rust_wasi_hello.wasm                                          │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
│ language     ┆ Rust                                                          │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
│ language     ┆ C11                                                           │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
│ processed-by ┆ rustc [1.82.0 (f6e511eec 2024-10-15)]                         │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
│ processed-by ┆ clang [18.1.2-wasi-sdk (https://github.com/llvm/llvm-project  │
│              ┆ 26a1d6601d727a96f4301d0d8647b5a42760ae0c)]                    │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
│ processed-by ┆ wit-component [0.20.1]                                        │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
│ processed-by ┆ wit-bindgen-rust [0.33.0]                                     │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
│ processed-by ┆ wit-bindgen-c [0.17.0]                                        │
╰──────────────┴───────────────────────────────────────────────────────────────╯
```

pchickey: As far as the increased complexity of this information, one approach with precedent is to optionally emit json so that users can use tools like `jq` or whatever other heavier-weight approach they need. This PR isn't the place to do that, but its at least one path to consider.
yoshuawuyts: > Sorry to bikeshed but is it possible to move the name to the top row in these tables?

Yep, for sure! Also: no need to apologize; I've been redecorating the communal bike shed in these PRs. This is a good time to chime in on what color to paint it. 

> As far as the increased complexity of this information, one approach with precedent is to optionally emit json so that users can use tools like jq or whatever other heavier-weight approach they need.

There is already a json option for that from the command line. That probably does buy us some space to experiment with the human-readable interface. Let's see what is possible here.

Patch:
diff --git a/src/bin/wasm-tools/metadata.rs b/src/bin/wasm-tools/metadata.rs
index 364b902d..7d3546d2 100644
--- a/src/bin/wasm-tools/metadata.rs
+++ b/src/bin/wasm-tools/metadata.rs
@@ -113,6 +113,8 @@ fn write_table(payload: &Payload, f: &mut Box<dyn WriteColor>) -> Result<()> {
     } = payload.metadata();
 
     // Add the basic information to the table first
+    let name = name.as_deref().unwrap_or("<unknown>");
+    table.add_row(vec!["name", &name]);
     let kind = match payload {
         Payload::Component { .. } => "component",
         Payload::Module(_) => "module",
@@ -122,8 +124,6 @@ fn write_table(payload: &Payload, f: &mut Box<dyn WriteColor>) -> Result<()> {
         "range",
         &format!("0x{:x}..0x{:x}", range.start, range.end),
     ]);
-    let name = name.as_deref().unwrap_or("<unknown>");
-    table.add_row(vec!["name", &name]);
 
     // Add the OCI annotations to the table
     if let Some(description) = description {
@@ -176,6 +176,18 @@ fn write_table(payload: &Payload, f: &mut Box<dyn WriteColor>) -> Result<()> {
         }
     }
 
+    // Add child relationships to the table
+    if let Payload::Component { children, .. } = &payload {
+        for payload in children {
+            let name = payload.metadata().name.as_deref().unwrap_or("<unknown>");
+            let kind = match payload {
+                Payload::Component { .. } => "component",
+                Payload::Module(_) => "module",
+            };
+            table.add_row(vec!["child", &format!("{name} [{kind}]")]);
+        }
+    }
+
     // Write the table to the writer
     writeln!(f, "{table}")?;
 


Test patch:
diff --git a/tests/cli/add-metadata-merge-sections.wat.stdout b/tests/cli/add-metadata-merge-sections.wat.stdout
index c6491c6f..b3564981 100644
--- a/tests/cli/add-metadata-merge-sections.wat.stdout
+++ b/tests/cli/add-metadata-merge-sections.wat.stdout
@@ -1,12 +1,12 @@
 ╭──────────┬───────────╮
 │ KIND     ┆ VALUE     │
 ╞══════════╪═══════════╡
+│ name     ┆ <unknown> │
+├╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤
 │ kind     ┆ module    │
 ├╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤
 │ range    ┆ 0x0..0x36 │
 ├╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤
-│ name     ┆ <unknown> │
-├╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤
 │ language ┆ foo [3]   │
 ├╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤
 │ language ┆ bar [1]   │
diff --git a/tests/cli/add-metadata-overwrite-name.wat.stdout b/tests/cli/add-metadata-overwrite-name.wat.stdout
index 3b5e74ed..b8a8496f 100644
--- a/tests/cli/add-metadata-overwrite-name.wat.stdout
+++ b/tests/cli/add-metadata-overwrite-name.wat.stdout
@@ -1,9 +1,9 @@
 ╭───────┬───────────╮
 │ KIND  ┆ VALUE     │
 ╞═══════╪═══════════╡
+│ name  ┆ foo       │
+├╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤
 │ kind  ┆ module    │
 ├╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤
 │ range ┆ 0x0..0x15 │
-├╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤
-│ name  ┆ foo       │
 ╰───────┴───────────╯
diff --git a/tests/cli/add-metadata.wat.stdout b/tests/cli/add-metadata.wat.stdout
index 3e88493c..d78adae2 100644
--- a/tests/cli/add-metadata.wat.stdout
+++ b/tests/cli/add-metadata.wat.stdout
@@ -1,12 +1,12 @@
 ╭──────────────┬────────────╮
 │ KIND         ┆ VALUE      │
 ╞══════════════╪════════════╡
+│ name         ┆ foo        │
+├╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌┤
 │ kind         ┆ module     │
 ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌┤
 │ range        ┆ 0x0..0x54  │
 ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌┤
-│ name         ┆ foo        │
-├╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌┤
 │ language     ┆ bar [1]    │
 ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌┤
 │ processed-by ┆ baz [1]    │
diff --git a/tests/cli/metadata-add-component.wat.stdout b/tests/cli/metadata-add-component.wat.stdout
index f0d29b40..dec6045f 100644
--- a/tests/cli/metadata-add-component.wat.stdout
+++ b/tests/cli/metadata-add-component.wat.stdout
@@ -1,20 +1,22 @@
-╭──────────┬───────────╮
-│ KIND     ┆ VALUE     │
-╞══════════╪═══════════╡
-│ kind     ┆ component │
-├╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤
-│ range    ┆ 0x0..0x65 │
-├╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤
-│ name     ┆ foo       │
-├╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤
-│ language ┆ foo [1]   │
-╰──────────┴───────────╯
+╭──────────┬────────────────────╮
+│ KIND     ┆ VALUE              │
+╞══════════╪════════════════════╡
+│ name     ┆ foo                │
+├╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
+│ kind     ┆ component          │
+├╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
+│ range    ┆ 0x0..0x65          │
+├╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
+│ language ┆ foo [1]            │
+├╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
+│ child    ┆ <unknown> [module] │
+╰──────────┴────────────────────╯
 ╭───────┬───────────╮
 │ KIND  ┆ VALUE     │
 ╞═══════╪═══════════╡
+│ name  ┆ <unknown> │
+├╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤
 │ kind  ┆ module    │
 ├╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤
 │ range ┆ 0xa..0x31 │
-├╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤
-│ name  ┆ <unknown> │
 ╰───────┴───────────╯
diff --git a/tests/cli/metadata-component.wat.stdout b/tests/cli/metadata-component.wat.stdout
index 5dd1cdb2..27421471 100644
--- a/tests/cli/metadata-component.wat.stdout
+++ b/tests/cli/metadata-component.wat.stdout
@@ -1,27 +1,31 @@
+╭───────┬────────────────────────────╮
+│ KIND  ┆ VALUE                      │
+╞═══════╪════════════════════════════╡
+│ name  ┆ my-name                    │
+├╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
+│ kind  ┆ component                  │
+├╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
+│ range ┆ 0x0..0x88                  │
+├╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
+│ child ┆ submodule [module]         │
+├╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
+│ child ┆ another submodule [module] │
+╰───────┴────────────────────────────╯
 ╭───────┬───────────╮
 │ KIND  ┆ VALUE     │
 ╞═══════╪═══════════╡
-│ kind  ┆ component │
-├╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤
-│ range ┆ 0x0..0x88 │
+│ name  ┆ submodule │
 ├╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤
-│ name  ┆ my-name   │
-╰───────┴───────────╯
-╭───────┬───────────╮
-│ KIND  ┆ VALUE     │
-╞═══════╪═══════════╡
 │ kind  ┆ module    │
 ├╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤
 │ range ┆ 0xa..0x25 │
-├╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤
-│ name  ┆ submodule │
 ╰───────┴───────────╯
 ╭───────┬───────────────────╮
 │ KIND  ┆ VALUE             │
 ╞═══════╪═══════════════════╡
+│ name  ┆ another submodule │
+├╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
 │ kind  ┆ module            │
 ├╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
 │ range ┆ 0x27..0x4a        │
-├╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
-│ name  ┆ another submodule │
 ╰───────┴───────────────────╯
diff --git a/tests/cli/metadata.wat.stdout b/tests/cli/metadata.wat.stdout
index 4919b01d..8cc41d31 100644
--- a/tests/cli/metadata.wat.stdout
+++ b/tests/cli/metadata.wat.stdout
@@ -1,9 +1,9 @@
 ╭───────┬───────────╮
 │ KIND  ┆ VALUE     │
 ╞═══════╪═══════════╡
+│ name  ┆ <unknown> │
+├╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤
 │ kind  ┆ module    │
 ├╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤
 │ range ┆ 0x0..0x8  │
-├╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤
-│ name  ┆ <unknown> │
 ╰───────┴───────────╯