BOOL get_vtbl_info(ea_t ea_address, VTBL_info_t &vtbl_info) { flags_t flags = getFlags(ea_address); if (!(hasRef(flags) || has_any_name(flags) && (isDwrd(flags) || isUnknown(flags)))) return(FALSE); else { BOOL is_move_xref = FALSE; ea_t ea_code_ref = get_first_dref_to(ea_address); if (ea_code_ref && (ea_code_ref != BADADDR)) { do { if (isCode(getFlags(ea_code_ref))) { LPCTSTR disasm_line = get_text_disasm(ea_code_ref); #ifndef __EA64__ if ((*((PUINT)disasm_line) == 0x20766F6D /*"mov "*/) && (strstr(disasm_line + 4, " offset ") != NULL)) #else if ((*((PUINT)disasm_line) == 0x2061656c /*"lea "*/) && (strstr(disasm_line + 4, "rcx") != NULL) && (strstr(disasm_line + 4, "const") != NULL)) #endif { is_move_xref = TRUE; break; } } ea_code_ref = get_next_dref_to(ea_address, ea_code_ref); } while (ea_code_ref && (ea_code_ref != BADADDR)); } if (!is_move_xref) return(FALSE); ZeroMemory(&vtbl_info, sizeof(VTBL_info_t)); // get_name(BADADDR, ea_address, vtbl_info.vtbl_name, (MAXSTR - 1)); f_get_ea_name(&vtbl_info.vtbl_name, ea_address); ea_t ea_start = vtbl_info.ea_begin = ea_address; while (TRUE) { flags_t index_flags = getFlags(ea_address); #ifndef __EA64__ if (!(hasValue(index_flags) && (isDwrd(index_flags) || isUnknown(index_flags)))) #else if (!(hasValue(index_flags) && (isQwrd(index_flags) || isUnknown(index_flags)))) #endif break; #ifndef __EA64__ ea_t ea_index_value = get_32bit(ea_address); #else ea_t ea_index_value = get_64bit(ea_address); #endif if (!(ea_index_value && (ea_index_value != BADADDR))) break; if (ea_address != ea_start) if (hasRef(index_flags)) break; flags_t value_flags = getFlags(ea_index_value); if (!isCode(value_flags)) break; else if (isUnknown(index_flags)) #ifndef __EA64__ doDwrd(ea_address, sizeof(DWORD)); ea_address += sizeof(UINT); #else doQwrd(ea_address, sizeof(UINT64)); ea_address += sizeof(UINT64); #endif }; #ifndef __EA64__ if ((vtbl_info.methods = ((ea_address - ea_start) / sizeof(UINT))) > 0) #else if((vtbl_info.methods = ((ea_address - ea_start) / sizeof(UINT64))) > 0) #endif { vtbl_info.ea_end = ea_address; return(TRUE); } else return(FALSE); } }
//-------------------------------------------------------------------------- static int idaapi gr_callback(void *ud, int code, va_list va) { bool result = false; switch (code) { // refresh user-defined graph nodes and edges case grcode_user_refresh: // in: mutable_graph_t *g // out: success { DECLARE_GI_VARS; func_t *f = get_func(gi->func_ea); if (f == NULL) break; graph_builder_t gb(*fg); // Graph builder helper class gb.apply_to(&gi->vu->cfunc->body, NULL); mutable_graph_t *mg = va_arg(va, mutable_graph_t *); // we have to resize mg->resize(fg->count()); callgraph_t::edge_iterator end = fg->end_edges(); for (callgraph_t::edge_iterator it = fg->begin_edges(); it != end; ++it) { mg->add_edge(it->id1, it->id2, NULL); } fg->clear_edges(); result = true; } break; // retrieve text for user-defined graph node case grcode_user_text: //mutable_graph_t *g // int node // const char **result // bgcolor_t *bg_color (maybe NULL) // out: must return 0, result must be filled // NB: do not use anything calling GDI! { DECLARE_GI_VARS; va_arg(va, mutable_graph_t *); int node = va_arg(va, int); const char **text = va_arg(va, const char **); bgcolor_t *bgcolor = va_arg(va, bgcolor_t *); callgraph_t::nodeinfo_t *ni = fg->get_info(node); result = ni != NULL; if (result) { *text = ni->name.c_str(); if (bgcolor != NULL) *bgcolor = ni->color; } } break; case grcode_user_hint: { DECLARE_GI_VARS; va_arg(va, mutable_graph_t *); int mousenode = va_argi(va, int); int to = va_argi(va, int); int from = va_argi(va, int); char **hint = va_arg(va, char **); callgraph_t::nodeinfo_t *ni = fg->get_info(mousenode); result = ni != NULL; if (result && ni->ea != BADADDR) { qstring s = get_text_disasm(ni->ea); *hint = qstrdup(s.c_str()); } } break; case grcode_dblclicked: { DECLARE_GI_VARS; graph_viewer_t *v = va_arg(va, graph_viewer_t *); selection_item_t *s = va_arg(va, selection_item_t *); callgraph_t::nodeinfo_t *ni = fg->get_info(s->node); result = ni != NULL; if (result && s->is_node && ni->ea != BADADDR) jumpto(ni->ea); } break; } return (int)result; }