update to ida 7.6, add builds
This commit is contained in:
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;
|
||||
}
|
||||
Reference in New Issue
Block a user