main.go 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  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. "os"
  10. )
  11. func main() {
  12. if len(os.Args) > 1 {
  13. data, err := os.ReadFile(os.Args[1])
  14. if err != nil {
  15. panic(err)
  16. }
  17. proto := binchunk.Undump(data)
  18. list(proto)
  19. }
  20. }
  21. func list(f *binchunk.Prototype) {
  22. printHeader(f)
  23. printCode(f)
  24. printDetail(f)
  25. for _, p := range f.Protos {
  26. list(p)
  27. }
  28. }
  29. // 打印常量表、局部变量表和 Upvalue 表
  30. func printDetail(f *binchunk.Prototype) {
  31. fmt.Printf("constants (%d):\n", len(f.Constants))
  32. for i, k := range f.Constants {
  33. fmt.Printf("\t%d\t%s\n", i+1, constantToString(k))
  34. }
  35. fmt.Printf("locals (%d):\n", len(f.LocVars))
  36. for i, locVar := range f.LocVars {
  37. fmt.Printf("\t%d\t%s\t%d\t%d\n", i, locVar.VarName, locVar.StartPC+1, locVar.EndPC+1)
  38. }
  39. fmt.Printf("upvalues (%d):\n", len(f.Upvalues))
  40. for i, upval := range f.Upvalues {
  41. fmt.Printf("\t%d\t%s\t%d\t%d\n", i, upvalName(f, i), upval.Instack, upval.Idx)
  42. }
  43. }
  44. // 根据 Upvalue 索引从调试信息里找出 Upvalue 的名字
  45. func upvalName(f *binchunk.Prototype, idx int) string {
  46. if len(f.UpvalueNames) > 0 {
  47. return f.UpvalueNames[idx]
  48. }
  49. return "-"
  50. }
  51. func constantToString(k interface{}) string {
  52. switch k.(type) {
  53. case nil:
  54. return "nil"
  55. case bool:
  56. return fmt.Sprintf("%t", k)
  57. case float64:
  58. return fmt.Sprintf("%g", k)
  59. case int64:
  60. return fmt.Sprintf("%d", k)
  61. case string:
  62. return fmt.Sprintf("%q", k)
  63. default:
  64. return "?"
  65. }
  66. }
  67. func printCode(f *binchunk.Prototype) {
  68. for pc, c := range f.Code {
  69. line := "-"
  70. if len(f.LineInfo) > 0 {
  71. line = fmt.Sprintf("%d", f.LineInfo[pc])
  72. }
  73. // 序号、行号和 十六进制表示
  74. fmt.Printf("\t%d\t[%s]\t0X%08X\n", pc+1, line, c)
  75. }
  76. }
  77. func printHeader(f *binchunk.Prototype) {
  78. funcType := "main"
  79. if f.LineDefined > 0 {
  80. funcType = "function"
  81. }
  82. varargFlag := ""
  83. if f.IsVararg > 0 {
  84. varargFlag = "+"
  85. }
  86. fmt.Printf("\n%s <%s:%d, %d> (%d instructions)\n", funcType, f.Source, f.LineDefined, f.LastLineDefined, len(f.Code))
  87. fmt.Printf("%d%s params, %d slots, %d upvalues, ", f.NumParams, varargFlag, f.MaxStackSize, len(f.Upvalues))
  88. fmt.Printf("%d locals, %d constants, %d functions\n", len(f.LocVars), len(f.Constants), len(f.Protos))
  89. }