void idaapi function_list::get_line(void *obj,uint32 n,char * const *arrptr) { if ( n == 0 ) // generate the column headers { for ( int i=0; i < qnumber(header); i++ ) qstrncpy(arrptr[i], header[i], MAXSTR); return; } function_list & ms = *(function_list*)obj; ea_t ea = ms.functions[n-1]; qsnprintf(arrptr[0], MAXSTR, "%08a", ea); get_func_name(ea, arrptr[1], MAXSTR); //get_short_name(BADADDR, ea, arrptr[1], MAXSTR); //get_demangled_name(BADADDR, ea, arrptr[1], MAXSTR, inf.long_demnames, DEMNAM_NAME, 0); func_t * f = get_func(ea); if(f) { const char * cmt = get_func_cmt(f, true); if(cmt) { qstrncpy(arrptr[2], cmt, MAXSTR); } } }
char *wrapped_get_func_cmt(func_t *fn, bool repeatable) { int length = -1; char *original_result = get_func_cmt(fn, repeatable); if (NULL == original_result) { return ""; } length = strlen(original_result); qstrncpy(function_comment_buffer, original_result, length+1); qfree(original_result); return function_comment_buffer; }
// 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; }
/* #<pydoc> def get_func_cmt(fn, repeatable): """ Retrieve function comment @param fn: function instance @param repeatable: retrieve repeatable or non-repeatable comments @return: None on failure or the comment """ pass #</pydoc> */ static PyObject *py_get_func_cmt(func_t *fn, bool repeatable) { char *s = get_func_cmt(fn, repeatable); if ( s == NULL ) { Py_RETURN_NONE; } else { PyObject *py_s = PyString_FromString(s); qfree(s); return py_s; } }
// 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); } }