def get_op(ea, op, stkvars=None): '''ea_t -> int -> opt:{int : tinfo_t} -> op_ret''' cmd = idautils.DecodeInstruction(ea) cmd.Operands = get_operands(cmd) # for mips_op_hack op = mips_op_hack(cmd, op) opd = cmd[op] if opd.type == idaapi.o_reg: # gpr, XXX sorta MIPS-specific return op_ret(op_ty.reg, regs.gpr(opd.reg), 0) elif opd.type == idaapi.o_idpspec1: # fpr, XXX sorta MIPS-specific return op_ret(op_ty.reg, regs.fpr(opd.reg), 0) elif opd.type in [idaapi.o_near, idaapi.o_mem]: return op_ret(op_ty.name, idc.Name(opd.addr), 0) elif idc.isStkvar1(idc.GetFlags(ea)): # IDA seems to set this flag even for operands beyond the second, # i.e. both of these are true for isStkvar1: # .text:10003A84 sd $a1, 0x2E0+var_58($sp) # .text:10003A68 addiu $a1, $sp, 0x2E0+var_2D8 try: func = idaapi.get_func(ea) off = idaapi.calc_stkvar_struc_offset(func, ea, op) (name, ti) = stkvars[off] return op_ret_for_ti(ti, name, off, off) except KeyError: raise OperandUnresolvableError('unable to get operand %u at %s' % (op, idc.atoa(ea))) elif opd.type in [idaapi.o_imm, idaapi.o_displ]: return cpu_ida.ida_current_cpu().data.get_op_addrmode(ea, op, cmd) else: raise OperandUnresolvableError('unable to get operand %u at %s' % (op, idc.atoa(ea)))
def c_for_insn(ea, our_fns, extern_reg_map, stkvars): while True: (ea, c) = cpu_ida.ida_current_cpu().gen.fmt_insn( ea, our_fns, extern_reg_map, stkvars, from_delay=False) yield c if ea == ida.BADADDR: break
def get_sig(node, typedefs): resolve_types(node, typedefs) if node.args is not None: return ida.ida_current_cpu().get_abi_fn_arg_map(node) else: raise EmptyArgListError("use (void) if %s takes no arguments" % node.name)
def c_for_insn(ea, our_fns, extern_reg_map, stkvars): while True: (ea, c) = cpu_ida.ida_current_cpu().gen.fmt_insn(ea, our_fns, extern_reg_map, stkvars, from_delay=False) yield c if ea == ida.BADADDR: break
def repl_make_insn(ea, from_delay): # for testing: print the C that will be generated from a line of assembly. # note that if you ask for the ea of an insn in a delay slot, you get only # that instruction; if you ask for a delayed instruction, you get both try: stkvars = STKVAR_MAP[ida.get_func_name(ea)] except KeyError: stkvars = {} return list(gen_from_node(x) for x in cpu_ida.ida_current_cpu().gen.fmt_insn( ea, OUR_FNS, EXTERN_REG_MAP, stkvars, from_delay).c)
def repl_make_insn(ea, from_delay): # for testing: print the C that will be generated from a line of assembly. # note that if you ask for the ea of an insn in a delay slot, you get only # that instruction; if you ask for a delayed instruction, you get both try: stkvars = STKVAR_MAP[ida.get_func_name(ea)] except KeyError: stkvars = {} return list( gen_from_node(x) for x in cpu_ida.ida_current_cpu().gen.fmt_insn( ea, OUR_FNS, EXTERN_REG_MAP, stkvars, from_delay).c)
def mips_op_hack(cmd, op): '''insn_t -> int''' # see note for get_operands if cpu_ida.ida_current_cpu_name() == 'mips': mnem = get_mnem(cmd.ea) if (len(cpu_ida.ida_current_cpu().insns.insns[mnem].opfs) != len(ida_operands(cmd))): if op > 0: return op - 1 else: return op else: return op else: return op
def op_ret_for_ti(ti, name, target, val): '''tinfo_t -> str -> int -> int -> op_ret''' if ti.is_array(): return op_ret(op_ty.array, name, target) elif ti.is_ptr(): return op_ret(op_ty.ptr, name, target) elif ti.is_func(): return op_ret(op_ty.func, name, target) elif name != '': # XXX name types are a misfeature, see mips/gen.py return op_ret(op_ty.name, name, target) else: if cpu_ida.ida_current_cpu_name() == 'mips': return op_ret(op_ty.value, cpu_ida.ida_current_cpu().data.interpret_li_arg(val), 0) else: return op_ret(op_ty.value, val, 0)
def mips_op_hack(cmd, op): '''insn_t -> int''' # see note for get_operands if cpu_ida.ida_current_cpu_name() == 'mips': mnem = get_mnem(cmd.ea) if (len(cpu_ida.ida_current_cpu().insns.insns[mnem].opfs) != len( ida_operands(cmd))): if op > 0: return op - 1 else: return op else: return op else: return op
def get_operands(cmd): '''insn_t -> [op_t]''' opnds = ida_operands(cmd) if cpu_ida.ida_current_cpu_name() == 'mips': # IDA returns "simplified" instructions with only two operands when the # first and second operands are the same register, but this forces you # to handle multiple formats for a single instruction, so here we # transform them into their canonical form mnem = get_mnem(cmd.ea) if len(cpu_ida.ida_current_cpu().insns.insns[mnem].opfs) != len(opnds): return [opnds[0], opnds[0], opnds[1]] else: return opnds else: return opnds
from itertools import imap, chain from pycparser import c_generator, c_ast from decomp import data, ida from decomp.c import decl as cdecl, types as ep_ct from decomp.cpu import ida as cpu_ida XXX_INTRO_HACK = cpu_ida.ida_current_cpu().insns.support_header + ''' #include <stdint.h> typedef union EPANOS_REG { uint8_t u8; int32_t i32; uint32_t u32; int64_t i64; uint64_t u64; float s; double d; } EPANOS_REG; typedef struct EPANOS_ARGS { EPANOS_REG v0; EPANOS_REG v1; EPANOS_REG a0; EPANOS_REG a1; EPANOS_REG a2; EPANOS_REG a3; EPANOS_REG a4; EPANOS_REG a5; EPANOS_REG a6; EPANOS_REG a7; EPANOS_REG f0; EPANOS_REG f2;
def __str__(self): return '%s' % ida.ida_current_cpu().abi.reg_list[ self.reg + ida.ida_current_cpu().abi.fpr_off]