def apply_to_dol(self, dol: DolFile, linker: "Linker"): self.address.assert_absolute() self.target.assert_absolute() if self.id == Command.KCmdID.Rel24: delta = self.target - self.address dol.seek(self.address.value) insn = (delta & 0x3FFFFFC) | (read_uint32(dol) & 0xFC000003) dol.seek(self.address.value) write_uint32(dol, insn.value) elif self.id == Command.KCmdID.Addr32: dol.seek(self.address.value) write_uint32(dol, self.target.value) elif self.id == Command.KCmdID.Addr16Lo: dol.seek(self.address.value) write_uint16(dol, self.target.value & 0xFFFF) elif self.id == Command.KCmdID.Addr16Hi: dol.seek(self.address.value) write_uint16(dol, (self.target.value >> 16) & 0xFFFF) elif self.id == Command.KCmdID.Addr16Ha: aTarget = (self.target.value >> 16) & 0xFFFF if self.target & 0x8000 == 0x8000: aTarget += 1 dol.seek(self.address.value) write_uint16(dol, aTarget) else: raise NotImplementedError("Unrecognized relocation type")
def apply_to_dol(self, dol: DolFile, linker: "Linker"): funcSize = linker._symbolSizes[self.address] funcEnd = self.address + (funcSize - 4) if funcSize < 4: raise InvalidOperationException("Queried function is too small") dol.seek(funcEnd) if read_uint32(dol) != 0x4E800020: raise InvalidOperationException("Function does not end in blr") instrLoc = self.address dol.seek(instrLoc) while instrLoc < funcEnd: insn = read_uint32(dol) if (insn & 0xFC00FFFF == 0x4C000020): raise InvalidOperationException( "Function contains a return partway through") instrLoc += 4 self.endAddress = funcEnd try: dol.resolve_address(self.address) dol.seek(self.endAddress.value) write_uint32(dol, self._generate_instruction()) return True except UnmappedAddressError: return False
def pack(self) -> BytesIO: _packedBinary = BytesIO() _packedBinary.write(b"Kamek\x00\x00\x01") write_uint32(_packedBinary, self.bssSize.value) write_uint32(_packedBinary, self.codeSize) _packedBinary.write(self.rawCode.getvalue()) for _key in self.commands: cmd = (self.commands[_key].id << 24) & 0xFFFFFFFF address = self.commands[_key].address if address.is_relative_addr(): if address > 0xFFFFFF: raise InvalidCommandException( f"Given address {address} is too high for packed command" ) write_uint32(_packedBinary, cmd | address.value) else: write_uint32(_packedBinary, cmd | 0xFFFFFE) write_uint32(_packedBinary, address.value) self.commands[_key].write_arguments(_packedBinary) _packedBinary.seek(0) return _packedBinary
def write_arguments(self, io: BytesIO): if self.valueType == WriteCommand.Type.Pointer: self.value.assert_not_ambiguous() else: self.value.assert_value() write_uint32(io, self.value.value) if self.original is not None: self.original.assert_not_relative() write_uint32(io, self.original.value)
def apply_to_dol(self, dol: DolFile, linker: "Linker"): self.address.assert_absolute() if self.valueType == WriteCommand.Type.Pointer: self.value.assert_absolute() else: self.value.assert_value() if self.original is not None: shouldPatch = False if self.valueType == WriteCommand.Type.Value8: dol.seek(self.address.value) shouldPatch = self.original == read_ubyte(dol) elif self.valueType == WriteCommand.Type.Value16: dol.seek(self.address.value) shouldPatch = self.original == read_uint16(dol) elif self.valueType == WriteCommand.Type.Value32: dol.seek(self.address.value) shouldPatch = self.original == read_uint32(dol) elif self.valueType == WriteCommand.Type.Pointer: dol.seek(self.address.value) shouldPatch = self.original == read_uint32(dol) if not shouldPatch: return if self.valueType == WriteCommand.Type.Value8: dol.seek(self.address.value) write_ubyte(dol, self.value.value) elif self.valueType == WriteCommand.Type.Value16: dol.seek(self.address.value) write_uint16(dol, self.value.value) elif self.valueType == WriteCommand.Type.Value32: dol.seek(self.address.value) write_uint32(dol, self.value.value) elif self.valueType == WriteCommand.Type.Pointer: dol.seek(self.address.value) write_uint32(dol, self.value.value)
def apply_to_dol(self, dol: DolFile, linker: "Linker"): self.address.assert_absolute() self.target.assert_absolute() dol.seek(self.address.value) write_uint32(dol, self._generate_instruction())
def write_arguments(self, io: BytesIO): self.target.assert_not_ambiguous() write_uint32(io, self.target.value)
def write_u32(self, address: int, val: int) -> int: self.seek(address - self.baseAddr.value) write_uint32(self.rawCode, val)