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 get_op_addrmode(ea, op, cmd): '''ea_t -> int -> insn_t -> op_ret''' # the ida module calls back into this module to deal with some MIPS-specific # operand handling here mnem = ida.get_mnem(ea) op = ida.mips_op_hack(cmd, op) if cmd[op].type == ida.o_imm: val = cmd[op].value elif cmd[op].type == ida.o_displ: val = cmd[op].addr else: raise utils.BugError('neither imm nor displ passed to get_op_addrmode') if mnem in insns.has_special_opnd: target = val return ida.resolve_opnd(target, val) # addiu is often used for address calculation, which IDA will resolve to a # name, so handle addiu's immval only if we fail to resolve it later elif mnem != 'addiu' and mnem in insns.has_imm: return ida.op_ret(ida.op_ty.value, immval(val), 0) else: target = ida.calc_target(ea, ea, op, immval(val)) if target == ida.BADADDR and cmd[op].type == ida.o_displ: reg = cmd[op].reg if reg >= 0 and reg <= 31: reg = regs.gpr(reg) elif reg >= 32 and reg <= 63: reg = regs.fpr(reg) else: raise utils.BugError('bogus register %u' % reg) return ida.op_ret(ida.op_ty.displ, ida.displ(reg=reg, displ=immval(val)), 0) else: opnd = ida.resolve_opnd(target, val) if mnem == 'addiu' and opnd.ty == ida.op_ty.value: # addiu is being used for regular addition; handle its third # operand as an immediate value return ida.op_ret(ida.op_ty.value, immval(opnd.val), 0) else: return opnd
def get_op_addrmode(ea, op, cmd): """ea_t -> int -> insn_t -> op_ret""" # the ida module calls back into this module to deal with some MIPS-specific # operand handling here mnem = ida.get_mnem(ea) op = ida.mips_op_hack(cmd, op) if cmd[op].type == ida.o_imm: val = cmd[op].value elif cmd[op].type == ida.o_displ: val = cmd[op].addr else: raise utils.BugError("neither imm nor displ passed to get_op_addrmode") if mnem in insns.has_special_opnd: target = val return ida.resolve_opnd(target, val) # addiu is often used for address calculation, which IDA will resolve to a # name, so handle addiu's immval only if we fail to resolve it later elif mnem != "addiu" and mnem in insns.has_imm: return ida.op_ret(ida.op_ty.value, immval(val), 0) else: target = ida.calc_target(ea, ea, op, immval(val)) if target == ida.BADADDR and cmd[op].type == ida.o_displ: reg = cmd[op].reg if reg >= 0 and reg <= 31: reg = regs.gpr(reg) elif reg >= 32 and reg <= 63: reg = regs.fpr(reg) else: raise utils.BugError("bogus register %u" % reg) return ida.op_ret(ida.op_ty.displ, ida.displ(reg=reg, displ=immval(val)), 0) else: opnd = ida.resolve_opnd(target, val) if mnem == "addiu" and opnd.ty == ida.op_ty.value: # addiu is being used for regular addition; handle its third # operand as an immediate value return ida.op_ret(ida.op_ty.value, immval(opnd.val), 0) else: return opnd