mirror of
https://github.com/zeldaret/tp
synced 2026-08-21 14:37:49 -04:00
.dead section fix
This commit is contained in:
+37
-2
@@ -60,6 +60,8 @@ def lcf(output_path):
|
||||
for name, align in SECTIONS:
|
||||
file.write("\t\t%s ALIGN(0x%X):{}\n" % (name, align))
|
||||
|
||||
file.write("\t\t/DISCARD/ : { *(.dead) }\n")
|
||||
|
||||
file.write("\t} > text\n")
|
||||
file.write("\t_stack_addr = (_f_sbss2 + SIZEOF(.sbss2) + 65536 + 0x7) & ~0x7;\n")
|
||||
file.write("\t_stack_end = _f_sbss2 + SIZEOF(.sbss2);\n")
|
||||
@@ -114,8 +116,9 @@ def lcf(output_path):
|
||||
if x['type'] == "StringBase":
|
||||
continue
|
||||
|
||||
rc = x['r']
|
||||
require_force_active = False
|
||||
"""
|
||||
rc = x['r']
|
||||
|
||||
# the static reference count is unchanged as the linker seems not to strip
|
||||
# static variables and functions. i.e., if the static reference count is
|
||||
@@ -137,10 +140,41 @@ def lcf(output_path):
|
||||
if static_rc == 0 and extern_rc == 0 and rels_rc == 0:
|
||||
require_force_active = True
|
||||
|
||||
if rels_rc > 0:
|
||||
require_force_active = True
|
||||
|
||||
if k.startswith("__sinit_"):
|
||||
require_force_active = True
|
||||
|
||||
if k.startswith("__vt__"):
|
||||
require_force_active = True
|
||||
"""
|
||||
|
||||
if not x['is_reachable']:
|
||||
require_force_active = True
|
||||
|
||||
# generate the force active.
|
||||
# the linker
|
||||
if require_force_active:
|
||||
file.write("\t\"%s\"\n" % (k))
|
||||
file.write(f"\t\"{x['label']}\"\n")
|
||||
if not x['label'] in main_names:
|
||||
file.write(f"\t\"{x['name']}\"\n")
|
||||
file.write(f"\t/* {x['label'] in main_names} */ \n")
|
||||
|
||||
for x in module0.SYMBOLS:
|
||||
if x['type'] == "StringBase":
|
||||
continue
|
||||
|
||||
if x['is_reachable']:
|
||||
if x['label'] != x['name']:
|
||||
file.write(f"\t\"{x['name']}\"\n")
|
||||
|
||||
for symbol in symbols:
|
||||
if not symbol.name:
|
||||
continue
|
||||
|
||||
if "__template" in symbol.name:
|
||||
file.write("\t\"%s\"\n" % (symbol.name))
|
||||
|
||||
file.write("\n")
|
||||
file.write("}\n")
|
||||
@@ -180,6 +214,7 @@ SECTIONS = [
|
||||
(".sdata2", 0x20),
|
||||
(".sbss2", 0x20),
|
||||
(".stack", 0x100),
|
||||
#(".dead", 0x100),
|
||||
]
|
||||
|
||||
# custom force actives
|
||||
|
||||
@@ -10,6 +10,7 @@ from .symbol import *
|
||||
class ArbitraryData(Symbol):
|
||||
data: bytes = field(default=None, repr=False)
|
||||
padding_data: bytes = field(default=None, repr=False)
|
||||
zero_length: bool = False
|
||||
|
||||
@property
|
||||
def element_size(self):
|
||||
@@ -38,6 +39,8 @@ class ArbitraryData(Symbol):
|
||||
return type
|
||||
|
||||
def array_type(self):
|
||||
if self.zero_length:
|
||||
return ZeroArrayType.create(self.element_type())
|
||||
return PaddingArrayType.create(
|
||||
self.element_type(),
|
||||
self.size // self.element_size,
|
||||
|
||||
@@ -2,3 +2,4 @@
|
||||
from .base import *
|
||||
from .asm import *
|
||||
from .ret import *
|
||||
from .sinit import *
|
||||
|
||||
@@ -7,33 +7,11 @@ from pathlib import Path
|
||||
from ...builder import AsyncBuilder
|
||||
from ...disassemble import AccessCollector
|
||||
from ... import util
|
||||
from .. import static_analyze
|
||||
from ..base import *
|
||||
from ..symbol import *
|
||||
from .base import *
|
||||
|
||||
"""
|
||||
@dataclass(eq=False)
|
||||
class Block(ArbitraryData):
|
||||
sda_hack_references: Set[int] = field(default=None, repr=False)
|
||||
|
||||
def _get_internal_references(self, context, symbol_table):
|
||||
collector = AccessCollector([])
|
||||
for x in collector.execute_generator(self.addr, self.data, self.size):
|
||||
pass
|
||||
sda_hack_symbols = [symbol_table[self._module, x]
|
||||
for x in collector.sda_hack_references]
|
||||
self.sda_hack_references = set([
|
||||
(x._module, x.addr)
|
||||
for x in sda_hack_symbols
|
||||
if x
|
||||
])
|
||||
symbols = [
|
||||
symbol_table[self._module, x.addr]
|
||||
for x in collector.accesses.values()
|
||||
]
|
||||
return set([(x._module, x.addr) for x in symbols if x])
|
||||
"""
|
||||
|
||||
@dataclass
|
||||
class Block():
|
||||
identifier: Identifier
|
||||
@@ -53,7 +31,6 @@ class Block():
|
||||
return None
|
||||
return self.identifier.label
|
||||
|
||||
from .. import static_analyze
|
||||
|
||||
@dataclass(eq=False)
|
||||
class ASMFunction(Function):
|
||||
@@ -63,6 +40,7 @@ class ASMFunction(Function):
|
||||
data: bytearray = None
|
||||
|
||||
def gather_references(self, context, valid_range):
|
||||
"""
|
||||
addrs = static_analyze.function(self.data, self.addr, self.size)
|
||||
function_range = AddressRange(self.start, self.end)
|
||||
self.references = [
|
||||
@@ -70,7 +48,25 @@ class ASMFunction(Function):
|
||||
for addr in addrs.values()
|
||||
if addr in valid_range and not addr in function_range
|
||||
]
|
||||
"""
|
||||
|
||||
collector = AccessCollector([])
|
||||
for i, addr in collector.execute_generator(self.addr, self.data, self.size):
|
||||
pass
|
||||
|
||||
function_range = AddressRange(self.start, self.end)
|
||||
self.references = [
|
||||
access.addr
|
||||
for access in collector.accesses.values()
|
||||
if access.addr in valid_range and not access.addr in function_range
|
||||
]
|
||||
|
||||
self.test_references = [
|
||||
(access.at, access.addr)
|
||||
for access in collector.accesses.values()
|
||||
if access.addr in valid_range and not access.addr in function_range
|
||||
]
|
||||
|
||||
async def export_function_body(self, exporter, builder: AsyncBuilder):
|
||||
await builder.write(f" {{")
|
||||
await builder.write(f"\tnofralloc")
|
||||
@@ -80,6 +76,15 @@ class ASMFunction(Function):
|
||||
async def export_declaration(self, exporter, builder: AsyncBuilder):
|
||||
assert self.padding == 0
|
||||
|
||||
|
||||
for k,v in self.test_references:
|
||||
symbol_name = "???"
|
||||
symbol = exporter.gst[-1, v]
|
||||
if symbol:
|
||||
symbol_name = symbol.label
|
||||
await builder.write(f"//\t{k:08X}: {v:08X} ({symbol_name})")
|
||||
|
||||
|
||||
await builder.write("#pragma push")
|
||||
await builder.write("#pragma optimization_level 0")
|
||||
await builder.write("#pragma optimizewithasm off")
|
||||
@@ -101,10 +106,6 @@ class ASMFunction(Function):
|
||||
|
||||
blocks = []
|
||||
for symbol in group:
|
||||
#block = Block(
|
||||
# Identifier("lbl", symbol.addr, None),
|
||||
# symbol.addr, symbol.size,
|
||||
# data=section.data_for_symbol(symbol))
|
||||
block = Block(
|
||||
Identifier("lbl", symbol.addr, None),
|
||||
symbol.addr, symbol.size,
|
||||
|
||||
@@ -24,6 +24,40 @@ class Function(Symbol):
|
||||
template_index: int = -1
|
||||
asm: bool = False
|
||||
|
||||
@property
|
||||
def uses_any_templates(self):
|
||||
if self.func_name and self.func_name.has_template:
|
||||
return True
|
||||
|
||||
is_templated = [False]
|
||||
def callback(tp, depth):
|
||||
if isinstance(tp, NamedType):
|
||||
is_templated[0] |= tp.has_template
|
||||
if is_templated[0]:
|
||||
return True
|
||||
|
||||
if self.return_type:
|
||||
self.return_type.traverse(callback, 0)
|
||||
for arg_type in self.argument_types:
|
||||
arg_type.traverse(callback, 0)
|
||||
|
||||
return is_templated[0]
|
||||
|
||||
@property
|
||||
def uses_class_template(self):
|
||||
return self.func_name and self.func_name.has_template
|
||||
|
||||
@property
|
||||
def is_static(self):
|
||||
static = super().is_static
|
||||
if not static:
|
||||
return False
|
||||
|
||||
if not self.func_name:
|
||||
return True
|
||||
|
||||
return not self.uses_any_templates
|
||||
|
||||
@property
|
||||
def label(self):
|
||||
return self.identifier.label
|
||||
@@ -96,13 +130,23 @@ class Function(Symbol):
|
||||
without_template: bool = False,
|
||||
comment_arguments: bool = False,
|
||||
template_args: List[str] = None):
|
||||
# prints internal references for the function
|
||||
if False:
|
||||
if not forward:
|
||||
refs = self.internal_references(exporter.context, exporter.gst)
|
||||
await builder.write(f"/* internal references (count {len(refs)})")
|
||||
for ref in refs:
|
||||
await builder.write(f"// {ref.addr:08X} {ref.label}")
|
||||
await builder.write(f"// {self.is_static} {self.uses_any_templates}")
|
||||
|
||||
lines = []
|
||||
def callback(tp, depth):
|
||||
pad = '\t' * depth
|
||||
template = False
|
||||
if isinstance(tp, NamedType):
|
||||
template = tp.has_template
|
||||
lines.append(f"// {pad} {tp.type()} {template}")
|
||||
|
||||
if self.return_type:
|
||||
self.return_type.traverse(callback, 0)
|
||||
for arg_type in self.argument_types:
|
||||
arg_type.traverse(callback, 0)
|
||||
|
||||
for line in lines:
|
||||
await builder.write(line)
|
||||
|
||||
declspec = "extern \"C\" "
|
||||
if not original and self.is_demangled():
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
import struct
|
||||
|
||||
from dataclasses import dataclass, field
|
||||
from typing import List, Set, Dict
|
||||
from pathlib import Path
|
||||
|
||||
from ...builder import AsyncBuilder
|
||||
from ...disassemble import AccessCollector
|
||||
from ... import util
|
||||
from .. import static_analyze
|
||||
from ..base import *
|
||||
from ..symbol import *
|
||||
from .base import *
|
||||
from .asm import *
|
||||
|
||||
@dataclass(eq=False)
|
||||
class SInitFunction(ASMFunction):
|
||||
async def export_declaration(self, exporter, builder: AsyncBuilder):
|
||||
await super().export_declaration(exporter, builder)
|
||||
|
||||
await builder.write("#pragma push")
|
||||
await builder.write("#pragma force_active on")
|
||||
await builder.write(f"#pragma section \".ctors$15\"")
|
||||
await builder.write(f"__declspec(section \".ctors$15\") void* const _ctors_{self.addr:08X} = (void*){self.label};")
|
||||
await builder.write("#pragma pop")
|
||||
await builder.write("")
|
||||
|
||||
@staticmethod
|
||||
def create(section, group):
|
||||
# TODO: This code is the same as ASMFunction.create
|
||||
first = group[0]
|
||||
last = group[-1]
|
||||
start = first.start
|
||||
end = last.end
|
||||
|
||||
blocks = []
|
||||
for symbol in group:
|
||||
block = Block(
|
||||
Identifier("lbl", symbol.addr, None),
|
||||
symbol.addr, symbol.size,
|
||||
)
|
||||
blocks.append(block)
|
||||
|
||||
# Calculate additional padding from zeros at the end of the function
|
||||
data = section.get_data(start, end)
|
||||
end_padding = 0
|
||||
last_data = list(util.chunks(data, 4))
|
||||
for x in last_data[::-1]:
|
||||
if struct.unpack('>I', x)[0] != 0:
|
||||
break
|
||||
end_padding += 4
|
||||
|
||||
if end_padding > 0:
|
||||
data = data[:-end_padding]
|
||||
end -= end_padding
|
||||
|
||||
return SInitFunction(
|
||||
Identifier("func", start, first.name),
|
||||
addr=start,
|
||||
size=end - start,
|
||||
padding=last.padding + end_padding,
|
||||
alignment=0,
|
||||
blocks=blocks,
|
||||
source=first.source,
|
||||
data=data)
|
||||
@@ -667,35 +667,9 @@ def analyze_function(instructions):
|
||||
|
||||
analyze_block(labels[0], True)
|
||||
|
||||
|
||||
if error:
|
||||
sys.exit(1)
|
||||
|
||||
"""
|
||||
for label, insns in label_groups.items():
|
||||
for xinsn in insns:
|
||||
addr, insn, _ = xinsn
|
||||
if not insn:
|
||||
continue
|
||||
|
||||
regs = registers[addr]
|
||||
if insn.id in branch_inst:
|
||||
for op in insn.operands:
|
||||
if op.type == PPC_OP_IMM:
|
||||
references.add(op.value.imm)
|
||||
|
||||
elif insn.id in {PPC_INS_ADDI, PPC_INS_ORI} and insn.operands[0].reg in regs:
|
||||
value = regs[insn.operands[0].reg]
|
||||
if value:
|
||||
references.add(value)
|
||||
|
||||
elif (is_load_store_reg_offset(insn, None) and insn.operands[1].mem.base in regs):
|
||||
value = regs[insn.operands[1].mem.base]
|
||||
if value != None:
|
||||
value += sign_extend_16(insn.operands[1].mem.disp)
|
||||
references.add(value)
|
||||
"""
|
||||
|
||||
if start == 0x802860CC and False:
|
||||
for label, insns in label_groups.items():
|
||||
final = (child_analyzed[label] == parent_list[label])
|
||||
|
||||
@@ -62,6 +62,7 @@ class Symbol:
|
||||
|
||||
demangled_name: NamedType = None
|
||||
references: Set[int] = field(default_factory=set)
|
||||
is_reachable: bool = False
|
||||
|
||||
def __hash__(self):
|
||||
return hash(self.addr)
|
||||
@@ -91,6 +92,10 @@ class Symbol:
|
||||
def is_static(self):
|
||||
return self.reference_count.static > 0 and self.reference_count.extern == 0 and self.reference_count.rel == 0
|
||||
|
||||
@property
|
||||
def uses_class_template(self):
|
||||
return False
|
||||
|
||||
def add_reference(self, referencer, count=1):
|
||||
self.reference_count.add_reference(self, referencer, count)
|
||||
|
||||
@@ -130,18 +135,26 @@ class Symbol:
|
||||
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("#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$10\") ")
|
||||
#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("#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("#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.force_section:
|
||||
if self.force_section == '.bss':
|
||||
await builder.write_nonewline("SECTION_BSS ")
|
||||
@@ -175,14 +188,21 @@ class Symbol:
|
||||
await builder.write_nonewline("SECTION_EXTABINDEX ")
|
||||
elif self._section == ".ctors":
|
||||
if self.identifier.label == "__init_cpp_exceptions_reference":
|
||||
section = "__declspec(section \".ctors$10\") "
|
||||
#section = "__declspec(section \".ctors$10\") "
|
||||
section = "SECTION_CTORS10 "
|
||||
elif self.identifier.label == "_ctors":
|
||||
section = "__declspec(section \".ctors$10\") "
|
||||
#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 = "__declspec(section \".dtors$10\") "
|
||||
section = "SECTION_DTORS10 "
|
||||
elif self.identifier.label == "__fini_cpp_exceptions_reference":
|
||||
section = "__declspec(section \".dtors$15\") "
|
||||
#section = "__declspec(section \".dtors$15\") "
|
||||
section = "SECTION_DTORS15 "
|
||||
elif self.identifier.label == "__dtors_null_terminator":
|
||||
#section = "__declspec(section \".dtors$15\") "
|
||||
section = "SECTION_DTORS15 "
|
||||
await builder.write_nonewline(section)
|
||||
|
||||
async def export_extern(self, builder: AsyncBuilder):
|
||||
|
||||
@@ -11,6 +11,10 @@ from .reference_array import *
|
||||
|
||||
@dataclass(eq=False)
|
||||
class VirtualTable(ReferenceArray):
|
||||
@property
|
||||
def is_static(self):
|
||||
return False
|
||||
|
||||
def export_reference_value(self, symbol_table, index, addr) -> str:
|
||||
base = super().export_reference_value(symbol_table,index, addr)
|
||||
if index == 0:
|
||||
|
||||
@@ -487,7 +487,8 @@ class AccessCollector(Disassembler):
|
||||
if not self.is_label_candidate(value):
|
||||
return
|
||||
|
||||
if value == 0x8037a118:
|
||||
if insn.address == 0x80143294:
|
||||
print(f"{insn.address:08X}")
|
||||
assert False
|
||||
|
||||
assert not insn.address in self.accesses
|
||||
@@ -509,6 +510,20 @@ class AccessCollector(Disassembler):
|
||||
r2_addr = self.r2AddrInsns[insn.address]
|
||||
r13_addr = self.r13AddrInsns[insn.address]
|
||||
|
||||
"""
|
||||
if address == 0x80143294:
|
||||
print(insn.address in self.splitDataLoads)
|
||||
print(is_load_store_reg_offset(insn, None))
|
||||
if insn.address in self.splitDataLoads:
|
||||
value = self.splitDataLoads[address]
|
||||
rA = insn.reg_name(insn.operands[0].reg)
|
||||
rB = insn.reg_name(insn.operands[1].mem.base)
|
||||
print(f"{value:08X} {rA} {rB}")
|
||||
print(f"{insn.mnemonic} {insn.op_str}")
|
||||
sys.exit(1)
|
||||
"""
|
||||
|
||||
|
||||
if insn.id in {PPC_INS_B, PPC_INS_BL, PPC_INS_BC, PPC_INS_BDZ, PPC_INS_BDNZ}:
|
||||
for op in insn.operands:
|
||||
if op.type == PPC_OP_IMM:
|
||||
|
||||
@@ -37,7 +37,6 @@ class CPPExporter:
|
||||
symbol._section, symbol.identifier.name))
|
||||
|
||||
async def export_section_ctors(self, builder: AsyncBuilder, section: Section):
|
||||
await builder.write("#pragma section \".ctors$10\"")
|
||||
for symbol in section.symbols:
|
||||
if symbol.identifier.label == "__init_cpp_exceptions_reference":
|
||||
await self.export_symbol_header(builder, symbol)
|
||||
@@ -57,12 +56,12 @@ class CPPExporter:
|
||||
continue
|
||||
if symbol.identifier.label == "_ctors":
|
||||
continue
|
||||
# TODO: Not sure about this???
|
||||
await self.export_symbol_header(builder, symbol)
|
||||
await symbol.export_declaration(self, builder)
|
||||
await builder.write("")
|
||||
|
||||
async def export_section_dtors(self, builder: AsyncBuilder, section: Section):
|
||||
await builder.write("#pragma section \".dtors$10\"")
|
||||
for symbol in section.symbols:
|
||||
if symbol.identifier.label == "__destroy_global_chain_reference":
|
||||
await self.export_symbol_header(builder, symbol)
|
||||
@@ -70,7 +69,6 @@ class CPPExporter:
|
||||
await builder.write("")
|
||||
break
|
||||
|
||||
await builder.write("#pragma section \".dtors$15\"")
|
||||
for symbol in section.symbols:
|
||||
if symbol.identifier.label == "__fini_cpp_exceptions_reference":
|
||||
await self.export_symbol_header(builder, symbol)
|
||||
@@ -78,11 +76,20 @@ class CPPExporter:
|
||||
await builder.write("")
|
||||
break
|
||||
|
||||
for symbol in section.symbols:
|
||||
if symbol.identifier.label == "__dtors_null_terminator":
|
||||
await self.export_symbol_header(builder, symbol)
|
||||
await symbol.export_declaration(self, builder)
|
||||
await builder.write("")
|
||||
break
|
||||
|
||||
for symbol in section.symbols:
|
||||
if symbol.identifier.label == "__destroy_global_chain_reference":
|
||||
continue
|
||||
if symbol.identifier.label == "__fini_cpp_exceptions_reference":
|
||||
continue
|
||||
if symbol.identifier.label == "__dtors_null_terminator":
|
||||
continue
|
||||
await self.export_symbol_header(builder, symbol)
|
||||
await symbol.export_declaration(self, builder)
|
||||
await builder.write("")
|
||||
|
||||
@@ -95,6 +95,8 @@ async def export_file_async(module, symbols):
|
||||
f"'lib':{lib_index},"
|
||||
f"'tu':{tu_index},"
|
||||
f"'section':{sec_index},"
|
||||
f"'class_template':{symbol.uses_class_template},"
|
||||
f"'is_reachable':{symbol.is_reachable},"
|
||||
f"'r':[{symbol.reference_count.static},{symbol.reference_count.extern},{symbol.reference_count.rel}],"
|
||||
f"'sh':[{symbol.sda_hack_reference_count.static},{symbol.sda_hack_reference_count.extern},{symbol.sda_hack_reference_count.rel}],"
|
||||
f"'type':{escape_text(type(symbol).__name__)}}},")
|
||||
|
||||
@@ -61,7 +61,7 @@ async def create_library(library: Library):
|
||||
await builder.write(f"\t@echo linking... {target_path}")
|
||||
await builder.write(f"\t@echo $({prefix}_O_FILES) > {input_file}")
|
||||
await builder.write(f"\t@$(LD) -xm l $({prefix}_LDFLAGS) -o {target_path} @{input_file}")
|
||||
await builder.write(f"\t@$(STRIP) -d -R .dead -R .comment {target_path}")
|
||||
#await builder.write(f"\t@$(STRIP) -d -R .dead -R .comment {target_path}")
|
||||
await builder.write("")
|
||||
|
||||
await builder.write(f"{o_path}/%.o: {cpp_path}/%.cpp")
|
||||
@@ -147,7 +147,7 @@ async def create_rel(module: Module):
|
||||
await builder.write(f"{o_path}/%.o: {cpp_path}/%.cpp")
|
||||
await builder.write(f"\t@mkdir -p $(@D)")
|
||||
await builder.write(f"\t$(CC) $(CFLAGS) $({prefix}_CFLAGS) -c -o $@ $<")
|
||||
await builder.write(f"\t$(STRIP) -d -R .dead -R .comment $@")
|
||||
#await builder.write(f"\t$(STRIP) -d -R .dead -R .comment $@")
|
||||
await builder.write("")
|
||||
|
||||
for library in libraries[1:]:
|
||||
@@ -212,7 +212,7 @@ async def create_rel(module: Module):
|
||||
await builder.write(f"{target_path}: $({prefix}_O_FILES)")
|
||||
await builder.write(f"\t@echo $({prefix}_O_FILES) > {input_file}")
|
||||
await builder.write(f"\t$(LD) -xm l $({prefix}_LDFLAGS) -o {target_path} @{input_file}")
|
||||
await builder.write(f"\t$(STRIP) -d -R .dead -R .comment {target_path}")
|
||||
#await builder.write(f"\t$(STRIP) -d -R .dead -R .comment {target_path}")
|
||||
await builder.write("")
|
||||
|
||||
await builder.write(f"{o_path}/%.o: {cpp_path}/%.cpp")
|
||||
|
||||
@@ -203,5 +203,8 @@ def from_group(section: Section, group: List[linker_map.Symbol]) -> Function:
|
||||
if first.size <= 0:
|
||||
return []
|
||||
|
||||
if first.name and first.name.startswith("__sinit_"):
|
||||
return [SInitFunction.create(section, group)]
|
||||
|
||||
# the function was not decompilable
|
||||
return [ASMFunction.create(section, group)]
|
||||
|
||||
@@ -65,7 +65,7 @@ def value_initialized_symbol(section: Section,
|
||||
""" Create symbols from data. This will try to find strings, integers, floats, and other special symbols. """
|
||||
|
||||
# all virtual tables begin with "__vt"
|
||||
if identifier.name and identifier.name.startswith("__vt"):
|
||||
if symbol.name and symbol.name.startswith("__vt"):
|
||||
assert section.name == ".data"
|
||||
assert symbol.size % 4 == 0
|
||||
assert len(padding_data) % 4 == 0
|
||||
@@ -110,17 +110,27 @@ def value_initialized_symbol(section: Section,
|
||||
count += 1
|
||||
|
||||
_ctors_data = padding_data[0:count*4]
|
||||
return [
|
||||
ReferenceArray.create(
|
||||
|
||||
__init_cpp_exceptions_reference = ReferenceArray.create(
|
||||
identifier,
|
||||
symbol.addr,
|
||||
data,
|
||||
bytearray()),
|
||||
ReferenceArray.create(
|
||||
Identifier("_ctors", symbol.addr + 4, "_ctors"),
|
||||
symbol.addr + 4,
|
||||
_ctors_data,
|
||||
bytearray()),
|
||||
bytearray())
|
||||
|
||||
# instead of creating the _ctors ourself we let the linker do it
|
||||
_ctors = ArbitraryData(
|
||||
identifier=Identifier("_xx", symbol.addr + 4, "_ctors"),
|
||||
addr=symbol.addr + 4,
|
||||
size=len(_ctors_data),
|
||||
data=[],
|
||||
data_type=PointerType(VOID),
|
||||
padding=0,
|
||||
padding_data=[],
|
||||
zero_length=True)
|
||||
|
||||
return [
|
||||
__init_cpp_exceptions_reference,
|
||||
_ctors
|
||||
]
|
||||
|
||||
if section.name == ".dtors":
|
||||
@@ -144,7 +154,18 @@ def value_initialized_symbol(section: Section,
|
||||
elif symbol.name == "__fini_cpp_exceptions_reference":
|
||||
assert len(data) == 4
|
||||
assert len(padding_data) == 0
|
||||
return [ReferenceArray.create(identifier, symbol.addr, data, bytearray())]
|
||||
|
||||
__fini_cpp_exceptions_reference = ReferenceArray.create(
|
||||
identifier, symbol.addr, data, bytearray())
|
||||
|
||||
__dtors_null_terminator = ReferenceArray.create(
|
||||
Identifier("_xx", symbol.addr + 4, "__dtors_null_terminator"),
|
||||
symbol.addr + 4, bytearray([0, 0, 0, 0]), bytearray())
|
||||
|
||||
return [
|
||||
__fini_cpp_exceptions_reference,
|
||||
__dtors_null_terminator,
|
||||
]
|
||||
|
||||
if isinstance(symbol.access, FloatLoadAccess):
|
||||
is_float_constant = identifier.name and identifier.name.startswith(
|
||||
|
||||
@@ -200,6 +200,9 @@ def nameFix(context, label_collisions, reference_collisions, dollar_names, symbo
|
||||
symbol.return_type = return_type
|
||||
else:
|
||||
symbol.return_type = return_type
|
||||
|
||||
#if not symbol.uses_class_template:
|
||||
# symbol.identifier.is_name_safe = True
|
||||
else:
|
||||
context.warning(
|
||||
f"one of the demangled parameters could not be converted to data-type.")
|
||||
@@ -213,13 +216,13 @@ def nameFix(context, label_collisions, reference_collisions, dollar_names, symbo
|
||||
context.error(f"\t{p.class_name}")
|
||||
context.error(f"\t{p.to_str()}")
|
||||
|
||||
if symbol.reference_count.extern > 0 or isinstance(symbol, StringBase):
|
||||
if not symbol.is_static or isinstance(symbol, StringBase):
|
||||
label_collisions[symbol.identifier.label] += 1
|
||||
reference_collisions[symbol.identifier.reference] += 1
|
||||
|
||||
|
||||
def nameCollision(context, label_collisions, reference_collisions, parent_name, symbol):
|
||||
if symbol.reference_count.extern > 0 or isinstance(symbol, StringBase):
|
||||
if not symbol.is_static or isinstance(symbol, StringBase):
|
||||
if label_collisions[symbol.identifier.label] > 1 or reference_collisions[symbol.identifier.reference] > 1:
|
||||
obj_prefix = parent_name.replace(
|
||||
"/", "_").replace(".", "_").replace("-", "_")
|
||||
|
||||
@@ -271,7 +271,8 @@ class Dol2AsmSplitter:
|
||||
self.symbol_table.add_section(module, section)
|
||||
|
||||
def combine_symbols(self):
|
||||
print(f"{self.step_count:2} Calculate function alignment and merge unaligned symbols")
|
||||
print(
|
||||
f"{self.step_count:2} Calculate function alignment and merge unaligned symbols")
|
||||
self.step_count += 1
|
||||
|
||||
for module in self.modules:
|
||||
@@ -302,6 +303,8 @@ class Dol2AsmSplitter:
|
||||
for tu in lib.translation_units.values():
|
||||
for section in tu.sections.values():
|
||||
for symbol in section.symbols:
|
||||
if isinstance(symbol, ReferenceArray):
|
||||
continue
|
||||
if not isinstance(symbol, ArbitraryData) and not isinstance(symbol, Integer):
|
||||
continue
|
||||
|
||||
@@ -489,7 +492,9 @@ class Dol2AsmSplitter:
|
||||
entrypoint = self.symbol_table[0, settings.ENTRY_POINT]
|
||||
entrypoint.add_reference(None)
|
||||
|
||||
valid_range = AddressRange(0x00000000, 0xFFFFFFFF)
|
||||
valid_range = AddressRange(
|
||||
self.symbol_table.symbols.begin(),
|
||||
self.symbol_table.symbols.end())
|
||||
|
||||
# these symbols are required to be external, because otherwise the linker will not find them
|
||||
__fini_cpp_exceptions = self.symbol_table[0, 0x8036283C]
|
||||
@@ -500,24 +505,31 @@ class Dol2AsmSplitter:
|
||||
# TODO: Use multiprocessing to speed this up
|
||||
total_rc_step_count = 0
|
||||
for module in self.modules:
|
||||
if not module.index in self.gen_modules:
|
||||
continue
|
||||
for lib in module.libraries.values():
|
||||
for tu in lib.translation_units.values():
|
||||
total_rc_step_count += sum([len(x.symbols)
|
||||
for x in tu.sections.values()])
|
||||
|
||||
sinit_functions = set()
|
||||
entrypoints = {
|
||||
settings.ENTRY_POINT
|
||||
}
|
||||
with Progress(console=get_console(), transient=True, refresh_per_second=1) as progress:
|
||||
task = progress.add_task(
|
||||
f"processing...", total=total_rc_step_count)
|
||||
task1 = progress.add_task(
|
||||
f"step 1...", total=total_rc_step_count)
|
||||
for module in self.modules:
|
||||
if not module.index in self.gen_modules:
|
||||
continue
|
||||
for lib in module.libraries.values():
|
||||
for tu in lib.translation_units.values():
|
||||
count = 0
|
||||
for section in tu.sections.values():
|
||||
for symbol in section.symbols:
|
||||
if isinstance(symbol, SInitFunction):
|
||||
sinit_functions.add(symbol.addr)
|
||||
if symbol.identifier.name == "_prolog":
|
||||
entrypoints.add(symbol.addr)
|
||||
elif symbol.identifier.name == "_epilog":
|
||||
entrypoints.add(symbol.addr)
|
||||
|
||||
symbol.gather_references(
|
||||
self.context, valid_range)
|
||||
references = self.symbol_table.all(
|
||||
@@ -525,7 +537,43 @@ class Dol2AsmSplitter:
|
||||
for reference in references:
|
||||
reference.add_reference(symbol)
|
||||
count += len(section.symbols)
|
||||
progress.update(task, advance=count)
|
||||
progress.update(task1, advance=count)
|
||||
|
||||
|
||||
for module in self.modules:
|
||||
found = set()
|
||||
|
||||
def reachable(current, depth):
|
||||
pad = ' ' * depth
|
||||
if current in found:
|
||||
return
|
||||
|
||||
symbol = self.symbol_table[-1, current]
|
||||
if not symbol:
|
||||
return
|
||||
if symbol._module != module.index:
|
||||
return
|
||||
|
||||
#print(f"{pad}{current:08X} {symbol.identifier.name} ({len(symbol.references)})")
|
||||
|
||||
found.add(current)
|
||||
for reference in symbol.references:
|
||||
reachable(reference, depth + 1)
|
||||
|
||||
|
||||
for entrypoint in entrypoints:
|
||||
reachable(entrypoint, 0)
|
||||
for function in sinit_functions:
|
||||
reachable(function, 0)
|
||||
|
||||
for lib in module.libraries.values():
|
||||
for tu in lib.translation_units.values():
|
||||
for section in tu.sections.values():
|
||||
for symbol in section.symbols:
|
||||
if symbol.addr in sinit_functions:
|
||||
continue
|
||||
if symbol.addr in found:
|
||||
symbol.is_reachable = True
|
||||
|
||||
def library_paths(self):
|
||||
print(f"{self.step_count:2} Determine library paths")
|
||||
|
||||
@@ -72,3 +72,25 @@ class PaddingArrayType(Type):
|
||||
@staticmethod
|
||||
def create(base: Type, size: int, padding: int) -> "PaddingArrayType":
|
||||
return PaddingArrayType(base, size, padding)
|
||||
|
||||
@dataclass(frozen=True, eq=True)
|
||||
class ZeroArrayType(Type):
|
||||
""" Array Type with zero/unknown length """
|
||||
|
||||
base: Type
|
||||
|
||||
def __hash__(self):
|
||||
return hash((self.base, "ZERO_ARRAY_TYPE"))
|
||||
|
||||
def type(self) -> str:
|
||||
assert False
|
||||
|
||||
def dependencies(self) -> Set["Type"]:
|
||||
assert False
|
||||
|
||||
def decl(self, label: str) -> str:
|
||||
return f"{self.base.type()} {label}[]"
|
||||
|
||||
@staticmethod
|
||||
def create(base: Type) -> "ZeroArrayType":
|
||||
return ZeroArrayType(base)
|
||||
@@ -26,6 +26,9 @@ class ClassName:
|
||||
for template in self.templates:
|
||||
template.traverse(callback, depth)
|
||||
|
||||
@property
|
||||
def has_templates(self) -> bool:
|
||||
return len(self.templates) > 0
|
||||
|
||||
@dataclass(frozen=True, eq=True)
|
||||
class NamedType(Type):
|
||||
@@ -57,7 +60,7 @@ class NamedType(Type):
|
||||
|
||||
@property
|
||||
def has_template(self) -> bool:
|
||||
return any([len(x.templates) > 0 for x in self.names])
|
||||
return any([x.has_templates for x in self.names])
|
||||
|
||||
@property
|
||||
def has_class(self) -> bool:
|
||||
|
||||
Reference in New Issue
Block a user