Fixed Java deassembly

This commit is contained in:
Pierre Pronchery 2011-11-29 18:44:03 +00:00
parent ce3a785edd
commit 8aed535978
2 changed files with 158 additions and 44 deletions

View File

@ -35,10 +35,12 @@ static ArchRegister _java_registers[] =
{ NULL, 0, 0 }
};
#define OP1F (8 << AOD_SIZE)
#define OP_U8 AO_IMMEDIATE(0, 8, 0)
#define OP_U16 AO_IMMEDIATE(0, 16, 0)
#define OP_U32 AO_IMMEDIATE(0, 32, 0)
#define OP1F (8 << AOD_SIZE)
#define OP_U8 AO_IMMEDIATE(0, 8, 0)
#define OP_U16 AO_IMMEDIATE(0, 16, 0)
#define OP_U16_STR AO_IMMEDIATE(0, 16, AOI_REFERS_STRING)
#define OP_U16_FUNC AO_IMMEDIATE(0, 16, AOI_REFERS_FUNCTION)
#define OP_U32 AO_IMMEDIATE(0, 32, 0)
static ArchInstruction _java_instructions[] =
{
{ "aaload", 0x32, OP1F, AO_0() },
@ -169,11 +171,11 @@ static ArchInstruction _java_instructions[] =
{ "impdep2", 0xff, OP1F, AO_0() },
{ "imul", 0x68, OP1F, AO_0() },
{ "ineg", 0x74, OP1F, AO_0() },
{ "instanceof", 0xc1, OP1F, AO_1(OP_U16) },
{ "invokeinterface",0xb9,OP1F,AO_2(OP_U16, OP_U8) },
{ "invokespecial",0xb7, OP1F, AO_1(OP_U16) },
{ "invokestatic",0xb8, OP1F, AO_1(OP_U16) },
{ "invokevirtual",0xb6, OP1F, AO_1(OP_U16) },
{ "instanceof", 0xc1, OP1F, AO_1(OP_U16_FUNC) },
{ "invokeinterface",0xb9,OP1F,AO_2(OP_U16_FUNC, OP_U8) },
{ "invokespecial",0xb7, OP1F, AO_1(OP_U16_FUNC) },
{ "invokestatic",0xb8, OP1F, AO_1(OP_U16_FUNC) },
{ "invokevirtual",0xb6, OP1F, AO_1(OP_U16_FUNC) },
{ "ior", 0x80, OP1F, AO_0() },
{ "irem", 0x70, OP1F, AO_0() },
{ "ireturn", 0xac, OP1F, AO_0() },
@ -331,6 +333,7 @@ static int _java_decode(ArchPlugin * plugin, ArchInstructionCall * call)
ArchOperand * ao;
uint16_t u16;
uint32_t u32;
AsmString * as;
if(helper->read(helper->arch, &u8, sizeof(u8)) != sizeof(u8))
return -1;
@ -380,6 +383,17 @@ static int _java_decode(ArchPlugin * plugin, ArchInstructionCall * call)
return -error_set_code(1, "%s", "Size not implemented");
ao->value.immediate.name = NULL;
ao->value.immediate.negative = 0;
switch(AO_GET_VALUE(ao->definition))
{
case AOI_REFERS_FUNCTION:
case AOI_REFERS_STRING:
as = helper->get_string_by_id(helper->arch,
ao->value.immediate.value);
if(as != NULL)
ao->value.immediate.name = as->name;
ao->value.immediate.negative = 0;
break;
}
}
call->operands_cnt = i;
return 0;

View File

@ -80,6 +80,15 @@ typedef struct _JavaAttributeInfo
uint32_t length;
char info[0];
} JavaAttributeInfo;
typedef struct _JavaMethodInfo
{
uint16_t access;
uint16_t name;
uint16_t descriptor;
uint16_t attributes_cnt;
} JavaMethodInfo;
#pragma pack()
typedef struct _JavaPlugin
@ -135,19 +144,19 @@ FormatPlugin format_plugin =
/* java_init */
static int _java_init(FormatPlugin * format, char const * arch)
{
FormatPluginHelper * helper = format->helper;
JavaHeader jh;
JavaPlugin * java;
if(arch != NULL && strcmp(arch, "java") != 0)
return error_set_code(1, "%s: %s", arch,
"Unsupported architecture for java");
#if 0 /* FIXME move this where appropriate */
memcpy(&jh.magic, format->signature, format->signature_len);
jh.minor = _htob16(0);
jh.major = _htob16(0x32); /* XXX choose a more appropriate version */
jh.cp_cnt = _htob16(0);
if(helper->write(helper->format, &jh, sizeof(jh)) != sizeof(jh))
return -1;
#endif
if((java = object_new(sizeof(*java))) == NULL)
return -1;
memset(java, 0, sizeof(*java));
@ -283,60 +292,92 @@ static int _exit_attribute_table(FormatPlugin * format)
/* java_detect */
static char const * _java_detect(FormatPlugin * format)
{
FormatPluginHelper * helper = format->helper;
JavaHeader jh;
if(helper->seek(helper->format, 0, SEEK_SET) != 0)
return NULL;
if(helper->read(helper->format, &jh, sizeof(jh)) != sizeof(jh))
return NULL;
if(memcmp(&jh.magic, _java_signature, sizeof(jh.magic)) != 0)
return NULL;
jh.minor = _htob16(jh.minor);
jh.major = _htob16(jh.major);
#ifdef DEBUG
fprintf(stderr, "DEBUG: %s() %u.%d\n", __func__, jh.major, jh.minor);
#endif
return "java";
}
/* java_decode */
static int _decode_skip_attributes(FormatPlugin * format, uint16_t cnt);
static int _decode_skip_constants(FormatPlugin * format, uint16_t cnt);
static int _decode_skip_fields(FormatPlugin * format, uint16_t cnt);
static int _decode_skip_interfaces(FormatPlugin * format, uint16_t cnt);
static int _java_decode(FormatPlugin * format, int raw)
{
FormatPluginHelper * helper = format->helper;
off_t end;
/* XXX consider the whole file as a section */
if((end = helper->seek(helper->format, 0, SEEK_END)) < 0)
return -1;
return helper->set_section(helper->format, 0, ".text", 0, end, 0);
}
/* java_decode_section */
static int _decode_attributes(FormatPlugin * format, uint16_t cnt,
ArchInstructionCall ** calls, size_t * calls_cnt);
static int _decode_constants(FormatPlugin * format, uint16_t cnt);
static int _decode_fields(FormatPlugin * format, uint16_t cnt);
static int _decode_interfaces(FormatPlugin * format, uint16_t cnt);
static int _decode_methods(FormatPlugin * format, uint16_t cnt,
ArchInstructionCall ** calls, size_t * calls_cnt);
static int _java_decode_section(FormatPlugin * format, AsmSection * section,
ArchInstructionCall ** calls, size_t * calls_cnt)
{
FormatPluginHelper * helper = format->helper;
JavaHeader jh;
JavaHeader2 jh2;
uint16_t u16;
off_t offset;
off_t end;
/* FIXME can this be correct? */
if(helper->seek(helper->format, sizeof(jh), SEEK_SET) != sizeof(jh))
/* read header */
if(helper->seek(helper->format, section->offset, SEEK_SET)
!= section->offset)
return -1;
if(helper->read(helper->format, &jh, sizeof(jh)) != sizeof(jh))
return -1;
/* skip constants */
jh.cp_cnt = _htob16(jh.cp_cnt);
if(jh.cp_cnt > 1 && _decode_skip_constants(format, jh.cp_cnt) != 0)
if(jh.cp_cnt > 1 && _decode_constants(format, jh.cp_cnt) != 0)
return -1;
/* skip interfaces */
if(helper->read(helper->format, &jh2, sizeof(jh2)) != sizeof(jh2))
return -1;
jh2.interfaces_cnt = _htob16(jh2.interfaces_cnt);
if(_decode_skip_interfaces(format, jh2.interfaces_cnt) != 0)
if(_decode_interfaces(format, jh2.interfaces_cnt) != 0)
return -1;
/* skip fields */
if(helper->read(helper->format, &u16, sizeof(u16)) != sizeof(u16))
return -1;
u16 = _htob16(u16);
if(_decode_skip_fields(format, u16) != 0)
if(_decode_fields(format, u16) != 0)
return -1;
/* disassemble the rest */
if((offset = helper->seek(helper->format, 0, SEEK_CUR)) < 0
|| (end = helper->seek(helper->format, 0, SEEK_END))
< 0)
/* skip methods */
if(helper->read(helper->format, &u16, sizeof(u16)) != sizeof(u16))
return -1;
return helper->set_section(helper->format, 0, ".text", offset,
end - offset, 0);
u16 = _htob16(u16);
if(_decode_methods(format, u16, calls, calls_cnt) != 0)
return -1;
return 0;
}
static int _decode_skip_attributes(FormatPlugin * format, uint16_t cnt)
static int _decode_attributes(FormatPlugin * format, uint16_t cnt,
ArchInstructionCall ** calls, size_t * calls_cnt)
{
FormatPluginHelper * helper = format->helper;
size_t i;
JavaAttributeInfo jai;
off_t offset;
#ifdef DEBUG
fprintf(stderr, "DEBUG: %s(%u)\n", __func__, cnt);
@ -351,13 +392,22 @@ static int _decode_skip_attributes(FormatPlugin * format, uint16_t cnt)
fprintf(stderr, "DEBUG: %s() length=%u\n", __func__,
jai.length);
#endif
if(helper->seek(helper->format, jai.length, SEEK_CUR) < 0)
return -1;
if(calls != NULL)
{
if((offset = helper->seek(helper->format, 0, SEEK_CUR))
< 0
|| helper->decode(helper->format,
offset, jai.length, offset,
calls, calls_cnt) != 0)
return -1;
}
else if(helper->seek(helper->format, jai.length, SEEK_CUR) < 0)
return -1;
}
return 0;
}
static int _decode_skip_constants(FormatPlugin * format, uint16_t cnt)
static int _decode_constants(FormatPlugin * format, uint16_t cnt)
{
FormatPluginHelper * helper = format->helper;
size_t i;
@ -365,11 +415,13 @@ static int _decode_skip_constants(FormatPlugin * format, uint16_t cnt)
size_t size;
char buf[8];
uint16_t u16;
off_t offset;
AsmString * as;
#ifdef DEBUG
fprintf(stderr, "DEBUG: %s(%u)\n", __func__, cnt);
#endif
for(i = 0; i < cnt; i++)
for(i = 1; i < cnt; i++)
{
if(helper->read(helper->format, &jci, sizeof(jci))
!= sizeof(jci))
@ -389,19 +441,56 @@ static int _decode_skip_constants(FormatPlugin * format, uint16_t cnt)
size = 4;
break;
case CONSTANT_Class:
case CONSTANT_String:
size = 2;
break;
case CONSTANT_String:
size = sizeof(u16);
if(helper->read(helper->format, &u16, size)
!= (ssize_t)size)
return -1;
u16 = _htob16(u16);
size = 0;
as = helper->get_string_by_id(helper->format,
u16 << 16);
/* set the proper string ID */
if(as != NULL && helper->set_string(
helper->format, i, NULL,
as->offset, as->size)
< 0)
return -1;
/* XXX abuse set_string() to remember string */
else if(as == NULL && helper->set_string(
helper->format,
u16 << 16, NULL, i, 0)
< 0)
return -1;
break;
case CONSTANT_Utf8:
size = sizeof(u16);
if(helper->read(helper->format, &u16, size)
!= (ssize_t)size)
return -1;
u16 = _htob16(u16);
if((offset = helper->seek(helper->format, 0,
SEEK_CUR)) < 0)
return -1;
size = 0;
if(helper->seek(helper->format, u16, SEEK_CUR)
< 0)
return -1;
size = 0;
as = helper->get_string_by_id(helper->format,
i << 16);
/* we do not know this string yet */
if(as == NULL && helper->set_string(
helper->format, i << 16,
NULL, offset, u16) < 0)
return -1;
/* we do know this string */
else if(as != NULL && helper->set_string(
helper->format,
as->offset, NULL,
offset, u16) < 0)
return -1;
break;
default:
return -error_set_code(1, "%s: %s 0x%x",
@ -417,7 +506,7 @@ static int _decode_skip_constants(FormatPlugin * format, uint16_t cnt)
return 0;
}
static int _decode_skip_fields(FormatPlugin * format, uint16_t cnt)
static int _decode_fields(FormatPlugin * format, uint16_t cnt)
{
FormatPluginHelper * helper = format->helper;
size_t i;
@ -432,12 +521,12 @@ static int _decode_skip_fields(FormatPlugin * format, uint16_t cnt)
!= sizeof(jfi))
return -1;
jfi.attributes_cnt = _htob16(jfi.attributes_cnt);
_decode_skip_attributes(format, jfi.attributes_cnt);
_decode_attributes(format, jfi.attributes_cnt, NULL, NULL);
}
return 0;
}
static int _decode_skip_interfaces(FormatPlugin * format, uint16_t cnt)
static int _decode_interfaces(FormatPlugin * format, uint16_t cnt)
{
FormatPluginHelper * helper = format->helper;
size_t i;
@ -453,13 +542,24 @@ static int _decode_skip_interfaces(FormatPlugin * format, uint16_t cnt)
return 0;
}
/* java_decode_section */
static int _java_decode_section(FormatPlugin * format, AsmSection * section,
static int _decode_methods(FormatPlugin * format, uint16_t cnt,
ArchInstructionCall ** calls, size_t * calls_cnt)
{
FormatPluginHelper * helper = format->helper;
size_t i;
JavaMethodInfo jmi;
return helper->decode(helper->format, section->offset, section->size,
section->base, calls, calls_cnt);
#ifdef DEBUG
fprintf(stderr, "DEBUG: %s(%u)\n", __func__, cnt);
#endif
for(i = 0; i < cnt; i++)
{
if(helper->read(helper->format, &jmi, sizeof(jmi))
!= sizeof(jmi))
return -1;
jmi.attributes_cnt = _htob16(jmi.attributes_cnt);
_decode_attributes(format, jmi.attributes_cnt, calls,
calls_cnt);
}
return 0;
}