Пример #1
0
    def __init__(self, proj, name, target, cond, addr):
        super(CallInstruction, self).__init__(name, addr)

        # XXX: IDIOM [CALL HL]
        if hasattr(target, 'value') and target.value == 0x00A0:
            target = placeholders.HL

        # XXX: IDIOM [CALL BC]
        if hasattr(target, 'value') and target.value == 0x0CDA:
            target = placeholders.BC

        # XXX: IDIOM [CALL LONG E:HL]
        if hasattr(target, 'value') and target.value == 0x008A:
            target = ComputedProcAddress(placeholders.E, placeholders.HL)

        self.cond = cond
        if hasattr(target, 'getAddress'):
            self.targetAddr = target.getAddress()
            self.target = ProcAddress(self.targetAddr)
        elif hasattr(target, 'value') and target.value is not None:
            self.targetAddr = address.fromVirtualAndCurrent(target.value, addr)
            self.target = ProcAddress(self.targetAddr)
        else:
            self.targetAddr = address.fromVirtual(0x4000)  # XXX: ambiguous address
            self.target = target

        self.target_depset = proj.database.procInfo(self.targetAddr).depset

        self.returns_used = ALL_REGS
        self.constant_params = dict()
Пример #2
0
    def render(self, r):
        """
        Writes the procedure info, name, the callers, callees etc
        :param r:
        """
        with r.lineAddress(self.addr), r.comment():
            r.write("Menu: /home | /data | /jump | /proc | /bank")
            r.hline()

            r.startNewLine()
            r.write("Procedure flow ")
            r.writeSymbol(self.addr, 'procedure')

            r.startNewLine()
            r.write("  This procedure is called by: ")
            r.writeList(ProcAddress(x) for x in sorted(self.info.callers))

            r.startNewLine()
            r.write("  This procedure calls: ")
            r.writeList(ProcAddress(x) for x in sorted(self.proc.calls()))

            r.hline()

        with r.indent():
            self.proc.render(r)
Пример #3
0
    def render(self, renderer):
        c = self.proj.database.connection.cursor()

        c.execute('select addr from procs where has_ambig_calls=1')
        renderer.startNewLine()
        renderer.add('ambig calls:')
        with renderer.indent():
            for addr, in c.fetchall():
                renderer.startNewLine()
                ProcAddress(addr).render(renderer)

        c.execute('select addr from procs where suspicious_switch=1')
        renderer.startNewLine()
        renderer.add('suspicious switch:')
        with renderer.indent():
            for addr, in c.fetchall():
                renderer.startNewLine()
                ProcAddress(addr).render(renderer)

        c.execute('select addr from procs where has_suspicious_instr=1')
        renderer.startNewLine()
        renderer.add('suspicious instr:')
        with renderer.indent():
            for addr, in c.fetchall():
                renderer.startNewLine()
                ProcAddress(addr).render(renderer)

        c.close()
Пример #4
0
    def optimizedWithContext(self, ctx):

        self.target = self.target.optimizedWithContext(ctx)
        if hasattr(self.target, 'getAddress'):
            self.targetAddr = self.target.getAddress()
        elif hasattr(self.target, 'value') and self.target.value is not None:
            self.targetAddr = address.fromVirtualAndCurrent(self.target.value, self.addr)
            self.target = ProcAddress(self.targetAddr)
        else:
            pass  # XXX

        deps = self.getDependencySet()

        ins = joinRegisters(deps.reads - set(['mem']))

        for param in ins:
            if ctx.hasConstantValue(param):
                self.constant_params[param] = ctx.getValue(param)

        for w in deps.writes:
            ctx.setValueComplex(w)

        # TODO: XXX
        if self.targetAddr.virtual() == 0x07B9:
            if 'A' in self.constant_params:
                ctx.setValue('ROMBANK', self.constant_params['A'])

        return self
Пример #5
0
    def render(self, renderer):
        bank_name = "{:04X}".format(self.bank)

        c = self.proj.database.connection.cursor()

        renderer.startNewLine()
        renderer.add('public interface:')
        c.execute(
            'select destination from calls where substr(source, 0, 5)<>? and substr(destination, 0, 5)=? group by destination order by destination',
            (bank_name, bank_name))
        with renderer.indent():
            for addr, in c.fetchall():
                renderer.startNewLine()
                ProcAddress(addr).render(renderer)

        renderer.startNewLine()
        renderer.add('dependencies:')
        c.execute(
            'select destination from calls where substr(source, 0, 5)=? and substr(destination, 0, 5)<>? group by source order by source',
            (bank_name, bank_name))
        with renderer.indent():
            for addr, in c.fetchall():
                renderer.startNewLine()
                ProcAddress(addr).render(renderer)

        renderer.startNewLine()
        renderer.add('reads:')
        c.execute(
            'select addr from memref where substr(proc, 0, 5)=? and type=? group by addr order by addr',
            (bank_name, 'read'))
        with renderer.indent():
            for addr, in c.fetchall():
                renderer.startNewLine()
                DataAddress(addr).render(renderer)

        renderer.startNewLine()
        renderer.add('writes:')
        c.execute(
            'select addr from memref where substr(proc, 0, 5)=? and type=? group by addr order by addr',
            (bank_name, 'write'))
        with renderer.indent():
            for addr, in c.fetchall():
                renderer.startNewLine()
                DataAddress(addr).render(renderer)

        c.close()
Пример #6
0
    def render(self, r):
        with r.lineAddress(self.addr), r.comment():
            r.hline()

            r.startNewLine()
            r.write("data ")
            r.writeSymbol(self.addr, 'data')

            r.startNewLine()
            r.write("  reads: ")
            r.writeList(ProcAddress(x) for x in sorted(self.reads))

            r.startNewLine()
            r.write("  writes: ")
            r.writeList(ProcAddress(x) for x in sorted(self.writes))

            r.hline()
Пример #7
0
    def addFakeBlock(self, proj, addr):
        pos = len(self.blocks)
        self.block_id_at_addr[addr] = pos

        instr = TailCall(proj, ProcAddress(addr))

        from .flowcontrol import Block
        self.blocks.append(Block([instr]))

        self.block_starts.append(addr)
        self._childs[pos] = [None]
Пример #8
0
    def render(self, r):

        with r.lineAddress(self.addr), r.comment():
            r.hline()

            r.startNewLine()
            r.write("procedure ")
            r.writeSymbol(self.addr, 'procedure')

            r.startNewLine()
            r.write("  callers: ")
            r.writeList(ProcAddress(x) for x in sorted(self.info.callers))

            r.startNewLine()
            r.write("  calls: ")
            r.writeList(ProcAddress(x) for x in sorted(self.info.calls))

            r.hline()
        with r.indent():
            self.proc.render(r)
Пример #9
0
class JumpInstruction(Instruction):
    def __init__(self, name, target, cond, addr, reads, writes):
        super(JumpInstruction, self).__init__(name, addr)

        self._reads = reads
        self._writes = writes

        self.cond = cond

        if hasattr(target, 'getAddress'):
            self.targetAddr = target.getAddress()
            self.target = target
        elif target.value is not None:
            self.targetAddr = address.fromVirtualAndCurrent(target.value, addr)
            self.target = ProcAddress(self.targetAddr)
        else:
            self.targetAddr = None
            self.target = target

    def optimizedWithContext(self, ctx):
        return JumpInstruction(self.name, self.target.optimizedWithContext(ctx), self.cond, self.addr, self._reads, self._writes)

    def getDependencies(self, needed):
        return (needed - self._writes) | self._reads

    def getDependencySet(self):
        return DependencySet(self._reads, self._writes)

    def hasContinue(self):
        try:
            return not self.cond.alwaysTrue()
        except AttributeError:
            return True

    def jumps(self):
        if self.targetAddr and not self.targetAddr.isAmbiguous():
            return set([self.targetAddr])
        else:
            return set()

    def allJumps(self):
        if self.targetAddr:
            return [self.targetAddr]
        else:
            return []

    def operands(self):
        if not self.cond.alwaysTrue():
            return [self.target, self.cond]
        else:
            return [self.target]
Пример #10
0
    def __init__(self, proj, addr):
        self.addr = addr
        self.targets = []

        for i in range(256):
            a = addr.offset(i * 2)
            lo = proj.rom.get(a)
            hi = proj.rom.get(a.offset(1))
            value = address.fromVirtualAndCurrent((hi << 8) | lo, addr)

            if not value.inPhysicalMem():
                break

            self.targets.append(ProcAddress(value))
Пример #11
0
    def __init__(self, name, target, cond, addr, reads, writes):
        super(JumpInstruction, self).__init__(name, addr)

        self._reads = reads
        self._writes = writes

        self.cond = cond

        if hasattr(target, 'getAddress'):
            self.targetAddr = target.getAddress()
            self.target = target
        elif target.value is not None:
            self.targetAddr = address.fromVirtualAndCurrent(target.value, addr)
            self.target = ProcAddress(self.targetAddr)
        else:
            self.targetAddr = None
            self.target = target
Пример #12
0
    def __init__(self, proj, addr):
        self.addr = addr
        self.targets = []
        romconfig = Config(proj.filename, rom=True)
        jumptables = romconfig.get(["Analysis", "Jumptable-List"])
        try:
            size = jumptables[str(addr)]
        except KeyError:
            size = 256
        for i in range(size):
            a = addr.offset(i * 2)
            lo = proj.rom.get(a)
            hi = proj.rom.get(a.offset(1))
            value = address.fromVirtualAndCurrent((hi << 8) | lo, addr)

            if not value.inPhysicalMem():
                print "breaking"
                break

            self.targets.append(ProcAddress(value))
Пример #13
0
class CallInstruction(Instruction):
    def __init__(self, proj, name, target, cond, addr):
        super(CallInstruction, self).__init__(name, addr)

        # XXX: IDIOM [CALL HL]
        if hasattr(target, 'value') and target.value == 0x00A0:
            target = placeholders.HL

        # XXX: IDIOM [CALL BC]
        if hasattr(target, 'value') and target.value == 0x0CDA:
            target = placeholders.BC

        # XXX: IDIOM [CALL LONG E:HL]
        if hasattr(target, 'value') and target.value == 0x008A:
            target = ComputedProcAddress(placeholders.E, placeholders.HL)

        self.cond = cond
        if hasattr(target, 'getAddress'):
            self.targetAddr = target.getAddress()
            self.target = ProcAddress(self.targetAddr)
        elif hasattr(target, 'value') and target.value is not None:
            self.targetAddr = address.fromVirtualAndCurrent(target.value, addr)
            self.target = ProcAddress(self.targetAddr)
        else:
            self.targetAddr = address.fromVirtual(0x4000)  # XXX: ambiguous address
            self.target = target

        self.target_depset = proj.database.procInfo(self.targetAddr).depset

        self.returns_used = ALL_REGS
        self.constant_params = dict()

    def getDependencies(self, needed):
        #return flow.getProcDeps(self.targetAddr, needed)
        deps = self.getDependencySet()
        return (needed - deps.writes) | deps.reads

    def getDependencySet(self):
        reads = set(self.target_depset.reads)
        for r in joinRegisters(reads):
            if r in self.constant_params:
                reads -= splitRegister(r)
        return DependencySet(reads, self.target_depset.writes)

    def optimizeDependencies(self, needed):
        self.returns_used = needed & self.getDependencySet().writes
        return self

    def optimizedWithContext(self, ctx):

        self.target = self.target.optimizedWithContext(ctx)
        if hasattr(self.target, 'getAddress'):
            self.targetAddr = self.target.getAddress()
        elif hasattr(self.target, 'value') and self.target.value is not None:
            self.targetAddr = address.fromVirtualAndCurrent(self.target.value, self.addr)
            self.target = ProcAddress(self.targetAddr)
        else:
            pass  # XXX

        deps = self.getDependencySet()

        ins = joinRegisters(deps.reads - set(['mem']))

        for param in ins:
            if ctx.hasConstantValue(param):
                self.constant_params[param] = ctx.getValue(param)

        for w in deps.writes:
            ctx.setValueComplex(w)

        # TODO: XXX
        if self.targetAddr.virtual() == 0x07B9:
            if 'A' in self.constant_params:
                ctx.setValue('ROMBANK', self.constant_params['A'])

        return self

    def calls(self):
        if self.targetAddr.inPhysicalMem() and not self.targetAddr.isAmbiguous():
            return set([self.targetAddr])
        else:
            return set([])

    def operands(self):
        if not self.cond.alwaysTrue():
            return [self.target, self.cond]
        else:
            return [self.target]

    def fillParamIfKnown(self, param):
        if param in self.constant_params:
            return param + '=' + str(self.constant_params[param])
        else:
            return param

    def signature(self):
        x = ''
        if not self.cond.alwaysTrue():
            x = 'CONDITIONAL'

        depset = self.getDependencySet().onlyRegisters()
        ins = joinRegisters(depset.reads - set(['mem']))
        outs = joinRegisters(self.returns_used - set(['mem']))

        ins |= set(param+'='+str(self.constant_params[param]) for param in self.constant_params)

        ins = ', '.join(sorted(ins))
        outs = ', '.join(sorted(outs))
        if ins:
            ins = ' @ (' + ins + ')'
        if not outs:
            outs = 'void'
        return x + ins + ' -> ' + outs