.dead section fix

This commit is contained in:
Julgodis
2021-03-31 23:22:32 +02:00
parent a868b6ae56
commit b999714187
8427 changed files with 1951354 additions and 667431 deletions
+37 -2
View File
@@ -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
+3
View File
@@ -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 *
+29 -28
View File
@@ -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,
+51 -7
View File
@@ -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():
+65
View File
@@ -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)
-26
View File
@@ -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])
+32 -12
View File
@@ -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):
+4
View File
@@ -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:
+16 -1
View File
@@ -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:
+10 -3
View File
@@ -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("")
+2
View File
@@ -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__)}}},")
+3 -3
View File
@@ -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")
+3
View File
@@ -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)]
+31 -10
View File
@@ -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(
+5 -2
View File
@@ -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("-", "_")
+57 -9
View File
@@ -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")
+22
View File
@@ -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)
+4 -1
View File
@@ -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: