mirror of
https://github.com/idapython/src
synced 2026-06-08 14:47:00 +00:00
420 lines
13 KiB
Python
420 lines
13 KiB
Python
# -----------------------------------------------------------------------
|
|
#<pycode(py_hexrays)>
|
|
import ida_funcs
|
|
|
|
hexrays_failure_t.__str__ = lambda self: str(self.str)
|
|
|
|
# ---------------------------------------------------------------------
|
|
class DecompilationFailure(Exception):
|
|
""" Raised on a decompilation error.
|
|
|
|
The associated hexrays_failure_t object is stored in the
|
|
'info' member of this exception. """
|
|
|
|
def __init__(self, info):
|
|
Exception.__init__(self, 'Decompilation failed: %s' % (str(info), ))
|
|
self.info = info
|
|
return
|
|
|
|
# ---------------------------------------------------------------------
|
|
def decompile(ea, hf=None):
|
|
if isinstance(ea, (int, long)):
|
|
func = ida_funcs.get_func(ea)
|
|
if not func: return
|
|
elif type(ea) == ida_funcs.func_t:
|
|
func = ea
|
|
else:
|
|
raise RuntimeError('arg 1 of decompile expects either ea_t or cfunc_t argument')
|
|
|
|
if hf is None:
|
|
hf = hexrays_failure_t()
|
|
|
|
ptr = _decompile(func, hf)
|
|
|
|
if ptr.__deref__() is None:
|
|
raise DecompilationFailure(hf)
|
|
|
|
return ptr
|
|
|
|
# ---------------------------------------------------------------------
|
|
# stringify all string types
|
|
#qtype.__str__ = qtype.c_str
|
|
#qstring.__str__ = qstring.c_str
|
|
#citem_cmt_t.__str__ = citem_cmt_t.c_str
|
|
|
|
# ---------------------------------------------------------------------
|
|
# listify all list types
|
|
import ida_idaapi
|
|
ida_idaapi._listify_types(
|
|
cinsnptrvec_t,
|
|
ctree_items_t,
|
|
qvector_lvar_t,
|
|
qvector_carg_t,
|
|
qvector_ccase_t,
|
|
hexwarns_t,
|
|
history_t,
|
|
lvar_saved_infos_t)
|
|
|
|
def citem_to_specific_type(self):
|
|
""" cast the citem_t object to its more specific type, either cexpr_t or cinsn_t. """
|
|
|
|
if self.op >= cot_empty and self.op <= cot_last:
|
|
return self.cexpr
|
|
elif self.op >= cit_empty and self.op < cit_end:
|
|
return self.cinsn
|
|
|
|
raise RuntimeError('unknown op type %s' % (repr(self.op), ))
|
|
citem_t.to_specific_type = property(citem_to_specific_type)
|
|
|
|
""" array used for translating cinsn_t->op type to their names. """
|
|
cinsn_t.op_to_typename = {}
|
|
for k in dir(_ida_hexrays):
|
|
if k.startswith('cit_'):
|
|
cinsn_t.op_to_typename[getattr(_ida_hexrays, k)] = k[4:]
|
|
|
|
""" array used for translating cexpr_t->op type to their names. """
|
|
cexpr_t.op_to_typename = {}
|
|
for k in dir(_ida_hexrays):
|
|
if k.startswith('cot_'):
|
|
cexpr_t.op_to_typename[getattr(_ida_hexrays, k)] = k[4:]
|
|
|
|
def property_op_to_typename(self):
|
|
return self.op_to_typename[self.op]
|
|
cinsn_t.opname = property(property_op_to_typename)
|
|
cexpr_t.opname = property(property_op_to_typename)
|
|
|
|
def cexpr_operands(self):
|
|
""" return a dictionary with the operands of a cexpr_t. """
|
|
|
|
if self.op >= cot_comma and self.op <= cot_asgumod or \
|
|
self.op >= cot_lor and self.op <= cot_fdiv or \
|
|
self.op == cot_idx:
|
|
return {'x': self.x, 'y': self.y}
|
|
|
|
elif self.op == cot_tern:
|
|
return {'x': self.x, 'y': self.y, 'z': self.z}
|
|
|
|
elif self.op in [cot_fneg, cot_neg, cot_sizeof] or \
|
|
self.op >= cot_lnot and self.op <= cot_predec:
|
|
return {'x': self.x}
|
|
|
|
elif self.op == cot_cast:
|
|
return {'type': self.type, 'x': self.x}
|
|
|
|
elif self.op == cot_call:
|
|
return {'x': self.x, 'a': self.a}
|
|
|
|
elif self.op in [cot_memref, cot_memptr]:
|
|
return {'x': self.x, 'm': self.m}
|
|
|
|
elif self.op == cot_num:
|
|
return {'n': self.n}
|
|
|
|
elif self.op == cot_fnum:
|
|
return {'fpc': self.fpc}
|
|
|
|
elif self.op == cot_str:
|
|
return {'string': self.string}
|
|
|
|
elif self.op == cot_obj:
|
|
return {'obj_ea': self.obj_ea}
|
|
|
|
elif self.op == cot_var:
|
|
return {'v': self.v}
|
|
|
|
elif self.op == cot_helper:
|
|
return {'helper': self.helper}
|
|
|
|
raise RuntimeError('unknown op type %s' % self.opname)
|
|
cexpr_t.operands = property(cexpr_operands)
|
|
|
|
def cinsn_details(self):
|
|
""" return the details pointer for the cinsn_t object depending on the value of its op member. \
|
|
this is one of the cblock_t, cif_t, etc. objects. """
|
|
|
|
if self.op not in self.op_to_typename:
|
|
raise RuntimeError('unknown item->op type')
|
|
|
|
opname = self.opname
|
|
if opname == 'empty':
|
|
return self
|
|
|
|
if opname in ['break', 'continue']:
|
|
return None
|
|
|
|
return getattr(self, 'c' + opname)
|
|
cinsn_t.details = property(cinsn_details)
|
|
|
|
def cblock_iter(self):
|
|
|
|
iter = self.begin()
|
|
for i in range(self.size()):
|
|
yield iter.cur
|
|
iter.next()
|
|
|
|
return
|
|
cblock_t.__iter__ = cblock_iter
|
|
cblock_t.__len__ = cblock_t.size
|
|
|
|
# cblock.find(cinsn_t) -> returns the iterator positioned at the given item
|
|
def cblock_find(self, item):
|
|
|
|
iter = self.begin()
|
|
for i in range(self.size()):
|
|
if iter.cur == item:
|
|
return iter
|
|
iter.next()
|
|
|
|
return
|
|
cblock_t.find = cblock_find
|
|
|
|
# cblock.index(cinsn_t) -> returns the index of the given item
|
|
def cblock_index(self, item):
|
|
|
|
iter = self.begin()
|
|
for i in range(self.size()):
|
|
if iter.cur == item:
|
|
return i
|
|
iter.next()
|
|
|
|
return
|
|
cblock_t.index = cblock_index
|
|
|
|
# cblock.at(int) -> returns the item at the given index index
|
|
def cblock_at(self, index):
|
|
|
|
iter = self.begin()
|
|
for i in range(self.size()):
|
|
if i == index:
|
|
return iter.cur
|
|
iter.next()
|
|
|
|
return
|
|
cblock_t.at = cblock_at
|
|
|
|
# cblock.remove(cinsn_t)
|
|
def cblock_remove(self, item):
|
|
|
|
iter = self.find(item)
|
|
self.erase(iter)
|
|
|
|
return
|
|
cblock_t.remove = cblock_remove
|
|
|
|
# cblock.insert(index, cinsn_t)
|
|
def cblock_insert(self, index, item):
|
|
|
|
pos = self.at(index)
|
|
iter = self.find(pos)
|
|
self.insert(iter, item)
|
|
|
|
return
|
|
cblock_t.insert = cblock_insert
|
|
|
|
cfuncptr_t.__str__ = lambda self: str(self.__deref__())
|
|
|
|
import ida_typeinf
|
|
def cfunc_type(self):
|
|
""" Get the function's return type tinfo_t object. """
|
|
tif = ida_typeinf.tinfo_t()
|
|
result = self.get_func_type(tif)
|
|
if not result:
|
|
return
|
|
return tif
|
|
cfunc_t.type = property(cfunc_type)
|
|
cfuncptr_t.type = property(lambda self: self.__deref__().type)
|
|
|
|
cfunc_t.arguments = property(lambda self: [o for o in self.lvars if o.is_arg_var])
|
|
cfuncptr_t.arguments = property(lambda self: self.__deref__().arguments)
|
|
|
|
cfunc_t.lvars = property(cfunc_t.get_lvars)
|
|
cfuncptr_t.lvars = property(lambda self: self.__deref__().lvars)
|
|
cfunc_t.warnings = property(cfunc_t.get_warnings)
|
|
cfuncptr_t.warnings = property(lambda self: self.__deref__().warnings)
|
|
cfunc_t.pseudocode = property(cfunc_t.get_pseudocode)
|
|
cfuncptr_t.pseudocode = property(lambda self: self.__deref__().get_pseudocode())
|
|
cfunc_t.eamap = property(cfunc_t.get_eamap)
|
|
cfuncptr_t.eamap = property(lambda self: self.__deref__().get_eamap())
|
|
cfunc_t.boundaries = property(cfunc_t.get_boundaries)
|
|
cfuncptr_t.boundaries = property(lambda self: self.__deref__().get_boundaries())
|
|
|
|
#pragma SWIG nowarn=+503
|
|
|
|
lvar_t.used = property(lvar_t.used)
|
|
lvar_t.typed = property(lvar_t.typed)
|
|
lvar_t.mreg_done = property(lvar_t.mreg_done)
|
|
lvar_t.has_nice_name = property(lvar_t.has_nice_name)
|
|
lvar_t.is_unknown_width = property(lvar_t.is_unknown_width)
|
|
lvar_t.has_user_info = property(lvar_t.has_user_info)
|
|
lvar_t.has_user_name = property(lvar_t.has_user_name)
|
|
lvar_t.has_user_type = property(lvar_t.has_user_type)
|
|
lvar_t.is_result_var = property(lvar_t.is_result_var)
|
|
lvar_t.is_arg_var = property(lvar_t.is_arg_var)
|
|
lvar_t.is_fake_var = property(lvar_t.is_fake_var)
|
|
lvar_t.is_overlapped_var = property(lvar_t.is_overlapped_var)
|
|
lvar_t.is_floating_var = property(lvar_t.is_floating_var)
|
|
lvar_t.is_spoiled_var = property(lvar_t.is_spoiled_var)
|
|
lvar_t.is_mapdst_var = property(lvar_t.is_mapdst_var)
|
|
|
|
# dictify all dict-like types
|
|
|
|
def _map___getitem__(self, key):
|
|
""" Returns the value associated with the provided key. """
|
|
if not isinstance(key, self.keytype):
|
|
raise KeyError('type of key should be ' + repr(self.keytype) + ' but got ' + repr(type(key)))
|
|
if key not in self:
|
|
raise KeyError('key not found')
|
|
return self.second(self.find(key))
|
|
|
|
def _map___setitem__(self, key, value):
|
|
""" Returns the value associated with the provided key. """
|
|
if not isinstance(key, self.keytype):
|
|
raise KeyError('type of `key` should be ' + repr(self.keytype) + ' but got ' + repr(type(key)))
|
|
if not isinstance(value, self.valuetype):
|
|
raise KeyError('type of `value` should be ' + repr(self.valuetype) + ' but got ' + type(value))
|
|
self.insert(key, value)
|
|
return
|
|
|
|
def _map___delitem__(self, key):
|
|
""" Removes the value associated with the provided key. """
|
|
if not isinstance(key, self.keytype):
|
|
raise KeyError('type of `key` should be ' + repr(self.keytype) + ' but got ' + repr(type(key)))
|
|
if key not in self:
|
|
raise KeyError('key not found')
|
|
self.erase(self.find(key))
|
|
return
|
|
|
|
def _map___contains__(self, key):
|
|
""" Returns true if the specified key exists in the . """
|
|
if not isinstance(key, self.keytype):
|
|
raise KeyError('type of `key` should be ' + repr(self.keytype) + ' but got ' + repr(type(key)))
|
|
if self.find(key) != self.end():
|
|
return True
|
|
return False
|
|
|
|
def _map_clear(self):
|
|
self.clear()
|
|
return
|
|
|
|
def _map_copy(self):
|
|
ret = {}
|
|
for k in self.iterkeys():
|
|
ret[k] = self[k]
|
|
return ret
|
|
|
|
def _map_get(self, key, default=None):
|
|
if key in self:
|
|
return self[key]
|
|
return default
|
|
|
|
def _map_iterkeys(self):
|
|
iter = self.begin()
|
|
while iter != self.end():
|
|
yield self.first(iter)
|
|
iter = self.next(iter)
|
|
return
|
|
|
|
def _map_itervalues(self):
|
|
iter = self.begin()
|
|
while iter != self.end():
|
|
yield self.second(iter)
|
|
iter = self.next(iter)
|
|
return
|
|
|
|
def _map_iteritems(self):
|
|
iter = self.begin()
|
|
while iter != self.end():
|
|
yield (self.first(iter), self.second(iter))
|
|
iter = self.next(iter)
|
|
return
|
|
|
|
def _map_keys(self):
|
|
return list(self.iterkeys())
|
|
|
|
def _map_values(self):
|
|
return list(self.itervalues())
|
|
|
|
def _map_items(self):
|
|
return list(self.iteritems())
|
|
|
|
def _map_has_key(self, key):
|
|
return key in self
|
|
|
|
def _map_pop(self, key):
|
|
""" Sets the value associated with the provided key. """
|
|
if not isinstance(key, self.keytype):
|
|
raise KeyError('type of `key` should be ' + repr(self.keytype) + ' but got ' + repr(type(key)))
|
|
if key not in self:
|
|
raise KeyError('key not found')
|
|
ret = self[key]
|
|
del self[key]
|
|
return ret
|
|
|
|
def _map_popitem(self):
|
|
""" Sets the value associated with the provided key. """
|
|
if len(self) == 0:
|
|
raise KeyError('key not found')
|
|
key = self.keys()[0]
|
|
return (key, self.pop(key))
|
|
|
|
def _map_setdefault(self, key, default=None):
|
|
""" Sets the value associated with the provided key. """
|
|
if not isinstance(key, self.keytype):
|
|
raise KeyError('type of `key` should be ' + repr(self.keytype) + ' but got ' + repr(type(key)))
|
|
if key in self:
|
|
return self[key]
|
|
self[key] = default
|
|
return default
|
|
|
|
def _map_as_dict(maptype, name, keytype, valuetype):
|
|
|
|
maptype.keytype = keytype
|
|
maptype.valuetype = valuetype
|
|
|
|
for fctname in ['begin', 'end', 'first', 'second', 'next', \
|
|
'find', 'insert', 'erase', 'clear', 'size']:
|
|
fct = getattr(_ida_hexrays, name + '_' + fctname)
|
|
setattr(maptype, '__' + fctname, fct)
|
|
|
|
maptype.__len__ = maptype.size
|
|
maptype.__getitem__ = maptype.at
|
|
|
|
maptype.begin = lambda self, *args: self.__begin(self, *args)
|
|
maptype.end = lambda self, *args: self.__end(self, *args)
|
|
maptype.first = lambda self, *args: self.__first(*args)
|
|
maptype.second = lambda self, *args: self.__second(*args)
|
|
maptype.next = lambda self, *args: self.__next(*args)
|
|
maptype.find = lambda self, *args: self.__find(self, *args)
|
|
maptype.insert = lambda self, *args: self.__insert(self, *args)
|
|
maptype.erase = lambda self, *args: self.__erase(self, *args)
|
|
maptype.clear = lambda self, *args: self.__clear(self, *args)
|
|
maptype.size = lambda self, *args: self.__size(self, *args)
|
|
maptype.__getitem__ = _map___getitem__
|
|
maptype.__setitem__ = _map___setitem__
|
|
maptype.__delitem__ = _map___delitem__
|
|
maptype.__contains__ = _map___contains__
|
|
maptype.clear = _map_clear
|
|
maptype.copy = _map_copy
|
|
maptype.get = _map_get
|
|
maptype.iterkeys = _map_iterkeys
|
|
maptype.itervalues = _map_itervalues
|
|
maptype.iteritems = _map_iteritems
|
|
maptype.keys = _map_keys
|
|
maptype.values = _map_values
|
|
maptype.items = _map_items
|
|
maptype.has_key = _map_has_key
|
|
maptype.pop = _map_pop
|
|
maptype.popitem = _map_popitem
|
|
maptype.setdefault = _map_setdefault
|
|
|
|
#_map_as_dict(user_labels_t, 'user_labels', (int, long), qstring)
|
|
_map_as_dict(user_cmts_t, 'user_cmts', treeloc_t, citem_cmt_t)
|
|
_map_as_dict(user_numforms_t, 'user_numforms', operand_locator_t, number_format_t)
|
|
_map_as_dict(user_iflags_t, 'user_iflags', citem_locator_t, (int, long))
|
|
import ida_pro
|
|
_map_as_dict(user_unions_t, 'user_unions', (int, long), ida_pro.intvec_t)
|
|
_map_as_dict(eamap_t, 'eamap', long, cinsnptrvec_t)
|
|
#_map_as_dict(boundaries_t, 'boundaries', cinsn_t, areaset_t)
|
|
|
|
#</pycode(py_hexrays)>
|