static int refput(ushort index) { if(!LoadOpis(index, CONSTANT_Utf8, NULL)) return(0); qfprintf(myFile, rfmt, index); return(utfstr(index, NULL)); }
//---------------------------------------------------------------------- int32 gen_map_file(FILE *fp) { static const char frm[] = "Map format\n\n" "<~W~idth:D:3:::> [72-%D], 0 - unlimited \n" " Printing\n" "<~A~ll:R> Included constant types\n" "<~U~nused :R>> <Utf~8~:C>\n" " Sorting by<~C~lass:C>\n" "<~T~ype:R><~R~eferences:C>\n" "<U~n~sorted:R>><Na~m~eAndType :C>\n" " Number in pool<Num~b~ers:C>\n" "<~D~ecimal :R><~S~tring:C>>\n" "<~H~ex:R>>\n\n" "<~O~ut Utf8 string without encoding :C>\n" "<~I~nclude loader problem messages :C>>\n\n"; static const struct { ushort mask; ushort skip; char name[8]; int (*proc)(ushort index, const ConstOpis *); ushort arg; }defr[MAX_CONSTANT_TYPE] = { {0x01, 0, "Utf8 ", utfstr, 0}, {0x00, 0, "", NULL, 0}, // unicode {0x10, 4, "Integer", outnum, 3 + dt_dword}, {0x10, 4, "Float ", outnum, 3 + dt_float}, {0x10, 8, "Long ", outnum, 3 + dt_qword}, {0x10, 8, "Double ", outnum, 3 + dt_double}, {0x02, 2, "Class ", outref, 1}, {0x20, 2, "String ", outref, 1}, {0x04, 4, "Fld_ref", outref, 3}, {0x04, 4, "Met_ref", outref, 3}, {0x04, 4, "Int_ref", outref, 3}, {0x08, 4, "nam&typ", outref, 2} }; #define STR_MIN_RESERVED 32 char str[MAXSTR]; uchar tflag; int32 width, pos, numstr = 0; uint32 save_flags = idpflags; ushort curbit = 1; short unus = 1, unsort = 1, hexnum = 0, typemask = 0x3F, encinc = 2; ConstOpis opis; register ushort i, j; static char lft_fmt[] = "%08lX %5u%c %s "; if(!(idpflags & IDF_ENCODING)) ++encinc; // |= 1 uFlag = decflag(); // Decimal OutValue width = 80; bufsize = pos = sizeof(str)-32; if(!AskUsingForm_c(frm, &width, &pos, &unus, &unsort, &typemask, &hexnum, &encinc)) return(0); if(encinc & 2) unus = 0; // from error - all idpflags &= ~IDF_ENCODING; if(!(encinc & 1)) idpflags |= IDF_ENCODING; #if (MAXSTR-STR_MIN_RESERVED) <= 72 #error #endif no_prompt = 0; if(width < 72) { if(width) width = 72; else { no_prompt = 0; set_max: width = sizeof(str)-STR_MIN_RESERVED; } } else if(width > (MAXSTR-STR_MIN_RESERVED)) goto set_max; if(!typemask) typemask = 0x3F; if(hexnum) { lft_fmt[7] = ind_fmt[5] = rfmt[17] = '4'; lft_fmt[8] = ind_fmt[6] = rfmt[18] = 'X'; curpos = 8 + 1 + 4 + 1 + 1 + 0 + 1; } else { lft_fmt[7] = ind_fmt[5] = rfmt[17] = '5'; lft_fmt[8] = ind_fmt[6] = rfmt[18] = 'u'; curpos = 8 + 1 + 5 + 1 + 1 + 0 + 1; } if(unsort) { curpos += 7; curbit = typemask; } maxpos = width; bufbeg = str; myFile = fp; do { while(!(typemask & curbit)) curbit <<= 1; for(tflag = (uchar)unsort, pos = 10, i = 1; i <= curClass.maxCPindex; i++) { if(!LoadOpis(i, 0, &opis) || opis.type == CONSTANT_Unicode) DESTROYED("map::CP"); j = opis.type - 1; DEB_ASSERT((j >= MAX_CONSTANT_TYPE), "map:type"); if((!unus || !(opis.flag & _REF)) && (curbit & defr[j].mask)) { if(!numstr) { static const char fmh[]= "This file generated by IDA"; for(int k = (maxpos - sizeof(fmh)) / 2; k; k--) qfputc(' ', fp); char dname[MAXSTR]; if(ConstantNode.supstr(CNS_SOURCE, dname, sizeof(dname)) < 0) DESTROYED("map:srcname"); qfprintf(fp, "%s\n\n" " Constant Pool for \"%s\"\n\n" " offset #(%s)\n", fmh, dname, hexnum ? "hex" : "dec"); numstr = 5; } if(!tflag) { qfprintf(fp, "\n-----CONSTANT-%s-----\n", (defr[j].arg < 3) ? defr[j].name : ((defr[j].arg == 3) ? "(program references)" : "(numeric values)")); ++tflag; numstr += 2; } qfprintf(fp, lft_fmt, pos, i, (opis.flag & _REF) ? ' ' : '*', (unsort || defr[j].arg >= 3) ? defr[j].name : ""); { register int n = defr[j].proc(defr[j].arg ? defr[j].arg : i, &opis); if(n <= 0) goto do_eof; numstr += n; } if(unus && unsort && opis.type >= CONSTANT_Class) { numstr += refput(opis._name); if(opis.type > CONSTANT_String) { if(opis.type == CONSTANT_NameAndType) numstr += refput(opis._class); else { numstr += refput(opis._subnam); numstr += refput(opis._dscr); } } } if(feof(fp) || ferror(fp)) goto do_eof; } ++pos; switch(j = defr[j].skip) { case 0: // Utf8 / Unicode pos += opis._Ssize + 2; break; case 8: // Long / Double DEB_ASSERT((i == curClass.maxCPindex), "map:CPend"); ++i; default: pos += j; break; } } }while((typemask ^= curbit) != 0); if(numstr) { // if error print before - header problems! qfprintf(fp, "\nEnd of map\n"); numstr += 2; if((encinc & 2) && curClass.msgNode) { qfprintf(fp, "\nLoader problem messages\n\n"); int32 slen = print_loader_messages(str, NULL); if(slen == -1) goto do_eof; numstr += slen + 5; qfprintf(fp, "\nEnd of messages\n"); } if(feof(fp) || ferror(fp)) { do_eof: numstr = EOF; } } myFile = NULL; idpflags = save_flags; return(numstr); }
static int ConstLoad(CIC_param ctype) { ConstOpis cntopis; uchar i; cmd.Op1.type = o_cpool; // cmd.Op1.ref = 0; if ( !cmd.Op1.cp_ind ) goto dmpchk; //NULL Ptr if ( !LoadOpis(cmd.Op1.cp_ind, 0, &cntopis) ) goto dmpchk; #ifdef __BORLANDC__ #if ( offsetof(ConstOpis,flag) != (offsetof(ConstOpis,type) + sizeof(uchar) ) \ || (sizeof(cntopis.type) != sizeof(uchar)) \ || (sizeof(cntopis.flag) != sizeof(uchar)) \ || (sizeof(cmd.Op1.cp_type) < (2*sizeof(uchar))) \ || (sizeof(ushort) != sizeof(cmd.Op1.cp_type))) #error #endif #endif cmd.Op1.cp_type = *((ushort *)&cntopis.type); i = cntopis.type; switch ( ctype ) { case C_Class: if ( i != CONSTANT_Class ) break; //PASS THRU case C_4byte: // ldc/ldcw switch ( i ) { case CONSTANT_Class: if ( !(cntopis.flag & HAS_CLSNAME) ) goto wrnret; cmd.Op1.addr = 0x10001ul * (ushort)fmt_fullname; loadref1: cmd.xtrn_ip = cntopis.ref_ip; //PASS THRU case CONSTANT_Integer: case CONSTANT_Float: case CONSTANT_String: cmd.Op1.value = cntopis.value; // for string index to Utf8 return(1); // or TWO index for other default: break; } break; case C_8byte: if ( i == CONSTANT_Long || i == CONSTANT_Double ) goto load2; break; case C_Field: if ( i != CONSTANT_Fieldref ) break; if ( (cntopis.flag & NORM_FIELD) != NORM_FIELD ) goto wrnret; loadref2: cmd.xtrn_ip = cntopis.ref_ip; load2: cmd.Op1.addr = cntopis.value2; cmd.Op1.value = cntopis.value; // for string index to Utf8 #ifdef __EA64__ cmd.Op1.value = make_ulonglong(int32(cmd.Op1.value), uint32(cmd.Op1.addr)); #endif return 1; case C_Interface: if ( i == CONSTANT_InterfaceMethodref ) goto methodchk; break; case C_Method: if ( i != CONSTANT_Methodref ) break; methodchk: if ( (cntopis.flag & NORM_METOD) == NORM_METOD ) goto loadref2; //load 3 ind. & xtrn_ref goto wrnret; case C_Type: if ( i != CONSTANT_Class ) break; if ( !(cntopis.flag & HAS_TYPEDSCR) ) goto wrnret; cmd.Op1.addr = ((uint32)fmt_dscr << 16) | (ushort)fmt_classname; goto loadref1; //load 1 ind. case C_TypeName: if ( i != CONSTANT_Class ) break; if ( !(cntopis.flag & (HAS_TYPEDSCR | HAS_CLSNAME)) ) goto wrnret; cmd.Op1.addr = ((uint32)fmt_cast << 16) | (ushort) ((cntopis.flag & HAS_CLSNAME) ? fmt_fullname : fmt_classname); goto loadref1; //load 1 ind. default: warning("Illegal CIC call (%x)\n", ctype); return(0); } dmpchk: if ( !debugmode) return(0 ); ++cmd.Op1.ref; wrnret: ++cmd.Op1.ref; cmd.Op1.addr_shorts.low = cmd.Op1.cp_ind; // for dmp out return(1); }
//---------------------------------------------------------------------- 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); }