Fixed Java deassembly
This commit is contained in:
parent
ce3a785edd
commit
8aed535978
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user