上QQ阅读APP看书,第一时间看更新
2.4 实现dump命令
在2.1节和2.2节,我们定义好了模块的内存表示。在2.3节,我们讨论了如何解码二进制模块。有了这两项基础,我们就可以自己写一个wasm-objdump工具了。Go工程的最佳实践是把命令行工具统一放在项目的cmd包里,我们也采用这种做法,下面是本章代码的完整目录结构。
code/go/ch02/wasm.go/ ├── binary/ ├── cmd/ │ └── wasmgo/ │ ├── dumper.go │ └── main.go ├── go.mod └── go.sum
相比模块的解码逻辑,打印逻辑更为简单,有关代码全部在dumper.go文件里。下面给出main.go文件的全部代码。
package main import ( "flag" "fmt" "os" "wasm.go/binary" ) func main() { dumpFlag := flag.Bool("d", false, "dump") flag.Parse() if flag.NArg() != 1 { fmt.Println("Usage: wasmgo [-d] filename") os.Exit(1) } module, err := binary.DecodeFile(flag.Args()[0]) if err != nil { fmt.Println(err.Error()) os.Exit(1) } if *dumpFlag { dump(module) // 在dumper.go文件里 } }
执行命令查看结果。
$ cd code/go/ch02/wasm.go/ $ go run wasm.go/cmd/wasmgo -d ../../../js/ch01_hw.wasm Version: 0x01 Type[5]: type[0]: (i32)->() type[1]: ()->() type[2]: (i32,i32)->(i32) type[3]: (i32)->(i32) type[4]: (i32,i32,i32)->() Import[1]: func[0]: env.print_char, sig=0 Function[11]: func[1]: sig=1 func[2]: sig=2 ... Table[1]: table[0]: {min: 1, max: 1} Memory[1]: memory[0]: {min: 17, max: 0} Global[3]: global[0]: {type: i32, mut: 1} global[1]: {type: i32, mut: 0} global[2]: {type: i32, mut: 0} Export[4]: memory[0]: name=memory global[1]: name=__data_end global[2]: name=__heap_base func[1]: name=main Start: Element[0]: Code[11]: func[1]: locals=[i32 x 22] func[2]: locals=[i32 x 1] ... Data[1]: data[0]: mem=0 Custom[1]: custom[0]: name=name