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_callee(ea, mnem, args): '''ea_t -> str -> formatter_args -> str''' # XXX we don't handle function pointers yet, but it should be easy now that # we handle all internal functions as having the same signature...i think if mnem == 'jalr': nn = ida.netnode('$ mips') fun = nn.altval(ea) - 1 if fun == -1: raise FunctionPointerError( 'unknown target for function pointer at %s' % ida.atoa(ea)) return ida.name(fun) elif mnem == 'jal': return args['rs'].name else: raise utils.BugError('unhandled call insn: %s' % mnem)
def get_args_for_va_function(callee, pos_arg): '''str -> str -> [(reg_type, slot_type) | None]''' def get_convs(acc, va_arg): return acc + [sw[va_arg.type]] pos_sw = {'printf' : (1, printf_sw, printf_parse, va_wrap), 'scanf' : (1, scanf_sw, scanf_parse, pos_wrap), 'sscanf' : (2, scanf_sw, scanf_parse, pos_wrap)} try: (pos, sw, fn, chooser) = pos_sw[callee] except KeyError: raise utils.BugError('unrecognized callee %s' % callee) (_, args) = fn(pos_arg) convs = reduce(get_convs, args.arg, []) return list(get_info_for_types( convs, lambda x: x, chooser, pos=pos, handle_va=True))
def get_arg_for_va_function(callee, start_ea): '''str -> ea_t -> str''' # XXX hacky; not a very general function # XXX imperative # get a relevant item needed for processing a variadic function sw = { 'printf' : regs.gpr(abi.arg_regs[0]), 'scanf' : regs.gpr(abi.arg_regs[0]), 'sscanf' : regs.gpr(abi.arg_regs[1]) } try: wanted_reg = sw[callee] except KeyError: raise utils.BugError('unrecognized callee %s' % callee) distance = 0 fn = ida.get_func(start_ea) # first, look at the delay slot ea = ida.next_head(start_ea, fn.endEA) while True: if distance > 10: raise VarargsError( 'gave up looking for needed varargs argument for %s between ' + '%s..%s' % (ida.atoa(ea), ida.atoa(start_ea))) if ea == start_ea: ea = ida.prev_head(ea) continue # skip the call insn elif list(ida.code_refs_from(ea, 0)) != []: raise VarargsError( 'encountered branch/jump while looking for varargs argument ' + 'between %s..%s' % (ida.atoa(ea), ida.atoa(start_ea))) rd = ida.get_op(ea, 0) if rd.val == wanted_reg: opvals = ida.get_opvals(ea) # XXX should try to track stkvar values s = ida.get_string(opvals[-1].target) if s is not None: return s ea = ida.prev_head(ea) distance += 1
def __init__(self, reg): if type(self) is reg_base: raise utils.BugError('reg_base cannot be directly instantiated') self.reg = reg
def initlist(arg): if type(arg) is not list: raise utils.BugError('non-list passed') return c_ast.InitList(arg)
def __init__(self, value): tyty = type(value) if tyty is not float: raise utils.BugError('must be float, not %s' % tyty.__name__) self.value = value