//---------------------------------------------------------------------- static void process_loader(char *ptr, pef_section_t *sec, int nsec) { int i; pef_loader_t &pl = *(pef_loader_t *)ptr; pef_library_t *pil = (pef_library_t *)(&pl + 1); swap_pef_loader(pl); uint32 *impsym = (uint32 *)(pil + pl.importLibraryCount); pef_reloc_header_t *prh = (pef_reloc_header_t *)(impsym + pl.totalImportedSymbolCount); uint16 *relptr = (uint16 *)(ptr + pl.relocInstrOffset); uint32 *hash = (uint32 *)(ptr + pl.exportHashOffset); uint32 hashsize = (1 << pl.exportHashTablePower); uint32 *keytable = hash + hashsize; pef_export_t *pe = (pef_export_t *)(keytable + pl.exportedSymbolCount); #if !__MF__ for ( i=0; i < pl.importLibraryCount; i++ ) swap_pef_library(pil[i]); for ( i=0; i < pl.relocSectionCount; i++ ) swap_pef_reloc_header(prh[i]); for ( i=0; i < pl.exportedSymbolCount; i++ ) swap_pef_export(pe[i]); #endif char *stable = ptr + pl.loaderStringsOffset; if ( pl.totalImportedSymbolCount != 0 ) { uint32 size = pl.totalImportedSymbolCount*4; ea_t undef = freechunk(inf.maxEA, size, -0xF); ea_t end = undef + size; set_selector(nsec+1, 0); if(!add_segm(nsec+1, undef, end, "IMPORT", "XTRN")) loader_failure(); for ( i=0; i < pl.importLibraryCount; i++ ) { ea_t ea = undef + 4*pil[i].firstImportedSymbol; add_long_cmt(ea, 1, "Imports from library %s", stable+pil[i].nameOffset); if ( pil[i].options & PEF_LIB_WEAK ) add_long_cmt(ea, 1, "Library is weak"); } inf.specsegs = 1; for ( i=0; i < pl.totalImportedSymbolCount; i++ ) { uint32 sym = mflong(impsym[i]); uchar sclass = uchar(sym >> 24); ea_t ea = undef+4*i; set_name(ea, get_impsym_name(stable,impsym,i)); if ( (sclass & kPEFWeak) != 0 ) make_name_weak(ea); doDwrd(ea,4); put_long(ea, 0); impsym[i] = (uint32)ea; } }
static int notify(processor_t::idp_notify msgid, ...) // Various messages { va_list va; va_start(va, msgid); // A well behaving processor module should call invoke_callbacks() // in his notify() function. If this function returns 0, then // the processor module should process the notification itself // Otherwise the code should be returned to the caller: int code = invoke_callbacks(HT_IDP, msgid, va); if ( code ) return code; switch ( msgid ) { case processor_t::newfile: { // ig: вообще у меня теперь такая точка зрения: // не надо в коде задавать вид имен. // при желании это можно сделать в ida.cfg: // #ifdef __80196__ // DUMMY_NAMES_TYPE = NM_SHORT // #endif segment_t *sptr = get_first_seg(); if( sptr != NULL ) set_segm_class( sptr, "CODE" ); ea_t ea, ea1; for( int i = 0; i < qnumber(entries); i++ ) { ea = toEA( inf.baseaddr, entries[i].off ); if( isEnabled(ea) ) { switch( entries[i].type ) { case I196F_BTS: doByte( ea, entries[i+1].off-entries[i].off ); set_cmt( ea, entries[i].cmt, 0 ); break; case I196F_CMT: if( entries[i].cmt ) add_long_cmt( ea, 1, "%s", entries[i].cmt ); else describe( ea, 1, "" ); break; case I196F_OFF: doWord( ea, 2 ); set_offset( ea, 0, toEA( inf.baseaddr, 0 ) ); ea1 = toEA( inf.baseaddr, get_word( ea ) ); auto_make_proc( ea1 ); //dash: long_cmt здесь не смотрится, так как рисуется до заголовка // хорошо бы поставить func_cmt, но к этому моменту функций еще нет // как быть? //ig: воспользоваться простым комментарием // при создании функции комментарий перетащится set_cmt( ea1, entries[i].cmt, 1 ); } set_name( ea, entries[i].name ); } } ea = toEA( inf.baseaddr, 0x2080 ); if( isEnabled( ea ) ) { inf.beginEA = ea; inf.startIP = 0x2080; } segment_t s; s.startEA = toEA( inf.baseaddr, 0 ); s.endEA = toEA( inf.baseaddr, 0x400 ); s.sel = inf.baseaddr; s.type = SEG_IMEM; // internal memory // ig: лучше искать дырку не от нуля, а от базы загрузки // ea_t bottom = toEA( inf.baseaddr, 0 ); // intmem = s.startEA = freechunk( bottom, 1024, 0xF ); // s.endEA = s.startEA + 1024; // s.sel = ushort(s.startEA >> 4); // dash: дырку искать не пришлось, но я оставил это как пример на будущее add_segm_ex( &s, "INTMEM", NULL, ADDSEG_OR_DIE); predefined_t *ptr; for( ptr = iregs; ptr->name != NULL; ptr++ ) { ea_t ea = toEA( inf.baseaddr, ptr->addr ); ea_t oldea = get_name_ea( BADADDR, ptr->name ); if( oldea != ea ) { if( oldea != BADADDR ) set_name( oldea, NULL ); do_unknown( ea, DOUNK_EXPAND ); set_name( ea, ptr->name ); } if( ptr->cmt != NULL ) set_cmt( ea, ptr->cmt, 1 ); } } // do16bit( 0x18, 2 ); // SP always word break; case processor_t::oldfile: for ( segment_t *s=get_first_seg(); s != NULL; s=get_next_seg(s->startEA) ) { if ( getSRarea(s->startEA) == NULL ) { segreg_t sr; sr.startEA = s->startEA; sr.endEA = s->endEA; sr.reg(WSR) = 0; sr.reg(WSR1) = 0; sr.reg(rVds) = inf.baseaddr; sr.settags(SR_autostart); SRareas.create_area(&sr); } } break; case processor_t::newseg: // default DS is equal to Base Address (va_arg(va, segment_t *))->defsr[rVds-ph.regFirstSreg] = inf.baseaddr; break; case processor_t::newprc: extended = va_arg(va,int) != 0; if ( !extended ) ph.flag &= ~PR_SEGS; else ph.flag |= PR_SEGS; default: break; } va_end(va); return(1); }
//-------------------------------------------------------------------------- // Process debugging information item and try to incorporate it into // the database. // NOTE: This function does not process all debugging information. // It knows only about some types of debugingo. static size_t process_item(uchar *di, size_t disize, section_t *sect) { uchar *const end = di + disize; uint32 fw = *(uint32 *)di; if ( mf ) fw = swap32(fw); size_t len = fw >> 16; if ( len == 0 || len > disize ) return 0; switch ( fw & 0xFFFF ) { case AIF_DEB_SECT: // section if ( disize < sizeof(section_t) ) return 0; sect = (section_t *)di; if ( mf ) swap_section(sect); if ( sect->debugsize != 0 ) len = sect->debugsize; switch ( sect->lang ) { case LANG_C: add_long_cmt(sect->codestart,1,"C source level debugging data is present"); break; case LANG_PASCAL: add_long_cmt(sect->codestart,1,"Pascal source level debugging data is present"); break; case LANG_FORTRAN: add_long_cmt(sect->codestart,1,"Fortran-77 source level debugging data is present"); break; case LANG_ASM: add_long_cmt(sect->codestart,1,"ARM assembler line number data is present"); break; } if ( sect->lang == LANG_NONE ) { size_t nsyms = size_t(sect->name); dsym_t *ds = (dsym_t *)(sect+1); char *str = (char *)(ds+nsyms); if ( str >= (char *)end ) return 0; bool use_pascal = swap_symbols(ds, str, end, nsyms); for ( int i=0; i < nsyms; i++,ds++ ) { if ( ds->sym & ASD_16BITSYM ) continue; size_t off = size_t(ds->sym & ASD_SYMOFF); char *name = str + off + use_pascal; if ( name < str || name >= (char *)end ) continue; if ( special_name(name) ) continue; if ( ds->sym & ASD_ABSSYM ) // if the symbol is absolute { add_pgm_cmt("%s = 0x%X", name, ds->value); } else if ( isEnabled(ds->value) ) { if ( ds->sym & ASD_GLOBSYM ) { add_entry(ds->value, ds->value, name, is_true_text_symbol(ds, name)); } else { do_name_anyway(ds->value, name); if ( is_true_text_symbol(ds, name) ) auto_make_code(ds->value); } } } } else { char name[64]; const uchar *nptr = (const uchar *)§->name; size_t namelen = *nptr++; namelen = qmin(namelen, sizeof(name) - 1); namelen = qmin(namelen, end - nptr); memcpy(name, nptr, namelen); //lint !e670 name[namelen] = '\0'; if ( sect->codestart != 0 ) add_long_cmt(sect->codestart,1,"Section \"%s\", size 0x%X",name,sect->codesize); if ( sect->datastart != 0 ) add_long_cmt(sect->datastart,1,"Section \"%s\", size 0x%X",name,sect->datasize); } #if 0 if ( sect->fileinfo != 0 ) { // fileinfo is present? process_item(di+size_t(sect->fileinfo),sect); } #endif break; case AIF_DEB_FDEF: // procedure/function definition deb(IDA_DEBUG_LDR, "procedure/function definition\n"); break; case AIF_DEB_ENDP: // endproc deb(IDA_DEBUG_LDR, "endproc\n"); break; case AIF_DEB_VAR: // variable deb(IDA_DEBUG_LDR, "variable\n"); break; case AIF_DEB_TYPE: // type deb(IDA_DEBUG_LDR, "type\n"); break; case AIF_DEB_STRU: // struct deb(IDA_DEBUG_LDR, "struct\n"); break; case AIF_DEB_ARRAY: // array deb(IDA_DEBUG_LDR, "array\n"); break; case AIF_DEB_RANGE: // subrange deb(IDA_DEBUG_LDR, "subrange\n"); break; case AIF_DEB_SET: // set deb(IDA_DEBUG_LDR, "set\n"); break; case AIF_DEB_FILE: // fileinfo deb(IDA_DEBUG_LDR, "fileinfo\n"); break; case AIF_DEB_CENUM: // contiguous enumeration deb(IDA_DEBUG_LDR, "contiguous enumeration\n"); break; case AIF_DEB_DENUM: // discontiguous enumeration deb(IDA_DEBUG_LDR, "discontiguous enumeration\n"); break; case AIF_DEB_FDCL: // procedure/function declaration deb(IDA_DEBUG_LDR, "procedure/function declaration\n"); break; case AIF_DEB_SCOPE: // begin naming scope deb(IDA_DEBUG_LDR, "begin naming scope\n"); break; case AIF_DEB_ENDS: // end naming scope deb(IDA_DEBUG_LDR, "end naming scope\n"); break; case AIF_DEB_BITF: // bitfield deb(IDA_DEBUG_LDR, "bitfield\n"); break; case AIF_DEB_MACRO: // macro definition deb(IDA_DEBUG_LDR, "macro definition\n"); break; case AIF_DEB_ENDM: // macro undefinition deb(IDA_DEBUG_LDR, "macro undefinition\n"); break; case AIF_DEB_CLASS: // class deb(IDA_DEBUG_LDR, "class\n"); break; case AIF_DEB_UNION: // union deb(IDA_DEBUG_LDR, "union\n"); break; case AIF_DEB_FPMAP: // FP map fragment deb(IDA_DEBUG_LDR, "FP map fragment\n"); break; default: msg("unknown (0x%d.)!!!\n", fw & 0xFFFF); break; } return len; }