The CTREE is built from the optimized microcode (maturity at CMAT_FINAL
), it represents an AST-like tree with C statements and expressions. It can be printed as C code.
ea = idaapi.here()
cfunc = idaapi.decompile(ea)
w = idaapi.get_current_widget()
# if widget type is pseudocode
if idaapi.get_widget_type(w) == idaapi.BWN_PSEUDOCODE:
vu = idaapi.get_widget_vdui(w)
cfunc = vu.cfunc
vu.refresh_ctext()
lvars = cfunc.get_lvars()
tinfo = idaapi.tinfo_t()
cfunc.get_func_type(tinfo)
funcdata = idaapi.func_type_data_t()
tinfo.get_func_details(funcdata)
cc = funcdata.cc # can be one of CM_CC_* -> examples: CM_CC_CDECL, CM_CC_STDCALL, CM_CC_FASTCALL
for i in cfunc.argidx:
tinfo = lvars[i].type()
tinfo = lvars[0].type()
if tinfo.is_funcptr():
number_of_args = tinfo.get_nargs()
rettype = tinfo.get_rettype()
for i in number_of_args:
tinfo_arg = tinfo.get_nth_arg(i)
import idaapi
class my_super_visitor(idaapi.ctree_visitor_t):
def __init__(self):
idaapi.ctree_visitor_t.__init__(self, idaapi.CV_FAST) # CV_FAST does not keep parents nodes in CTREE
def visit_insn(self, i):
return 0
def visit_expr(self, e):
if e.op != idaapi.cot_asg:
return 0
return 0
cfunc = idaapi.decompile(idc.here())
v = my_super_visitor()
v.apply_to(cfunc.body, None)
enum ctype_t
{
cot_empty = 0,
cot_comma = 1, ///< x, y
cot_asg = 2, ///< x = y
cot_asgbor = 3, ///< x |= y
cot_asgxor = 4, ///< x ^= y
cot_asgband = 5, ///< x &= y
cot_asgadd = 6, ///< x += y
cot_asgsub = 7, ///< x -= y
cot_asgmul = 8, ///< x *= y
cot_asgsshr = 9, ///< x >>= y signed
cot_asgushr = 10, ///< x >>= y unsigned
cot_asgshl = 11, ///< x <<= y
cot_asgsdiv = 12, ///< x /= y signed
cot_asgudiv = 13, ///< x /= y unsigned
cot_asgsmod = 14, ///< x %= y signed
cot_asgumod = 15, ///< x %= y unsigned
cot_tern = 16, ///< x ? y : z
cot_lor = 17, ///< x || y
cot_land = 18, ///< x && y
cot_bor = 19, ///< x | y
cot_xor = 20, ///< x ^ y
cot_band = 21, ///< x & y
cot_eq = 22, ///< x == y int or fpu (see EXFL_FPOP)
cot_ne = 23, ///< x != y int or fpu (see EXFL_FPOP)
cot_sge = 24, ///< x >= y signed or fpu (see EXFL_FPOP)
cot_uge = 25, ///< x >= y unsigned
cot_sle = 26, ///< x <= y signed or fpu (see EXFL_FPOP)
cot_ule = 27, ///< x <= y unsigned
cot_sgt = 28, ///< x > y signed or fpu (see EXFL_FPOP)
cot_ugt = 29, ///< x > y unsigned
cot_slt = 30, ///< x < y signed or fpu (see EXFL_FPOP)
cot_ult = 31, ///< x < y unsigned
cot_sshr = 32, ///< x >> y signed
cot_ushr = 33, ///< x >> y unsigned
cot_shl = 34, ///< x << y
cot_add = 35, ///< x + y
cot_sub = 36, ///< x - y
cot_mul = 37, ///< x * y
cot_sdiv = 38, ///< x / y signed
cot_udiv = 39, ///< x / y unsigned
cot_smod = 40, ///< x % y signed
cot_umod = 41, ///< x % y unsigned
cot_fadd = 42, ///< x + y fp
cot_fsub = 43, ///< x - y fp
cot_fmul = 44, ///< x * y fp
cot_fdiv = 45, ///< x / y fp
cot_fneg = 46, ///< -x fp
cot_neg = 47, ///< -x
cot_cast = 48, ///< (type)x
cot_lnot = 49, ///< !x
cot_bnot = 50, ///< ~x
cot_ptr = 51, ///< *x, access size in 'ptrsize'
cot_ref = 52, ///< &x
cot_postinc = 53, ///< x++
cot_postdec = 54, ///< x--
cot_preinc = 55, ///< ++x
cot_predec = 56, ///< --x
cot_call = 57, ///< x(...)
cot_idx = 58, ///< x[y]
cot_memref = 59, ///< x.m
cot_memptr = 60, ///< x->m, access size in 'ptrsize'
cot_num = 61, ///< n
cot_fnum = 62, ///< fpc
cot_str = 63, ///< string constant
cot_obj = 64, ///< obj_ea
cot_var = 65, ///< v
cot_insn = 66, ///< instruction in expression, internal representation only
cot_sizeof = 67, ///< sizeof(x)
cot_helper = 68, ///< arbitrary name
cot_type = 69, ///< arbitrary type
cot_last = cot_type,
cit_empty = 70, ///< instruction types start here
cit_block = 71, ///< block-statement: { ... }
cit_expr = 72, ///< expression-statement: expr;
cit_if = 73, ///< if-statement
cit_for = 74, ///< for-statement
cit_while = 75, ///< while-statement
cit_do = 76, ///< do-statement
cit_switch = 77, ///< switch-statement
cit_break = 78, ///< break-statement
cit_continue = 79, ///< continue-statement
cit_return = 80, ///< return-statement
cit_goto = 81, ///< goto-statement
cit_asm = 82, ///< asm-statement
cit_end
};
Make sure you use
lvar_locator_t
if you plan on keeping anlvar_t
around sincelvar_t
can go out of scope in-between ctree/mba refreshes.