Exemplo n.º 1
0
class Disassembly:
    def __init__(self, snapshot, ctl_parser, final=False, defb_size=8, defb_mod=1, zfill=False, defm_width=66, asm_hex=False, asm_lower=False):
        self.disassembler = Disassembler(snapshot, defb_size, defb_mod, zfill, defm_width, asm_hex, asm_lower)
        self.ctl_parser = ctl_parser
        if asm_hex:
            if asm_lower:
                self.address_fmt = '{0:04x}'
            else:
                self.address_fmt = '{0:04X}'
        else:
            self.address_fmt = '{0}'
        self.entry_map = {}
        self.build(final)

    def build(self, final=False):
        self.instructions = {}
        self.entries = []
        self._create_entries()
        self.org = self.entries[0].address
        if final:
            self._calculate_references()

    def _create_entries(self):
        for block in self.ctl_parser.get_blocks():
            if block.start in self.entry_map:
                entry = self.entry_map[block.start]
                self.entries.append(entry)
                for instruction in entry.instructions:
                    self.instructions[instruction.address] = instruction
                continue
            title = block.title
            if block.ctl == 'c':
                title = title or 'Routine at {}'.format(self._address_str(block.start))
            elif block.ctl in 'bw':
                title = title or 'Data block at {}'.format(self._address_str(block.start))
            elif block.ctl == 't':
                title = title or 'Message at {}'.format(self._address_str(block.start))
            elif block.ctl == 'g':
                title = title or 'Game status buffer entry at {}'.format(self._address_str(block.start))
            elif block.ctl in 'us':
                title = title or 'Unused'
            elif block.ctl == 'i' and (block.description or block.registers or block.blocks[0].header):
                title = title or 'Ignored'
            for sub_block in block.blocks:
                address = sub_block.start
                if sub_block.ctl in 'cBT':
                    base = sub_block.sublengths[0][1]
                    instructions = self.disassembler.disassemble(sub_block.start, sub_block.end, base)
                elif sub_block.ctl in 'bgstuw':
                    sublengths = sub_block.sublengths
                    if sublengths[0][0]:
                        if sub_block.ctl == 's':
                            length = sublengths[0][0]
                        else:
                            length = sum([s[0] for s in sublengths])
                    else:
                        length = sub_block.end - sub_block.start
                    instructions = []
                    while address < sub_block.end:
                        end = min(address + length, sub_block.end)
                        if sub_block.ctl == 't':
                            instructions += self.disassembler.defm_range(address, end, sublengths)
                        elif sub_block.ctl == 'w':
                            instructions += self.disassembler.defw_range(address, end, sublengths)
                        elif sub_block.ctl == 's':
                            instructions.append(self.disassembler.defs(address, end, sublengths))
                        else:
                            instructions += self.disassembler.defb_range(address, end, sublengths)
                        address += length
                else:
                    instructions = self.disassembler.ignore(sub_block.start, sub_block.end)
                sub_block.instructions = instructions
                for instruction in instructions:
                    self.instructions[instruction.address] = instruction
                    instruction.asm_directives = sub_block.asm_directives.get(instruction.address, ())

            sub_blocks = []
            i = 0
            while i < len(block.blocks):
                sub_block = block.blocks[i]
                i += 1
                sub_blocks.append(sub_block)
                if sub_block.multiline_comment is not None:
                    end, sub_block.comment = sub_block.multiline_comment
                    while i < len(block.blocks) and block.blocks[i].start < end:
                        next_sub_block = block.blocks[i]
                        sub_block.instructions += next_sub_block.instructions
                        sub_block.end = next_sub_block.end
                        i += 1

            entry = Entry(title, block.description, block.ctl, sub_blocks,
                          block.registers, block.end_comment, block.asm_directives,
                          block.ignoreua_directives)
            self.entry_map[entry.address] = entry
            self.entries.append(entry)
        for i, entry in enumerate(self.entries[1:]):
            self.entries[i].next = entry

    def remove_entry(self, address):
        if address in self.entry_map:
            del self.entry_map[address]

    def contains_entry_asm_directive(self, asm_dir):
        for entry in self.entries:
            for directive, value in entry.asm_directives:
                if directive == asm_dir:
                    return True

    def _calculate_references(self):
        for entry in self.entries:
            for instruction in entry.instructions:
                instruction.referrers = []
        for entry in self.entries:
            for instruction in entry.instructions:
                operation = instruction.operation
                if operation.upper().startswith(('DJ', 'JR', 'JP', 'CA', 'RS')):
                    addr_str = get_address(operation)
                    if addr_str:
                        callee = self.instructions.get(parse_int(addr_str))
                        if callee:
                            callee.add_referrer(entry)

    def _address_str(self, address):
        return self.address_fmt.format(address)
Exemplo n.º 2
0
class Disassembly:
    def __init__(self,
                 snapshot,
                 ctl_parser,
                 config=None,
                 final=False,
                 defb_size=8,
                 defb_mod=1,
                 zfill=False,
                 defm_width=66,
                 asm_hex=False,
                 asm_lower=False):
        ctl_parser.apply_asm_data_directives(snapshot)
        self.disassembler = Disassembler(snapshot, defb_size, defb_mod, zfill,
                                         defm_width, asm_hex, asm_lower)
        self.ctl_parser = ctl_parser
        if asm_hex:
            if asm_lower:
                self.address_fmt = '{0:04x}'
            else:
                self.address_fmt = '{0:04X}'
        else:
            self.address_fmt = '{0}'
        self.entry_map = {}
        self.config = config or {}
        self.build(final)

    def build(self, final=False):
        self.instructions = {}
        self.entries = []
        self._create_entries()
        if self.entries:
            self.org = self.entries[0].address
        else:
            self.org = None
        if final:
            self._calculate_references()

    def _create_entries(self):
        for block in self.ctl_parser.get_blocks():
            if block.start in self.entry_map:
                entry = self.entry_map[block.start]
                self.entries.append(entry)
                for instruction in entry.instructions:
                    self.instructions[instruction.address] = instruction
                continue
            title = block.title
            if not title:
                ctl = block.ctl
                if ctl != 'i' or block.description or block.registers or block.blocks[
                        0].header:
                    name = 'Title-' + ctl
                    title = format_template(self.config.get(name, ''),
                                            name,
                                            address=self._address_str(
                                                block.start))
            for sub_block in block.blocks:
                address = sub_block.start
                if sub_block.ctl in 'cBT':
                    base = sub_block.sublengths[0][1]
                    instructions = self.disassembler.disassemble(
                        sub_block.start, sub_block.end, base)
                elif sub_block.ctl in 'bgstuw':
                    sublengths = sub_block.sublengths
                    if sublengths[0][0]:
                        if sub_block.ctl == 's':
                            length = sublengths[0][0]
                        else:
                            length = sum([s[0] for s in sublengths])
                    else:
                        length = sub_block.end - sub_block.start
                    instructions = []
                    while address < sub_block.end:
                        end = min(address + length, sub_block.end)
                        if sub_block.ctl == 't':
                            instructions += self.disassembler.defm_range(
                                address, end, sublengths)
                        elif sub_block.ctl == 'w':
                            instructions += self.disassembler.defw_range(
                                address, end, sublengths)
                        elif sub_block.ctl == 's':
                            instructions.append(
                                self.disassembler.defs(address, end,
                                                       sublengths))
                        else:
                            instructions += self.disassembler.defb_range(
                                address, end, sublengths)
                        address += length
                else:
                    instructions = self.disassembler.ignore(
                        sub_block.start, sub_block.end)
                sub_block.instructions = instructions
                for instruction in instructions:
                    self.instructions[instruction.address] = instruction
                    instruction.asm_directives = sub_block.asm_directives.get(
                        instruction.address, ())

            sub_blocks = []
            i = 0
            while i < len(block.blocks):
                sub_block = block.blocks[i]
                i += 1
                sub_blocks.append(sub_block)
                if sub_block.multiline_comment is not None:
                    end, sub_block.comment = sub_block.multiline_comment
                    while i < len(
                            block.blocks) and block.blocks[i].start < end:
                        next_sub_block = block.blocks[i]
                        sub_block.instructions += next_sub_block.instructions
                        sub_block.end = next_sub_block.end
                        i += 1

            entry = Entry(block.header, title, block.description, block.ctl,
                          sub_blocks, block.registers, block.end_comment,
                          block.footer, block.asm_directives,
                          block.ignoreua_directives)
            self.entry_map[entry.address] = entry
            self.entries.append(entry)
        for i, entry in enumerate(self.entries[1:]):
            self.entries[i].next = entry

    def remove_entry(self, address):
        if address in self.entry_map:
            del self.entry_map[address]

    def _calculate_references(self):
        for entry in self.entries:
            for instruction in entry.instructions:
                instruction.referrers = []
        for entry in self.entries:
            for instruction in entry.instructions:
                operation = instruction.operation
                if operation.upper().startswith(
                    ('DJ', 'JR', 'JP', 'CA', 'RS')):
                    addr_str = get_address(operation)
                    if addr_str:
                        callee = self.instructions.get(parse_int(addr_str))
                        if callee:
                            callee.add_referrer(entry)

    def _address_str(self, address):
        return self.address_fmt.format(address)
Exemplo n.º 3
0
class Disassembly:
    def __init__(self, snapshot, ctl_parser, config=None, final=False, defb_size=8, defb_mod=1,
                 zfill=False, defm_width=66, asm_hex=False, asm_lower=False):
        ctl_parser.apply_asm_data_directives(snapshot)
        self.disassembler = Disassembler(snapshot, defb_size, defb_mod, zfill, defm_width, asm_hex, asm_lower)
        self.ctl_parser = ctl_parser
        if asm_hex:
            if asm_lower:
                self.address_fmt = '{0:04x}'
            else:
                self.address_fmt = '{0:04X}'
        else:
            self.address_fmt = '{0}'
        self.entry_map = {}
        self.config = config or {}
        self.build(final)

    def build(self, final=False):
        self.instructions = {}
        self.entries = []
        self._create_entries()
        if self.entries:
            self.org = self.entries[0].address
        else:
            self.org = None
        if final:
            self._calculate_references()

    def _create_entries(self):
        for block in self.ctl_parser.get_blocks():
            if block.start in self.entry_map:
                entry = self.entry_map[block.start]
                self.entries.append(entry)
                for instruction in entry.instructions:
                    self.instructions[instruction.address] = instruction
                continue
            title = block.title
            if not any(title):
                ctl = block.ctl
                if ctl != 'i' or block.description or block.registers or block.blocks[0].header:
                    name = 'Title-' + ctl
                    title = [format_template(self.config.get(name, ''), name, address=self._address_str(block.start))]
            for sub_block in block.blocks:
                address = sub_block.start
                if sub_block.ctl in 'cBT':
                    base = sub_block.sublengths[0][1]
                    instructions = self.disassembler.disassemble(sub_block.start, sub_block.end, base)
                elif sub_block.ctl in 'bgstuw':
                    sublengths = sub_block.sublengths
                    if sublengths[0][0]:
                        if sub_block.ctl == 's':
                            length = sublengths[0][0]
                        else:
                            length = sum([s[0] for s in sublengths])
                    else:
                        length = sub_block.end - sub_block.start
                    instructions = []
                    while address < sub_block.end:
                        end = min(address + length, sub_block.end)
                        if sub_block.ctl == 't':
                            instructions += self.disassembler.defm_range(address, end, sublengths)
                        elif sub_block.ctl == 'w':
                            instructions += self.disassembler.defw_range(address, end, sublengths)
                        elif sub_block.ctl == 's':
                            instructions += self.disassembler.defs(address, end, sublengths)
                        else:
                            instructions += self.disassembler.defb_range(address, end, sublengths)
                        address += length
                else:
                    instructions = self.disassembler.ignore(sub_block.start, sub_block.end)
                self._add_instructions(sub_block, instructions)

            sub_blocks = []
            i = 0
            while i < len(block.blocks):
                sub_block = block.blocks[i]
                i += 1
                sub_blocks.append(sub_block)
                if sub_block.multiline_comment is not None:
                    end, sub_block.comment = sub_block.multiline_comment
                    while i < len(block.blocks) and block.blocks[i].start < end:
                        next_sub_block = block.blocks[i]
                        sub_block.instructions += next_sub_block.instructions
                        sub_block.end = next_sub_block.end
                        i += 1

            entry = Entry(block.header, title, block.description, block.ctl, sub_blocks,
                          block.registers, block.end_comment, block.footer, block.asm_directives,
                          block.ignoreua_directives)
            self.entry_map[entry.address] = entry
            self.entries.append(entry)
        for i, entry in enumerate(self.entries[1:]):
            self.entries[i].next = entry

    def remove_entry(self, address):
        if address in self.entry_map:
            del self.entry_map[address]

    def _add_instructions(self, sub_block, instructions):
        sub_block.instructions = instructions
        for instruction in instructions:
            self.instructions[instruction.address] = instruction
            instruction.asm_directives = sub_block.asm_directives.get(instruction.address, ())
            instruction.label = None
            for asm_dir in instruction.asm_directives:
                if asm_dir.startswith(AD_LABEL + '='):
                    instruction.label = asm_dir[6:]
                    if instruction.label.startswith('*'):
                        instruction.ctl = '*'
                    break

    def _calculate_references(self):
        for entry in self.entries:
            for instruction in entry.instructions:
                instruction.referrers = []
        for entry in self.entries:
            for instruction in entry.instructions:
                operation = instruction.operation
                if operation.upper().startswith(('DJ', 'JR', 'JP', 'CA', 'RS')):
                    addr_str = get_address(operation)
                    if addr_str:
                        callee = self.instructions.get(parse_int(addr_str))
                        if callee and (entry.ctl != 'u' or callee.entry == entry) and callee.label != '':
                            callee.add_referrer(entry)

    def _address_str(self, address):
        return self.address_fmt.format(address)