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