Exemplo n.º 1
0
    def __init__(self, endness):
        if endness not in ('Iend_LE', 'Iend_BE'):
            raise ArchError('Must pass a valid VEX endness: "Iend_LE" or "Iend_BE"')

        if _pyvex:
            self.vex_archinfo = _pyvex.default_vex_archinfo()
        if endness == 'Iend_BE':
            if self.vex_archinfo:
                self.vex_archinfo['endness'] = _pyvex.vex_endness_from_string('VexEndnessBE')
            self.memory_endness = 'Iend_BE'
            self.register_endness = 'Iend_BE'
            self.cs_mode -= _capstone.CS_MODE_LITTLE_ENDIAN
            self.cs_mode += _capstone.CS_MODE_BIG_ENDIAN
            self.ret_instruction = reverse_ends(self.ret_instruction)
            self.nop_instruction = reverse_ends(self.nop_instruction)

        # generate regitster mapping (offset, size): name
        self.register_size_names = {}
        for k, v in self.registers.iteritems():
            if v in self.register_size_names and k not in self.register_names:
                continue
            self.register_size_names[v] = k

        # unicorn specific stuff
        if self.uc_mode is not None:
            if endness == 'Iend_BE':
                self.uc_mode -= _unicorn.UC_MODE_LITTLE_ENDIAN
                self.uc_mode += _unicorn.UC_MODE_BIG_ENDIAN
            self.uc_regs = { }
            # map register names to unicorn const
            for r in self.register_names.itervalues():
                reg_name = self.uc_prefix + 'REG_' + r.upper()
                if hasattr(self.uc_const, reg_name):
                    self.uc_regs[r] = getattr(self.uc_const, reg_name)
Exemplo n.º 2
0
    def __init__(self, endness, instruction_endness=None):

        if endness not in (Endness.LE, Endness.BE, Endness.ME):
            raise ArchError(
                'Must pass a valid endness: Endness.LE, Endness.BE, or Endness.ME'
            )

        if instruction_endness is not None:
            self.instruction_endness = instruction_endness

        if self.vex_support:
            if _pyvex:
                self.vex_archinfo = _pyvex.default_vex_archinfo()
        else:
            self._vex_archinfo = None

        if endness == Endness.BE:
            if self.vex_archinfo:
                self.vex_archinfo['endness'] = _pyvex.vex_endness_from_string(
                    'VexEndnessBE')
            self.memory_endness = Endness.BE
            self.register_endness = Endness.BE
            if _capstone and self.cs_mode is not None:
                self.cs_mode -= _capstone.CS_MODE_LITTLE_ENDIAN
                self.cs_mode += _capstone.CS_MODE_BIG_ENDIAN
            if _keystone and self.ks_mode is not None:
                self.ks_mode -= _keystone.KS_MODE_LITTLE_ENDIAN
                self.ks_mode += _keystone.KS_MODE_BIG_ENDIAN
            self.ret_instruction = reverse_ends(self.ret_instruction)
            self.nop_instruction = reverse_ends(self.nop_instruction)

        # generate register mapping (offset, size): name
        self.register_size_names = {}
        for k in self.registers:
            v = self.registers[k]

            # special hacks for X86 and AMD64 - don't translate register names to bp, sp, etc.
            if self.name in {'X86', 'AMD64'} and k in {'bp', 'sp', 'ip'}:
                continue

            if v in self.register_size_names and k not in self.register_names:
                continue
            self.register_size_names[v] = k

        # Unicorn specific stuff
        if self.uc_mode is not None:
            if endness == Endness.BE:
                self.uc_mode -= _unicorn.UC_MODE_LITTLE_ENDIAN
                self.uc_mode += _unicorn.UC_MODE_BIG_ENDIAN
            self.uc_regs = {}
            # map register names to Unicorn const
            for r in self.register_names.values():
                reg_name = self.uc_prefix + 'REG_' + r.upper()
                if hasattr(self.uc_const, reg_name):
                    self.uc_regs[r] = getattr(self.uc_const, reg_name)
Exemplo n.º 3
0
    def __init__(self, name, bits=32):
        self.name = name
        self.bits = bits
        self.vex_archinfo = _pyvex.default_vex_archinfo()

        if self.register_endness == "Iend_BE":
            if self.vex_archinfo:
                self.vex_archinfo['endness'] = _pyvex.vex_endness_from_string(
                    'VexEndnessBE')
            self.memory_endness = 'Iend_BE'
            self.cs_mode -= _capstone.CS_MODE_LITTLE_ENDIAN
            self.cs_mode += _capstone.CS_MODE_BIG_ENDIAN
            self.ret_instruction = reverse_ends(self.ret_instruction)
            self.nop_instruction = reverse_ends(self.nop_instruction)
Exemplo n.º 4
0
    def __init__(self, endness):
        if endness not in ('Iend_LE', 'Iend_BE'):
            raise ArchError('Must pass a valid VEX endness: "Iend_LE" or "Iend_BE"')

        if _pyvex:
            self.vex_archinfo = _pyvex.default_vex_archinfo()
        if endness == 'Iend_BE':
            if self.vex_archinfo:
                self.vex_archinfo['endness'] = _pyvex.vex_endness_from_string('VexEndnessBE')
            self.memory_endness = 'Iend_BE'
            self.register_endness = 'Iend_BE'
            self.cs_mode -= _capstone.CS_MODE_LITTLE_ENDIAN
            self.cs_mode += _capstone.CS_MODE_BIG_ENDIAN
            self.ret_instruction = reverse_ends(self.ret_instruction)
            self.nop_instruction = reverse_ends(self.nop_instruction)
Exemplo n.º 5
0
    def __init__(self, endness):
        if endness not in ('Iend_LE', 'Iend_BE'):
            raise ArchError('Must pass a valid VEX endness: "Iend_LE" or "Iend_BE"')

        if _pyvex:
            self.vex_archinfo = _pyvex.default_vex_archinfo()
        if endness == 'Iend_BE':
            if self.vex_archinfo:
                self.vex_archinfo['endness'] = _pyvex.vex_endness_from_string('VexEndnessBE')
            self.memory_endness = 'Iend_BE'
            self.register_endness = 'Iend_BE'
            if _capstone:
                self.cs_mode -= _capstone.CS_MODE_LITTLE_ENDIAN
                self.cs_mode += _capstone.CS_MODE_BIG_ENDIAN
            self.ret_instruction = reverse_ends(self.ret_instruction)
            self.nop_instruction = reverse_ends(self.nop_instruction)

        # generate regitster mapping (offset, size): name
        self.register_size_names = {}
        for k, v in self.registers.iteritems():

            # special hacks for X86 and AMD64 - don't translate register names to bp, sp, etc.
            if self.name in {'X86', 'AMD64'} and k in {'bp', 'sp', 'ip'}:
                continue

            if v in self.register_size_names and k not in self.register_names:
                continue
            self.register_size_names[v] = k

        # unicorn specific stuff
        if self.uc_mode is not None:
            if endness == 'Iend_BE':
                self.uc_mode -= _unicorn.UC_MODE_LITTLE_ENDIAN
                self.uc_mode += _unicorn.UC_MODE_BIG_ENDIAN
            self.uc_regs = { }
            # map register names to unicorn const
            for r in self.register_names.itervalues():
                reg_name = self.uc_prefix + 'REG_' + r.upper()
                if hasattr(self.uc_const, reg_name):
                    self.uc_regs[r] = getattr(self.uc_const, reg_name)
Exemplo n.º 6
0
    def __init__(self, endness, instruction_endness=None):

        self.bytes = self.bits // self.byte_width

        if endness not in (Endness.LE, Endness.BE, Endness.ME):
            raise ArchError('Must pass a valid endness: Endness.LE, Endness.BE, or Endness.ME')

        if instruction_endness is not None:
            self.instruction_endness = instruction_endness

        if self.vex_support:
            if _pyvex:
                self.vex_archinfo = _pyvex.default_vex_archinfo()
        else:
            self._vex_archinfo = None

        if endness == Endness.BE:
            if self.vex_archinfo:
                self.vex_archinfo['endness'] = _pyvex.vex_endness_from_string('VexEndnessBE')
            self.memory_endness = Endness.BE
            self.register_endness = Endness.BE
            if _capstone and self.cs_mode is not None:
                self.cs_mode -= _capstone.CS_MODE_LITTLE_ENDIAN
                self.cs_mode += _capstone.CS_MODE_BIG_ENDIAN
            if _keystone and self.ks_mode is not None:
                self.ks_mode -= _keystone.KS_MODE_LITTLE_ENDIAN
                self.ks_mode += _keystone.KS_MODE_BIG_ENDIAN
            self.ret_instruction = reverse_ends(self.ret_instruction)
            self.nop_instruction = reverse_ends(self.nop_instruction)

        if self.register_list and _pyvex is not None:
            (_, _), max_offset = max(_pyvex.vex_ffi.guest_offsets.items(), key=lambda x: x[1])
            max_offset += self.bits
            # Register collections
            if type(self.vex_arch) is str:
                va = self.vex_arch[7:].lower() # pylint: disable=unsubscriptable-object
                for r in self.register_list:
                    if r.vex_offset is None:
                        for name in (r.vex_name, r.name) + r.alias_names:
                            try:
                                r.vex_offset = _pyvex.vex_ffi.guest_offsets[(va, name)]
                            except KeyError:
                                r.vex_offset = max_offset
                                max_offset += r.size
                            else:
                                break

            self.default_register_values = [(r.name,) + r.default_value for r in self.register_list if r.default_value is not None]
            self.entry_register_values = {r.name: r.linux_entry_value for r in self.register_list if r.linux_entry_value is not None}
            self.default_symbolic_registers = [r.name for r in self.register_list if r.general_purpose]
            self.register_names = {r.vex_offset: r.name for r in self.register_list}
            self.registers = self._get_register_dict()
            self.argument_registers = set(r.vex_offset for r in self.register_list if r.argument)
            self.persistent_regs = [r.name for r in self.register_list if r.persistent]
            self.concretize_unique_registers = set(r.vex_offset for r in self.register_list if r.concretize_unique)
            self.artificial_registers = set(r.name for r in self.register_list if r.artificial)

            # Register offsets
            try:
                self.ip_offset = self.registers['ip'][0]
                self.sp_offset = self.registers['sp'][0]
                self.bp_offset = self.registers['bp'][0]
                self.lr_offset = self.registers.get('lr', (None, None))[0]
            except KeyError:
                pass

        # generate register mapping (offset, size): name
        self.register_size_names = {}
        for reg in self.register_list:
            if reg.vex_offset is None:
                continue
            self.register_size_names[(reg.vex_offset, reg.size)] = reg.name
            for name, off, sz in reg.subregisters:
                # special hacks for X86 and AMD64 - don't translate register names to bp, sp, etc.
                if self.name in {'X86', 'AMD64'} and name in {'bp', 'sp', 'ip'}:
                    continue
                self.register_size_names[(reg.vex_offset + off, sz)] = name

        # allow mapping a sub-register to its base register
        self.subregister_map = { }
        for reg in self.register_list:
            if reg.vex_offset is None:
                continue
            base_reg = reg.vex_offset, reg.size
            self.subregister_map[(reg.vex_offset, reg.size)] = base_reg
            self.subregister_map[reg.vex_offset] = base_reg
            for name, off, sz in reg.subregisters:
                if self.name in {'X86', 'AMD64'} and name in {'bp', 'sp', 'ip'}:
                    continue
                subreg_offset = reg.vex_offset + off
                self.subregister_map[(subreg_offset, sz)] = base_reg
                if subreg_offset not in self.subregister_map:
                    self.subregister_map[subreg_offset] = base_reg

        # Unicorn specific stuff
        if self.uc_mode is not None:
            if endness == Endness.BE:
                self.uc_mode -= _unicorn.UC_MODE_LITTLE_ENDIAN
                self.uc_mode += _unicorn.UC_MODE_BIG_ENDIAN
            self.uc_regs = { }
            # map register names to Unicorn const
            for r in self.register_names.values():
                reg_name = self.uc_prefix + 'REG_' + r.upper()
                if hasattr(self.uc_const, reg_name):
                    self.uc_regs[r] = getattr(self.uc_const, reg_name)
Exemplo n.º 7
0
    def __init__(self, endness, instruction_endness=None):

        self.bytes = self.bits // self.byte_width

        if endness not in (Endness.LE, Endness.BE, Endness.ME):
            raise ArchError(
                'Must pass a valid endness: Endness.LE, Endness.BE, or Endness.ME'
            )

        if instruction_endness is not None:
            self.instruction_endness = instruction_endness

        if self.vex_support and _pyvex:
            self.vex_archinfo = _pyvex.default_vex_archinfo()

        if endness == Endness.BE:
            if self.vex_archinfo:
                self.vex_archinfo['endness'] = _pyvex.vex_endness_from_string(
                    'VexEndnessBE')
            self.memory_endness = Endness.BE
            self.register_endness = Endness.BE
            if _capstone and self.cs_mode is not None:
                self.cs_mode -= _capstone.CS_MODE_LITTLE_ENDIAN
                self.cs_mode += _capstone.CS_MODE_BIG_ENDIAN
            if _keystone and self.ks_mode is not None:
                self.ks_mode -= _keystone.KS_MODE_LITTLE_ENDIAN
                self.ks_mode += _keystone.KS_MODE_BIG_ENDIAN
            self.ret_instruction = reverse_ends(self.ret_instruction)
            self.nop_instruction = reverse_ends(self.nop_instruction)

        if self.register_list and _pyvex is not None:
            (_, _), max_offset = max(_pyvex.vex_ffi.guest_offsets.items(),
                                     key=lambda x: x[1])
            max_offset += self.bits
            # Register collections
            if type(self.vex_arch) is str:
                va = self.vex_arch[7:].lower()  # pylint: disable=unsubscriptable-object
                for r in self.register_list:
                    if r.vex_offset is None:
                        for name in (r.vex_name, r.name) + r.alias_names:
                            try:
                                r.vex_offset = _pyvex.vex_ffi.guest_offsets[(
                                    va, name)]
                            except KeyError:
                                r.vex_offset = max_offset
                                max_offset += r.size
                            else:
                                break

            self.default_register_values = [(r.name, ) + r.default_value
                                            for r in self.register_list
                                            if r.default_value is not None]
            self.entry_register_values = {
                r.name: r.linux_entry_value
                for r in self.register_list if r.linux_entry_value is not None
            }
            self.default_symbolic_registers = [
                r.name for r in self.register_list if r.general_purpose
            ]
            self.register_names = {
                r.vex_offset: r.name
                for r in self.register_list
            }
            self.registers = self._get_register_dict()
            self.argument_registers = set(r.vex_offset
                                          for r in self.register_list
                                          if r.argument)
            self.persistent_regs = [
                r.name for r in self.register_list if r.persistent
            ]
            self.concretize_unique_registers = set(r.vex_offset
                                                   for r in self.register_list
                                                   if r.concretize_unique)
            self.artificial_registers = set(r.name for r in self.register_list
                                            if r.artificial)

            # Register offsets
            try:
                self.ip_offset = self.registers['ip'][0]
                self.sp_offset = self.registers['sp'][0]
                self.bp_offset = self.registers['bp'][0]
                self.lr_offset = self.registers.get('lr', (None, None))[0]
            except KeyError:
                pass

        # generate register mapping (offset, size): name
        self.register_size_names = {}
        for reg in self.register_list:
            if reg.vex_offset is None:
                continue
            self.register_size_names[(reg.vex_offset, reg.size)] = reg.name
            for name, off, sz in reg.subregisters:
                # special hacks for X86 and AMD64 - don't translate register names to bp, sp, etc.
                if self.name in {'X86', 'AMD64'
                                 } and name in {'bp', 'sp', 'ip'}:
                    continue
                self.register_size_names[(reg.vex_offset + off, sz)] = name

        # allow mapping a sub-register to its base register
        self.subregister_map = {}
        for reg in self.register_list:
            if reg.vex_offset is None:
                continue
            base_reg = reg.vex_offset, reg.size
            self.subregister_map[(reg.vex_offset, reg.size)] = base_reg
            self.subregister_map[reg.vex_offset] = base_reg
            for name, off, sz in reg.subregisters:
                if self.name in {'X86', 'AMD64'
                                 } and name in {'bp', 'sp', 'ip'}:
                    continue
                subreg_offset = reg.vex_offset + off
                self.subregister_map[(subreg_offset, sz)] = base_reg
                if subreg_offset not in self.subregister_map:
                    self.subregister_map[subreg_offset] = base_reg

        # Unicorn specific stuff
        if self.uc_mode is not None:
            if endness == Endness.BE:
                self.uc_mode -= _unicorn.UC_MODE_LITTLE_ENDIAN
                self.uc_mode += _unicorn.UC_MODE_BIG_ENDIAN
            self.uc_regs = {}
            # map register names to Unicorn const
            for r in self.register_names.values():
                reg_name = self.uc_prefix + 'REG_' + r.upper()
                if hasattr(self.uc_const, reg_name):
                    self.uc_regs[r] = getattr(self.uc_const, reg_name)

            # Register blacklist
            reg_blacklist = ('cs', 'ds', 'es', 'fs', 'gs', 'ss', 'mm0', 'mm1',
                             'mm2', 'mm3', 'mm4', 'mm5', 'mm6', 'mm7', 'gdt',
                             'ldt')
            self.reg_blacklist = []
            self.reg_blacklist_offsets = []
            for register in self.register_list:
                if register.name in reg_blacklist:
                    self.reg_blacklist.append(register.name)
                    self.reg_blacklist_offsets.append(register.vex_offset)

            # Artificial registers offsets
            self.artificial_registers_offsets = []
            self.vex_reg_to_size_map = {}
            for reg_name in self.artificial_registers:
                reg = self.get_register_by_name(reg_name)
                self.vex_reg_to_size_map[reg.vex_offset] = reg.size
                self.artificial_registers_offsets.extend(
                    range(reg.vex_offset, reg.vex_offset + reg.size))

            # VEX register offset to unicorn register ID and to name maps
            self.vex_reg_offset_to_name = {}
            self.vex_to_unicorn_map = {}
            self.vex_sub_reg_to_reg_map = {}
            pc_reg_name = self.get_register_by_name("pc")
            for reg_name, unicorn_reg_id in self.uc_regs.items():
                if reg_name == pc_reg_name:
                    continue

                vex_reg = self.get_register_by_name(reg_name)
                self.vex_reg_offset_to_name[vex_reg.vex_offset] = (
                    reg_name, vex_reg.size)
                self.vex_to_unicorn_map[vex_reg.vex_offset] = unicorn_reg_id
                self.vex_reg_to_size_map[vex_reg.vex_offset] = vex_reg.size
                for vex_sub_reg in vex_reg.subregisters:
                    vex_sub_reg_offset = self.get_register_offset(
                        vex_sub_reg[0])
                    if vex_sub_reg_offset not in self.vex_reg_offset_to_name:
                        self.vex_reg_offset_to_name[vex_sub_reg_offset] = (
                            reg_name, vex_reg.size)

                    self.vex_sub_reg_to_reg_map[
                        vex_sub_reg_offset] = vex_reg.vex_offset

            # CPU flag registers
            cpu_flag_registers = {'d': 10, 'ac': 18, 'id': 21}
            self.cpu_flag_register_offsets_and_bitmasks_map = {}
            for flag_reg, bitmask in cpu_flag_registers.items():
                if flag_reg in self.registers:
                    flag_reg_offset = self.get_register_offset(flag_reg)
                    flag_bitmask = (1 << bitmask)
                    self.cpu_flag_register_offsets_and_bitmasks_map[
                        flag_reg_offset] = flag_bitmask
Exemplo n.º 8
0
    def __init__(self, endness, instruction_endness=None):

        if endness not in (Endness.LE, Endness.BE, Endness.ME):
            raise ArchError(
                'Must pass a valid endness: Endness.LE, Endness.BE, or Endness.ME'
            )

        if instruction_endness is not None:
            self.instruction_endness = instruction_endness

        if self.vex_support:
            if _pyvex:
                self.vex_archinfo = _pyvex.default_vex_archinfo()
        else:
            self._vex_archinfo = None

        if endness == Endness.BE:
            if self.vex_archinfo:
                self.vex_archinfo['endness'] = _pyvex.vex_endness_from_string(
                    'VexEndnessBE')
            self.memory_endness = Endness.BE
            self.register_endness = Endness.BE
            if _capstone and self.cs_mode is not None:
                self.cs_mode -= _capstone.CS_MODE_LITTLE_ENDIAN
                self.cs_mode += _capstone.CS_MODE_BIG_ENDIAN
            if _keystone and self.ks_mode is not None:
                self.ks_mode -= _keystone.KS_MODE_LITTLE_ENDIAN
                self.ks_mode += _keystone.KS_MODE_BIG_ENDIAN
            self.ret_instruction = reverse_ends(self.ret_instruction)
            self.nop_instruction = reverse_ends(self.nop_instruction)

        # Register collections
        if self.register_list:
            if self.vex_arch is not None and _pyvex is not None:
                va = self.vex_arch[7:].lower()
                for r in self.register_list:
                    if r.vex_offset is None:
                        for name in (r.vex_name, r.name) + r.alias_names:
                            try:
                                r.vex_offset = _pyvex.vex_ffi.guest_offsets[(
                                    va, name)]
                            except KeyError:
                                pass
                            else:
                                break

            self.default_register_values = [(r.name, ) + r.default_value
                                            for r in self.register_list
                                            if r.default_value is not None]
            #           print 'default_register_values'
            #           for i in self.default_register_values:
            #               print i
            self.entry_register_values = {
                r.name: r.linux_entry_value
                for r in self.register_list if r.linux_entry_value is not None
            }
            #           print 'entry_register_values'
            #           for i in self.entry_register_values:
            #               print i
            self.default_symbolic_registers = [
                r.name for r in self.register_list if r.general_purpose
            ]
            #           print 'default_symbolic_registers'
            #           for i in self.default_symbolic_registers:
            #               print i
            self.register_names = {
                r.vex_offset: r.name
                for r in self.register_list
            }
            #           print 'register_names'
            #           for k, v in self.register_names.iteritems():
            #               print k, v
            self.registers = self._get_register_dict()
            #           print 'registers'
            #           for k, v in self.registers.iteritems():
            #               print k, v
            self.argument_registers = set(r.vex_offset
                                          for r in self.register_list
                                          if r.argument)
            #           print 'argument_registers'
            #           for i in self.argument_registers:
            #               print i
            self.persistent_regs = [
                r.name for r in self.register_list if r.persistent
            ]
            #           print 'persistent_regs'
            #           for i in self.persistent_regs:
            #               print i
            self.concretize_unique_registers = set(r.vex_offset
                                                   for r in self.register_list
                                                   if r.concretize_unique)


#           print 'concretize_unique_registers'
#           for i in self.concretize_unique_registers:
#               print i

# generate register mapping (offset, size): name
        self.register_size_names = {}
        for k in self.registers:
            v = self.registers[k]

            # special hacks for X86 and AMD64 - don't translate register names to bp, sp, etc.
            if self.name in {'X86', 'AMD64'} and k in {'bp', 'sp', 'ip'}:
                continue

            if v in self.register_size_names and k not in self.register_names:
                continue
            self.register_size_names[v] = k

        # Unicorn specific stuff
        if self.uc_mode is not None:
            if endness == Endness.BE:
                self.uc_mode -= _unicorn.UC_MODE_LITTLE_ENDIAN
                self.uc_mode += _unicorn.UC_MODE_BIG_ENDIAN
            self.uc_regs = {}
            # map register names to Unicorn const
            for r in self.register_names.values():
                reg_name = self.uc_prefix + 'REG_' + r.upper()
                if hasattr(self.uc_const, reg_name):
                    self.uc_regs[r] = getattr(self.uc_const, reg_name)
Exemplo n.º 9
0
    def __init__(self, endness, instruction_endness=None):

        if endness not in (Endness.LE, Endness.BE, Endness.ME):
            raise ArchError('Must pass a valid endness: Endness.LE, Endness.BE, or Endness.ME')

        if instruction_endness is not None:
            self.instruction_endness = instruction_endness

        if self.vex_support:
            if _pyvex:
                self.vex_archinfo = _pyvex.default_vex_archinfo()
        else:
            self._vex_archinfo = None

        if endness == Endness.BE:
            if self.vex_archinfo:
                self.vex_archinfo['endness'] = _pyvex.vex_endness_from_string('VexEndnessBE')
            self.memory_endness = Endness.BE
            self.register_endness = Endness.BE
            if _capstone and self.cs_mode is not None:
                self.cs_mode -= _capstone.CS_MODE_LITTLE_ENDIAN
                self.cs_mode += _capstone.CS_MODE_BIG_ENDIAN
            if _keystone and self.ks_mode is not None:
                self.ks_mode -= _keystone.KS_MODE_LITTLE_ENDIAN
                self.ks_mode += _keystone.KS_MODE_BIG_ENDIAN
            self.ret_instruction = reverse_ends(self.ret_instruction)
            self.nop_instruction = reverse_ends(self.nop_instruction)

        if self.register_list and _pyvex is not None:
            (_, _), max_offset = max(_pyvex.vex_ffi.guest_offsets.items(), key=lambda x: x[1])
            max_offset += self.bits
            # Register collections
            if type(self.vex_arch) is str:
                va = self.vex_arch[7:].lower() # pylint: disable=unsubscriptable-object
                for r in self.register_list:
                    if r.vex_offset is None:
                        for name in (r.vex_name, r.name) + r.alias_names:
                            try:
                                r.vex_offset = _pyvex.vex_ffi.guest_offsets[(va, name)]
                            except KeyError:
                                r.vex_offset = max_offset
                                max_offset += r.size
                            else:
                                break

            self.default_register_values = [(r.name,) + r.default_value for r in self.register_list if r.default_value is not None]
            self.entry_register_values = {r.name: r.linux_entry_value for r in self.register_list if r.linux_entry_value is not None}
            self.default_symbolic_registers = [r.name for r in self.register_list if r.general_purpose]
            self.register_names = {r.vex_offset: r.name for r in self.register_list}
            self.registers = self._get_register_dict()
            self.argument_registers = set(r.vex_offset for r in self.register_list if r.argument)
            self.persistent_regs = [r.name for r in self.register_list if r.persistent]
            self.concretize_unique_registers = set(r.vex_offset for r in self.register_list if r.concretize_unique)
            self.artificial_registers = set(r.name for r in self.register_list if r.artificial)

            # Register offsets
            try:
                self.ip_offset = self.registers['ip'][0]
                self.sp_offset = self.registers['sp'][0]
                self.bp_offset = self.registers['bp'][0]
                self.lr_offset = self.registers.get('lr', (None, None))[0]
            except KeyError:
                pass

        # generate register mapping (offset, size): name
        self.register_size_names = {}
        for reg in self.register_list:
            if reg.vex_offset is None:
                continue
            self.register_size_names[(reg.vex_offset, reg.size)] = reg.name
            for name, off, sz in reg.subregisters:
                # special hacks for X86 and AMD64 - don't translate register names to bp, sp, etc.
                if self.name in {'X86', 'AMD64'} and name in {'bp', 'sp', 'ip'}:
                    continue
                self.register_size_names[(reg.vex_offset + off, sz)] = name

        # allow mapping a sub-register to its base register
        self.subregister_map = { }
        for reg in self.register_list:
            if reg.vex_offset is None:
                continue
            base_reg = reg.vex_offset, reg.size
            self.subregister_map[(reg.vex_offset, reg.size)] = base_reg
            self.subregister_map[reg.vex_offset] = base_reg
            for name, off, sz in reg.subregisters:
                if self.name in {'X86', 'AMD64'} and name in {'bp', 'sp', 'ip'}:
                    continue
                subreg_offset = reg.vex_offset + off
                self.subregister_map[(subreg_offset, sz)] = base_reg
                if subreg_offset not in self.subregister_map:
                    self.subregister_map[subreg_offset] = base_reg

        # Unicorn specific stuff
        if self.uc_mode is not None:
            if endness == Endness.BE:
                self.uc_mode -= _unicorn.UC_MODE_LITTLE_ENDIAN
                self.uc_mode += _unicorn.UC_MODE_BIG_ENDIAN
            self.uc_regs = { }
            # map register names to Unicorn const
            for r in self.register_names.values():
                reg_name = self.uc_prefix + 'REG_' + r.upper()
                if hasattr(self.uc_const, reg_name):
                    self.uc_regs[r] = getattr(self.uc_const, reg_name)