wasm-tools
wasm-tools copied to clipboard
wamprinter: support printing name and bytes for unknown custom sections
Currently, if a custom section in a WASM module does not have a registered printer, and it is not producers or dylink.0, it is ignored. It would be nice if an option as added (or it was the default behavior) to print the names of unknown custom sections, then a hex encoding of their bytes. I would specifically find this useful in the context of wasmtime explore.
I'd love to contribute this functionality if there is alignment!
This seems reasonable to me, but what do other disassemblers do? We'd ideally not stray too far from them.
@fitzgen thanks for following up! Support was recently added to wasm2wat (https://github.com/WebAssembly/wabt/pull/2284) in accordance with the annotations proposal. I am not sure what the status is of the proposal, but if we wanted to be in alignment, we should also likely update the current handling of custom sections. I have provided a few examples below to show the default behavior of wasmprinter / wasm2wat, as well as enabling annotations in wasm2wat.
wasmprinter will use @<name> syntax for the known custom sections.
$ wasmtime explore wasm32_args.wasm
(copied from browser)
(module
(type (;0;) (func))
(type (;1;) (func (param i32 i32) (result i32)))
(func $__wasm_call_ctors (;0;) (type 0))
(func $add (;1;) (type 1) (param i32 i32) (result i32)
(local i32 i32 i32 i32 i32 i32)
global.get $__stack_pointer
local.set 2
i32.const 16
local.set 3
local.get 2
local.get 3
i32.sub
local.set 4
local.get 4
local.get 0
i32.store offset=12
local.get 4
local.get 1
i32.store offset=8
local.get 4
i32.load offset=12
local.set 5
local.get 4
i32.load offset=8
local.set 6
local.get 5
local.get 6
i32.add
local.set 7
local.get 7
return
)
(memory (;0;) 2)
(global $__stack_pointer (;0;) (mut i32) i32.const 66560)
(global (;1;) i32 i32.const 1024)
(global (;2;) i32 i32.const 1024)
(global (;3;) i32 i32.const 1024)
(global (;4;) i32 i32.const 66560)
(global (;5;) i32 i32.const 1024)
(global (;6;) i32 i32.const 66560)
(global (;7;) i32 i32.const 131072)
(global (;8;) i32 i32.const 0)
(global (;9;) i32 i32.const 1)
(export "memory" (memory 0))
(export "__wasm_call_ctors" (func $__wasm_call_ctors))
(export "add" (func $add))
(export "__dso_handle" (global 1))
(export "__data_end" (global 2))
(export "__stack_low" (global 3))
(export "__stack_high" (global 4))
(export "__global_base" (global 5))
(export "__heap_base" (global 6))
(export "__heap_end" (global 7))
(export "__memory_base" (global 8))
(export "__table_base" (global 9))
(@producers
(processed-by "Ubuntu clang" "17.0.6 (++20231209124227+6009708b4367-1~exp1~20231209124336.77)")
)
)
wasm2wat will ignore all custom sections by default.
$ wasm2wat wasm32_args.wasm
(module
(type (;0;) (func))
(type (;1;) (func (param i32 i32) (result i32)))
(func $__wasm_call_ctors (type 0))
(func $add (type 1) (param i32 i32) (result i32)
(local i32 i32 i32 i32 i32 i32)
global.get $__stack_pointer
local.set 2
i32.const 16
local.set 3
local.get 2
local.get 3
i32.sub
local.set 4
local.get 4
local.get 0
i32.store offset=12
local.get 4
local.get 1
i32.store offset=8
local.get 4
i32.load offset=12
local.set 5
local.get 4
i32.load offset=8
local.set 6
local.get 5
local.get 6
i32.add
local.set 7
local.get 7
return)
(memory (;0;) 2)
(global $__stack_pointer (mut i32) (i32.const 66560))
(global (;1;) i32 (i32.const 1024))
(global (;2;) i32 (i32.const 1024))
(global (;3;) i32 (i32.const 1024))
(global (;4;) i32 (i32.const 66560))
(global (;5;) i32 (i32.const 1024))
(global (;6;) i32 (i32.const 66560))
(global (;7;) i32 (i32.const 131072))
(global (;8;) i32 (i32.const 0))
(global (;9;) i32 (i32.const 1))
(export "memory" (memory 0))
(export "__wasm_call_ctors" (func $__wasm_call_ctors))
(export "add" (func $add))
(export "__dso_handle" (global 1))
(export "__data_end" (global 2))
(export "__stack_low" (global 3))
(export "__stack_high" (global 4))
(export "__global_base" (global 5))
(export "__heap_base" (global 6))
(export "__heap_end" (global 7))
(export "__memory_base" (global 8))
(export "__table_base" (global 9)))
When annotations are enabled, wasm2wat uses the @custom "<name>" syntax.
$ wasm2wat --enable-annotations wasm32_args.wasm
(module
(type (;0;) (func))
(type (;1;) (func (param i32 i32) (result i32)))
(func $__wasm_call_ctors (type 0))
(func $add (type 1) (param i32 i32) (result i32)
(local i32 i32 i32 i32 i32 i32)
global.get $__stack_pointer
local.set 2
i32.const 16
local.set 3
local.get 2
local.get 3
i32.sub
local.set 4
local.get 4
local.get 0
i32.store offset=12
local.get 4
local.get 1
i32.store offset=8
local.get 4
i32.load offset=12
local.set 5
local.get 4
i32.load offset=8
local.set 6
local.get 5
local.get 6
i32.add
local.set 7
local.get 7
return)
(memory (;0;) 2)
(global $__stack_pointer (mut i32) (i32.const 66560))
(global (;1;) i32 (i32.const 1024))
(global (;2;) i32 (i32.const 1024))
(global (;3;) i32 (i32.const 1024))
(global (;4;) i32 (i32.const 66560))
(global (;5;) i32 (i32.const 1024))
(global (;6;) i32 (i32.const 66560))
(global (;7;) i32 (i32.const 131072))
(global (;8;) i32 (i32.const 0))
(global (;9;) i32 (i32.const 1))
(export "memory" (memory 0))
(export "__wasm_call_ctors" (func $__wasm_call_ctors))
(export "add" (func $add))
(export "__dso_handle" (global 1))
(export "__data_end" (global 2))
(export "__stack_low" (global 3))
(export "__stack_high" (global 4))
(export "__global_base" (global 5))
(export "__heap_base" (global 6))
(export "__heap_end" (global 7))
(export "__memory_base" (global 8))
(export "__table_base" (global 9))
(@custom "name" "\01\19\02\00\11__wasm_call_ctors\01\03add\07\12\01\00\0f__stack_pointer")
(@custom "producers" "\01\0cprocessed-by\01\0cUbuntu clang?17.0.6 (++20231209124227+6009708b4367-1~exp1~20231209124336.77)")
(@custom "target_features" "\02+\0fmutable-globals+\08sign-ext"))
I think this'd be a good idea to support! The @producers and @dylink.0 syntax is made up by wasmprinter under the assumption that other text-to-binary tools ignore unknown headers, which in retrospect may not be the best of ideas. In any case though as it relates to arbitrary custom sections I think it'd make sense to print those by default, and wast, the text parser, already supports @custom and all its variations.