update to ida 7.6, add builds

This commit is contained in:
2021-10-31 21:20:46 +02:00
parent e0e0f2be99
commit b1809fe2d9
1408 changed files with 279193 additions and 302468 deletions

View File

@@ -0,0 +1,577 @@
/*
* Interactive disassembler (IDA)
* Copyright (c) 1990-98 by Ilfak Guilfanov.
* E-mail: ig@datarescue.com
* JVM module.
* Copyright (c) 1995-2006 by Iouri Kharon.
* E-mail: yjh@styx.cabel.net
*
* ALL RIGHTS RESERVED.
*
*/
#include "java.hpp"
//----------------------------------------------------------------------
int java_t::LoadIndex(insn_t &insn)
{
ushort top;
insn.Op1.type = o_mem;
// insn.Op1.ref = 0;
insn.Op1.offb = char(insn.size);
top = insn.wid ? insn.get_next_word() : insn.get_next_byte();
insn.Op1.addr = top;
if ( ((insn.Op1.dtype == dt_qword || insn.Op1.dtype == dt_double) && !++top)
|| top >= curSeg.DataSize )
{
if ( !debugmode )
return 0;
++insn.Op1.ref;
}
return 1;
}
//----------------------------------------------------------------------
void copy_const_to_opnd(op_t &x, const const_desc_t &co)
{
x.addr = co.value2;
x.value = co.value;
#ifdef __EA64__
// in 64-bit version of IDA the 'value' field is 64bit, so copy the value
// there
x.value = make_ulonglong((uint32)x.value, (uint32)x.addr);
#endif
}
//----------------------------------------------------------------------
int java_t::ConstLoad(insn_t &insn, CIC_param ctype)
{
const_desc_t cntopis;
insn.Op1.type = o_cpool;
// insn.Op1.ref = 0;
if ( !insn.Op1.cp_ind )
goto dmpchk; // NULL Ptr
if ( !LoadOpis(lm_normal, insn.Op1.cp_ind, 0, &cntopis) )
goto dmpchk;
CASSERT(offsetof(const_desc_t,flag) == (offsetof(const_desc_t,type) + sizeof(uchar) )
&& (sizeof(cntopis.type) == sizeof(uchar))
&& (sizeof(cntopis.flag) == sizeof(uchar))
&& (sizeof(insn.Op1.cp_type) >= (2*sizeof(uchar)))
&& (sizeof(ushort) == sizeof(insn.Op1.cp_type)));
insn.Op1.cp_type = *((ushort *)&cntopis.type);
switch ( ctype )
{
case C_Class:
if ( cntopis.type != CONSTANT_Class )
break;
// no break
case C_4byte: // ldc/ldcw
switch ( cntopis.type )
{
case CONSTANT_Class:
if ( !(cntopis.flag & HAS_CLSNAME) )
goto wrnret;
insn.Op1.addr = 0x10001ul * (ushort)fmt_fullname;
loadref1:
insn.xtrn_ip = cntopis.ref_ip;
// no break
case CONSTANT_Integer:
case CONSTANT_Float:
case CONSTANT_String:
insn.Op1.value = cntopis.value; // for string index to Utf8
return 1; // or TWO index for other
default:
break;
}
break;
case C_8byte:
if ( cntopis.type == CONSTANT_Long || cntopis.type == CONSTANT_Double )
goto load2;
break;
case C_Field:
if ( cntopis.type != CONSTANT_Fieldref )
break;
if ( (cntopis.flag & NORM_FIELD) != NORM_FIELD )
goto wrnret;
loadref2:
insn.xtrn_ip = cntopis.ref_ip;
load2:
copy_const_to_opnd(insn.Op1, cntopis); // for string index to Utf8
return 1;
case C_Interface:
if ( cntopis.type == CONSTANT_InterfaceMethodref )
goto methodchk;
break;
case C_Method:
if ( cntopis.type != CONSTANT_Methodref )
break;
methodchk:
if ( (cntopis.flag & NORM_METOD) == NORM_METOD )
goto loadref2; // load 3 ind. & xtrn_ref
goto wrnret;
case C_CallSite:
if ( cntopis.type != CONSTANT_InvokeDynamic )
break;
goto wrnret;
case C_Type:
if ( cntopis.type != CONSTANT_Class )
break;
if ( !(cntopis.flag & HAS_TYPEDSCR) )
goto wrnret;
insn.Op1.addr = ((uint32)fmt_FieldDescriptor << 16) | (ushort)fmt_ClassName;
goto loadref1; // load 1 ind.
case C_TypeName:
if ( cntopis.type != CONSTANT_Class )
break;
if ( !(cntopis.flag & (HAS_TYPEDSCR | HAS_CLSNAME)) )
goto wrnret;
insn.Op1.addr = ((uint32)fmt_ClassName_or_Array << 16)
| (ushort)((cntopis.flag & HAS_CLSNAME)
? fmt_fullname
: fmt_ClassName);
goto loadref1; // load 1 ind.
default:
warning("Illegal CIC call (%x)", ctype);
return 0;
}
dmpchk:
if ( !debugmode )
return 0;
++insn.Op1.ref;
wrnret:
++insn.Op1.ref;
insn.Op1.addr_shorts.low = insn.Op1.cp_ind; // for dmp out
return 1;
}
//----------------------------------------------------------------------
int java_t::ana(insn_t *_insn)
{
insn_t &insn = *_insn;
CIC_param ctype;
segment_t *s = getMySeg(insn.ea); // also set curSeg
if ( s->type != SEG_CODE || insn.ip >= curSeg.CodeSize )
{
warning("Can't decode non-code fragment!");
return 0;
}
insn.Op1.dtype = dt_void;
insn.wid = insn.swit = 0;
insn.Op1.ref = 0;
insn.itype = insn.get_next_byte();
if ( insn.itype == j_wide )
{
insn.itype = insn.get_next_byte();
if ( insn.itype == j_iinc
|| (insn.itype >= j_iload && insn.itype <= j_aload)
|| (insn.itype >= j_istore && insn.itype <= j_astore)
|| insn.itype == j_ret )
{
insn.wid = 1; // _w
}
else
{
if ( !debugmode )
return 0;
insn.size = 1;
insn.itype = j_wide;
}
}
if ( insn.itype >= j_lastnorm )
{
if ( !debugmode )
return 0;
if ( insn.itype < j_quick_last )
{
static const uchar redefcmd[j_quick_last - j_lastnorm] =
{
j_ldc, // j_ldc_quick
j_ldcw, // j_ldcw_quick
j_ldc2w, // j_ldc2w_quick
j_getfield, // j_getfield_quick
j_putfield, // j_putfield_quick
j_getfield, // j_getfield2_quick
j_putfield, // j_putfield2_quick
j_getstatic, // j_getstatic_quick
j_putstatic, // j_putstatic_quick
j_getstatic, // j_getstatic2_quick
j_putstatic, // j_putstatic2_quick
j_invokevirtual, // j_invokevirtual_quick
j_invokespecial, // j_invokenonvirtual_quick
j_a_invokesuper, // j_invokesuper_quick
j_invokestatic, // j_invokestatic_quick
j_invokeinterface, // j_invokeinterface_quick
j_a_invokevirtualobject, // j_invokevirtualobject_quick
j_a_invokeignored, // j_invokeignored_quick
j_new, // j_new_quick
j_anewarray, // j_anewarray_quick
j_multianewarray, // j_multianewarray_quick
j_checkcast, // j_checkcast_quick
j_instanceof, // j_instanceof_quick
j_invokevirtual, // j_invokevirtual_quick_w
j_getfield, // j_getfield_quick_w
j_putfield // j_putfield_quick_w
};
insn.wid = 2; // _quick;
switch ( insn.itype )
{
case j_getstatic2_quick:
case j_putstatic2_quick:
case j_getfield2_quick:
case j_putfield2_quick:
insn.wid = 3; // 2_quick
break;
case j_invokevirtual_quick_w:
case j_getfield_quick_w:
case j_putfield_quick_w:
insn.wid = 4; // _quick_w
break;
default:
break;
}
insn.itype = redefcmd[insn.itype - j_lastnorm];
}
else if ( insn.itype < j_software )
{
return 0;
}
else
{
insn.itype -= (j_software - j_a_software);
}
}
//---
switch ( insn.itype )
{
default:
{
uint refs, ref2f;
if ( insn.itype >= j_iload_0 && insn.itype <= j_aload_3 )
{
refs = (insn.itype - j_iload_0) % 4;
ref2f = (insn.itype - j_iload_0) / 4;
ref2f = ref2f == ((j_lload_0 - j_iload_0) / 4)
|| ref2f == ((j_dload_0 - j_iload_0) / 4);
goto refer;
}
if ( insn.itype >= j_istore_0 && insn.itype <= j_astore_3 )
{
refs = (insn.itype - j_istore_0) % 4;
ref2f = (insn.itype - j_istore_0) / 4;
ref2f = ref2f == ((j_lstore_0 - j_istore_0) / 4)
|| ref2f == ((j_dstore_0 - j_istore_0) / 4);
refer:
insn.Op1.addr = curSeg.DataBase + (ushort)refs;
insn.Op1.ref = (uchar)(ref2f + 1);
if ( (ushort)(refs + ref2f) >= curSeg.DataSize )
insn.Op1.ref |= 0x80;
break;
}
} // end refs/refx
if ( insn.itype < j_ifeq || insn.itype > j_jsr )
break;
case j_ifnull:
case j_ifnonnull:
insn.Op1.addr = (short)insn.get_next_word();
b_near:
insn.Op1.type = o_near;
insn.Op1.offb = 1;
insn.Op1.addr += insn.ip;
if ( insn.Op1.addr >= curSeg.CodeSize )
goto set_bad_ref;
break;
case j_goto_w:
case j_jsr_w:
insn.Op1.addr = insn.get_next_dword();
goto b_near;
case j_bipush:
insn.Op1.dtype = dt_byte;
insn.Op1.value = (char)insn.get_next_byte();
goto setdat;
case j_sipush:
insn.Op1.dtype = dt_word;
insn.Op1.value = (short)insn.get_next_word();
setdat:
insn.Op1.type = o_imm;
insn.Op1.offb = 1;
break;
case j_ldc:
insn.Op1.cp_ind = insn.get_next_byte();
ctype = C_4byte;
goto constchk;
case j_ldcw:
ctype = C_4byte;
goto const2w;
case j_ldc2w:
ctype = C_8byte;
const2w:
insn.Op1.cp_ind = insn.get_next_word();
constchk:
if ( !ConstLoad(insn, ctype) )
return 0;
break;
case j_getstatic:
case j_putstatic:
case j_getfield:
case j_putfield:
if ( insn.wid > 1 ) // _quick form
{
insn.Op1.type = o_imm;
insn.Op1.ref = 2; // #data
insn.Op1.offb = 1;
if ( insn.wid == 4 )
{
insn.Op1.dtype = dt_word;
insn.Op1.value = insn.get_next_word();
}
else
{
insn.Op1.dtype = dt_byte;
insn.Op1.value = insn.get_next_byte();
++insn.size; // SKIP
}
break;
}
ctype = C_Field;
goto const2w;
case j_new:
ctype = C_Class;
goto const2w;
case j_anewarray:
//\\ ?/
case j_checkcast:
case j_instanceof:
ctype = C_TypeName;
goto const2w;
case j_a_invokesuper:
case j_a_invokeignored:
goto fictarg;
case j_invokevirtual:
case j_a_invokevirtualobject:
insn.Op2.dtype = dt_void;
if ( insn.wid > 1 )
{
if ( insn.wid == 4 )
{
fictarg:
insn.Op1.value = insn.get_next_word(); //???
insn.Op1.dtype = dt_word;
}
else
{
insn.Op2.type = o_imm;
insn.Op1.ref = 2; // #data
insn.Op1.dtype = insn.Op2.dtype = dt_byte;
insn.Op1.value = insn.get_next_byte();
insn.Op2.offb = 2;
insn.Op2.value = insn.get_next_byte();
}
insn.Op1.offb = 1;
insn.Op1.type = o_imm;
insn.Op1.ref = 2; // #data
break;
}
// fallthrough
case j_invokespecial:
case j_invokestatic:
ctype = C_Method;
goto const2w;
case j_invokedynamic:
ctype = C_CallSite;
insn.Op1.cp_ind = insn.get_next_word();
if ( !ConstLoad(insn, ctype) )
return 0;
insn.get_next_word(); // eat two mandatory 0's
insn.Op1.ref = 0;
break;
case j_invokeinterface:
ctype = C_Interface;
insn.Op1.cp_ind = insn.get_next_word();
insn.Op2.type = o_imm;
insn.Op2.ref = 1; // not descriptor
insn.Op2.dtype = dt_byte;
insn.Op2.value = insn.get_next_byte();
if ( insn.wid > 1 )
{
insn.Op3.type = o_imm;
insn.Op3.ref = 2; // #data
insn.Op3.value = insn.get_next_byte();
insn.Op3.offb = 4;
insn.Op3.dtype = dt_byte;
}
else
{
++insn.size; // reserved
insn.Op3.dtype = dt_void;
}
goto constchk;
case j_multianewarray:
insn.Op1.cp_ind = insn.get_next_word();
insn.Op2.type = o_imm;
insn.Op2.ref = 1; // not descriptor
insn.Op2.dtype = dt_byte;
insn.Op2.value = insn.get_next_byte();
if ( insn.Op2.value == 0 && !debugmode )
return 0;
ctype = C_Type;
goto constchk;
case j_iinc:
case j_iload:
case j_istore:
insn.Op1.dtype = dt_dword;
goto memref;
case j_lload:
case j_lstore:
insn.Op1.dtype = dt_qword;
goto memref;
case j_fload:
case j_fstore:
insn.Op1.dtype = dt_float;
goto memref;
case j_dload:
case j_dstore:
insn.Op1.dtype = dt_double;
goto memref;
case j_aload:
case j_astore:
insn.Op1.dtype = dt_string;
goto memref;
case j_ret:
insn.Op1.dtype = dt_code;
memref:
if ( !LoadIndex(insn) )
return 0;
if ( insn.itype == j_iinc )
{
insn.Op2.type = o_imm;
insn.Op2.ref = 0;
insn.Op2.offb = (uchar)insn.size;
if ( insn.wid )
{
insn.Op2.dtype = dt_word;
insn.Op2.value = (short)insn.get_next_word();
}
else
{
insn.Op2.dtype = dt_byte;
insn.Op2.value = (char)insn.get_next_byte();
}
}
break;
case j_tableswitch:
case j_lookupswitch:
{
int32 count;
uint32 top;
insn.swit = 1;
for ( top = (4 - uint32((insn.ip + insn.size) % 4)) & 3; top; top-- )
{
if ( insn.get_next_byte() )
{
if ( !debugmode )
return 0;
insn.swit |= 0100;
}
}
insn.Op3.type = o_near;
insn.Op3.offb = (uchar)insn.size;
insn.Op3.addr = insn.get_next_dword();
insn.Op3.addr += insn.ip;
insn.Op3.ref = 0;
if ( insn.Op3.addr >= curSeg.CodeSize )
{
if ( !debugmode )
return 0;
++insn.Op3.ref;
}
insn.swit |= 2; // start out arguments
count = insn.get_next_dword();
if ( insn.itype == j_tableswitch )
{
insn.Op1.type = o_imm;
insn.Op1.dtype = dt_dword;
insn.Op1.value = count; // minimal value
insn.Op2.ref = 0;
insn.Op2.type = o_imm;
insn.Op2.dtype = dt_dword;
count = (uint32(insn.Op2.value = insn.get_next_dword()) - count + 1);
}
insn.Op3.value = count;
insn.Op2.addr = insn.ip + insn.size;
top = uint32(curSeg.CodeSize - insn.ip);
while ( count-- )
{
if ( insn.itype == j_lookupswitch )
insn.get_next_dword(); // skip pairs;
if ( (insn.ip + insn.get_next_dword()) >= curSeg.CodeSize )
{
if ( !debugmode )
return 0;
insn.swit |= 0200;
}
if ( (uint32)insn.size >= top )
return 0;
}
}
break;
case j_newarray:
insn.Op1.type = o_array; // type!
insn.Op1.offb = 1;
insn.Op1.cp_type = insn.get_next_byte();
if ( insn.Op1.cp_type < T_BOOLEAN || (uchar)insn.Op1.cp_type > T_LONG )
{
set_bad_ref:
if ( !debugmode )
return 0;
++insn.Op1.ref;
}
break;
} // switch ( insn.itype )
return insn.size;
}
//----------------------------------------------------------------------
bool idaapi can_have_type(const op_t &x)
{
if ( x.type == o_cpool )
return (uchar)x.cp_type == CONSTANT_Integer
|| (uchar)x.cp_type == CONSTANT_Long;
return x.type == o_imm;
}

View File

@@ -0,0 +1,212 @@
/*
* Interactive disassembler (IDA)
* Copyright (c) 1990-98 by Ilfak Guilfanov.
* E-mail: ig@datarescue.com
* JVM module.
* Copyright (c) 1995-2006 by Iouri Kharon.
* E-mail: yjh@styx.cabel.net
*
* ALL RIGHTS RESERVED.
*
*/
#ifndef _CLASSFIL_HPP_
#define _CLASSFIL_HPP_
//
// Java File definition
//
#define MAGICNUMBER 0xcafebabeUL // magic number
// Oracle's Java Virtual Machine implementation in JDK release 1.0.2
// supports class file format versions 45.0 through 45.3 inclusive. JDK
// releases 1.1.* support class file format versions in the range 45.0
// through 45.65535 inclusive. For k >= 2, JDK release 1.k supports class
// file format versions in the range 45.0 through 44+k.0 inclusive.
#define JDK_1_02_MINOR 2 // (45.2) JDK1.0
#define JDK_1_1_MINOR 3 // (45.3) JDK1.1
#define JDK_MIN_MAJOR 45 // JDK1.0/JDK1.1
#define JDK_MAX_MAJOR (44+11)// JDK1.11(JDK11): Java11?
//
// access_flags
//
#define ACC_PUBLIC 0x0001 // Visible to everyone
#define ACC_PRIVATE 0x0002 // Visible only to the defning
#define ACC_PROTECTED 0x0004 // Visible to subclasses
#define ACC_STATIC 0x0008 // Variable or method is static Method
#define ACC_FINAL 0x0010 // No further subclassing, overriding, or
// assignment after initialization
#define ACC_SYNCHRONIZED 0x0020 // Wrap use in monitor lock
#define ACC_SUPER 0x0020 // invoke by the 'invokespecial' (deprecated)
#define ACC_VOLATILE 0x0040 // Can't cache (field)
#define ACC_BRIDGE 0x0040 // Bridge method (java5) (generate by compiler)
#define ACC_TRANSIENT 0x0080 // Not to be written or read by
// a persistent object manager (field)
#define ACC_VARARGS 0x0080 // Method with variable number of arguments
// (java5)
#define ACC_NATIVE 0x0100 // Implemented in a language otherthan Java
#define ACC_INTERFACE 0x0200 // Is an interface
#define ACC_ABSTRACT 0x0400 // No body provided
#define ACC_STRICT 0x0800 // Delcared strictfp (floating-point mode
// is FP-strict) (method)
#define ACC_SYNTHETIC 0x1000 // Generate by compiler (no present in source)
// (java2)
#define ACC_ANNOTATION 0x2000 // only with INTERFACE (annotated) (java5)
#define ACC_ENUM 0x4000 // Class or BaseClass is enum (java5)
/* jdk1.5
ACC_BRIDGE, ACC_VARARGS, ACC_STRICT, ACC_SYNTHETIC, ACC_ANNOTATION, ACC_ENUM
*/
//
#define ACC_ACCESS_MASK (ACC_PUBLIC | ACC_PROTECTED | ACC_PRIVATE)
#define _ACC_ALLTP (ACC_ACCESS_MASK | ACC_STATIC | ACC_FINAL \
| ACC_SYNTHETIC)
#define ACC_THIS_MASK (ACC_PUBLIC | ACC_FINAL | ACC_SUPER | ACC_INTERFACE \
| ACC_ABSTRACT | ACC_SYNTHETIC | ACC_ANNOTATION \
| ACC_ENUM)
#define ACC_NESTED_MASK (_ACC_ALLTP | ACC_INTERFACE | ACC_ABSTRACT \
| ACC_ANNOTATION | ACC_ENUM)
#define ACC_FIELD_MASK (_ACC_ALLTP | ACC_VOLATILE | ACC_TRANSIENT | ACC_ENUM)
#define ACC_METHOD_MASK (_ACC_ALLTP | ACC_SYNCHRONIZED | ACC_BRIDGE \
| ACC_VARARGS | ACC_NATIVE | ACC_ABSTRACT \
| ACC_STRICT)
//-----------------------------------
// base type
//
#define j_byte 'B' // signed byte
#define j_char 'C' // unicode character
#define j_double 'D' // double precision IEEE float
#define j_float 'F' // single precision IEEE foat
#define j_int 'I' // integer
#define j_long 'J' // long integer
#define j_class 'L' // <fullclassname>;
// ... an object of the given class
#define j_endclass ';' // tag for end of classname
#define j_parm_list_start '(' // start of function parameters
#define j_parm_list_end ')' // end of function parameters
#define j_short 'S' // signed short
#define j_bool 'Z' // boolean true or false
#define j_array '[' // <length><field sig> ... array
#define j_void_ret 'V' // return no value
//----------- make as mnemonic in new version
#define j_field_dlm '.' // use as field delimiter
#define j_clspath_dlm '/' // use as classpath delimeter
//#define j_legacy_dlm '$' // mechanically generated & legacy systems
//----------- jdk1.5
// signatures
#define j_typeref 'T' // TypeVariable signature
#define j_throw '^' // ThrowsSignature start
#define j_wild '*' // wildcard(unknown) <?>
#define j_wild_e '+' // wildcard(extends) <+name>
#define j_wild_s '-' // wildcard(super) <-name>
// type declaration syntax: <name:typesign>
// iface declaration syntax: <name:typesign:ifacesign>
// super declaration syntax:
#define j_sign '<' // formal type parameter start
#define j_endsign '>' // formal type parameter end
#define j_tag ':' // delimeter
// annotation tags
// possible const types is: B, C, D, F, I, J, S, Z, [
// additional annotation tag types
#define j_string 's' // constant string
#define j_enumconst 'e' // enum (type + name)
#define j_class_ret 'c' // return type descriptor
#define j_annotation '@' // nested annotation
//-----------------------------------------------------
// Constant Pool
//
#define CONSTANT_Asciz 1 // jdk1.1
#define CONSTANT_Utf8 1 // jdk1.x
#define CONSTANT_Unicode 2 // unused if jdk >= 1.0 (45.2)
#define CONSTANT_Integer 3
#define CONSTANT_Float 4
#define CONSTANT_Long 5
#define CONSTANT_Double 6
#define CONSTANT_Class 7
#define CONSTANT_String 8
#define CONSTANT_Fieldref 9
#define CONSTANT_Methodref 10
#define CONSTANT_InterfaceMethodref 11
#define CONSTANT_NameAndType 12
#define MAX_CONSTANT_TYPE 12 // Check in Loader flag
// JDK1.7 (JSR 292) -- dynamic for multiLanguage (python, ruby, etc)
#define CONSTANT_MethodHandle 15
#define CONSTANT_MethodType 16
// JDK 1.8
#define CONSTANT_InvokeDynamic 18
#define CONSTANT_LAST CONSTANT_InvokeDynamic
// JVM_CONSTANT_MethodHandle subtypes
#define JVM_REF_getField 1
#define JVM_REF_getStatic 2
#define JVM_REF_putField 3
#define JVM_REF_putStatic 4
#define JVM_REF_invokeVirtual 5
#define JVM_REF_invokeStatic 6
#define JVM_REF_invokeSpecial 7
#define JVM_REF_newInvokeSpecial 8
#define JVM_REF_invokeInterface 9
//-------------------------------------------------------
// Array Type (newarray)
//
#define T_BOOLEAN 4
#define T_CHAR 5
#define T_FLOAT 6
#define T_DOUBLE 7
#define T_BYTE 8
#define T_SHORT 9
#define T_INT 10
#define T_LONG 11
//--------------------------------------------------------
// StackMapTable records
#define JDK_SMF_MAJOR_MIN 50 // minimal version (previous: CLDC)
// offset for record 0 == offset, else previous_offset + offset + 1;
#define SMT_SAME_FRM_S0_min 0 // off_dt=type, loc=prev, stack=empty
#define SMT_SAME_FRM_S0_max 63
#define SMT_SAME_FRM_S1_min 64 // off_dt=type-min, loc=prev, stack=1
#define SMT_SAME_FRM_S1_max 127 // [ + verinf[1] ]
#define SMT_reserved_min 128
#define SMT_reserved_max 246
#define SMT_SAME_FRM_S1 247 // loc=prev, stack=1 [ + off_d, verinf[1] ]
#define SMT_CHOP_FRM_S0_min 248 // stack=empty, loc=prev-((max+1)-type)
#define SMT_CHOP_FRM_S0_max 250 // [ + off_dt ]
#define SMT_SAME_FRM_S0 251 // stack=empty, loca=prev [ + off_dt ]
#define SMT_APPE_FRM_S0_min 252 // stack=empty, loc+=prev+(type-(min-1))
#define SMT_APPE_FRM_S0_max 254 // [ + off_dt, { verinf[n] } ]
#define SMT_FULL_FRAME 255 // see below
/*
struct sm_full
{
u1 type; // for JDK16 or higher
u2 off_dt; // for StackMap - off
u2 nloc;
verinf locs[nlocks];
u2 nstk;
verinf stks[nstk];
};
*/
// Initial stack map frame: off=0, stack is free, max_locals, max_stack;
// StackMap types
enum SM_ITEM // u1
{
ITEM_Bogus = 0, // unused (unknown type -- can't used directly)
ITEM_Integer,
ITEM_Float,
ITEM_Double,
ITEM_Long,
ITEM_Null,
ITEM_UnitializedThis,
ITEM_Object, // +pool_index
ITEM_Uninitialized, // +offset (u2)
// additional for out
ITEM_BADOBJECT,
ITEM_CURCLASS
};
#endif

View File

@@ -0,0 +1,316 @@
/*
* Interactive disassembler (IDA)
* Copyright (c) 1990-98 by Ilfak Guilfanov.
* E-mail: ig@datarescue.com
* JVM module.
* Copyright (c) 1995-2006 by Iouri Kharon.
* E-mail: yjh@styx.cabel.net
*
* ALL RIGHTS RESERVED.
*
*/
#include "java.hpp"
static const char badlocvar[] = "Invalid local variable number";
//----------------------------------------------------------------------
uval_t java_t::SearchFM(ushort name, ushort dscr, char *naprN)
{
char buf[(qmax(sizeof(FieldInfo), sizeof(SegInfo))+1+3)&~3];
sval_t pos = curClass.FieldCnt;
uint32 csz = sizeof(FieldInfo);
sval_t napr = *naprN;
if ( napr != 1 )
{
if ( napr != -1 )
INTERNAL("SearchFM");
pos = -(uval_t)curClass.MethodCnt;
csz = sizeof(SegInfo);
}
void *p = buf;
for ( ; pos; pos -= napr )
{
if ( ClassNode.supval(pos, p, sizeof(buf)) != csz )
DESTROYED("SearchFM");
if ( ((_FMid_ *)p)->extflg & EFL_NAMETYPE
|| CmpString(name, ((_FMid_ *)p)->name)
|| CmpString(dscr, ((_FMid_ *)p)->dscr) )
{
continue;
}
if ( napr >= 0 )
return curClass.start_ea + ((FieldInfo *)p)->id.Number;
if ( ((SegInfo *)p)->CodeSize )
*naprN = 0;
return ((SegInfo *)p)->start_ea;
}
return BADADDR;
}
//------------------------------------------------------------------------
void java_t::mark_and_comment(ea_t ea, const char *cmt) const
{
remember_problem(PR_ATTN, ea);
if ( *cmt && (!has_cmt(get_flags(ea)) || ea == curClass.start_ea) )
append_cmt(ea, cmt, false);
}
//------------------------------------------------------------------------
void java_t::TouchArg(const insn_t &insn, const op_t &x, bool isload)
{
const char *p;
switch ( x.type )
{
case o_void: // not operand
break;
case o_cpool: // ConstantPool reference (index)
if ( x.ref )
{
p = x.ref == 1
? "Invalid string in constant pool"
: "Invalid index in constant pool";
goto mark;
}
if ( x.cp_ind )
{
ea_t ea;
char npr = -1;
switch ( (uchar)x.cp_type )
{
case CONSTANT_Fieldref:
npr = 1;
// fallthrough
case CONSTANT_InterfaceMethodref:
case CONSTANT_Methodref:
if ( !(x._subnam | x._name | x._class) )
break;
if ( x._class == curClass.This.Dscr )
{
ea = SearchFM(x._subnam, x._dscr, &npr);
if ( ea == BADADDR )
break;
}
else
{
if ( !insn.xtrn_ip )
break;
ea = insn.xtrn_ip == 0xFFFF
? curClass.start_ea
: curClass.xtrnEA + insn.xtrn_ip;
if ( npr < 0 )
npr = 0;
}
if ( npr <= 0 )
{
insn.add_cref(ea, x.offb, fl_CF);
if ( !npr )
auto_cancel(ea, ea+1);
}
else
{
dref_t type = insn.itype == j_putstatic || insn.itype == j_putfield
? dr_W
: dr_R;
insn.add_dref(ea, x.offb, type);
}
break;
case CONSTANT_Class:
if ( insn.xtrn_ip )
{
ea_t target = insn.xtrn_ip == 0xFFFF
? curClass.start_ea
: curClass.xtrnEA + insn.xtrn_ip;
insn.add_dref(target, x.offb, dr_I);
}
break;
default:
break;
}
}
break;
case o_array: // type!
if ( x.ref )
{
p = "Invalid array type";
goto mark;
}
break;
case o_imm: // const (& #data)
if ( x.ref < 2 )
set_immd(insn.ea);
break;
case o_mem: // local data pool
if ( x.ref )
{
p = badlocvar;
mark:
mark_and_comment(insn.ea, p);
}
else
{
dref_t ref = isload ? dr_R : dr_W;
ea_t adr = curSeg.DataBase + x.addr;
insn.add_dref(adr, x.offb, ref);
if ( (x.dtype == dt_qword || x.dtype == dt_double)
&& get_item_size(adr) <= 1 )
{
insn.add_dref(adr + 1, x.offb, ref);
}
}
break;
case o_near:
if ( x.ref )
{
p = "Invalid jump address";
goto mark;
}
insn.add_cref(
curSeg.start_ea + x.addr,
x.offb,
(Feature & CF_CALL) != 0 ? fl_CN : fl_JN);
break;
default:
warning("%a: %s,%d: bad optype %d", insn.ea, insn.get_canon_mnem(ph), x.n,
x.type);
break;
}
}
//----------------------------------------------------------------------
int java_t::emu(const insn_t &insn)
{
Feature = insn.get_canon_feature(ph);
if ( insn.wid > 1 )
mark_and_comment(insn.ea, "Limited usage instruction");
if ( insn.itype >= j_a_software )
mark_and_comment(insn.ea, "Undocumented instruction");
if ( insn.Op1.type == o_void && insn.Op1.ref )
{
if ( (char)insn.Op1.ref < 0 )
{
mark_and_comment(insn.ea, badlocvar);
}
else
{
dref_t ref = (insn.itype >= j_istore_0) ? dr_W : dr_R;
insn.add_dref(insn.Op1.addr, 0, ref);
if ( (insn.Op1.ref & 2) && get_item_size(insn.Op1.addr) <= 1 )
insn.add_dref(insn.Op1.addr + 1, 0, ref);
}
}
if ( Feature & CF_USE1 )
TouchArg(insn, insn.Op1, true);
if ( Feature & CF_USE2 )
TouchArg(insn, insn.Op2, true);
if ( Feature & CF_USE3 )
TouchArg(insn, insn.Op3, true);
if ( Feature & CF_CHG1 )
TouchArg(insn, insn.Op1, false);
if ( insn.swit ) // tableswitch OR lookupswitch
{
uval_t count, addr, rnum;
if ( insn.swit & 0200 )
mark_and_comment(insn.ea, badlocvar);
if ( insn.swit & 0100 )
mark_and_comment(insn.ea, "Nonzero filler (warning)");
rnum = insn.Op2.value - 1; // for lookupswtitch
for ( addr=insn.Op2.addr, count=insn.Op3.value; count; addr +=4, count-- )
{
uval_t refa;
if ( insn.itype != j_lookupswitch )
{
++rnum;
}
else
{
rnum = get_dword(curSeg.start_ea + addr); // skip pairs
addr += 4;
}
refa = insn.ip + get_dword(curSeg.start_ea + addr);
if ( refa < curSeg.CodeSize )
{
add_cref(insn.ea, (refa += curSeg.start_ea), fl_JN);
if ( !has_cmt(get_flags(refa)) )
{
char str[32];
qsnprintf(str, sizeof(str), "case %" FMT_EA "u", rnum);
set_cmt(refa, str, false);
}
}
}
}
if ( !(Feature&CF_STOP) && (!(Feature&CF_CALL) || func_does_return(insn.ea)) )
add_cref(insn.ea, insn.ea + insn.size, fl_F);
return 1;
}
//----------------------------------------------------------------------
size_t java_t::make_locvar_cmt(qstring *buf, const insn_t &insn)
{
LocVar lv;
if ( curSeg.varNode )
{
const char *p = NULL;
uval_t idx = insn.Op1.addr;
if ( insn.Op1.type == o_mem )
{
if ( !insn.Op1.ref )
{
switch ( insn.itype )
{
case j_ret:
p = "Return";
break;
case j_iinc:
p = "Add 8-bit signed const to";
break;
default:
p = "Push";
if ( insn.get_canon_feature(ph) & CF_CHG1 )
p = "Pop";
break;
}
}
}
else if ( insn.Op1.type == o_void
&& (char)insn.Op1.ref >= 0
&& (int32)(idx -= curSeg.DataBase) >= 0 )
{
p = "Push";
if ( insn.itype >= j_istore_0 )
p = "Pop";
}
if ( p != NULL && netnode(curSeg.varNode).supval(idx,&lv,sizeof(lv)) == sizeof(lv) )
{
if ( fmtName(lv.var.Name, tmp_name, sizeof(tmp_name), fmt_UnqualifiedName) )
return buf->sprnt("%s %s", p, tmp_name).length();
}
}
return 0;
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,235 @@
/*
* Interactive disassembler (IDA)
* Copyright (c) 1990-98 by Ilfak Guilfanov.
* E-mail: ig@datarescue.com
* JVM module.
* Copyright (c) 1995-2006 by Iouri Kharon.
* E-mail: yjh@styx.cabel.net
*
* ALL RIGHTS RESERVED.
*
*/
#include <ida.hpp>
#include <idp.hpp>
#include "ins.hpp"
// ATTENTION: if change mnemonic(s) change version in 'jas_rw.cc'
const instruc_t Instructions[] =
{
{ "nop", 0 }, // Do nothing
{ "aconst_null", 0 }, // Push null object reference
{ "iconst_m1", 0 }, // Push integer constant -1
{ "iconst_0", 0 }, // Push the integer 0
{ "iconst_1", 0 }, // Push the integer 1
{ "iconst_2", 0 }, // Push the integer 2
{ "iconst_3", 0 }, // Push the integer 3
{ "iconst_4", 0 }, // Push the integer 4
{ "iconst_5", 0 }, // Push the integer 5
{ "lconst_0", 0 }, // Push the long integer 0
{ "lconst_1", 0 }, // Push the long integer 1
{ "fconst_0", 0 }, // Push the single-precision foating point 0.0
{ "fconst_1", 0 }, // Push the single-precision foating point 1.0
{ "fconst_2", 0 }, // Push the single-precision foating point 2.0
{ "dconst_0", 0 }, // Push the double-precision foating point 0.0
{ "dconst_1", 0 }, // Push the double-precision foating point 1.0
{ "bipush", CF_USE1 }, // Push one-byte integer
{ "sipush", CF_USE1 }, // Push two-byte integer
{ "ldc", CF_USE1 }, // Push item from constant pool (i1)
{ "ldc_w", CF_USE1 }, // Push item from constant pool (i2)
{ "ldc2_w", CF_USE1 }, // Push long or double from constant pool
{ "iload", CF_USE1 }, // Push integer value of the local variable
{ "lload", CF_USE1 }, // Push long value of the local variable
{ "fload", CF_USE1 }, // Push single-float. val. of the local variable
{ "dload", CF_USE1 }, // Push double-float. val. of the local variable
{ "aload", CF_USE1 }, // Push object reference from the local variable
{ "iload_0", 0 }, // Push integer value of the local variable #0
{ "iload_1", 0 }, // Push integer value of the local variable #1
{ "iload_2", 0 }, // Push integer value of the local variable #2
{ "iload_3", 0 }, // Push integer value of the local variable #3
{ "lload_0", 0 }, // Push long value of the local variable #0
{ "lload_1", 0 }, // Push long value of the local variable #1
{ "lload_2", 0 }, // Push long value of the local variable #2
{ "lload_3", 0 }, // Push long value of the local variable #3
{ "fload_0", 0 }, // Push single-flt. val. of the local variable #0
{ "fload_1", 0 }, // Push single-flt. val. of the local variable #1
{ "fload_2", 0 }, // Push single-flt. val. of the local variable #2
{ "fload_3", 0 }, // Push single-flt. val. of the local variable #3
{ "dload_0", 0 }, // Push double-flt. val. of the local variable #0
{ "dload_1", 0 }, // Push double-flt. val. of the local variable #1
{ "dload_2", 0 }, // Push double-flt. val. of the local variable #2
{ "dload_3", 0 }, // Push double-flt. val. of the local variable #3
{ "aload_0", 0 }, // Push object reference from the local var. #0
{ "aload_1", 0 }, // Push object reference from the local var. #1
{ "aload_2", 0 }, // Push object reference from the local var. #2
{ "aload_3", 0 }, // Push object reference from the local var. #3
{ "iaload", 0 }, // Push integer from array
{ "laload", 0 }, // Push long from array
{ "faload", 0 }, // Push single float from array
{ "daload", 0 }, // Push double float from array
{ "aaload", 0 }, // Push object reference from array
{ "baload", 0 }, // Push signed byte from array
{ "caload", 0 }, // Push signed char from array
{ "saload", 0 }, // Push short from array
{ "istore", CF_CHG1 }, // Pop integer value into local variable
{ "lstore", CF_CHG1 }, // Pop long value into local variable
{ "fstore", CF_CHG1 }, // Pop single float value into local variable
{ "dstore", CF_CHG1 }, // Pop double float value into local variable
{ "astore", CF_CHG1 }, // Pop object refernce into local variable
{ "istore_0", 0 }, // Pop integer value into local variable #0
{ "istore_1", 0 }, // Pop integer value into local variable #1
{ "istore_2", 0 }, // Pop integer value into local variable #2
{ "istore_3", 0 }, // Pop integer value into local variable #3
{ "lstore_0", 0 }, // Pop long value into local variable #0
{ "lstore_1", 0 }, // Pop long value into local variable #1
{ "lstore_2", 0 }, // Pop long value into local variable #2
{ "lstore_3", 0 }, // Pop long value into local variable #3
{ "fstore_0", 0 }, // Pop single float value into local variable #0
{ "fstore_1", 0 }, // Pop single float value into local variable #1
{ "fstore_2", 0 }, // Pop single float value into local variable #2
{ "fstore_3", 0 }, // Pop single float value into local variable #3
{ "dstore_0", 0 }, // Pop doublefloat value into local variable #0
{ "dstore_1", 0 }, // Pop doublefloat value into local variable #1
{ "dstore_2", 0 }, // Pop doublefloat value into local variable #2
{ "dstore_3", 0 }, // Pop doublefloat value into local variable #3
{ "astore_0", 0 }, // Pop object refernce into local variable #0
{ "astore_1", 0 }, // Pop object refernce into local variable #1
{ "astore_2", 0 }, // Pop object refernce into local variable #2
{ "astore_3", 0 }, // Pop object refernce into local variable #3
{ "iastore", 0 }, // Pop integer from array
{ "lastore", 0 }, // Pop long from array
{ "fastore", 0 }, // Pop single float from array
{ "dastore", 0 }, // Pop double float from array
{ "aastore", 0 }, // Pop object reference from array
{ "bastore", 0 }, // Pop signed byte from array
{ "castore", 0 }, // Pop signed char from array
{ "sastore", 0 }, // Pop short from array
{ "pop", 0 }, // Pop top stack word
{ "pop2", 0 }, // Pop top two stack word
{ "dup", 0 }, // Duplicate top stack word
{ "dup_x1", 0 }, // Duplicate top stack word and put two down
{ "dup_x2", 0 }, // Duplicate top stack word and put three down
{ "dup2", 0 }, // Duplicate top two stack word
{ "dup2_x1", 0 }, // Duplicate top two stack words and put two down
{ "dup2_x2", 0 }, // Duplicate top two stack words and put three down
{ "swap", 0 }, // Swap two top stack words
{ "iadd", 0 }, // Integer add
{ "ladd", 0 }, // Long add
{ "fadd", 0 }, // Single float add
{ "dadd", 0 }, // Double float add
{ "isub", 0 }, // Integer subtract
{ "lsub", 0 }, // Long subtract
{ "fsub", 0 }, // Single float subtract
{ "dsub", 0 }, // Double float subtract
{ "imul", 0 }, // Integer multiply
{ "lmul", 0 }, // Long multiply
{ "fmul", 0 }, // Single float multiply
{ "dmul", 0 }, // Double float multiply
{ "idiv", 0 }, // Integer divide
{ "ldiv", 0 }, // Long divide
{ "fdiv", 0 }, // Single float divide
{ "ddiv", 0 }, // Double float divide
{ "irem", 0 }, // Integer remainder
{ "lrem", 0 }, // Long remainder
{ "frem", 0 }, // Single float remainder
{ "drem", 0 }, // Double float remainder
{ "ineg", 0 }, // Integer negate
{ "lneg", 0 }, // Long negate
{ "fneg", 0 }, // Single float negate
{ "dneg", 0 }, // Double float negate
{ "ishl", 0 }, // Integer shift left
{ "lshl", 0 }, // Long shift left
{ "ishr", 0 }, // Integer logical shift right
{ "lshr", 0 }, // Long logical shift right
{ "iushr", 0 }, // Integer arithmetic shift right
{ "lushr", 0 }, // Long arithmeticshift right
{ "iand", 0 }, // Integer boolean AND
{ "land", 0 }, // Long boolean AND
{ "ior", 0 }, // Integer boolean OR
{ "lor", 0 }, // Long boolean OR
{ "ixor", 0 }, // Integer boolean XOR
{ "lxor", 0 }, // Long boolean XOR
{ "iinc", CF_CHG1|CF_USE2 }, // Add 8-bit signed const to local variable
{ "i2l", 0 }, // Integer to Long conversion
{ "i2f", 0 }, // Integer to Single float conversion
{ "i2d", 0 }, // Integer to Double float conversion
{ "l2i", 0 }, // Long to Integer conversion
{ "l2f", 0 }, // Long to Single float conversion
{ "l2d", 0 }, // Long to Double float conversion
{ "f2i", 0 }, // Single float to Integer conversion
{ "f2l", 0 }, // Single float to Long conversion
{ "f2d", 0 }, // Single float to Double float conversion
{ "d2i", 0 }, // Double float to Integer conversion
{ "d2l", 0 }, // Double float to Long conversion
{ "d2f", 0 }, // Double float to Single float conversion
{ "int2byte", 0 }, // Integer to signed byte conversion
{ "int2char", 0 }, // Integer to unsigned short conversion
{ "int2short", 0 }, // Integer to signed short conversion
{ "lcmp", 0 }, // Long compare
{ "fcmpl", 0 }, // Single float compare (-1 on NaN)
{ "fcmpg", 0 }, // Single float compare (1 on NaN)
{ "dcmpl", 0 }, // Double float compare (-1 on NaN)
{ "dcmpg", 0 }, // Double float compare (1 on NaN)
{ "ifeq", CF_USE1 }, // Branch if equal to 0
{ "ifne", CF_USE1 }, // Branch if not equal to 0
{ "iflt", CF_USE1 }, // Branch if less then 0
{ "ifge", CF_USE1 }, // Branch if greater than or equal to 0
{ "ifgt", CF_USE1 }, // Branch if greater than 0
{ "ifle", CF_USE1 }, // Branch if less than or equal to 0
{ "if_icmpeq", CF_USE1 }, // Branch if integers equal
{ "if_icmpne", CF_USE1 }, // Branch if integers not equal
{ "if_icmplt", CF_USE1 }, // Branch if integers less than
{ "if_icmpge", CF_USE1 }, // Branch if integers grater than or equal to
{ "if_icmpgt", CF_USE1 }, // Branch if integers grater than
{ "if_icmple", CF_USE1 }, // Branch if integers less than or equal to
{ "if_acmpeq", CF_USE1 }, // Branch if object references are equal
{ "if_acmpne", CF_USE1 }, // Branch if object references not equal
{ "goto", CF_USE1|CF_STOP }, // Branch always
{ "jsr", CF_USE1|CF_CALL }, // Jump subroutine
{ "ret", CF_USE1|CF_STOP }, // Return from subroutine
{ "tableswitch", CF_USE1|CF_USE2|CF_USE3 }, // Access jump table by index and jump
{ "lookupswitch", CF_USE1|CF_USE2 }, // Access jump table by key match and jump
{ "ireturn", CF_STOP }, // Return integer from function
{ "lreturn", CF_STOP }, // Return long from function
{ "freturn", CF_STOP }, // Return single float from function
{ "dreturn", CF_STOP }, // Return double float from function
{ "areturn", CF_STOP }, // Return object reference from function
{ "return", CF_STOP }, // Return (void) from procedure
{ "getstatic", CF_USE1 }, // Set static field from class
{ "putstatic", CF_USE1 }, // Set static field in class
{ "getfield", CF_USE1 }, // Fetch field from object
{ "putfield", CF_CHG1 }, // Set field in object
{ "invokevirtual", CF_USE1|CF_USE2|CF_CALL }, // invoke instance method
{ "invokespecial", CF_USE1|CF_CALL }, // invoke instance method (super/private/init)
{ "invokestatic", CF_USE1|CF_CALL }, // invoke a class (static) method
{ "invokeinterface", CF_USE1|CF_USE2|CF_USE3|CF_CALL }, // invoke interface method
{ "invokedynamic", CF_USE1|CF_USE2|CF_CALL }, //
{ "new", CF_USE1 }, // Create new object
{ "newarray", CF_USE1 }, // Allocate new array
{ "anewarray", CF_USE1 }, // Allocate new array of references to object
{ "arraylength", 0 }, // Get length of array
{ "athrow", CF_STOP }, // Throw exception or error
{ "checkcast", CF_USE1 }, // Make sure object is of given type
{ "instanceof", CF_USE1 }, // Determine if an object is of given type
{ "monitorenter", 0 }, // Enter monitored region of code
{ "monitorexit", 0 }, // Exit monitored region of code
{ "wide", 0 }, // WIDE PREFIX of Command
{ "multianewarray", CF_USE1|CF_USE2 }, // Allocate new multidimensional array
{ "ifnull", CF_USE1 }, // Branch if NULL-ptr
{ "ifnonnull", CF_USE1 }, // Branch if not NULL-ptr
{ "goto_w", CF_USE1 }, // Branch always (wide index)
{ "jsr_w", CF_USE1 }, // Jump subroutine (wide index)
{ "breakpoint", 0 }, // Stop and pass control to breakpoint handler
//{ "ret_w", CF_USE1 }, // Return from subroutine (wide index)
// Pseudocode for quick
{ "invokesuper", CF_USE1|CF_CALL },
{ "invokevirtualobject", CF_USE1|CF_USE2|CF_CALL },
{ "invokeignored", CF_USE1 },
// SUN-dependet
{ "software", 0 },
{ "hardware", 0 }
};
CASSERT(qnumber(Instructions) == j_last);

View File

@@ -0,0 +1,267 @@
/*
* Interactive disassembler (IDA)
* Copyright (c) 1990-2021 Hex-Rays
* JVM module.
* Copyright (c) 1995-2006 by Iouri Kharon.
* E-mail: yjh@styx.cabel.net
*
* ALL RIGHTS RESERVED.
*
*/
#ifndef __INSTRS_HPP
#define __INSTRS_HPP
extern const instruc_t Instructions[];
enum nameNum ENUM_SIZE(uint16)
{
j_nop = 0, // 0 Do nothing
j_aconst_null, // 1 Push null object reference
j_iconst_m1, // 2 Push integer constant -1
j_iconst_0, // 3 Push the integer 0
j_iconst_1, // 4 Push the integer 1
j_iconst_2, // 5 Push the integer 2
j_iconst_3, // 6 Push the integer 3
j_iconst_4, // 7 Push the integer 4
j_iconst_5, // 8 Push the integer 5
j_lconst_0, // 9 Push the long integer 0
j_lconst_1, // 10 Push the long integer 1
j_fconst_0, // 11 Push the single-precision foating point 0.0
j_fconst_1, // 12 Push the single-precision foating point 1.0
j_fconst_2, // 13 Push the single-precision foating point 2.0
j_dconst_0, // 14 Push the double-precision foating point 2.0
j_dconst_1, // 15 Push the double-precision foating point 2.0
j_bipush, // 16 Push one byte signed integer
j_sipush, // 17 Push two-byte signed integer
j_ldc, // 18 Push item from constant pool (i1)
j_ldcw, // 19 Push item from constant pool (i2)
j_ldc2w, // 20 Push long or double from constant pool
j_iload, // 21 Push integer value of the local variable
j_lload, // 22 Push long value of the local variable
j_fload, // 23 Push single float value of the local variable
j_dload, // 24 Push double float value of the local variable
j_aload, // 25 Push object reference from the local variable
j_iload_0, // 26 Push integer value of the local variable #0
j_iload_1, // 27 Push integer value of the local variable #1
j_iload_2, // 28 Push integer value of the local variable #2
j_iload_3, // 29 Push integer value of the local variable #3
j_lload_0, // 30 Push long value of the local variable #0
j_lload_1, // 31 Push long value of the local variable #1
j_lload_2, // 32 Push long value of the local variable #2
j_lload_3, // 33 Push long value of the local variable #3
j_fload_0, // 34 Push single float value of the local variable #0
j_fload_1, // 35 Push single float value of the local variable #1
j_fload_2, // 36 Push single float value of the local variable #2
j_fload_3, // 37 Push single float value of the local variable #3
j_dload_0, // 38 Push double float value of the local variable #0
j_dload_1, // 39 Push double float value of the local variable #1
j_dload_2, // 40 Push double float value of the local variable #2
j_dload_3, // 41 Push double float value of the local variable #3
j_aload_0, // 42 Push object reference from the local variable #0
j_aload_1, // 43 Push object reference from the local variable #1
j_aload_2, // 44 Push object reference from the local variable #2
j_aload_3, // 45 Push object reference from the local variable #3
j_iaload, // 46 Push integer from array
j_laload, // 47 Push long from array
j_faload, // 48 Push single float from array
j_daload, // 49 Push double float from array
j_aaload, // 50 Push object refernce from array
j_baload, // 51 Push signed byte from array
j_caload, // 52 Push character from array
j_saload, // 53 Push short from array
j_istore, // 54 Pop integer value into local variable
j_lstore, // 55 Pop long value into local variable
j_fstore, // 56 Pop single float value into local variable
j_dstore, // 57 Pop double float value into local variable
j_astore, // 58 Pop object refernce into local variable
j_istore_0, // 59 Pop integer value into local variable #0
j_istore_1, // 60 Pop integer value into local variable #1
j_istore_2, // 61 Pop integer value into local variable #2
j_istore_3, // 62 Pop integer value into local variable #3
j_lstore_0, // 63 Pop long value into local variable #0
j_lstore_1, // 64 Pop long value into local variable #1
j_lstore_2, // 65 Pop long value into local variable #2
j_lstore_3, // 66 Pop long value into local variable #3
j_fstore_0, // 67 Pop single float value into local variable #0
j_fstore_1, // 68 Pop single float value into local variable #1
j_fstore_2, // 69 Pop single float value into local variable #2
j_fstore_3, // 70 Pop single float value into local variable #3
j_dstore_0, // 71 Pop double float value into local variable
j_dstore_1, // 72 Pop double float value into local variable #0
j_dstore_2, // 73 Pop double float value into local variable #1
j_dstore_3, // 74 Pop double float value into local variable #2
j_astore_0, // 75 Pop object refernce into local variable #0
j_astore_1, // 76 Pop object refernce into local variable #1
j_astore_2, // 77 Pop object refernce into local variable #2
j_astore_3, // 78 Pop object refernce into local variable #3
j_iastore, // 79 Pop integer from array
j_lastore, // 80 Pop long from array
j_fastore, // 81 Pop single float from array
j_dastore, // 82 Pop double float from array
j_aastore, // 83 Pop object refernce from array
j_bastore, // 84 Pop signed byte from array
j_castore, // 85 Pop character from array
j_sastore, // 86 Pop short from array
j_pop, // 87 Pop top stack word
j_pop2, // 88 Pop top two stack word
j_dup, // 89 Duplicate top stack word
j_dup_x1, // 90 Duplicate top stack word and put two down
j_dup_x2, // 91 Duplicate top stack word and put three down
j_dup2, // 92 Duplicate top two stack word
j_dup2_x1, // 93 Duplicate top two stack words and put two down
j_dup2_x2, // 94 Duplicate top two stack words and put three down
j_swap, // 95 Swap two top stack words
j_iadd, // 96 Integer add
j_ladd, // 97 Long add
j_fadd, // 98 Single float add
j_dadd, // 99 Double float add
j_isub, // 100 Integer subtract
j_lsub, // 101 Long subtract
j_fsub, // 102 Single float subtract
j_dsub, // 103 Double Float subtract
j_imul, // 104 Integer multiply
j_lmul, // 105 Long multiply
j_fmul, // 106 Single float multiply
j_dmul, // 107 Double Float multiply
j_idiv, // 108 Integer divide
j_ldiv, // 109 Long divide
j_fdiv, // 110 Single float divide
j_ddiv, // 111 Double Float divide
j_irem, // 112 Integer reminder
j_lrem, // 113 Long reminder
j_frem, // 114 Single float reminder
j_drem, // 115 Double Float reminder
j_ineg, // 116 Integer negate
j_lneg, // 117 Long negate
j_fneg, // 118 Single float negate
j_dneg, // 119 Double Float negate
j_ishl, // 120 Integer shift left
j_lshl, // 121 Long shift left
j_ishr, // 122 Integer logical shift right
j_lshr, // 123 Long logical shift right
j_iushr, // 124 Integer arithmetic shift right
j_lushr, // 125 Long arithmeticshift right
j_iand, // 126 Integer boolean AND
j_land, // 127 Long boolean AND
j_ior, // 128 Integer boolean OR
j_lor, // 129 Long boolean OR
j_ixor, // 130 Integer boolean XOR
j_lxor, // 131 Long boolean XOR
j_iinc, // 132 Add 8-bit signed const to local variable
j_i2l, // 133 Integer to Long conversion
j_i2f, // 134 Integer to single float conversion
j_i2d, // 135 Integer to double float conversion
j_l2i, // 136 Long to Integer conversion
j_l2f, // 137 Long to single float conversion
j_l2d, // 138 Long to double float conversion
j_f2i, // 139 Single float to Integer conversion
j_f2l, // 140 Single float to Long conversion
j_f2d, // 141 Single float to double float conversion
j_d2i, // 142 Double float to Integer conversion
j_d2l, // 143 Double float to Long conversion
j_d2f, // 144 Double float to double float conversion
j_i2b, // 145 Integer to signed byte conversion
j_i2c, // 146 Integer to unsigned short conversion
j_i2s, // 147 Integer to signed short conversion
j_lcmp, // 148 Long compare
j_fcmpl, // 149 Single float compare (-1 on NaN)
j_fcmpg, // 150 Single float compare (1 on NaN)
j_dcmpl, // 151 Double float compare (-1 on NaN)
j_dcmpg, // 152 Double float compare (1 on NaN)
j_ifeq, // 153 Branch if equal to 0
j_ifne, // 154 Branch if not equal to 0
j_iflt, // 155 Branch if less then 0
j_ifge, // 156 Branch if greater than or equal to 0
j_ifgt, // 157 Branch if greater than 0
j_ifle, // 158 Branch if less than or equal to 0
j_if_icmpeq, // 159 Branch if integers equal
j_if_icmpne, // 160 Branch if integers not equal
j_if_icmplt, // 161 Branch if integers less than
j_if_icmpge, // 162 Branch if integers grater than or equal to
j_if_icmpgt, // 163 Branch if integers grater than
j_if_icmple, // 164 Branch if integers less than or equal to
j_if_acmpeq, // 165 Branch if object references are equal
j_if_acmpne, // 166 Branch if object references not equal
j_goto, // 167 Branch always
j_jsr, // 168 Jump subroutine
j_ret, // 169 Return from subroutine
j_tableswitch, // 170 Access jump table by index and jump
j_lookupswitch, // 171 Access jump table by key match and jump
j_ireturn, // 172 Return integer from function
j_lreturn, // 173 Return long from function
j_freturn, // 174 Return single floatr from function
j_dreturn, // 175 Return double float from function
j_areturn, // 176 Return object reference from function
j_return, // 177 Return (void) from procedure
j_getstatic, // 178 Set static field from class
j_putstatic, // 179 Set static field in class
j_getfield, // 180 Fetch field from object
j_putfield, // 181 Set field in object
j_invokevirtual, // 182 invoke instance method
j_invokespecial, // 183 invoke instance method (superclass/init/...)
j_invokestatic, // 184 invoke a class (static) method
j_invokeinterface,// 185 invoke interface method
j_invokedynamic, // 186 invoke instance method (select by paraneter)
j_new, // 187 Create new object
j_newarray, // 188 Allocate new array
j_anewarray, // 189 Allocate new array of refernces to object
j_arraylength, // 190 Get length of array
j_athrow, // 191 Throw exception or error
j_checkcast, // 192 Make sure object is of given type
j_instanceof, // 193 Determine if an object is of given type
j_monitorenter, // 194 Enter monitored region of code
j_monitorexit, // 195 Exit monitored region of code
j_wide, // 196 wide (prefix of command)
j_multianewarray, // 197 Allocate new multi-dimensional array
j_ifnull, // 198 Branch if NULL-ptr
j_ifnonnull, // 199 Branch if not NULL-ptr
j_goto_w, // 200 Branch always (wide index)
j_jsr_w, // 201 Jump subroutine (wide index)
j_breakpoint, // 202 Stop and pass control to breakpoint handler
//
j_lastnorm,
j_a_invokesuper = j_lastnorm,
j_a_invokevirtualobject,
j_a_invokeignored,
// bottom of table ! (emu)
j_a_software,
j_a_hardware,
//
j_last
};
enum name_quick
{
j_ldc_quick = j_lastnorm, // 203 (18)
j_ldcw_quick, // 204 (19)
j_ldc2w_quick, // 205 (20)
j_getfield_quick, // 206 (180)
j_putfield_quick, // 207 (181)
j_getfield2_quick, // 208
j_putfield2_quick, // 209
j_getstatic_quick, // 210 (178)
j_putstatic_quick, // 211 (179)
j_getstatic2_quick, // 212
j_putstatic2_quick, // 213
j_invokevirtual_quick, // 214 (182)
j_invokenonvirtual_quick, // 215 (183)
j_invokesuper_quick, // 216
j_invokestatic_quick, // 217 (184)
j_invokeinterface_quick, // 218 (185)
j_invokevirtualobject_quick, // 219
j_invokeignored_quick, // 220
j_new_quick, // 221 (187)
j_anewarray_quick, // 222 (189)
j_multianewarray_quick, // 223 (197)
j_checkcast_quick, // 224 (192)
j_instanceof_quick, // 225 (193)
j_invokevirtual_quick_w, // 226
j_getfield_quick_w, // 227
j_putfield_quick_w, // 228
j_quick_last
};
#define j_software 254
#define j_hardware 255
#endif

View File

@@ -0,0 +1,20 @@
// ATT: version also must be changed when changing instruction names
#define KEYWORD_VERSION 1
//-------------
// command aliases for backward (to 1.0) compatibility
//
"int2byte", "int2char", "int2short", "invokenonvirtual",
"ret_w",
//-------------
// keywords
//
"from", "method", "to", "is", "using", "signature", "field", "use",
"stack", "offset", "locals", "default", "inner", "outer", "class",
"public", "private", "protected", "static", "final", "synchronized",
"volatile", "transient", "native", "interface", "abstract",
"annotation", "enum", "bridge", "varargs", "fpstrict", "synthetic",
"visible", "invisible", "visibleparam", "invisibleparam",
//-------------

View File

@@ -0,0 +1,651 @@
//#define __debug__
/*
* Interactive disassembler (IDA)
* Copyright (c) 1990-98 by Ilfak Guilfanov.
* E-mail: ig@datarescue.com
* JVM module.
* Copyright (c) 1995-2006 by Iouri Kharon.
* E-mail: yjh@styx.cabel.net
*
* ALL RIGHTS RESERVED.
*
*/
#ifndef _JAVA_HPP
#define _JAVA_HPP
#define VIEW_WITHOUT_TYPE // no show return/filed type in command if !jasmin()
#include <pro.h>
#include "../idaidp.hpp"
#include <fpro.h>
#include <ieee.h>
#include "classfil.hpp"
#include "ins.hpp"
struct java_t;
#pragma pack(1)
//----------------------------------------------------------------------
// Redefine temporary names
//
#define wid segpref
#define xtrn_ip auxpref
#define swit Op1.specflag2
#define ref specflag1
#define _name value_shorts.low
#define _class value_shorts.high
#define _bmidx value_shorts.high
#define _mhr_kind value_shorts.low // MethodHandle reference_kind
#define _mhr_index value_shorts.high // MethodHandle reference_index
#define _mtd_index value_shorts.low // MethodType descriptor_index
#define _dscr addr_shorts.low
#define _subnam addr_shorts.high
#define cp_ind specval_shorts.low
#define cp_type specval_shorts.high
// nexts for Utf8 (on load) and _Ssize used in MAP only
#define _Ssize addr_shorts.low
#define _Sflags addr_shorts.high
#define _Sopstr value2
// command aliases
#define o_cpool o_idpspec0
#define o_array o_idpspec1
//----------------------------------------------------------------------
struct TXS
{
const char *str;
uchar size;
};
#define TXS_DECLARE(p) { p, (uchar)(sizeof(p)-1) }
#define TXS_EMPTY() { NULL, 0 }
//----------------------------------------------------------------------
struct const_desc_t
{
uchar type; // CONSTANT_type
uchar flag;
#define _REF 0x01 // has reference
#define HAS_FLDNAME 0x02 // Utf8 is valid Field/Variable Name
#define HAS_TYPEDSCR 0x04 // Utf8 is valid Descriptor
#define HAS_CALLDSCR 0x08 // Utf8 is valid Descriptor for Method
#define HAS_CLSNAME 0x10 // Utf8 is valid as Class Name (Not FLD!)
#define SUB_FLDNAME 0x20
#define SUB_TYPEDSCR 0x40
#define SUB_CALLDSCR 0x80
#define SUB_SHIFT 4
CASSERT((HAS_FLDNAME << SUB_SHIFT) == SUB_FLDNAME
&& (HAS_TYPEDSCR << SUB_SHIFT) == SUB_TYPEDSCR
&& (HAS_CALLDSCR << SUB_SHIFT) == SUB_CALLDSCR);
bool is_referenced() const { return (flag & _REF) != 0; }
void mark_referenced() { flag |= _REF; }
#define NORM_FIELD (HAS_CLSNAME | SUB_FLDNAME | SUB_TYPEDSCR)
#define NORM_METOD (HAS_CLSNAME | SUB_FLDNAME | SUB_CALLDSCR)
ushort ref_ip; // in xtrn-segment...
union
{
uint32 value; // low part of # value
struct
{
ushort low; // BegInd Utf8 (name)
ushort high; // index to _Class
} value_shorts; // unification
};
union
{
uint32 value2; // hi part of # value
struct
{
ushort low; // TypeName
ushort high; // Descriptor
} addr_shorts;
};
};
union Object
{ // in IDP_JDK12 format was in reverse order!
struct
{
ushort Name; // index to name
ushort Dscr; // index to descriptor
};
uint32 Ref; // used in out
};
struct _FMid_
{
ushort name; // index to name
ushort dscr; // index to descriptor
ushort access; // access flag
// Number not needed for search/out
ushort Number; // Number of current Field or Method
uchar extflg; // for ERROR diagnostic and other flags
#define EFL_NAME 1
#define EFL_TYPE 2
#define EFL_NAMETYPE (EFL_NAME | EFL_TYPE)
//#define _OLD_EFL_ACCESS 4
#define EFL__MASK (EFL_NAME | EFL_TYPE | 4) // for check on conversion
// next constant added in JDK15 store-format
// java-2 store format only
#define XFL_DEPRECATED 0x04
#define XFL_UNICODENAME 0x08 // name contain unicode character
#define XFL_M_LABSTART 0x10 // for METHOD set label at entry
#define XFL_C_SUPEROBJ 0x10 // for THIS - parent(.super) == Object
#define XFL_M_LABEND 0x20 // for METHOD set label at exit
#define XFL_C_DEBEXT 0x20 // for THIS - have stored SourceDebugExtension
#define XFL_M_EMPTYSM 0x40 // for METHOD - have empty StackMap
#define XFL_C_ERRLOAD 0x40 // for THIS - have loadtime problems
#define XFL_C_DONE 0x80 // analisys pass complete
// next fields added in JDK15 store-format
uchar _UNUSED_ALING; // = 0
ushort utsign; // index to signature attribute
};
struct FieldInfo
{
_FMid_ id; // for search procedure
uval_t valNode; // init value's node
// next fields added in JDK15 store-format
uval_t annNodes[2]; // nodes for Vis/Invis annotation
uval_t genNode; // list of stored generic attributes
};
struct SegInfo
{
_FMid_ id; // for search procedure
uint32 CodeSize; // CODE size
ea_t start_ea; // EA of Code (checker & slb)
ea_t DataBase; // EA of loc variable segment
ushort DataSize; // max locals (DATA size)
ushort stacks; // stack size
uval_t excNode; // Node for exception table
uval_t thrNode; // Node for throws (fmt change!)
// next fields added in JDK15 store-format
uval_t varNode; // LocVar descriptors
uval_t smNode; // StackMap descriptors
// Visible, Invisible, VisibleParam, InvisibleParam, Default
uval_t annNodes[5]; // nodes for all types of annotations
uval_t genNodes[2]; // list of stored generic attributes + code
};
struct ClassInfo
{
ushort maxCPindex; // max valid index in ConstantPool
ushort MinVers; //-> of file
Object This; // class name/descriptor
Object super; // .super class (parent)
ushort AccessFlag; // access flags
ushort FieldCnt; // Field Declaration Counter
uval_t ClassNode; // Field (>0) & Method (<0) (0?)
ushort MethodCnt; // Method's Segment fot this Class
ushort SourceName; // Index of Utf8 Source File Name
uval_t impNode; // Node for Interfaces (fmt change!)
ea_t start_ea; // for SearchFM
uint32 maxSMsize; // optimize memory allocation (StackMap)
// ATT: JDK15 - previous errload
ea_t xtrnEA; // beg header segment
uval_t xtrnNode; // node for xtrn Segment
ushort xtrnCnt; // header size
ushort xtrnLQE;
// next fields added in JDK15 store-format
ushort MajVers; // -> of file
uchar extflg; // XFL_.... consts
uchar JDKsubver; // for speed/size ONLY
uval_t innerNode; // Node for Inner classes
ushort encClass; // EnclosingMethod class
ushort encMethod; // EnclosingMethod NameAndType
uval_t msgNode; // node for store loading messages
ushort utsign; // signature attribute index
ushort maxStrSz; // optimize memory allocation (string)
uval_t annNodes[2]; // nodes for Visible/Invisible
uint32 maxAnnSz; // optimize memory allocation (annotation)
uval_t genNode; // list of stored generic attributes
};
#define FOR_EACH_CONSTANT_POOL_INDEX(Binding) for ( ushort Binding = 1; Binding <= curClass.maxCPindex; ++Binding )
struct Exception
{
ushort start_pc;
ushort end_pc;
ushort handler_pc;
Object filter;
};
struct LocVar
{
ushort ScopeBeg; // scope start
ushort ScopeTop; // scope end
Object var; // name & descriptor
ushort utsign; // signature attribute index
};
struct InnerClass
{
ushort inner;
ushort outer;
ushort name;
ushort access;
};
//------------------------------------------------------------------------
enum sm_node_t
{
smn_aa_not_finished = -1,
smn_ok = 0,
smn_no_use = 1,
};
#define CNS_SOURCE -2
#define CNS_CLASS 0
//>0 - opis[i]
//>=0x10000 - string blobs
#define CNA_VERSION -1
#define CNA_KWRDVER -2
#define CNA_IDPFLAGS -3 // idpflags value
#define CNA_LIMITER -4 // user_limiter state
//>=0x10000 - string info
#define UR_TAG 'r'
//------------------------------------------------------------------------
// !DO NOT CHANGE ORDER!
enum fmt_t
{
fmt_debug = 0, // as fmt_string, but have prompting
fmt_string, // string as text
fmt_string_single_quotes,
fmt_FieldDescriptor,
// MethodTypeSignature:
// FormalTypeParameters opt (TypeSignature*) ReturnType ThrowsSignature*
// ^
fmt_method_FormalTypeParameters,
// MethodTypeSignature:
// FormalTypeParameters opt (TypeSignature*) ReturnType ThrowsSignature*
// ^
fmt_method_ReturnType,
// MethodTypeSignature:
// FormalTypeParameters opt (TypeSignature*) ReturnType ThrowsSignature*
// ^
fmt_method_TypeSignature,
// MethodTypeSignature:
// FormalTypeParameters opt (TypeSignature*) ReturnType ThrowsSignature*
// ^
fmt_method_ThrowsSignature,
fmt_ClassSignature, // class signature (start width <...:...>)
fmt_FieldDescriptor_nospace, // signature (==dscr, without space)
fmt_ClassName_or_Array, // if have '[' desriptor, else fieldname
fmt_ClassName, // extract class from descriptor
fmt_fullname, // full qualified name
fmt_UnqualifiedName,
fmt__ENDENUM
};
#define FMT_ENC_RESERVED (uchar)0x80
//-------------------------------------------------------------------------
inline bool fmt_expects_call_descriptor(fmt_t fmt)
{
return fmt >= fmt_method_FormalTypeParameters && fmt <= fmt_ClassSignature;
}
//-------------------------------------------------------------------------
struct SMinfo // for sm_getinfo
{
const uchar *pb;
const uchar *pe;
uint fcnt;
ea_t ea;
};
enum load_mode_t
{
lm_lenient = -1, // don't call remember_problem()
lm_no_set_ref = 0, // no set reference
lm_normal = 1, // Normal mode
lm_need_cr = 2, // needed CR
};
ea_t extract_name_ea(
char buf[MAXSTR],
const char *name,
int pos,
uchar clv);
const TXS *get_base_typename(uchar tag, bool or_void=false);
#if defined(__debug__) || defined(TEST_FMTSTR)
NORETURN extern void _destroyed(const char *from);
NORETURN extern void _faterr(uchar mode, const char *from);
#define UNCOMPAT(p) _faterr(1, p)
#define INTERNAL(p) _faterr(0, p)
#define DESTROYED(p) _destroyed(p)
#else
NORETURN extern void _destroyed(void);
NORETURN extern void _faterr(uchar mode);
#define UNCOMPAT(p) _faterr(1)
#define INTERNAL(p) _faterr(0)
#define DESTROYED(p) _destroyed()
#endif
uchar javaIdent(ushort v, uchar *isStart = NULL);
// information record of StackMap
struct sm_info_t
{
uint32 noff; // start offset in blob
uint32 eoff; // end offset in blob
uint fcnt; // locals at entry
};
//------------------------------------------------------------------------
#ifdef __debug__
#define DEB_ASSERT(cond, text) if ( cond ) error(text)
#else
#define DEB_ASSERT(cond, text)
#endif
//------------------------------------------------------------------------
enum j_registers { Rvars=0, Roptop, Rframe, rVcs, rVds };
//------------------------------------------------------------------------
void idaapi java_header(outctx_t &ctx);
void idaapi java_segstart(outctx_t &ctx, segment_t *seg);
void idaapi java_segend(outctx_t &ctx, segment_t *seg);
fpvalue_error_t idaapi j_realcvt(void *m, fpvalue_t *e, ushort swt);
void idaapi java_data(outctx_t &ctx, bool analyze_only);
int cmp_operands(op_t &op1, op_t &op2);
bool idaapi can_have_type(const op_t &op);
void copy_const_to_opnd(op_t &x, const const_desc_t &co);
//----------------------------------------------------------------------
#define UAS_JASMIN 0x0001 // is jasmin assembler?
//------------------------------------------------------------------------
#define MLD_EXTREF 0x01
#define MLD_VARREF 0x02 // if present EXTREF must be present
#define MLD_METHREF 0x04 // if present VARREF must be present
#define MLD_EXTATR 0x08 // store additional attributes to file(s)
#define MLD_LOCVAR 0x10 // Rename local variables
#define MLD_STRIP 0x20 // Semantic error names show
#define MLD_FORCE 0x40 // Ignore 'additional error' on load
#define MLD__DEFAULT ((MLD_EXTREF|MLD_VARREF) /* | MLD_LOCVAR */)
//------------------------------------------------------------------------
#define IDF_MULTDEB 0x0001 // multiline debug
#define IDF_HIDESM 0x0002 // hide stackmap
#define IDF_AUTOSTR 0x0004 // fmt_string as fmt_debug (next string at \n)
#define IDF_CONVERT 0x0008 // convert (to jasmin) when write asm file
#define IDF_ENCODING 0x0010 // enable unicode-encoding (also see map)
#define IDF_NOPATH 0x0020 // .attribute's filename without path
// not stored (in base) flags
#define IDM_BADIDXSTR 0x00010000 // show invalid indexes as string's
// ... and used loader only
#define IDM_REQUNK 0x20000000 // make request of ;unknown attribute'
#define IDM_WARNUNK 0x40000000 // 'unknown attribute' produced warnings
// ... in module, but temporary
#define IDM_OUTASM 0x80000000 // currently write asm file
#define IDM__REQMASK ((~(IDM_REQUNK | IDM_WARNUNK | IDM_OUTASM)) >> 16)
// curent modes
#define IDFM__DEFAULT ((IDF_MULTDEB|IDF_CONVERT|IDF_ENCODING) | IDM_WARNUNK)
#pragma pack()
//------------------------------------------------------------------
enum CIC_param
{
C_4byte = 0,
C_8byte,
C_Field,
C_Method,
C_Interface,
C_Class,
C_Type,
C_TypeName,
C_CallSite,
};
enum attr_parent_kind_t
{
attr_parent_kind_code = 0,
attr_parent_kind_field,
attr_parent_kind_method,
attr_parent_kind_class_file,
attr_parent_kind_CHECK,
};
class out_java_t;
typedef size_t _PRMPT_(java_t &pm, out_java_t *oj);
#define MAX_ATTR_NMSZ 128
//------------------------------------------------------------------
DECLARE_PROC_LISTENER(idb_listener_t, struct java_t);
struct java_t : public procmod_t
{
idb_listener_t idb_listener = idb_listener_t(*this);
int start_asm_list = 0;
uint32 idpflags = IDFM__DEFAULT;
#ifdef TEST_FMTSTR
inline bool jasmin(void) const { return false; }
inline bool is_multiline_debug(void) const { return true; } // true by default, it seems
inline bool is_fmt_string_as_fmt_debug(void) const { return false; } // false by default, it seems
#else
inline bool jasmin(void) const { return (ash.uflag & UAS_JASMIN) != 0; }
inline bool is_multiline_debug(void) const { return (idpflags & IDF_MULTDEB) != 0; }
inline bool is_fmt_string_as_fmt_debug(void) const { return (idpflags & IDF_AUTOSTR) != 0; }
#endif
bool mode_changed = false;
bool displayed_nl = false;
bool g_bufinited = false;
uint32 g_bufsize = 0;
uint32 maxpos = 0;
uint32 curpos = 0;
uchar user_limiter = 0;
// next fields are only for out
bool no_prim = false;
size_t outcnt = 0;
size_t ref_pos = 0;
uint32 Feature = 0;
// Normally static buffers of MAX_NODENAME_SIZE are forbidden but since
// 'tmp_name' is defined only in the java module, it is acceptable. To avoid
// warnings we define JAVA_BUFSIZE:
#define JAVA_BUFSIZE MAX_NODENAME_SIZE
char tmp_name[JAVA_BUFSIZE];
// map.cpp vars
char rfmt[23] = " %5u=> ";
char ind_fmt[8] = "%s=%-5u";
char lft_fmt[16] = "%08lX %5u%c %s ";
// npool.cpp vars
int32 savesize = -1;
uchar sde = 0;
// npooluti.cpp vars
ClassInfo curClass;
SegInfo curSeg;
FieldInfo curField;
FILE *myFile = nullptr;
netnode ClassNode;
netnode XtrnNode;
netnode ConstantNode;
char debugmode = 0;
uchar SMF_mode = 0;
// only for npool
uchar loadMode = 0;
uint32 errload = 0;
ushort *tsPtr = nullptr;
uchar *smBuf = nullptr;
uchar *annBuf = nullptr;
uint32 FileSize = 0;
sm_node_t sm_node = smn_aa_not_finished;
uchar uni_chk = (uchar)-1; // unicode 'renaming' support
uchar name_chk = 0;
char tmpbuf[JAVA_BUFSIZE]; // see comment for TMP_NAME
netnode SMnode;
uint32 SMsize = 0;
uint endcls = 0;
uchar clunic = 0; // for unicode renaming
ea_t start_ea = 0;
ushort cursel = 1;
// jasmin reserved word support
std::set<qstring> ResW;
java_t()
{
memset(&curClass, 0, sizeof(curClass));
memset(&curSeg, 0, sizeof(curSeg));
memset(&curField, 0, sizeof(curField));
memset(tmp_name, 0, sizeof(tmp_name));
memset(tmpbuf, 0, sizeof(tmpbuf));
}
inline void StoreOpis(uint index, const const_desc_t &opis)
{
ConstantNode.supset(index, &opis, sizeof(opis));
}
virtual ssize_t idaapi on_event(ssize_t msgid, va_list va) override;
const char *set_idp_options(
const char *keyword,
int value_type,
const void * value,
bool idb_loaded);
void sm_validate(const SegInfo *si);
uchar loadDialog(bool manual);
int32 gen_map_file(FILE *fp);
char *convert_clsname(char *buf) const;
void database_loaded(const char *file);
void make_new_name(ushort name, ushort subnam, uchar mode, uint ip);
int upgrade_db_format(int ver, netnode constnode);
void coagulate_unused_data(const SegInfo *ps);
void java_footer(outctx_t &ctx);
void load_attributes(attr_parent_kind_t apk);
void loader(FILE *fp, bool manual);
ea_t get_ref_addr(ea_t ea, const char *name, size_t pos);
void TouchArg(const insn_t &insn, const op_t &x, bool isload);
uval_t SearchFM(ushort name, ushort dscr, char *naprN);
void mark_and_comment(ea_t ea, const char *cmt) const;
int emu(const insn_t &insn);
int format_utf16_string(
const ushort *_tp,
uint32 ostsz,
uint32 off_ReturnType,
uint32 off_ThrowsSignature_and_TypeSignature,
ssize_t size,
fmt_t mode,
out_java_t *oj,
_PRMPT_ putproc);
void xtrnSet(
uint cin,
const_desc_t *co,
uint xip,
char *str,
size_t strsize,
bool full,
uchar rmod=3);
void rename_uninames(int32 mode);
void setPoolReference(void);
void SetName(ushort name, ea_t ea, ushort access, uval_t number, uchar rmod=3);
int refput(ushort index);
bool fmtName(ushort index, char *buf, size_t bufsize, fmt_t fmt);
uchar set_parent_object(void);
uchar attribute_type_from_str(ushort index, attr_parent_kind_t apk, char str[MAX_ATTR_NMSZ]);
void CheckPoolReference(bool insns_created);
void set_lv_name(ushort name, ea_t ea, uchar rmod);
int is_locvar_name(const insn_t &insn, const char *name);
void ValidateStoreLocVar(ushort slot, LocVar & lv);
void dump_floating_constants(
const char *problem,
const char *what,
const intvec_t &ks);
ssize_t check_special_label(const char *buf, size_t len) const;
bool LoadOpis(load_mode_t load_mode, ushort index, uchar _op, const_desc_t *p);
void load_msg(const char *format, ...);
bool isSingleClass(ushort val);
const char *mk_diag(attr_parent_kind_t apk, char str[128]) const;
uint load_constants_pool(void);
inline void BadRefFile(const char *to, ushort id);
void BadRef(ea_t ea, const char *to, ushort id, attr_parent_kind_t apk);
void mark_access(ea_t ea, ushort acc) const;
uchar *sm_realloc(uint size);
uchar *annotation_realloc(uint size);
ushort *append_tmp_buffer(uint size);
bool getblob(uval_t ind, void *p, uval_t sz);
bool getstr(qstring *out, ushort index);
ushort read2(void);
uint32 read4(void);
uchar read1(void);
void readData(void *data, uint32 size);
void skipData(uint32 size);
const uchar *get_annotation(uval_t node, uint *plen);
bool sm_getinfo(const insn_t &insn, SMinfo *pinf);
uchar *annot_elm(uchar *ptr, uint32 *psize, uchar is_array=0);
uchar *annotation(uchar *p, uint32 *psize);
segment_t *getMySeg(ea_t ea, segment_t *seg = nullptr);
bool sm_chkargs(uchar **pptr, uint32 *pDopSize, ushort cnt);
int sm_load(ushort declcnt, uint32 *pDopSize);
NORETURN void loader_failure_bad_attr_decl_size(attr_parent_kind_t apk) const;
int CmpString(ushort index1, ushort index2);
int cmpDscrString(ushort index1, uchar met, ushort index2, uchar self);
ushort xtrnDscrSearch(ushort name, uchar met);
void mark_strange_name(ea_t ea) const;
void xtrnRef(ea_t ea, const const_desc_t &opis) const;
void xtrnRef_dscr(ea_t ea, const_desc_t *opis, uchar met=0);
void deltry(uint bg, uint ic, uint ui, const const_desc_t &pco);
segment_t *_add_seg(int caller);
void resizeLocVars(void) const;
const char *CopyAttrToFile(const char *astr, uint32 size, ushort id);
inline int strstrpos(const char *s1, const char *s2)
{
s2 = strstr(s1, s2);
return s2 == NULL ? -1 : s2 - s1;
}
bool is_valid_string_index(ushort index) const;
uchar LoadUtf8(ushort index, const_desc_t *co);
void parse_const_desc(ushort index, const_desc_t *co);
uchar CheckSignature(ushort index, attr_parent_kind_t apk);
void ResW_init(void);
void ResW_newbase(void);
uchar ResW_oldbase(void);
void ResW_validate(uint32 *Flags, const ushort *pend);
uint32 upgrade_ResW(uint32 opstr);
void ResW_free(void);
size_t make_locvar_cmt(qstring *buf, const insn_t &insn);
int32 print_loader_messages(char str[MAXSTR], const char *cmt, outctx_t *ctx);
int LoadIndex(insn_t &insn);
int ConstLoad(insn_t &insn, CIC_param ctype);
int ana(insn_t *_insn);
};
extern int data_id;
#endif

View File

@@ -0,0 +1,131 @@
PROC=java
O1=oututil
O2=map
O3=npool
O4=npooluti
O5=resword
O6=upgrade
O7=fmtstr
include ../module.mak
test_fmtstr: $(R)test_fmtstr$(B)
TEST_FMTSTR_OBJS:=$(F)test_fmtstr_main$(O)
$(R)test_fmtstr$(B): $(call dumb_target, unicode pro, $(TEST_FMTSTR_OBJS))
$(F)test_fmtstr_main$(O): CFLAGS += -DTEST_FMTSTR=1
# MAKEDEP dependency list ------------------
$(F)ana$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \
$(I)config.hpp $(I)fpro.h $(I)funcs.hpp \
$(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \
$(I)lines.hpp $(I)llong.hpp $(I)loader.hpp \
$(I)nalt.hpp $(I)name.hpp \
$(I)netnode.hpp $(I)offset.hpp $(I)pro.h \
$(I)problems.hpp $(I)range.hpp $(I)segment.hpp \
$(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ana.cpp \
classfil.hpp ins.hpp java.hpp
$(F)emu$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \
$(I)config.hpp $(I)fpro.h $(I)funcs.hpp \
$(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \
$(I)lines.hpp $(I)llong.hpp $(I)loader.hpp \
$(I)nalt.hpp $(I)name.hpp \
$(I)netnode.hpp $(I)offset.hpp $(I)pro.h \
$(I)problems.hpp $(I)range.hpp $(I)segment.hpp \
$(I)ua.hpp $(I)xref.hpp ../idaidp.hpp classfil.hpp \
emu.cpp ins.hpp java.hpp
$(F)fmtstr$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \
$(I)config.hpp $(I)fpro.h $(I)funcs.hpp \
$(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \
$(I)lines.hpp $(I)llong.hpp $(I)loader.hpp \
$(I)nalt.hpp $(I)name.hpp \
$(I)netnode.hpp $(I)offset.hpp $(I)pro.h \
$(I)problems.hpp $(I)range.hpp $(I)segment.hpp \
$(I)ua.hpp $(I)xref.hpp ../idaidp.hpp classfil.hpp \
fmtstr.cpp ins.hpp java.hpp oututil.hpp upgrade.hpp
$(F)ins$(O) : $(I)bitrange.hpp $(I)bytes.hpp $(I)config.hpp $(I)fpro.h \
$(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)ieee.h \
$(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp $(I)nalt.hpp \
$(I)netnode.hpp $(I)pro.h $(I)range.hpp $(I)segment.hpp \
$(I)ua.hpp $(I)xref.hpp ins.cpp ins.hpp
$(F)map$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \
$(I)config.hpp $(I)fpro.h $(I)funcs.hpp \
$(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \
$(I)lines.hpp $(I)llong.hpp $(I)loader.hpp \
$(I)nalt.hpp $(I)name.hpp \
$(I)netnode.hpp $(I)offset.hpp $(I)pro.h \
$(I)problems.hpp $(I)range.hpp $(I)segment.hpp \
$(I)ua.hpp $(I)xref.hpp ../idaidp.hpp classfil.hpp \
ins.hpp java.hpp map.cpp oututil.hpp
$(F)npool$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \
$(I)config.hpp $(I)diskio.hpp $(I)fpro.h \
$(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)ieee.h \
$(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \
$(I)loader.hpp \
$(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp \
$(I)pro.h $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \
$(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \
classfil.hpp ins.hpp java.hpp npool.cpp npooluti.hpp \
oututil.hpp upgrade.hpp
$(F)npooluti$(O): $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \
$(I)config.hpp $(I)diskio.hpp \
$(I)entry.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \
$(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp $(I)lines.hpp \
$(I)llong.hpp $(I)loader.hpp \
$(I)nalt.hpp $(I)name.hpp \
$(I)netnode.hpp $(I)offset.hpp $(I)pro.h \
$(I)problems.hpp $(I)range.hpp $(I)segment.hpp \
$(I)ua.hpp $(I)xref.hpp ../idaidp.hpp classfil.hpp \
ins.hpp java.hpp npooluti.cpp npooluti.hpp oututil.hpp \
upgrade.hpp
$(F)out$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \
$(I)config.hpp $(I)fpro.h $(I)funcs.hpp \
$(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \
$(I)lines.hpp $(I)llong.hpp $(I)loader.hpp \
$(I)nalt.hpp $(I)name.hpp \
$(I)netnode.hpp $(I)offset.hpp $(I)pro.h \
$(I)problems.hpp $(I)range.hpp $(I)segment.hpp \
$(I)ua.hpp $(I)xref.hpp ../idaidp.hpp classfil.hpp \
ins.hpp java.hpp npooluti.hpp out.cpp oututil.hpp \
upgrade.hpp
$(F)oututil$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \
$(I)config.hpp $(I)fpro.h $(I)funcs.hpp \
$(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \
$(I)lines.hpp $(I)llong.hpp $(I)loader.hpp \
$(I)nalt.hpp $(I)name.hpp \
$(I)netnode.hpp $(I)offset.hpp $(I)pro.h \
$(I)problems.hpp $(I)range.hpp $(I)segment.hpp \
$(I)ua.hpp $(I)xref.hpp ../idaidp.hpp classfil.hpp \
ins.hpp java.hpp oututil.cpp oututil.hpp
$(F)reg$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \
$(I)config.hpp $(I)diskio.hpp $(I)fpro.h \
$(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)ieee.h \
$(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \
$(I)loader.hpp \
$(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp \
$(I)pro.h $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \
$(I)ua.hpp $(I)xref.hpp ../idaidp.hpp classfil.hpp \
ins.hpp java.hpp notify_codes.hpp npooluti.hpp reg.cpp \
upgrade.hpp
$(F)resword$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \
$(I)config.hpp $(I)fpro.h $(I)funcs.hpp \
$(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \
$(I)lines.hpp $(I)llong.hpp $(I)loader.hpp \
$(I)nalt.hpp $(I)name.hpp \
$(I)netnode.hpp $(I)offset.hpp $(I)pro.h \
$(I)problems.hpp $(I)range.hpp $(I)segment.hpp \
$(I)ua.hpp $(I)xref.hpp ../idaidp.hpp classfil.hpp \
ins.hpp jas_rw.cc java.hpp npooluti.hpp resword.cpp \
upgrade.hpp
$(F)test_fmtstr_main$(O): $(I)kernwin.hpp $(I)llong.hpp $(I)pro.h \
fmtstr.cpp test_fmtstr_main.cpp
$(F)upgrade$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \
$(I)config.hpp $(I)fpro.h $(I)funcs.hpp \
$(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \
$(I)lines.hpp $(I)llong.hpp $(I)loader.hpp \
$(I)nalt.hpp $(I)name.hpp \
$(I)netnode.hpp $(I)offset.hpp $(I)pro.h \
$(I)problems.hpp $(I)range.hpp $(I)segment.hpp \
$(I)ua.hpp $(I)xref.hpp ../idaidp.hpp classfil.hpp \
ins.hpp java.hpp oututil.hpp upgrade.cpp upgrade.hpp

View File

@@ -0,0 +1,474 @@
/*
* Interactive disassembler (IDA)
* Copyright (c) 1990-98 by Ilfak Guilfanov.
* E-mail: ig@datarescue.com
* JVM module.
* Copyright (c) 1995-2006 by Iouri Kharon.
* E-mail: yjh@styx.cabel.net
*
* ALL RIGHTS RESERVED.
*
*/
#include "java.hpp"
#include "oututil.hpp"
//----------------------------------------------------------------------
int32 java_t::print_loader_messages(char str[MAXSTR], const char *cmt, outctx_t *ctx)
{
netnode temp(curClass.msgNode);
ssize_t i = 0;
ssize_t j = (ssize_t)temp.altval(i);
if ( j == 0 )
BADIDB:
DESTROYED("loader_message");
do
{
ssize_t len = temp.supstr(i, str, MAXSTR);
if ( len <= 0 )
goto BADIDB;
if ( cmt )
{
QASSERT(10264, ctx != NULL);
if ( ctx->gen_printf(0, "%s%s", cmt, str) )
return -1;
}
else
{
qfwrite(myFile, str, len);
if ( qfputc('\n', myFile) == EOF )
return -1;
}
}
while ( ++i < j );
return i;
}
//----------------------------------------------------------------------
bool out_java_t::print_newline(void)
{
if ( ferror(pm().myFile) )
return false;
if ( qfputc('\n', pm().myFile) == EOF )
return false;
qfprintf(pm().myFile, "%*c", int(pm().curpos), ' ');
return true;
}
//----------------------------------------------------------------------
//lint -esym(818,write_utf) could be made const
static size_t write_utf(java_t &pm, out_java_t *oj)
{
qfprintf(pm.myFile, "%s", oj->outbuf.c_str());
if ( !oj->print_newline() )
return 0;
return pm.maxpos - 1;
}
//----------------------------------------------------------------------
static int utfstr(java_t &pm, ushort index, const const_desc_t &)
{
out_java_t *pctx = (out_java_t *)create_outctx(BADADDR);
int i = pctx->fmtString(pm, index, pm.maxpos -= pm.curpos, fmt_string, write_utf);
pm.maxpos += pm.curpos;
if ( i >= 0 )
qfprintf(pm.myFile, "%s\n", pctx->outbuf.c_str());
delete pctx;
return i < 0 ? 0 : ++i;
}
//----------------------------------------------------------------------
static int outnum(java_t &pm, ushort /*type*/, const const_desc_t &co)
{
op_t x;
copy_const_to_opnd(x, co);
qfprintf(pm.myFile, "value = %" FMT_EA "u\n", x.value);
return 1;
}
//----------------------------------------------------------------------
GCC_DIAG_OFF(format-nonliteral);
static int outref(java_t &pm, ushort count, const const_desc_t &co)
{
static const char typ[] = " Descriptor", nam[] = " Name";
switch ( count )
{
case 3:
qfprintf(pm.myFile, pm.ind_fmt, "Class", co._class);
qfprintf(pm.myFile, pm.ind_fmt, " ref", co._name);
qfprintf(pm.myFile, pm.ind_fmt, typ, co._dscr);
qfprintf(pm.myFile, pm.ind_fmt, nam, co._subnam);
break;
case 2:
qfprintf(pm.myFile, pm.ind_fmt, &typ[1], co._name);
qfprintf(pm.myFile, pm.ind_fmt, nam, co._class);
break;
case 1:
qfprintf(pm.myFile, pm.ind_fmt, "Index", co._name);
break;
}
qfputc('\n', pm.myFile);
return 1;
}
//----------------------------------------------------------------------
int java_t::refput(ushort index)
{
if ( !LoadOpis(lm_normal, index, CONSTANT_Utf8, NULL) )
return 0;
qfprintf(myFile, rfmt, index);
return utfstr(*this, index, const_desc_t());
}
GCC_DIAG_ON(format-nonliteral);
//----------------------------------------------------------------------
GCC_DIAG_OFF(format-nonliteral);
int32 java_t::gen_map_file(FILE *fp)
{
static const char form[] =
"Map format\n\n"
"<~W~idth:D::::> [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
{
int (*proc)(java_t &pm, ushort index, const const_desc_t &);
ushort mask;
ushort skip;
char name[8];
ushort arg;
} defr[MAX_CONSTANT_TYPE] =
{
{ utfstr, 0x01, 0, "Utf8 ", 0 },
{ NULL, 0x00, 0, "", 0 }, // unicode
{ outnum, 0x10, 4, "Integer", 3 + dt_dword },
{ outnum, 0x10, 4, "Float ", 3 + dt_float },
{ outnum, 0x10, 8, "Long ", 3 + dt_qword },
{ outnum, 0x10, 8, "Double ", 3 + dt_double },
{ outref, 0x02, 2, "Class ", 1 },
{ outref, 0x20, 2, "String ", 1 },
{ outref, 0x04, 4, "Fld_ref", 3 },
{ outref, 0x04, 4, "Met_ref", 3 },
{ outref, 0x04, 4, "Int_ref", 3 },
{ outref, 0x08, 4, "nam&typ", 2 }
};
#define STR_MIN_RESERVED 32
char str[MAXSTR];
uchar tflag;
sval_t width;
sval_t pos;
int32 numstr = 0;
uint32 save_flags = idpflags;
ushort curbit = 1;
short unus = 1, unsort = 1, hexnum = 0, typemask = 0x3F, encinc = 2;
const_desc_t opis;
ushort j;
if ( !(idpflags & IDF_ENCODING) )
++encinc; // |= 1
width = 80;
if ( !ask_form(form, &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;
CASSERT(MAXSTR - STR_MIN_RESERVED > 72);
if ( width < 72 )
{
if ( width != 0 )
{
width = 72;
}
else
{
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;
myFile = fp;
do
{
while ( !(typemask & curbit) )
curbit <<= 1;
tflag = (uchar)unsort;
pos = 10;
FOR_EACH_CONSTANT_POOL_INDEX(i)
{
if ( !LoadOpis(lm_normal, 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.is_referenced()) && (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, int32(pos), i,
opis.is_referenced() ? ' ' : '*',
(unsort || defr[j].arg >= 3) ? defr[j].name : "");
{
int n = defr[j].proc(*this, 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;
j = defr[j].skip;
switch ( j )
{
case 0: // Utf8 / Unicode
pos += opis._Ssize + 2;
break;
case 8: // Long / Double
DEB_ASSERT((i == curClass.maxCPindex), "map:CPend");
++i;
// fallthrough
default:
pos += j;
break;
}
}
typemask ^= curbit;
}
while ( typemask != 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, 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;
}
GCC_DIAG_ON(format-nonliteral);
//----------------------------------------------------------------------
uchar java_t::loadDialog(bool manual)
{
static const char fmt[] =
"HELP\n"
"Java-VM class file loading options\n"
"\n"
"Do not create 'import' segment with external-references\n"
"\n"
" Prohibits the creation of a segment with external names, classes, and\n"
" methods.\n"
"\n"
"\n"
"Create 'import' segment with with references from commands\n"
"\n"
" Only regular references to the import segment will be collected.\n"
" If this option is off, then all references (including simple text\n"
" references) will be collected.\n"
"\n"
"\n"
"Field/variable declarations are included in references\n"
"\n"
" Cross references from field declarations are collected in the import\n"
" segment. For example, a field declaration\n"
"\n"
" Field borland.ui.AboutDialog about\n"
"\n"
" creates a reference to class borland.ui.AboutDialog\n"
"\n"
"\n"
"Method return types are included in references\n"
"\n"
" Cross references from the return type and arguments of method\n"
" declarations are collected in the import segment.\n"
" NOTE: The import segment does not contain classes that appear only in\n"
" the arguments of the method declarations.\n"
"\n"
"Store unknown attributes to external files\n"
"\n"
" This option allows to extract non-standard attributes (if present)\n"
" and store them to a set of files in the current directory.\n"
" Filenames will have <classname>.<tagname>.<attributename> form\n"
"\n"
"\n"
"Rename local (slot) variables (if information is available)\n"
"\n"
" This option allows to use names from variable declarations to\n"
" rename local variables if the input file has this information.\n"
"\n"
"\n"
"Create visible representation of stripped names\n"
"\n"
" Some java classes have their local\n"
" names stripped. This option allows IDA to recreate such local names.\n"
" NOTE: If this option is selected then all one-character names with\n"
" the character code >= 0x80 will be ignored.\n"
"\n"
"\n"
"Continue loading after errors in additional attributes\n"
"\n"
" Normally all errors in the classfile structure are fatal.\n"
" If this option is on, errors in the additional attributes\n"
" produce only warnings and the loading process continues.\n"
"\n"
"ENDHELP\n"
"Java loading options\n"
"\n"
" Class File version %D.%D (JDK1.%D%A)\n"
"\n"
"\n"
"<~D~o not create 'import' segment with external-references :R>\n"
"<~C~reate 'import' segment with references from commands :R>\n"
"<~F~ield/variable declarations are included in references :R>\n"
"<~M~ethod return types are included in references :R>>\n"
"\n"
"<~S~tore unknown attributes to external files :C>\n"
"<~R~ename local (slot) variables (if info is available) :C>\n"
"<Create ~v~isible representation of stripped names :C>\n"
"<Continue ~l~oading after errors in additional attributes :C>>\n"
"\n"
"\n";
CASSERT(((MLD__DEFAULT & MLD_METHREF) == 0 || (MLD__DEFAULT & MLD_VARREF) != 0)); //-V590
CASSERT(((MLD__DEFAULT & MLD_VARREF) == 0 || (MLD__DEFAULT & MLD_EXTREF) != 0)); //-V590
if ( !manual )
return MLD__DEFAULT;
short rtyp =
#if MLD__DEFAULT & MLD_METHREF
3;
#elif MLD__DEFAULT & MLD_VARREF
2;
#elif MLD__DEFAULT & MLD_EXTREF
1;
#else
0;
#endif
short mod = (MLD__DEFAULT & (MLD_EXTATR | MLD_LOCVAR | MLD_STRIP | MLD_FORCE)) >> 3; //lint !e572 Excessive shift value (precision 1 shifted right by 3)
CASSERT((MLD_EXTATR >> 3) == 1
&& (MLD_LOCVAR >> 3 ) == 2
&& (MLD_STRIP >> 3) == 4
&& (MLD_FORCE >> 3) == 8);
{
uval_t maxv = curClass.MajVers;
uval_t minv = curClass.MinVers;
uval_t jdk = curClass.JDKsubver;
if ( !ask_form(fmt, &maxv, &minv, &jdk,
jdk == 3 ? "/CLDC" : "",
&rtyp, &mod) )
qexit(1);
}
idpflags &= ~IDM_REQUNK; // do not use 'request mode' when 'manual options'
uchar ans = 0;
CASSERT(MLD_EXTATR == (1<<3)
&& MLD_LOCVAR == (2<<3)
&& MLD_STRIP == (4<<3)
&& MLD_FORCE == (8<<3));
ans |= ((uchar)mod) << 3;
CASSERT(MLD_EXTREF == 1 && MLD_VARREF == 2 && MLD_METHREF == 4);
ans |= (uchar)((1 << rtyp) - 1);
return ans;
}

View File

@@ -0,0 +1,37 @@
/*
* Interactive disassembler (IDA).
* Copyright (c) 1990-2021 Hex-Rays
* ALL RIGHTS RESERVED.
*
*/
#ifndef __JAVA_NOTIFY_CODES_HPP
#define __JAVA_NOTIFY_CODES_HPP
#include <idp.hpp>
//----------------------------------------------------------------------
// The following events are supported by the JAVA module in the ph.notify() function
namespace java_module_t
{
enum event_codes_t
{
ev_load_file = processor_t::ev_loader,
// load input file (see also function loader())
// in: linput_t *li
// bool manual
// Returns: 0-ok, otherwise-failed
};
inline processor_t::event_t idp_ev(event_codes_t ev)
{
return processor_t::event_t(ev);
}
inline bool load_file(linput_t *li, bool manual)
{
return processor_t::notify(idp_ev(ev_load_file), li, manual) == 0;
}
}
#endif // __JAVA_NOTIFY_CODES_HPP

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,104 @@
#ifndef _NPOOLUTI_HPP_
#define _NPOOLUTI_HPP_
#include "upgrade.hpp"
const char *constant_type_to_str(uchar ctype);
void print_constant(
qstrvec_t *out,
const const_desc_t &cd,
ushort index,
bool strip_tags=false);
void *myAlloc(uint size);
NORETURN void errtrunc(void);
//-------------------------------------------------------------------------
struct bootstrap_method_def_t
{
ushort method_ref;
qvector<ushort> args;
bootstrap_method_def_t() : method_ref(0) {}
};
nodeidx_t bootstrap_methods_get_node(bool assert=true, bool can_create=false);
nodeidx_t bootstrap_methods_get_count();
void bootstrap_methods_set_count(nodeidx_t cnt);
bool bootstrap_methods_get_method(
bootstrap_method_def_t *out,
nodeidx_t idx);
//-----------------------------------------------------------------------------
void make_NameChars(bool on_load);
enum namechar_op_t
{
ncop_disable,
ncop_enable,
ncop_enable_without_parens,
};
//-------------------------------------------------------------------------
void op_NameChars(namechar_op_t op);
//------------------
static void inline endLoad_NameChar(void)
{
op_NameChars(ncop_enable_without_parens); // end load base (remove '()')
}
//------------------
static void inline enableExt_NameChar(void)
{
op_NameChars(ncop_enable); //j_field_dlm; // (for searches)
}
//------------------
static void inline disableExt_NameChar(void)
{
op_NameChars(ncop_disable);
}
//-----------------------------------------------------------------------
struct _STROP_
{
ushort size;
ushort flags;
};
// new flags at VER15
#define _OP_NOSIGN 0x0001 // not signature (always +_OP_NODSCR)
#define _OP_METSIGN 0x0002 // method signature: <:>(...)ret
#define _OP_CLSSIGN 0x0004 // class signature: <:>super{iface}
//#define _OP_ 0x0008
//#define _OP_ 0x0010
#define _OP_JSMRES_ 0x0020 // name reserved in jasmin (asm support)
// end of new flags
#define _OP_ONECLS 0x0040 // descriptor has class reference
#define _OP_FULLNM 0x0080 // field have '.', '/' or [ => no FM name
#define _OP_NOFNM 0x0100 // can only descriptor. Not name
#define _OP_VALPOS 0x0200 // has posit for call descriptor
#define _OP_NODSCR 0x0400 // not descriptor
//#define _OP_NULL_ 0x0800 // has simbols 0
//#define _OP_NAT0_ 0x1000 // has simbols disabled in Xlat-table
//#define _OP_WIDE_ 0x2000 // has simbols >= 0x100
#define _OP_BADFIRST 0x1000 // first char in string is badStart for ident
#define _OP_UNICHARS 0x2000 // have valid unicode characters
#define _OP_UTF8_ 0x4000 // Utf8 String
#define _OP_EXTSYM_ 0x8000 // contain (!qisprint(english) && !isJavaIdent())
// ver12 bits
// #define _OP_UNICODE_ 0x8000 // Unicode String (removed? from standard)
// for jasmin reserved words checking
#define _OP_NOWORD uint32(0xFFFF & ~(_OP_NOSIGN|_OP_ONECLS|_OP_NODSCR|_OP_UTF8_))
// low bits used as temporary in VER12
// _OP_NULL_ | _OP_NAT0_ | _OP_WIDE_
CASSERT((UPG12_EXTMASK >> 16) == 0x7000
&& (UPG12_CLRMASK >> 16) == 0xF03F
&& (UPG12_BADMASK >> 16) == 0x8000
&& (UPG12_EXTSET >> 16) == _OP_EXTSYM_);
//-----------------------------------------------------------------------------
#endif

2160
idasdk76/module/java/out.cpp Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,813 @@
#include "java.hpp"
#include "oututil.hpp"
//--------------------------------------------------------------------------
// returns number of positions advanced
int out_java_t::out_commented(const char *p, color_t color)
{
if ( color != COLOR_NONE )
out_tagon(color);
size_t inplen = outbuf.length();
out_printf("%s %s", ash.cmnt, p);
int npos = outbuf.length() - inplen;
if ( color != COLOR_NONE )
out_tagoff(color);
return npos;
}
//----------------------------------------------------------------------
bool out_java_t::change_line(bool main)
{
bool overflow = false;
if ( pm().g_bufinited )
{
pm().outcnt = 0;
uchar sv = inf_get_indent();
inf_set_indent((uchar)pm().curpos);
overflow = flush_buf(outbuf.c_str(), main ? -1 : pm().curpos);
inf_set_indent(sv);
// for autocomment with call fmtName
outbuf.qclear();
outbuf.reserve(pm().g_bufsize);
}
return overflow;
}
//----------------------------------------------------------------------
size_t out_java_t::putLine(java_t &pm)
{
color_t color = COLOR_NONE;
if ( pm.g_bufinited )
{
const char *p = strrchr(outbuf.c_str(), COLOR_ON);
if ( p != NULL && p[1] && strchr(p+2, COLOR_OFF) == NULL ) // second - PARANOYA
{
color = (color_t)*(p + 1);
out_tagoff(color);
}
}
out_symbol('\\');
if ( change_line(pm.curpos != 0 && !pm.no_prim) )
return 0;
pm.curpos = 0;
if ( color != COLOR_NONE )
out_tagon(color);
pm.ref_pos = outbuf.length();
return pm.maxpos;
}
//----------------------------------------------------------------------
bool out_java_t::checkLine(size_t size)
{
if ( !pm().g_bufinited )
return true;
if ( pm().maxpos - pm().curpos > pm().outcnt + size )
return true;
return putLine(pm()) != 0;
}
//----------------------------------------------------------------------
bool out_java_t::chkOutLine(const char *str, size_t len)
{
if ( !checkLine(len) )
return true;
pm().outcnt += len;
out_line(str);
return false;
}
//----------------------------------------------------------------------
bool out_java_t::chkOutKeyword(const char *str, uint len)
{
if ( !checkLine(len) )
return true;
OutKeyword(str, len);
return false;
}
//----------------------------------------------------------------------
bool out_java_t::chkOutSymbol(char c)
{
if ( !checkLine(1) )
return true;
++pm().outcnt;
out_symbol(c);
return false;
}
//----------------------------------------------------------------------
bool out_java_t::chkOutChar(char c)
{
if ( !checkLine(1) )
return true;
++pm().outcnt;
out_char(c);
return false;
}
//----------------------------------------------------------------------
bool out_java_t::chkOutSymSpace(char c)
{
if ( !checkLine(2) )
return true;
out_symbol(c);
out_char(' ');
pm().outcnt += 2;
return false;
}
//----------------------------------------------------------------------
uchar out_java_t::putShort(ushort value, uchar wsym)
{
size_t inplen = outbuf.length();
out_tagon(COLOR_ERROR);
if ( wsym )
out_char(wsym);
out_btoa(value,
#ifdef __debug__
debugmode ? 16 :
#endif
10);
out_tagoff(COLOR_ERROR);
char tmpstr[32];
size_t curlen = outbuf.length();
size_t len = curlen - inplen;
qstrncpy(tmpstr, &outbuf[inplen], qmin(len+1, sizeof(tmpstr)));
outbuf.resize(inplen);
return chkOutLine(tmpstr, tag_strlen(tmpstr));
}
//----------------------------------------------------------------------
char out_java_t::outName(ea_t from, int n, ea_t ea, uval_t off, uchar *rbad)
{
qstring qbuf;
if ( get_name_expr(&qbuf, from, n, ea + off, off) <= 0 )
{
remember_problem(PR_NONAME, insn.ea);
return 0;
}
if ( chkOutLine(qbuf.begin(), tag_strlen(qbuf.begin())) )
{
*rbad = 1;
return 0;
}
return 1;
}
//---------------------------------------------------------------------------
uchar out_java_t::putVal(const op_t &x, uchar mode, uchar warn)
{
size_t inplen = outbuf.length();
{
flags_t saved = F;
F = 0;
out_value(x, mode);
F = saved;
}
char str[MAXSTR];
size_t curlen = outbuf.length();
size_t len = curlen - inplen;
qstrncpy(str, &outbuf[inplen], qmin(len+1, sizeof(str)));
outbuf.resize(inplen);
if ( warn )
out_tagon(COLOR_ERROR);
if ( warn )
{
qstring qstr;
len = tag_remove(&qstr, str);
qstrncpy(str, qstr.c_str(), sizeof(str));
}
else
{
len = tag_strlen(str);
}
if ( chkOutLine(str, len) )
return 0;
if ( warn )
out_tagoff(COLOR_ERROR);
return 1;
}
//----------------------------------------------------------------------
CASSERT(MIN_ARG_SIZE >= 2 && MIN_ARG_SIZE < 30);
uchar out_java_t::OutUtf8(ushort index, fmt_t mode, color_t color)
{
size_t size = (pm().maxpos - pm().curpos) - pm().outcnt;
if ( (int)size <= MIN_ARG_SIZE )
{
DEB_ASSERT(((int)size < 0), "OutUtf8");
size = putLine(pm());
if ( size == 0 )
return 1;
}
if ( color != COLOR_NONE )
out_tagon(color);
pm().ref_pos = outbuf.length();
struct ida_local lambda_t
{
static size_t call_putLine(java_t &pm, out_java_t *oj)
{
return oj->putLine(pm);
}
};
if ( fmtString(pm(), index, size, mode, lambda_t::call_putLine) < 0 )
return 1;
pm().outcnt += outbuf.length() - pm().ref_pos;
if ( color != COLOR_NONE )
out_tagoff(color);
return 0;
}
//---------------------------------------------------------------------------
uchar out_java_t::out_index(ushort index, fmt_t mode, color_t color, uchar as_index)
{
if ( as_index )
{
if ( !(pm().idpflags & (IDM_BADIDXSTR | IDM_OUTASM)) // no store in file
|| !pm().is_valid_string_index(index) )
{
return putShort(index);
}
color = COLOR_ERROR;
mode = fmt_string;
}
return OutUtf8(index, mode, color);
}
//--------------------------------------------------------------------------
uchar out_java_t::out_alt_ind(uint32 val)
{
if ( (ushort)val )
return OutUtf8((ushort)val, fmt_fullname, COLOR_IMPNAME);
return putShort((ushort)(val >> 16));
}
//--------------------------------------------------------------------------
// special label format/scan procedures
//--------------------------------------------------------------------------
void out_java_t::out_method_label(uchar is_end)
{
set_gen_cmt(true);
set_gen_xrefs(true);
gen_printf(0, COLSTR("met%03u_%s%s", SCOLOR_CODNAME), pm().curSeg.id.Number,
is_end ? "end" : "begin", COLSTR(":", SCOLOR_SYMBOL));
}
//---------------------------------------------------------------------------
char out_java_t::putMethodLabel(ushort off)
{
char str[32];
int len = qsnprintf(str, sizeof(str), "met%03u_%s", pm().curSeg.id.Number,
off ? "end" : "begin");
if ( !checkLine(len) )
return 1;
out_tagon(COLOR_CODNAME);
outLine(str, len);
out_tagoff(COLOR_CODNAME);
return 0;
}
//--------------------------------------------------------------------------
// procedure for get_ref_addr
ssize_t java_t::check_special_label(const char *buf, size_t len) const
{
if ( len >= sizeof("met000_end")-1
&& (*(uint32*)buf & 0xFFFFFF) == ('m'|('e'<<8)|('t'<<16)) )
{
switch ( *(uint32*)&buf[len -= 4] )
{
case ('_'|('e'<<8)|('n'<<16)|('d'<<24)):
break;
case ('e'|('g'<<8)|('i'<<16)|('n'<<24)):
if ( len >= sizeof("met000_begin")-1 - 4
&& *(ushort*)&buf[len -= 2] == ('_'|('b'<<8)) )
{
break;
}
// no break
default:
len |= -1; // as flag
break;
}
if ( len <= sizeof("met00000")-1 )
{
size_t off = curSeg.CodeSize;
if ( buf[len+1] == 'b' )
off = 0;
size_t n = 0;
size_t j = sizeof("met")-1;
while ( true )
{
if ( !qisdigit((uchar)buf[j]) )
break;
n = n*10 + (buf[j] - '0');
if ( ++j == len )
{
if ( n >= 0x10000 || (ushort)n != curSeg.id.Number )
break;
return off;
}
}
}
}
return -1;
}
//--------------------------------------------------------------------------
// end of special-label procedures
//----------------------------------------------------------------------
uchar out_java_t::outOffName(ushort off)
{
if ( !off || off == pm().curSeg.CodeSize )
return putMethodLabel(off);
if ( off < pm().curSeg.CodeSize )
{
uchar err = 0;
if ( outName(pm().curSeg.start_ea + pm().curSeg.CodeSize, 0,
pm().curSeg.start_ea, off, &err) )
return 0; // good
if ( err )
return 1; // bad
}
return putShort(off, 0);
}
//----------------------------------------------------------------------
bool out_java_t::block_begin(uchar off)
{
return flush_buf(COLSTR("{", SCOLOR_SYMBOL), off);
}
//----------------------------------------------------------------------
bool out_java_t::block_end(uint32 off)
{
return flush_buf(COLSTR("}", SCOLOR_SYMBOL), off);
}
//----------------------------------------------------------------------
bool out_java_t::block_close(uint32 off, const char *name)
{
if ( !jasmin() )
return block_end(off);
return gen_printf(off, COLSTR(".end %s", SCOLOR_KEYWORD), name);
}
//----------------------------------------------------------------------
bool out_java_t::close_comment(void)
{
return flush_buf(COLSTR("*/", SCOLOR_AUTOCMT), 0);
}
//---------------------------------------------------------------------------
uchar out_java_t::out_nodelist(uval_t nodeid, uchar pos, const char *pref)
{
netnode node(nodeid);
uval_t cnt = node.altval(0);
if ( cnt == 0 )
DESTROYED("out::nodelist");
uval_t off = 0;
if ( pref ) // jasmin
{
if ( change_line() )
{
bad:
return 0;
}
off = strlen(pref);
}
uint i = 0;
while ( true )
{
if ( pref ) // jasmin (single directive per line)
{
pm().curpos = pos;
out_keyword(pref);
pm().outcnt = off;
}
else if ( i && chkOutSymSpace(',') )
{
goto bad; // prompted list
}
if ( out_alt_ind((uint32)node.altval(++i)) )
goto bad;
if ( i >= cnt )
return 1;
if ( pref && change_line() )
goto bad; // jasmin
}
}
//----------------------------------------------------------------------
void out_java_t::init_prompted_output(uchar pos)
{
pm().maxpos = inf_get_margin();
// if ( maxpos < 32 )
// maxpos = 32;
// if ( maxpos > MAXSTR - 4 )
// maxpos = MAXSTR - 4;
#ifdef __debug__
if ( debugmode == -1
&& inf.show_line_pref() && inf_get_margin() == 77 && !inf.bin_prefix_size )
{
maxpos -= gl_psize;
}
#endif
pm().g_bufsize = (MAXSTR*2) - STR_PRESERVED;
pm().g_bufinited = true;
outbuf.qclear();
outbuf.reserve(pm().g_bufsize);
pm().curpos = pos;
pm().outcnt = 0;
}
//----------------------------------------------------------------------
void out_java_t::term_prompted_output(void)
{
outbuf.qclear();
pm().g_bufinited = false;
pm().g_bufsize = 0;
pm().maxpos = 0;
pm().curpos = -1;
}
//----------------------------------------------------------------------
uchar out_java_t::OutConstant(const op_t &_x, bool include_descriptor)
{
op_t x = _x;
fmt_t fmt = fmt_FieldDescriptor;
color_t color;
insn_t cur_insn;
decode_insn(&cur_insn, insn_ea);
switch ( (uchar)x.cp_type )
{
default:
warning("OC: bad constant type %u", (uchar)x.cp_type);
break;
case CONSTANT_Long:
x.dtype = dt_qword;
goto outNum;
case CONSTANT_Double:
x.dtype = dt_double;
goto outNum;
case CONSTANT_Integer:
x.dtype = dt_dword;
goto outNum;
case CONSTANT_Float:
x.dtype = dt_float;
outNum:
if ( putVal(x, OOF_NUMBER | OOF_SIGNED | OOFW_IMM, 0) )
break;
badconst:
return 0;
case CONSTANT_Utf8:
if ( OutUtf8(x.cp_ind, fmt_string, COLOR_STRING) )
goto badconst;
break;
case CONSTANT_String:
if ( OutUtf8(x._name, fmt_string, COLOR_STRING) )
goto badconst;
break;
case CONSTANT_NameAndType:
nameandtype:
if ( OutUtf8(x._class, fmt_fullname)
|| OutUtf8(x._name, fmt_fullname) )
{
goto badconst;
}
break;
case CONSTANT_InvokeDynamic:
{
const_desc_t invdyn;
if ( pm().ConstantNode.supval(x.cp_ind, &invdyn, sizeof(invdyn)) != sizeof(invdyn) )
goto badconst;
// Retrieve NameAndType
const_desc_t nat;
if ( pm().ConstantNode.supval(invdyn._name, &nat, sizeof(nat)) != sizeof(nat) )
goto badconst;
memset(&x, 0, sizeof(x));
copy_const_to_opnd(x, nat);
x.ref = 0;
x.cp_type = nat.type;
x.cp_ind = invdyn._name;
goto nameandtype;
}
break;
case CONSTANT_MethodHandle:
{
const_desc_t tmp;
if ( pm().ConstantNode.supval(x._mhr_index, &tmp, sizeof(tmp)) != sizeof(tmp) )
goto badconst;
op_t tmpop;
memset(&tmpop, 0, sizeof(tmpop));
copy_const_to_opnd(tmpop, tmp);
tmpop.ref = 0; // as flag
tmpop.cp_type = tmp.type;
tmpop.cp_ind = x._mhr_index;
OutConstant(tmpop, include_descriptor);
}
break;
case CONSTANT_MethodType:
if ( OutUtf8(x._mtd_index, fmt_fullname, COLOR_KEYWORD) )
goto badconst;
break;
case CONSTANT_Class:
CASSERT((fmt_ClassName_or_Array+1) == fmt_ClassName && (fmt_ClassName+1) == fmt_fullname);
{
fmt_t f2 = (fmt_t )x.addr_shorts.high;
color_t c2 = f2 < fmt_ClassName_or_Array || f2 > fmt_fullname ? COLOR_KEYWORD
: cur_insn.xtrn_ip == 0xFFFF ? COLOR_DNAME : COLOR_IMPNAME;
if ( OutUtf8(x._name, f2, c2) )
goto badconst;
}
break;
case CONSTANT_InterfaceMethodref:
case CONSTANT_Methodref:
fmt = fmt_method_ReturnType;
// fallthrough
case CONSTANT_Fieldref:
#ifdef VIEW_WITHOUT_TYPE
if ( include_descriptor )
#endif
if ( !jasmin() && OutUtf8(x._dscr, fmt, COLOR_KEYWORD) )
goto badconst;
color = x._class == pm().curClass.This.Dscr ? COLOR_DNAME : COLOR_IMPNAME;
out_tagon(color);
if ( jasmin() || (color == COLOR_IMPNAME && !include_descriptor) ) // other class
{
if ( OutUtf8(x._name, fmt_ClassName) || chkOutDot() )
goto badconst;
}
if ( OutUtf8(x._subnam, fmt_UnqualifiedName) )
goto badconst; // Field
out_tagoff(color);
if ( jasmin() )
{
if ( fmt == fmt_method_ReturnType )
fmt = fmt_FieldDescriptor_nospace; // no space at end
else if ( chkOutSpace() )
goto badconst;
}
else
{
if ( fmt != fmt_method_ReturnType )
break;
fmt = fmt_method_TypeSignature;
}
if ( OutUtf8(x._dscr, fmt, COLOR_KEYWORD) )
goto badconst;
break;
}
return 1;
}
//--------------------------------------------------------------------------
// FIXME: there should be a better way of suppressing borders in disassembly
void out_java_t::myBorder(void)
{
gen_empty_line();
if ( pm().user_limiter )
{
inf_set_limiter(LMT_THIN);
gen_border_line(false);
}
inf_set_limiter(0); // do not output border between method & vars :(
}
//--------------------------------------------------------------------------
uchar out_java_t::out_problems(char str[MAXSTR], const char *prefix)
{
if ( pm().curClass.extflg & XFL_C_ERRLOAD )
{
myBorder();
gen_printf(DEFAULT_INDENT,
COLSTR("%s This class has had loading time problem(s)", SCOLOR_ERROR),
prefix);
if ( pm().curClass.msgNode )
{
gen_empty_line();
if ( pm().print_loader_messages(str, prefix, this) == -1 )
return 1;
}
myBorder();
}
return 0;
}
//--------------------------------------------------------------------------
uchar out_java_t::putScope(ushort scope, uint32 doff)
{
if ( !scope || scope == pm().curSeg.CodeSize )
return putMethodLabel(scope);
if ( scope < pm().curSeg.CodeSize )
{
uchar err = 0;
if ( outName(pm().curSeg.DataBase + doff, 0, pm().curSeg.start_ea, scope, &err) )
return 0;
if ( err )
return 1;
}
return putShort(scope, 0);
}
//----------------------------------------------------------------------
size_t out_java_t::debLine(java_t &)
{
out_char('"');
out_tagoff(COLOR_STRING);
if ( change_line() )
return 0;
return putDeb(1);
}
//----------------------------------------------------------------------
void out_java_t::OutKeyword(const char *str, size_t len)
{
pm().outcnt += len;
out_keyword(str);
}
//----------------------------------------------------------------------
void out_java_t::outLine(const char *str, uint len)
{
pm().outcnt += len;
out_line(str);
}
//----------------------------------------------------------------------
uchar out_java_t::chkOutDot(void)
{
return chkOutChar('.');
}
//----------------------------------------------------------------------
void out_java_t::OutSpace(void)
{
++pm().outcnt;
out_char(' ');
}
//----------------------------------------------------------------------
uchar out_java_t::chkOutSpace(void)
{
return chkOutChar(' ');
}
//--------------------------------------------------------------------------
size_t out_java_t::putDeb(uchar next)
{
OUT_KEYWORD(".debug ");
out_tagon(COLOR_STRING);
if ( next )
out_char('"');
return pm().maxpos - pm().outcnt;
}
//----------------------------------------------------------------------
bool out_java_t::out_operand(const op_t &x)
{
int outf;
uchar warn = 0;
switch ( x.type )
{
case o_near:
if ( x.ref )
{
++warn;
}
else
{
if ( outName(insn.ea + x.offb, x.n, pm().curSeg.start_ea, x.addr, &warn) )
break;
if ( warn )
goto badop;
}
if ( putVal(x, OOF_ADDR | OOF_NUMBER | OOFS_NOSIGN | OOFW_32, warn) )
break;
// no break
case o_void:
badop:
return false;
case o_imm:
if ( x.ref == 2 )
++warn;
outf = OOFW_IMM | OOF_NUMBER | (x.ref ? OOFS_NOSIGN : OOF_SIGNED);
if ( putVal(x, outf, warn) )
break;
goto badop;
case o_mem:
if ( jasmin() )
goto putidcv_num;
if ( x.ref )
{
putAddr:
++warn;
}
else
{
if ( outName(insn.ea + x.offb, x.n, pm().curSeg.DataBase, x.addr, &warn) )
break;
if ( warn )
goto badop;
}
putidcv_num:
if ( putVal(x, OOF_ADDR | OOF_NUMBER | OOFS_NOSIGN | OOFW_16, warn) )
break;
goto badop;
case o_cpool:
if ( !x.cp_ind )
{
OUT_KEYWORD("NULL");
}
else
{
if ( x.ref )
goto putAddr;
if ( !OutConstant(x) )
goto badop;
}
break;
case o_array:
if ( !x.ref )
{
uchar btype = 0;
switch ( uchar(x.cp_type) )
{
case T_BOOLEAN: btype = j_bool; break;
case T_CHAR: btype = j_char; break;
case T_FLOAT: btype = j_float; break;
case T_DOUBLE: btype = j_double; break;
case T_BYTE: btype = j_byte; break;
case T_SHORT: btype = j_short; break;
case T_INT: btype = j_int; break;
case T_LONG: btype = j_long; break;
}
const TXS *tname = get_base_typename(btype);
if ( tname == 0 || chkOutKeyword(tname->str, tname->size) )
goto badop;
}
else
{
static const char tt_bogust[] = "BOGUST_TYPE-";
if ( !checkLine(sizeof(tt_bogust) + 2) )
goto badop;
out_tagon(COLOR_ERROR);
size_t inplen = outbuf.length();
out_printf("%c%s%u", WARN_SYM, tt_bogust, (uchar)x.cp_type);
pm().outcnt += outbuf.length() - inplen;
out_tagoff(COLOR_ERROR);
}
break;
default:
warning("out: %a: bad optype %d", insn.ip, x.type);
break;
}
return true;
}
//--------------------------------------------------------------------------
void java_t::java_footer(outctx_t &ctx)
{
if ( !jasmin() )
{
out_java_t *p = (out_java_t *)&ctx;
p->block_end(0);
}
}

View File

@@ -0,0 +1,117 @@
#ifndef _OUTUTIL_HPP__
#define _OUTUTIL_HPP__
const color_t COLOR_NONE = 0;
#define WARN_SYM ('#')
#define MIN_ARG_SIZE 3
#define STR_PRESERVED 64 // overlapped (MAXSTR*2) preservation (for color)
class out_java_t;
//----------------------------------------------------------------------
#ifdef TEST_FMTSTR
class out_java_t
{
public:
qstring outbuf;
void out_char(char c);
void out_line(const char *str);
private:
AS_PRINTF(2, 0) void out_vprintf(const char *format, va_list va);
};
#else
class out_java_t : public outctx_t
{
out_java_t(void) = delete; // not used
// due to create_context() call we cannot use PM from outctx_t
java_t &pm() { return *GET_MODULE_DATA(java_t); }
inline bool jasmin(void) const { return GET_MODULE_DATA(java_t)->jasmin(); }
public:
// oututil.cpp
int out_commented(const char *p, color_t color = COLOR_NONE);
bool change_line(bool main = false);
size_t putLine(java_t &pm);
bool checkLine(size_t size);
bool chkOutLine(const char *str, size_t len);
bool chkOutKeyword(const char *str, uint len);
bool chkOutSymbol(char c);
bool chkOutChar(char c);
bool chkOutSymSpace(char c);
uchar putShort(ushort value, uchar wsym = WARN_SYM);
char outName(ea_t from, int n, ea_t ea, uval_t off, uchar *rbad);
uchar putVal(const op_t &x, uchar mode, uchar warn);
uchar OutUtf8(ushort index, fmt_t mode, color_t color = COLOR_NONE);
uchar out_index(ushort index, fmt_t mode, color_t color, uchar as_index);
uchar out_alt_ind(uint32 val);
void out_method_label(uchar is_end);
uchar outOffName(ushort off);
bool block_begin(uchar off);
bool block_end(uint32 off);
bool block_close(uint32 off, const char *name);
bool close_comment(void);
uchar out_nodelist(uval_t nodeid, uchar pos, const char *pref);
void init_prompted_output(uchar pos = 0);
void term_prompted_output(void);
uchar OutConstant(const op_t &_x, bool include_descriptor=false);
void myBorder(void);
uchar out_problems(char str[MAXSTR], const char *prefix);
uchar putScope(ushort scope, uint32 doff);
size_t debLine(java_t &pm);
void OutKeyword(const char *str, size_t len);
void outLine(const char *str, uint len);
uchar chkOutDot(void);
void OutSpace(void);
uchar chkOutSpace(void);
size_t putDeb(uchar next);
bool out_operand(const op_t &x);
void out_insn(void);
void out_proc_mnem(void);
// npooluti.cpp
size_t _one_line(void) { return 0; }
int fmtString(java_t &pm, ushort index, ssize_t size, fmt_t mode, _PRMPT_ putproc = NULL);
void trunc_name(uint num, uchar type = 0);
// out.cpp
bool out_sm_end(void);
bool out_deprecated(uchar pos);
bool out_sm_start(int same);
bool out_stackmap(const SMinfo *pinf);
uchar OutModes(uint32 mode);
uchar sign_out(ushort utsign, char mode);
void out_switch(void);
bool close_annotation(uint32 pos);
const ushort *annotation(const ushort *p, uint *plen, uint pos);
const ushort *annotation_element(const ushort *p, uint *plen, uint pos, ushort name);
uchar annotation_loop(const uval_t *pnodes, uint nodecnt);
uchar enclose_out(void);
uchar out_seg_type(fmt_t fmt);
uchar out_field_type(void);
uchar out_includes(uval_t node, uchar pos);
void java_header(void);
void java_segstart(segment_t *seg);
void java_segend(segment_t *seg);
void java_data(bool /*analyze_only*/);
// map.cpp
bool print_newline(void);
size_t write_utf(void);
private:
char putMethodLabel(ushort off);
};
CASSERT(sizeof(out_java_t) == sizeof(outctx_t));
#endif // TEST_FMTSTR
//----------------------------------------------------------------------
#define CHK_OUT_STR(p) chkOutLine(p, sizeof(p)-1)
#define OUT_KEYWORD(p) OutKeyword(p, sizeof(p)-1)
#define CHK_OUT_KEYWORD(p) chkOutKeyword(p, sizeof(p)-1)
#define OUT_STR(p) outLine(p, sizeof(p)-1)
#endif

View File

@@ -0,0 +1,822 @@
/*
* Interactive disassembler (IDA)
* Copyright (c) 1990-98 by Ilfak Guilfanov.
* E-mail: ig@datarescue.com
* JVM module.
* Copyright (c) 1995-2006 by Iouri Kharon.
* E-mail: yjh@styx.cabel.net
*
* ALL RIGHTS RESERVED.
*
*/
#include "java.hpp"
#include <diskio.hpp>
#include <ieee.h>
#include "npooluti.hpp"
#include "notify_codes.hpp"
int data_id;
//-----------------------------------------------------------------------
#ifdef __debug__
NORETURN void _destroyed(const char *from)
{
error("Database is corrupted! [at: %s]", from);
}
//-----------------------------------------------------------------------
NORETURN void _faterr(uchar mode, const char *from)
{
error("Internal error (%s) [at: %s]",
mode ? "compatibility" : "idp",
from);
}
#else
//-----------------------------------------------------------------------
NORETURN void _destroyed(void)
{
error("Database is corrupted!");
}
//-----------------------------------------------------------------------
NORETURN void _faterr(uchar mode)
{
error("Internal error (%s)", mode ? "compatibility" : "idp");
}
#endif
//-----------------------------------------------------------------------
void java_t::sm_validate(const SegInfo *si)
{
ea_t segTopEA = si->start_ea + si->CodeSize;
netnode temp(si->smNode);
nodeidx_t nid = temp.supfirst();
if ( (ea_t)nid < si->start_ea )
goto destroyed;
do
{
if ( (ea_t)nid >= segTopEA )
goto destroyed;
if ( temp.supval(nid, NULL, 0) != sizeof(sm_info_t) )
goto destroyed;
if ( !is_head(get_flags((ea_t)nid)) )
{
remember_problem(PR_HEAD, (ea_t)nid);
if ( !displayed_nl )
{
displayed_nl = true;
msg("\n");
}
msg("StackMap refers to nonHead offset %X in Method#%u\n",
(uint32)((ea_t)nid - si->start_ea), si->id.Number);
}
nid = temp.supnext(nid);
}
while ( nid != BADNODE );
return;
destroyed:
DESTROYED("sm_validate");
}
//----------------------------------------------------------------------
// visble for upgrade ONLY
void java_t::coagulate_unused_data(const SegInfo *ps)
{
uint size = 0;
ea_t ea = ps->DataBase;
ea_t top = ea + ps->DataSize;
for ( ; ea < top; ea++ )
{
if ( is_head(get_flags(ea))
&& get_first_dref_to(ea) == BADADDR )
{
ConstantNode.chardel(ea, UR_TAG); // unicode renaming support
del_global_name(ea);
del_items(ea, DELIT_SIMPLE);
++size;
ea_t to;
while ( (to=get_first_dref_from(ea)) != BADADDR )
del_dref(ea, to);
}
else if ( size )
{
create_data(ea-size, align_flag(), size, BADNODE);
size = 0;
}
}
if ( size )
create_data(ea-size, align_flag(), size, BADNODE);
}
//--------------------------------------------------------------------------
//--------------------------------------------------------------------------
static int idaapi out_asm_file(
FILE *fp,
const qstring &line,
bgcolor_t,
bgcolor_t)
{
qstring qbuf;
tag_remove(&qbuf, line);
size_t len = qbuf.length();
size_t chk = len;
if ( qbuf.last() == '\\' )
--len;
if ( qfwrite(fp, qbuf.c_str(), len) != len )
return 0;
if ( chk == len && qfputc('\n', fp) == EOF )
return 0;
return 1;
}
//----------------------------------------------------------------------
static void idaapi func_header(outctx_t &ctx, func_t *) { ctx.ctxflags |= CTXF_LABEL_OK; }
static void idaapi func_footer(outctx_t &, func_t *) {}
static bool idaapi java_specseg(outctx_t &ctx, uchar) { java_data(ctx, false); return false; }
//----------------------------------------------------------------------
// floating point conversion
fpvalue_error_t idaapi j_realcvt(void *m, fpvalue_t *e, ushort swt)
{
return ieee_realcvt(m, e, swt | 0x80);
}
//----------------------------------------------------------------------
// Set IDP options. Either from the configuration file either allow the user
// to specify them in a dialog box.
const char *java_t::set_idp_options(
const char *keyword,
int value_type,
const void * value,
bool idb_loaded)
{
static const char form[] =
"HELP\n"
"JAVA specific options\n"
"\n"
" Multiline .debug\n"
"\n"
" If this option is on, IDA forces new .debug directive at every\n"
" LR ('\\n') in the input string\n"
"\n"
" Hide StackMap(s)\n"
"\n"
" If this option is on, IDA hides .stack verification declarations\n"
"\n"
" Auto strings\n"
"\n"
" If this option is on, IDA makes 'prompt-string' after every CR in\n"
" the quoted-string operand\n"
"\n"
" Save to jasmin\n"
"\n"
" If this option is on, IDA creates asm-file in the jasmin-\n"
" compatibe form: concatenates 'prompted' string, reserved names\n"
" will be enclosed in quotes.\n"
" Also when this option is on IDA changes unicode-to-oem encoding to\n"
" unicode-to-ansi encoding because jasmin expects ansi encoding.\n"
"\n"
" Enable encoding\n"
"\n"
" If this option is on, IDA converts unicode characters which\n"
" can't be represented in current locale to ascii characters.\n"
"\n"
" Nopath .attribute\n"
" If this option is on, IDA prints filename in '.attribute'\n"
" directives without the path part.\n"
"\n"
"\n"
" Bad index as string\n"
" If this option is on, IDA will show invalid name/type references\n"
" as a quoted string.\n"
"ENDHELP\n"
"JAVA specific options\n"
"\n"
" <~M~ultilne .debug :C>\n"
" <~H~ide StackMap(s) :C>\n"
" <~A~uto strings :C>\n"
" <~S~ave to jasmin :C>\n"
" <~E~nable encoding :C>\n"
" <~N~opath .attribute :C>>\n"
"\n"
" <~B~ad index as string :C>>\n"
"\n"
"\n";
if ( !keyword )
{
ushort tmp = (idpflags >> 16) & IDM__REQMASK;
ushort flags = idpflags;
if ( ask_form(form, &flags, &tmp) )
{
int32 old = idpflags;
idpflags = (flags & ~(IDM__REQMASK << 16)) | (tmp << 16);
if ( (idpflags ^ old) & IDF_ENCODING )
rename_uninames(-1);
}
goto SAVE;
}
if ( value_type != IDPOPT_BIT )
return IDPOPT_BADTYPE;
struct keyword_info_t
{
const char *name;
int bit;
};
static const keyword_info_t keywords[] =
{
{ "JAVA_MULTILINE_DEBUG", IDF_MULTDEB },
{ "JAVA_HIDE_STACKMAP", IDF_HIDESM },
{ "JAVA_AUTO_STRING", IDF_AUTOSTR },
{ "JAVA_ASMFILE_CONVERT", IDF_CONVERT },
{ "JAVA_ENABLE_ENCODING", IDF_ENCODING },
{ "JAVA_NOPATH_ATTRIBUTE", IDF_NOPATH },
{ "JAVA_UNKATTR_REQUEST", IDM_REQUNK },
{ "JAVA_UNKATTR_WARNING", IDM_WARNUNK },
};
for ( int i=0; i < qnumber(keywords); i++ )
{
if ( strcmp(keywords[i].name, keyword) == 0 )
{
setflag(idpflags, keywords[i].bit, *(int*)value != 0);
goto SAVE;
}
}
if ( streq(keyword, "JAVA_STARTASM_LIST") )
{
start_asm_list = *(int*)value;
return IDPOPT_OK;
}
else
{
return IDPOPT_BADKEY;
}
SAVE:
if ( idb_loaded )
ConstantNode.altset(CNA_IDPFLAGS, (ushort)idpflags);
return IDPOPT_OK;
}
//----------------------------------------------------------------------
static const asm_t jasmin_asm =
{
AS_COLON | ASH_HEXF3 | ASO_OCTF1 | ASD_DECF0 | AS_ONEDUP | ASB_BINF3,
UAS_JASMIN,
"Jasmin assembler",
0, // no help screen
NULL, // header
NULL, // origin
NULL, // end of file
";", // comment string
'"', // string delimiter
'\'', // char delimiter
"\"'\\", // special symbols in char and string constants
"", // ascii string directive
"", // byte directive
NULL, // word directive
NULL, // double words
NULL, // qwords
NULL, // oword (16 bytes)
NULL, // float
NULL, // double
NULL, // no tbytes
NULL, // no packreal
NULL, // arrays:
// #h - header(.byte,.word)
// #d - size of array
// #v - value of array elements
NULL, //".reserv %s", // uninited data (reserve space)
" = ", // equ
NULL, // seg prefix
NULL, // a_curip
func_header, // func header
func_footer, // func footer
"", // public (disable ouput)
NULL, // weak
NULL, // extrn
NULL, // comm
NULL, // get_type_name
NULL, // align
'(', ')', // lbrace, rbrace
NULL, // mod
"&", // and
"|", // or
"^", // xor
"!", // not
"<<", // shl
">>", // shr
NULL, // sizeof
0, // flag2
NULL, // cmnt2
NULL, // low8
NULL, // high8
NULL, // low16
NULL, // high16
NULL, // a_include_fmt
NULL, // a_vstruc_fmt
NULL, // a_rva
};
//----------------------------------------------------------------------
static const asm_t list_asm =
{
AS_COLON | ASH_HEXF3 | ASO_OCTF1 | ASD_DECF0 | AS_ONEDUP | ASB_BINF3,
0,
"User friendly listing",
0, // no help screen
NULL, // header
NULL, // origin
NULL, // end of file
"//", // comment string
'"', // string delimiter
'\'', // char delimiter
"\"'\\", // special symbols in char and string constants
"", // ascii string directive
"", // byte directive
NULL, // word directive
NULL, // double words
NULL, // qwords
NULL, // oword (16 bytes)
NULL, // float
NULL, // double
NULL, // no tbytes
NULL, // no packreal
NULL, // arrays:
// #h - header(.byte,.word)
// #d - size of array
// #v - value of array elements
NULL, //".reserv %s", // uninited data (reserve space)
" = ", // equ
NULL, // seg prefix
NULL, // a_curip
func_header, // func header
func_footer, // func footer
"", // public (disable ouput)
NULL, // weak
NULL, // extrn
NULL, // comm
NULL, // get_type_name
NULL, // align
'(', ')', // lbrace, rbrace
NULL, // mod
"&", // and
"|", // or
"^", // xor
"!", // not
"<<", // shl
">>", // shr
NULL, // sizeof
0, // flag2
NULL, // cmnt2
NULL, // low8
NULL, // high8
NULL, // low16
NULL, // high16
NULL, // a_include_fmt
NULL, // a_vstruc_fmt
NULL, // a_rva
};
//-----------------------------------------------------------------------
static const asm_t *const asms[] = { &jasmin_asm, &list_asm, NULL };
static const char *const RegNames[] = { "vars", "optop", "frame", "cs", "ds" };
#define FAMILY "Java Virtual Machine:"
static const char *const shnames[] =
{
"java",
#ifdef __debug__
"_javaPC",
#endif
NULL
};
static const char *const lnames[] =
{
FAMILY"Java",
#ifdef __debug__
"Java full (IBM PC, debug mode)",
#endif
NULL
};
//--------------------------------------------------------------------------
static const uchar retcode_0[] = { j_ret };
static const uchar retcode_1[] = { j_ireturn };
static const uchar retcode_2[] = { j_lreturn };
static const uchar retcode_3[] = { j_freturn };
static const uchar retcode_4[] = { j_dreturn };
static const uchar retcode_5[] = { j_areturn };
static const uchar retcode_6[] = { j_return };
static const uchar retcode_7[] = { j_wide, j_ret };
static const bytes_t retcodes[] =
{
{ sizeof(retcode_0), retcode_0 },
{ sizeof(retcode_1), retcode_1 },
{ sizeof(retcode_2), retcode_2 },
{ sizeof(retcode_3), retcode_3 },
{ sizeof(retcode_4), retcode_4 },
{ sizeof(retcode_5), retcode_5 },
{ sizeof(retcode_6), retcode_6 },
{ sizeof(retcode_7), retcode_7 },
{ 0, NULL }
};
//--------------------------------------------------------------------------
ssize_t idaapi idb_listener_t::on_event(ssize_t code, va_list)
{
switch ( code )
{
case idb_event::closebase:
memset(&pm.curClass, 0, sizeof(pm.curClass));
// no break
case idb_event::savebase:
pm.ConstantNode.altset(CNA_IDPFLAGS, (ushort)pm.idpflags);
break;
case idb_event::auto_empty:
if ( !(pm.curClass.extflg & XFL_C_DONE) ) // kernel BUGs
{
pm.curClass.extflg |= XFL_C_DONE;
msg("JavaLoader finalization stage...");
for ( int n = pm.curClass.MethodCnt; n; n-- )
{
SegInfo si;
if ( pm.ClassNode.supval(-n, &si, sizeof(si)) != sizeof(si) )
DESTROYED("postprocess");
if ( si.smNode || si.DataSize )
{
show_addr(si.start_ea);
if ( si.smNode )
pm.sm_validate(&si);
if ( si.DataSize )
pm.coagulate_unused_data(&si);
}
}
pm.ConstantNode.supset(CNS_CLASS, &pm.curClass, sizeof(pm.curClass)); // all chgs
pm.sm_node = smn_ok;
msg("OK\n");
}
break;
}
return 0;
}
//----------------------------------------------------------------------
// This old-style callback only returns the processor module object.
static ssize_t idaapi notify(void *, int msgid, va_list)
{
if ( msgid == processor_t::ev_get_procmod )
return size_t(SET_MODULE_DATA(java_t));
return 0;
}
//--------------------------------------------------------------------------
ssize_t idaapi java_t::on_event(ssize_t msgid, va_list va)
{
int retcode = 0;
switch ( msgid )
{
case processor_t::ev_init:
hook_event_listener(HT_IDB, &idb_listener, &LPH);
inf_set_be(true); // reverse byte!
break;
case processor_t::ev_rename:
va_arg(va, ea_t);
for ( char const *pn, *p = va_arg(va, const char *);
(pn = strchr(p, '\\')) != NULL;
p = pn+1 )
{
if ( *++pn != 'u' )
{
inv_name:
--retcode; // 0
warning("Backslash is accepted only as a unicode escape sequence in names");
break;
}
for ( int i = 0; i < 4; i++ )
if ( !qisxdigit((uchar)*++pn) )
goto inv_name;
}
break;
case processor_t::ev_newfile:
if ( inf_get_filetype() != f_LOADER )
{
set_database_flag(DBFL_KILL); // clean up the database files
error("The input file does not have a supported Java file format");
}
database_loaded (va_arg(va, char *));
inf_set_lowoff(BADADDR);
inf_set_highoff(BADADDR);
break;
case processor_t::ev_ending_undo:
case processor_t::ev_oldfile:
database_loaded(NULL);
break;
case processor_t::ev_term:
unhook_event_listener(HT_IDB, &idb_listener);
qfree(tsPtr);
qfree(smBuf);
qfree(annBuf);
clr_module_data(data_id);
break;
#ifdef __debug__
case processor_t::ev_newprc:
{
int procnum = va_arg(va, int);
bool keep_cfg = va_argi(va, bool);
if ( procnum == 1 ) // debug mode
{
ph.flag &= ~(PR_DEFNUM | PR_NOCHANGE);
ph.flag |= PRN_HEX;
if ( inf_get_margin() == 77 && !inf.bin_prefix_size && !inf.show_line_pref() )
{
if ( !keep_cfg )
inf_set_show_line_pref(true);
--debugmode;
}
else
{
++debugmode;
}
}
else // normal node
{
ph.flag &= ~PR_DEFNUM;
ph.flag |= PRN_DEC;
if ( debugmode == -1
&& inf.show_line_pref()
&& !inf.bin_prefix_size
&& inf_get_margin() == 77
&& !keep_cfg )
{
inf.show_line_pref(false);
}
debugmode = 0;
}
}
break;
#endif
case java_module_t::ev_load_file:
{
linput_t *li = va_arg(va, linput_t *);
FILE *f = qlfile(li);
QASSERT(10082, f != NULL);
bool manual = va_argi(va, bool);
loader(f, manual);
retcode = 0;
}
if ( start_asm_list )
set_target_assembler(1);
break;
case processor_t::ev_gen_src_file_lnnum:
if ( jasmin() )
{
outctx_t *ctx = va_arg(va, outctx_t *);
va_arg(va, const char *); // skip file name
size_t lineno = va_arg(va, size_t);
ctx->gen_printf(2, COLSTR(".line %" FMT_Z, SCOLOR_ASMDIR), lineno);
retcode = 1;
}
break;
case processor_t::ev_gen_asm_or_lst:
{
if ( va_argi(va, bool) ) // starting (else end of generation )
{
va_arg(va, FILE *); // output file (skip)
bool isasm = va_argi(va, bool); // assembler-true, listing-false
if ( isasm && (idpflags & IDF_CONVERT) )
{
va_arg(va, int); // flags of gen_file() (skip)
*va_arg(va, gen_outline_t**) = out_asm_file;
idpflags |= IDM_OUTASM;
}
if ( isasm == jasmin() )
break; // need change mode?
}
else // end of generation.
{
idpflags &= ~IDM_OUTASM;
if ( !mode_changed )
break; // mode changed?
}
mode_changed = !mode_changed;
set_target_assembler(!inf_get_asmtype());
}
break;
case processor_t::ev_get_autocmt:
{
qstring *buf = va_arg(va, qstring *);
const insn_t *insn = va_arg(va, insn_t *);
if ( make_locvar_cmt(buf, *insn) )
retcode = 1;
}
break;
case processor_t::ev_out_mnem:
{
outctx_t *ctx = va_arg(va, outctx_t *);
out_mnem(*ctx);
return 1;
}
case processor_t::ev_out_header:
{
outctx_t *ctx = va_arg(va, outctx_t *);
java_header(*ctx);
return 1;
}
case processor_t::ev_out_footer:
{
outctx_t *ctx = va_arg(va, outctx_t *);
java_footer(*ctx);
return 1;
}
case processor_t::ev_out_segstart:
{
outctx_t *ctx = va_arg(va, outctx_t *);
segment_t *seg = va_arg(va, segment_t *);
java_segstart(*ctx, seg);
return 1;
}
case processor_t::ev_out_segend:
{
outctx_t *ctx = va_arg(va, outctx_t *);
segment_t *seg = va_arg(va, segment_t *);
java_segend(*ctx, seg);
return 1;
}
case processor_t::ev_ana_insn:
{
insn_t *out = va_arg(va, insn_t *);
return ana(out);
}
case processor_t::ev_emu_insn:
{
const insn_t *insn = va_arg(va, const insn_t *);
return emu(*insn) ? 1 : -1;
}
case processor_t::ev_out_insn:
{
outctx_t *ctx = va_arg(va, outctx_t *);
out_insn(*ctx);
return 1;
}
case processor_t::ev_out_operand:
{
outctx_t *ctx = va_arg(va, outctx_t *);
const op_t *op = va_arg(va, const op_t *);
return out_opnd(*ctx, *op) ? 1 : -1;
}
case processor_t::ev_out_data:
{
outctx_t *ctx = va_arg(va, outctx_t *);
bool analyze_only = va_argi(va, bool);
java_data(*ctx, analyze_only);
return 1;
}
case processor_t::ev_can_have_type:
{
const op_t *op = va_arg(va, const op_t *);
return can_have_type(*op) ? 1 : -1;
}
case processor_t::ev_realcvt:
{
void *m = va_arg(va, void *);
fpvalue_t *e = va_arg(va, fpvalue_t *);
uint16 swt = va_argi(va, uint16);
fpvalue_error_t code = j_realcvt(m, e, swt);
return code == REAL_ERROR_OK ? 1 : code;
}
case processor_t::ev_gen_map_file:
{
int *nlines = va_arg(va, int *);
FILE *fp = va_arg(va, FILE *);
int code = gen_map_file(fp);
if ( code == -1 )
return -1;
*nlines = code;
return 1;
}
case processor_t::ev_extract_address:
{
ea_t *out_ea = va_arg(va, ea_t *);
ea_t screen_ea = va_arg(va, ea_t);
const char *str = va_arg(va, const char *);
size_t pos = va_arg(va, size_t);
ea_t ea = get_ref_addr(screen_ea, str, pos);
if ( ea == BADADDR )
return -1;
if ( ea == (BADADDR-1) )
return 0;
*out_ea = ea;
return 1;
}
case processor_t::ev_out_special_item:
{
outctx_t *ctx = va_arg(va, outctx_t *);
uchar seg_type = va_argi(va, uchar);
java_specseg(*ctx, seg_type);
return 1;
}
case processor_t::ev_set_idp_options:
{
const char *keyword = va_arg(va, const char *);
int value_type = va_arg(va, int);
const char *value = va_arg(va, const char *);
const char **errmsg = va_arg(va, const char **);
bool idb_loaded = va_argi(va, bool);
const char *ret = set_idp_options(keyword, value_type, value, idb_loaded);
if ( ret == IDPOPT_OK )
return 1;
if ( errmsg != NULL )
*errmsg = ret;
return -1;
}
default:
break;
}
return retcode;
}
//-----------------------------------------------------------------------
// Processor Definition
//-----------------------------------------------------------------------
processor_t LPH =
{
IDP_INTERFACE_VERSION, // version
PLFM_JAVA, // id
// flag
PRN_DEC
| PR_RNAMESOK
| PR_NO_SEGMOVE,
// flag2
PR2_REALCVT // the module has 'realcvt' event implementation
| PR2_IDP_OPTS, // the module has processor-specific configuration options
8, // 8 bits in a byte for code segments
8, // 8 bits in a byte for other segments
shnames,
lnames,
asms,
notify,
RegNames, // Regsiter names
qnumber(RegNames), // Number of registers
rVcs,rVds,
0, // size of a segment register
rVcs,rVds,
NULL, // No known code start sequences
retcodes,
0,j_last,
Instructions, // instruc
0, // size of tbyte
{0,7,15,0}, // real width
j_ret, // icode_return
NULL, // Micro virtual machine description
};

View File

@@ -0,0 +1,94 @@
#include "java.hpp"
#include "npooluti.hpp"
//-----------------------------------------------------------------------
// as procedupre for converter only
void java_t::ResW_init(void)
{
static char const *const jasRW[] =
{
#include "jas_rw.cc"
};
for ( uint i = 0; i < j_lastnorm; i++ )
ResW.insert(Instructions[i].name);
ResW.insert(jasRW, jasRW+qnumber(jasRW));
}
//-----------------------------------------------------------------------
// as procedure for rw-changed
void java_t::ResW_validate(uint32 *Flags, const ushort *pend)
{
ushort *pi = tsPtr;
uchar *p = (uchar *)pi;
do
{
if ( *pi >= CHP_MAX )
return;
*p++ = (uchar)*pi++;
}
while ( pi < pend );
*p = '\0';
if ( ResW.find((const char *)tsPtr) != ResW.end() )
*Flags |= _OP_JSMRES_;
}
//-----------------------------------------------------------------------
// visible for converter only
uint32 java_t::upgrade_ResW(uint32 opstr)
{
if ( !(opstr & (_OP_NOWORD << 16)) ) // check for upg12
{
CASSERT(offsetof(_STROP_, size) == 0 && offsetof(_STROP_, flags) == 2);
uint32 len = (ushort)opstr;
uint32 flg = (opstr >> 16) & ~_OP_JSMRES_;
ResW_validate(&flg, tsPtr + len);
opstr = (flg << 16) | len;
}
return opstr;
}
//-----------------------------------------------------------------------
uchar java_t::ResW_oldbase(void)
{
if ( ConstantNode.altval(CNA_KWRDVER) != KEYWORD_VERSION )
{
ResW_init(); // prepare conversion
FOR_EACH_CONSTANT_POOL_INDEX(pos)
{
const_desc_t co;
if ( ConstantNode.supval(pos, &co, sizeof(co)) != sizeof(co) )
goto BADIDB;
if ( co.type != CONSTANT_Utf8 || !co._Ssize )
continue;
if ( (co._Sflags & _OP_JSMRES_) || !(co._Sflags & _OP_NOWORD) )
{
if ( !getblob(pos << 16, tsPtr, co._Ssize) )
goto BADIDB;
uint32 v = upgrade_ResW(co._Sopstr);
if ( v == co._Sopstr )
continue;
ConstantNode.altset(pos << 16, v);
co._Sopstr = v;
ConstantNode.supset(pos, &co, sizeof(co));
}
}
ResW.clear();
ConstantNode.altset(CNA_KWRDVER, KEYWORD_VERSION);
}
return 1;
BADIDB:
return 0;
}
//-----------------------------------------------------------------------
void java_t::ResW_newbase(void)
{
ConstantNode.altset(CNA_KWRDVER, KEYWORD_VERSION);
}
//-----------------------------------------------------------------------
void java_t::ResW_free(void)
{
ResW.clear(); // free mem - this set not needed later
}

View File

@@ -0,0 +1,10 @@
#ifndef _RESWORD_HPP__
#define _RESWORD_HPP__
void ResW_init(void);
void ResW_validate(uint32 *Flags, const ushort *pend);
uchar ResW_oldbase(void);
void ResW_newbase(void);
void ResW_free();
#endif

View File

@@ -0,0 +1,391 @@
/*
* Interactive disassembler (IDA)
* Copyright (c) 1990-98 by Ilfak Guilfanov.
* E-mail: ig@datarescue.com
* JVM module.
* Copyright (c) 1995-2006 by Iouri Kharon.
* E-mail: yjh@styx.cabel.net
*
* ALL RIGHTS RESERVED.
*
*/
#include "java.hpp"
#include "upgrade.hpp"
#include "oututil.hpp"
//----------------------------------------------------------------------
#define _TO_VERSION IDP_JDK16
//----------------------------------------------------------------------
void java_t::make_new_name(ushort name, ushort subnam, uchar mode, uint ip)
{
out_java_t *pctx = (out_java_t *)create_outctx(BADADDR);
if ( pctx->fmtString(*this, name, MAXNAMELEN-2, fmt_fullname) )
{
trunc:
pctx->trunc_name(ip, mode & 4);
}
else if ( (char)mode > 0 )
{
size_t len = pctx->outbuf.length();
if ( len >= (MAXNAMELEN-3) )
goto trunc;
pctx->out_char(' ');
if ( pctx->fmtString(*this, subnam, (MAXNAMELEN-2) - len, fmt_UnqualifiedName) )
goto trunc;
}
force_name(ip, convert_clsname(pctx->outbuf.begin()));
delete pctx;
hide_name(ip);
}
//----------------------------------------------------------------------
int java_t::upgrade_db_format(int ver, netnode constnode)
{
if ( ask_yn(ASKBTN_YES,
"AUTOHIDE REGISTRY\nHIDECANCEL\n"
"The database has an old java data format.\n"
"Do you want to upgrade it?") <= ASKBTN_NO )
{
qexit(1);
}
switch ( ver )
{
default:
INTERNAL("upgrade::ver");
case IDP_JDK12:
break;
}
// change format: jdk-version
if ( curClass.MinVers > 0x8000u )
{
BADIDB:
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
CASSERT(offsetof(ClassInfo, This.Ref) == offsetof(ClassInfo, This.Name)
&& offsetof(ClassInfo, This.Dscr) == offsetof(ClassInfo, This.Name) + 2);
curClass.This.Ref = (curClass.This.Ref << 16) | curClass.This.Dscr;
if ( !curClass.This.Name )
goto BADIDB;
// change format: Super
CASSERT(offsetof(ClassInfo, super.Ref) == offsetof(ClassInfo, super.Name)
&& offsetof(ClassInfo, super.Dscr) == offsetof(ClassInfo, super.Name) + 2);
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 BADIDB;
// 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 = getseg(curClass.start_ea);
if ( S == NULL )
goto BADIDB;
S->set_hidden_segtype(true);
S->update();
if ( curClass.xtrnCnt )
{
S = getseg(curClass.xtrnEA);
if ( S == NULL )
goto BADIDB;
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]; //lint !e754 not referenced
} u;
if ( !pos ) // class node
{
oldsize += (sizeof(FieldInfo) - FLEXPSZ) - (sizeof(SegInfo) - SGEXPSZ);
continue;
}
if ( ClassNode.supval(pos, &u, sizeof(u)) != oldsize )
goto BADIDB;
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 BADIDB;
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 )
{
S = getseg(u.s.DataBase);
if ( S == NULL )
goto BADIDB;
S->type = SEG_BSS;
S->set_hidden_segtype(true);
S->update();
}
// change: Exception format
if ( u.s.excNode )
{
netnode enode(u.s.excNode);
ushort j = (ushort)enode.altval(0);
if ( j == 0 )
goto BADIDB;
ea_t ea = u.s.start_ea + u.s.CodeSize;
ushort i = 1;
do
{
Exception exc;
if ( enode.supval(i, &exc, sizeof(exc)) != sizeof(exc) )
goto BADIDB;
CASSERT(offsetof(Exception, filter.Ref) == offsetof(Exception, filter.Name)
&& offsetof(Exception, filter.Dscr) == offsetof(Exception, filter.Name) + 2);
if ( !exc.filter.Name != !exc.filter.Dscr )
goto BADIDB;
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%03d", u.s.id.Number, --i);
--ea;
if ( force_name(ea, str) )
make_name_auto(ea);
else
hide_name(ea);
}
while ( i > 0 );
coagulate_unused_data(&u.s);
}
} // for
// change format of string presentation in constant pool
FOR_EACH_CONSTANT_POOL_INDEX(pos)
{
const_desc_t co;
if ( constnode.supval(pos, &co, sizeof(co)) != sizeof(co) )
goto BADIDB;
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, i = pos << 16;
uint32 n = (uint32)constnode.altval(i);
if ( (n & UPG12_BADMASK) != 0 || (v = n & ~UPG12_CLRMASK) == 0 )
goto BADIDB;
if ( n & UPG12_EXTMASK )
v |= UPG12_EXTSET;
n = ushort(v);
if ( n != 0 )
{
uchar *po = (uchar*)append_tmp_buffer(v);
n *= sizeof(ushort);
uint32 idx = 0;
do
{
uint32 sz = n - idx;
if ( sz > MAXSPECSIZE )
sz = MAXSPECSIZE;
if ( constnode.supval(++i, &po[idx], sz) != sz )
goto BADIDB;
constnode.supdel(i);
idx += sz;
}
while ( idx < n );
constnode.setblob(po, n, i & ~0xFFFF, BLOB_TAG);
if ( !(v & UPG12_EXTSET) )
{
do
{
CASSERT((sizeof(ushort) % 2) == 0 && (MAXSPECSIZE % 2) == 0);
ushort cw = *(ushort *)&po[idx];
if ( cw >= CHP_MAX )
{
if ( !javaIdent(cw) )
goto extchar;
}
else if ( (uchar)cw <= CHP_MIN )
{
extchar:
v |= UPG12_EXTSET;
break;
}
}
while ( (idx -= 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 ( uint ip = 1; (ushort)ip <= curClass.xtrnCnt; ip++ )
{
const_desc_t co;
{
uint j = (uint)XtrnNode.altval(ip);
if ( j == 0 || !LoadOpis(lm_lenient, (ushort)j, 0, &co) )
goto BADIDB;
}
switch ( co.type )
{
default:
goto BADIDB;
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, (uint)curClass.start_ea);
return _TO_VERSION;
}
//-----------------------------------------------------------------------
//----------------------------------------------------------------------
// some utilities (size of npool)
//----------------------------------------------------------------------
// visible for converter only
char *java_t::convert_clsname(char *buf) const
{
if ( jasmin() )
for ( char *p = buf; (p = strchr(p, j_clspath_dlm)) != NULL; p++ )
*p = j_field_dlm;
return buf;
}
//-----------------------------------------------------------------------
// visible for converter only
uchar set_exception_xref(SegInfo *ps, Exception const & exc, ea_t ea)
{
uchar ans = 0;
if ( exc.start_pc >= ps->CodeSize )
{
ans = 1;
}
else
{
if ( !exc.start_pc )
ps->id.extflg |= XFL_M_LABSTART; // special label at entry
add_dref(ea, ps->start_ea + exc.start_pc, dr_I);
}
if ( exc.end_pc > ps->CodeSize )
{
ans = 1;
}
else
{
if ( exc.end_pc == ps->CodeSize )
ps->id.extflg |= XFL_M_LABEND; // special label at end
add_dref(ea, ps->start_ea + exc.end_pc, dr_I);
}
if ( exc.handler_pc >= ps->CodeSize )
return 1;
add_dref(ea, ps->start_ea + exc.handler_pc, dr_I);
return ans;
}

View File

@@ -0,0 +1,35 @@
/*
* Interactive disassembler (IDA)
* Copyright (c) 1990-98 by Ilfak Guilfanov.
* E-mail: ig@datarescue.com
* JVM module.
* Copyright (c) 1995-2006 by Iouri Kharon.
* E-mail: yjh@styx.cabel.net
*
* ALL RIGHTS RESERVED.
*
*/
#ifndef _UPGRADE_HPP_
#define _UPGRADE_HPP_
//----------------------------------------------------------------------
#define IDP_JDK12 19
#define IDP_JDK15 151
#define IDP_JDK16 161
//----------------------------------------------------------------------
#define UPG12_BADMASK 0x80000000
#define UPG12_EXTMASK 0x70000000
#define UPG12_CLRMASK 0xF03F0000
#define UPG12_EXTSET 0x80000000
//----------------------------------------------------------------------
#define CHP_MIN ' '
#define CHP_MAX 0x7F
#define BLOB_TAG 'j'
uchar set_exception_xref(SegInfo *ps, Exception const & exc, ea_t ea);
char *convert_clsname(char *buf);
//----------------------------------------------------------------------
#endif