Ejemplo n.º 1
0
    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")
Ejemplo n.º 2
0
    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
Ejemplo n.º 3
0
    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
Ejemplo n.º 4
0
    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)
Ejemplo n.º 5
0
    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)
Ejemplo n.º 6
0
    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())
Ejemplo n.º 7
0
 def write_arguments(self, io: BytesIO):
     self.target.assert_not_ambiguous()
     write_uint32(io, self.target.value)
Ejemplo n.º 8
0
 def write_u32(self, address: int, val: int) -> int:
     self.seek(address - self.baseAddr.value)
     write_uint32(self.rawCode, val)