def make_stdio_sw(fmt_type, types, pointerize): '''enum -> [str] -> bool -> dict''' # the printf/scanf parsers can parse nearly all format string types, but we # do not handle all of them here fmt_to_type = izip([fmt_type[x] for x in types], c_type_to_slot) return {ty: (ep_ct.ptr(val) if pointerize is True else val) for (ty, (_, val)) in fmt_to_type}
def make_stdio_sw(fmt_type, types, pointerize): '''enum -> [str] -> bool -> dict''' # the printf/scanf parsers can parse nearly all format string types, but we # do not handle all of them here fmt_to_type = izip([fmt_type[x] for x in types], c_type_to_slot) return {ty : (ep_ct.ptr(val) if pointerize is True else val) for (ty, (_, val)) in fmt_to_type}
printf_types = [ 'TYPE_SCHAR', 'TYPE_UCHAR', 'TYPE_SHORT', 'TYPE_USHORT', 'TYPE_INT', 'TYPE_UINT', 'TYPE_LONGINT', 'TYPE_ULONGINT', 'TYPE_LONGLONGINT', 'TYPE_ULONGLONGINT', 'TYPE_DOUBLE', 'TYPE_DOUBLE', 'TYPE_CHAR' ] scanf_types = [ 'TYPE_SCHAR', 'TYPE_UCHAR', 'TYPE_SHORT', 'TYPE_USHORT', 'TYPE_INT', 'TYPE_UINT', 'TYPE_LONGINT', 'TYPE_ULONGINT', 'TYPE_LONGLONGINT', 'TYPE_ULONGLONGINT', 'TYPE_FLOAT', 'TYPE_DOUBLE', 'TYPE_CHAR' ] printf_sw = make_stdio_sw(p_Arg_type, printf_types, pointerize=False) printf_sw[p_Arg_type.TYPE_POINTER] = ep_ct.ptr(ep_ct.simple_typename(['void'])) printf_sw[p_Arg_type.TYPE_STRING] = ep_ct.ptr(ep_ct.simple_typename(['char'])) scanf_sw = make_stdio_sw(s_Arg_type, scanf_types, pointerize=True) scanf_sw[s_Arg_type.TYPE_POINTER] = ep_ct.ptr(ep_ct.ptr(ep_ct.simple_typename(['void']))) scanf_sw[s_Arg_type.TYPE_STRING] = ep_ct.ptr(ep_ct.simple_typename(['char'])) scanf_sw[s_Arg_type.TYPE_CHARSEQ] = scanf_sw[s_Arg_type.TYPE_STRING] def n32ify_regs(regs): '''[str] -> [str]''' n32_map = {'$t0': '$a4', '$t1': '$a5', '$t2': '$a6', '$t3': '$a7'} r = enumerate(regs) return list(n32_map[reg] if reg in n32_map else regs[i] for (i, reg) in r)
def fmt_op(arg, mnem, op=None): '''op_ty -> str -> opt:int -> c_ast()''' insn = insns.insns[mnem] def addrof_or_deref(arg): # since addiu cannot touch memory, it must be calculating an address if mnem == 'addiu' or (insn.ty == insns.types.usefn and insn.subst == 'memcpy'): return c_ast.UnaryOp('&', arg) else: return arg if arg.ty == ida.op_ty.reg: try: slot = insn.slots[op] except IndexError: slot = None reg = fmt_reg(mnem, arg.val, slot) if insn.ty == insns.types.usefn and insn.subst == 'memcpy': return c_ast.UnaryOp('&', reg) else: return reg if mnem == 'la': # XXX the "name" type is neither suitable for a decompiler nor a # braindead static translator such as this one. i.e., in order to # translate to C, we have no choice but to deal with C's type system, # because things like "la ptr" should be translated as "reg = ptr", but # "la not_ptr" should be translated as "reg = ¬_ptr" if arg.ty in [ida.op_ty.array, ida.op_ty.ptr]: return c_ast.ID(arg.val) elif arg.ty == ida.op_ty.name: return c_ast.UnaryOp('&', c_ast.ID(arg.val)) else: # an address return c_ast.Constant('int', str(arg.val)) elif arg.ty == ida.op_ty.array: (idx, rem) = ida.item_off(arg.target) arr = c_ast.ArrayRef(c_ast.ID(arg.val), c_ast.Constant('int', str(idx))) return addrof_or_deref(arr) # retained in case we ever come across some strange pointer math. this # will generate a nonsense lvalue anyway, so we'd need to handle it some # other way # left = addrof_or_deref(arr) #return c_ast.BinaryOp('+', left, c_ast.Constant('int', str(rem))) elif arg.ty == ida.op_ty.ptr: # dereferencing of pointers is handled by the "displ" case, so just # return an address here too (_, rem) = ida.item_off(arg.target) return c_ast.ID(arg.val) # same as above # return c_ast.BinaryOp('+', # c_ast.ID(arg.val), # c_ast.Constant('int', str(rem))) elif arg.ty == ida.op_ty.name: nameval = c_ast.ID(arg.val) return addrof_or_deref(nameval) elif arg.ty == ida.op_ty.displ: r = fmt_reg(mnem, arg.val.reg, ep_ct.slot_types.u32) off = c_ast.BinaryOp('+', r, c_ast.Constant('int', str(arg.val.displ))) tyns = ['char' if insns.types.usefn and insn.subst == 'memcpy' else insn.subst] cast = ep_ct.simple_cast(ep_ct.ptr(ep_ct.simple_typename(tyns)), off) if insn.ty == insns.types.usefn and insn.subst == 'memcpy': return cast else: return c_ast.UnaryOp('*', cast) else: return c_ast.Constant('int', str(arg.val))
printf_types = [ 'TYPE_SCHAR', 'TYPE_UCHAR', 'TYPE_SHORT', 'TYPE_USHORT', 'TYPE_INT', 'TYPE_UINT', 'TYPE_LONGINT', 'TYPE_ULONGINT', 'TYPE_LONGLONGINT', 'TYPE_ULONGLONGINT', 'TYPE_DOUBLE', 'TYPE_DOUBLE', 'TYPE_CHAR' ] scanf_types = [ 'TYPE_SCHAR', 'TYPE_UCHAR', 'TYPE_SHORT', 'TYPE_USHORT', 'TYPE_INT', 'TYPE_UINT', 'TYPE_LONGINT', 'TYPE_ULONGINT', 'TYPE_LONGLONGINT', 'TYPE_ULONGLONGINT', 'TYPE_FLOAT', 'TYPE_DOUBLE', 'TYPE_CHAR' ] printf_sw = make_stdio_sw(p_Arg_type, printf_types, pointerize=False) printf_sw[p_Arg_type.TYPE_POINTER] = ep_ct.ptr( ep_ct.simple_typename(['void'])) printf_sw[p_Arg_type.TYPE_STRING] = ep_ct.ptr( ep_ct.simple_typename(['char'])) scanf_sw = make_stdio_sw(s_Arg_type, scanf_types, pointerize=True) scanf_sw[s_Arg_type.TYPE_POINTER] = ep_ct.ptr(ep_ct.ptr( ep_ct.simple_typename(['void']))) scanf_sw[s_Arg_type.TYPE_STRING] = ep_ct.ptr( ep_ct.simple_typename(['char'])) scanf_sw[s_Arg_type.TYPE_CHARSEQ] = scanf_sw[s_Arg_type.TYPE_STRING] def n32ify_regs(regs): '''[str] -> [str]''' n32_map = {'$t0' : '$a4', '$t1' : '$a5', '$t2' : '$a6', '$t3' : '$a7'} r = enumerate(regs)