//-------------------------------------------------------------------------- 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; } } }
//---------------------------------------------------------------------- static void fixup(uint32 ea, uint32 delta, int extdef) { fixup_data_t fd; fd.type = FIXUP_OFF32; if ( extdef ) fd.type |= FIXUP_EXTDEF; segment_t *s = getseg(delta); fd.displacement = get_long(ea); if ( s == NULL ) { fd.sel = 0; fd.off = delta; } else { fd.sel = (ushort)s->sel; fd.off = delta - get_segm_base(s); } set_fixup(ea, &fd); uint32 target = get_long(ea) + delta; put_long(ea, target); set_offset(ea, 0, 0); cmd.ea = ea; ua_add_dref(0, target, dr_O); cmd.ea = BADADDR; if ( target != toc_ea && !has_name(get_flags_novalue(ea)) && has_name(get_flags_novalue(target)) ) { char buf[MAXSTR]; if ( get_true_name(BADADDR, target, &buf[3], sizeof(buf)-3) != NULL ) { buf[0] = 'T'; buf[1] = 'C'; buf[2] = '_'; do_name_anyway(ea, buf); make_name_auto(ea); } } // toc.charset(ea,XMC_TC+1,1); }
//---------------------------------------------------------------------- static void make_new_name(ushort name, ushort subnam, uchar mode, unsigned ip) { char str[MAXNAMELEN]; init_output_buffer(str, sizeof(str)); if ( fmtString(name, sizeof(str)-2, fmt_fullname) ) { trunc: trunc_name(ip, mode & 4); } else if ( (char)mode > 0 ) { register char *p = get_output_ptr(); if ( p >= &str[sizeof(str)-3] ) goto trunc; *p++ = '.'; set_output_ptr(p); if ( fmtString(subnam, &str[sizeof(str)-2] - p, fmt_name) ) goto trunc; } term_output_buffer(); do_name_anyway(ip, convert_clsname(str)); hide_name(ip); }
//-------------------------------------------------------------------------- static void load_symbols(linput_t *li, header &h, long fpos, int n) { if ( !n ) return; qlseek(li, fpos); char buf[MAXSTR]; for ( int i=0; i < n; i++ ) { symbol_dictionary_record sr; lread(li, &sr, sizeof(sr)); sr.swap(); if ( sr.symbol_scope() == SS_UNSAT ) continue; char *name = get_symbol_name(li, h, sr.name.n_strx, buf, sizeof(buf)); ea_t ea = sr.symbol_value & ~3; switch ( sr.symbol_type() ) { case ST_NULL : case ST_ABSOLUTE : break; case ST_DATA : do_name_anyway(ea, name); break; case ST_STUB : append_cmt(ea, "STUB", false); case ST_CODE : case ST_ENTRY : case ST_MILLICODE: case ST_MILLI_EXT: add_entry(ea, ea, name, true); add_entry(ea, ea, name, true); break; case ST_PRI_PROG : case ST_STORAGE : case ST_MODULE : case ST_SYM_EXT : case ST_ARG_EXT : case ST_PLABEL : case ST_OCT_DIS : case ST_TSTORAGE : break; } } }
//-------------------------------------------------------------------------- static bool create_impdir(const area_t &impdir) { // now rename all entries in impdir do_unknown_range(impdir.startEA, impdir.size(), DOUNK_EXPAND); if ( !create_idata_segm(impdir) ) return false; char dll[MAXSTR]; char buf[MAXSTR]; dll[0] = '\0'; module_info_t mi; mi.base = BADADDR; mi.size = 0; size_t len = 0; for ( ea_t ea=impdir.startEA; ea < impdir.endEA; ea += ptrSz ) { doPtr(ea); ea_t func = is_9x ? win9x_find_thunk(ea) : getPtr(ea); if ( !get_true_name(BADADDR, func, buf, sizeof(buf)) ) continue; if ( !area_t(mi.base, mi.base+mi.size).contains(func) ) { find_module(func, &mi); qstrncpy(dll, qbasename(mi.name), sizeof(dll)); char *ptr = strrchr(dll, '.'); if ( ptr != NULL ) *ptr = '\0'; len = strlen(dll); } const char *name = buf; if ( strnicmp(dll, buf, len) == 0 && buf[len] == '_' ) name += len + 1; if ( !do_name_anyway(ea, name) ) msg("%a: can not rename to imported name '%s'\n", ea, name); } return true; }
//-------------------------------------------------------------------------- // 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; }
//---------------------------------------------------------------------- int upgrade_db_format(int ver, netnode constnode) { if(askyn_c(1, "AUTOHIDE REGISTRY\nHIDECANCEL\n" "The database has an old java data format.\n" "Do you want to upgrade it?") <= 0) qexit(1); switch ( ver ) { default: INTERNAL("upgrade::ver"); case IDP_JDK12: break; } // change format: jdk-version if ( curClass.MinVers > 0x8000u ) { badbase: return(0); } curClass.MajVers = JDK_MIN_MAJOR; if ( curClass.MinVers >= 0x8000 ) { curClass.MinVers &= ~0; ++curClass.MajVers; curClass.JDKsubver = 2; } else if ( curClass.MinVers >= JDK_1_1_MINOR ) ++curClass.JDKsubver; // change format: This #ifdef __BORLANDC__ #if offsetof(ClassInfo, This.Ref) != offsetof(ClassInfo, This.Name) || \ offsetof(ClassInfo, This.Dscr) != offsetof(ClassInfo, This.Name) + 2 #error #endif #endif curClass.This.Ref = (curClass.This.Ref << 16) | curClass.This.Dscr; if ( !curClass.This.Name ) goto badbase; // change format: Super #ifdef __BORLANDC__ #if offsetof(ClassInfo, super.Ref) != offsetof(ClassInfo, super.Name) || \ offsetof(ClassInfo, super.Dscr) != offsetof(ClassInfo, super.Name) + 2 #error #endif #endif switch ( curClass.super.Name ) { case 0: // absent curClass.super.Ref &= 0; break; case 0xFFFF: // bad index ++curClass.super.Name; break; default: // reverse order curClass.super.Ref = (curClass.super.Ref << 16) | curClass.super.Dscr; break; } // validate: impNode if ( curClass.impNode && !netnode(curClass.impNode).altval(0) ) goto badbase; // change variable 'errload' in previous version if ( curClass.maxSMsize ) { curClass.extflg |= XFL_C_ERRLOAD; curClass.maxSMsize &= 0; } // set segments type type for special segments segment_t *S; if ( (S = getseg(curClass.startEA)) == NULL ) goto badbase; S->set_hidden_segtype(true); S->update(); if ( curClass.xtrnCnt ) { if ( (S = getseg(curClass.xtrnEA)) == NULL ) goto badbase; S->set_hidden_segtype(true); S->update(); } curClass.extflg |= XFL_C_DONE; // do not repeat datalabel destroyer :) // change: method/fields format #define SGEXPSZ (sizeof(SegInfo) - offsetof(SegInfo, varNode)) #define FMEXPSZ (sizeof(_FMid_) - offsetof(_FMid_, _UNUSED_ALING)) #define FLEXPSZ (sizeof(FieldInfo) - offsetof(FieldInfo, annNodes)) uval_t oldsize = sizeof(SegInfo) - FMEXPSZ - SGEXPSZ; for(int pos=-(int)curClass.MethodCnt; pos<=(int)curClass.FieldCnt; pos++) { union { SegInfo s; FieldInfo f; _FMid_ id; uchar _space[qmax(sizeof(SegInfo), sizeof(FieldInfo)) + 1]; }u; if ( !pos ) { // class node oldsize += (sizeof(FieldInfo) - FLEXPSZ) - (sizeof(SegInfo) - SGEXPSZ); continue; } if ( ClassNode.supval(pos, &u, sizeof(u)) != oldsize ) goto badbase; memmove((uchar *)&u.id + sizeof(u.id), &u.id._UNUSED_ALING, (size_t)oldsize - offsetof(_FMid_, _UNUSED_ALING)); u.id._UNUSED_ALING = 0; u.id.utsign = 0; if ( u.id.extflg & ~EFL__MASK ) goto badbase; u.id.extflg &= (EFL_NAMETYPE); if ( pos > 0 ) { // fields memset(&u.f.annNodes, 0, sizeof(u.f)-offsetof(FieldInfo, annNodes)); ClassNode.supset(pos, &u.f, sizeof(u.f)); continue; } // segments memset(&u.s.varNode, 0, sizeof(u.s) - offsetof(SegInfo, varNode)); if ( u.s.thrNode && !netnode(u.s.thrNode).altval(0) ) { netnode(u.s.thrNode).kill(); // empty node (old format) u.s.thrNode = 0; } // have locvars? if ( u.s.DataSize ) { if ( (S = getseg(u.s.DataBase)) == NULL ) goto badbase; S->type = SEG_BSS; S->set_hidden_segtype(true); S->update(); } // change: Exception format if ( u.s.excNode ) { register ushort i, j; netnode enode(u.s.excNode); if ( (j = (ushort)enode.altval(0)) == 0 ) goto badbase; ea_t ea = u.s.startEA + u.s.CodeSize; i = 1; do { Exception exc; if ( enode.supval(i, &exc, sizeof(exc)) != sizeof(exc) ) goto badbase; #ifdef __BORLANDC__ #if offsetof(Exception, filter.Ref) != offsetof(Exception, filter.Name) || \ offsetof(Exception, filter.Dscr) != offsetof(Exception, filter.Name) + 2 #error #endif #endif if ( !exc.filter.Name != !exc.filter.Dscr ) goto badbase; exc.filter.Ref = (exc.filter.Ref << 16) | exc.filter.Dscr; // was reverse order if ( exc.filter.Name == 0xFFFF ) ++exc.filter.Name; enode.supset(i, &exc, sizeof(exc)); set_exception_xref(&u.s, exc, ea); }while ( ++i <= j ); } ClassNode.supset(pos, &u.s, sizeof(u.s)); //rename local variables (for references) if ( u.s.DataSize ) { int i = u.s.DataSize; ea_t ea = u.s.DataBase + i; do { char str[MAXNAMELEN]; qsnprintf(str, sizeof(str), "met%03u_slot%03u", u.s.id.Number, --i); --ea; if ( do_name_anyway(ea, str)) make_name_auto(ea ); else hide_name(ea); }while ( i ); coagulate_unused_data(&u.s); } } // for //change format of string presentation in constant pool for(int pos = 0; (ushort)pos <= curClass.maxCPindex; pos++) { ConstOpis co; if ( constnode.supval(pos, &co, sizeof(co)) != sizeof(co) ) goto badbase; switch ( co.type ) { default: continue; case CONSTANT_Unicode: error("Base contain CONSTANT_Unicode, but it is removed from " "the standard in 1996 year and never normal loaded in IDA"); case CONSTANT_Utf8: break; } uint32 v, n, i = pos << 16; if( ((n = (uint32)constnode.altval(i)) & UPG12_BADMASK) || (v = n & ~UPG12_CLRMASK) == 0) goto badbase; if ( n & UPG12_EXTMASK ) v |= UPG12_EXTSET; if ( (n = (ushort)v) != 0 ) { register uchar *po = (uchar*)append_tmp_buffer(v); n *= sizeof(ushort); uint32 pos = 0; do { uint32 sz = n - pos; if ( sz > MAXSPECSIZE ) sz = MAXSPECSIZE; if ( constnode.supval(++i, &po[pos], sz) != sz ) goto badbase; constnode.supdel(i); pos += sz; }while ( pos < n ); constnode.setblob(po, n, i & ~0xFFFF, BLOB_TAG); if ( !(v & UPG12_EXTSET) ) do { #ifdef __BORLANDC__ #if ( sizeof(ushort) % 2) || (MAXSPECSIZE % 2 ) #error #endif #endif ushort cw = *(ushort *)&po[pos]; if ( cw >= CHP_MAX ) { if ( !javaIdent(cw) ) goto extchar; } else if ( (uchar)cw <= CHP_MIN ) { extchar: v |= UPG12_EXTSET; break; } }while ( (pos -= sizeof(ushort)) != 0 ); v = upgrade_ResW(v); } constnode.altset(i, v); co._Sopstr = v; // my be not needed? (next also) constnode.supset(pos, &co, sizeof(co)); } // rename 'import' variables for refernces for(unsigned ip = 1; (ushort)ip <= curClass.xtrnCnt; ip++) { ConstOpis co; { register unsigned j; if( (j = (unsigned)XtrnNode.altval(ip)) == 0 || !LoadOpis((ushort)j, 0, &co)) goto badbase; } switch ( co.type ) { default: goto badbase; case CONSTANT_Class: if ( !(co.flag & HAS_CLSNAME) ) continue; break; case CONSTANT_InterfaceMethodref: case CONSTANT_Methodref: if ( (co.flag & NORM_METOD) != NORM_METOD ) continue; break; case CONSTANT_Fieldref: if ( (co.flag & NORM_FIELD) != NORM_FIELD ) continue; break; } make_new_name(co._name, co._subnam, co.type != CONSTANT_Class, ip); } if ( curClass.This.Dscr ) make_new_name(curClass.This.Name, 0, (uchar)-1, (unsigned)curClass.startEA); return(_TO_VERSION); }