示例#1
0
 def assert_not_ambiguous(self):
     if self.is_absolute_addr() and (self & 0x80000000) == 0:
         raise InvalidOperationException(
             f"{self.value} is ambiguous: absolute, top bit not set")
     if self.is_relative_addr() and (self & 0x80000000) != 0:
         raise InvalidOperationException(
             f"{self.value} is ambiguous: relative, top bit set")
示例#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
示例#3
0
    def pack_gecko_codes(self) -> list:
        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:
            raise NotImplementedError(
                "Conditional writes not yet supported for gecko")
        elif self.address >= 0x90000000:
            raise NotImplementedError(
                "MEM2 writes not yet supported for gecko")

        code = ((self.address.value & 0x1FFFFFF) << 32) | self.value.value

        if self.valueType == WriteCommand.Type.Value16:
            return list(code | (0x2000000 << 32))
        elif self.valueType == WriteCommand.Type.Value32:
            return list(code | (0x4000000 << 32))
        elif self.valueType == WriteCommand.Type.Pointer:
            return list(code | (0x4000000 << 32))

        raise InvalidOperationException(
            f"Invalid command type {self.valueType} specified")
示例#4
0
    def pack_riivo(self) -> str:
        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:
            self.original.assert_not_relative()

            if self.valueType == WriteCommand.Type.Value8:
                return f"<memory offset='0x{self.address:X8}' value='{self.value:X2}' original='{self.original:X2}' />"
            elif self.valueType == WriteCommand.Type.Value16:
                return f"<memory offset='0x{self.address:X8}' value='{self.value:X4}' original='{self.original:X4}' />"
            elif self.valueType == WriteCommand.Type.Value32:
                return f"<memory offset='0x{self.address:X8}' value='{self.value:X8}' original='{self.original:X8}' />"
            elif self.valueType == WriteCommand.Type.Pointer:
                return f"<memory offset='0x{self.address:X8}' value='{self.value:X8}' original='{self.original:X8}' />"

        else:
            if self.valueType == WriteCommand.Type.Value8:
                return f"<memory offset='0x{self.address:X8}' value='{self.value:X2}' />"
            elif self.valueType == WriteCommand.Type.Value16:
                return f"<memory offset='0x{self.address:X8}' value='{self.value:X4}' />"
            elif self.valueType == WriteCommand.Type.Value32:
                return f"<memory offset='0x{self.address:X8}' value='{self.value:X8}' />"
            elif self.valueType == WriteCommand.Type.Pointer:
                return f"<memory offset='0x{self.address:X8}' value='{self.value:X8}' />"

        raise InvalidOperationException(
            f"Invalid command type {self.valueType} specified")
示例#5
0
    def load_from_linker(self, linker: Linker):
        if self.codeSize > 0:
            raise InvalidOperationException(
                "This Kamek binary already has stuff in it")

        self.mapper = linker

        # Extract only code/data sections
        linker._memory.seek(linker.outputStart.value -
                            linker.baseAddress.value)

        self.rawCode = BytesIO(linker._memory.read(linker.outputSize.value))

        self.baseAddr = linker.baseAddress
        self.bssSize = linker.bssSize

        for _key in linker._symbolSizes:
            self.symbolSizes[_key] = linker._symbolSizes[_key]

        self.add_relocs_as_commands(linker._fixups)

        for cmd in linker._kamekHooks:
            self.apply_hook(cmd)

        self.apply_static_commands()
示例#6
0
    def add_relocs_as_commands(self, relocs: list):
        for rel in relocs:
            if rel.source in self.commands:
                raise InvalidOperationException(
                    f"Duplicate commands for address {rel.source.value:X}")

            self.commands[rel.source] = RelocCommand(rel.source, rel.dest,
                                                     rel.type)
示例#7
0
    def apply_to_dol(self, dol: DolFile):
        if self.baseAddr.type == KWord.Types.RELATIVE:
            raise InvalidOperationException(
                "Cannot pack a dynamically linked binary into a DOL")

        dol.append_section(TextSection(self.baseAddr.value, self.rawCode))

        for _key in self.commands:
            self.commands[_key].apply_to_dol(dol, self.mapper)
示例#8
0
    def apply_hook(self, hookData):
        hook = KHook.create(hookData, self.mapper)
        for cmd in hook.commands:
            if cmd.address in self.commands:
                raise InvalidOperationException(
                    f"Duplicate commands for address {cmd.address.value:X}")

            self.commands[cmd.address] = cmd
        self.hooks.append(hook)
示例#9
0
    def _kamek_use_reloc(self, _type: ELFFlags.Reloc, source: KWord,
                         dest: KWord):
        if source < self.kamekStart or source >= self.kamekEnd:
            return False
        elif _type != ELFFlags.Reloc.R_PPC_ADDR32:
            raise InvalidOperationException(
                "Unsupported relocation type in the Kamek hook data section")

        self._kamekRelocs[source] = dest
        return True
示例#10
0
    def apply(self, f: "KamekBinary") -> bool:
        funcSize = f.get_symbol_size(self.address)
        funcEnd = self.address + (funcSize - 4)

        if funcSize < 4:
            raise InvalidOperationException("Queried function is too small")

        if f.read_u32(funcEnd) != 0x4E800020:
            raise InvalidOperationException("Function does not end in blr")

        instrLoc = self.address
        while instrLoc < funcEnd:
            insn = f.read_u32(instrLoc)
            if (insn & 0xFC00FFFF == 0x4C000020):
                raise InvalidOperationException(
                    "Function contains a return partway through")
            instrLoc += 4

        self.endAddress = funcEnd
        if self.is_equal_reloc_absolute() and f.contains(self.address):
            f.write_u32(self.endAddress.value, self._generate_instruction())
            return True
        else:
            return False
示例#11
0
 def assert_not_absolute(self):
     if self.is_absolute_addr():
         raise InvalidOperationException(
             f"KWord {self.value} must not be a absolute address in this context"
         )
示例#12
0
 def assert_not_relative(self):
     if self.is_relative_addr():
         raise InvalidOperationException(
             f"KWord {self.value} must not be a relative address in this context"
         )
示例#13
0
 def assert_not_value(self):
     if self.is_value():
         raise InvalidOperationException(
             f"KWord {self.value} must not be a value in this context")