-
Notifications
You must be signed in to change notification settings - Fork 0
/
luaDisasm.go
139 lines (115 loc) · 3.25 KB
/
luaDisasm.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
package main
import (
"io/ioutil"
//"unsafe"
"fmt"
"encoding/binary"
"bytes"
"os"
)
type LuaHeaderType struct {
W0, W1, W2 uint32
}
type LuaInstructionType uint32
//Holds part of a Function block for the top-level (main()). It is missing the source name
//Not included in this type due to variable length string.
type LuaTopLevelFuncType struct {
LineDefined, LastLineDefined uint32
NumUpVals, NumParameters byte // For the main chunk, the values of both fields are 0.
IsVarg byte
MaxStackSize byte
}
type LuaFuncType struct {
SourceNameSize uint32//0 for non-main funcs
LineDefined, LastLineDefined uint32
NumUpVals, NumParameters byte
IsVarg byte
MaxStackSize byte
}
func extractOpcodeIndex(instr LuaInstructionType) LuaInstructionType {
return instr & 0x3F
}
func main() {
//------- READ ENTIRE FILE ---------------
fileBytes, fileErr := ioutil.ReadFile(os.Args[1])
if fileErr != nil { panic(fileErr) }
var lhdr LuaHeaderType
mybuf := bytes.NewBuffer(fileBytes[:])//fileBytes[4:]
myerr := binary.Read(mybuf, binary.LittleEndian, &lhdr)
if myerr != nil {
fmt.Println("binary.Read failed:", myerr)
}
//-------- HEADER ---------------
if lhdr.W0 != 0x61754C1B {
panic ("Lua signature not found")
}
major := (lhdr.W1 >> 4) & 0xF
minor := (lhdr.W1 >> 0) & 0xF
fmt.Printf("Lua version %d.%d\n", major, minor)
//-------- Original source filename
var StringLength uint32
binary.Read(mybuf, binary.LittleEndian, &StringLength)
if StringLength != 0 {
var srcFilename = make([]byte, StringLength)
binary.Read(mybuf, binary.LittleEndian, &srcFilename)
fmt.Printf("Src file is %s\n", srcFilename)
}
var mainFunc LuaTopLevelFuncType
binary.Read(mybuf, binary.LittleEndian, &mainFunc)
fmt.Printf("First line %d.\n", mainFunc.LineDefined)
fmt.Printf("Last line %d.\n", mainFunc.LastLineDefined)
fmt.Printf("Up vals %d.\n", mainFunc.NumUpVals)
fmt.Printf("Parameters %d.\n", mainFunc.NumParameters)
fmt.Printf("Varg %d.\n", mainFunc.IsVarg)
fmt.Printf("Max stack size %d.\n", mainFunc.MaxStackSize)
var codeSize uint32
binary.Read(mybuf, binary.LittleEndian, &codeSize)
fmt.Printf("Code size %d.\n", codeSize)
var mainInstList = make([]LuaInstructionType, codeSize)
binary.Read(mybuf, binary.LittleEndian, &mainInstList)
var instNum uint32 = 0
for ; instNum < codeSize; instNum++ {
luaP_opnames := [...] string { "MOVE","LOADK","LOADBOOL","LOADNIL","GETUPVAL","GETGLOBAL",
"MOVE",
"LOADK",
"LOADBOOL",
"LOADNIL",
"GETUPVAL",
"GETGLOBAL",
"GETTABLE",
"SETGLOBAL",
"SETUPVAL",
"SETTABLE",
"NEWTABLE",
"SELF",
"ADD",
"SUB",
"MUL",
"DIV",
"MOD",
"POW",
"UNM",
"NOT",
"LEN",
"CONCAT",
"JMP",
"EQ",
"LT",
"LE",
"TEST",
"TESTSET",
"CALL",
"TAILCALL",
"RETURN",
"FORLOOP",
"FORPREP",
"TFORLOOP",
"SETLIST",
"CLOSE",
"CLOSURE",
"VARARG"}
opcodeIdx := extractOpcodeIndex(mainInstList[instNum])
fmt.Printf("Opcode is %s\n", luaP_opnames[ opcodeIdx ])
}
}
//http://golangtutorials.blogspot.co.uk/2011/06/structs-in-go-instead-of-classes-in.html