From 24200d46892221949e14a9dea6f6b46a77971e30 Mon Sep 17 00:00:00 2001 From: Pierre Pronchery Date: Thu, 28 Apr 2011 08:47:28 +0000 Subject: [PATCH] Moved deassembly printout into the Code class (allows printing strings) --- include/Asm/asm.h | 2 +- src/arch.c | 118 ++++++++++++--------------------------- src/arch.h | 7 ++- src/code.c | 138 +++++++++++++++++++++++++++++++++++++++++++--- src/format.h | 2 +- src/format/dex.c | 51 ++++------------- 6 files changed, 181 insertions(+), 137 deletions(-) diff --git a/include/Asm/asm.h b/include/Asm/asm.h index c4c79b7..d9c4627 100644 --- a/include/Asm/asm.h +++ b/include/Asm/asm.h @@ -80,7 +80,7 @@ int asm_set_section(Asm * a, char const * name, off_t offset, ssize_t size); AsmString * asm_get_string_by_id(Asm * a, AsmId id); AsmString * asm_get_string_by_name(Asm * a, char const * name); int asm_set_string(Asm * a, int id, char const * name, off_t offset, - ssize_t size); + ssize_t length); /* useful */ diff --git a/src/arch.c b/src/arch.c index 7bc169d..9110d99 100644 --- a/src/arch.c +++ b/src/arch.c @@ -431,112 +431,41 @@ ArchRegister * arch_get_register_by_name_size(Arch * arch, char const * name, /* useful */ /* arch_decode */ -static int _decode_print(Arch * arch, ArchInstructionCall * call); -static void _decode_print_immediate(Arch * arch, ArchOperand * ao); - -int arch_decode(Arch * arch) +int arch_decode(Arch * arch, ArchInstructionCall ** calls, size_t * calls_cnt) { - ArchInstructionCall * calls = NULL; - size_t calls_cnt = 0; + ArchInstructionCall * c = NULL; + size_t c_cnt = 0; ArchInstructionCall * p; - size_t i; if(arch->plugin->decode == NULL) return -error_set_code(1, "%s: %s", arch->plugin->name, "Disassembly not supported"); - printf("\n%08lx:\n", arch->buffer_pos + (long)arch->base); for(;;) { - if((p = realloc(calls, sizeof(*calls) * (calls_cnt + 1))) - == NULL) + if((p = realloc(c, sizeof(*c) * (c_cnt + 1))) == NULL) { - free(calls); + free(c); return -error_set_code(1, "%s", strerror(errno)); } - calls = p; - p = &calls[calls_cnt]; + c = p; + p = &c[c_cnt]; memset(p, 0, sizeof(*p)); p->base = arch->base; p->offset = arch->buffer_pos; if(arch->plugin->decode(arch->plugin, p) != 0) break; p->size = arch->buffer_pos - p->offset; - calls_cnt++; + c_cnt++; } - for(i = 0; i < calls_cnt; i++) - if(_decode_print(arch, &calls[i]) != 0) - return -1; - free(calls); + *calls = c; + *calls_cnt = c_cnt; return 0; } -static int _decode_print(Arch * arch, ArchInstructionCall * call) -{ - char const * sep = " "; - size_t i; - uint8_t u8; - ArchOperand * ao; - char const * name; - - if(arch->helper.seek(arch, call->offset, SEEK_SET) < 0) - return -1; - printf("%8lx:", (long)call->base + (long)call->offset); - for(i = 0; i < call->size; i++) - { - if(arch->helper.read(arch, &u8, sizeof(u8)) != sizeof(u8)) - return -1; - printf(" %02x", u8); - } - for(; i < 8; i++) - printf(" "); - printf(" %-12s", call->name); - for(i = 0; i < call->operands_cnt; i++) - { - ao = &call->operands[i]; - fputs(sep, stdout); - switch(AO_GET_TYPE(ao->type)) - { - case AOT_DREGISTER: - name = ao->value.dregister.name; - if(ao->value.dregister.offset == 0) - { - printf("[%%%s]", name); - break; - } - printf("[%%%s + $0x%lx]", name, - ao->value.dregister.offset); - break; - case AOT_DREGISTER2: - name = ao->value.dregister2.name; - printf("[%%%s + %%%s]", name, - ao->value.dregister2.name2); - break; - case AOT_IMMEDIATE: - _decode_print_immediate(arch, ao); - break; - case AOT_REGISTER: - name = call->operands[i].value._register.name; - printf("%%%s", name); - break; - } - sep = ", "; - } - putchar('\n'); - return 0; -} - -static void _decode_print_immediate(Arch * arch, ArchOperand * ao) -{ - printf("%s$0x%lx", ao->value.immediate.negative ? "-" : "", - ao->value.immediate.value); - if(AO_GET_VALUE(ao->type) == AOI_REFERS_STRING) - /* FIXME really print */ - printf("%s", " (string)"); -} - /* arch_decode_at */ -int arch_decode_at(Arch * arch, off_t offset, size_t size, off_t base) +int arch_decode_at(Arch * arch, ArchInstructionCall ** calls, + size_t * calls_cnt, off_t offset, size_t size, off_t base) { int ret; @@ -550,9 +479,12 @@ int arch_decode_at(Arch * arch, off_t offset, size_t size, off_t base) arch->base = base; arch->buffer_pos = offset; arch->buffer_cnt = offset + size; - if((ret = arch_decode(arch)) == 0 + if((ret = arch_decode(arch, calls, calls_cnt)) == 0 && fseek(arch->fp, offset + size, SEEK_SET) != 0) + { + free(*calls); /* XXX the pointer was updated anyway... */ ret = -error_set_code(1, "%s", strerror(errno)); + } return ret; } @@ -624,6 +556,24 @@ int arch_init_buffer(Arch * arch, char const * buffer, size_t size) } +/* arch_read */ +ssize_t arch_read(Arch * arch, void * buf, size_t size) +{ + if(arch->helper.read == NULL) + return -error_set_code(1, "%s", "read: No helper defined"); + return arch->helper.read(arch, buf, size); +} + + +/* arch_seek */ +off_t arch_seek(Arch * arch, off_t offset, int whence) +{ + if(arch->helper.seek == NULL) + return -error_set_code(1, "%s", "seek: No helper defined"); + return arch->helper.seek(arch, offset, whence); +} + + /* arch_write */ int arch_write(Arch * arch, ArchInstruction * instruction, ArchInstructionCall * call) diff --git a/src/arch.h b/src/arch.h index 258128c..55589c6 100644 --- a/src/arch.h +++ b/src/arch.h @@ -59,7 +59,10 @@ int arch_write(Arch * arch, ArchInstruction * instruction, ArchInstructionCall * call); /* disassembly */ -int arch_decode(Arch * arch); -int arch_decode_at(Arch * arch, off_t offset, size_t size, off_t base); +int arch_decode(Arch * arch, ArchInstructionCall ** calls, size_t * calls_cnt); +int arch_decode_at(Arch * arch, ArchInstructionCall ** calls, + size_t * calls_cnt, off_t offset, size_t size, off_t base); +ssize_t arch_read(Arch * arch, void * buf, size_t cnt); +off_t arch_seek(Arch * arch, off_t offset, int whence); #endif /* !ASM_ARCH_H */ diff --git a/src/code.c b/src/code.c index 5eaff50..3d67a0d 100644 --- a/src/code.c +++ b/src/code.c @@ -37,7 +37,7 @@ typedef struct _CodeString int id; char * name; off_t offset; - ssize_t size; + ssize_t length; } CodeString; struct _Code @@ -60,9 +60,10 @@ static void _code_string_delete_all(Code * code); static CodeString * _code_string_get_by_id(Code * code, AsmId id); static int _code_string_set(CodeString * codestring, int id, char const * name, - off_t offset, ssize_t size); + off_t offset, ssize_t length); static CodeString * _code_string_append(Code * code); +static int _code_string_read(Code * code, CodeString * codestring); /* functions */ @@ -146,16 +147,101 @@ int code_close(Code * code) /* code_decode */ +static int _decode_print(Code * code, ArchInstructionCall * call); +static void _decode_print_immediate(Code * code, ArchOperand * ao); + int code_decode(Code * code, char const * buffer, size_t size) { int ret; + ArchInstructionCall * calls = NULL; + size_t calls_cnt = 0; + size_t i; arch_init_buffer(code->arch, buffer, size); - ret = arch_decode(code->arch); + if((ret = arch_decode(code->arch, &calls, &calls_cnt)) == 0) + { + fprintf(stderr, "DEBUG: %lu\n", calls_cnt); + for(i = 0; i < calls_cnt; i++) + _decode_print(code, &calls[i]); + free(calls); + } arch_exit(code->arch); return ret; } +static int _decode_print(Code * code, ArchInstructionCall * call) +{ + char const * sep = " "; + size_t i; + uint8_t u8; + ArchOperand * ao; + char const * name; + + if(arch_seek(code->arch, call->offset, SEEK_SET) < 0) + return -1; + printf("%8lx:", (long)call->base + (long)call->offset); + for(i = 0; i < call->size; i++) + { + if(arch_read(code->arch, &u8, sizeof(u8)) != sizeof(u8)) + return -1; + printf(" %02x", u8); + } + for(; i < 8; i++) + printf(" "); + printf(" %-12s", call->name); + for(i = 0; i < call->operands_cnt; i++) + { + ao = &call->operands[i]; + fputs(sep, stdout); + switch(AO_GET_TYPE(ao->type)) + { + case AOT_DREGISTER: + name = ao->value.dregister.name; + if(ao->value.dregister.offset == 0) + { + printf("[%%%s]", name); + break; + } + printf("[%%%s + $0x%lx]", name, + ao->value.dregister.offset); + break; + case AOT_DREGISTER2: + name = ao->value.dregister2.name; + printf("[%%%s + %%%s]", name, + ao->value.dregister2.name2); + break; + case AOT_IMMEDIATE: + _decode_print_immediate(code, ao); + break; + case AOT_REGISTER: + name = call->operands[i].value._register.name; + printf("%%%s", name); + break; + } + sep = ", "; + } + putchar('\n'); + return 0; +} + +static void _decode_print_immediate(Code * code, ArchOperand * ao) +{ + CodeString * cs; + + printf("%s$0x%lx", ao->value.immediate.negative ? "-" : "", + ao->value.immediate.value); + if(AO_GET_VALUE(ao->type) == AOI_REFERS_STRING) + { + cs = _code_string_get_by_id(code, ao->value.immediate.value); + if(cs != NULL && cs->name == NULL) + _code_string_read(code, cs); + if(cs != NULL && cs->name != NULL) + printf(" \"%s\"", cs->name); + else + printf("%s", " (string)"); + } +} + /* code_decode_file */ static int _decode_file_callback(void * priv, char const * section, @@ -185,14 +271,23 @@ static int _decode_file_callback(void * priv, char const * section, off_t offset, size_t size, off_t base) { Code * code = priv; + ArchInstructionCall * calls = NULL; + size_t calls_cnt = 0; + size_t i; if(section != NULL) printf("%s%s:\n", "\nDisassembly of section ", section); - return arch_decode_at(code->arch, offset, size, base); + if(arch_decode_at(code->arch, &calls, &calls_cnt, offset, size, base) + != 0) + return -1; + for(i = 0; i < calls_cnt; i++) + _decode_print(code, &calls[i]); + free(calls); + return 0; } static int _set_string_callback(void * priv, int id, char const * name, - off_t offset, ssize_t size) + off_t offset, ssize_t length) { Code * code = priv; CodeString * cs = NULL; @@ -201,7 +296,7 @@ static int _set_string_callback(void * priv, int id, char const * name, cs = _code_string_get_by_id(code, id); if(cs == NULL) cs = _code_string_append(code); - if(cs == NULL || _code_string_set(cs, id, name, offset, size) != 0) + if(cs == NULL || _code_string_set(cs, id, name, offset, length) != 0) return -1; return cs->id; } @@ -293,7 +388,7 @@ static CodeString * _code_string_get_by_id(Code * code, AsmId id) /* code_string_set */ static int _code_string_set(CodeString * codestring, int id, char const * name, - off_t offset, ssize_t size) + off_t offset, ssize_t length) { char * p = NULL; @@ -303,7 +398,7 @@ static int _code_string_set(CodeString * codestring, int id, char const * name, free(codestring->name); codestring->name = p; codestring->offset = offset; - codestring->size = size; + codestring->length = length; return 0; } @@ -324,6 +419,31 @@ static CodeString * _code_string_append(Code * code) p->id = -1; p->name = NULL; p->offset = -1; - p->size = -1; + p->length = -1; return p; } + + +/* code_string_read */ +static int _code_string_read(Code * code, CodeString * codestring) +{ + char * buf; + + if(codestring->offset < 0 || codestring->length < 0) + return -error_set_code(1, "%s", "Insufficient information to" + " read string"); + if(arch_seek(code->arch, codestring->offset, SEEK_SET) + != codestring->offset) + return -1; + if((buf = malloc(codestring->length + 1)) == NULL) + return -error_set_code(1, "%s", strerror(errno)); + if(arch_read(code->arch, buf, codestring->length) != codestring->length) + { + free(buf); + return -1; + } + buf[codestring->length] = '\0'; + free(codestring->name); + codestring->name = buf; + return 0; +} diff --git a/src/format.h b/src/format.h index 6fb4918..4d8234e 100644 --- a/src/format.h +++ b/src/format.h @@ -27,7 +27,7 @@ typedef int (*FormatDecodeCallback)(void * priv, char const * section, off_t offset, size_t size, off_t base); typedef int (*FormatSetStringCallback)(void * priv, int id, char const * name, - off_t offset, ssize_t size); + off_t offset, ssize_t length); /* functions */ Format * format_new(char const * format, char const * arch); diff --git a/src/format/dex.c b/src/format/dex.c index 1d209d6..e61c505 100644 --- a/src/format/dex.c +++ b/src/format/dex.c @@ -101,10 +101,6 @@ typedef struct _DexString char * string; } DexString; -typedef struct _Dex -{ -} Dex; - /* variables */ static char _dex_signature[4] = "dex\n"; @@ -113,12 +109,9 @@ static char _dex_signature[4] = "dex\n"; /* prototypes */ /* plug-in */ static int _dex_init(FormatPlugin * format, char const * arch); -static int _dex_destroy(FormatPlugin * format); static char const * _dex_detect(FormatPlugin * format); static int _dex_decode(FormatPlugin * format); -static int _dex_error(FormatPlugin * format); - /* public */ /* variables */ @@ -129,7 +122,7 @@ FormatPlugin format_plugin = _dex_signature, sizeof(_dex_signature), _dex_init, - _dex_destroy, + NULL, NULL, NULL, _dex_detect, @@ -144,28 +137,12 @@ FormatPlugin format_plugin = /* dex_init */ static int _dex_init(FormatPlugin * format, char const * arch) { - Dex * dex; - #ifdef DEBUG fprintf(stderr, "DEBUG: %s(\"%s\")\n", __func__, arch); #endif if(arch != NULL && strcmp(arch, "dalvik") != 0) return -error_set_code(1, "%s: %s", arch, "Unsupported Dex architecture"); - if((dex = object_new(sizeof(*dex))) == NULL) - return -1; - format->priv = dex; - return 0; -} - - -/* dex_destroy */ -static int _dex_destroy(FormatPlugin * format) -{ - Dex * dex = format->priv; - size_t i; - - object_delete(dex); return 0; } @@ -313,10 +290,10 @@ static int _decode_map_string_id(FormatPlugin * format, off_t offset, size_t size) { FormatPluginHelper * helper = format->helper; - Dex * dex = format->priv; size_t i; DexStringIdItem * dsii; ssize_t s; + uint8_t u8; if(helper->seek(helper->format, offset, SEEK_SET) != offset) return -1; @@ -328,22 +305,16 @@ static int _decode_map_string_id(FormatPlugin * format, off_t offset, for(i = 0; i < size; i++) { dsii[i].string_data_off = _htol32(dsii[i].string_data_off); -#if 1 /* def DEBUG */ - fprintf(stderr, "DEBUG: %s() string %lu offset 0x%x\n", - __func__, i, dsii[i].string_data_off); + offset = dsii[i].string_data_off; + if(helper->seek(helper->format, offset, SEEK_SET) != offset) + return -1; + if(helper->read(helper->format, &u8, sizeof(u8)) != sizeof(u8)) + return -1; +#ifdef DEBUG + fprintf(stderr, "DEBUG: %s() string %lu offset 0x%x len %u\n", + __func__, i, offset, u8); #endif - helper->set_string(helper->format, i, NULL, - dsii[i].string_data_off, -1); + helper->set_string(helper->format, i, NULL, offset + 1, u8); } return 0; } - - -/* dex_error */ -static int _dex_error(FormatPlugin * format) -{ - FormatPluginHelper * helper = format->helper; - - return -error_set_code(1, "%s: %s", - helper->get_filename(helper->format), strerror(errno)); -}