char *DieHolder::get_type_comment(void) { char *comment = NULL; uint32 ordinal = 0; if(get_type_ordinal(&ordinal)) { type_t const *type = NULL; p_list const *fields = NULL; bool const found = get_numbered_type(idati, ordinal, &type, &fields); if(found) { // dynamic type string allocation does not work (returns T_SHORTSTR) // so allocate a huge buffer on the stack... char buf[MAXSTR]; int const ret = print_type_to_one_line(buf, sizeof(buf), idati, type, get_name(), NULL, fields, NULL); if(ret >= 0); { size_t len = strlen(buf); comment = static_cast<char *>(qalloc(len + 1)); if(comment != NULL) { memcpy(comment, buf, len + 1); } } } } return comment; }
int get_idx_type_size(cexpr_t *idx_expr) { char buff[MAXSTR]; print_type_to_one_line(buff, MAXSTR, idati, idx_expr->type.u_str()); if(strstr(buff, "char")) return 1; else if(strstr(buff, "short")) return 2; else if(strstr(buff, "int")) return 4; return 0; }
// Determine the node color. Feel free to change it. bgcolor_t idaapi cfunc_graph_t::get_node_color(int n) { const citem_t *item = items[n]; if ( item == highlight ) return CL_GREEN; // Highlighted item if ( item->is_expr() ) { char buf[MAXSTR]; const cexpr_t *e = (const cexpr_t *)item; if ( print_type_to_one_line(buf, sizeof(buf), idati, e->type.u_str()) != T_NORMAL ) return CL_YELLOWGREEN; // Problematic type } if(item->op == cot_call) return CL_RED; return DEFCOLOR; }
char * callgraph_t::get_node_label(int n, char *buf, int bufsize) const { int_ea_map_t::const_iterator it = node2ea.find(n); if ( it != node2ea.end() ) { const citem_t *item = it->second; char *ptr = buf; char *endp = buf + bufsize; // Each node will have the element type at the first line APPEND(ptr, endp, get_ctype_name(item->op)); const cexpr_t *e = (const cexpr_t *)item; const cinsn_t *i = (const cinsn_t *)item; // For some item types, display additional information switch ( item->op ) { case cot_ptr : // *x case cot_memptr : // x->m // Display access size for pointers ptr += qsnprintf(ptr, endp-ptr, ".%d", e->ptrsize); if ( item->op == cot_ptr ) break; case cot_memref : // x.m // Display member offset for structure fields ptr += qsnprintf(ptr, endp-ptr, " (m=%d)", e->m); break; case cot_obj : // v case cot_var : // l // Display object size for local variables and global data ptr += qsnprintf(ptr, endp-ptr, ".%d", e->refwidth); case cot_num : // n case cot_helper : // arbitrary name case cot_str : // string constant // Display helper names and number values APPCHAR(ptr, endp, ' '); e->print1(ptr, endp-ptr, NULL); tag_remove(ptr, ptr, 0); ptr = tail(ptr); break; case cit_goto: // Display target label number for gotos ptr += qsnprintf(ptr, endp-ptr, " LABEL_%d", i->cgoto->label_num); break; case cit_asm: // Display instruction block address and size for asm-statements ptr += qsnprintf(ptr, endp-ptr, " %a.%"FMT_Z, *i->casm->begin(), i->casm->size()); break; default: break; } // The second line of the node contains the item address ptr += qsnprintf(ptr, endp-ptr, "\nea: %a", item->ea); if ( item->is_expr() && !e->type.empty() ) { // For typed expressions, the third line will have // the expression type in human readable form APPCHAR(ptr, endp, '\n'); if ( print_type_to_one_line(ptr, endp-ptr, idati, e->type.u_str()) != T_NORMAL ) { // could not print the type? APPCHAR(ptr, endp, '?'); APPZERO(ptr, endp); } if(e->type.is_ptr()) { typestring ptr_rem = remove_pointer(e->type); if(ptr_rem.is_struct()) { qstring typenm; print_type_to_qstring(&typenm, "prefix ", 0,0, PRTYPE_MULTI | PRTYPE_TYPE | PRTYPE_SEMI, idati, ptr_rem.u_str()); } } } } return buf; }
//-------------------------------------------------------------------------- void run(int /*arg*/) { if ( !autoIsOk() && askyn_c(-1, "HIDECANCEL\n" "The autoanalysis has not finished yet.\n" "The result might be incomplete. Do you want to continue?") < 0 ) return; // gather information about the entry points entrylist_t *li = new entrylist_t; size_t n = get_entry_qty(); for ( size_t i=0; i < n; i++ ) { asize_t ord = get_entry_ordinal((int)i); ea_t ea = get_entry(ord); if ( ord == ea ) continue; qtype type, fnames; char decl[MAXSTR]; char true_name[MAXSTR]; asize_t argsize = 0; get_entry_name(ord, true_name, sizeof(true_name)); if ( get_tinfo(ea, &type, &fnames) && print_type_to_one_line( decl, sizeof(decl), idati, type.c_str(), true_name, NULL, fnames.c_str()) == T_NORMAL ) { // found type info -- calc the args size func_type_info_t fi; int a = build_funcarg_info(idati, type.c_str(), fnames.c_str(), &fi, 0); if ( a != 0 ) { for ( int k=0; k < a; k++ ) { const type_t *ptr = fi[k].type.c_str(); int s1 = (int)get_type_size(idati, ptr); s1 = qmax(s1, inf.cc.size_i); argsize += s1; } } } else if ( get_long_name(BADADDR, ea, decl, sizeof(decl)) != NULL && get_true_name(BADADDR, ea, true_name, sizeof(true_name)) != NULL && strcmp(decl, true_name) != 0 ) { // found mangled name } else { // found nothing, just show the name const char *name = get_name(BADADDR, ea, true_name, sizeof(true_name)); if ( name == NULL ) continue; qstrncpy(decl, name, sizeof(decl)); } if ( argsize == 0 ) { func_t *pfn = get_func(ea); if ( pfn != NULL ) argsize = pfn->argsize; } item_t x; x.ord = (int)ord; x.ea = ea; x.decl = decl; x.argsize = (uint32)argsize; li->push_back(x); } // now open the window choose2(false, // non-modal window -1, -1, -1, -1, // position is determined by Windows li, // pass the created array qnumber(header), // number of columns widths, // widths of columns sizer, // function that returns number of lines desc, // function that generates a line "Exported functions", // window title -1, // use the default icon for the window 0, // position the cursor on the first line NULL, // "kill" callback NULL, // "new" callback NULL, // "update" callback NULL, // "edit" callback enter_cb, // function to call when the user pressed Enter destroy_cb, // function to call when the window is closed NULL, // use default popup menu items NULL); // use the same icon for all lines }
//-------------------------------------------------------------------------- // Generate text for the current location int ida_export class_place_t__generate( const cp_t *ths, void *ud, char *lines[], int maxsize, int *default_lnnum, color_t *prefix_color, bgcolor_t *bg_color) { strvec_t &sv = *(strvec_t *)ud; uval_t idx = ths->idx; if ( idx > get_last_class_idx() || maxsize <= 0 ) return 0; char name[MAXNAMESIZE]; tid_t tid = get_class_by_idx(idx); if (tid==BADNODE) return 0; switch (ths->section) { case 0: if (get_class_name(tid, name, MAXNAMESIZE)) { char line[MAXSTR]; class_t * clas = get_class(tid); if(!clas) return 0; if (clas->parents_tid.size()) qsnprintf(line, MAXSTR, "class %s: derived from: 0x%p", name, clas->parents_tid.front()); else qsnprintf(line, MAXSTR, "class %s", name ); lines[0] = qstrdup(line); *bg_color = 0xC0C0FF; } break; case 1: { char line[MAXSTR]; class_t * clas = get_class(tid); if(!clas) return 0; if (clas->virt_table_ea != BADADDR) qsnprintf(line, MAXSTR, "vftable: %p", clas->virt_table_ea); else qsnprintf(line, MAXSTR, "no virtual table"); lines[0] = qstrdup(line); *bg_color = 0xC0FFC0; } break; case 2: { char *line; class_t * clas = get_class(tid); if(!clas) return 0; ea_t ea = BADADDR; if (clas->functions_ea.size() && ths->subsection<=clas->functions_ea.size()) ea = clas->functions_ea[ths->subsection]; if (ea!=BADADDR) { qstring tmpline; get_colored_long_name(&tmpline, ea); qtype type; qtype fields; if (!get_tinfo(ea, &type, &fields)) { if (!guess_func_tinfo(get_func(ea), &type, &fields)) goto pokracuj; } line = qstrdup(tmpline.c_str()); print_type_to_one_line(line, MAXSTR, idati, type.c_str(), line, 0, fields.c_str(), 0); pokracuj: ; } else qsnprintf(line, MAXSTR, "bad func"); lines[0] = qstrdup(line); *bg_color = 0xC0FFFF; } break; } //*prefix_color = sv[idx%sv.size()].color; //*bg_color = sv[idx%sv.size()].bgcolor; *default_lnnum = 0; return 1; // generated one line //setup_makeline(-1, ..., save_line_in_array, 0) //finish_makeline(); }
/*! @brief This function determines if a ctree item is legitimate; it marks variables legitimate via the afVariableIsLegit array and saves legitimate items in the vectorLegitItems vector @param[in] pItem The visited ctree item @return Returns 0 to continue the traversal, returns 1 to stop the traversal */ int visit_item ( citem_t* pItem ) { cexpr_t* pExpression; char szType[16]; // // Ensure that we're initialized // if (!fInitialized) { if (!Initialize()) { return 1; } } // // If we're traversing the graph solely to mark descendants as // legitimate... // if (fMarkingDescendantsLegit) { // // Don't descend through items through which we've already // descended // if (vectorDescendantsMarkedLegit.has(pItem)) { return 0; } // // If this is a variable, mark the variable legitimate // if (pItem->op == cot_var) { afVariableIsLegit[((cexpr_t*)pItem)->v.idx] = true; } // // Mark the item itself legitimate // if (!vectorLegitItems.has(pItem)) { vectorLegitItems.push_back( pItem); fNewLegitItemFound = true; } // // Remember that we've now descended through this item // vectorDescendantsMarkedLegit.push_back( pItem); // // Continue marking other descendant items as legitimate // return 0; } // // If this item was already marked as legititmate... // if (vectorLegitItems.has(pItem)) { // // If we have a legitimate item that's an if/for/while/do/ // return statement then mark the expression part of that node // (for example, the "x" in "if(x)") as legitimate as well // pExpression = NULL; switch (pItem->op) { case cit_if: pExpression = &((cinsn_t*)pItem)->cif->expr; break; case cit_for: pExpression = &((cinsn_t*)pItem)->cfor->expr; break; case cit_while: pExpression = &((cinsn_t*)pItem)->cwhile->expr; break; case cit_do: pExpression = &((cinsn_t*)pItem)->cdo->expr; break; case cit_return: pExpression = &((cinsn_t*)pItem)->creturn->expr; break; default: break; } if (pExpression == NULL) { return 0; } // // If the expression hasn't already been marked as legitimate // then mark it so and mark all of its descendants as // legitimate as well // if (!vectorDescendantsMarkedLegit.has(pExpression)) { // // Mark all items under this expression/call as legitimate // fMarkingDescendantsLegit = true; apply_to( pExpression, NULL); fMarkingDescendantsLegit = false; // // cit_for statements require us to also process the // for-loop initialization and step expressions // if (pItem->op == cit_for) { // // Process the for-loop's initialization expression // pExpression = &((cinsn_t*)pItem)->cfor->init; if (!vectorDescendantsMarkedLegit.has(pExpression)) { // // Mark all items under this expression as legit // fMarkingDescendantsLegit = true; apply_to( pExpression, NULL); fMarkingDescendantsLegit = false; } // // Process the for-loop's step expression // pExpression = &((cinsn_t*)pItem)->cfor->step; if (!vectorDescendantsMarkedLegit.has(pExpression)) { // // Mark all items under this expression as legit // fMarkingDescendantsLegit = true; apply_to( pExpression, NULL); fMarkingDescendantsLegit = false; } } } return 0; } // // If this item is a legitimate variable and/or a CPPEH_RECORD // variable, or a function, global variable, legit macro, goto, // break, continue, return, or asm-statement then mark the ancestor // expressions as legitimate // if (pItem->op == cot_var) { if (!afVariableIsLegit[((cexpr_t*)pItem)->v.idx]) { if (T_NORMAL != print_type_to_one_line( szType, _countof(szType), idati, ((cexpr_t*)pItem)->type.u_str())) { return 0; } if (0 != strcmp(szType, "CPPEH_RECORD")) { return 0; } } } else if (!((pItem->op == cot_obj) || ((pItem->op == cot_call) && IsLegitimateCall((cexpr_t*)pItem)) || (pItem->op == cit_goto) || (pItem->op == cit_break) || (pItem->op == cit_continue) || (pItem->op == cit_return)) || (pItem->op == cit_asm)) { return 0; } // // Iterate through all ancestors (assumes that the decompilation // graph is a tree and that no item has more than one parent) // for(citem_t* pCurrentItem = pItem; pCurrentItem != NULL; pCurrentItem = pFunction->body.find_parent_of(pCurrentItem)) { if (!vectorLegitItems.has(pCurrentItem)) { vectorLegitItems.push_back( pCurrentItem); fNewLegitItemFound = true; } if ((pCurrentItem->op == cit_expr) || ((pCurrentItem->op == cot_call) && IsLegitimateCall((cexpr_t*)pCurrentItem)) || (pCurrentItem->op == cit_return)) { // // This is a cit_expr statement node or cot_call // expression // if (!vectorDescendantsMarkedLegit.has(pCurrentItem)) { // // Mark all items under this expression/call as legit // fMarkingDescendantsLegit = true; apply_to( pCurrentItem, NULL); fMarkingDescendantsLegit = false; } } } return 0; }