Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

make rvl/nand relocatable #166

Merged
merged 4 commits into from
Apr 1, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions build.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import subprocess
import sys

from elftools.elf.elffile import ELFFile
from multiprocessing.dummy import Pool as ThreadPool, Lock
import multiprocessing

Expand All @@ -23,6 +24,7 @@
from mkwutil.sections import DOL_SECTIONS
from mkwutil.verify_object_file import verify_object_file
from mkwutil.gen_lcf import gen_lcf
from mkwutil.mkw_binary_patch import patch_elf
from mkwutil.pack_main_dol import pack_main_dol
from mkwutil.pack_staticr_rel import pack_staticr_rel
from mkwutil.verify_main_dol import verify_dol
Expand Down Expand Up @@ -363,6 +365,9 @@ def link_dol(o_files: list[Path]):
elf_path = dest_dir / "main.elf"
map_path = dest_dir / "main.map"
link(elf_path, o_files, dst_lcf_path, map_path)
# Execute patches.
with open(elf_path, "rb+") as elf_file:
patch_elf(elf_file)
# Convert ELF to DOL.
dol_path = dest_dir / "main.dol"
pack_main_dol(elf_path, dol_path)
Expand Down
50 changes: 50 additions & 0 deletions mkwutil/mkw_binary_patch.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import argparse
from dataclasses import dataclass
from pathlib import Path
import struct
from typing import Iterator

from elftools.elf.elffile import ELFFile, Section as ELFSection


@dataclass
class BinaryPatch:
vaddr: int
size: int
val: int

LAYOUT = ">IIQ"

def from_struct_fields(fields) -> "BinaryPatch":
return BinaryPatch(fields[0], fields[1], fields[2])


def load_binary_patches(elf: ELFFile) -> Iterator[BinaryPatch]:
patches: ELFSection = elf.get_section_by_name("mkw_patches")
if not patches:
return
for patch_fields in struct.iter_unpack(BinaryPatch.LAYOUT, patches.data()):
yield BinaryPatch.from_struct_fields(patch_fields)


def patch_elf(elf_file):
elf = ELFFile(elf_file)
for patch in load_binary_patches(elf):
offsets = list(elf.address_offsets(patch.vaddr, patch.size))
if len(offsets) != 1 or patch.size > 8:
continue
file_offset = offsets[0]
elf_file.seek(file_offset)
elf_file.write(struct.pack(">Q", patch.val)[8 - patch.size :])


def main():
parser = argparse.ArgumentParser()
parser.add_argument("elf", type=Path)
args = parser.parse_args()
with open(args.elf, "rb+") as elf_file:
patch_elf(elf_file)


if __name__ == "__main__":
main()
2 changes: 1 addition & 1 deletion mkwutil/pack_main_dol.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

def segment_is_dummy(seg):
"""Returns whether segment contains dummy info."""
return seg["p_vaddr"] == 0xA000_0000 # Binary blobs section
return seg["p_vaddr"] in (0xA000_0000, 0xB000_0000) # Binary blobs section


def segment_is_text(seg):
Expand Down
46 changes: 36 additions & 10 deletions mkwutil/tools/lint_inline_asm.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,12 +75,37 @@ def on_match(self, match: re.Match, violation: LintViolation):
pass


class SdataAbsoluteRule(BaseRegexRule):
class SdataAbsoluteRefRule(BaseRegexRule):
def __init__(self, dol: Optional[DolBinary]):
self.dol = dol
self.r13 = 0x8038CC00
super().__init__(
"sdata/sbss reference",
"sdata/sbss absolute addressing",
r"^\s+(addi r\d{1,2}, r13, (-?(?:0x)?[0-9a-f]+));.*$",
)

def on_match(self, match: re.Match, violation: LintViolation):
try:
self._on_match(match, violation)
except Exception as e:
violation.comment = str(e)

def _on_match(self, match: re.Match, violation: LintViolation):
source = int(match.group(2))
address = self.r13 + source
values = ""
if self.dol:
data = self.dol.virtual_read(address, 4) or b"\x00\x00\x00\x00"
values = "~> %#010x " % (struct.unpack(">I", data)[0])
violation.comment = f"{values}@ {hex(address)}"


class SdataAbsoluteAccessRule(BaseRegexRule):
def __init__(self, dol: Optional[DolBinary]):
self.dol = dol
self.r13 = 0x8038CC00
super().__init__(
"sdata/sbss absolute access",
r"^\s+((lwz|stw|lhz|lha|sth|lbz|stb) r\d{1,2}, (-?0x[0-9a-f]+)\(r13\));.*$",
)

Expand All @@ -99,26 +124,26 @@ def _on_match(self, match: re.Match, violation: LintViolation):
if self.dol:
if opcode == "lwz":
data = self.dol.virtual_read(address, 4) or b"\x00\x00\x00\x00"
values = "~> %#08x " % (struct.unpack(">I", data)[0])
values = "~> %#010x " % (struct.unpack(">I", data)[0])
elif opcode == "lhz":
data = self.dol.virtual_read(address, 2) or b"\x00\x00"
values = "~> %#04x " % (struct.unpack(">H", data)[0])
values = "~> %#06x " % (struct.unpack(">H", data)[0])
elif opcode == "lha":
data = self.dol.virtual_read(address, 2) or b"\x00\x00"
values = "~> %#04x " % (struct.unpack(">h", data)[0])
values = "~> %#06x " % (struct.unpack(">h", data)[0])
elif opcode == "lbz":
data = self.dol.virtual_read(address, 1) or b"\x00"
values = "~> %#02x " % data[0]
values = "~> %#04x " % data[0]

violation.comment = f"{values}@ {hex(address)}"


class Sdata2AbsoluteRule(BaseRegexRule):
class Sdata2AbsoluteAccessRule(BaseRegexRule):
def __init__(self, dol: Optional[DolBinary]):
self.dol = dol
self.r2 = 0x8038EFA0
super().__init__(
"sdata2 reference",
"sdata2 absolute access",
r"^\s+((lfs|lfd|lhz) [rf]\d{1,2}, (-?0x[0-9a-f]+)\(r2\));.*$",
)

Expand Down Expand Up @@ -212,8 +237,9 @@ def main():
)

linters = [
SdataAbsoluteRule(dol),
Sdata2AbsoluteRule(dol),
SdataAbsoluteAccessRule(dol),
SdataAbsoluteRefRule(dol),
Sdata2AbsoluteAccessRule(dol),
]
formatter = get_lint_formatter(args.pretty, args.short)
for source_path in source_paths:
Expand Down
4 changes: 4 additions & 0 deletions pack/dol.lcf.j2
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ MEMORY {
text : origin = 0x80004000
// Dummy address
binary_blobs : origin = 0xA0000000
mkw_patches : origin = 0xB0000000
}
SECTIONS {
GROUP:{
Expand All @@ -24,6 +25,9 @@ extabindex_ ALIGN(0x20):{}
GROUP:{
binary_blobs ALIGN(0x20):{}
} > binary_blobs
GROUP: {
mkw_patches ALIGN(0x20):{}
} > mkw_patches

_stack_addr = (_f_sbss2 + SIZEOF(.sbss2) + 65536 + 0x7) & ~0x7;
_stack_end = _f_sbss2 + SIZEOF(.sbss2);
Expand Down
15 changes: 10 additions & 5 deletions pack/dol_objects.txt
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,7 @@ out/ppcArch.o
out/dol/text_8012e6d4_80169bcc.o
out/fs.o
out/dol/text_8016b49c_80192f7c.o
out/dol/data_802826d7_8028f058.o
out/dol/data_802826d7_8028e9f0.o
out/dol/sdata_803857f6_80385a08.o
out/dol/sbss_80386448_803867e8.o
out/ipcMain.o
Expand All @@ -245,21 +245,26 @@ out/rvlMemExpHeap.o
out/rvlMemFrmHeap.o
out/rvlMemUnitHeap.o
out/dol/bss_80346d18_803481b0.o
out/dol/sbss_8038683c_803868a0.o
out/dol/sbss_8038683c_80386840.o
out/dol/sdata2_803884a4_80388860.o
out/rvlMemAllocator.o
out/rvlMemList.o
out/rvlMtx.o
out/rvlMtx2.o
out/rvlVec.o
out/dol/sdata_80385a10_80385a98.o
out/dol/sdata2_803888b4_803888b8.o
out/rvlQuat.o
out/nand.o
out/rvlNand1.o
out/rvlNand2.o
out/dol/rodata_80252c84_80252dd0.o
out/dol/sbss_80386844_80386848.o
out/rvlNand3.o
out/dol/text_8019f1a8_801a05b8.o
out/dol/data_8028ec3b_8028f058.o
out/dol/sdata_80385a64_80385a98.o
out/dol/sbss_80386858_803868a0.o
out/osAlarm.o
out/osAlloc.o
out/dol/rodata_80252c84_80252dd0.o
out/dol/data_8028f068_8028f320.o
out/dol/sdata_80385a9c_80385aa0.o
out/osArena.o
Expand Down
4 changes: 3 additions & 1 deletion pack/dol_slices.csv
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,9 @@ enabled,strip,name,initStart,initEnd,extabStart,extabEnd,extabindexStart,extabin
1,,source/rvl/mtx/rvlMtx2.c,,,,,,,0x8019a9c4,0x8019abe4,,,,,,,,,,,,,,,0x80388890,0x803888a8,,
1,,source/rvl/mtx/rvlVec.c,,,,,,,0x8019abe4,0x8019ae08,,,,,,,,,,,,,,,0x803888a8,0x803888b4,,
1,,source/rvl/mtx/rvlQuat.c,,,,,,,0x8019ae08,0x8019b314,,,,,0x80252c78,0x80252c84,,,,,,,,,0x803888b8,0x803888d0,,
1,,source/rvl/nand/nand.c,,,,,,,0x8019b314,0x8019f1a8,,,,,,,,,,,,,,,,,,
1,,source/rvl/nand/rvlNand1.c,,,,,,,0x8019b314,0x8019c6ec,,,,,,,,,,,0x80385a10,0x80385a18,,,,,,
1,,source/rvl/nand/rvlNand2.c,,,,,,,0x8019c6ec,0x8019daa0,,,,,,,0x8028e9f0,0x8028ea20,,,0x80385a18,0x80385a28,0x80386840,0x80386844,,,,
1,,source/rvl/nand/rvlNand3.c,,,,,,,0x8019daa0,0x8019f1a8,,,,,,,0x8028ea20,0x8028ec3b,,,0x80385a28,0x80385a64,0x80386848,0x80386858,,,,
1,,source/rvl/os/osAlarm.c,,,,,,,0x801a05b8,0x801a0d9c,,,,,,,0x8028f058,0x8028f068,,,,,0x803868a0,0x803868a8,,,,
1,,source/rvl/os/osAlloc.c,,,,,,,0x801a0d9c ,0x801a10a4 ,,,,,,,,,,,0x80385a98,0x80385a9c,0x803868a8,0x803868b8,,,,
1,,source/rvl/os/osArena.c,,,,,,,0x801a10a4 ,0x801a1138,,,,,,,,,,,0x80385aa0,0x80385aa8,0x803868b8,0x803868c0,,,,
Expand Down
13 changes: 13 additions & 0 deletions source/decomp.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,26 @@
#endif

#ifdef __CWCC__

#pragma section "binary_blobs"
#define SECTION_BINARY_BLOBS __declspec(section "binary_blobs")
#define MARK_BINARY_BLOB(name, start, stop) \
SECTION_BINARY_BLOBS static const char MARK_BINARY_BLOB_##name[] = \
"BINARY_BLOB: " #name "\t" #start "\t" #stop "\n" \
__attribute__((force_export))

struct __mkw_patch {
void* ptr;
unsigned int len;
unsigned long long val;
};

#pragma section "mkw_patches"
#define SECTION_MKW_PATCHES __declspec(section "mkw_patches")
#define MKW_PATCH_WORD(target, val) \
SECTION_MKW_PATCHES static const struct __mkw_patch __mkw_patch_##target \
__attribute__((force_export)) = {&target, 4, val}

// Compiler intrinsics.
#include <eabi.h>
#else
Expand Down
Loading