| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152 |
- // Author: simon
- // Author: ynwdlxm@163.com
- // Date: 2024/4/13 17:14
- // Desc:
- package main
- import (
- "fmt"
- "luago/binchunk"
- "luago/vm"
- "os"
- )
- func main() {
- if len(os.Args) > 1 {
- data, err := os.ReadFile(os.Args[1])
- if err != nil {
- panic(err)
- }
- proto := binchunk.Undump(data)
- list(proto)
- }
- }
- func list(f *binchunk.Prototype) {
- printHeader(f)
- printCode(f)
- printDetail(f)
- for _, p := range f.Protos {
- list(p)
- }
- }
- // 打印常量表、局部变量表和 Upvalue 表
- func printDetail(f *binchunk.Prototype) {
- fmt.Printf("constants (%d):\n", len(f.Constants))
- for i, k := range f.Constants {
- fmt.Printf("\t%d\t%s\n", i+1, constantToString(k))
- }
- fmt.Printf("locals (%d):\n", len(f.LocVars))
- for i, locVar := range f.LocVars {
- fmt.Printf("\t%d\t%s\t%d\t%d\n", i, locVar.VarName, locVar.StartPC+1, locVar.EndPC+1)
- }
- fmt.Printf("upvalues (%d):\n", len(f.Upvalues))
- for i, upval := range f.Upvalues {
- fmt.Printf("\t%d\t%s\t%d\t%d\n", i, upvalName(f, i), upval.Instack, upval.Idx)
- }
- }
- // 根据 Upvalue 索引从调试信息里找出 Upvalue 的名字
- func upvalName(f *binchunk.Prototype, idx int) string {
- if len(f.UpvalueNames) > 0 {
- return f.UpvalueNames[idx]
- }
- return "-"
- }
- func constantToString(k interface{}) string {
- switch k.(type) {
- case nil:
- return "nil"
- case bool:
- return fmt.Sprintf("%t", k)
- case float64:
- return fmt.Sprintf("%g", k)
- case int64:
- return fmt.Sprintf("%d", k)
- case string:
- return fmt.Sprintf("%q", k)
- default:
- return "?"
- }
- }
- func printCode(f *binchunk.Prototype) {
- for pc, c := range f.Code {
- line := "-"
- if len(f.LineInfo) > 0 {
- line = fmt.Sprintf("%d", f.LineInfo[pc])
- }
- // 序号、行号和 十六进制表示
- // fmt.Printf("\t%d\t[%s]\t0X%08X\n", pc+1, line, c)
- i := vm.Instruction(c)
- fmt.Printf("\t%d\t[%s]\t%s \t", pc+1, line, i.OpName())
- printOperands(i)
- fmt.Printf("\n")
- }
- }
- func printOperands(i vm.Instruction) {
- switch i.OpMode() {
- case vm.IABC:
- a, b, c := i.ABC()
- fmt.Printf("%d", a)
- // 如果操作数 B 和 C 的最高位是 1, 就默认为它表示常量表索引,按负数输出
- if i.BMode() != vm.OpArgN {
- if b > 0XFF {
- fmt.Printf(" %d", -1-b&0XFF)
- } else {
- fmt.Printf(" %d", b)
- }
- }
- if i.CMode() != vm.OpArgN {
- if c > 0XFF {
- fmt.Printf(" %d", -1-c&0XFF)
- } else {
- fmt.Printf(" %d", c)
- }
- }
- case vm.IABx:
- a, bx := i.ABx()
- fmt.Printf("%d", a)
- if i.BMode() == vm.OpArgK {
- fmt.Printf(" %d", -1-bx)
- } else if i.BMode() == vm.OpArgU {
- fmt.Printf(" %d", bx)
- }
- case vm.IAsBx:
- a, sbx := i.AsBx()
- fmt.Printf("%d %d", a, sbx)
- case vm.IAx:
- ax := i.Ax()
- fmt.Printf("%d", -1-ax)
- default:
- panic("unhandled default case")
- }
- }
- func printHeader(f *binchunk.Prototype) {
- funcType := "main"
- if f.LineDefined > 0 {
- funcType = "function"
- }
- varargFlag := ""
- if f.IsVararg > 0 {
- varargFlag = "+"
- }
- fmt.Printf("\n%s <%s:%d, %d> (%d instructions)\n", funcType, f.Source, f.LineDefined, f.LastLineDefined, len(f.Code))
- fmt.Printf("%d%s params, %d slots, %d upvalues, ", f.NumParams, varargFlag, f.MaxStackSize, len(f.Upvalues))
- fmt.Printf("%d locals, %d constants, %d functions\n", len(f.LocVars), len(f.Constants), len(f.Protos))
- }
|