Пример #1
0
 def __init__(self, machine):
     self.machine = machine
     self.cpu = machine.get_cpu()
     self.label_mgr = machine.get_label_mgr()
     self.disasm = DisAsm(machine)
     # state
     self.mem_tracer = None
Пример #2
0
def machine_disasm_create_test():
    disasm = DisAsm.create()
    buf = b"\x4e\x75"
    assert disasm.disassemble_raw(0, buf) == (2, "rts")
    disasm = DisAsm.create("68020")
    buf = b"\x60\xff\x11\x22\x33\x44"
    assert disasm.disassemble_raw(0, buf) == (6, "bra     $11223346; (2+)")
Пример #3
0
def machine_disasm_block_test():
    mach = Machine()
    disasm = DisAsm(mach)
    buf = b"\x4e\x75" + b"\x10\x1c" + b"\x48\xe7\x3f\x3e"
    assert disasm.disassemble_block(buf, 0x100) == [
        (0x100, [0x4e75], "rts"), (0x102, [0x101c], "move.b  (A4)+, D0"),
        (0x104, [0x48e7, 0x3f3e], "movem.l D2-D7/A2-A6, -(A7)")
    ]
Пример #4
0
def machine_disasm_default_test():
  mach = Machine()
  disasm = DisAsm(mach)
  mem = mach.get_mem()
  cpu = mach.get_cpu()
  traps = mach.get_traps()
  # trap without func
  mem.w16(0, 0xa123)
  assert disasm.disassemble(0) == (2, "PyTrap  #$123")
  # trap with func
  def bla(opcode, pc):
    pass
  tid = traps.setup(bla)
  mem.w16(2, 0xa000 | tid)
  assert disasm.disassemble(2) == (2, "PyTrap  #$%03x ; bla" % tid)
  traps.free(tid)
Пример #5
0
 def __init__(self, machine):
   self.machine = machine
   self.cpu = machine.get_cpu()
   self.label_mgr = machine.get_label_mgr()
   self.disasm = DisAsm(machine)
   # state
   self.mem_tracer = None
Пример #6
0
def machine_disasm_block_dump_test():
    mach = Machine()
    disasm = DisAsm(mach)
    buf = b"\x4e\x75" + b"\x10\x1c" + b"\x48\xe7\x3f\x3e" + b"\x48\xe7"
    code = disasm.disassemble_block(buf, 0x100)
    result = []

    def store(line):
        result.append(line)

    disasm.dump_block(code, store)
    assert result == [
        "00000100:  4e75                  rts",
        "00000102:  101c                  move.b  (A4)+, D0",
        "00000104:  48e7 3f3e             movem.l D2-D7/A2-A6, -(A7)"
    ]
Пример #7
0
def machine_disasm_default_test():
    mach = Machine()
    disasm = DisAsm(mach)
    mem = mach.get_mem()
    cpu = mach.get_cpu()
    traps = mach.get_traps()
    # trap without func
    mem.w16(0, 0xa123)
    assert disasm.disassemble(0) == (2, "PyTrap  #$123")

    # trap with func

    def bla(opcode, pc):
        pass

    tid = traps.setup(bla)
    mem.w16(2, 0xa000 | tid)
    assert disasm.disassemble(2) == (2, "PyTrap  #$%03x ; bla" % tid)
    traps.free(tid)
Пример #8
0
def machine_disasm_raw_test():
    mach = Machine()
    disasm = DisAsm(mach)
    buf = b"\x4e\x75"
    assert disasm.disassemble_raw(0, buf) == (2, "rts")
    buf = b"\x10\x1c"
    assert disasm.disassemble_raw(0, buf) == (2, "move.b  (A4)+, D0")
    buf = b"\x48\xe7\x3f\x3e"
    assert disasm.disassemble_raw(0, buf) == (4, "movem.l D2-D7/A2-A6, -(A7)")
    # too short buffer
    buf = b"\x48\xe7"
    assert disasm.disassemble_raw(0, buf) == (0, "")
Пример #9
0
def machine_disasm_line_test():
    mach = Machine()
    disasm = DisAsm(mach)
    buf = b"\x4e\x75"
    assert disasm.disassemble_line(0x100, buf) == (0x100, [0x4e75], "rts")
    buf = b"\x10\x1c"
    assert disasm.disassemble_line(0x200, buf) == (0x200, [0x101c],
                                                   "move.b  (A4)+, D0")
    buf = b"\x48\xe7\x3f\x3e"
    assert disasm.disassemble_line(0x300,
                                   buf) == (0x300, [0x48e7, 0x3f3e],
                                            "movem.l D2-D7/A2-A6, -(A7)")
    # too short buffer
    buf = b"\x48\xe7"
    assert disasm.disassemble_line(0, buf) == (0, [], "")
Пример #10
0
class TraceManager(object):
    trace_val_str = ("%02x      ", "%04x    ", "%08x")

    def __init__(self, machine):
        self.machine = machine
        self.cpu = machine.get_cpu()
        self.label_mgr = machine.get_label_mgr()
        self.disasm = DisAsm(machine)
        # state
        self.mem_tracer = None

    def parse_config(self, cfg):
        if not cfg:
            return True
        if cfg.vamos_ram:
            self.setup_vamos_ram_trace()
        if cfg.memory:
            self.setup_cpu_mem_trace()
        if cfg.instr:
            with_regs = cfg.reg_dump
            self.setup_cpu_instr_trace(with_regs)
        return True

    def setup_vamos_ram_trace(self):
        mem = self.machine.get_mem()
        self.mem_tracer = TraceMemory(mem, self)
        if not log_mem_int.isEnabledFor(logging.INFO):
            log_mem_int.setLevel(logging.INFO)
        # replace machine mem with trace memory
        self.machine.set_mem(self.mem_tracer)

    def setup_cpu_mem_trace(self):
        self.machine.set_cpu_mem_trace_hook(self.trace_cpu_mem)
        if not log_mem.isEnabledFor(logging.INFO):
            log_mem.setLevel(logging.INFO)

    def setup_cpu_instr_trace(self, with_regs):
        if not log_instr.isEnabledFor(logging.INFO):
            log_instr.setLevel(logging.INFO)
        cpu = self.cpu
        state = CPUState()
        if with_regs:

            def instr_hook():
                # add register dump
                state.get(cpu)
                res = state.dump()
                for r in res:
                    log_instr.info(r)
                # disassemble line
                pc = cpu.r_reg(REG_PC)
                self.trace_code_line(pc)

        else:

            def instr_hook():
                # disassemble line
                pc = cpu.r_reg(REG_PC)
                self.trace_code_line(pc)

        self.machine.set_instr_hook(instr_hook)

    # trace callback from CPU core
    def trace_cpu_mem(self, mode, width, addr, value=0):
        self._trace_mem(log_mem, mode, width, addr, value)
        return 0

    def trace_int_mem(self, mode, width, addr, value=0, text="", addon=""):
        self._trace_mem(log_mem_int, mode, width, addr, value, text, addon)

    def trace_int_block(self, mode, addr, size, text="", addon=""):
        info, label = self._get_mem_info(addr)
        log_mem_int.info("%s(B): %06x: +%06x   %6s  [%s] %s", mode, addr, size,
                         text, info, addon)

    def trace_code_line(self, pc):
        label, sym, src, addon = self._get_disasm_info(pc)
        _, txt = self.disasm.disassemble(pc)
        if sym is not None:
            log_instr.info("%s%s:", " " * 40, sym)
        if src is not None:
            log_instr.info("%s%s", " " * 50, src)
        log_instr.info("%-40s  %06x    %-20s  %s" % (label, pc, txt, addon))

    # ----- internal -----

    def _get_disasm_info(self, addr):
        if not self.label_mgr:
            return "N/A", None, None, ""
        label = self.label_mgr.get_label(addr)
        sym = None
        src = None
        addon = ""
        if label:
            rel_addr = addr - label.addr
            if isinstance(label, LabelSegment):
                rel_addr = rel_addr - 8  # real start of code in segment
                sym, src = self._get_segment_info(label.segment, rel_addr)
            mem = "@%06x +%06x %s" % (label.addr, rel_addr, label.name)
            if isinstance(label, LabelLib):
                delta, fd_name = self._get_lib_short_info(addr, label)
                mem += "(-%d)" % delta
                if fd_name:
                    addon = "; " + fd_name
        else:
            mem = "N/A"
        return mem, sym, src, addon

    def _get_segment_info(self, segment, rel_addr):
        sym = segment.find_symbol(rel_addr)
        info = segment.find_debug_line(rel_addr)
        if info is None:
            src = None
        else:
            f = info.get_file()
            src_file = f.get_src_file()
            src_line = info.get_src_line()
            src = "[%s:%d]" % (src_file, src_line)
        return sym, src

    def _trace_mem(self, log, mode, width, addr, value, text="", addon=""):
        val = self.trace_val_str[width] % int(value)
        info, label = self._get_mem_info(addr)
        if text == "" and addon == "" and label is not None:
            text, addon = self._get_label_extra(label, mode, addr, width,
                                                value)
        log.info(
            "%s(%d): %06x: %s  %6s  [%s] %s",
            mode,
            2**width,
            addr,
            val,
            text,
            info,
            addon,
        )

    def _get_mem_info(self, addr, width=None):
        if not self.label_mgr:
            return "??", None
        label = self.label_mgr.get_label(addr)
        if label is not None:
            txt = "@%06x +%06x %s" % (label.addr, addr - label.addr,
                                      label.name)
            return txt, label
        else:
            return "??", None

    def _get_label_extra(self, label, mode, addr, width, value):
        if isinstance(label, LabelLib):
            text, addon = self._get_lib_extra(label, mode, addr, width, value)
            if text:
                return text, addon
        if isinstance(label, LabelStruct):
            return self._get_struct_extra(label, addr, width)
        else:
            return "", ""

    def _get_struct_extra(self, label, addr, width):
        delta = addr - label.struct_begin
        if delta >= 0 and delta < label.struct_size:
            struct = label.struct(None, addr)
            st, field, f_delta = struct.get_struct_field_for_offset(delta)

            type_name = struct.get_type_name()
            name = st.get_field_path_name(field)
            type_sig = field.type_sig
            addon = "%s+%d = %s(%s)+%d" % (type_name, delta, name, type_sig,
                                           f_delta)
            return "Struct", addon
        else:
            return "", ""

    op_jmp = 0x4EF9
    op_reset = 0x04E70

    def _get_fd_signature(self, fd, bias):
        if fd is not None:
            f = fd.get_func_by_bias(bias)
            if f is not None:
                return f.get_str()

    def _get_lib_extra(self, label, mode, addr, width, value):
        # inside jump table
        if addr < label.base_addr:
            delta = label.base_addr - addr
            slot = delta // 6
            rel = delta % 6
            if rel == 0:
                addon = "-%d  [%d]" % (delta, slot)
            else:
                addon = "-%d  [%d]+%d" % (delta, slot, rel)
            fd_str = self._get_fd_signature(label.fd, delta)
            if fd_str:
                addon += "  " + fd_str
            return "JUMP", addon
        else:
            return None, None

    def _get_fd_name(self, fd, bias):
        if fd is not None:
            f = fd.get_func_by_bias(bias)
            if f is not None:
                return f.get_name()

    def _get_lib_short_info(self, addr, label):
        """get '(-offset)FuncName' string if addr is in jump table of label"""
        if addr < label.base_addr:
            delta = label.base_addr - addr
            fd_name = self._get_fd_name(label.fd, delta)
            return delta, fd_name
Пример #11
0
 def __init__(self, cpu='68000'):
     self.disasm = DisAsm.create(cpu)
Пример #12
0
    def handle_blkdev(self, blkdev):
        n = len(self.opts)
        if n == 0:
            print(
                "Usage: boot ( show [hex] [asm] | read <file> | write <file> | install [boot1x] | clear )"
            )
            return 1
        cmd = self.opts[0]
        # fetch boot blcok
        bb = BootBlock(blkdev, 0)
        bb.read()
        # boot show [hex] [asm]
        if cmd == "show":
            bb.dump()
            if bb.valid and bb.boot_code != None:
                if "hex" in self.opts:
                    print_hex(bb.boot_code)
                if "asm" in self.opts:
                    from amitools.vamos.machine import DisAsm

                    dis = DisAsm.create()
                    code = dis.disassemble_block(bb.boot_code)
                    dis.dump_block(code)
            return 0
        # boot read <file>
        elif cmd == "read":
            if n > 1:
                if bb.valid:
                    if bb.boot_code != None:
                        f = open(self.opts[1], "wb")
                        f.write(bb.boot_code)
                        f.close()
                        return 0
                    else:
                        print("No Boot Code found!")
                        return 2
                else:
                    print("Invalid Boot Block!")
                    return 1
            else:
                print("No file name!")
                return 1
        # boot write <file>
        elif cmd == "write":
            if n > 1:
                f = open(self.opts[1], "rb")
                data = f.read()
                f.close()
                ok = bb.set_boot_code(data)
                if ok:
                    bb.write()
                    return 0
                else:
                    print("Boot Code invalid!")
                    return 2
            else:
                print("No file name!")
                return 1
        # boot install [<name>]
        elif cmd == "install":
            if n == 1:  # default boot code
                name = "boot2x3x"
            else:
                name = self.opts[1]
            # boot code directory
            bc_dir = bb.get_boot_code_dir()
            if bc_dir == None:
                print("No boot code directory found!")
                return 1
            path = os.path.join(bc_dir, name + ".bin")
            if not os.path.exists:
                print("Boot code '%s' not found!" % path)
                return 1
            # read data
            f = open(path, "rb")
            data = f.read()
            f.close()
            ok = bb.set_boot_code(data)
            if ok:
                bb.write()
                return 0
            else:
                print("Boot Code invalid!")
                return 2
        # boot clear
        elif cmd == "clear":
            bb.set_boot_code(None)
            bb.write()
            return 0
        # boot ?
        else:
            print("Unknown boot command!")
            return 1
Пример #13
0
class TraceManager(object):
  trace_val_str = ("%02x      ", "%04x    ", "%08x")

  def __init__(self, machine):
    self.machine = machine
    self.cpu = machine.get_cpu()
    self.label_mgr = machine.get_label_mgr()
    self.disasm = DisAsm(machine)
    # state
    self.mem_tracer = None

  def parse_config(self, cfg):
    if not cfg:
      return True
    if cfg.vamos_ram:
      self.setup_vamos_ram_trace()
    if cfg.memory:
      self.setup_cpu_mem_trace()
    if cfg.instr:
      with_regs = cfg.reg_dump
      self.setup_cpu_instr_trace(with_regs)
    return True

  def setup_vamos_ram_trace(self):
    mem = self.machine.get_mem()
    self.mem_tracer = TraceMemory(mem, self)
    if not log_mem_int.isEnabledFor(logging.INFO):
      log_mem_int.setLevel(logging.INFO)

  def setup_cpu_mem_trace(self):
    self.machine.set_cpu_mem_trace_hook(self.trace_cpu_mem)
    if not log_mem.isEnabledFor(logging.INFO):
      log_mem.setLevel(logging.INFO)

  def setup_cpu_instr_trace(self, with_regs):
    if not log_instr.isEnabledFor(logging.INFO):
      log_instr.setLevel(logging.INFO)
    cpu = self.cpu
    state = CPUState()
    if with_regs:
      def instr_hook():
        # add register dump
        state.get(cpu)
        res = state.dump()
        for r in res:
          log_instr.info(r)
        # disassemble line
        pc = cpu.r_reg(REG_PC)
        self.trace_code_line(pc)
    else:
      def instr_hook():
        # disassemble line
        pc = cpu.r_reg(REG_PC)
        self.trace_code_line(pc)
    self.machine.set_instr_hook(instr_hook)

  # trace callback from CPU core
  def trace_cpu_mem(self, mode, width, addr, value=0):
    self._trace_mem(log_mem, mode, width, addr, value)
    return 0

  def trace_int_mem(self, mode, width, addr, value=0,
                    text="", addon=""):
    self._trace_mem(log_mem_int, mode, width, addr, value, text, addon)

  def trace_int_block(self, mode, addr, size,
                      text="", addon=""):
    info, label = self._get_mem_info(addr)
    log_mem_int.info(
        "%s(B): %06x: +%06x   %6s  [%s] %s",
        mode, addr, size,
        text, info, addon)

  def trace_code_line(self, pc):
    label, sym, src, addon = self._get_disasm_info(pc)
    _, txt = self.disasm.disassemble(pc)
    if sym is not None:
      log_instr.info("%s%s:", " "*40, sym)
    if src is not None:
      log_instr.info("%s%s", " "*50, src)
    log_instr.info("%-40s  %06x    %-20s  %s" % (label, pc, txt, addon))

  # ----- internal -----

  def _get_disasm_info(self, addr):
    if not self.label_mgr:
      return "N/A", None, None
    label = self.label_mgr.get_label(addr)
    sym = None
    src = None
    addon = ""
    if label:
      mem = "@%06x +%06x %s" % (label.addr, addr - label.addr, label.name)
      if isinstance(label, LabelSegment):
        sym, src = self._get_segment_info(label.segment, label.addr, addr)
      elif isinstance(label, LabelLib):
        delta, fd_name = self._get_lib_short_info(addr, label)
        mem += "(-%d)" % delta
        if fd_name:
          addon = "; " + fd_name
    else:
      mem = "N/A"
    return mem, sym, src, addon

  def _get_segment_info(self, segment, segment_addr, addr):
    rel_addr = addr - segment_addr
    sym = segment.find_symbol(rel_addr)
    info = segment.find_debug_line(rel_addr)
    if info is None:
      src = None
    else:
      f = info.get_file()
      src_file = f.get_src_file()
      src_line = info.get_src_line()
      src = "[%s:%d]" % (src_file, src_line)
    return sym, src

  def _trace_mem(self, log, mode, width, addr, value,
                 text="", addon=""):
    val = self.trace_val_str[width] % value
    info, label = self._get_mem_info(addr)
    if text == "" and addon == "" and label is not None:
      text, addon = self._get_label_extra(label, mode, addr, width, value)
    log.info("%s(%d): %06x: %s  %6s  [%s] %s",
             mode, 2**width, addr, val,
             text, info, addon)

  def _get_mem_info(self, addr, width=None):
    if not self.label_mgr:
      return "??", None
    label = self.label_mgr.get_label(addr)
    if label is not None:
      txt = "@%06x +%06x %s" % (label.addr, addr - label.addr, label.name)
      return txt, label
    else:
      return "??", None

  def _get_label_extra(self, label, mode, addr, width, value):
    if isinstance(label, LabelLib):
      text, addon = self._get_lib_extra(label, mode, addr, width, value)
      if text:
        return text, addon
    if isinstance(label, LabelStruct):
      return self._get_struct_extra(label, addr, width)
    else:
      return "", ""

  def _get_struct_extra(self, label, addr, width):
    delta = addr - label.struct_begin
    if delta >= 0 and delta < label.struct_size:
      struct = label.struct(None, addr)
      st, field, f_delta = struct.get_struct_field_for_offset(delta)

      type_name = struct.get_type_name()
      name = st.get_field_path_name(field)
      type_sig = field.type_sig
      addon = "%s+%d = %s(%s)+%d" % (type_name, delta,
                                     name, type_sig, f_delta)
      return "Struct", addon
    else:
      return "", ""

  op_jmp = 0x4ef9
  op_reset = 0x04e70

  def _get_fd_signature(self, fd, bias):
    if fd is not None:
      f = fd.get_func_by_bias(bias)
      if f is not None:
        return f.get_str()

  def _get_lib_extra(self, label, mode, addr, width, value):
    # inside jump table
    if addr < label.base_addr:
      delta = label.base_addr - addr
      slot = delta / 6
      rel = delta % 6
      if rel == 0:
        addon = "-%d  [%d]" % (delta, slot)
      else:
        addon = "-%d  [%d]+%d" % (delta, slot, rel)
      fd_str = self._get_fd_signature(label.fd, delta)
      if fd_str:
        addon += "  " + fd_str
      return "JUMP", addon
    else:
      return None, None

  def _get_fd_name(self, fd, bias):
    if fd is not None:
      f = fd.get_func_by_bias(bias)
      if f is not None:
        return f.get_name()

  def _get_lib_short_info(self, addr, label):
    """get '(-offset)FuncName' string if addr is in jump table of label"""
    if addr < label.base_addr:
      delta = label.base_addr - addr
      fd_name = self._get_fd_name(label.fd, delta)
      return delta, fd_name