update to ida 7.6, add builds
This commit is contained in:
577
idasdk76/module/java/ana.cpp
Normal file
577
idasdk76/module/java/ana.cpp
Normal 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;
|
||||
}
|
||||
212
idasdk76/module/java/classfil.hpp
Normal file
212
idasdk76/module/java/classfil.hpp
Normal 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
|
||||
316
idasdk76/module/java/emu.cpp
Normal file
316
idasdk76/module/java/emu.cpp
Normal 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;
|
||||
}
|
||||
1285
idasdk76/module/java/fmtstr.cpp
Normal file
1285
idasdk76/module/java/fmtstr.cpp
Normal file
File diff suppressed because it is too large
Load Diff
235
idasdk76/module/java/ins.cpp
Normal file
235
idasdk76/module/java/ins.cpp
Normal 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);
|
||||
267
idasdk76/module/java/ins.hpp
Normal file
267
idasdk76/module/java/ins.hpp
Normal 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
|
||||
20
idasdk76/module/java/jas_rw.cc
Normal file
20
idasdk76/module/java/jas_rw.cc
Normal 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",
|
||||
|
||||
//-------------
|
||||
651
idasdk76/module/java/java.hpp
Normal file
651
idasdk76/module/java/java.hpp
Normal 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
|
||||
|
||||
131
idasdk76/module/java/makefile
Normal file
131
idasdk76/module/java/makefile
Normal 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
|
||||
474
idasdk76/module/java/map.cpp
Normal file
474
idasdk76/module/java/map.cpp
Normal 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;
|
||||
}
|
||||
37
idasdk76/module/java/notify_codes.hpp
Normal file
37
idasdk76/module/java/notify_codes.hpp
Normal 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
|
||||
2499
idasdk76/module/java/npool.cpp
Normal file
2499
idasdk76/module/java/npool.cpp
Normal file
File diff suppressed because it is too large
Load Diff
2031
idasdk76/module/java/npooluti.cpp
Normal file
2031
idasdk76/module/java/npooluti.cpp
Normal file
File diff suppressed because it is too large
Load Diff
104
idasdk76/module/java/npooluti.hpp
Normal file
104
idasdk76/module/java/npooluti.hpp
Normal 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
2160
idasdk76/module/java/out.cpp
Normal file
File diff suppressed because it is too large
Load Diff
813
idasdk76/module/java/oututil.cpp
Normal file
813
idasdk76/module/java/oututil.cpp
Normal 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);
|
||||
}
|
||||
}
|
||||
117
idasdk76/module/java/oututil.hpp
Normal file
117
idasdk76/module/java/oututil.hpp
Normal 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
|
||||
822
idasdk76/module/java/reg.cpp
Normal file
822
idasdk76/module/java/reg.cpp
Normal 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
|
||||
};
|
||||
94
idasdk76/module/java/resword.cpp
Normal file
94
idasdk76/module/java/resword.cpp
Normal 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
|
||||
}
|
||||
10
idasdk76/module/java/resword.hpp
Normal file
10
idasdk76/module/java/resword.hpp
Normal 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
|
||||
391
idasdk76/module/java/upgrade.cpp
Normal file
391
idasdk76/module/java/upgrade.cpp
Normal 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;
|
||||
}
|
||||
35
idasdk76/module/java/upgrade.hpp
Normal file
35
idasdk76/module/java/upgrade.hpp
Normal 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
|
||||
Reference in New Issue
Block a user