-
Notifications
You must be signed in to change notification settings - Fork 0
/
SymbTableHelpers.py
128 lines (98 loc) · 3.27 KB
/
SymbTableHelpers.py
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
import gdb
import sys
import os
sys.path.append(os.getcwd())
from CodeStackHelpers import *
from SortedCollection import *
def GetSymbolByIndexFromGothic(index):
return zCPar_Symbol(ReadInt(GetSymbTablePtr()+4*index))
def ReadZString(ptr):
charPtr = ReadInt(ptr + 8)
length = ReadInt(ptr + 12)
return ReadString(charPtr, length)
zCPar_Symbol_bitfield_ele = ((1 << 12) - 1) << 0
zCPar_Symbol_bitfield_type = ((1 << 4) - 1) << 12
zCPar_Symbol_bitfield_flags = ((1 << 6) - 1) << 16
zCPar_Symbol_bitfield_space = ((1 << 1) - 1) << 22
zPAR_TYPE_VOID = 0 << 12
zPAR_TYPE_FLOAT = 1 << 12
zPAR_TYPE_INT = 2 << 12
zPAR_TYPE_STRING = 3 << 12
zPAR_TYPE_CLASS = 4 << 12
zPAR_TYPE_FUNC = 5 << 12
zPAR_TYPE_PROTOTYPE = 6 << 12
zPAR_TYPE_INSTANCE = 7 << 12
zPAR_FLAG_CONST = 1 << 16
zPAR_FLAG_RETURN = 2 << 16
zPAR_FLAG_CLASSVAR = 4 << 16
zPAR_FLAG_EXTERNAL = 8 << 16
zPAR_FLAG_MERGED = 16 << 16
class zCPar_Symbol():
def __init__(self, ptr):
self.name = ReadZString(ptr)
self.content = ReadInt(ptr + 0x18)
self.offset = ReadInt(ptr + 0x1C)
self.bitfield = ReadInt(ptr + 0x20)
self.parent = ReadInt(ptr + 0x38)
def GetType(self):
return self.bitfield & zCPar_Symbol_bitfield_type
def GetFlags(self):
return self.bitfield & zCPar_Symbol_bitfield_flags
def IsFunc(self):
return (self.GetType() & zCPar_Symbol_bitfield_type) == zPAR_TYPE_FUNC
def IsDaedalusFunc(self):
return self.IsFunc() \
and not (self.GetFlags() & zPAR_FLAG_EXTERNAL == zPAR_FLAG_EXTERNAL) \
and (self.GetFlags() & zPAR_FLAG_CONST == zPAR_FLAG_CONST)
def IsExternal(self):
return self.IsFunc() and (self.GetFlags() & zPAR_FLAG_EXTERNAL == zPAR_FLAG_EXTERNAL)
def __repr__(self):
return self.name
# Preprocess all Gothic symbols into Python zCPar_Symbols
def InitSymbTable():
global SymbTable
SymbTable = []
for i in range(GetSymbTableLength()):
SymbTable.append(GetSymbolByIndexFromGothic(i))
def GetSymbTable():
global SymbTable
if len(SymbTable) == 0:
InitSymbTable()
return SymbTable
# List of all symbols sorted by name (for faster searching)
def InitSymbNameList():
global SymbolNameList
SymbolNameList = SortedCollection(key=lambda id: SymbTable[id].name)
for i in range(GetSymbTableLength()):
SymbolNameList.insert(i)
def GetSymbIdByName(name):
global SymbolNameList
try:
return SymbolNameList.find(name)
except ValueError:
return None
# List of all functions (for faster searching)
def InitFuncList():
global FuncIdList, SymbTable
FuncIdList = SortedCollection(key=lambda id: SymbTable[id].content)
for i in range(GetSymbTableLength()):
if SymbTable[i].IsDaedalusFunc():
FuncIdList.insert(i)
def GetFuncIdByOffset(offset):
global SymbTable, FuncIdList
try:
return FuncIdList.find_le(offset)
except ValueError: # Value not found - happens with hook etc., generally any code that was constructed at runtime
return None
def GetFuncNameByOffset(offset):
id = GetFuncIdByOffset(offset)
if id is None:
return "[UNKNOWN]"
else:
return GetSymbTable()[id].name
def PrintFuncNameByOffset(offset):
name = GetFuncNameByOffset(offset)
print(name)
def PrintCurrFuncName():
offset = GetCurrParserStackOffset()
PrintFuncNameByOffset(offset)