diff options
26 files changed, 4307 insertions, 85 deletions
diff --git a/.travis.yml b/.travis.yml index 19b64ace..bc203658 100644 --- a/.travis.yml +++ b/.travis.yml @@ -23,7 +23,7 @@ before_script: - "cp tinycc/libtcc.h include" - "cp tinycc/libtcc.so.1.0 tinycc/libtcc.so" # install elfesteem -- "hg clone https://code.google.com/p/elfesteem/ elfesteem && cd elfesteem && python setup.py install && cd ..;" +- "git clone https://github.com/serpilliere/elfesteem elfesteem && cd elfesteem && python setup.py install && cd ..;" # install pyparsing - "pip install pyparsing" # install z3 diff --git a/example/ida/utils.py b/example/ida/utils.py index 5a0e4c83..8a7ecccb 100644 --- a/example/ida/utils.py +++ b/example/ida/utils.py @@ -5,21 +5,27 @@ from miasm2.analysis.machine import Machine from miasm2.ir.translators import Translator import miasm2.expression.expression as m2_expr +def max_size_to_size(max_size): + for size in [16, 32, 64]: + if (1 << size) - 1 == max_size: + return size + return None def guess_machine(): "Return an instance of Machine corresponding to the IDA guessed processor" processor_name = GetLongPrm(INF_PROCNAME) + max_size = GetLongPrm(INF_START_SP) + size = max_size_to_size(max_size) if processor_name == "metapc": # HACK: check 32/64 using INF_START_SP - max_size = GetLongPrm(INF_START_SP) if max_size == 0x80: # TODO XXX check machine = Machine("x86_16") - elif max_size == 0xFFFFFFFF: + elif size == 32: machine = Machine("x86_32") - elif max_size == 0xFFFFFFFFFFFFFFFF: + elif size == 64: machine = Machine("x86_64") else: raise ValueError('cannot guess 32/64 bit! (%x)' % max_size) @@ -27,18 +33,20 @@ def guess_machine(): # TODO ARM/thumb # hack for thumb: set armt = True in globals :/ # set bigendiant = True is bigendian + # Thumb, size, endian + info2machine = {(True, 32, True): "armtb", + (True, 32, False): "armtl", + (False, 32, True): "armb", + (False, 32, False): "arml", + (False, 64, True): "aarch64b", + (False, 64, False): "aarch64l", + } is_armt = globals().get('armt', False) is_bigendian = globals().get('bigendian', False) - if is_armt: - if is_bigendian: - machine = Machine("armtb") - else: - machine = Machine("armtl") - else: - if is_bigendian: - machine = Machine("armb") - else: - machine = Machine("arml") + infos = (is_armt, size, is_bigendian) + if not infos in info2machine: + raise NotImplementedError('not fully functional') + machine = Machine(info2machine[infos]) from miasm2.analysis.disasm_cb import guess_funcs, guess_multi_cb from miasm2.analysis.disasm_cb import arm_guess_subcall, arm_guess_jump_table diff --git a/example/jitter/sandbox_elf_aarch64l.py b/example/jitter/sandbox_elf_aarch64l.py new file mode 100644 index 00000000..0a4c88db --- /dev/null +++ b/example/jitter/sandbox_elf_aarch64l.py @@ -0,0 +1,28 @@ +import os +from pdb import pm +from miasm2.analysis.sandbox import Sandbox_Linux_aarch64l +from miasm2.jitter.jitload import log_func +import logging + + +# Python auto completion +filename = os.environ.get('PYTHONSTARTUP') +if filename and os.path.isfile(filename): + execfile(filename) + +# Insert here user defined methods + +# Parse arguments +parser = Sandbox_Linux_aarch64l.parser(description="ELF sandboxer") +parser.add_argument("filename", help="ELF Filename") +options = parser.parse_args() + +# Create sandbox +sb = Sandbox_Linux_aarch64l(options.filename, options, globals()) + +log_func.setLevel(logging.ERROR) + +# Run +sb.run() + +assert(sb.jitter.run is False) diff --git a/example/samples/aarch64_simple.S b/example/samples/aarch64_simple.S new file mode 100644 index 00000000..f786f168 --- /dev/null +++ b/example/samples/aarch64_simple.S @@ -0,0 +1,17 @@ +main: + SUB SP, SP, 0x10 + STRB W0, [SP,0xF] + LDRB W0, [SP,0xF] + CMP W0, 0x1F + B.LS is_print + LDRB W0, [SP,0xF] + CMP W0, 0x7E + B.HI is_print + MOVZ W0, 1 + B ret_ +is_print: + MOVZ W0, 0 + +ret_: + ADD SP, SP, 0x10 + RET LR \ No newline at end of file diff --git a/example/samples/md5_aarch64l b/example/samples/md5_aarch64l new file mode 100755 index 00000000..700b58bd --- /dev/null +++ b/example/samples/md5_aarch64l Binary files differdiff --git a/miasm2/analysis/machine.py b/miasm2/analysis/machine.py index 778c5def..f963628c 100644 --- a/miasm2/analysis/machine.py +++ b/miasm2/analysis/machine.py @@ -12,7 +12,8 @@ class Machine(object): __gdbserver = None # GdbServer handler __available = ["arml", "armb", "armtl", "armtb", "sh4", "x86_16", "x86_32", - "x86_64", "msp430", "mips32b", "mips32l"] + "x86_64", "msp430", "mips32b", "mips32l", + "aarch64l", "aarch64b"] def __init__(self, machine_name): @@ -43,6 +44,20 @@ class Machine(object): jitter = jit.jitter_armb from miasm2.arch.arm.ira import ir_a_armb as ira from miasm2.arch.arm.sem import ir_armb as ir + elif machine_name == "aarch64l": + from miasm2.arch.aarch64.disasm import dis_aarch64l as dis_engine + from miasm2.arch.aarch64 import arch, jit + mn = arch.mn_aarch64 + jitter = jit.jitter_aarch64l + from miasm2.arch.aarch64.ira import ir_a_aarch64l as ira + from miasm2.arch.aarch64.sem import ir_aarch64l as ir + elif machine_name == "aarch64b": + from miasm2.arch.aarch64.disasm import dis_aarch64b as dis_engine + from miasm2.arch.aarch64 import arch, jit + mn = arch.mn_aarch64 + jitter = jit.jitter_aarch64b + from miasm2.arch.aarch64.ira import ir_a_aarch64b as ira + from miasm2.arch.aarch64.sem import ir_aarch64b as ir elif machine_name == "armtl": from miasm2.arch.arm.disasm import dis_armtl as dis_engine from miasm2.arch.arm import arch diff --git a/miasm2/analysis/sandbox.py b/miasm2/analysis/sandbox.py index 3bacda5e..7dc5d76e 100644 --- a/miasm2/analysis/sandbox.py +++ b/miasm2/analysis/sandbox.py @@ -317,6 +317,29 @@ class Arch_armb(Arch): self.jitter.stack_size = self.STACK_SIZE self.jitter.init_stack() +class Arch_aarch64l(Arch): + _ARCH_ = "aarch64l" + STACK_SIZE = 0x100000 + + def __init__(self): + super(Arch_aarch64l, self).__init__() + + # Init stack + self.jitter.stack_size = self.STACK_SIZE + self.jitter.init_stack() + + +class Arch_aarch64b(Arch): + _ARCH_ = "aarch64b" + STACK_SIZE = 0x100000 + + def __init__(self): + super(Arch_aarch64b, self).__init__() + + # Init stack + self.jitter.stack_size = self.STACK_SIZE + self.jitter.init_stack() + class Sandbox_Win_x86_32(Sandbox, Arch_x86_32, OS_Win): @@ -465,3 +488,20 @@ class Sandbox_Linux_arml_str(Sandbox, Arch_arml, OS_Linux_str): if addr is None and self.options.address is not None: addr = int(self.options.address, 16) super(Sandbox_Linux_arml_str, self).run(addr) + + +class Sandbox_Linux_aarch64l(Sandbox, Arch_aarch64l, OS_Linux): + + def __init__(self, *args, **kwargs): + Sandbox.__init__(self, *args, **kwargs) + + self.jitter.cpu.LR = 0x1337beef + + # Set the runtime guard + self.jitter.add_breakpoint(0x1337beef, self.__class__.code_sentinelle) + + + def run(self, addr = None): + if addr is None and self.options.address is not None: + addr = int(self.options.address, 16) + super(Sandbox_Linux_aarch64l, self).run(addr) diff --git a/miasm2/arch/aarch64/__init__.py b/miasm2/arch/aarch64/__init__.py new file mode 100644 index 00000000..bbad893b --- /dev/null +++ b/miasm2/arch/aarch64/__init__.py @@ -0,0 +1 @@ +__all__ = ["arch", "disasm", "regs", "sem"] diff --git a/miasm2/arch/aarch64/arch.py b/miasm2/arch/aarch64/arch.py new file mode 100644 index 00000000..b991fe81 --- /dev/null +++ b/miasm2/arch/aarch64/arch.py @@ -0,0 +1,1944 @@ +#!/usr/bin/env python +#-*- coding:utf-8 -*- + +import logging +from pyparsing import * +from miasm2.expression import expression as m2_expr +from miasm2.core.cpu import * +from collections import defaultdict +from miasm2.core.bin_stream import bin_stream +import regs as regs_module +from regs import * +from miasm2.core.asmbloc import asm_label +from miasm2.core.cpu import log as log_cpu +from miasm2.expression.modint import uint32, uint64 +import math + +log = logging.getLogger("aarch64dis") +console_handler = logging.StreamHandler() +console_handler.setFormatter(logging.Formatter("%(levelname)-5s: %(message)s")) +log.addHandler(console_handler) +log.setLevel(logging.DEBUG) + +# refs from A_e_armv8_arm.pdf + +# log_cpu.setLevel(logging.DEBUG) + + +replace_regs = { + W0: X0[:32], + W1: X1[:32], + W2: X2[:32], + W3: X3[:32], + W4: X4[:32], + W5: X5[:32], + W6: X6[:32], + W7: X7[:32], + W8: X8[:32], + W9: X9[:32], + + W10: X10[:32], + W11: X11[:32], + W12: X12[:32], + W13: X13[:32], + W14: X14[:32], + W15: X15[:32], + W16: X16[:32], + W17: X17[:32], + W18: X18[:32], + W19: X19[:32], + + W20: X20[:32], + W21: X21[:32], + W22: X22[:32], + W23: X23[:32], + W24: X24[:32], + W25: X25[:32], + W26: X26[:32], + W27: X27[:32], + W28: X28[:32], + W29: X29[:32], + + W30: LR[:32], + + WSP: SP[:32], + + WZR: m2_expr.ExprInt32(0), + XZR: m2_expr.ExprInt64(0), + +} + + +variable, operand, base_expr = gen_base_expr() +_, _, base_expr32 = gen_base_expr() +_, _, base_expr64 = gen_base_expr() + + +def ast_id2expr32(t): + if not t in mn_aarch64.regs.all_regs_ids_byname: + r = m2_expr.ExprId(asm_label(t)) + else: + r = mn_aarch64.regs.all_regs_ids_byname[t] + if not r.size == 32: + raise StopIteration + return r + + +def ast_int2expr32(a): + return m2_expr.ExprInt32(a) + + +def ast_id2expr64(t): + if not t in mn_aarch64.regs.all_regs_ids_byname: + r = m2_expr.ExprId(asm_label(t)) + else: + r = mn_aarch64.regs.all_regs_ids_byname[t] + if not r.size == 64: + raise StopIteration + return r + + +def ast_int2expr64(a): + return m2_expr.ExprInt64(a) + +my_var_parser32 = parse_ast(ast_id2expr32, ast_int2expr32) +my_var_parser64 = parse_ast(ast_id2expr64, ast_int2expr64) + +base_expr32.setParseAction(my_var_parser32) +base_expr64.setParseAction(my_var_parser64) + + +int_or_expr = base_expr +int_or_expr32 = base_expr32 +int_or_expr64 = base_expr64 + + +shift2expr_dct = {'LSL': '<<', 'LSR': '>>', 'ASR': 'a>>', 'ROR': '>>>'} +shift_str = ["LSL", "LSR", "ASR", "ROR"] +shift_expr = ["<<", ">>", "a>>", '>>>'] + + +def op_shift2expr(s, l, t): + return shift2expr_dct[t[0]] + + +def op_shift2expr_slice_at(s, l, t): + return "slice_at" + + +def op_ext_reg(s, l, t): + return t[0] + + +def shift2expr(t): + if len(t) == 1: + return t[0] + elif len(t) == 3: + if t[0].size == 32 and isinstance(t[2], m2_expr.ExprInt): + t[2] = m2_expr.ExprInt32(t[2].arg) + return m2_expr.ExprOp(t[1], t[0], t[2]) + else: + raise ValueError('bad string') + + +def shift2expr_sc(t): + if len(t) == 1: + return t[0] + elif len(t) == 3: + if t[0].size == 32 and isinstance(t[2], m2_expr.ExprInt): + t[2] = m2_expr.ExprInt32(t[2].arg) + if t[1] != '<<': + raise ValueError('bad op') + return m2_expr.ExprOp("slice_at", t[0], t[2]) + else: + raise ValueError('bad string') + + +def extend2expr(t): + if len(t) == 1: + return t[0] + return m2_expr.ExprOp(t[1], t[0], t[2]) + + +def shiftext2expr(t): + if len(t) == 1: + return t[0] + else: + return m2_expr.ExprOp(t[1], t[0], t[2]) + +all_binaryop_lsl_t = literal_list( + shift_str).setParseAction(op_shift2expr) + +all_binaryop_shiftleft_t = literal_list( + ["LSL"]).setParseAction(op_shift2expr) + +extend_lst = ['UXTB', 'UXTH', 'UXTW', 'UXTX', 'SXTB', 'SXTH', 'SXTW', 'SXTX'] +extend2_lst = ['UXTW', 'LSL', 'SXTW', 'SXTX'] + +all_extend_t = literal_list(extend_lst).setParseAction(op_ext_reg) +all_extend2_t = literal_list(extend2_lst).setParseAction(op_ext_reg) + + +gpreg32_extend = (gpregs32_info.parser + Optional( + all_extend_t + int_or_expr32)).setParseAction(extend2expr) +gpreg64_extend = (gpregs64_info.parser + Optional( + all_extend_t + int_or_expr64)).setParseAction(extend2expr) + + +shift32_off = (gpregsz32_info.parser + Optional(all_binaryop_lsl_t + + (gpregs32_info.parser | int_or_expr))).setParseAction(shift2expr) +shift64_off = (gpregsz64_info.parser + Optional(all_binaryop_lsl_t + + (gpregs64_info.parser | int_or_expr))).setParseAction(shift2expr) + + +shiftimm_imm_sc = (int_or_expr + all_binaryop_shiftleft_t + + int_or_expr).setParseAction(shift2expr_sc) + +shiftimm_off_sc = shiftimm_imm_sc | int_or_expr + + +shift_off = (shift32_off | shift64_off) +reg_ext_off = (gpreg32_extend | gpreg64_extend) + +gpregs_32_64 = (gpregs32_info.parser | gpregs64_info.parser) +gpregsz_32_64 = (gpregsz32_info.parser | gpregsz64_info.parser | int_or_expr) + +simdregs = (simd08_info.parser | simd16_info.parser | + simd32_info.parser | simd64_info.parser) +simdregs_h = (simd32_info.parser | simd64_info.parser | simd128_info.parser) + +simdregs_h_zero = (simd32_info.parser | + simd64_info.parser | simd128_info.parser | int_or_expr) + + +def ast_id2expr(t): + if not t in mn_aarch64.regs.all_regs_ids_byname: + r = m2_expr.ExprId(asm_label(t)) + else: + r = mn_aarch64.regs.all_regs_ids_byname[t] + return r + + +def ast_int2expr(a): + return m2_expr.ExprInt64(a) + +gpregs_info = {32: gpregs32_info, + 64: gpregs64_info} +gpregsz_info = {32: gpregsz32_info, + 64: gpregsz64_info} + + +simds_info = {8: simd08_info, + 16: simd16_info, + 32: simd32_info, + 64: simd64_info, + 128: simd128_info} + + +my_var_parser = parse_ast(ast_id2expr, ast_int2expr) +base_expr.setParseAction(my_var_parser) + + +def deref2expr_nooff(t): + t = t[0] + # XXX default + return m2_expr.ExprOp("preinc", t[0], m2_expr.ExprInt64(0)) + + +def deref2expr_post(t): + t = t[0] + if t[1] in regs_module.all_regs_ids: + raise StopIteration + return m2_expr.ExprOp("postinc", t[0], t[1]) + + +def deref2expr_pre(t): + t = t[0] + if t[1] in regs_module.all_regs_ids: + raise StopIteration + return m2_expr.ExprOp("preinc", t[0], t[1]) + + +def deref2expr_pre_wb(t): + t = t[0] + if t[1] in regs_module.all_regs_ids: + raise StopIteration + return m2_expr.ExprOp("preinc_wb", t[0], t[1]) + +LBRACK = Suppress("[") +RBRACK = Suppress("]") +COMMA = Suppress(",") +POSTINC = Suppress("!") + +deref_nooff = Group( + LBRACK + gpregs64_info.parser + RBRACK).setParseAction(deref2expr_nooff) +deref_off_post = Group(LBRACK + gpregs64_info.parser + + RBRACK + COMMA + int_or_expr64).setParseAction(deref2expr_post) +deref_off_pre = Group(LBRACK + gpregs64_info.parser + + COMMA + int_or_expr64 + RBRACK).setParseAction(deref2expr_pre) +deref_off_pre_wb = Group(LBRACK + gpregs64_info.parser + COMMA + + int_or_expr64 + RBRACK + POSTINC).setParseAction(deref2expr_pre_wb) + +deref = (deref_off_post | deref_off_pre_wb | deref_off_pre | deref_nooff) + + +def deref_ext2op(t): + t = t[0] + if len(t) == 4: + expr = set_imm_to_size(t[1].size, t[3]) + if expr is None: + raise StopIteration + return m2_expr.ExprOp('segm', t[0], m2_expr.ExprOp(t[2], t[1], expr)) + elif len(t) == 2: + return m2_expr.ExprOp('segm', t[0], t[1]) + + raise ValueError("cad deref") + +deref_ext2 = Group(LBRACK + gpregs_32_64 + COMMA + gpregs_32_64 + + Optional(all_extend2_t + int_or_expr) + RBRACK).setParseAction(deref_ext2op) + + +class additional_info: + + def __init__(self): + self.except_on_instr = False + self.lnk = None + self.cond = None + +CONDS = [ + 'EQ', 'NE', 'CS', 'CC', + 'MI', 'PL', 'VS', 'VC', + 'HI', 'LS', 'GE', 'LT', + 'GT', 'LE', 'AL', 'NV'] + +CONDS_INV = [ + 'NE', 'EQ', 'CC', 'CS', + 'PL', 'MI', 'VC', 'VS', + 'LS', 'HI', 'LT', 'GE', + 'LE', 'GT', 'NV', 'AL'] + +BRCOND = ['B.' + cond for cond in CONDS] + ['CBZ', 'CBNZ', 'TBZ', 'TBNZ'] + +# for conditional selec +conds_expr, _, conds_info = gen_regs(CONDS, {}) +conds_inv_expr, _, conds_inv_info = gen_regs(CONDS_INV, {}) + + +class instruction_aarch64(instruction): + delayslot = 0 + + def __init__(self, *args, **kargs): + super(instruction_aarch64, self).__init__(*args, **kargs) + + @staticmethod + def arg2str(e, pos=None): + wb = False + if isinstance(e, m2_expr.ExprId) or isinstance(e, m2_expr.ExprInt): + return str(e) + elif isinstance(e, m2_expr.ExprOp) and e.op in shift_expr: + op_str = shift_str[shift_expr.index(e.op)] + return "%s %s %s" % (e.args[0], op_str, e.args[1]) + elif isinstance(e, m2_expr.ExprOp) and e.op == "slice_at": + return "%s LSL %s" % (e.args[0], e.args[1]) + elif isinstance(e, m2_expr.ExprOp) and e.op in extend_lst: + op_str = e.op + return "%s %s %s" % (e.args[0], op_str, e.args[1]) + elif isinstance(e, m2_expr.ExprOp) and e.op == "postinc": + if e.args[1].arg != 0: + return "[%s], %s" % (e.args[0], e.args[1]) + else: + return "[%s]" % (e.args[0]) + elif isinstance(e, m2_expr.ExprOp) and e.op == "preinc_wb": + if e.args[1].arg != 0: + return "[%s, %s]!" % (e.args[0], e.args[1]) + else: + return "[%s]" % (e.args[0]) + elif isinstance(e, m2_expr.ExprOp) and e.op == "preinc": + if len(e.args) == 1: + return "[%s]" % (e.args[0]) + elif not isinstance(e.args[1], m2_expr.ExprInt) or e.args[1].arg != 0: + return "[%s, %s]" % (e.args[0], e.args[1]) + else: + return "[%s]" % (e.args[0]) + elif isinstance(e, m2_expr.ExprOp) and e.op == 'segm': + arg = e.args[1] + if isinstance(arg, m2_expr.ExprId): + arg = str(arg) + elif arg.op == 'LSL' and arg.args[1].arg == 0: + arg = str(arg.args[0]) + else: + arg = "%s %s %s" % (arg.args[0], arg.op, arg.args[1]) + return '[%s, %s]' % (e.args[0], arg) + + else: + raise NotImplementedError("bad op") + + def dstflow(self): + return self.name in self.name in BRCOND + ["B", "BL"] + + def mnemo_flow_to_dst_index(self, name): + if self.name in ['CBZ', 'CBNZ']: + return 1 + elif self.name in ['TBZ', 'TBNZ']: + return 2 + else: + return 0 + + def dstflow2label(self, symbol_pool): + index = self.mnemo_flow_to_dst_index(self.name) + e = self.args[index] + if not isinstance(e, m2_expr.ExprInt): + return + ad = e.arg + self.offset + l = symbol_pool.getby_offset_create(ad) + s = m2_expr.ExprId(l, e.size) + self.args[index] = s + + def breakflow(self): + return self.name in BRCOND + ["BR", "BLR", "RET", "ERET", "DRPS", "B", "BL"] + + def is_subcall(self): + return self.name in ["BLR", "BL"] + + def getdstflow(self, symbol_pool): + index = self.mnemo_flow_to_dst_index(self.name) + return [self.args[index]] + + def splitflow(self): + return self.name in BRCOND + ["BLR", "BL"] + + def get_symbol_size(self, symbol, symbol_pool): + return 64 + + def fixDstOffset(self): + index = self.mnemo_flow_to_dst_index(self.name) + e = self.args[index] + if self.offset is None: + raise ValueError('symbol not resolved %s' % l) + if not isinstance(e, m2_expr.ExprInt): + log.debug('dyn dst %r', e) + return + off = e.arg - self.offset + if int(off % 4): + raise ValueError('strange offset! %r' % off) + self.args[index] = m2_expr.ExprInt32(off) + + + +class mn_aarch64(cls_mn): + delayslot = 0 + name = "aarch64" + regs = regs_module + bintree = {} + num = 0 + all_mn = [] + all_mn_mode = defaultdict(list) + all_mn_name = defaultdict(list) + all_mn_inst = defaultdict(list) + pc = {'l': PC, 'b': PC} + sp = {'l': SP, 'b': SP} + instruction = instruction_aarch64 + max_instruction_len = 4 + alignment = 4 + + @classmethod + def getpc(cls, attrib=None): + return PC + + @classmethod + def getsp(cls, attrib=None): + return SP + + def additional_info(self): + info = additional_info() + info.lnk = False + if hasattr(self, "lnk"): + info.lnk = self.lnk.value != 0 + return info + + @classmethod + def getbits(cls, bs, attrib, start, n): + if not n: + return 0 + o = 0 + if n > bs.getlen() * 8: + raise ValueError('not enought bits %r %r' % (n, len(bs.bin) * 8)) + while n: + offset = start / 8 + n_offset = cls.endian_offset(attrib, offset) + c = cls.getbytes(bs, n_offset, 1) + if not c: + raise IOError + c = ord(c) + r = 8 - start % 8 + c &= (1 << r) - 1 + l = min(r, n) + c >>= (r - l) + o <<= l + o |= c + n -= l + start += l + return o + + @classmethod + def endian_offset(cls, attrib, offset): + if attrib == "l": + return (offset & ~3) + 3 - offset % 4 + elif attrib == "b": + return offset + else: + raise NotImplementedError('bad attrib') + + @classmethod + def check_mnemo(cls, fields): + l = sum([x.l for x in fields]) + assert l == 32, "len %r" % l + + @classmethod + def getmn(cls, name): + return name.upper() + + @classmethod + def mod_fields(cls, fields): + l = sum([x.l for x in fields]) + if l == 32: + return fields + return fields + + @classmethod + def gen_modes(cls, subcls, name, bases, dct, fields): + dct['mode'] = None + return [(subcls, name, bases, dct, fields)] + + def value(self, mode): + v = super(mn_aarch64, self).value(mode) + if mode == 'l': + return [x[::-1] for x in v] + elif mode == 'b': + return [x for x in v] + else: + raise NotImplementedError('bad attrib') + + def get_symbol_size(self, symbol, symbol_pool, mode): + return 32 + + def reset_class(self): + super(mn_aarch64, self).reset_class() + if hasattr(self, "sf"): + self.sf.value = None + + +def aarch64op(name, fields, args=None, alias=False): + dct = {"fields": fields, "alias":alias} + if args is not None: + dct['args'] = args + type(name, (mn_aarch64,), dct) + + +class aarch64_gpreg_noarg(reg_noarg): + parser = gpregs_32_64 + gpregs_info = gpregs_info + + def decode(self, v): + size = 64 if self.parent.sf.value else 32 + self.expr = self.gpregs_info[size].expr[v] + return True + + def encode(self): + if not test_set_sf(self.parent, self.expr.size): + return False + if not self.expr.size in self.gpregs_info: + return False + if not self.expr in self.gpregs_info[self.expr.size].expr: + return False + self.value = self.gpregs_info[self.expr.size].expr.index(self.expr) + return True + + +class aarch64_simdreg(reg_noarg, m_arg): + parser = simdregs + simd_size = [8, 16, 32, 64] + + def decode(self, v): + if self.parent.size.value > len(self.simd_size): + return False + size = self.simd_size[self.parent.size.value] + self.expr = simds_info[size].expr[v] + return True + + def encode(self): + if not self.expr.size in self.simd_size: + return False + if not self.expr in simds_info[self.expr.size].expr: + return False + self.value = simds_info[self.expr.size].expr.index(self.expr) + self.parent.size.value = self.simd_size.index(self.expr.size) + return True + + +class aarch64_simdreg_h(aarch64_simdreg): + parser = simdregs_h + simd_size = [32, 64, 128] + + +class aarch64_simdreg_32_64(aarch64_simdreg): + parser = simdregs_h + simd_size = [32, 64] + + +class aarch64_simdreg_32_64_zero(aarch64_simdreg_32_64): + parser = simdregs_h_zero + + def decode(self, v): + if v == 0 and self.parent.opc.value == 1: + size = 64 if self.parent.size.value else 32 + self.expr = m2_expr.ExprInt_fromsize(size, 0) + return True + else: + return super(aarch64_simdreg_32_64_zero, self).decode(v) + + def encode(self): + if isinstance(self.expr, m2_expr.ExprInt): + self.parent.opc.value = 1 + self.value = 0 + return True + else: + self.parent.opc.value = 0 + return super(aarch64_simdreg_32_64_zero, self).encode() + + +class aarch64_gpreg_isf(reg_noarg, m_arg): + parser = gpregs_32_64 + + def decode(self, v): + size = 32 if self.parent.sf.value else 64 + self.expr = gpregs_info[size].expr[v] + return True + + def encode(self): + if not self.expr in gpregs_info[self.expr.size].expr: + return False + self.value = gpregs_info[self.expr.size].expr.index(self.expr) + self.parent.sf.value = 1 if self.expr.size == 32 else 0 + return True + + +class aarch64_gpreg(aarch64_gpreg_noarg, m_arg): + pass + + +class aarch64_gpreg_n1(aarch64_gpreg): + + def decode(self, v): + if v == 0b11111: + return False + return super(aarch64_gpreg_n1, self).decode(v) + + def encode(self): + super(aarch64_gpreg_n1, self).encode() + return self.value != 0b11111 + + +class aarch64_gpregz(aarch64_gpreg_noarg, m_arg): + parser = gpregsz_32_64 + gpregs_info = gpregsz_info + + +class aarch64_gpreg0(bsi, m_arg): + parser = gpregsz_32_64 + gpregs_info = gpregsz_info + + def decode(self, v): + size = 64 if self.parent.sf.value else 32 + if v == 0x1F: + self.expr = m2_expr.ExprInt_fromsize(size, 0) + else: + self.expr = self.gpregs_info[size].expr[v] + return True + + def encode(self): + if isinstance(self.expr, m2_expr.ExprInt): + if self.expr.arg == 0: + self.value = 0x1F + return True + return False + if not self.expr.size in self.gpregs_info: + return False + if not test_set_sf(self.parent, self.expr.size): + return False + if not self.expr in self.gpregs_info[self.expr.size].expr: + return False + self.value = self.gpregs_info[self.expr.size].expr.index(self.expr) + return True + + +class aarch64_crreg(reg_noarg, m_arg): + reg_info = cr_info + parser = reg_info.parser + + +class aarch64_gpreg32_nodec(bsi): + reg_info = gpregs32_info + + +class aarch64_gpreg64_nodec(bsi): + reg_info = gpregs64_info + + +class aarch64_gpreg32_noarg(reg_noarg): + reg_info = gpregs32_info + parser = reg_info.parser + + +class aarch64_gpreg32(aarch64_gpreg32_noarg, m_arg): + reg_info = gpregs32_info + parser = reg_info.parser + + +class aarch64_gpreg64_noarg(reg_noarg): + reg_info = gpregs64_info + parser = reg_info.parser + + +class aarch64_gpreg64(reg_noarg, m_arg): + reg_info = gpregs64_info + parser = reg_info.parser + + +class aarch64_gpregz32_noarg(reg_noarg): + reg_info = gpregsz32_info + parser = reg_info.parser + + +class aarch64_gpregz32(aarch64_gpreg32_noarg, m_arg): + reg_info = gpregsz32_info + parser = reg_info.parser + + +class aarch64_gpregz64_noarg(reg_noarg): + reg_info = gpregsz64_info + parser = reg_info.parser + + +class aarch64_gpregz64(reg_noarg, m_arg): + reg_info = gpregsz64_info + parser = reg_info.parser + + +class aarch64_simd08_noarg(reg_noarg): + reg_info = simd08_info + parser = reg_info.parser + + +class aarch64_simd08(aarch64_simd08_noarg, m_arg): + reg_info = simd08_info + parser = reg_info.parser + + +class aarch64_simd16_noarg(reg_noarg): + reg_info = simd16_info + parser = reg_info.parser + + +class aarch64_simd16(aarch64_simd16_noarg, m_arg): + reg_info = simd16_info + parser = reg_info.parser + + +class aarch64_simd32_noarg(reg_noarg): + reg_info = simd32_info + parser = reg_info.parser + + +class aarch64_simd32(aarch64_simd32_noarg, m_arg): + reg_info = simd32_info + parser = reg_info.parser + + +class aarch64_simd64_noarg(reg_noarg): + reg_info = simd64_info + parser = reg_info.parser + + +class aarch64_simd64(aarch64_simd64_noarg, m_arg): + reg_info = simd64_info + parser = reg_info.parser + + +class aarch64_simd128_noarg(reg_noarg): + reg_info = simd128_info + parser = reg_info.parser + + +class aarch64_simd128(aarch64_simd128_noarg, m_arg): + reg_info = simd128_info + parser = reg_info.parser + + +class aarch64_imm_32(imm_noarg, m_arg): + parser = base_expr + + +class aarch64_imm_64(aarch64_imm_32): + parser = base_expr + + +class aarch64_int64_noarg(int32_noarg): + parser = base_expr + intsize = 64 + intmask = (1 << intsize) - 1 + int2expr = lambda self, x: m2_expr.ExprInt64( + sign_ext(x, self.l, self.intsize)) + + +class aarch64_uint64_noarg(imm_noarg): + parser = base_expr + intsize = 64 + intmask = (1 << intsize) - 1 + int2expr = lambda self, x: m2_expr.ExprInt64(x) + + +class aarch64_uint64(aarch64_uint64_noarg, m_arg): + parser = base_expr + + +def set_imm_to_size(size, expr): + if size == expr.size: + return expr + if size > expr.size: + expr = m2_expr.ExprInt_fromsize(size, expr.arg) + else: + if expr.arg > (1 << size) - 1: + return None + expr = m2_expr.ExprInt_fromsize(size, expr.arg) + return expr + + +class aarch64_imm_sf(imm_noarg): + parser = base_expr + + def fromstring(self, s, parser_result=None): + start, stop = super(aarch64_imm_sf, self).fromstring(s, parser_result) + if start is None: + return start, stop + size = self.parent.args[0].expr.size + if self.expr in gpregs64_info.expr + gpregs32_info.expr: + return None, None + if isinstance(self.expr, m2_expr.ExprOp): + return False + expr = set_imm_to_size(size, self.expr) + if expr is None: + return None, None + self.expr = expr + return start, stop + + def encode(self): + if not isinstance(self.expr, m2_expr.ExprInt): + return False + if not test_set_sf(self.parent, self.expr.size): + return False + value = int(self.expr.arg) + if value >= 1 << self.l: + return False + self.value = value + return True + + def decode(self, v): + size = 64 if self.parent.sf.value else 32 + self.expr = m2_expr.ExprInt_fromsize(size, v) + return True + + +class aarch64_imm_sft(aarch64_imm_sf, m_arg): + + def encode(self): + if not isinstance(self.expr, m2_expr.ExprInt): + return False + if not test_set_sf(self.parent, self.expr.size): + return False + value = int(self.expr.arg) + if value < 1 << self.l: + self.parent.shift.value = 0 + else: + if value & 0xFFF: + return False + value >>= 12 + if value >= 1 << self.l: + return False + self.parent.shift.value = 1 + self.value = value + return True + + def decode(self, v): + size = 64 if self.parent.sf.value else 32 + if self.parent.shift.value == 0: + self.expr = m2_expr.ExprInt_fromsize(size, v) + elif self.parent.shift.value == 1: + self.expr = m2_expr.ExprInt_fromsize(size, v << 12) + else: + return False + return True + +OPTION2SIZE = [32, 32, 32, 64, + 32, 32, 32, 64] + + +class aarch64_gpreg_ext(reg_noarg, m_arg): + parser = reg_ext_off + + def encode(self): + if not isinstance(self.expr, m2_expr.ExprOp): + return False + if self.expr.op not in extend_lst: + return False + reg, amount = self.expr.args + + if not reg in gpregs_info[self.expr.size].expr: + return False + self.value = gpregs_info[self.expr.size].expr.index(reg) + option = extend_lst.index(self.expr.op) + if self.expr.size != OPTION2SIZE[option]: + if not test_set_sf(self.parent, self.expr.size): + return False + self.parent.option.value = option + self.parent.imm.value = int(amount.arg) + return True + + def decode(self, v): + if self.parent.sf.value == 0: + size = 64 if self.parent.sf.value else 32 + else: + size = OPTION2SIZE[self.parent.option.value] + reg = gpregs_info[size].expr[v] + + self.expr = m2_expr.ExprOp(extend_lst[self.parent.option.value], + reg, m2_expr.ExprInt_from(reg, self.parent.imm.value)) + return True + +EXT2_OP = {0b010: 'UXTW', + 0b011: 'LSL', + 0b110: 'SXTW', + 0b111: 'SXTX'} +EXT2_OP_INV = dict([(items[1], items[0]) for items in EXT2_OP.items()]) + + +class aarch64_gpreg_ext2(reg_noarg, m_arg): + parser = deref_ext2 + + def get_size(self): + return self.parent.size.value + + def encode(self): + print "DECODE", self.expr + if not isinstance(self.expr, m2_expr.ExprOp): + return False + arg0, arg1 = self.expr.args + if not (isinstance(self.expr, m2_expr.ExprOp) and self.expr.op == 'segm'): + return False + print 'OKI' + if not arg0 in self.parent.rn.reg_info.expr: + return False + self.parent.rn.value = self.parent.rn.reg_info.expr.index(arg0) + print 'tt', arg0 + is_reg = False + self.parent.shift.value = 0 + if isinstance(arg1, m2_expr.ExprId): + reg = arg1 + self.parent.option.value = 0b011 + is_reg = True + elif isinstance(arg1, m2_expr.ExprOp) and arg1.op in EXT2_OP.values(): + reg = arg1.args[0] + else: + return False + print 'ISR', is_reg + if not (reg.size in gpregs_info and + reg in gpregs_info[reg.size].expr): + return False + self.value = gpregs_info[reg.size].expr.index(reg) + if is_reg: + return True + print 'test int', arg1.args + if not (isinstance(arg1.args[1], m2_expr.ExprInt)): + return False + if arg1.op not in EXT2_OP_INV: + return False + self.parent.option.value = EXT2_OP_INV[arg1.op] + if arg1.args[1].arg == 0: + self.parent.shift.value = 0 + return True + + if arg1.args[1].arg != self.get_size(): + return False + print "RR", arg1.args[1].arg + + self.parent.shift.value = 1 + + return True + + def decode(self, v): + opt = self.parent.option.value + if opt in [0, 1, 4, 5]: + return False + elif opt in [2, 6]: + reg_expr = gpregs32_info.expr + elif opt in [3, 7]: + reg_expr = gpregs64_info.expr + arg = reg_expr[v] + + if opt in EXT2_OP: + if self.parent.shift.value == 1: + arg = m2_expr.ExprOp(EXT2_OP[opt], arg, + m2_expr.ExprInt_from(arg, self.get_size())) + else: + arg = m2_expr.ExprOp(EXT2_OP[opt], arg, + m2_expr.ExprInt_from(arg, 0)) + + reg = self.parent.rn.reg_info.expr[self.parent.rn.value] + self.expr = m2_expr.ExprOp('segm', reg, arg) + return True + + +class aarch64_gpreg_ext2_128(aarch64_gpreg_ext2): + + def get_size(self): + return 4 + + +def test_set_sf(parent, size): + if not hasattr(parent, 'sf'): + return False + if parent.sf.value == None: + parent.sf.value = 1 if size == 64 else 0 + return True + psize = 64 if parent.sf.value else 32 + return psize == size + + +class aarch64_gpreg_sftimm(reg_noarg, m_arg): + reg_info = gpregsz_info + parser = shift_off + + def encode(self): + size = self.expr.size + if not test_set_sf(self.parent, size): + return False + if isinstance(self.expr, m2_expr.ExprId): + if not size in gpregs_info: + return False + if not self.expr in self.reg_info[size].expr: + return False + self.parent.shift.value = 0 + self.parent.imm.value = 0 + self.value = self.reg_info[size].expr.index(self.expr) + return True + + if not isinstance(self.expr, m2_expr.ExprOp): + return False + if not self.expr.op in shift_expr: + return False + args = self.expr.args + if not args[0] in self.reg_info[size].expr: + return False + if not isinstance(args[1], m2_expr.ExprInt): + return False + self.parent.shift.value = shift_expr.index(self.expr.op) + self.parent.imm.value = int(args[1].arg) + self.value = self.reg_info[size].expr.index(args[0]) + return True + + def decode(self, v): + size = 64 if self.parent.sf.value else 32 + e = self.reg_info[size].expr[v] + amount = self.parent.imm.value + if amount != 0: + e = m2_expr.ExprOp( + shift_expr[self.parent.shift.value], e, m2_expr.ExprInt_from(e, amount)) + self.expr = e + return True + + +def ror(value, amount, size): + return (value >> amount) | (value << (size - amount)) + + +def rol(value, amount, size): + return (value << amount) | (value >> (size - amount)) + +UINTS = {32: uint32, 64: uint64} + + +def imm_to_imm_rot_form(value, size): + for i in xrange(0, size): + mod_value = int(rol(value, i, size)) + if (mod_value + 1) & mod_value == 0: + return i + return None + + +class aarch64_imm_nsr(aarch64_imm_sf, m_arg): + parser = base_expr + + def decode(self, v): + size = 64 if self.parent.sf.value else 32 + mask = UINTS[size]((1 << (v + 1)) - 1) + mask = ror(mask, self.parent.immr.value, size) + self.expr = m2_expr.ExprInt_fromsize(size, mask) + return True + + def encode(self): + if not isinstance(self.expr, m2_expr.ExprInt): + return False + if not test_set_sf(self.parent, self.expr.size): + return False + value = self.expr.arg + if value == 0: + return False + + index = imm_to_imm_rot_form(value, self.expr.size) + if index == None: + return False + power = int(rol(value, index, self.expr.size)) + 1 + length = None + for i in xrange(self.expr.size): + if 1 << i == power: + length = i + break + if length is None: + return False + self.parent.immr.value = index + self.value = length - 1 + self.parent.immn.value = 1 if self.expr.size == 64 else 0 + return True + + +class aarch64_pcoff(aarch64_imm_32): + parser = base_expr + + +class aarch64_immhip_page(aarch64_imm_32): + parser = base_expr + + def decode(self, v): + v = ((v << 2) | self.parent.immlo.value) << 12 + v = sign_ext(v, 33, 64) + self.expr = m2_expr.ExprInt64(v) + return True + + def encode(self): + v = int(self.expr.arg) + if v & (1 << 63): + v &= (1 << 33) - 1 + if v & 0xfff: + return False + v >>= 12 + self.parent.immlo.value = v & 3 + v >>= 2 + self.value = v + return True + + +class aarch64_immhi_page(aarch64_imm_32): + parser = base_expr + + def decode(self, v): + v = ((v << 2) | self.parent.immlo.value) + v = sign_ext(v, 21, 64) + self.expr = m2_expr.ExprInt64(v) + return True + + def encode(self): + v = int(self.expr.arg) + if v & (1 << 63): + v &= (1 << 33) - 1 + self.parent.immlo.value = v & 3 + v >>= 2 + if v > (1 << 19) - 1: + return False + self.value = v & ((1 << 19) - 1) + return True + + +class aarch64_imm_hw(m_arg): + parser = base_expr + shift_op = '<<' + + def decode(self, v): + size = 64 if self.parent.sf.value else 32 + self.expr = m2_expr.ExprInt_fromsize(size, v << (16 * self.parent.hw.value)) + return True + + def encode(self): + if not isinstance(self.expr, m2_expr.ExprInt): + return False + size = self.parent.args[0].expr.size + if set_imm_to_size(size, self.expr) is None: + return False + value = int(self.expr.arg) + mask = (1 << size) - 1 + for i in xrange(size / 16): + if ((0xffff << (i * 16)) ^ mask) & value: + continue + self.parent.hw.value = i + self.value = value >> (i * 16) + return True + return False + + +class aarch64_imm_hw_sc(m_arg): + parser = shiftimm_off_sc + shift_op = 'slice_at' + + def decode(self, v): + size = 64 if self.parent.sf.value else 32 + expr = m2_expr.ExprInt_fromsize(size, v) + amount = m2_expr.ExprInt_fromsize(size, 16 * self.parent.hw.value) + if self.parent.hw.value: + self.expr = m2_expr.ExprOp(self.shift_op, expr, amount) + else: + self.expr = expr + return True + + def encode(self): + if isinstance(self.expr, m2_expr.ExprInt): + if self.expr.arg > 0xFFFF: + return False + self.value = int(self.expr.arg) + self.parent.hw.value = 0 + return True + + if not (isinstance(self.expr, m2_expr.ExprOp) and + self.expr.op == self.shift_op and + len(self.expr.args) == 2 and + isinstance(self.expr.args[0], m2_expr.ExprInt) and + isinstance(self.expr.args[1], m2_expr.ExprInt)): + return False + if set_imm_to_size(self.parent.args[0].expr.size, self.expr.args[0]) is None: + return False + if set_imm_to_size(self.parent.args[0].expr.size, self.expr.args[1]) is None: + return False + arg, amount = [int(arg.arg) for arg in self.expr.args] + if arg > 0xFFFF: + return False + if amount % 16 or amount / 16 > 4: + return False + self.value = arg + self.parent.hw.value = amount / 16 + return True + + +class aarch64_offs(imm_noarg, m_arg): + parser = base_expr + + def decode(self, v): + v = v & self.lmask + v = (v << 2) + v = sign_ext(v, (self.l + 2), 64) + self.expr = m2_expr.ExprInt64(v) + return True + + def encode(self): + if not isinstance(self.expr, m2_expr.ExprInt): + return False + v = int(self.expr.arg) + if v & (1 << 63): + v &= (1 << (self.l + 2)) - 1 + self.value = v >> 2 + return True + + +def set_mem_off(parent, imm): + if hasattr(parent, 'simm'): + mask = (1 << parent.simm.l) - 1 + if imm != sign_ext(imm & mask, parent.simm.l, 64): + return False + parent.simm.value = imm & mask + elif hasattr(parent, 'uimm'): + mask = (1 << parent.uimm.l) - 1 + if imm > mask: + return False + parent.uimm.value = imm + else: + raise ValueError('unknown imm') + return True + + +def get_size(parent): + if not hasattr(parent, "size"): + return 0 + if hasattr(parent.size, "amount"): + size = parent.size.amount + else: + size = parent.size.value + return size + + +class aarch64_deref(m_arg): + parser = deref + + def decode_w_size(self, off): + return off + + def encode_w_size(self, off): + return off + + def get_postpre(self, parent): + if hasattr(self.parent, "postpre"): + if self.parent.postpre.value == 0: + op = 'postinc' + else: + op = 'preinc_wb' + else: + op = 'preinc' + return op + + def decode(self, v): + reg = gpregs64_info.expr[v] + off = self.parent.imm.expr.arg + op = self.get_postpre(self.parent) + off = self.decode_w_size(off) + self.expr = m2_expr.ExprOp(op, reg, m2_expr.ExprInt64(off)) + return True + + def encode(self): + expr = self.expr + if not isinstance(expr, m2_expr.ExprOp): + return False + if not expr.op in ['postinc', 'preinc_wb', 'preinc']: + return False + if hasattr(self.parent, "postpre"): + if expr.op == 'postinc': + self.parent.postpre.value = 0 + else: + self.parent.postpre.value = 1 + reg, off = expr.args + if not reg in gpregs64_info.expr: + return False + if not isinstance(off, m2_expr.ExprInt): + return False + imm = int(off.arg) + imm = self.encode_w_size(imm) + if imm is False: + return False + self.parent.imm.expr = m2_expr.ExprInt64(imm) + if not self.parent.imm.encode(): + return False + self.value = gpregs64_info.expr.index(reg) + return True + + +class aarch64_deref_size(aarch64_deref): + + def decode_w_size(self, off): + size = get_size(self.parent) + return off << size + + def encode_w_size(self, off): + size = get_size(self.parent) + if size: + if off & ((1 << size) - 1): + return False + off >>= size + return off + + +class aarch64_deref_nooff(aarch64_deref): + parser = deref_nooff + + def decode(self, v): + reg = gpregs64_info.expr[v] + self.expr = m2_expr.ExprOp('preinc', reg) + return True + + def encode(self): + expr = self.expr + if not isinstance(expr, m2_expr.ExprOp): + return False + if expr.op != 'preinc': + return False + if len(expr.args) == 1: + reg = expr.args[0] + elif len(expr.args) == 2: + reg, off = expr.args + if not isinstance(off, m2_expr.ExprInt): + return False + if off.arg != 0: + return False + else: + return False + + if not reg in gpregs64_info.expr: + return False + self.value = gpregs64_info.expr.index(reg) + return True + + +class aarch64_sf_scale(aarch64_deref): + size2scale = {32: 2, 64: 3} + + def decode_w_size(self, off): + size = 2 + self.parent.sf.value + return off << size + + def encode_w_size(self, off): + size = self.parent.args[0].expr.size + if not size in self.size2scale: + return False + scale = self.size2scale[size] + off = int(mod_size2int[size](off) >> scale) + return off + + +class aarch64_sd_scale(aarch64_sf_scale): + size2scale = {32: 2, 64: 3, 128: 4} + + def decode_w_size(self, off): + size = 2 + self.parent.size.value + return off << size + + +class aarch64_eq(bsi): + + def decode(self, v): + return getattr(self.parent, self.ref).value == v + + def encode(self): + self.value = getattr(self.parent, self.ref).value + return True +modf = bs_mod_name(l=1, fname='modf', mn_mod=['', 'S']) +sf = bs(l=1, fname='sf', order=-1) + + +class aarch64_cond_arg(reg_noarg, m_arg): + reg_info = conds_info + parser = reg_info.parser + + +class aarch64_cond_inv_arg(reg_noarg, m_arg): + reg_info = conds_inv_info + parser = reg_info.parser + + +class aarch64_b40(m_arg): + parser = base_expr + + def decode(self, v): + self.expr = m2_expr.ExprInt_from( + self.parent.rt.expr, (self.parent.sf.value << self.l) | v) + return True + + def encode(self): + if not isinstance(self.expr, m2_expr.ExprInt): + return False + size = self.parent.args[0].expr.size + value = int(self.expr.arg) + self.value = value & self.lmask + print 'TT', hex(value) + if self.parent.sf.value is None: + self.parent.sf.value = value >> self.l + return True + else: + return value >> self.l == self.parent.sf.value + + +shift = bs(l=2, fname='shift') + +shiftb = bs(l=1, fname='shift', order=-1) + + +rn64_v = bs(l=5, cls=(aarch64_gpreg64_nodec,), fname='rn', order=-1) + +rn = bs(l=5, cls=(aarch64_gpreg,), fname="rn") +rs = bs(l=5, cls=(aarch64_gpreg,), fname="rs") +rm = bs(l=5, cls=(aarch64_gpreg,), fname="rm") +rd = bs(l=5, cls=(aarch64_gpreg,), fname="rd") +ra = bs(l=5, cls=(aarch64_gpregz,), fname="ra") +rt = bs(l=5, cls=(aarch64_gpreg,), fname="rt") +rt2 = bs(l=5, cls=(aarch64_gpreg,), fname="rt2") +rn0 = bs(l=5, cls=(aarch64_gpreg0,), fname="rn") + + +rn_n1 = bs(l=5, cls=(aarch64_gpreg_n1,), fname="rn") +rm_n1 = bs(l=5, cls=(aarch64_gpreg_n1,), fname="rm") + + +rn_na = bs(l=5, cls=(aarch64_gpreg_noarg,), fname="rn", order=-1) +rn32_na = bs(l=5, cls=(aarch64_gpreg32_noarg,), fname="rn", order=-1) +rn64_na = bs(l=5, cls=(aarch64_gpreg64_noarg,), fname="rn", order=-1) + +sd1 = bs(l=5, cls=(aarch64_simdreg_h,), fname="rt") +sd2 = bs(l=5, cls=(aarch64_simdreg_h,), fname="rt2") + +sdn_32_64 = bs(l=5, cls=(aarch64_simdreg_32_64,), fname="rn") +sdd_32_64 = bs(l=5, cls=(aarch64_simdreg_32_64,), fname="rd") +sdm_32_64 = bs(l=5, cls=(aarch64_simdreg_32_64,), fname="rm") +sda_32_64 = bs(l=5, cls=(aarch64_simdreg_32_64,), fname="ra") + + +sdm_32_64_zero = bs(l=5, cls=(aarch64_simdreg_32_64_zero,), fname="rm") + +crn = bs(l=4, cls=(aarch64_crreg,), fname="crn") +crm = bs(l=4, cls=(aarch64_crreg,), fname="crm") + + +rn64 = bs(l=5, cls=(aarch64_gpreg64,), fname="rn") +rs64 = bs(l=5, cls=(aarch64_gpreg64,), fname="rs") +rm64 = bs(l=5, cls=(aarch64_gpreg64,), fname="rm") +rd64 = bs(l=5, cls=(aarch64_gpreg64,), fname="rd") +rt64 = bs(l=5, cls=(aarch64_gpregz64,), fname="rt") +ra64 = bs(l=5, cls=(aarch64_gpregz64,), fname="ra") + +rn32 = bs(l=5, cls=(aarch64_gpreg32,), fname="rn") +rm32 = bs(l=5, cls=(aarch64_gpreg32,), fname="rm") +rd32 = bs(l=5, cls=(aarch64_gpreg32,), fname="rd") +rs32 = bs(l=5, cls=(aarch64_gpreg32,), fname="rs") + +sd08 = bs(l=5, cls=(aarch64_simd08,), fname="rd") +sd16 = bs(l=5, cls=(aarch64_simd16,), fname="rd") +sd32 = bs(l=5, cls=(aarch64_simd32,), fname="rd") +sd64 = bs(l=5, cls=(aarch64_simd64,), fname="rd") +sd128 = bs(l=5, cls=(aarch64_simd128,), fname="rd") + +sn08 = bs(l=5, cls=(aarch64_simd08,), fname="rn") +sn16 = bs(l=5, cls=(aarch64_simd16,), fname="rn") +sn32 = bs(l=5, cls=(aarch64_simd32,), fname="rn") +sn64 = bs(l=5, cls=(aarch64_simd64,), fname="rn") +sn128 = bs(l=5, cls=(aarch64_simd128,), fname="rn") + + +rt32 = bs(l=5, cls=(aarch64_gpregz32,), fname="rt") + +rt_isf = bs(l=5, cls=(aarch64_gpreg_isf,), fname="rt") + +rn64_deref = bs(l=5, cls=(aarch64_deref,), fname="rn") +rn64_deref_sz = bs(l=5, cls=(aarch64_deref_size,), fname="rn") +rn64_deref_sf = bs(l=5, cls=(aarch64_sf_scale,), fname="rn") +rn64_deref_sd = bs(l=5, cls=(aarch64_sd_scale,), fname="rn") + +rn64_deref_nooff = bs(l=5, cls=(aarch64_deref_nooff,), fname="rn") + +imm_sft_12 = bs(l=12, cls=(aarch64_imm_sft,)) + +# imm32_3 = bs(l=3, cls=(aarch64_imm_32,)) +imm32_3 = bs(l=3, fname="imm") +imm6 = bs(l=6, fname="imm", order=-1) +imm3 = bs(l=3, fname="imm", order=-1) +simm6 = bs(l=6, cls=(aarch64_int64_noarg, m_arg), fname="imm", order=-1) +simm9 = bs(l=9, cls=(aarch64_int64_noarg,), fname="imm", order=-1) +simm7 = bs(l=7, cls=(aarch64_int64_noarg,), fname="imm", order=-1) +nzcv = bs(l=4, cls=(aarch64_uint64_noarg, m_arg), fname="nzcv", order=-1) +uimm5 = bs(l=5, cls=(aarch64_uint64_noarg, m_arg), fname="imm", order=-1) +uimm12 = bs(l=12, cls=(aarch64_uint64_noarg,), fname="imm", order=-1) +uimm16 = bs(l=16, cls=(aarch64_uint64_noarg, m_arg), fname="imm", order=-1) +uimm7 = bs(l=7, cls=(aarch64_uint64_noarg,), fname="imm", order=-1) + +uimm8 = bs(l=8, cls=(aarch64_uint64,), fname="imm", order=-1) + +op1 = bs(l=3, cls=(aarch64_uint64, m_arg), fname="op1") +op2 = bs(l=3, cls=(aarch64_uint64, m_arg), fname="op2") + + +imm16 = bs(l=16, fname="imm", order=-1) + + +immlo = bs(l=2, fname='immlo') +immhip = bs(l=19, cls=(aarch64_immhip_page,)) +immhi = bs(l=19, cls=(aarch64_immhi_page,)) + +option = bs(l=3, fname='option', order=-1) + + +rm_ext = bs(l=5, cls=(aarch64_gpreg_ext,), fname="rm") +rm_sft = bs(l=5, cls=(aarch64_gpreg_sftimm,), fname="rm") + +rm_ext2 = bs(l=5, cls=(aarch64_gpreg_ext2,), fname="rm") +rm_ext2_128 = bs(l=5, cls=(aarch64_gpreg_ext2_128,), fname="rm") + + +imms = bs(l=6, cls=(aarch64_imm_nsr,), fname='imms') +immr = bs(l=6, fname='immr') +immn = bs(l=1, fname='immn') + + +imm16_hw = bs(l=16, cls=(aarch64_imm_hw,), fname='imm') +imm16_hw_sc = bs(l=16, cls=(aarch64_imm_hw_sc,), fname='imm') +hw = bs(l=2, fname='hw') + + +a_imms = bs(l=6, cls=(aarch64_imm_sf, m_arg), fname="imm1", order=-1) +a_immr = bs(l=6, cls=(aarch64_imm_sf, m_arg), fname="imm1", order=-1) + + + +adsu_name = {'ADD': 0, 'SUB': 1} +bs_adsu_name = bs_name(l=1, name=adsu_name) + + +offs19 = bs(l=19, cls=(aarch64_offs,), fname='off') +offs26 = bs(l=26, cls=(aarch64_offs,), fname='off') +offs14 = bs(l=14, cls=(aarch64_offs,), fname='off') + +b40 = bs(l=5, cls=(aarch64_b40,), fname='b40', order=1) + +sdsize1 = bs(l=1, fname="size") + +sdsize = bs(l=2, fname="size") +opsize = bs(l=2, fname="size") +sd = bs(l=5, cls=(aarch64_simdreg,), fname='sd') + +opc = bs(l=1, fname='opc', order=-1) + +# add/sub (imm) +aarch64op("addsub", [sf, bs_adsu_name, modf, bs('10001'), shift, imm_sft_12, rn, rd], [rd, rn, imm_sft_12]) +aarch64op("cmp", [sf, bs('1'), bs('1'), bs('10001'), shift, imm_sft_12, rn, bs('11111')], [rn, imm_sft_12], alias=True) +aarch64op("cmn", [sf, bs('0'), bs('1'), bs('10001'), shift, imm_sft_12, rn, bs('11111')], [rn, imm_sft_12], alias=True) + +aarch64op("adrp", [bs('1'), immlo, bs('10000'), immhip, rd64], [rd64, immhip]) +aarch64op("adr", [bs('0'), immlo, bs('10000'), immhi, rd64], [rd64, immhi]) + +# add/sub (reg shift) +aarch64op("addsub", [sf, bs_adsu_name, modf, bs('01011'), shift, bs('0'), rm_sft, imm6, rn, rd], [rd, rn, rm_sft]) +aarch64op("cmp", [sf, bs('1'), bs('1'), bs('01011'), shift, bs('0'), rm_sft, imm6, rn, bs('11111')], [rn, rm_sft], alias=True) +# add/sub (reg ext) +aarch64op("addsub", [sf, bs_adsu_name, modf, bs('01011'), bs('00'), bs('1'), rm_ext, option, imm3, rn, rd], [rd, rn, rm_ext]) +#aarch64op("cmp", [sf, bs('1'), bs('1'), bs('01011'), bs('00'), bs('1'), rm_ext, option, imm3, rn, bs('11111')], [rn, rm_ext], alias=True) + + +aarch64op("neg", [sf, bs('1'), modf, bs('01011'), shift, bs('0'), rm_sft, imm6, bs('11111'), rd], [rd, rm_sft], alias=True) + + +logic_name = {'AND': 0, 'ORR': 1, 'EOR': 2, 'ANDS': 3} +bs_logic_name = bs_name(l=2, name=logic_name) +# logical (imm) +aarch64op("logic", [sf, bs_logic_name, bs('100100'), immn, immr, imms, rn0, rd], [rd, rn0, imms]) + +# bitfield move p.149 +logicbf_name = {'SBFM': 0b00, 'BFM': 0b01, 'UBFM': 0b10} +bs_logicbf_name = bs_name(l=2, name=logicbf_name) +aarch64op("logic", [sf, bs_logicbf_name, bs('100110'), bs(l=1, cls=(aarch64_eq,), ref="sf"), a_immr, a_imms, rn, rd], [rd, rn, a_immr, a_imms]) + + +# logical (reg shift) +aarch64op("and", [sf, bs('00'), bs('01010'), shift, bs('0'), rm_sft, imm6, rn, rd], [rd, rn, rm_sft]) +aarch64op("bic", [sf, bs('00'), bs('01010'), shift, bs('1'), rm_sft, imm6, rn, rd], [rd, rn, rm_sft]) +aarch64op("orr", [sf, bs('01'), bs('01010'), shift, bs('0'), rm_sft, imm6, rn, rd], [rd, rn, rm_sft]) +aarch64op("orn", [sf, bs('01'), bs('01010'), shift, bs('1'), rm_sft, imm6, rn, rd], [rd, rn, rm_sft]) +aarch64op("mvn", [sf, bs('01'), bs('01010'), shift, bs('1'), rm_sft, imm6, bs('11111'), rd], [rd, rm_sft], alias=True) +aarch64op("eor", [sf, bs('10'), bs('01010'), shift, bs('0'), rm_sft, imm6, rn, rd], [rd, rn, rm_sft]) +aarch64op("eon", [sf, bs('10'), bs('01010'), shift, bs('1'), rm_sft, imm6, rn, rd], [rd, rn, rm_sft]) +aarch64op("ands", [sf, bs('11'), bs('01010'), shift, bs('0'), rm_sft, imm6, rn, rd], [rd, rn, rm_sft]) +aarch64op("tst", [sf, bs('11'), bs('01010'), shift, bs('0'), rm_sft, imm6, rn, bs('11111')], [rn, rm_sft]) +aarch64op("bics", [sf, bs('11'), bs('01010'), shift, bs('1'), rm_sft, imm6, rn, rd], [rd, rn, rm_sft]) + +# move reg +aarch64op("mov", [sf, bs('01'), bs('01010'), bs('00'), bs('0'), rm, bs('000000'), bs('11111'), rd], [rd, rm], alias=True) + + + +bcond = bs_mod_name(l=4, fname='cond', mn_mod=['EQ', 'NE', 'CS', 'CC', + 'MI', 'PL', 'VS', 'VC', + 'HI', 'LS', 'GE', 'LT', + 'GT', 'LE', 'AL', 'NV']) + +cond_arg = bs(l=4, cls=(aarch64_cond_arg,), fname=cond) +cond_inv_arg = bs(l=4, cls=(aarch64_cond_inv_arg,), fname=cond) +# unconditional branch (ret) +aarch64op("br", [bs('1101011'), bs('0000'), bs('11111'), bs('000000'), rn64, bs('00000')], [rn64]) +aarch64op("blr", [bs('1101011'), bs('0001'), bs('11111'), bs('000000'), rn64, bs('00000')], [rn64]) +aarch64op("ret", [bs('1101011'), bs('0010'), bs('11111'), bs('000000'), rn64, bs('00000')], [rn64]) +aarch64op("eret", [bs('1101011'), bs('0100'), bs('11111'), bs('000000'), bs('11111'), bs('00000')]) +aarch64op("drps", [bs('1101011'), bs('0101'), bs('11111'), bs('000000'), bs('11111'), bs('00000')]) + +# unconditional branch (imm) +aarch64op("b", [bs('0'), bs('00101'), offs26], [offs26]) +aarch64op("bl", [bs('1'), bs('00101'), offs26], [offs26]) + + +post_pre = bs(l=1, order=-1, fname='postpre') + +# conditional compare (imm) p.158 +ccmp_name = {'CCMN': 0, 'CCMP': 1} +bs_ccmp_name = bs_name(l=1, name=ccmp_name) +aarch64op("condcmp", [sf, bs_ccmp_name, bs('1'), bs('11010010'), uimm5, cond_arg, bs('1'), bs('0'), rn, bs('0'), nzcv], [rn, uimm5, nzcv, cond_arg]) +aarch64op("condcmp", [sf, bs_ccmp_name, bs('1'), bs('11010010'), rm, cond_arg, bs('0'), bs('0'), rn, bs('0'), nzcv], [rn, rm, nzcv, cond_arg]) + +ldst_b_name = {'STRB': 0, 'LDRB': 1} +bs_ldst_b_name = bs_name(l=1, name=ldst_b_name) +ldst_name = {'STR': 0, 'LDR': 1} +bs_ldst_name = bs_name(l=1, name=ldst_name) +ldst_h_name = {'STRH': 0, 'LDRH': 1} +bs_ldst_h_name = bs_name(l=1, name=ldst_h_name) + +ldst_tb_name = {'STTRB': 0, 'LDTRB': 1} +bs_ldst_tb_name = bs_name(l=1, name=ldst_tb_name) + +ldst_th_name = {'STTRH': 0, 'LDTRH': 1} +bs_ldst_th_name = bs_name(l=1, name=ldst_th_name) + +ldst_ub_name = {'STURB': 0, 'LDURB': 1} +bs_ldst_ub_name = bs_name(l=1, name=ldst_ub_name) +ldst_u_name = {'STUR': 0, 'LDUR': 1} +bs_ldst_u_name = bs_name(l=1, name=ldst_u_name) + +ldst_t_name = {'STTR': 0, 'LDTR': 1} +bs_ldst_st_name = bs_name(l=1, name=ldst_t_name) + +ldst_1u_name = {'STUR': 0b0, 'LDUR': 0b1} +bs_ldst_1u_name = bs_name(l=1, name=ldst_1u_name) + +ldst_uh_name = {'STURH': 0, 'LDURH': 1} +bs_ldst_uh_name = bs_name(l=1, name=ldst_uh_name) + + +ldst_sw_name = {'STRSW': 0, 'LDRSW': 1} +bs_ldst_sw_name = bs_name(l=1, name=ldst_sw_name) + +# load/store register (imm post index) +aarch64op("ldst", [bs('00'), bs('111'), bs('0'), bs('00'), bs('0'), bs_ldst_b_name, bs('0'), simm9, post_pre, bs('1'), rn64_deref, rt32], [rt32, rn64_deref ]) +aarch64op("ldrsb", [bs('00'), bs('111'), bs('0'), bs('00'), bs('1'), sf, bs('0'), simm9, post_pre, bs('1'), rn64_deref, rt_isf], [rt_isf, rn64_deref ]) +aarch64op("ldrsh", [bs('01'), bs('111'), bs('0'), bs('00'), bs('1'), sf, bs('0'), simm9, post_pre, bs('1'), rn64_deref, rt_isf], [rt_isf, rn64_deref ]) +aarch64op("ldst", [bs('01'), bs('111'), bs('0'), bs('00'), bs('0'), bs_ldst_h_name, bs('0'), simm9, post_pre, bs('1'), rn64_deref, rt32], [rt32, rn64_deref ]) +aarch64op("ldst", [bs('10'), bs('111'), bs('0'), bs('00'), bs('0'), bs_ldst_name, bs('0'), simm9, post_pre, bs('1'), rn64_deref, rt32], [rt32, rn64_deref ]) +aarch64op("ldrsw", [bs('10'), bs('111'), bs('0'), bs('00'), bs('10'), bs('0'), simm9, post_pre, bs('1'), rn64_deref, rt64], [rt64, rn64_deref ]) +aarch64op("ldst", [bs('11'), bs('111'), bs('0'), bs('00'), bs('0'), bs_ldst_name, bs('0'), simm9, post_pre, bs('1'), rn64_deref, rt64], [rt64, rn64_deref ]) + +aarch64op("ldst", [sdsize, bs('111'), bs('1'), bs('00'), bs('0'), bs_ldst_name, bs('0'), simm9, post_pre, bs('1'), rn64_deref, sd], [sd, rn64_deref ]) +aarch64op("ldst", [bs('00'), bs('111'), bs('1'), bs('00'), bs('1'), bs_ldst_name, bs('0'), simm9, post_pre, bs('1'), rn64_deref, sd128], [sd128, rn64_deref ]) + +# load/store register (unsigned imm) +aarch64op("ldst", [bs('00', fname="size"), bs('111'), bs('0'), bs('01'), bs('0'), bs_ldst_b_name, uimm12, rn64_deref_sz, rt32], [rt32, rn64_deref_sz ]) +aarch64op("ldrsb", [bs('00', fname="size"), bs('111'), bs('0'), bs('01'), bs('1'), sf, uimm12, rn64_deref_sz, rt_isf], [rt_isf, rn64_deref_sz ]) +aarch64op("ldrsh", [bs('01', fname="size"), bs('111'), bs('0'), bs('01'), bs('1'), sf, uimm12, rn64_deref_sz, rt_isf], [rt_isf, rn64_deref_sz ]) +aarch64op("ldst", [bs('01', fname="size"), bs('111'), bs('0'), bs('01'), bs('0'), bs_ldst_h_name, uimm12, rn64_deref_sz, rt32], [rt32, rn64_deref_sz ]) +aarch64op("ldst", [bs('10', fname="size"), bs('111'), bs('0'), bs('01'), bs('0'), bs_ldst_name, uimm12, rn64_deref_sz, rt32], [rt32, rn64_deref_sz ]) +aarch64op("ldrsw", [bs('10', fname="size"), bs('111'), bs('0'), bs('01'), bs('10'), uimm12, rn64_deref_sz, rt64], [rt64, rn64_deref_sz ]) +aarch64op("ldst", [bs('11', fname="size"), bs('111'), bs('0'), bs('01'), bs('0'), bs_ldst_name, uimm12, rn64_deref_sz, rt64], [rt64, rn64_deref_sz ]) + +aarch64op("ldst", [sdsize, bs('111'), bs('1'), bs('01'), bs('0'), bs_ldst_name, uimm12, rn64_deref_sz, sd], [sd, rn64_deref_sz ]) +aarch64op("ldst", [bs('00'), bs('111'), bs('1'), bs('01'), bs('1', fname='size', amount=4), bs_ldst_name, uimm12, rn64_deref_sz, sd128], [sd128, rn64_deref_sz ]) + +# load/store register (unp) +aarch64op("ldst", [bs('00'), bs('111'), bs('0'), bs('00'), bs('0'), bs_ldst_tb_name, bs('0'), simm9, bs('10'), rn64_deref, rt32], [rt32, rn64_deref ]) +aarch64op("ldtrsb", [bs('00'), bs('111'), bs('0'), bs('00'), bs('1'), sf, bs('0'), simm9, bs('10'), rn64_deref, rt_isf], [rt_isf, rn64_deref ]) +aarch64op("ldtrsh", [bs('01'), bs('111'), bs('0'), bs('00'), bs('1'), sf, bs('0'), simm9, bs('10'), rn64_deref, rt_isf], [rt_isf, rn64_deref ]) +aarch64op("ldsttrh",[bs('01'), bs('111'), bs('0'), bs('00'), bs('0'), bs_ldst_th_name, bs('0'), simm9, bs('10'), rn64_deref, rt32], [rt32, rn64_deref ]) +aarch64op("ldtrsw", [bs('10'), bs('111'), bs('0'), bs('00'), bs('10'), bs('0'), simm9, bs('10'), rn64_deref, rt64], [rt64, rn64_deref ]) +aarch64op("ldstt", [bs('1'), sf, bs('111'), bs('0'), bs('00'), bs('0'), bs_ldst_st_name, bs('0'), simm9, bs('10'), rn64_deref, rt], [rt, rn64_deref ]) + +aarch64op("ldstt", [sdsize, bs('111'), bs('1'), bs('00'), bs('0'), bs_ldst_st_name, bs('0'), simm9, bs('10'), rn64_deref, sd], [sd, rn64_deref ]) +aarch64op("ldst", [bs('00'), bs('111'), bs('1'), bs('00'), bs('1'), bs_ldst_st_name, bs('0'), simm9, bs('10'), rn64_deref, sd128], [sd128, rn64_deref ]) + +# load/store register (unscaled imm) +aarch64op("ldst", [bs('00'), bs('111'), bs('0'), bs('00'), bs('0'), bs_ldst_ub_name, bs('0'), simm9, bs('00'), rn64_deref, rt32], [rt32, rn64_deref ]) +aarch64op("ldursb", [bs('00'), bs('111'), bs('0'), bs('00'), bs('1'), sf, bs('0'), simm9, bs('00'), rn64_deref, rt_isf], [rt_isf, rn64_deref ]) +aarch64op("ldstuh", [bs('01'), bs('111'), bs('0'), bs('00'), bs('0'), bs_ldst_uh_name, bs('0'), simm9, bs('00'), rn64_deref, rt32], [rt32, rn64_deref ]) +aarch64op("ldursh", [bs('01'), bs('111'), bs('0'), bs('00'), bs('1'), sf, bs('0'), simm9, bs('00'), rn64_deref, rt_isf], [rt_isf, rn64_deref ]) +aarch64op("ldursw", [bs('10'), bs('111'), bs('0'), bs('00'), bs('10'), bs('0'), simm9, bs('00'), rn64_deref, rt64], [rt64, rn64_deref ]) +aarch64op("ldst", [bs('1'), sf, bs('111'), bs('0'), bs('00'), bs('0'), bs_ldst_u_name, bs('0'), simm9, bs('00'), rn64_deref, rt], [rt, rn64_deref ]) + +aarch64op("ldstu", [sdsize, bs('111'), bs('1'), bs('00'), bs('0'), bs_ldst_u_name, bs('0'), simm9, bs('00'), rn64_deref, sd], [sd, rn64_deref ]) +aarch64op("ldst", [bs('00'), bs('111'), bs('1'), bs('00'), bs('1'), bs_ldst_1u_name, bs('0'), simm9, bs('00'), rn64_deref, sd128], [sd128, rn64_deref ]) + +# load/store (register) p.728 + +aarch64op("ldstrb",[bs('00', fname="size"), bs('111'), bs('0'), bs('00'), bs('0'), bs_ldst_b_name, bs('1'), rm_ext2, option, shiftb, bs('10'), rn64_v, rt32], [rt32, rm_ext2]) + +aarch64op("ldstrh",[bs('01', fname="size"), bs('111'), bs('0'), bs('00'), bs('0'), bs_ldst_h_name, bs('1'), rm_ext2, option, shiftb, bs('10'), rn64_v, rt32], [rt32, rm_ext2]) + +aarch64op("ldrsb", [bs('00', fname="size"), bs('111'), bs('0'), bs('00'), bs('1'), sf, bs('1'), rm_ext2, option, shiftb, bs('10'), rn64_v, rt_isf], [rt_isf, rm_ext2]) + +aarch64op("ldrsh", [bs('01', fname="size"), bs('111'), bs('0'), bs('00'), bs('1'), sf, bs('1'), rm_ext2, option, shiftb, bs('10'), rn64_v, rt_isf], [rt_isf, rm_ext2]) + +aarch64op("ldst", [sdsize, bs('111'), bs('1'), bs('00'), bs('0'), bs_ldst_name, bs('1'), rm_ext2, option, shiftb, bs('10'), rn64_v, sd], [sd, rm_ext2]) +aarch64op("ldst", [bs('00', fname="size"), bs('111'), bs('1'), bs('00'), bs('1'), bs_ldst_name, bs('1'), rm_ext2_128, option, shiftb, bs('10'), rn64_v, sd128], [sd128, rm_ext2_128]) + +aarch64op("str", [bs('10', fname="size"), bs('111'), bs('0'), bs('00'), bs('0'), bs_ldst_name, bs('1'), rm_ext2, option, shiftb, bs('10'), rn64_v, rt32], [rt32, rm_ext2]) + +aarch64op("ldrsw", [bs('10', fname="size"), bs('111'), bs('0'), bs('00'), bs('10'), bs('1'), rm_ext2, option, shiftb, bs('10'), rn64_v, rt64], [rt64, rm_ext2]) + +aarch64op("ldst", [bs('11', fname="size"), bs('111'), bs('0'), bs('00'), bs('0'), bs_ldst_name, bs('1'), rm_ext2, option, shiftb, bs('10'), rn64_v, rt64], [rt64, rm_ext2]) + +# load/store literal p.137 +aarch64op("ldr", [bs('0'), sf, bs('011'), bs('0'), bs('00'), offs19, rt], [rt, offs19]) +aarch64op("ldr", [bs('10'), bs('011'), bs('0'), bs('00'), offs19, rt64], [rt64, offs19]) + +# load/store simd literal p.142 +aarch64op("ldr", [sdsize, bs('011'), bs('1'), bs('00'), offs19, sd1], [sd1, offs19]) + + +# move wide p.203 +movwide_name = {'MOVN': 0b00, 'MOVZ': 0b10} +bs_movwide_name = bs_name(l=2, name=movwide_name) +# mov wide (imm) +aarch64op("mov", [sf, bs_movwide_name, bs('100101'), hw, imm16_hw, rd], [rd, imm16_hw]) +aarch64op("movk", [sf, bs('11'), bs('100101'), hw, imm16_hw_sc, rd], [rd, imm16_hw_sc]) + +# stp/ldp p.139 +ldstp_name = {'STP': 0b0, 'LDP': 0b1} +bs_ldstp_name = bs_name(l=1, name=ldstp_name) +aarch64op("ldstp", [sf, bs('0'), bs('101'), bs('0'), bs('0'), post_pre, bs('1'), bs_ldstp_name, simm7, rt2, rn64_deref_sf, rt], [rt, rt2, rn64_deref_sf]) +#aarch64op("ldstp", [sf, bs('0'), bs('101'), bs('0'), bs('0'), bs('1'), bs('0'), bs_ldstp_name, simm7, rt2, rn64_deref_sf, rt], [rt, rt2, rn64_deref_sf]) + +aarch64op("ldstp", [sdsize, bs('101'), bs('1'), bs('0'), post_pre, bs('1'), bs_ldstp_name, uimm7, sd2, rn64_deref_sd, sd1], [sd1, sd2, rn64_deref_sd]) +aarch64op("ldstp", [sdsize, bs('101'), bs('1'), bs('0'), bs('1'), bs('0'), bs_ldstp_name, uimm7, sd2, rn64_deref_sd, sd1], [sd1, sd2, rn64_deref_sd]) + + +# data process p.207 +datap0_name = {'RBIT': 0b000000, 'REV16': 0b000001, + 'REV': 0b000010, + 'CLZ': 0b000100, 'CLS': 0b000101} +bs_datap0_name = bs_name(l=6, name=datap0_name) +aarch64op("ldstp", [bs('0', fname='sf'), bs('1'), modf, bs('11010110'), bs('00000'), bs_datap0_name, rn, rd]) +datap1_name = {'RBIT': 0b000000, 'REV16': 0b000001, + 'REV32': 0b000010, 'REV': 0b000011, + 'CLZ': 0b000100, 'CLS': 0b000101} +bs_datap1_name = bs_name(l=6, name=datap1_name) +aarch64op("ldstp", [bs('1', fname='sf'), bs('1'), modf, bs('11010110'), bs('00000'), bs_datap1_name, rn, rd]) + + +# conditional branch p.132 +aarch64op("b.", [bs('0101010'), bs('0'), offs19, bs('0'), bcond], [offs19]) +aarch64op("cbnz", [sf, bs('011010'), bs('1'), offs19, rt], [rt, offs19]) +aarch64op("cbz", [sf, bs('011010'), bs('0'), offs19, rt], [rt, offs19]) +aarch64op("tbnz", [sf, bs('011011'), bs('1'), b40, offs14, rt], [rt, b40, offs14]) +aarch64op("tbz", [sf, bs('011011'), bs('0'), b40, offs14, rt], [rt, b40, offs14]) + + +# fmov register p.160 +aarch64op("fmov", [bs('000'), bs('11110'), bs('0'), sdsize1, bs('1'), bs('0000'), bs('00'), bs('10000'), sdn_32_64, sdd_32_64], [sdd_32_64, sdn_32_64]) +# fmov scalar imm p.160 +aarch64op("fmov", [bs('000'), bs('11110'), bs('0'), sdsize1, bs('1'), uimm8, bs('100'), bs('00000'), sdd_32_64], [sdd_32_64, uimm8]) +# floating point comparison p.164 +aarch64op("fcmp", [bs('000'), bs('11110'), bs('0'), sdsize1, bs('1'), sdm_32_64_zero, bs('00'), bs('1000'), sdn_32_64, bs('0'), opc, bs('000')], [sdn_32_64, sdm_32_64_zero]) +aarch64op("fcmpe", [bs('000'), bs('11110'), bs('0'), sdsize1, bs('1'), sdm_32_64_zero, bs('00'), bs('1000'), sdn_32_64, bs('1'), opc, bs('000')], [sdn_32_64, sdm_32_64_zero]) +# floating point convert p.161 +aarch64op("fcvtas",[sf, bs('00'), bs('11110'), bs('0'), sdsize1, bs('1'), bs('00'), bs('100'), bs('000000'), sdn_32_64, rd], [rd, sdn_32_64]) +aarch64op("fcvtzu",[sf, bs('00'), bs('11110'), bs('0'), sdsize1, bs('1'), bs('11'), bs('001'), bs('000000'), sdn_32_64, rd], [rd, sdn_32_64]) +aarch64op("fcvtzs",[sf, bs('00'), bs('11110'), bs('0'), sdsize1, bs('1'), bs('11'), bs('000'), bs('000000'), sdn_32_64, rd], [rd, sdn_32_64]) + +aarch64op("fcvt", [bs('000'), bs('11110'), bs('11'), bs('1'), bs('0001'), bs('00'), bs('10000'), sn16, sd32], [sd32, sn16]) +aarch64op("fcvt", [bs('000'), bs('11110'), bs('11'), bs('1'), bs('0001'), bs('01'), bs('10000'), sn16, sd64], [sd64, sn16]) +aarch64op("fcvt", [bs('000'), bs('11110'), bs('00'), bs('1'), bs('0001'), bs('11'), bs('10000'), sn32, sd16], [sd16, sn32]) +aarch64op("fcvt", [bs('000'), bs('11110'), bs('00'), bs('1'), bs('0001'), bs('01'), bs('10000'), sn32, sd64], [sd64, sn32]) +aarch64op("fcvt", [bs('000'), bs('11110'), bs('01'), bs('1'), bs('0001'), bs('11'), bs('10000'), sn64, sd16], [sd16, sn64]) +aarch64op("fcvt", [bs('000'), bs('11110'), bs('01'), bs('1'), bs('0001'), bs('00'), bs('10000'), sn64, sd32], [sd32, sn64]) + + + +swapargs = bs_swapargs(l=1, fname="swap", mn_mod=range(1 << 1)) + +aarch64op("fmov", [bs('0'), bs('00'), bs('11110'), bs('00'), bs('1'), bs('00'), bs('110'), bs('000000'), sn32, rd32], [rd32, sn32]) +aarch64op("fmov", [bs('0'), bs('00'), bs('11110'), bs('00'), bs('1'), bs('00'), bs('111'), bs('000000'), rn32, sd32], [sd32, rn32]) +aarch64op("fmov", [bs('1'), bs('00'), bs('11110'), bs('00'), bs('1'), bs('00'), bs('110'), bs('000000'), sd32, rd32], [rd32, sd32]) +aarch64op("fmov", [bs('1'), bs('00'), bs('11110'), bs('01'), bs('1'), bs('00'), bs('111'), bs('000000'), rd64, sd64], [sd64, rd64]) +aarch64op("fmov", [bs('1'), bs('00'), bs('11110'), bs('01'), bs('1'), bs('00'), bs('110'), bs('000000'), sd64, rd64], [rd64, sd64]) + + + +# floating point arith p.163 +aarch64op("fsub", [bs('0'), bs('00'), bs('11110'), bs('0'), sdsize1, bs('1'), sdm_32_64, bs('001'), bs('1'), bs('10'), sdn_32_64, sdd_32_64], [sdd_32_64, sdn_32_64, sdm_32_64]) +aarch64op("fadd", [bs('0'), bs('00'), bs('11110'), bs('0'), sdsize1, bs('1'), sdm_32_64, bs('001'), bs('0'), bs('10'), sdn_32_64, sdd_32_64], [sdd_32_64, sdn_32_64, sdm_32_64]) +aarch64op("fdiv", [bs('0'), bs('00'), bs('11110'), bs('0'), sdsize1, bs('1'), sdm_32_64, bs('000'), bs('1'), bs('10'), sdn_32_64, sdd_32_64], [sdd_32_64, sdn_32_64, sdm_32_64]) +aarch64op("fmul", [bs('0'), bs('00'), bs('11110'), bs('0'), sdsize1, bs('1'), sdm_32_64, bs('000'), bs('0'), bs('10'), sdn_32_64, sdd_32_64], [sdd_32_64, sdn_32_64, sdm_32_64]) +aarch64op("fnmul", [bs('0'), bs('00'), bs('11110'), bs('0'), sdsize1, bs('1'), sdm_32_64, bs('100'), bs('0'), bs('10'), sdn_32_64, sdd_32_64], [sdd_32_64, sdn_32_64, sdm_32_64]) + +aarch64op("fabs", [bs('0'), bs('00'), bs('11110'), bs('0'), sdsize1, bs('1'), bs('0000'), bs('01'), bs('10000'), sdn_32_64, sdd_32_64], [sdd_32_64, sdn_32_64]) +aarch64op("fneg", [bs('0'), bs('00'), bs('11110'), bs('0'), sdsize1, bs('1'), bs('0000'), bs('10'), bs('10000'), sdn_32_64, sdd_32_64], [sdd_32_64, sdn_32_64]) +aarch64op("fsqrt", [bs('0'), bs('00'), bs('11110'), bs('0'), sdsize1, bs('1'), bs('0000'), bs('11'), bs('10000'), sdn_32_64, sdd_32_64], [sdd_32_64, sdn_32_64]) + + +# floating point multiply add p.163 +aarch64op("fmadd", [bs('0'), bs('00'), bs('11111'), bs('0'), sdsize1, bs('0'), sdm_32_64, bs('0'), sda_32_64, sdn_32_64, sdd_32_64], [sdd_32_64, sdn_32_64, sdm_32_64, sda_32_64]) +aarch64op("fmsub", [bs('0'), bs('00'), bs('11111'), bs('0'), sdsize1, bs('0'), sdm_32_64, bs('1'), sda_32_64, sdn_32_64, sdd_32_64], [sdd_32_64, sdn_32_64, sdm_32_64, sda_32_64]) +aarch64op("fnmadd",[bs('0'), bs('00'), bs('11111'), bs('0'), sdsize1, bs('1'), sdm_32_64, bs('0'), sda_32_64, sdn_32_64, sdd_32_64], [sdd_32_64, sdn_32_64, sdm_32_64, sda_32_64]) +aarch64op("fnmsub",[bs('0'), bs('00'), bs('11111'), bs('0'), sdsize1, bs('1'), sdm_32_64, bs('1'), sda_32_64, sdn_32_64, sdd_32_64], [sdd_32_64, sdn_32_64, sdm_32_64, sda_32_64]) + +# convertion float integer p.235 +aarch64op("scvtf", [sf, bs('0'), bs('0'), bs('11110'), bs('0'), sdsize1, bs('1'), bs('00'), bs('010'), bs('000000'), rn, sdd_32_64], [sdd_32_64, rn]) +aarch64op("ucvtf", [sf, bs('0'), bs('0'), bs('11110'), bs('0'), sdsize1, bs('1'), bs('00'), bs('011'), bs('000000'), rn, sdd_32_64], [sdd_32_64, rn]) + + + +# conditional select p.158 +aarch64op("csel", [sf, bs('0'), bs('0'), bs('11010100'), rm, cond_arg, bs('00'), rn, rd], [rd, rn, rm, cond_arg]) +aarch64op("csinc", [sf, bs('0'), bs('0'), bs('11010100'), rm, cond_arg, bs('01'), rn, rd], [rd, rn, rm, cond_arg]) +aarch64op("csinv", [sf, bs('1'), bs('0'), bs('11010100'), rm, cond_arg, bs('00'), rn, rd], [rd, rn, rm, cond_arg]) +aarch64op("csneg", [sf, bs('1'), bs('0'), bs('11010100'), rm, cond_arg, bs('01'), rn, rd], [rd, rn, rm, cond_arg]) +aarch64op("cset", [sf, bs('0'), bs('0'), bs('11010100'), bs('11111'), cond_inv_arg, bs('01'), bs('11111'), rd], [rd, cond_inv_arg], alias=True) +aarch64op("csetm", [sf, bs('1'), bs('0'), bs('11010100'), bs('11111'), cond_inv_arg, bs('00'), bs('11111'), rd], [rd, cond_inv_arg], alias=True) + + +# multiply p.156 +aarch64op("madd", [sf, bs('00'), bs('11011'), bs('000'), rm, bs('0'), ra, rn, rd], [rd, rn, rm, ra]) +aarch64op("msub", [sf, bs('00'), bs('11011'), bs('000'), rm, bs('1'), ra, rn, rd], [rd, rn, rm, ra]) + +aarch64op("umulh", [bs('1'), bs('00'), bs('11011'), bs('110'), rm64, bs('0'), bs('11111'), rn64, rd64], [rd64, rn64, rm64]) +aarch64op("smulh", [bs('1'), bs('00'), bs('11011'), bs('010'), rm64, bs('0'), bs('11111'), rn64, rd64], [rd64, rn64, rm64]) +aarch64op("umsubh",[bs('1'), bs('00'), bs('11011'), bs('101'), rm32, bs('1'), ra64, rn32, rd64], [rd64, rn32, rm32, ra64]) + + +aarch64op("smaddl",[bs('1'), bs('00'), bs('11011'), bs('001'), rm32, bs('0'), ra64, rn32, rd64], [rd64, rn32, rm32, ra64]) +aarch64op("umaddl",[bs('1'), bs('00'), bs('11011'), bs('101'), rm32, bs('0'), ra64, rn32, rd64], [rd64, rn32, rm32, ra64]) + +aarch64op("smsubl",[bs('1'), bs('00'), bs('11011'), bs('001'), rm32, bs('1'), ra64, rn32, rd64], [rd64, rn32, rm32, ra64]) +aarch64op("umsubl",[bs('1'), bs('00'), bs('11011'), bs('101'), rm32, bs('1'), ra64, rn32, rd64], [rd64, rn32, rm32, ra64]) + +# division p.156 +aarch64op("sdiv", [sf, bs('0'), bs('0'), bs('11010110'), rm, bs('00001'), bs('1'), rn, rd], [rd, rn, rm]) +aarch64op("udiv", [sf, bs('0'), bs('0'), bs('11010110'), rm, bs('00001'), bs('0'), rn, rd], [rd, rn, rm]) + + +# extract register p.150 +aarch64op("extr", [sf, bs('00100111'), bs(l=1, cls=(aarch64_eq,), ref="sf"), bs('0'), rm, simm6, rn, rd], [rd, rn, rm, simm6]) + +# shift reg p.155 +shiftr_name = {'LSL': 0b00, 'LSR': 0b01, 'ASR': 0b10, 'ROR': 0b11} +bs_shiftr_name = bs_name(l=2, name=shiftr_name) + +aarch64op("shiftr", [sf, bs('0'), bs('0'), bs('11010110'), rm, bs('0010'), bs_shiftr_name, rn, rd], [rd, rn, rm]) + +# +aarch64op("NOP", [bs('11010101000000110010000000011111')]) + +# exception p.133 +aarch64op("brk", [bs('11010100'), bs('001'), uimm16, bs('000'), bs('00')], [uimm16]) +aarch64op("hlt", [bs('11010100'), bs('010'), uimm16, bs('000'), bs('00')], [uimm16]) +aarch64op("svc", [bs('11010100'), bs('000'), uimm16, bs('000'), bs('01')], [uimm16]) +aarch64op("hvc", [bs('11010100'), bs('000'), uimm16, bs('000'), bs('10')], [uimm16]) +aarch64op("smc", [bs('11010100'), bs('000'), uimm16, bs('000'), bs('11')], [uimm16]) + +# msr p.631 +msr_name = {'MSR': 0b0, 'MRS': 0b1} +bs_msr_name = bs_name(l=1, name=msr_name) +aarch64op("mrs", [bs('1101010100'), bs('1'), bs('1'), bs('1'), op1, crn, crm, op2, rt64], [rt64, op1, crn, crm, op2]) +aarch64op("msr", [bs('1101010100'), bs('0'), bs('1'), bs('1'), op1, crn, crm, op2, rt64], [op1, crn, crm, op2, rt64]) + +# load/store exclusive p.140 +aarch64op("stxr", [bs('1'), sf, bs('001000'), bs('0'), bs('0'), bs('0'), rs32, bs('0'), bs('11111'), rn64_deref_nooff, rt], [rs32, rt, rn64_deref_nooff]) +aarch64op("ldxr", [bs('1'), sf, bs('001000'), bs('0'), bs('1'), bs('0'), bs('11111'), bs('0'), bs('11111'), rn64_deref_nooff, rt], [rt, rn64_deref_nooff]) + + +aarch64op("stxrb", [bs('0'), bs('0'), bs('001000'), bs('0'), bs('0'), bs('0'), rs32, bs('0'), bs('11111'), rn64_deref_nooff, rt32], [rs32, rt32, rn64_deref_nooff]) +aarch64op("ldxrb", [bs('0'), bs('0'), bs('001000'), bs('0'), bs('1'), bs('0'), bs('11111'), bs('0'), bs('11111'), rn64_deref_nooff, rt32], [rt32, rn64_deref_nooff]) + +aarch64op("stxrb", [bs('0'), bs('1'), bs('001000'), bs('0'), bs('0'), bs('0'), rs32, bs('0'), bs('11111'), rn64_deref_nooff, rt32], [rs32, rt32, rn64_deref_nooff]) +aarch64op("ldxrh", [bs('0'), bs('1'), bs('001000'), bs('0'), bs('1'), bs('0'), bs('11111'), bs('0'), bs('11111'), rn64_deref_nooff, rt32], [rt32, rn64_deref_nooff]) + +aarch64op("stxp", [bs('1'), sf, bs('001000'), bs('0'), bs('0'), bs('1'), rs32, bs('0'), rt2, rn64_deref_nooff, rt], [rs32, rt, rt2, rn64_deref_nooff]) +aarch64op("ldxp", [bs('1'), sf, bs('001000'), bs('0'), bs('1'), bs('1'), bs('11111'), bs('0'), rt2, rn64_deref_nooff, rt], [rt, rt2, rn64_deref_nooff]) + +# load acquire/store release p.141 +aarch64op("ldar", [bs('1'), sf, bs('001000'), bs('1'), bs('1'), bs('0'), bs('11111'), bs('1'), bs('11111'), rn64_deref_nooff, rt], [rt, rn64_deref_nooff]) +aarch64op("ldarb",[bs('0'), bs('0'), bs('001000'), bs('1'), bs('1'), bs('0'), bs('11111'), bs('1'), bs('11111'), rn64_deref_nooff, rt], [rt, rn64_deref_nooff]) +aarch64op("ldarh",[bs('0'), bs('1'), bs('001000'), bs('0'), bs('1'), bs('0'), bs('11111'), bs('1'), bs('11111'), rn64_deref_nooff, rt], [rt, rn64_deref_nooff]) +aarch64op("ldaxp",[bs('1'), sf, bs('001000'), bs('0'), bs('1'), bs('1'), bs('11111'), bs('1'), bs('11111'), rn64_deref_nooff, rt], [rt, rn64_deref_nooff]) +aarch64op("ldaxr",[bs('1'), sf, bs('001000'), bs('0'), bs('1'), bs('0'), bs('11111'), bs('1'), bs('11111'), rn64_deref_nooff, rt], [rt, rn64_deref_nooff]) + +aarch64op("stlxr", [bs('1'), sf, bs('001000'), bs('0'), bs('0'), bs('0'), rs32, bs('1'), bs('11111'), rn64_deref_nooff, rt], [rs32, rt, rn64_deref_nooff]) +aarch64op("stlxrb",[bs('0'), bs('0'), bs('001000'), bs('0'), bs('0'), bs('0'), rs32, bs('1'), bs('11111'), rn64_deref_nooff, rt32], [rs32, rt32, rn64_deref_nooff]) +aarch64op("stlxrh",[bs('0'), bs('1'), bs('001000'), bs('0'), bs('0'), bs('0'), rs32, bs('1'), bs('11111'), rn64_deref_nooff, rt32], [rs32, rt32, rn64_deref_nooff]) +aarch64op("stlxp", [bs('1'), sf, bs('001000'), bs('0'), bs('0'), bs('1'), rs32, bs('1'), rt2, rn64_deref_nooff, rt], [rs32, rt, rt2, rn64_deref_nooff]) + +# barriers p.135 +aarch64op("dsb", [bs('1101010100'), bs('0000110011'), crm, bs('1'), bs('00'), bs('11111')], [crm]) +aarch64op("dmb", [bs('1101010100'), bs('0000110011'), crm, bs('1'), bs('01'), bs('11111')], [crm]) +aarch64op("isb", [bs('1101010100'), bs('0000110011'), crm, bs('1'), bs('10'), bs('11111')], [crm]) diff --git a/miasm2/arch/aarch64/disasm.py b/miasm2/arch/aarch64/disasm.py new file mode 100644 index 00000000..1fc19d07 --- /dev/null +++ b/miasm2/arch/aarch64/disasm.py @@ -0,0 +1,27 @@ +from miasm2.core.asmbloc import asm_constraint, disasmEngine +from miasm2.arch.aarch64.arch import mn_aarch64 + +cb_aarch64_funcs = [] + + +def cb_aarch64_disasm(mn, attrib, pool_bin, cur_bloc, offsets_to_dis, symbol_pool): + for func in cb_aarch64_funcs: + func(mn, attrib, pool_bin, cur_bloc, offsets_to_dis, symbol_pool) + + +class dis_aarch64b(disasmEngine): + attrib = "b" + def __init__(self, bs=None, **kwargs): + super(dis_aarch64b, self).__init__( + mn_aarch64, self.attrib, bs, + dis_bloc_callback = cb_aarch64_disasm, + **kwargs) + + +class dis_aarch64l(disasmEngine): + attrib = "l" + def __init__(self, bs=None, **kwargs): + super(dis_aarch64l, self).__init__( + mn_aarch64, self.attrib, bs, + dis_bloc_callback = cb_aarch64_disasm, + **kwargs) diff --git a/miasm2/arch/aarch64/ira.py b/miasm2/arch/aarch64/ira.py new file mode 100644 index 00000000..cf44f42c --- /dev/null +++ b/miasm2/arch/aarch64/ira.py @@ -0,0 +1,95 @@ +#!/usr/bin/env python +#-*- coding:utf-8 -*- + +from miasm2.expression.expression import * +from miasm2.ir.ir import ir, irbloc +from miasm2.ir.analysis import ira +from miasm2.arch.aarch64.sem import ir_aarch64l, ir_aarch64b +from miasm2.arch.aarch64.regs import * + + +class ir_a_aarch64l_base(ir_aarch64l, ira): + + def __init__(self, symbol_pool=None): + ir_aarch64l.__init__(self, symbol_pool) + self.ret_reg = self.arch.regs.X0 + + +class ir_a_aarch64b_base(ir_aarch64b, ira): + + def __init__(self, symbol_pool=None): + ir_aarch64b.__init__(self, symbol_pool) + self.ret_reg = self.arch.regs.X0 + + +class ir_a_aarch64l(ir_a_aarch64l_base): + + def __init__(self, symbol_pool=None): + ir_a_aarch64l_base.__init__(self, symbol_pool) + self.ret_reg = self.arch.regs.X0 + + # for test XXX TODO + def set_dead_regs(self, b): + b.rw[-1][1].add(self.arch.regs.zf) + b.rw[-1][1].add(self.arch.regs.nf) + b.rw[-1][1].add(self.arch.regs.of) + b.rw[-1][1].add(self.arch.regs.cf) + + def call_effects(self, ad): + irs = [[ExprAff(self.ret_reg, ExprOp('call_func_ret', ad, self.sp)), + ExprAff(self.sp, ExprOp('call_func_stack', ad, self.sp)), + ]] + return irs + + def post_add_bloc(self, bloc, ir_blocs): + ir.post_add_bloc(self, bloc, ir_blocs) + for irb in ir_blocs: + pc_val = None + lr_val = None + for exprs in irb.irs: + for e in exprs: + if e.dst == PC: + pc_val = e.src + if e.dst == LR: + lr_val = e.src + if pc_val is None or lr_val is None: + continue + if not isinstance(lr_val, ExprInt): + continue + + l = bloc.lines[-1] + if lr_val.arg != l.offset + l.l: + continue + lbl = bloc.get_next() + new_lbl = self.gen_label() + irs = self.call_effects(pc_val) + irs.append([ExprAff(self.IRDst, ExprId(lbl, size=self.pc.size))]) + nbloc = irbloc(new_lbl, irs) + nbloc.lines = [l] * len(irs) + self.blocs[new_lbl] = nbloc + irb.dst = ExprId(new_lbl, size=self.pc.size) + + def get_out_regs(self, b): + return set([self.ret_reg, self.sp]) + + def sizeof_char(self): + return 8 + + def sizeof_short(self): + return 16 + + def sizeof_int(self): + return 32 + + def sizeof_long(self): + return 32 + + def sizeof_pointer(self): + return 32 + + +class ir_a_aarch64b(ir_a_aarch64b_base, ir_a_aarch64l): + + def __init__(self, symbol_pool=None): + ir_a_aarch64b_base.__init__(self, symbol_pool) + self.ret_reg = self.arch.regs.X0 diff --git a/miasm2/arch/aarch64/jit.py b/miasm2/arch/aarch64/jit.py new file mode 100644 index 00000000..44b0609f --- /dev/null +++ b/miasm2/arch/aarch64/jit.py @@ -0,0 +1,73 @@ +import logging + +from miasm2.jitter.jitload import jitter, named_arguments +from miasm2.core import asmbloc +from miasm2.core.utils import * +from miasm2.arch.aarch64.sem import ir_aarch64b, ir_aarch64l + +log = logging.getLogger('jit_aarch64') +hnd = logging.StreamHandler() +hnd.setFormatter(logging.Formatter("[%(levelname)s]: %(message)s")) +log.addHandler(hnd) +log.setLevel(logging.CRITICAL) + + +class jitter_aarch64l(jitter): + max_reg_arg = 8 + + def __init__(self, *args, **kwargs): + sp = asmbloc.asm_symbol_pool() + jitter.__init__(self, ir_aarch64l(sp), *args, **kwargs) + self.vm.set_little_endian() + self.ir_arch.jit_pc = self.ir_arch.arch.regs.PC + + def push_uint64_t(self, v): + self.cpu.SP -= 8 + self.vm.set_mem(self.cpu.SP, pck64(v)) + + def pop_uint64_t(self): + x = upck32(self.vm.get_mem(self.cpu.SP, 8)) + self.cpu.SP += 8 + return x + + def get_stack_arg(self, n): + x = upck64(self.vm.get_mem(self.cpu.SP + 8 * n, 8)) + return x + + # calling conventions + + @named_arguments + def func_args_stdcall(self, n_args): + args = [] + for i in xrange(min(n_args, self.max_reg_arg)): + args.append(self.cpu.get_gpreg()['X%d' % i]) + for i in xrange(max(0, n_args - self.max_reg_arg)): + args.append(self.get_stack_arg(i)) + ret_ad = self.cpu.LR + return ret_ad, args + + def func_ret_stdcall(self, ret_addr, ret_value=None): + self.pc = self.cpu.PC = ret_addr + if ret_value is not None: + self.cpu.X0 = ret_value + return True + + def get_arg_n_stdcall(self, n): + if n < self.max_reg_arg: + arg = self.cpu.get_gpreg()['X%d' % n] + else: + arg = self.get_stack_arg(n - self.max_reg_arg) + return arg + + def init_run(self, *args, **kwargs): + jitter.init_run(self, *args, **kwargs) + self.cpu.PC = self.pc + + +class jitter_aarch64b(jitter_aarch64l): + + def __init__(self, *args, **kwargs): + sp = asmbloc.asm_symbol_pool() + jitter.__init__(self, ir_aarch64b(sp), *args, **kwargs) + self.vm.set_big_endian() + self.ir_arch.jit_pc = self.ir_arch.arch.regs.PC diff --git a/miasm2/arch/aarch64/regs.py b/miasm2/arch/aarch64/regs.py new file mode 100644 index 00000000..6130d075 --- /dev/null +++ b/miasm2/arch/aarch64/regs.py @@ -0,0 +1,124 @@ +#!/usr/bin/env python +#-*- coding:utf-8 -*- + +from miasm2.expression.expression import * +from miasm2.core.cpu import gen_reg, gen_regs + +exception_flags = ExprId('exception_flags', 32) + + +gpregs32_str = ["W%d" % i for i in xrange(0x1f)] + ["WSP"] +gpregs32_expr, gpregs32_init, gpregs32_info = gen_regs( + gpregs32_str, globals(), 32) + +gpregs64_str = ["X%d" % i for i in xrange(0x1E)] + ["LR", "SP"] +gpregs64_expr, gpregs64_init, gpregs64_info = gen_regs( + gpregs64_str, globals(), 64) + + +gpregsz32_str = ["W%d" % i for i in xrange(0x1f)] + ["WZR"] +gpregsz32_expr, gpregsz32_init, gpregsz32_info = gen_regs( + gpregsz32_str, globals(), 32) + +gpregsz64_str = ["X%d" % i for i in xrange(0x1e)] + ["LR", "XZR"] +gpregsz64_expr, gpregsz64_init, gpregsz64_info = gen_regs( + gpregsz64_str, globals(), 64) + +cr_str = ["c%d" % i for i in xrange(0xf)] +cr_expr, cr_init, cr_info = gen_regs(cr_str, globals(), 32) + + +simd08_str = ["B%d" % i for i in xrange(0x20)] +simd08_expr, simd08_init, simd08_info = gen_regs(simd08_str, globals(), 8) + +simd16_str = ["H%d" % i for i in xrange(0x20)] +simd16_expr, simd16_init, simd16_info = gen_regs(simd16_str, globals(), 16) + +simd32_str = ["S%d" % i for i in xrange(0x20)] +simd32_expr, simd32_init, simd32_info = gen_regs(simd32_str, globals(), 32) + +simd64_str = ["D%d" % i for i in xrange(0x20)] +simd64_expr, simd64_init, simd64_info = gen_regs(simd64_str, globals(), 64) + +simd128_str = ["Q%d" % i for i in xrange(0x20)] +simd128_expr, simd128_init, simd128_info = gen_regs( + simd128_str, globals(), 128) + + +PC, PC_init = gen_reg("PC", globals(), 64) +WZR, WZR_init = gen_reg("WZR", globals(), 32) +XZR, XZR_init = gen_reg("XZR", globals(), 64) + +reg_zf = 'zf' +reg_nf = 'nf' +reg_of = 'of' +reg_cf = 'cf' + +zf = ExprId(reg_zf, size=1) +nf = ExprId(reg_nf, size=1) +of = ExprId(reg_of, size=1) +cf = ExprId(reg_cf, size=1) + +zf_init = ExprId("zf_init", size=1) +nf_init = ExprId("nf_init", size=1) +of_init = ExprId("of_init", size=1) +cf_init = ExprId("cf_init", size=1) + + +all_regs_ids = [ + B0, B1, B2, B3, B4, B5, B6, B7, B8, B9, B10, B11, B12, B13, B14, B15, B16, + B17, B18, B19, B20, B21, B22, B23, B24, B25, B26, B27, B28, B29, B30, B31, + + H0, H1, H2, H3, H4, H5, H6, H7, H8, H9, H10, H11, H12, H13, H14, H15, H16, + H17, H18, H19, H20, H21, H22, H23, H24, H25, H26, H27, H28, H29, H30, H31, + + S0, S1, S2, S3, S4, S5, S6, S7, S8, S9, S10, S11, S12, S13, S14, S15, S16, + S17, S18, S19, S20, S21, S22, S23, S24, S25, S26, S27, S28, S29, S30, S31, + + D0, D1, D2, D3, D4, D5, D6, D7, D8, D9, D10, D11, D12, D13, D14, D15, D16, + D17, D18, D19, D20, D21, D22, D23, D24, D25, D26, D27, D28, D29, D30, D31, + + Q0, Q1, Q2, Q3, Q4, Q5, Q6, Q7, Q8, Q9, Q10, Q11, Q12, Q13, Q14, Q15, Q16, + Q17, Q18, Q19, Q20, Q21, Q22, Q23, Q24, Q25, Q26, Q27, Q28, Q29, Q30, Q31, + + W0, W1, W2, W3, W4, W5, W6, W7, W8, W9, W10, W11, W12, W13, W14, W15, W16, + W17, W18, W19, W20, W21, W22, W23, W24, W25, W26, W27, W28, W29, W30, WSP, + + X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, + X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, LR, SP, + + exception_flags, + PC, + WZR, WZR, + zf, nf, of, cf, + XZR, WZR, + +] + + +all_regs_ids_no_alias = all_regs_ids + +all_regs_ids_byname = dict([(x.name, x) for x in all_regs_ids]) + +all_regs_ids_init = (simd08_init + + simd16_init + + simd32_init + + simd64_init + + simd128_init + + gpregs32_init + + gpregs64_init + + [ + ExprInt32(0), + PC_init, + WZR_init, + XZR_init, + zf_init, nf_init, of_init, cf_init, + ExprInt64(0), ExprInt32(0), + ] + ) + +regs_init = {} +for i, r in enumerate(all_regs_ids): + regs_init[r] = all_regs_ids_init[i] + +regs_flt_expr = [] diff --git a/miasm2/arch/aarch64/sem.py b/miasm2/arch/aarch64/sem.py new file mode 100644 index 00000000..800cc677 --- /dev/null +++ b/miasm2/arch/aarch64/sem.py @@ -0,0 +1,740 @@ +from miasm2.expression import expression as m2_expr +from miasm2.ir.ir import ir, irbloc +from miasm2.arch.aarch64.arch import mn_aarch64, conds_expr, replace_regs +from miasm2.arch.aarch64.regs import * +from miasm2.core.sembuilder import SemBuilder + +EXCEPT_PRIV_INSN = (1 << 17) + +# CPSR: N Z C V + + +def update_flag_zf(a): + return [m2_expr.ExprAff(zf, m2_expr.ExprCond(a, m2_expr.ExprInt1(0), m2_expr.ExprInt1(1)))] + + +def update_flag_nf(a): + return [m2_expr.ExprAff(nf, a.msb())] + + +def update_flag_zn(a): + e = [] + e += update_flag_zf(a) + e += update_flag_nf(a) + return e + + +def update_flag_logic(a): + e = [] + e += update_flag_zn(a) + # XXX TODO: set cf if ROT imm in argument + # e.append(m2_expr.ExprAff(cf, m2_expr.ExprInt1(0))) + return e + + +def update_flag_arith(a): + e = [] + e += update_flag_zn(a) + return e + + +def check_ops_msb(a, b, c): + if not a or not b or not c or a != b or a != c: + raise ValueError('bad ops size %s %s %s' % (a, b, c)) + + +def arith_flag(a, b, c): + a_s, b_s, c_s = a.size, b.size, c.size + check_ops_msb(a_s, b_s, c_s) + a_s, b_s, c_s = a.msb(), b.msb(), c.msb() + return a_s, b_s, c_s + +# checked: ok for adc add because b & c before +cf + + +def update_flag_add_cf(op1, op2, res): + "Compute cf in @res = @op1 + @op2" + return m2_expr.ExprAff(cf, (((op1 ^ op2) ^ res) ^ ((op1 ^ res) & (~(op1 ^ op2)))).msb()) + + +def update_flag_add_of(op1, op2, res): + "Compute of in @res = @op1 + @op2" + return m2_expr.ExprAff(of, (((op1 ^ res) & (~(op1 ^ op2)))).msb()) + + +# checked: ok for sbb add because b & c before +cf +def update_flag_sub_cf(op1, op2, res): + "Compote CF in @res = @op1 - @op2" + return m2_expr.ExprAff(cf, + ((((op1 ^ op2) ^ res) ^ ((op1 ^ res) & (op1 ^ op2))).msb()) ^ m2_expr.ExprInt1(1)) + + +def update_flag_sub_of(op1, op2, res): + "Compote OF in @res = @op1 - @op2" + return m2_expr.ExprAff(of, (((op1 ^ res) & (op1 ^ op2))).msb()) + +# z = x+y (+cf?) + + +def update_flag_add(x, y, z): + e = [] + e.append(update_flag_add_cf(x, y, z)) + e.append(update_flag_add_of(x, y, z)) + return e + +# z = x-y (+cf?) + + +def update_flag_sub(x, y, z): + e = [] + e.append(update_flag_sub_cf(x, y, z)) + e.append(update_flag_sub_of(x, y, z)) + return e + + +cond2expr = {'EQ': zf, + 'NE': zf ^ m2_expr.ExprInt1(1), + 'CS': cf, + 'CC': cf ^ m2_expr.ExprInt1(1), + 'MI': nf, + 'PL': nf ^ m2_expr.ExprInt1(1), + 'VS': of, + 'VC': of ^ m2_expr.ExprInt1(1), + 'HI': cf & (zf ^ m2_expr.ExprInt1(1)), + 'LS': (cf ^ m2_expr.ExprInt1(1)) | zf, + 'GE': nf ^ of ^ m2_expr.ExprInt1(1), + 'LT': nf ^ of, + 'GT': ((zf ^ m2_expr.ExprInt1(1)) & + (nf ^ of ^ m2_expr.ExprInt1(1))), + 'LE': zf | (nf ^ of), + 'AL': m2_expr.ExprInt1(1), + 'NV': m2_expr.ExprInt1(0) + } + + +def extend_arg(dst, arg): + if not isinstance(arg, m2_expr.ExprOp): + return arg + + op, (reg, shift) = arg.op, arg.args + if op == 'SXTW': + base = reg.signExtend(dst.size) + else: + base = reg.zeroExtend(dst.size) + + out = base << (shift.zeroExtend(dst.size) + & m2_expr.ExprInt_from(dst, dst.size - 1)) + return out + + +# SemBuilder context +ctx = {"PC": PC, + "LR": LR, + "nf": nf, + "zf": zf, + "cf": cf, + "of": of, + "cond2expr": cond2expr, + "extend_arg": extend_arg, + "m2_expr":m2_expr + } + +sbuild = SemBuilder(ctx) + + +# instruction definition ############## + +@sbuild.parse +def add(arg1, arg2, arg3): + arg1 = arg2 + extend_arg(arg2, arg3) + + +@sbuild.parse +def sub(arg1, arg2, arg3): + arg1 = arg2 - extend_arg(arg2, arg3) + + +@sbuild.parse +def neg(arg1, arg2): + arg1 = - arg2 + + +@sbuild.parse +def and_l(arg1, arg2, arg3): + arg1 = arg2 & extend_arg(arg2, arg3) + + +@sbuild.parse +def eor(arg1, arg2, arg3): + arg1 = arg2 ^ extend_arg(arg2, arg3) + + +@sbuild.parse +def eon(arg1, arg2, arg3): + arg1 = arg2 ^ (~extend_arg(arg2, arg3)) + + +@sbuild.parse +def orr(arg1, arg2, arg3): + arg1 = arg2 | extend_arg(arg2, arg3) + + +@sbuild.parse +def orn(arg1, arg2, arg3): + arg1 = arg2 | (~extend_arg(arg2, arg3)) + + +@sbuild.parse +def bic(arg1, arg2, arg3): + arg1 = arg2 & (~extend_arg(arg2, arg3)) + + +@sbuild.parse +def mvn(arg1, arg2): + arg1 = (~extend_arg(arg1, arg2)) + + +def adds(ir, instr, arg1, arg2, arg3): + e = [] + arg3 = extend_arg(arg2, arg3) + res = arg2 + arg3 + e += update_flag_arith(res) + e += update_flag_add(arg2, arg3, res) + e.append(m2_expr.ExprAff(arg1, res)) + return e, [] + + +def subs(ir, instr, arg1, arg2, arg3): + e = [] + arg3 = extend_arg(arg2, arg3) + res = arg2 - arg3 + e += update_flag_arith(res) + e += update_flag_sub(arg2, arg3, res) + e.append(m2_expr.ExprAff(arg1, res)) + return e, [] + + +def cmp(ir, instr, arg1, arg2): + e = [] + arg2 = extend_arg(arg1, arg2) + res = arg1 - arg2 + e += update_flag_arith(res) + e += update_flag_sub(arg1, arg2, res) + return e, [] + + +def cmn(ir, instr, arg1, arg2): + e = [] + arg2 = extend_arg(arg1, arg2) + res = arg1 + arg2 + e += update_flag_arith(res) + e += update_flag_add(arg1, arg2, res) + return e, [] + + +def ands(ir, instr, arg1, arg2, arg3): + e = [] + arg3 = extend_arg(arg2, arg3) + res = arg2 & arg3 + e += update_flag_logic(res) + e.append(m2_expr.ExprAff(arg1, res)) + return e, [] + + +@sbuild.parse +def lsl(arg1, arg2, arg3): + arg1 = arg2 << (arg3 & m2_expr.ExprInt_from(arg3, arg3.size - 1)) + + +@sbuild.parse +def lsr(arg1, arg2, arg3): + arg1 = arg2 >> (arg3 & m2_expr.ExprInt_from(arg3, arg3.size - 1)) + + +@sbuild.parse +def asr(arg1, arg2, arg3): + arg1 = m2_expr.ExprOp( + 'a>>', arg2, (arg3 & m2_expr.ExprInt_from(arg3, arg3.size - 1))) + + +@sbuild.parse +def mov(arg1, arg2): + arg1 = arg2 + + +def movk(ir, instr, arg1, arg2): + e = [] + if isinstance(arg2, m2_expr.ExprOp): + assert(arg2.op == 'slice_at' and + isinstance(arg2.args[0], m2_expr.ExprInt) and + isinstance(arg2.args[1], m2_expr.ExprInt)) + value, shift = int(arg2.args[0].arg), int(arg2.args[1].arg) + e.append( + m2_expr.ExprAff(arg1[shift:shift + 16], m2_expr.ExprInt16(value))) + else: + e.append(m2_expr.ExprAff(arg1[:16], m2_expr.ExprInt16(int(arg2.arg)))) + + return e, [] + + +@sbuild.parse +def movz(arg1, arg2): + arg1 = arg2 + + +@sbuild.parse +def movn(arg1, arg2): + arg1 = ~arg2 + + +@sbuild.parse +def bl(arg1): + PC = arg1 + ir.IRDst = arg1 + LR = m2_expr.ExprInt64(instr.offset + instr.l) + +@sbuild.parse +def csel(arg1, arg2, arg3, arg4): + cond_expr = cond2expr[arg4.name] + arg1 = arg2 if cond_expr else arg3 + + +def csinc(ir, instr, arg1, arg2, arg3, arg4): + e = [] + cond_expr = cond2expr[arg4.name] + e.append(m2_expr.ExprAff(arg1, m2_expr.ExprCond(cond_expr, + arg2, + arg3 + m2_expr.ExprInt_from(arg3, 1)))) + return e, [] + + +def csinv(ir, instr, arg1, arg2, arg3, arg4): + e = [] + cond_expr = cond2expr[arg4.name] + e.append(m2_expr.ExprAff(arg1, m2_expr.ExprCond(cond_expr, + arg2, + ~arg3))) + return e, [] + + +def csneg(ir, instr, arg1, arg2, arg3, arg4): + e = [] + cond_expr = cond2expr[arg4.name] + e.append(m2_expr.ExprAff(arg1, m2_expr.ExprCond(cond_expr, + arg2, + -arg3))) + return e, [] + + +def cset(ir, instr, arg1, arg2): + e = [] + cond_expr = cond2expr[arg2.name] + e.append(m2_expr.ExprAff(arg1, m2_expr.ExprCond(cond_expr, + m2_expr.ExprInt_from( + arg1, 1), + m2_expr.ExprInt_from(arg1, 0)))) + return e, [] + + +def csetm(ir, instr, arg1, arg2): + e = [] + cond_expr = cond2expr[arg2.name] + e.append(m2_expr.ExprAff(arg1, m2_expr.ExprCond(cond_expr, + m2_expr.ExprInt_from( + arg1, -1), + m2_expr.ExprInt_from(arg1, 0)))) + return e, [] + + +def get_mem_access(mem): + updt = None + if isinstance(mem, m2_expr.ExprOp): + if mem.op == 'preinc': + addr = mem.args[0] + mem.args[1] + elif mem.op == 'segm': + base = mem.args[0] + op, (reg, shift) = mem.args[1].op, mem.args[1].args + if op == 'SXTW': + off = reg.signExtend(base.size) << shift.zeroExtend(base.size) + addr = base + off + elif op == 'UXTW': + off = reg.zeroExtend(base.size) << shift.zeroExtend(base.size) + addr = base + off + elif op == 'LSL': + if isinstance(shift, m2_expr.ExprInt) and int(shift.arg) == 0: + addr = base + reg.zeroExtend(base.size) + else: + addr = base + \ + (reg.zeroExtend(base.size) + << shift.zeroExtend(base.size)) + else: + raise NotImplementedError('bad op') + elif mem.op == "postinc": + addr, off = mem.args + updt = m2_expr.ExprAff(addr, addr + off) + elif mem.op == "preinc_wb": + base, off = mem.args + addr = base + off + updt = m2_expr.ExprAff(base, base + off) + else: + raise NotImplementedError('bad op') + else: + raise NotImplementedError('bad op') + return addr, updt + + +def strb(ir, instr, arg1, arg2): + e = [] + addr, updt = get_mem_access(arg2) + e.append(m2_expr.ExprAff(m2_expr.ExprMem(addr, 8), arg1[:8])) + if updt: + e.append(updt) + return e, [] + + +def ldrb(ir, instr, arg1, arg2): + e = [] + addr, updt = get_mem_access(arg2) + e.append( + m2_expr.ExprAff(arg1, m2_expr.ExprMem(addr, 8).zeroExtend(arg1.size))) + if updt: + e.append(updt) + return e, [] + + +def str(ir, instr, arg1, arg2): + e = [] + addr, updt = get_mem_access(arg2) + e.append(m2_expr.ExprAff(m2_expr.ExprMem(addr, arg1.size), arg1)) + if updt: + e.append(updt) + return e, [] + + +def ldr(ir, instr, arg1, arg2): + e = [] + addr, updt = get_mem_access(arg2) + e.append(m2_expr.ExprAff(arg1, m2_expr.ExprMem(addr, arg1.size))) + if updt: + e.append(updt) + return e, [] + + +def stp(ir, instr, arg1, arg2, arg3): + e = [] + addr, updt = get_mem_access(arg3) + e.append(m2_expr.ExprAff(m2_expr.ExprMem(addr, arg1.size), arg1)) + e.append( + m2_expr.ExprAff(m2_expr.ExprMem(addr + m2_expr.ExprInt_from(addr, arg1.size / 8), arg2.size), arg2)) + if updt: + e.append(updt) + return e, [] + + +def ldp(ir, instr, arg1, arg2, arg3): + e = [] + addr, updt = get_mem_access(arg3) + e.append(m2_expr.ExprAff(arg1, m2_expr.ExprMem(addr, arg1.size))) + e.append( + m2_expr.ExprAff(arg2, m2_expr.ExprMem(addr + m2_expr.ExprInt_from(addr, arg1.size / 8), arg2.size))) + if updt: + e.append(updt) + return e, [] + + +def ldrsw(ir, instr, arg1, arg2): + e = [] + addr, updt = get_mem_access(arg2) + e.append( + m2_expr.ExprAff(arg1, m2_expr.ExprMem(addr, 32).signExtend(arg1.size))) + if updt: + e.append(updt) + return e, [] + + +def sbfm(ir, instr, arg1, arg2, arg3, arg4): + e = [] + rim, sim = int(arg3.arg), int(arg4.arg) + 1 + if sim > rim: + res = arg2[rim:sim].signExtend(arg1.size) + else: + shift = m2_expr.ExprInt_from(arg2, arg2.size - rim) + res = (arg2[:sim].signExtend(arg1.size) << shift) + e.append(m2_expr.ExprAff(arg1, res)) + return e, [] + + +def ubfm(ir, instr, arg1, arg2, arg3, arg4): + e = [] + rim, sim = int(arg3.arg), int(arg4.arg) + 1 + if sim > rim: + res = arg2[rim:sim].zeroExtend(arg1.size) + else: + shift = m2_expr.ExprInt_from(arg2, arg2.size - rim) + res = (arg2[:sim].zeroExtend(arg1.size) << shift) + e.append(m2_expr.ExprAff(arg1, res)) + return e, [] + + +@sbuild.parse +def madd(arg1, arg2, arg3, arg4): + arg1 = arg2 * arg3 + arg4 + + +@sbuild.parse +def udiv(arg1, arg2, arg3): + arg1 = m2_expr.ExprOp('udiv', arg2, arg3) + + +@sbuild.parse +def cbz(arg1, arg2): + dst = m2_expr.ExprId(ir.get_next_label(instr), 64) if arg1 else arg2 + PC = dst + ir.IRDst = dst + + +@sbuild.parse +def cbnz(arg1, arg2): + dst = arg2 if arg1 else m2_expr.ExprId(ir.get_next_label(instr), 64) + PC = dst + ir.IRDst = dst + + +@sbuild.parse +def tbz(arg1, arg2, arg3): + bitmask = m2_expr.ExprInt_from(arg1, 1) << arg2 + dst = m2_expr.ExprId( + ir.get_next_label(instr), 64) if arg1 & bitmask else arg3 + PC = dst + ir.IRDst = dst + + +@sbuild.parse +def tbnz(arg1, arg2, arg3): + bitmask = m2_expr.ExprInt_from(arg1, 1) << arg2 + dst = arg3 if arg1 & bitmask else m2_expr.ExprId( + ir.get_next_label(instr), 64) + PC = dst + ir.IRDst = dst + + +@sbuild.parse +def b_ne(arg1): + dst = m2_expr.ExprId(ir.get_next_label(instr), 64) if zf else arg1 + PC = dst + ir.IRDst = dst + + +@sbuild.parse +def b_eq(arg1): + dst = arg1 if zf else m2_expr.ExprId(ir.get_next_label(instr), 64) + PC = dst + ir.IRDst = dst + + +@sbuild.parse +def b_ge(arg1): + cond = cond2expr['GE'] + dst = arg1 if cond else m2_expr.ExprId(ir.get_next_label(instr), 64) + PC = dst + ir.IRDst = dst + + +@sbuild.parse +def b_gt(arg1): + cond = cond2expr['GT'] + dst = arg1 if cond else m2_expr.ExprId(ir.get_next_label(instr), 64) + PC = dst + ir.IRDst = dst + + +@sbuild.parse +def b_cc(arg1): + cond = cond2expr['CC'] + dst = arg1 if cond else m2_expr.ExprId(ir.get_next_label(instr), 64) + PC = dst + ir.IRDst = dst + + +@sbuild.parse +def b_cs(arg1): + cond = cond2expr['CS'] + dst = arg1 if cond else m2_expr.ExprId(ir.get_next_label(instr), 64) + PC = dst + ir.IRDst = dst + + +@sbuild.parse +def b_hi(arg1): + cond = cond2expr['HI'] + dst = arg1 if cond else m2_expr.ExprId(ir.get_next_label(instr), 64) + PC = dst + ir.IRDst = dst + + +@sbuild.parse +def b_le(arg1): + cond = cond2expr['LE'] + dst = arg1 if cond else m2_expr.ExprId(ir.get_next_label(instr), 64) + PC = dst + ir.IRDst = dst + + +@sbuild.parse +def b_ls(arg1): + cond = cond2expr['LS'] + dst = arg1 if cond else m2_expr.ExprId(ir.get_next_label(instr), 64) + PC = dst + ir.IRDst = dst + + +@sbuild.parse +def b_lt(arg1): + cond = cond2expr['LT'] + dst = arg1 if cond else m2_expr.ExprId(ir.get_next_label(instr), 64) + PC = dst + ir.IRDst = dst + + +@sbuild.parse +def ret(arg1): + PC = arg1 + ir.IRDst = arg1 + + +@sbuild.parse +def adrp(arg1, arg2): + arg1 = (PC & m2_expr.ExprInt64(0xfffffffffffff000)) + arg2 + + +@sbuild.parse +def b(arg1): + PC = arg1 + ir.IRDst = arg1 + + +@sbuild.parse +def br(arg1): + PC = arg1 + ir.IRDst = arg1 + + +@sbuild.parse +def nop(): + """Do nothing""" + +mnemo_func = sbuild.functions +mnemo_func.update({ + 'and': and_l, + 'adds': adds, + 'ands': ands, + 'subs': subs, + 'cmp': cmp, + 'cmn': cmn, + 'movk': movk, + 'csinc': csinc, + 'csinv': csinv, + 'csneg': csneg, + 'cset': cset, + 'csetm': csetm, + + 'b.ne': b_ne, + 'b.eq': b_eq, + 'b.ge': b_ge, + 'b.gt': b_gt, + 'b.cc': b_cc, + 'b.cs': b_cs, + 'b.hi': b_hi, + 'b.le': b_le, + 'b.ls': b_ls, + 'b.lt': b_lt, + + 'ret': ret, + 'stp': stp, + 'ldp': ldp, + + 'str': str, + 'ldr': ldr, + + 'ldur': ldr, # XXXX CHECK + + 'ldrsw': ldrsw, + + 'strb': strb, + 'ldrb': ldrb, + + 'sbfm': sbfm, + 'ubfm': ubfm, + +}) + + +def get_mnemo_expr(ir, instr, *args): + if not instr.name.lower() in mnemo_func: + raise NotImplementedError('unknown mnemo %s' % instr) + instr, extra_ir = mnemo_func[instr.name.lower()](ir, instr, *args) + return instr, extra_ir + + +class aarch64info: + mode = "aarch64" + # offset + + +class ir_aarch64l(ir): + + def __init__(self, symbol_pool=None): + ir.__init__(self, mn_aarch64, "l", symbol_pool) + self.pc = PC + self.sp = SP + self.IRDst = m2_expr.ExprId('IRDst', 64) + + def get_ir(self, instr): + args = instr.args + if len(args) and isinstance(args[-1], m2_expr.ExprOp): + if (args[-1].op in ['<<', '>>', '<<a', 'a>>', '<<<', '>>>'] and + isinstance(args[-1].args[-1], m2_expr.ExprId)): + args[-1] = m2_expr.ExprOp(args[-1].op, + args[-1].args[0], + args[-1].args[-1][:8].zeroExtend(32)) + instr_ir, extra_ir = get_mnemo_expr(self, instr, *args) + # for i, expr in enumerate(instr_ir): + # instr_ir[i] = self.expraff_fix_regs_for_mode(expr) + # for b in extra_ir: + # for irs in b.irs: + # for i, expr in enumerate(irs): + # irs[i] = self.expraff_fix_regs_for_mode(expr) + return instr_ir, extra_ir + + def expr_fix_regs_for_mode(self, e): + return e.replace_expr(replace_regs) + + def expraff_fix_regs_for_mode(self, e): + dst = self.expr_fix_regs_for_mode(e.dst) + src = self.expr_fix_regs_for_mode(e.src) + return m2_expr.ExprAff(dst, src) + + def irbloc_fix_regs_for_mode(self, irbloc, mode=64): + for irs in irbloc.irs: + for i, e in enumerate(irs): + """ + special case for 64 bits: + if destination is a 32 bit reg, zero extend the 64 bit reg + """ + if (isinstance(e.dst, m2_expr.ExprId) and + e.dst.size == 32 and + e.dst in replace_regs): + src = self.expr_fix_regs_for_mode(e.src) + dst = replace_regs[e.dst].arg + e = m2_expr.ExprAff(dst, src.zeroExtend(64)) + irs[i] = self.expr_fix_regs_for_mode(e) + irbloc.dst = self.expr_fix_regs_for_mode(irbloc.dst) + + +class ir_aarch64b(ir_aarch64l): + + def __init__(self, symbol_pool=None): + ir.__init__(self, mn_aarch64, "b", symbol_pool) + self.pc = PC + self.sp = SP + self.IRDst = m2_expr.ExprId('IRDst', 64) diff --git a/miasm2/jitter/arch/JitCore_aarch64.c b/miasm2/jitter/arch/JitCore_aarch64.c new file mode 100644 index 00000000..28661bfe --- /dev/null +++ b/miasm2/jitter/arch/JitCore_aarch64.c @@ -0,0 +1,699 @@ +#include <Python.h> +#include "../JitCore.h" +#include "structmember.h" +#include <stdint.h> +#include <inttypes.h> +#include "../queue.h" +#include "../vm_mngr.h" +#include "../vm_mngr_py.h" +#include "JitCore_aarch64.h" + + + +reg_dict gpreg_dict[] = { + {.name = "X0", .offset = offsetof(vm_cpu_t, X0)}, + {.name = "X1", .offset = offsetof(vm_cpu_t, X1)}, + {.name = "X2", .offset = offsetof(vm_cpu_t, X2)}, + {.name = "X3", .offset = offsetof(vm_cpu_t, X3)}, + {.name = "X4", .offset = offsetof(vm_cpu_t, X4)}, + {.name = "X5", .offset = offsetof(vm_cpu_t, X5)}, + {.name = "X6", .offset = offsetof(vm_cpu_t, X6)}, + {.name = "X7", .offset = offsetof(vm_cpu_t, X7)}, + {.name = "X8", .offset = offsetof(vm_cpu_t, X8)}, + {.name = "X9", .offset = offsetof(vm_cpu_t, X9)}, + {.name = "X10", .offset = offsetof(vm_cpu_t, X10)}, + {.name = "X11", .offset = offsetof(vm_cpu_t, X11)}, + {.name = "X12", .offset = offsetof(vm_cpu_t, X12)}, + {.name = "X13", .offset = offsetof(vm_cpu_t, X13)}, + {.name = "X14", .offset = offsetof(vm_cpu_t, X14)}, + {.name = "X15", .offset = offsetof(vm_cpu_t, X15)}, + {.name = "X16", .offset = offsetof(vm_cpu_t, X16)}, + {.name = "X17", .offset = offsetof(vm_cpu_t, X17)}, + {.name = "X18", .offset = offsetof(vm_cpu_t, X18)}, + {.name = "X19", .offset = offsetof(vm_cpu_t, X19)}, + {.name = "X20", .offset = offsetof(vm_cpu_t, X20)}, + {.name = "X21", .offset = offsetof(vm_cpu_t, X21)}, + {.name = "X22", .offset = offsetof(vm_cpu_t, X22)}, + {.name = "X23", .offset = offsetof(vm_cpu_t, X23)}, + {.name = "X24", .offset = offsetof(vm_cpu_t, X24)}, + {.name = "X25", .offset = offsetof(vm_cpu_t, X25)}, + {.name = "X26", .offset = offsetof(vm_cpu_t, X26)}, + {.name = "X27", .offset = offsetof(vm_cpu_t, X27)}, + {.name = "X28", .offset = offsetof(vm_cpu_t, X28)}, + {.name = "X29", .offset = offsetof(vm_cpu_t, X29)}, + {.name = "LR", .offset = offsetof(vm_cpu_t, LR)}, + + {.name = "SP", .offset = offsetof(vm_cpu_t, SP)}, + {.name = "PC", .offset = offsetof(vm_cpu_t, PC)}, + + {.name = "zf", .offset = offsetof(vm_cpu_t, zf)}, + {.name = "nf", .offset = offsetof(vm_cpu_t, nf)}, + {.name = "of", .offset = offsetof(vm_cpu_t, of)}, + {.name = "cf", .offset = offsetof(vm_cpu_t, cf)}, +}; + +/************************** JitCpu object **************************/ + + + + +PyObject* cpu_get_gpreg(JitCpu* self) +{ + PyObject *dict = PyDict_New(); + PyObject *o; + + get_reg(X0); + get_reg(X1); + get_reg(X2); + get_reg(X3); + get_reg(X4); + get_reg(X5); + get_reg(X6); + get_reg(X7); + get_reg(X8); + get_reg(X9); + get_reg(X10); + get_reg(X11); + get_reg(X12); + get_reg(X13); + get_reg(X14); + get_reg(X15); + get_reg(X16); + get_reg(X17); + get_reg(X18); + get_reg(X19); + get_reg(X20); + get_reg(X21); + get_reg(X22); + get_reg(X23); + get_reg(X24); + get_reg(X25); + get_reg(X26); + get_reg(X27); + get_reg(X28); + get_reg(X29); + get_reg(LR); + get_reg(SP); + get_reg(PC); + + get_reg(zf); + get_reg(nf); + get_reg(of); + get_reg(cf); + + return dict; +} + + + +PyObject* cpu_set_gpreg(JitCpu* self, PyObject *args) +{ + PyObject* dict; + PyObject *d_key, *d_value = NULL; + Py_ssize_t pos = 0; + uint64_t val; + unsigned int i, found; + + if (!PyArg_ParseTuple(args, "O", &dict)) + return NULL; + if(!PyDict_Check(dict)) + RAISE(PyExc_TypeError, "arg must be dict"); + while(PyDict_Next(dict, &pos, &d_key, &d_value)){ + if(!PyString_Check(d_key)) + RAISE(PyExc_TypeError, "key must be str"); + + PyGetInt(d_value, val); + + found = 0; + for (i=0; i < sizeof(gpreg_dict)/sizeof(reg_dict); i++){ + if (strcmp(PyString_AsString(d_key), gpreg_dict[i].name)) + continue; + *((uint32_t*)(((char*)(self->cpu)) + gpreg_dict[i].offset)) = val; + found = 1; + break; + } + + if (found) + continue; + fprintf(stderr, "unkown key: %s\n", PyString_AsString(d_key)); + RAISE(PyExc_ValueError, "unkown reg"); + } + Py_INCREF(Py_None); + return Py_None; +} + + +PyObject * cpu_init_regs(JitCpu* self) +{ + memset(self->cpu, 0, sizeof(vm_cpu_t)); + + Py_INCREF(Py_None); + return Py_None; +} + +void dump_gpregs(vm_cpu_t* vmcpu) +{ + printf("X0 %.16"PRIX64" X1 %.16"PRIX64" X2 %.16"PRIX64" X3 %.16"PRIX64" "\ + "X4 %.16"PRIX64" X5 %.16"PRIX64" X6 %.16"PRIX64" X7 %.16"PRIX64"\n", + vmcpu->X0, vmcpu->X1, vmcpu->X2, vmcpu->X3, vmcpu->X4, vmcpu->X5, vmcpu->X6, vmcpu->X7); + printf("X8 %.16"PRIX64" X9 %.16"PRIX64" X10 %.16"PRIX64" X11 %.16"PRIX64" "\ + "X12 %.16"PRIX64" X13 %.16"PRIX64" X14 %.16"PRIX64" X15 %.16"PRIX64"\n", + vmcpu->X8, vmcpu->X9, vmcpu->X10, vmcpu->X11, + vmcpu->X12, vmcpu->X13, vmcpu->X14, vmcpu->X15); + printf("X16 %.16"PRIX64" X17 %.16"PRIX64" X18 %.16"PRIX64" X19 %.16"PRIX64" "\ + "X20 %.16"PRIX64" X21 %.16"PRIX64" X22 %.16"PRIX64" X23 %.16"PRIX64"\n", + vmcpu->X16, vmcpu->X17, vmcpu->X18, vmcpu->X19, + vmcpu->X20, vmcpu->X21, vmcpu->X22, vmcpu->X23); + printf("X24 %.16"PRIX64" X25 %.16"PRIX64" X26 %.16"PRIX64" X27 %.16"PRIX64" "\ + "X28 %.16"PRIX64" X29 %.16"PRIX64" LR %.16"PRIX64"\n", + vmcpu->X24, vmcpu->X25, vmcpu->X26, vmcpu->X27, + vmcpu->X28, vmcpu->X29, vmcpu->LR); + + + printf("SP %.16"PRIX64" PC %.16"PRIX64" "\ + "zf %.16"PRIX32" nf %.16"PRIX32" of %.16"PRIX32" cf %.16"PRIX32"\n", + vmcpu->SP, vmcpu->PC, + vmcpu->zf, vmcpu->nf, vmcpu->of, vmcpu->cf); +} + + +PyObject * cpu_dump_gpregs(JitCpu* self, PyObject* args) +{ + vm_cpu_t* vmcpu; + + vmcpu = self->cpu; + dump_gpregs(vmcpu); + Py_INCREF(Py_None); + return Py_None; +} + + +PyObject* cpu_set_exception(JitCpu* self, PyObject* args) +{ + PyObject *item1; + uint64_t i; + + if (!PyArg_ParseTuple(args, "O", &item1)) + return NULL; + + PyGetInt(item1, i); + + ((vm_cpu_t*)self->cpu)->exception_flags = i; + Py_INCREF(Py_None); + return Py_None; +} + +PyObject* cpu_get_exception(JitCpu* self, PyObject* args) +{ + return PyLong_FromUnsignedLongLong((uint64_t)(((vm_cpu_t*)self->cpu)->exception_flags)); +} + + + + + +void check_automod(JitCpu* jitcpu, uint64_t addr, uint64_t size) +{ + PyObject *result; + + if (!(((VmMngr*)jitcpu->pyvm)->vm_mngr.exception_flags & EXCEPT_CODE_AUTOMOD)) + return; + result = PyObject_CallMethod(jitcpu->jitter, "automod_cb", "LL", addr, size); + Py_DECREF(result); + +} + +void MEM_WRITE_08(JitCpu* jitcpu, uint64_t addr, uint8_t src) +{ + vm_MEM_WRITE_08(&((VmMngr*)jitcpu->pyvm)->vm_mngr, addr, src); + check_automod(jitcpu, addr, 8); +} + +void MEM_WRITE_16(JitCpu* jitcpu, uint64_t addr, uint16_t src) +{ + vm_MEM_WRITE_16(&((VmMngr*)jitcpu->pyvm)->vm_mngr, addr, src); + check_automod(jitcpu, addr, 16); +} + +void MEM_WRITE_32(JitCpu* jitcpu, uint64_t addr, uint32_t src) +{ + vm_MEM_WRITE_32(&((VmMngr*)jitcpu->pyvm)->vm_mngr, addr, src); + check_automod(jitcpu, addr, 32); +} + +void MEM_WRITE_64(JitCpu* jitcpu, uint64_t addr, uint64_t src) +{ + vm_MEM_WRITE_64(&((VmMngr*)jitcpu->pyvm)->vm_mngr, addr, src); + check_automod(jitcpu, addr, 64); +} + + + + + + +PyObject* vm_set_mem(JitCpu *self, PyObject* args) +{ + PyObject *py_addr; + PyObject *py_buffer; + Py_ssize_t py_length; + + char * buffer; + uint64_t size; + uint64_t addr; + int ret = 0x1337; + + if (!PyArg_ParseTuple(args, "OO", &py_addr, &py_buffer)) + return NULL; + + PyGetInt(py_addr, addr); + + if(!PyString_Check(py_buffer)) + RAISE(PyExc_TypeError,"arg must be str"); + + size = PyString_Size(py_buffer); + PyString_AsStringAndSize(py_buffer, &buffer, &py_length); + + ret = vm_write_mem(&(((VmMngr*)self->pyvm)->vm_mngr), addr, buffer, size); + if (ret < 0) + RAISE(PyExc_TypeError,"arg must be str"); + check_automod(self, addr, size*8); + + Py_INCREF(Py_None); + return Py_None; +} + + +UDIV(16) +UDIV(32) +UDIV(64) + +UMOD(16) +UMOD(32) +UMOD(64) + + +IDIV(16) +IDIV(32) +IDIV(64) + +IMOD(16) +IMOD(32) +IMOD(64) + + +static PyMemberDef JitCpu_members[] = { + {NULL} /* Sentinel */ +}; + +static PyMethodDef JitCpu_methods[] = { + {"init_regs", (PyCFunction)cpu_init_regs, METH_NOARGS, + "X"}, + {"dump_gpregs", (PyCFunction)cpu_dump_gpregs, METH_NOARGS, + "X"}, + {"get_gpreg", (PyCFunction)cpu_get_gpreg, METH_NOARGS, + "X"}, + {"set_gpreg", (PyCFunction)cpu_set_gpreg, METH_VARARGS, + "X"}, + {"get_exception", (PyCFunction)cpu_get_exception, METH_VARARGS, + "X"}, + {"set_exception", (PyCFunction)cpu_set_exception, METH_VARARGS, + "X"}, + {"set_mem", (PyCFunction)vm_set_mem, METH_VARARGS, + "X"}, + {"get_mem", (PyCFunction)vm_get_mem, METH_VARARGS, + "X"}, + {NULL} /* Sentinel */ +}; + +static int +JitCpu_init(JitCpu *self, PyObject *args, PyObject *kwds) +{ + self->cpu = malloc(sizeof(vm_cpu_t)); + if (self->cpu == NULL) { + fprintf(stderr, "cannot alloc vm_cpu_t\n"); + exit(0); + } + return 0; +} + + + +getset_reg_u64(X0); +getset_reg_u64(X1); +getset_reg_u64(X2); +getset_reg_u64(X3); +getset_reg_u64(X4); +getset_reg_u64(X5); +getset_reg_u64(X6); +getset_reg_u64(X7); +getset_reg_u64(X8); +getset_reg_u64(X9); +getset_reg_u64(X10); +getset_reg_u64(X11); +getset_reg_u64(X12); +getset_reg_u64(X13); +getset_reg_u64(X14); +getset_reg_u64(X15); +getset_reg_u64(X16); +getset_reg_u64(X17); +getset_reg_u64(X18); +getset_reg_u64(X19); +getset_reg_u64(X20); +getset_reg_u64(X21); +getset_reg_u64(X22); +getset_reg_u64(X23); +getset_reg_u64(X24); +getset_reg_u64(X25); +getset_reg_u64(X26); +getset_reg_u64(X27); +getset_reg_u64(X28); +getset_reg_u64(X29); +getset_reg_u64(LR); +getset_reg_u64(SP); +getset_reg_u64(PC); + +getset_reg_u32(zf); +getset_reg_u32(nf); +getset_reg_u32(of); +getset_reg_u32(cf); + + + +PyObject* get_gpreg_offset_all(void) +{ + PyObject *dict = PyDict_New(); + PyObject *o; + + get_reg_off(exception_flags); + get_reg_off(exception_flags_new); + + get_reg_off(X0); + get_reg_off(X1); + get_reg_off(X2); + get_reg_off(X3); + get_reg_off(X4); + get_reg_off(X5); + get_reg_off(X6); + get_reg_off(X7); + get_reg_off(X8); + get_reg_off(X9); + get_reg_off(X10); + get_reg_off(X11); + get_reg_off(X12); + get_reg_off(X13); + get_reg_off(X14); + get_reg_off(X15); + get_reg_off(X16); + get_reg_off(X17); + get_reg_off(X18); + get_reg_off(X19); + get_reg_off(X20); + get_reg_off(X21); + get_reg_off(X22); + get_reg_off(X23); + get_reg_off(X24); + get_reg_off(X25); + get_reg_off(X26); + get_reg_off(X27); + get_reg_off(X28); + get_reg_off(X29); + get_reg_off(LR); + get_reg_off(SP); + get_reg_off(PC); + + + get_reg_off(X0_new); + get_reg_off(X1_new); + get_reg_off(X2_new); + get_reg_off(X3_new); + get_reg_off(X4_new); + get_reg_off(X5_new); + get_reg_off(X6_new); + get_reg_off(X7_new); + get_reg_off(X8_new); + get_reg_off(X9_new); + get_reg_off(X10_new); + get_reg_off(X11_new); + get_reg_off(X12_new); + get_reg_off(X13_new); + get_reg_off(X14_new); + get_reg_off(X15_new); + get_reg_off(X16_new); + get_reg_off(X17_new); + get_reg_off(X18_new); + get_reg_off(X19_new); + get_reg_off(X20_new); + get_reg_off(X21_new); + get_reg_off(X22_new); + get_reg_off(X23_new); + get_reg_off(X24_new); + get_reg_off(X25_new); + get_reg_off(X26_new); + get_reg_off(X27_new); + get_reg_off(X28_new); + get_reg_off(X29_new); + get_reg_off(LR_new); + get_reg_off(SP_new); + get_reg_off(PC_new); + + + + /* eflag */ + get_reg_off(zf); + get_reg_off(nf); + get_reg_off(of); + get_reg_off(cf); + + get_reg_off(zf_new); + get_reg_off(nf_new); + get_reg_off(of_new); + get_reg_off(cf_new); + + + get_reg_off(pfmem08_0); + get_reg_off(pfmem08_1); + get_reg_off(pfmem08_2); + get_reg_off(pfmem08_3); + get_reg_off(pfmem08_4); + get_reg_off(pfmem08_5); + get_reg_off(pfmem08_6); + get_reg_off(pfmem08_7); + get_reg_off(pfmem08_8); + get_reg_off(pfmem08_9); + get_reg_off(pfmem08_10); + get_reg_off(pfmem08_11); + get_reg_off(pfmem08_12); + get_reg_off(pfmem08_13); + get_reg_off(pfmem08_14); + get_reg_off(pfmem08_15); + get_reg_off(pfmem08_16); + get_reg_off(pfmem08_17); + get_reg_off(pfmem08_18); + get_reg_off(pfmem08_19); + + + get_reg_off(pfmem16_0); + get_reg_off(pfmem16_1); + get_reg_off(pfmem16_2); + get_reg_off(pfmem16_3); + get_reg_off(pfmem16_4); + get_reg_off(pfmem16_5); + get_reg_off(pfmem16_6); + get_reg_off(pfmem16_7); + get_reg_off(pfmem16_8); + get_reg_off(pfmem16_9); + get_reg_off(pfmem16_10); + get_reg_off(pfmem16_11); + get_reg_off(pfmem16_12); + get_reg_off(pfmem16_13); + get_reg_off(pfmem16_14); + get_reg_off(pfmem16_15); + get_reg_off(pfmem16_16); + get_reg_off(pfmem16_17); + get_reg_off(pfmem16_18); + get_reg_off(pfmem16_19); + + + get_reg_off(pfmem32_0); + get_reg_off(pfmem32_1); + get_reg_off(pfmem32_2); + get_reg_off(pfmem32_3); + get_reg_off(pfmem32_4); + get_reg_off(pfmem32_5); + get_reg_off(pfmem32_6); + get_reg_off(pfmem32_7); + get_reg_off(pfmem32_8); + get_reg_off(pfmem32_9); + get_reg_off(pfmem32_10); + get_reg_off(pfmem32_11); + get_reg_off(pfmem32_12); + get_reg_off(pfmem32_13); + get_reg_off(pfmem32_14); + get_reg_off(pfmem32_15); + get_reg_off(pfmem32_16); + get_reg_off(pfmem32_17); + get_reg_off(pfmem32_18); + get_reg_off(pfmem32_19); + + + get_reg_off(pfmem64_0); + get_reg_off(pfmem64_1); + get_reg_off(pfmem64_2); + get_reg_off(pfmem64_3); + get_reg_off(pfmem64_4); + get_reg_off(pfmem64_5); + get_reg_off(pfmem64_6); + get_reg_off(pfmem64_7); + get_reg_off(pfmem64_8); + get_reg_off(pfmem64_9); + get_reg_off(pfmem64_10); + get_reg_off(pfmem64_11); + get_reg_off(pfmem64_12); + get_reg_off(pfmem64_13); + get_reg_off(pfmem64_14); + get_reg_off(pfmem64_15); + get_reg_off(pfmem64_16); + get_reg_off(pfmem64_17); + get_reg_off(pfmem64_18); + get_reg_off(pfmem64_19); + + return dict; +} + + +static PyGetSetDef JitCpu_getseters[] = { + {"vmmngr", + (getter)JitCpu_get_vmmngr, (setter)JitCpu_set_vmmngr, + "vmmngr", + NULL}, + + {"jitter", + (getter)JitCpu_get_jitter, (setter)JitCpu_set_jitter, + "jitter", + NULL}, + + + + {"X0" , (getter)JitCpu_get_X0 , (setter)JitCpu_set_X0 , "X0" , NULL}, + {"X1" , (getter)JitCpu_get_X1 , (setter)JitCpu_set_X1 , "X1" , NULL}, + {"X2" , (getter)JitCpu_get_X2 , (setter)JitCpu_set_X2 , "X2" , NULL}, + {"X3" , (getter)JitCpu_get_X3 , (setter)JitCpu_set_X3 , "X3" , NULL}, + {"X4" , (getter)JitCpu_get_X4 , (setter)JitCpu_set_X4 , "X4" , NULL}, + {"X5" , (getter)JitCpu_get_X5 , (setter)JitCpu_set_X5 , "X5" , NULL}, + {"X6" , (getter)JitCpu_get_X6 , (setter)JitCpu_set_X6 , "X6" , NULL}, + {"X7" , (getter)JitCpu_get_X7 , (setter)JitCpu_set_X7 , "X7" , NULL}, + {"X8" , (getter)JitCpu_get_X8 , (setter)JitCpu_set_X8 , "X8" , NULL}, + {"X9" , (getter)JitCpu_get_X9 , (setter)JitCpu_set_X9 , "X9" , NULL}, + + {"X10" , (getter)JitCpu_get_X10 , (setter)JitCpu_set_X10 , "X10" , NULL}, + {"X11" , (getter)JitCpu_get_X11 , (setter)JitCpu_set_X11 , "X11" , NULL}, + {"X12" , (getter)JitCpu_get_X12 , (setter)JitCpu_set_X12 , "X12" , NULL}, + {"X13" , (getter)JitCpu_get_X13 , (setter)JitCpu_set_X13 , "X13" , NULL}, + {"X14" , (getter)JitCpu_get_X14 , (setter)JitCpu_set_X14 , "X14" , NULL}, + {"X15" , (getter)JitCpu_get_X15 , (setter)JitCpu_set_X15 , "X15" , NULL}, + {"X16" , (getter)JitCpu_get_X16 , (setter)JitCpu_set_X16 , "X16" , NULL}, + {"X17" , (getter)JitCpu_get_X17 , (setter)JitCpu_set_X17 , "X17" , NULL}, + {"X18" , (getter)JitCpu_get_X18 , (setter)JitCpu_set_X18 , "X18" , NULL}, + {"X19" , (getter)JitCpu_get_X19 , (setter)JitCpu_set_X19 , "X19" , NULL}, + + {"X20" , (getter)JitCpu_get_X20 , (setter)JitCpu_set_X20 , "X20" , NULL}, + {"X21" , (getter)JitCpu_get_X21 , (setter)JitCpu_set_X21 , "X21" , NULL}, + {"X22" , (getter)JitCpu_get_X22 , (setter)JitCpu_set_X22 , "X22" , NULL}, + {"X23" , (getter)JitCpu_get_X23 , (setter)JitCpu_set_X23 , "X23" , NULL}, + {"X24" , (getter)JitCpu_get_X24 , (setter)JitCpu_set_X24 , "X24" , NULL}, + {"X25" , (getter)JitCpu_get_X25 , (setter)JitCpu_set_X25 , "X25" , NULL}, + {"X26" , (getter)JitCpu_get_X26 , (setter)JitCpu_set_X26 , "X26" , NULL}, + {"X27" , (getter)JitCpu_get_X27 , (setter)JitCpu_set_X27 , "X27" , NULL}, + {"X28" , (getter)JitCpu_get_X28 , (setter)JitCpu_set_X28 , "X28" , NULL}, + {"X29" , (getter)JitCpu_get_X29 , (setter)JitCpu_set_X29 , "X29" , NULL}, + + {"LR" , (getter)JitCpu_get_LR , (setter)JitCpu_set_LR , "LR" , NULL}, + + + + {"SP" , (getter)JitCpu_get_SP , (setter)JitCpu_set_SP , "SP" , NULL}, + {"PC" , (getter)JitCpu_get_PC , (setter)JitCpu_set_PC , "PC" , NULL}, + + {"zf", (getter)JitCpu_get_zf, (setter)JitCpu_set_zf, "zf", NULL}, + {"nf", (getter)JitCpu_get_nf, (setter)JitCpu_set_nf, "nf", NULL}, + {"of", (getter)JitCpu_get_of, (setter)JitCpu_set_of, "of", NULL}, + {"cf", (getter)JitCpu_get_cf, (setter)JitCpu_set_cf, "cf", NULL}, + + {NULL} /* Sentinel */ +}; + + +static PyTypeObject JitCpuType = { + PyObject_HEAD_INIT(NULL) + 0, /*ob_size*/ + "JitCore_aarch64.JitCpu", /*tp_name*/ + sizeof(JitCpu), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + (destructor)JitCpu_dealloc,/*tp_dealloc*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash */ + 0, /*tp_call*/ + 0, /*tp_str*/ + 0, /*tp_getattro*/ + 0, /*tp_setattro*/ + 0, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ + "JitCpu objects", /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + JitCpu_methods, /* tp_methods */ + JitCpu_members, /* tp_members */ + JitCpu_getseters, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)JitCpu_init, /* tp_init */ + 0, /* tp_alloc */ + JitCpu_new, /* tp_new */ +}; + + + +static PyMethodDef JitCore_aarch64_Methods[] = { + {"get_gpreg_offset_all", (PyCFunction)get_gpreg_offset_all, METH_NOARGS}, + {NULL, NULL, 0, NULL} /* Sentinel */ + +}; + +static PyObject *JitCore_aarch64_Error; + +PyMODINIT_FUNC +initJitCore_aarch64(void) +{ + PyObject *m; + + if (PyType_Ready(&JitCpuType) < 0) + return; + + m = Py_InitModule("JitCore_aarch64", JitCore_aarch64_Methods); + if (m == NULL) + return; + + JitCore_aarch64_Error = PyErr_NewException("JitCore_aarch64.error", NULL, NULL); + Py_INCREF(JitCore_aarch64_Error); + PyModule_AddObject(m, "error", JitCore_aarch64_Error); + + Py_INCREF(&JitCpuType); + PyModule_AddObject(m, "JitCpu", (PyObject *)&JitCpuType); + +} + diff --git a/miasm2/jitter/arch/JitCore_aarch64.h b/miasm2/jitter/arch/JitCore_aarch64.h new file mode 100644 index 00000000..e1708541 --- /dev/null +++ b/miasm2/jitter/arch/JitCore_aarch64.h @@ -0,0 +1,196 @@ + +typedef struct { + uint32_t exception_flags; + uint32_t exception_flags_new; + + /* gpregs */ + + uint64_t X0; + uint64_t X1; + uint64_t X2; + uint64_t X3; + uint64_t X4; + uint64_t X5; + uint64_t X6; + uint64_t X7; + uint64_t X8; + uint64_t X9; + uint64_t X10; + uint64_t X11; + uint64_t X12; + uint64_t X13; + uint64_t X14; + uint64_t X15; + uint64_t X16; + uint64_t X17; + uint64_t X18; + uint64_t X19; + uint64_t X20; + uint64_t X21; + uint64_t X22; + uint64_t X23; + uint64_t X24; + uint64_t X25; + uint64_t X26; + uint64_t X27; + uint64_t X28; + uint64_t X29; + uint64_t LR; + uint64_t SP; + + uint64_t PC; + + + uint64_t X0_new; + uint64_t X1_new; + uint64_t X2_new; + uint64_t X3_new; + uint64_t X4_new; + uint64_t X5_new; + uint64_t X6_new; + uint64_t X7_new; + uint64_t X8_new; + uint64_t X9_new; + uint64_t X10_new; + uint64_t X11_new; + uint64_t X12_new; + uint64_t X13_new; + uint64_t X14_new; + uint64_t X15_new; + uint64_t X16_new; + uint64_t X17_new; + uint64_t X18_new; + uint64_t X19_new; + uint64_t X20_new; + uint64_t X21_new; + uint64_t X22_new; + uint64_t X23_new; + uint64_t X24_new; + uint64_t X25_new; + uint64_t X26_new; + uint64_t X27_new; + uint64_t X28_new; + uint64_t X29_new; + uint64_t LR_new; + uint64_t SP_new; + + uint64_t PC_new; + + /* eflag */ + uint32_t zf; + uint32_t nf; + uint32_t of; + uint32_t cf; + + uint32_t zf_new; + uint32_t nf_new; + uint32_t of_new; + uint32_t cf_new; + + + uint8_t pfmem08_0; + uint8_t pfmem08_1; + uint8_t pfmem08_2; + uint8_t pfmem08_3; + uint8_t pfmem08_4; + uint8_t pfmem08_5; + uint8_t pfmem08_6; + uint8_t pfmem08_7; + uint8_t pfmem08_8; + uint8_t pfmem08_9; + uint8_t pfmem08_10; + uint8_t pfmem08_11; + uint8_t pfmem08_12; + uint8_t pfmem08_13; + uint8_t pfmem08_14; + uint8_t pfmem08_15; + uint8_t pfmem08_16; + uint8_t pfmem08_17; + uint8_t pfmem08_18; + uint8_t pfmem08_19; + + + uint16_t pfmem16_0; + uint16_t pfmem16_1; + uint16_t pfmem16_2; + uint16_t pfmem16_3; + uint16_t pfmem16_4; + uint16_t pfmem16_5; + uint16_t pfmem16_6; + uint16_t pfmem16_7; + uint16_t pfmem16_8; + uint16_t pfmem16_9; + uint16_t pfmem16_10; + uint16_t pfmem16_11; + uint16_t pfmem16_12; + uint16_t pfmem16_13; + uint16_t pfmem16_14; + uint16_t pfmem16_15; + uint16_t pfmem16_16; + uint16_t pfmem16_17; + uint16_t pfmem16_18; + uint16_t pfmem16_19; + + + uint32_t pfmem32_0; + uint32_t pfmem32_1; + uint32_t pfmem32_2; + uint32_t pfmem32_3; + uint32_t pfmem32_4; + uint32_t pfmem32_5; + uint32_t pfmem32_6; + uint32_t pfmem32_7; + uint32_t pfmem32_8; + uint32_t pfmem32_9; + uint32_t pfmem32_10; + uint32_t pfmem32_11; + uint32_t pfmem32_12; + uint32_t pfmem32_13; + uint32_t pfmem32_14; + uint32_t pfmem32_15; + uint32_t pfmem32_16; + uint32_t pfmem32_17; + uint32_t pfmem32_18; + uint32_t pfmem32_19; + + + uint64_t pfmem64_0; + uint64_t pfmem64_1; + uint64_t pfmem64_2; + uint64_t pfmem64_3; + uint64_t pfmem64_4; + uint64_t pfmem64_5; + uint64_t pfmem64_6; + uint64_t pfmem64_7; + uint64_t pfmem64_8; + uint64_t pfmem64_9; + uint64_t pfmem64_10; + uint64_t pfmem64_11; + uint64_t pfmem64_12; + uint64_t pfmem64_13; + uint64_t pfmem64_14; + uint64_t pfmem64_15; + uint64_t pfmem64_16; + uint64_t pfmem64_17; + uint64_t pfmem64_18; + uint64_t pfmem64_19; + +}vm_cpu_t; + + +uint64_t udiv64(vm_cpu_t* vmcpu, uint64_t a, uint64_t b); +uint64_t umod64(vm_cpu_t* vmcpu, uint64_t a, uint64_t b); +int64_t idiv64(vm_cpu_t* vmcpu, int64_t a, int64_t b); +int64_t imod64(vm_cpu_t* vmcpu, int64_t a, int64_t b); + +uint32_t udiv32(vm_cpu_t* vmcpu, uint32_t a, uint32_t b); +uint32_t umod32(vm_cpu_t* vmcpu, uint32_t a, uint32_t b); +int32_t idiv32(vm_cpu_t* vmcpu, int32_t a, int32_t b); +int32_t imod32(vm_cpu_t* vmcpu, int32_t a, int32_t b); + +uint16_t udiv16(vm_cpu_t* vmcpu, uint16_t a, uint16_t b); +uint16_t umod16(vm_cpu_t* vmcpu, uint16_t a, uint16_t b); +int16_t idiv16(vm_cpu_t* vmcpu, int16_t a, int16_t b); +int16_t imod16(vm_cpu_t* vmcpu, int16_t a, int16_t b); + +#define RETURN_PC return BlockDst; diff --git a/miasm2/jitter/arch/JitCore_x86.c b/miasm2/jitter/arch/JitCore_x86.c index baa66755..dd4ce7cb 100644 --- a/miasm2/jitter/arch/JitCore_x86.c +++ b/miasm2/jitter/arch/JitCore_x86.c @@ -236,57 +236,6 @@ uint64_t segm2addr(JitCpu* jitcpu, uint64_t segm, uint64_t addr) } -#define UDIV(sizeA) \ - uint ## sizeA ## _t udiv ## sizeA (vm_cpu_t* vmcpu, uint ## sizeA ## _t a, uint ## sizeA ## _t b) \ - { \ - uint ## sizeA ## _t r; \ - if (b == 0) { \ - vmcpu->exception_flags |= EXCEPT_INT_DIV_BY_ZERO; \ - return 0; \ - } \ - r = a/b; \ - return r; \ - } - - -#define UMOD(sizeA) \ - uint ## sizeA ## _t umod ## sizeA (vm_cpu_t* vmcpu, uint ## sizeA ## _t a, uint ## sizeA ## _t b) \ - { \ - uint ## sizeA ## _t r; \ - if (b == 0) { \ - vmcpu->exception_flags |= EXCEPT_INT_DIV_BY_ZERO; \ - return 0; \ - } \ - r = a%b; \ - return r; \ - } - - -#define IDIV(sizeA) \ - int ## sizeA ## _t idiv ## sizeA (vm_cpu_t* vmcpu, int ## sizeA ## _t a, int ## sizeA ## _t b) \ - { \ - int ## sizeA ## _t r; \ - if (b == 0) { \ - vmcpu->exception_flags |= EXCEPT_INT_DIV_BY_ZERO; \ - return 0; \ - } \ - r = a/b; \ - return r; \ - } - - -#define IMOD(sizeA) \ - int ## sizeA ## _t imod ## sizeA (vm_cpu_t* vmcpu, int ## sizeA ## _t a, int ## sizeA ## _t b) \ - { \ - int ## sizeA ## _t r; \ - if (b == 0) { \ - vmcpu->exception_flags |= EXCEPT_INT_DIV_BY_ZERO; \ - return 0; \ - } \ - r = a%b; \ - return r; \ - } - UDIV(16) UDIV(32) UDIV(64) diff --git a/miasm2/jitter/jitload.py b/miasm2/jitter/jitload.py index 6faa3a9f..1c88d0b7 100644 --- a/miasm2/jitter/jitload.py +++ b/miasm2/jitter/jitload.py @@ -186,6 +186,8 @@ class jitter: from miasm2.jitter.arch import JitCore_x86 as jcore elif arch_name == "arm": from miasm2.jitter.arch import JitCore_arm as jcore + elif arch_name == "aarch64": + from miasm2.jitter.arch import JitCore_aarch64 as jcore elif arch_name == "msp430": from miasm2.jitter.arch import JitCore_msp430 as jcore elif arch_name == "mips32": diff --git a/miasm2/jitter/loader/elf.py b/miasm2/jitter/loader/elf.py index 61c40ddd..b3946000 100644 --- a/miasm2/jitter/loader/elf.py +++ b/miasm2/jitter/loader/elf.py @@ -85,6 +85,8 @@ class libimp_elf(libimp): # machine, size, sex -> arch_name ELF_machine = {(elf_csts.EM_ARM, 32, elf_csts.ELFDATA2LSB): "arml", (elf_csts.EM_ARM, 32, elf_csts.ELFDATA2MSB): "armb", + (elf_csts.EM_AARCH64, 64, elf_csts.ELFDATA2LSB): "aarch64l", + (elf_csts.EM_AARCH64, 64, elf_csts.ELFDATA2MSB): "aarch64b", (elf_csts.EM_MIPS, 32, elf_csts.ELFDATA2MSB): "mips32b", (elf_csts.EM_MIPS, 32, elf_csts.ELFDATA2LSB): "mips32l", (elf_csts.EM_386, 32, elf_csts.ELFDATA2LSB): "x86_32", diff --git a/miasm2/jitter/vm_mngr.c b/miasm2/jitter/vm_mngr.c index 23464bfb..bf1eb7df 100644 --- a/miasm2/jitter/vm_mngr.c +++ b/miasm2/jitter/vm_mngr.c @@ -821,11 +821,11 @@ uint64_t rot_left(uint64_t size, uint64_t a, uint64_t b) } } -unsigned int rot_right(unsigned int size, unsigned int a, unsigned int b) +uint64_t rot_right(uint64_t size, uint64_t a, uint64_t b) { - unsigned int tmp; + uint64_t tmp; - b = b&0x1F; + b = b&0x3F; b %= size; switch(size){ case 8: @@ -837,8 +837,11 @@ unsigned int rot_right(unsigned int size, unsigned int a, unsigned int b) case 32: tmp = ((a&0xFFFFFFFF) >> b) | (a << (size-b)); return tmp&0xffffffff; + case 64: + tmp = ((a&0xFFFFFFFFFFFFFFFF) >> b) | (a << (size-b)); + return tmp&0xFFFFFFFFFFFFFFFF; default: - fprintf(stderr, "inv size in rotleft %d\n", size); + fprintf(stderr, "inv size in rotright %"PRIX64"\n", size); exit(0); } } @@ -1699,3 +1702,5 @@ uint64_t get_exception_flag(vm_mngr_t* vm_mngr) { return vm_mngr->exception_flags; } + + diff --git a/miasm2/jitter/vm_mngr.h b/miasm2/jitter/vm_mngr.h index fc346cc5..c93ed583 100644 --- a/miasm2/jitter/vm_mngr.h +++ b/miasm2/jitter/vm_mngr.h @@ -205,10 +205,63 @@ unsigned int umul16_hi(unsigned short a, unsigned short b); unsigned int div_op(unsigned int size, unsigned int a, unsigned int b, unsigned int c); unsigned int rem_op(unsigned int size, unsigned int a, unsigned int b, unsigned int c); uint64_t rot_left(uint64_t size, uint64_t a, uint64_t b); -unsigned int rot_right(unsigned int size, unsigned int a, unsigned int b); +uint64_t rot_right(uint64_t size, uint64_t a, uint64_t b); int rcl_rez_op(unsigned int size, unsigned int a, unsigned int b, unsigned int cf); int rcl_cf_op(unsigned int size, unsigned int a, unsigned int b, unsigned int cf); + +#define UDIV(sizeA) \ + uint ## sizeA ## _t udiv ## sizeA (vm_cpu_t* vmcpu, uint ## sizeA ## _t a, uint ## sizeA ## _t b) \ + { \ + uint ## sizeA ## _t r; \ + if (b == 0) { \ + vmcpu->exception_flags |= EXCEPT_INT_DIV_BY_ZERO; \ + return 0; \ + } \ + r = a/b; \ + return r; \ + } + + +#define UMOD(sizeA) \ + uint ## sizeA ## _t umod ## sizeA (vm_cpu_t* vmcpu, uint ## sizeA ## _t a, uint ## sizeA ## _t b) \ + { \ + uint ## sizeA ## _t r; \ + if (b == 0) { \ + vmcpu->exception_flags |= EXCEPT_INT_DIV_BY_ZERO; \ + return 0; \ + } \ + r = a%b; \ + return r; \ + } + + +#define IDIV(sizeA) \ + int ## sizeA ## _t idiv ## sizeA (vm_cpu_t* vmcpu, int ## sizeA ## _t a, int ## sizeA ## _t b) \ + { \ + int ## sizeA ## _t r; \ + if (b == 0) { \ + vmcpu->exception_flags |= EXCEPT_INT_DIV_BY_ZERO; \ + return 0; \ + } \ + r = a/b; \ + return r; \ + } + + +#define IMOD(sizeA) \ + int ## sizeA ## _t imod ## sizeA (vm_cpu_t* vmcpu, int ## sizeA ## _t a, int ## sizeA ## _t b) \ + { \ + int ## sizeA ## _t r; \ + if (b == 0) { \ + vmcpu->exception_flags |= EXCEPT_INT_DIV_BY_ZERO; \ + return 0; \ + } \ + r = a%b; \ + return r; \ + } + + //PyObject* _vm_push_uint32_t(PyObject *item); //PyObject* _vm_pop_uint32_t(void); ////PyObject* _vm_put_str(PyObject *item); diff --git a/miasm2/os_dep/linux_stdlib.py b/miasm2/os_dep/linux_stdlib.py index d64c70b9..ec814864 100644 --- a/miasm2/os_dep/linux_stdlib.py +++ b/miasm2/os_dep/linux_stdlib.py @@ -4,6 +4,21 @@ from sys import stdout from string import printable +from miasm2.os_dep.common import \ + heap, set_str_ansi, set_str_unic, get_str_ansi, get_str_unic + + +class c_linobjs(object): + + base_addr = 0x20000000 + align_addr = 0x1000 + def __init__(self): + self.alloc_ad = self.base_addr + self.alloc_align = self.align_addr + self.heap = heap() + +linobjs = c_linobjs() + def xxx_isprint(jitter): ''' @@ -12,7 +27,7 @@ def xxx_isprint(jitter): checks for any printable character including space. ''' - ret_addr, args = jitter.func_args_stdcall(['c']) + ret_addr, args = jitter.func_args_stdcall(['c']) ret = 1 if chr(args.c & 0xFF) in printable else 0 return jitter.func_ret_stdcall(ret_addr, ret) @@ -29,6 +44,19 @@ def xxx_memcpy(jitter): return jitter.func_ret_stdcall(ret_addr, args.dest) +def xxx_memset(jitter): + ''' + #include <string.h> + void *memset(void *s, int c, size_t n); + + fills the first n bytes of the memory area pointed to by s with the constant + byte c.''' + + ret_addr, args = jitter.func_args_stdcall(['dest', 'c', 'n']) + jitter.vm.set_mem(args.dest, chr(args.c & 0xFF) * args.n) + return jitter.func_ret_stdcall(ret_addr, args.dest) + + def xxx_puts(jitter): ''' #include <stdio.h> @@ -47,16 +75,8 @@ def xxx_puts(jitter): return jitter.func_ret_stdcall(ret_addr, 1) -def xxx_snprintf(jitter): - ''' - #include <stdio.h> - int snprintf(char *str, size_t size, const char *format, ...); - - writes to string str according to format format and at most size bytes. - ''' - ret_addr, args = jitter.func_args_stdcall(['string', 'size', 'fmt']) - curarg, output, fmt = 3, '', args.fmt - size = args.size if args.size else 1 +def get_fmt_args(jitter, fmt, cur_arg): + output = "" while True: char = jitter.vm.get_mem(fmt, 1) fmt += 1 @@ -68,12 +88,80 @@ def xxx_snprintf(jitter): char = jitter.vm.get_mem(fmt, 1) fmt += 1 token += char - if char in '%cdfsux': + if char.lower() in '%cdfsux': break - char = token % jitter.get_arg_n_stdcall(curarg) - curarg += 1 + if token.endswith('s'): + arg = jitter.get_str_ansi(jitter.get_arg_n_stdcall(cur_arg)) + else: + arg = jitter.get_arg_n_stdcall(cur_arg) + char = token % arg + cur_arg += 1 output += char + return output + + +def xxx_snprintf(jitter): + ret_addr, args = jitter.func_args_stdcall(['string', 'size', 'fmt']) + cur_arg, fmt = 3, args.fmt + size = args.size if args.size else 1 + output = get_fmt_args(jitter, fmt, cur_arg) output = output[:size - 1] ret = len(output) jitter.vm.set_mem(args.string, output + '\x00') return jitter.func_ret_stdcall(ret_addr, ret) + + +def xxx_sprintf(jitter): + ret_addr, args = jitter.func_args_stdcall(['string', 'fmt']) + cur_arg, fmt = 2, args.fmt + output = get_fmt_args(jitter, fmt, cur_arg) + ret = len(output) + jitter.vm.set_mem(args.string, output + '\x00') + return jitter.func_ret_stdcall(ret_addr, ret) + + +def xxx_printf(jitter): + ret_addr, args = jitter.func_args_stdcall(['fmt']) + cur_arg, fmt = 1, args.fmt + output = get_fmt_args(jitter, fmt, cur_arg) + ret = len(output) + print output, + return jitter.func_ret_stdcall(ret_addr, ret) + + +def xxx_strcpy(jitter): + ret_ad, args = jitter.func_args_stdcall(["dst", "src"]) + str_src = jitter.get_str_ansi(args.src) + '\x00' + jitter.vm.set_mem(args.dst, str_src) + jitter.func_ret_stdcall(ret_ad, args.dst) + + +def xxx_strlen(jitter): + ret_ad, args = jitter.func_args_stdcall(["src"]) + str_src = jitter.get_str_ansi(args.src) + jitter.func_ret_stdcall(ret_ad, len(str_src)) + + +def xxx_malloc(jitter): + ret_ad, args = jitter.func_args_stdcall(["msize"]) + addr = linobjs.heap.alloc(jitter, args.msize) + jitter.func_ret_stdcall(ret_ad, addr) + + +def xxx_free(jitter): + ret_ad, args = jitter.func_args_stdcall(["ptr"]) + jitter.func_ret_stdcall(ret_ad, 0) + + +def xxx_strcmp(jitter): + ret_ad, args = jitter.func_args_stdcall(["ptr_str1", "ptr_str2"]) + s1 = get_str_ansi(jitter, args.ptr_str1) + s2 = get_str_ansi(jitter, args.ptr_str2) + jitter.func_ret_stdcall(ret_ad, cmp(s1, s2)) + + +def xxx_strncmp(jitter): + ret_ad, args = jitter.func_args_stdcall(["ptr_str1", "ptr_str2", "size"]) + s1 = get_str_ansi(jitter, args.ptr_str1, args.size) + s2 = get_str_ansi(jitter, args.ptr_str2, args.size) + jitter.func_ret_stdcall(ret_ad, cmp(s1, s2)) diff --git a/setup.py b/setup.py index f4618abc..3b504542 100755 --- a/setup.py +++ b/setup.py @@ -10,6 +10,7 @@ def buil_all(): 'miasm2/arch', 'miasm2/arch/x86', 'miasm2/arch/arm', + 'miasm2/arch/aarch64', 'miasm2/arch/msp430', 'miasm2/arch/sh4', 'miasm2/arch/mips32', @@ -35,6 +36,10 @@ def buil_all(): ["miasm2/jitter/JitCore.c", "miasm2/jitter/vm_mngr.c", "miasm2/jitter/arch/JitCore_arm.c"]), + Extension("miasm2.jitter.arch.JitCore_aarch64", + ["miasm2/jitter/JitCore.c", + "miasm2/jitter/vm_mngr.c", + "miasm2/jitter/arch/JitCore_aarch64.c"]), Extension("miasm2.jitter.arch.JitCore_msp430", ["miasm2/jitter/JitCore.c", "miasm2/jitter/vm_mngr.c", @@ -59,6 +64,10 @@ def buil_all(): ["miasm2/jitter/JitCore.c", "miasm2/jitter/vm_mngr.c", "miasm2/jitter/arch/JitCore_arm.c"]), + Extension("miasm2.jitter.arch.JitCore_aarch64", + ["miasm2/jitter/JitCore.c", + "miasm2/jitter/vm_mngr.c", + "miasm2/jitter/arch/JitCore_aarch64.c"]), Extension("miasm2.jitter.arch.JitCore_msp430", ["miasm2/jitter/JitCore.c", "miasm2/jitter/vm_mngr.c", diff --git a/test/arch/aarch64/unit/asm_test.py b/test/arch/aarch64/unit/asm_test.py new file mode 100644 index 00000000..60ed418e --- /dev/null +++ b/test/arch/aarch64/unit/asm_test.py @@ -0,0 +1,64 @@ +#! /usr/bin/env python +import sys +import os + +from miasm2.core.cpu import parse_ast +from miasm2.arch.aarch64.arch import mn_aarch64, base_expr, variable +from miasm2.core import parse_asm +from miasm2.expression.expression import * +from miasm2.core import asmbloc +from elfesteem.strpatchwork import StrPatchwork +from miasm2.analysis.machine import Machine +from miasm2.jitter.csts import * +from pdb import pm + + +filename = os.environ.get('PYTHONSTARTUP') +if filename and os.path.isfile(filename): + execfile(filename) + + +reg_and_id = dict(mn_aarch64.regs.all_regs_ids_byname) + +class Asm_Test(object): + def __init__(self): + self.myjit = Machine("aarch64l").jitter() + self.myjit.init_stack() + + self.myjit.jit.log_regs = False + self.myjit.jit.log_mn = False + + + def __call__(self): + self.asm() + self.run() + self.check() + + + def asm(self): + blocs, symbol_pool = parse_asm.parse_txt(mn_aarch64, 'l', self.TXT, + symbol_pool = self.myjit.ir_arch.symbol_pool) + # fix shellcode addr + symbol_pool.set_offset(symbol_pool.getby_name("main"), 0x0) + s = StrPatchwork() + patches = asmbloc.asm_resolve_final(mn_aarch64, blocs[0], symbol_pool) + for offset, raw in patches.items(): + s[offset] = raw + + self.assembly = str(s) + + def run(self): + run_addr = 0 + self.myjit.vm.add_memory_page(run_addr, PAGE_READ | PAGE_WRITE, self.assembly) + + self.myjit.cpu.LR = 0x1337beef + + self.myjit.add_breakpoint(0x1337beef, lambda x:False) + + self.myjit.init_run(run_addr) + self.myjit.continue_run() + + assert(self.myjit.pc == 0x1337beef) + + def check(self): + raise NotImplementedError('abstract method') diff --git a/test/arch/aarch64/unit/mn_ubfm.py b/test/arch/aarch64/unit/mn_ubfm.py new file mode 100644 index 00000000..938f13cf --- /dev/null +++ b/test/arch/aarch64/unit/mn_ubfm.py @@ -0,0 +1,30 @@ +#! /usr/bin/env python +from asm_test import Asm_Test +from pdb import pm + + +class Test_UBFM1(Asm_Test): + TXT = ''' +main: + MOVZ X0, 0x5600 + UBFM X0, X0, 8, 15 + RET LR + ''' + def check(self): + assert(self.myjit.cpu.X0 == 0x56) + pass + +class Test_UBFM2(Asm_Test): + TXT = ''' +main: + MOVZ X0, 0x56 + UBFM X0, X0, 4, 55 + RET LR + ''' + def check(self): + assert(self.myjit.cpu.X0 == 0x5) + pass + + +if __name__ == "__main__": + [test()() for test in [Test_UBFM1, Test_UBFM2 ]] diff --git a/test/test_all.py b/test/test_all.py index b5dc0abf..7270af3d 100644 --- a/test/test_all.py +++ b/test/test_all.py @@ -40,6 +40,7 @@ for script in ["x86/sem.py", "x86/unit/mn_das.py", "arm/arch.py", "arm/sem.py", + "aarch64/unit/mn_ubfm.py", "msp430/arch.py", "msp430/sem.py", "sh4/arch.py", @@ -214,6 +215,8 @@ for source in test_box_names: test_armb = ExampleShellcode(["armb", "arm_simple.S", "demo_arm_b.bin"]) test_arml = ExampleShellcode(["arml", "arm_simple.S", "demo_arm_l.bin"]) +test_aarch64b = ExampleShellcode(["aarch64b", "aarch64_simple.S", "demo_aarch64_b.bin"]) +test_aarch64l = ExampleShellcode(["aarch64l", "aarch64_simple.S", "demo_aarch64_l.bin"]) test_armb_sc = ExampleShellcode(["armb", "arm_sc.S", "demo_arm2_b.bin"]) test_arml_sc = ExampleShellcode(["arml", "arm_sc.S", "demo_arm2_l.bin"]) test_armtb = ExampleShellcode(["armtb", "armt.S", "demo_armt_b.bin"]) @@ -226,6 +229,8 @@ test_x86_64 = ExampleShellcode(["x86_64", "x86_64.S", "demo_x86_64.bin", testset += test_armb testset += test_arml +testset += test_aarch64b +testset += test_aarch64l testset += test_armb_sc testset += test_arml_sc testset += test_armtb @@ -277,6 +282,10 @@ testset += ExampleDisasmFull(["armtl", Example.get_sample("demo_armt_l.bin"), "0"], depends=[test_armtl]) testset += ExampleDisasmFull(["armtb", Example.get_sample("demo_armt_b.bin"), "0"], depends=[test_armtb]) +testset += ExampleDisasmFull(["aarch64l", Example.get_sample("demo_aarch64_l.bin"), + "0"], depends=[test_aarch64l]) +testset += ExampleDisasmFull(["aarch64b", Example.get_sample("demo_aarch64_b.bin"), + "0"], depends=[test_aarch64b]) testset += ExampleDisasmFull(["x86_32", Example.get_sample("x86_32_simple.bin"), "0x401000"], depends=[test_box["simple"]]) testset += ExampleDisasmFull(["msp430", Example.get_sample("msp430_sc.bin"), @@ -287,6 +296,8 @@ testset += ExampleDisasmFull(["mips32b", Example.get_sample("mips32_sc_b.bin"), "0"], depends=[test_mips32b]) testset += ExampleDisasmFull(["x86_64", Example.get_sample("demo_x86_64.bin"), "0x401000"], depends=[test_x86_64]) +testset += ExampleDisasmFull(["aarch64l", Example.get_sample("md5_aarch64l"), + "0x400A00"], depends=[test_aarch64l]) ## Expression @@ -363,6 +374,8 @@ for jitter in ExampleJitter.jitter_engines: for script, dep in [(["x86_32.py", Example.get_sample("x86_32_sc.bin")], []), (["arm.py", Example.get_sample("md5_arm"), "-a", "A684"], []), + (["sandbox_elf_aarch64l.py", Example.get_sample("md5_aarch64l"), "-a", "0x400A00"], + []), (["msp430.py", Example.get_sample("msp430_sc.bin"), "0"], [test_msp430]), (["mips32.py", Example.get_sample("mips32_sc_l.bin"), "0"], |