main.go 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. // Author: simon
  2. // Author: ynwdlxm@163.com
  3. // Date: 2024/4/13 17:14
  4. // Desc:
  5. package main
  6. import (
  7. "fmt"
  8. "luago/binchunk"
  9. "luago/vm"
  10. "os"
  11. )
  12. func main() {
  13. if len(os.Args) > 1 {
  14. data, err := os.ReadFile(os.Args[1])
  15. if err != nil {
  16. panic(err)
  17. }
  18. proto := binchunk.Undump(data)
  19. list(proto)
  20. }
  21. }
  22. func list(f *binchunk.Prototype) {
  23. printHeader(f)
  24. printCode(f)
  25. printDetail(f)
  26. for _, p := range f.Protos {
  27. list(p)
  28. }
  29. }
  30. // 打印常量表、局部变量表和 Upvalue 表
  31. func printDetail(f *binchunk.Prototype) {
  32. fmt.Printf("constants (%d):\n", len(f.Constants))
  33. for i, k := range f.Constants {
  34. fmt.Printf("\t%d\t%s\n", i+1, constantToString(k))
  35. }
  36. fmt.Printf("locals (%d):\n", len(f.LocVars))
  37. for i, locVar := range f.LocVars {
  38. fmt.Printf("\t%d\t%s\t%d\t%d\n", i, locVar.VarName, locVar.StartPC+1, locVar.EndPC+1)
  39. }
  40. fmt.Printf("upvalues (%d):\n", len(f.Upvalues))
  41. for i, upval := range f.Upvalues {
  42. fmt.Printf("\t%d\t%s\t%d\t%d\n", i, upvalName(f, i), upval.Instack, upval.Idx)
  43. }
  44. }
  45. // 根据 Upvalue 索引从调试信息里找出 Upvalue 的名字
  46. func upvalName(f *binchunk.Prototype, idx int) string {
  47. if len(f.UpvalueNames) > 0 {
  48. return f.UpvalueNames[idx]
  49. }
  50. return "-"
  51. }
  52. func constantToString(k interface{}) string {
  53. switch k.(type) {
  54. case nil:
  55. return "nil"
  56. case bool:
  57. return fmt.Sprintf("%t", k)
  58. case float64:
  59. return fmt.Sprintf("%g", k)
  60. case int64:
  61. return fmt.Sprintf("%d", k)
  62. case string:
  63. return fmt.Sprintf("%q", k)
  64. default:
  65. return "?"
  66. }
  67. }
  68. func printCode(f *binchunk.Prototype) {
  69. for pc, c := range f.Code {
  70. line := "-"
  71. if len(f.LineInfo) > 0 {
  72. line = fmt.Sprintf("%d", f.LineInfo[pc])
  73. }
  74. // 序号、行号和 十六进制表示
  75. // fmt.Printf("\t%d\t[%s]\t0X%08X\n", pc+1, line, c)
  76. i := vm.Instruction(c)
  77. fmt.Printf("\t%d\t[%s]\t%s \t", pc+1, line, i.OpName())
  78. printOperands(i)
  79. fmt.Printf("\n")
  80. }
  81. }
  82. func printOperands(i vm.Instruction) {
  83. switch i.OpMode() {
  84. case vm.IABC:
  85. a, b, c := i.ABC()
  86. fmt.Printf("%d", a)
  87. // 如果操作数 B 和 C 的最高位是 1, 就默认为它表示常量表索引,按负数输出
  88. if i.BMode() != vm.OpArgN {
  89. if b > 0XFF {
  90. fmt.Printf(" %d", -1-b&0XFF)
  91. } else {
  92. fmt.Printf(" %d", b)
  93. }
  94. }
  95. if i.CMode() != vm.OpArgN {
  96. if c > 0XFF {
  97. fmt.Printf(" %d", -1-c&0XFF)
  98. } else {
  99. fmt.Printf(" %d", c)
  100. }
  101. }
  102. case vm.IABx:
  103. a, bx := i.ABx()
  104. fmt.Printf("%d", a)
  105. if i.BMode() == vm.OpArgK {
  106. fmt.Printf(" %d", -1-bx)
  107. } else if i.BMode() == vm.OpArgU {
  108. fmt.Printf(" %d", bx)
  109. }
  110. case vm.IAsBx:
  111. a, sbx := i.AsBx()
  112. fmt.Printf("%d %d", a, sbx)
  113. case vm.IAx:
  114. ax := i.Ax()
  115. fmt.Printf("%d", -1-ax)
  116. default:
  117. panic("unhandled default case")
  118. }
  119. }
  120. func printHeader(f *binchunk.Prototype) {
  121. funcType := "main"
  122. if f.LineDefined > 0 {
  123. funcType = "function"
  124. }
  125. varargFlag := ""
  126. if f.IsVararg > 0 {
  127. varargFlag = "+"
  128. }
  129. fmt.Printf("\n%s <%s:%d, %d> (%d instructions)\n", funcType, f.Source, f.LineDefined, f.LastLineDefined, len(f.Code))
  130. fmt.Printf("%d%s params, %d slots, %d upvalues, ", f.NumParams, varargFlag, f.MaxStackSize, len(f.Upvalues))
  131. fmt.Printf("%d locals, %d constants, %d functions\n", len(f.LocVars), len(f.Constants), len(f.Protos))
  132. }