//-------------------------------------------------------------------------- static void load_imports(linput_t *li, dl_header &dl) { if ( !dl.import_list_count ) return; qlseek(li, first_text_subspace_fpos+dl.import_list_loc); ea_t ea = data_start + dl.dlt_loc; int n = dl.dlt_count; char buf[MAXSTR]; for ( int i=0; i < dl.import_list_count; i++ ) { import_entry ie; lread(li, &ie, sizeof(ie)); ie.swap(); if ( n == 0 ) ea = data_start + dl.plt_loc; n--; buf[0] = '.'; get_text_name(ie.name, &buf[1], sizeof(buf)-1); do_name_anyway(ea, buf); doDwrd(ea, 4); set_offset(ea, 0, 0); if ( n > 0 ) { ea += 4; } else { ea_t ea2 = get_long(ea); do_name_anyway(ea2, &buf[1]); add_func(ea2, BADADDR); set_func_cmt(get_func(ea2), "THUNK", false); doDwrd(ea+4, 4); ea += 8; } } }
// terrible function - tries to identify entries in VTBL int fill_vtbl(char *name, ea_t vtbl, pdb_class *pc = NULL) { if ( NULL == p_pool ) return 0; if ( pc == NULL ) pc = p_pool->find_class(name); if ( !pc ) return -1; // no such class int max = pc->find_right_range(); if ( !max ) return 0; // empty vtbl ? struct vtbl_method *vm; int processed = 0; ///warning("processing %s (%d entries)", pc->m_name, max); ea_t mm = NULL; // message map ea_t cm = NULL; // command map // do_unknown_range(vtbl, max, false); - because first entry in VTBL is death for ( int i = 0; i <= max; i += sizeof(ea_t), vtbl += sizeof(ea_t)) { make_vtbl_entry(vtbl); vm = pc->by_offset(i); if ( vm != NULL ) { processed++; /* check for message map */ if ( !mm ) { mm = is_message_map_func(vtbl, vm->name); if ( mm ) process_message_map(mm, name); } /* check for command map */ if ( !cm ) { cm = is_command_map_func(vtbl, vm->name); if ( cm ) process_command_map(cm); } // set comment for entry in this VTBL rp_set_comment(vtbl, vm->name, false); // set function comment func_t *f = get_func(get_long(vtbl)); if ( f ) { char *fcmt = get_func_cmt(f, true); if ( fcmt ) del_func_cmt(f, false); set_func_cmt(f, vm->name, true); } } } return processed; }
// Process function void processFunction(func_t *f) { // Skip tiny functions if(f->size() >= 5) { // Don't add comments to API wrappers char name[MAXNAMELEN]; name[0] = name[SIZESTR(name)] = 0; if(!apiMap.empty()) { if(get_short_name(BADADDR, f->startEA, name, SIZESTR(name))) { if(apiMap.find(name) != apiMap.end()) return; } } // Iterate function body STRLIST importLstTmp; LPSTR commentPtr = NULL; char comment[MAXSTR]; comment[0] = comment[SIZESTR(comment)] = 0; UINT commentLen = 0; #define ADDNM(_str) { UINT l = strlen(_str); memcpy(comment + commentLen, _str, l); commentLen += l; _ASSERT(commentLen < MAXSTR); } func_item_iterator_t it(f); do { ea_t currentEA = it.current(); // Will be a "to" xref xrefblk_t xb; if(xb.first_from(currentEA, XREF_FAR)) { BOOL isImpFunc = FALSE; name[0] = 0; // If in import segment // ============================================================================================ ea_t refAdrEa = xb.to; if(isInImportSeg(refAdrEa)) { flags_t flags = get_flags_novalue(refAdrEa); if(has_name(flags) && hasRef(flags) && isDwrd(flags)) { if(get_short_name(BADADDR, refAdrEa, name, SIZESTR(name))) { // Nix the imp prefix if there is one if(strncmp(name, "__imp_", SIZESTR("__imp_")) == 0) memmove(name, name + SIZESTR("__imp_"), ((strlen(name) - SIZESTR("__imp_")) + 1)); isImpFunc = TRUE; } else msg(EAFORMAT" *** Failed to get import name! ***\n", refAdrEa); } } // Else, check for import wrapper // ============================================================================================ else if(!apiMap.empty()) { // Reference is a function entry? flags_t flags = get_flags_novalue(refAdrEa); if(isCode(flags) && has_name(flags) && hasRef(flags)) { if(func_t *refFuncPtr = get_func(refAdrEa)) { if(refFuncPtr->startEA == refAdrEa) { if(get_short_name(BADADDR, refAdrEa, name, SIZESTR(name))) { // Skip common unwanted types "sub_.." or "unknown_libname_.." if( // not "sub_.. /*"sub_"*/ (*((PUINT) name) != 0x5F627573) && // not "unknown_libname_.. /*"unknown_"*/ ((*((PUINT64) name) != 0x5F6E776F6E6B6E75) && (*((PUINT64) (name + 8)) != /*"libname_"*/ 0x5F656D616E62696C)) && // not nullsub_.. /*"nullsub_"*/ (*((PUINT64) name) != 0x5F6275736C6C756E) ) { // Nix the import prefixes if(strncmp(name, "__imp_", SIZESTR("__imp_")) == 0) memmove(name, name + SIZESTR("__imp_"), ((strlen(name) - SIZESTR("__imp_")) + 1)); // Assumed to be a wrapped import if it's in the list isImpFunc = (apiMap.find(name) != apiMap.end()); } } else msg(EAFORMAT" *** Failed to get function name! ***\n", refAdrEa); } } } } // Found import function to add list if(isImpFunc) { // Skip those large common STL names if(strncmp(name, "std::", SIZESTR("std::")) != 0) { // Skip if already seen in this function BOOL known = FALSE; for(STRLIST::iterator ji = importLstTmp.begin(); ji != importLstTmp.end(); ji++) { if(strcmp(ji->c_str(), name) == 0) { known = TRUE; break; } } // Not seen if(!known) { importLstTmp.push_front(name); // Append to existing comments w/line feed if(!commentLen && !commentPtr) { commentPtr = get_func_cmt(f, true); if(!commentPtr) get_func_cmt(f, false); if(commentPtr) { commentLen = strlen(commentPtr); // Bail out not enough comment space if(commentLen >= (MAXSTR - 20)) { qfree(commentPtr); return; } memcpy(comment, commentPtr, commentLen); ADDNM("\n"MYTAG); } } if(!commentLen) ADDNM(MYTAG); // Append a "..." (continuation) and bail out if name hits max comment length if((commentLen + strlen(name) + SIZESTR("()") + sizeof(", ")) >= (MAXSTR - sizeof("..."))) { ADDNM(" ..."); break; } // Append this function name else { if(importLstTmp.size() != 1) ADDNM(", "); ADDNM(name); ADDNM("()"); } } } else { //msg("%s\n", szName); } } } }while(it.next_addr()); if(!importLstTmp.empty() && commentLen) { // Add comment comment[commentLen] = 0; set_func_cmt(f, comment, true); commentCount++; } if(commentPtr) qfree(commentPtr); } }
bool wrapped_set_func_cmt(func_t *fn, const char *cmt, bool repeatable) { return set_func_cmt(fn, cmt, repeatable); }