Fixed Java deassembly
This commit is contained in:
parent
ce3a785edd
commit
8aed535978
@ -38,6 +38,8 @@ static ArchRegister _java_registers[] =
|
|||||||
#define OP1F (8 << AOD_SIZE)
|
#define OP1F (8 << AOD_SIZE)
|
||||||
#define OP_U8 AO_IMMEDIATE(0, 8, 0)
|
#define OP_U8 AO_IMMEDIATE(0, 8, 0)
|
||||||
#define OP_U16 AO_IMMEDIATE(0, 16, 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)
|
#define OP_U32 AO_IMMEDIATE(0, 32, 0)
|
||||||
static ArchInstruction _java_instructions[] =
|
static ArchInstruction _java_instructions[] =
|
||||||
{
|
{
|
||||||
@ -169,11 +171,11 @@ static ArchInstruction _java_instructions[] =
|
|||||||
{ "impdep2", 0xff, OP1F, AO_0() },
|
{ "impdep2", 0xff, OP1F, AO_0() },
|
||||||
{ "imul", 0x68, OP1F, AO_0() },
|
{ "imul", 0x68, OP1F, AO_0() },
|
||||||
{ "ineg", 0x74, OP1F, AO_0() },
|
{ "ineg", 0x74, OP1F, AO_0() },
|
||||||
{ "instanceof", 0xc1, OP1F, AO_1(OP_U16) },
|
{ "instanceof", 0xc1, OP1F, AO_1(OP_U16_FUNC) },
|
||||||
{ "invokeinterface",0xb9,OP1F,AO_2(OP_U16, OP_U8) },
|
{ "invokeinterface",0xb9,OP1F,AO_2(OP_U16_FUNC, OP_U8) },
|
||||||
{ "invokespecial",0xb7, OP1F, AO_1(OP_U16) },
|
{ "invokespecial",0xb7, OP1F, AO_1(OP_U16_FUNC) },
|
||||||
{ "invokestatic",0xb8, OP1F, AO_1(OP_U16) },
|
{ "invokestatic",0xb8, OP1F, AO_1(OP_U16_FUNC) },
|
||||||
{ "invokevirtual",0xb6, OP1F, AO_1(OP_U16) },
|
{ "invokevirtual",0xb6, OP1F, AO_1(OP_U16_FUNC) },
|
||||||
{ "ior", 0x80, OP1F, AO_0() },
|
{ "ior", 0x80, OP1F, AO_0() },
|
||||||
{ "irem", 0x70, OP1F, AO_0() },
|
{ "irem", 0x70, OP1F, AO_0() },
|
||||||
{ "ireturn", 0xac, OP1F, AO_0() },
|
{ "ireturn", 0xac, OP1F, AO_0() },
|
||||||
@ -331,6 +333,7 @@ static int _java_decode(ArchPlugin * plugin, ArchInstructionCall * call)
|
|||||||
ArchOperand * ao;
|
ArchOperand * ao;
|
||||||
uint16_t u16;
|
uint16_t u16;
|
||||||
uint32_t u32;
|
uint32_t u32;
|
||||||
|
AsmString * as;
|
||||||
|
|
||||||
if(helper->read(helper->arch, &u8, sizeof(u8)) != sizeof(u8))
|
if(helper->read(helper->arch, &u8, sizeof(u8)) != sizeof(u8))
|
||||||
return -1;
|
return -1;
|
||||||
@ -380,6 +383,17 @@ static int _java_decode(ArchPlugin * plugin, ArchInstructionCall * call)
|
|||||||
return -error_set_code(1, "%s", "Size not implemented");
|
return -error_set_code(1, "%s", "Size not implemented");
|
||||||
ao->value.immediate.name = NULL;
|
ao->value.immediate.name = NULL;
|
||||||
ao->value.immediate.negative = 0;
|
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;
|
call->operands_cnt = i;
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -80,6 +80,15 @@ typedef struct _JavaAttributeInfo
|
|||||||
uint32_t length;
|
uint32_t length;
|
||||||
char info[0];
|
char info[0];
|
||||||
} JavaAttributeInfo;
|
} JavaAttributeInfo;
|
||||||
|
|
||||||
|
typedef struct _JavaMethodInfo
|
||||||
|
{
|
||||||
|
uint16_t access;
|
||||||
|
uint16_t name;
|
||||||
|
uint16_t descriptor;
|
||||||
|
uint16_t attributes_cnt;
|
||||||
|
|
||||||
|
} JavaMethodInfo;
|
||||||
#pragma pack()
|
#pragma pack()
|
||||||
|
|
||||||
typedef struct _JavaPlugin
|
typedef struct _JavaPlugin
|
||||||
@ -135,19 +144,19 @@ FormatPlugin format_plugin =
|
|||||||
/* java_init */
|
/* java_init */
|
||||||
static int _java_init(FormatPlugin * format, char const * arch)
|
static int _java_init(FormatPlugin * format, char const * arch)
|
||||||
{
|
{
|
||||||
FormatPluginHelper * helper = format->helper;
|
|
||||||
JavaHeader jh;
|
|
||||||
JavaPlugin * java;
|
JavaPlugin * java;
|
||||||
|
|
||||||
if(arch != NULL && strcmp(arch, "java") != 0)
|
if(arch != NULL && strcmp(arch, "java") != 0)
|
||||||
return error_set_code(1, "%s: %s", arch,
|
return error_set_code(1, "%s: %s", arch,
|
||||||
"Unsupported architecture for java");
|
"Unsupported architecture for java");
|
||||||
|
#if 0 /* FIXME move this where appropriate */
|
||||||
memcpy(&jh.magic, format->signature, format->signature_len);
|
memcpy(&jh.magic, format->signature, format->signature_len);
|
||||||
jh.minor = _htob16(0);
|
jh.minor = _htob16(0);
|
||||||
jh.major = _htob16(0x32); /* XXX choose a more appropriate version */
|
jh.major = _htob16(0x32); /* XXX choose a more appropriate version */
|
||||||
jh.cp_cnt = _htob16(0);
|
jh.cp_cnt = _htob16(0);
|
||||||
if(helper->write(helper->format, &jh, sizeof(jh)) != sizeof(jh))
|
if(helper->write(helper->format, &jh, sizeof(jh)) != sizeof(jh))
|
||||||
return -1;
|
return -1;
|
||||||
|
#endif
|
||||||
if((java = object_new(sizeof(*java))) == NULL)
|
if((java = object_new(sizeof(*java))) == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
memset(java, 0, sizeof(*java));
|
memset(java, 0, sizeof(*java));
|
||||||
@ -283,60 +292,92 @@ static int _exit_attribute_table(FormatPlugin * format)
|
|||||||
/* java_detect */
|
/* java_detect */
|
||||||
static char const * _java_detect(FormatPlugin * format)
|
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";
|
return "java";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* java_decode */
|
/* 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)
|
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;
|
FormatPluginHelper * helper = format->helper;
|
||||||
JavaHeader jh;
|
JavaHeader jh;
|
||||||
JavaHeader2 jh2;
|
JavaHeader2 jh2;
|
||||||
uint16_t u16;
|
uint16_t u16;
|
||||||
off_t offset;
|
|
||||||
off_t end;
|
|
||||||
|
|
||||||
/* FIXME can this be correct? */
|
/* read header */
|
||||||
if(helper->seek(helper->format, sizeof(jh), SEEK_SET) != sizeof(jh))
|
if(helper->seek(helper->format, section->offset, SEEK_SET)
|
||||||
|
!= section->offset)
|
||||||
return -1;
|
return -1;
|
||||||
if(helper->read(helper->format, &jh, sizeof(jh)) != sizeof(jh))
|
if(helper->read(helper->format, &jh, sizeof(jh)) != sizeof(jh))
|
||||||
return -1;
|
return -1;
|
||||||
/* skip constants */
|
/* skip constants */
|
||||||
jh.cp_cnt = _htob16(jh.cp_cnt);
|
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;
|
return -1;
|
||||||
/* skip interfaces */
|
/* skip interfaces */
|
||||||
if(helper->read(helper->format, &jh2, sizeof(jh2)) != sizeof(jh2))
|
if(helper->read(helper->format, &jh2, sizeof(jh2)) != sizeof(jh2))
|
||||||
return -1;
|
return -1;
|
||||||
jh2.interfaces_cnt = _htob16(jh2.interfaces_cnt);
|
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;
|
return -1;
|
||||||
/* skip fields */
|
/* skip fields */
|
||||||
if(helper->read(helper->format, &u16, sizeof(u16)) != sizeof(u16))
|
if(helper->read(helper->format, &u16, sizeof(u16)) != sizeof(u16))
|
||||||
return -1;
|
return -1;
|
||||||
u16 = _htob16(u16);
|
u16 = _htob16(u16);
|
||||||
if(_decode_skip_fields(format, u16) != 0)
|
if(_decode_fields(format, u16) != 0)
|
||||||
return -1;
|
return -1;
|
||||||
/* disassemble the rest */
|
/* skip methods */
|
||||||
if((offset = helper->seek(helper->format, 0, SEEK_CUR)) < 0
|
if(helper->read(helper->format, &u16, sizeof(u16)) != sizeof(u16))
|
||||||
|| (end = helper->seek(helper->format, 0, SEEK_END))
|
|
||||||
< 0)
|
|
||||||
return -1;
|
return -1;
|
||||||
return helper->set_section(helper->format, 0, ".text", offset,
|
u16 = _htob16(u16);
|
||||||
end - offset, 0);
|
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;
|
FormatPluginHelper * helper = format->helper;
|
||||||
size_t i;
|
size_t i;
|
||||||
JavaAttributeInfo jai;
|
JavaAttributeInfo jai;
|
||||||
|
off_t offset;
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
fprintf(stderr, "DEBUG: %s(%u)\n", __func__, cnt);
|
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__,
|
fprintf(stderr, "DEBUG: %s() length=%u\n", __func__,
|
||||||
jai.length);
|
jai.length);
|
||||||
#endif
|
#endif
|
||||||
if(helper->seek(helper->format, jai.length, SEEK_CUR) < 0)
|
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 -1;
|
||||||
}
|
}
|
||||||
return 0;
|
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;
|
FormatPluginHelper * helper = format->helper;
|
||||||
size_t i;
|
size_t i;
|
||||||
@ -365,11 +415,13 @@ static int _decode_skip_constants(FormatPlugin * format, uint16_t cnt)
|
|||||||
size_t size;
|
size_t size;
|
||||||
char buf[8];
|
char buf[8];
|
||||||
uint16_t u16;
|
uint16_t u16;
|
||||||
|
off_t offset;
|
||||||
|
AsmString * as;
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
fprintf(stderr, "DEBUG: %s(%u)\n", __func__, cnt);
|
fprintf(stderr, "DEBUG: %s(%u)\n", __func__, cnt);
|
||||||
#endif
|
#endif
|
||||||
for(i = 0; i < cnt; i++)
|
for(i = 1; i < cnt; i++)
|
||||||
{
|
{
|
||||||
if(helper->read(helper->format, &jci, sizeof(jci))
|
if(helper->read(helper->format, &jci, sizeof(jci))
|
||||||
!= sizeof(jci))
|
!= sizeof(jci))
|
||||||
@ -389,19 +441,56 @@ static int _decode_skip_constants(FormatPlugin * format, uint16_t cnt)
|
|||||||
size = 4;
|
size = 4;
|
||||||
break;
|
break;
|
||||||
case CONSTANT_Class:
|
case CONSTANT_Class:
|
||||||
case CONSTANT_String:
|
|
||||||
size = 2;
|
size = 2;
|
||||||
break;
|
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:
|
case CONSTANT_Utf8:
|
||||||
size = sizeof(u16);
|
size = sizeof(u16);
|
||||||
if(helper->read(helper->format, &u16, size)
|
if(helper->read(helper->format, &u16, size)
|
||||||
!= (ssize_t)size)
|
!= (ssize_t)size)
|
||||||
return -1;
|
return -1;
|
||||||
u16 = _htob16(u16);
|
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)
|
if(helper->seek(helper->format, u16, SEEK_CUR)
|
||||||
< 0)
|
< 0)
|
||||||
return -1;
|
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;
|
break;
|
||||||
default:
|
default:
|
||||||
return -error_set_code(1, "%s: %s 0x%x",
|
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;
|
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;
|
FormatPluginHelper * helper = format->helper;
|
||||||
size_t i;
|
size_t i;
|
||||||
@ -432,12 +521,12 @@ static int _decode_skip_fields(FormatPlugin * format, uint16_t cnt)
|
|||||||
!= sizeof(jfi))
|
!= sizeof(jfi))
|
||||||
return -1;
|
return -1;
|
||||||
jfi.attributes_cnt = _htob16(jfi.attributes_cnt);
|
jfi.attributes_cnt = _htob16(jfi.attributes_cnt);
|
||||||
_decode_skip_attributes(format, jfi.attributes_cnt);
|
_decode_attributes(format, jfi.attributes_cnt, NULL, NULL);
|
||||||
}
|
}
|
||||||
return 0;
|
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;
|
FormatPluginHelper * helper = format->helper;
|
||||||
size_t i;
|
size_t i;
|
||||||
@ -453,13 +542,24 @@ static int _decode_skip_interfaces(FormatPlugin * format, uint16_t cnt)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int _decode_methods(FormatPlugin * format, uint16_t cnt,
|
||||||
/* java_decode_section */
|
|
||||||
static int _java_decode_section(FormatPlugin * format, AsmSection * section,
|
|
||||||
ArchInstructionCall ** calls, size_t * calls_cnt)
|
ArchInstructionCall ** calls, size_t * calls_cnt)
|
||||||
{
|
{
|
||||||
FormatPluginHelper * helper = format->helper;
|
FormatPluginHelper * helper = format->helper;
|
||||||
|
size_t i;
|
||||||
|
JavaMethodInfo jmi;
|
||||||
|
|
||||||
return helper->decode(helper->format, section->offset, section->size,
|
#ifdef DEBUG
|
||||||
section->base, calls, calls_cnt);
|
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