def activate(self, ctx): # get the current item vu = ida_hexrays.get_widget_vdui(ctx.widget) vu.get_current_item(ida_hexrays.USE_KEYBOARD) # REGION1, will be referenced later # check that the current item is a union field if not vu.item.is_citem(): ida_kernwin.warning("Please position the cursor on a union member") return 0 e = vu.item.e while True: op = e.op if op != ida_hexrays.cot_memptr and op != ida_hexrays.cot_memref: ida_kernwin.warning( "Please position the cursor on a union member") return 0 e = e.x if op == ida_hexrays.cot_memptr: if e.type.is_union(): break else: if ida_typeinf.remove_pointer(e.type).is_union(): break if not e.type.is_udt(): ida_kernwin.warning( "Please position the cursor on a union member") return 0 # END REGION1 # REGION2 # calculate the member offset off = 0 e = vu.item.e while True: e2 = e.x tif = ida_typeinf.remove_pointer(e2.type) if not tif.is_union(): off += e.m e = e2 if e2.op != ida_hexrays.cot_memptr and e2.op != ida_hexrays.cot_memref: break if not e2.type.is_udt(): break # END REGION2 # REGION3 # go up and collect more member references (in order to calculate the final offset) p = vu.item.e while True: p2 = vu.cfunc.body.find_parent_of(p) if p2.op == ida_hexrays.cot_memptr: break if p2.op == ida_hexrays.cot_memref: e2 = p2.cexpr tif = ida_typeinf.remove_pointer(e2.x.type) if not tif.is_union(): off += e2.m p = p2 continue if p2.op == ida_hexrays.cot_ref: # handle &a.b + N (this expression may appear if the user previously selected # a wrong field) delta = 0 add = vu.cfunc.body.find_parent_of(p2) if add.op == ida_hexrays.cot_cast: add = vu.cfunc.body.find_parent_of(add) if add.op == ida_hexrays.cot_add and add.y.op == ida_hexrays.cot_num: delta = add.y.numval() objsize = add.type.get_ptrarr_objsize() nbytes = delta * objsize off += nbytes # we could use helpers like WORD/BYTE/... to calculate a more precise offset # if ( p2->op == cot_call && (e2->exflags & EXFL_LVALUE) != 0 ) break # END REGION3 # REGION4 ea = vu.item.e.ea # the item itself may be unaddressable. # TODO: find its addressable parent if ea == ida_idaapi.BADADDR: ida_kernwin.warning("Sorry, the current item is not addressable") return 0 # END REGION4 # REGION5 # prepare the text representation for the item, # use the neighborhoods of cursor line = ida_lines.tag_remove( ida_kernwin.get_custom_viewer_curline(vu.ct, False)) line_len = len(line) x = max(0, vu.cpos.x - 10) l = min(10, line_len - vu.cpos.x) + 10 line = line[x:x + l] # END REGION5 # REGION6 ops = ida_hexrays.ui_stroff_ops_t() op = ops.push_back() op.offset = off op.text = line # END REGION6 # REGION7 class set_union_sel_t(ida_hexrays.ui_stroff_applicator_t): def __init__(self, ea): ida_hexrays.ui_stroff_applicator_t.__init__(self) self.ea = ea def apply(self, opnum, path, top_tif, spath): typename = ida_typeinf.print_tinfo('', 0, 0, ida_typeinf.PRTYPE_1LINE, top_tif, '', '') ida_kernwin.msg("User selected %s of type %s\n" % (spath, typename)) if path.empty(): return False vu.cfunc.set_user_union_selection(self.ea, path) vu.cfunc.save_user_unions() return True # END REGION7 # REGION8 su = set_union_sel_t(ea) res = ida_hexrays.select_udt_by_offset(None, ops, su) if res != 0: # regenerate ctree vu.refresh_view(True) # END REGION8 return 1
def activate(self, ctx): # get current item vu = ida_hexrays.get_widget_vdui(ctx.widget) vu.get_current_item(idaapi.USE_KEYBOARD) # check the current item is union field if not vu.item.is_citem(): return 0 e = vu.item.e while True: op = e.op if op != ida_hexrays.cot_memptr and op != ida_hexrays.cot_memref: return 0 e = e.x if op == ida_hexrays.cot_memptr: if e.type.is_union(): break else: if ida_typeinf.remove_pointer(e.type).is_union(): break if not e.type.is_udt(): return 0 # calculate member's offset off = 0 e = vu.item.e while True: e2 = e.x tif = ida_typeinf.remove_pointer(e2.type) if not tif.is_union(): off += e.m e = e2 if e2.op != ida_hexrays.cot_memptr and e2.op != ida_hexrays.cot_memref: break if not e2.type.is_udt(): break # go up and collect more member references (in order to calculate the final offset) p = vu.item.e while True: p2 = vu.cfunc.body.find_parent_of(p) if p2.op == ida_hexrays.cot_memptr: break if p2.op == ida_hexrays.cot_memref: e2 = p2 tif = remove_pointer(e2.x.type) if not tif.is_union(): off += e2.m p = p2 continue if p2.op == ida_hexrays.cot_ref: # handle &a.b + N (this expression may appear if the user previously selected # a wrong field) delta = 0 add = vu.cfunc.body.find_parent_of(p2) if add.op == ida_hexrays.cot_cast: add = vu.cfunc.body.find_parent_of(add) if add.op == ida_hexrays.cot_add and add.y.op == ida_hexrays.cot_num: delta = add.y.numval() objsize = add.type.get_ptrarr_objsize() nbytes = delta * objsize off += nbytes # we can use the calling helpers like WORD/BYTE/... # to calculate the more precise offset # if ( p2->op == cot_call && (e2->exflags & EXFL_LVALUE) != 0 ) break ea = vu.item.e.ea # the item itself may be unaddressable. # TODO: find its addressable parent if ea == idaapi.BADADDR: return 0 # prepare the text representation for the item, # use the neighborhoods of cursor line = idaapi.tag_remove( ida_kernwin.get_custom_viewer_curline(vu.ct, False)) line_len = len(line) x = max(0, vu.cpos.x - 10) l = min(10, line_len - vu.cpos.x) + 10 line = line[x:x + l] ops = ida_hexrays.ui_stroff_ops_t() op = ops.push_back() op.offset = off op.text = line class set_union_sel_t(ida_hexrays.ui_stroff_applicator_t): def __init__(self, eas): ida_hexrays.ui_stroff_applicator_t.__init__(self) self.eas = eas def apply(self, opnum, path): vu.cfunc.set_user_union_selection(self.eas[opnum], path) vu.cfunc.save_user_unions() return True su = set_union_sel_t([ea]) res = ida_hexrays.select_udt_by_offset(None, ops, su) if res != 0: # regenerate ctree vu.refresh_view(True) return 1