diff --git a/src/arch/java.c b/src/arch/java.c index cbcc5d8..96174e0 100644 --- a/src/arch/java.c +++ b/src/arch/java.c @@ -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; diff --git a/src/format/java.c b/src/format/java.c index 9a7f799..e46b639 100644 --- a/src/format/java.c +++ b/src/format/java.c @@ -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; }