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
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
|
from dataclasses import dataclass, field
from .. import util
from ..builder import AsyncBuilder
from ..types import *
from .identifier import *
@dataclass(frozen=True)
class AddressRange:
start: int
end: int
def __contains__(self, value):
return value >= self.start and value < self.end
@dataclass
class ReferenceCount:
total: int = 0
static: int = 0
extern: int = 0
rel: int = 0
def add_reference(self, referencee, referencer, count):
self.total += count
if referencer:
if referencee._module != referencer._module:
self.rel += count
elif (referencee._library == referencer._library and
referencee._translation_unit == referencer._translation_unit):
self.static += count
else:
self.extern += count
else:
self.extern += count
def make_static(self):
self.total = 1
self.static = 1
self.extern = 0
self.rel = 0
@dataclass(eq=False)
class Symbol:
identifier: Identifier
addr: int
size: int
padding: int = 0
alignment: int = 0
reference_count: ReferenceCount = field(default_factory=ReferenceCount)
implicit_reference_count: ReferenceCount = field(default_factory=ReferenceCount)
sda_hack_reference_count: ReferenceCount = field(
default_factory=ReferenceCount)
require_forward_reference: bool = False
data_type: Type = None
source: str = None
force_section: str = None
_module: str = None
_library: str = None
_translation_unit: str = None
_section: str = None
alignment: int = 0
relative_addr: int = -1
template_index: int = -1
demangled_name: NamedType = None
references: Set[int] = field(default_factory=set)
implicit_references: Set[int] = field(default_factory=set)
is_reachable: bool = False
def __hash__(self):
return hash(self.addr)
def __eq__(self, other):
if not hasattr(self, 'addr'):
return True
return self.addr == other.addr and self.size == other.size
@property
def start(self):
return self.addr
@property
def end(self):
return self.addr + self.size
@property
def offset(self):
return self.addr - self.section.addr
@property
def label(self):
return self.identifier.label
@property
def is_static(self):
return False
@property
def has_body(self):
return True
@property
def has_class(self):
return self.demangled_name and self.demangled_name.has_class
@property
def has_template(self):
return self.demangled_name and self.demangled_name.has_template
@property
def uses_class_template(self):
return self.demangled_name and self.demangled_name.has_template
@property
def is_demangled(self):
return self.demangled_name != None
@property
def requires_force_active(self):
return False
def add_reference(self, referencer, count=1):
self.reference_count.add_reference(self, referencer, count)
def add_implicit_reference(self, referencer, count=1):
self.implicit_reference_count.add_reference(self, referencer, count)
def add_sda_hack(self, referencer, count=1):
self.sda_hack_reference_count.add_reference(self, referencer, count)
def valid_reference(self, addr):
return addr == self.addr
def cpp_reference(self, accessor, addr):
if addr != self.addr:
raise Dol2ZelException(
f"invalid reference addr 0x{addr:08X} for {type(self).__name__}\n{self}")
return f"&{self.identifier.label}"
def cpp_load(self, accessor, addr):
if addr != self.addr:
raise Dol2ZelException(
f"invalid reference addr 0x{addr:08X} for {type(self).__name__}\n{self}")
return f"{self.identifier.label}"
def asm_reference(self, addr):
if addr != self.addr:
return None
return self.identifier.label
def gather_references(self, context, valid_range):
pass
def get_reference_information(self, context, symbol_table):
pass
def types(self):
return set()
def set_mlts(self, module: int, library: str, translation_unit: str, section: str):
self._module = module
self._library = library
self._translation_unit = translation_unit
self._section = section
async def export_section_header(self, builder: AsyncBuilder):
if self._section == ".extab":
await builder.write("#pragma section \"extab_\"")
if self._section == ".extabindex":
await builder.write("#pragma section \"extabindex_\"")
elif self._section == ".ctors":
if self.identifier.label == "__init_cpp_exceptions_reference":
#await builder.write("#pragma section \".ctors$10\"")
#await builder.write_nonewline("__declspec(section \".ctors$10\") ")
await builder.write_nonewline("SECTION_CTORS10 ")
elif self.identifier.label == "_ctors":
#await builder.write("#pragma section \".ctors$15\"")
#await builder.write_nonewline("__declspec(section \".ctors$15\") ")
await builder.write_nonewline("SECTION_CTORS15 ")
elif self._section == ".dtors":
if self.identifier.label == "__destroy_global_chain_reference":
#await builder.write("#pragma section \".dtors$10\"")
#await builder.write_nonewline("__declspec(section \".dtors$10\") ")
await builder.write_nonewline("SECTION_DTORS10 ")
elif self.identifier.label == "__fini_cpp_exceptions_reference":
#await builder.write("#pragma section \".dtors$15\"")
#await builder.write_nonewline("__declspec(section \".dtors$15\") ")
await builder.write_nonewline("SECTION_DTORS15 ")
elif self.identifier.label == "__dtors_null_terminator":
#await builder.write("#pragma section \".dtors$15\"")
#await builder.write_nonewline("__declspec(section \".dtors$15\") ")
await builder.write_nonewline("SECTION_DTORS15 ")
elif self.identifier.label == "_dtors":
await builder.write_nonewline("SECTION_DTORS10 ")
elif self.force_section:
if self.force_section == '.bss':
await builder.write_nonewline("SECTION_BSS ")
else:
assert False
else:
await builder.write_nonewline("extern \"C\" ")
async def export_section(self, builder: AsyncBuilder):
section = ""
if self._section == ".data":
section = "SECTION_DATA "
elif self._section == ".sdata":
section = "SECTION_SDATA "
elif self._section == ".sdata2":
section = "SECTION_SDATA2 "
# elif self._section == ".bss":
# section = "SECTION_BSS "
# elif self._section == ".sbss":
# section = "SECTION_SBSS "
elif self._section == ".sbss2":
section = "SECTION_SBSS2 "
elif self._section == ".init":
section = "SECTION_INIT "
elif self._section == ".rodata":
section = "SECTION_RODATA "
elif self._section == ".extab":
await builder.write_nonewline("SECTION_EXTAB ")
elif self._section == ".extabindex":
await builder.write_nonewline("SECTION_EXTABINDEX ")
elif self._section == ".ctors":
if self.identifier.label == "__init_cpp_exceptions_reference":
#section = "__declspec(section \".ctors$10\") "
section = "SECTION_CTORS10 "
elif self.identifier.label == "_ctors":
#section = "__declspec(section \".ctors$15\") "
section = "SECTION_CTORS15 "
elif self._section == ".dtors":
if self.identifier.label == "__destroy_global_chain_reference":
#section = "__declspec(section \".dtors$10\") "
section = "SECTION_DTORS10 "
elif self.identifier.label == "__fini_cpp_exceptions_reference":
#section = "__declspec(section \".dtors$15\") "
section = "SECTION_DTORS15 "
elif self.identifier.label == "__dtors_null_terminator":
#section = "__declspec(section \".dtors$15\") "
section = "SECTION_DTORS15 "
elif self.identifier.label == "_dtors":
section = "SECTION_DTORS10 "
await builder.write_nonewline(section)
async def export_extern(self, builder: AsyncBuilder):
await builder.write_nonewline(f"extern ")
async def export_static(self, builder: AsyncBuilder):
await builder.write_nonewline(f"static ")
async def export_force_active(self, builder: AsyncBuilder):
await builder.write_nonewline(f"__declspec(forceactive) ")
async def export_readonly(self, builder: AsyncBuilder):
if self._section == ".rodata":
await builder.write_nonewline(f"const ")
elif self._section == ".extab":
await builder.write_nonewline(f"const ")
elif self._section == ".extabindex":
await builder.write_nonewline(f"const ")
elif self._section == ".ctors":
await builder.write_nonewline(f"const ")
elif self._section == ".dtors":
await builder.write_nonewline(f"const ")
async def export_declaration_head(self, builder: AsyncBuilder):
assert False
async def export_declaration_body(self, builder: AsyncBuilder):
assert False
async def export_declaration(self, exporter, builder: AsyncBuilder):
await self.export_declaration_head(exporter, builder)
await self.export_declaration_body(exporter, builder)
async def export_u8_data(self, builder: AsyncBuilder, data: bytearray):
for chunk in util.chunks(data, 16):
line = ", ".join([f"0x{x:02X}" for x in chunk])
await builder.write(f"\t{line},")
|