summaryrefslogtreecommitdiff
path: root/tools/libdol2asm/data/function
diff options
context:
space:
mode:
authorJulgodis <>2021-03-31 23:22:32 +0200
committerJulgodis <>2021-03-31 23:22:38 +0200
commitb999714187d934636004d3d93e1ed1da792d6f80 (patch)
treeb89ce29aafb588cc0d191343c915ae1447d1c7a6 /tools/libdol2asm/data/function
parenta868b6ae56e5d586f31a445f47b45f5ac039c74a (diff)
.dead section fix
Diffstat (limited to 'tools/libdol2asm/data/function')
-rw-r--r--tools/libdol2asm/data/function/__init__.py1
-rw-r--r--tools/libdol2asm/data/function/asm.py57
-rw-r--r--tools/libdol2asm/data/function/base.py58
-rw-r--r--tools/libdol2asm/data/function/sinit.py65
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)