diff options
| author | Julgodis <> | 2021-03-31 23:22:32 +0200 |
|---|---|---|
| committer | Julgodis <> | 2021-03-31 23:22:38 +0200 |
| commit | b999714187d934636004d3d93e1ed1da792d6f80 (patch) | |
| tree | b89ce29aafb588cc0d191343c915ae1447d1c7a6 /tools/libdol2asm/data/function | |
| parent | a868b6ae56e5d586f31a445f47b45f5ac039c74a (diff) | |
.dead section fix
Diffstat (limited to 'tools/libdol2asm/data/function')
| -rw-r--r-- | tools/libdol2asm/data/function/__init__.py | 1 | ||||
| -rw-r--r-- | tools/libdol2asm/data/function/asm.py | 57 | ||||
| -rw-r--r-- | tools/libdol2asm/data/function/base.py | 58 | ||||
| -rw-r--r-- | tools/libdol2asm/data/function/sinit.py | 65 |
4 files changed, 146 insertions, 35 deletions
diff --git a/tools/libdol2asm/data/function/__init__.py b/tools/libdol2asm/data/function/__init__.py index 394419b9d6..c390847b02 100644 --- a/tools/libdol2asm/data/function/__init__.py +++ b/tools/libdol2asm/data/function/__init__.py @@ -2,3 +2,4 @@ from .base import * from .asm import * from .ret import * +from .sinit import * diff --git a/tools/libdol2asm/data/function/asm.py b/tools/libdol2asm/data/function/asm.py index e19ebbda03..c4e50a83a2 100644 --- a/tools/libdol2asm/data/function/asm.py +++ b/tools/libdol2asm/data/function/asm.py @@ -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, diff --git a/tools/libdol2asm/data/function/base.py b/tools/libdol2asm/data/function/base.py index cf822e53af..98b0d5b51f 100644 --- a/tools/libdol2asm/data/function/base.py +++ b/tools/libdol2asm/data/function/base.py @@ -25,6 +25,40 @@ class Function(Symbol): 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(): diff --git a/tools/libdol2asm/data/function/sinit.py b/tools/libdol2asm/data/function/sinit.py new file mode 100644 index 0000000000..8f6214dfea --- /dev/null +++ b/tools/libdol2asm/data/function/sinit.py @@ -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) |
