From d43e27eb8d511740a53e6b5de3fb23c276e7bb32 Mon Sep 17 00:00:00 2001 From: Pierre Pronchery Date: Wed, 31 Aug 2011 16:19:07 +0000 Subject: [PATCH] Let the arch plug-ins know the current base address when decoding instructions --- include/Asm/arch.h | 3 ++- src/arch.c | 10 ++++++---- src/arch.h | 2 +- src/arch/dalvik.c | 6 ++++-- src/arch/i386.h | 23 ++++++++++++++++++----- src/arch/java.c | 6 ++++-- src/arch/sparc.h | 6 ++++-- src/code.c | 6 +++--- 8 files changed, 42 insertions(+), 20 deletions(-) diff --git a/include/Asm/arch.h b/include/Asm/arch.h index 845ef40..7d41f42 100644 --- a/include/Asm/arch.h +++ b/include/Asm/arch.h @@ -221,7 +221,8 @@ struct _ArchPlugin int (*write)(ArchPlugin * arch, ArchInstruction * instruction, ArchInstructionCall * call); - int (*decode)(ArchPlugin * arch, ArchInstructionCall * call); + int (*decode)(ArchPlugin * arch, ArchInstructionCall * call, + off_t base); }; #endif /* !DEVEL_ASM_ARCH_H */ diff --git a/src/arch.c b/src/arch.c index 2dfdff8..bb7d3d5 100644 --- a/src/arch.c +++ b/src/arch.c @@ -436,12 +436,13 @@ ArchRegister * arch_get_register_by_name_size(Arch * arch, char const * name, /* useful */ /* arch_decode */ int arch_decode(Arch * arch, Code * code, ArchInstructionCall ** calls, - size_t * calls_cnt) + size_t * calls_cnt, off_t base) { int ret = 0; ArchInstructionCall * c = NULL; size_t c_cnt = 0; ArchInstructionCall * p; + size_t offset = 0; if(arch->plugin->decode == NULL) return -error_set_code(1, "%s: %s", arch->plugin->name, @@ -458,11 +459,12 @@ int arch_decode(Arch * arch, Code * code, ArchInstructionCall ** calls, c = p; p = &c[c_cnt]; memset(p, 0, sizeof(*p)); - p->base = arch->base; + p->base = base + offset; p->offset = arch->buffer_pos; - if(arch->plugin->decode(arch->plugin, p) != 0) + if(arch->plugin->decode(arch->plugin, p, base) != 0) break; p->size = arch->buffer_pos - p->offset; + offset += p->size; c_cnt++; } if(ret == 0) @@ -491,7 +493,7 @@ int arch_decode_at(Arch * arch, Code * code, ArchInstructionCall ** calls, arch->code = code; arch->buffer_pos = offset; arch->buffer_cnt = offset + size; - if((ret = arch_decode(arch, code, calls, calls_cnt)) == 0 + if((ret = arch_decode(arch, code, calls, calls_cnt, base)) == 0 && fseek(arch->fp, offset + size, SEEK_SET) != 0) { free(*calls); /* XXX the pointer was updated anyway... */ diff --git a/src/arch.h b/src/arch.h index 4632d0c..6dbdf07 100644 --- a/src/arch.h +++ b/src/arch.h @@ -61,7 +61,7 @@ int arch_write(Arch * arch, ArchInstruction * instruction, /* disassembly */ int arch_decode(Arch * arch, Code * code, ArchInstructionCall ** calls, - size_t * calls_cnt); + size_t * calls_cnt, off_t base); int arch_decode_at(Arch * arch, Code * code, 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); diff --git a/src/arch/dalvik.c b/src/arch/dalvik.c index 2837822..430327d 100644 --- a/src/arch/dalvik.c +++ b/src/arch/dalvik.c @@ -79,7 +79,8 @@ static ArchInstruction _dalvik_instructions[] = /* plug-in */ static int _dalvik_write(ArchPlugin * plugin, ArchInstruction * instruction, ArchInstructionCall * call); -static int _dalvik_decode(ArchPlugin * plugin, ArchInstructionCall * call); +static int _dalvik_decode(ArchPlugin * plugin, ArchInstructionCall * call, + off_t base); /* public */ @@ -138,7 +139,8 @@ static int _decode_immediate(DalvikDecode * dd, size_t i); static int _decode_operand(DalvikDecode * dd, size_t i); static int _decode_register(DalvikDecode * dd, size_t i); -static int _dalvik_decode(ArchPlugin * plugin, ArchInstructionCall * call) +static int _dalvik_decode(ArchPlugin * plugin, ArchInstructionCall * call, + off_t base) { DalvikDecode dd; ArchPluginHelper * helper = plugin->helper; diff --git a/src/arch/i386.h b/src/arch/i386.h index 312893e..f74708f 100644 --- a/src/arch/i386.h +++ b/src/arch/i386.h @@ -23,7 +23,8 @@ /* i386 */ /* private */ /* prototypes */ -static int _i386_decode(ArchPlugin * plugin, ArchInstructionCall * call); +static int _i386_decode(ArchPlugin * plugin, ArchInstructionCall * call, + off_t base); static int _i386_write(ArchPlugin * plugin, ArchInstruction * instruction, ArchInstructionCall * call); @@ -45,18 +46,22 @@ static int _decode_operand(ArchPlugin * plugin, ArchInstructionCall * call, static int _decode_register(ArchPlugin * plugin, ArchInstructionCall * call, size_t i); -static int _i386_decode(ArchPlugin * plugin, ArchInstructionCall * call) +static int _i386_decode(ArchPlugin * plugin, ArchInstructionCall * call, + off_t base) { ArchPluginHelper * helper = plugin->helper; ArchInstruction * ai = NULL; + unsigned int opcode; uint8_t u8; uint16_t u16; size_t i; + off_t offset; /* FIXME detect end of input */ if(helper->read(helper->arch, &u8, sizeof(u8)) != sizeof(u8)) return -1; - if((ai = helper->get_instruction_by_opcode(helper->arch, 8, u8)) + opcode = u8; + if((ai = helper->get_instruction_by_opcode(helper->arch, 8, opcode)) == NULL) { u16 = u8; @@ -70,9 +75,9 @@ static int _i386_decode(ArchPlugin * plugin, ArchInstructionCall * call) call->operands_cnt = 1; return 0; } - u16 = (u16 << 8) | u8; + opcode = (u16 << 8) | u8; if((ai = helper->get_instruction_by_opcode(helper->arch, 16, - u16)) == NULL) + opcode)) == NULL) { call->name = "dw"; call->operands[0].definition = AO_IMMEDIATE(0, 16, 0); @@ -92,6 +97,14 @@ static int _i386_decode(ArchPlugin * plugin, ArchInstructionCall * call) if(_decode_operand(plugin, call, &i) != 0) return -1; call->operands_cnt = i; + /* additional adjustments */ + switch(opcode) + { + case 0xe8: /* call */ + call->operands[0].value.immediate.value += call->base + + 5; + break; + } return 0; } diff --git a/src/arch/java.c b/src/arch/java.c index b817b35..20d9f86 100644 --- a/src/arch/java.c +++ b/src/arch/java.c @@ -250,7 +250,8 @@ static ArchInstruction _java_instructions[] = /* plug-in */ static int _java_write(ArchPlugin * plugin, ArchInstruction * instruction, ArchInstructionCall * call); -static int _java_decode(ArchPlugin * plugin, ArchInstructionCall * call); +static int _java_decode(ArchPlugin * plugin, ArchInstructionCall * call, + off_t base); /* public */ @@ -317,7 +318,8 @@ static int _java_write(ArchPlugin * plugin, ArchInstruction * instruction, /* java_decode */ -static int _java_decode(ArchPlugin * plugin, ArchInstructionCall * call) +static int _java_decode(ArchPlugin * plugin, ArchInstructionCall * call, + off_t base) { ArchPluginHelper * helper = plugin->helper; uint8_t u8; diff --git a/src/arch/sparc.h b/src/arch/sparc.h index ed3131b..894af70 100644 --- a/src/arch/sparc.h +++ b/src/arch/sparc.h @@ -22,7 +22,8 @@ /* private */ /* prototypes */ /* plug-in */ -static int _sparc_decode(ArchPlugin * plugin, ArchInstructionCall * call); +static int _sparc_decode(ArchPlugin * plugin, ArchInstructionCall * call, + off_t base); static int _sparc_write(ArchPlugin * plugin, ArchInstruction * instruction, ArchInstructionCall * call); @@ -30,7 +31,8 @@ static int _sparc_write(ArchPlugin * plugin, ArchInstruction * instruction, /* functions */ /* plug-in */ /* sparc_decode */ -static int _sparc_decode(ArchPlugin * plugin, ArchInstructionCall * call) +static int _sparc_decode(ArchPlugin * plugin, ArchInstructionCall * call, + off_t base) { ArchPluginHelper * helper = plugin->helper; uint32_t u32; diff --git a/src/code.c b/src/code.c index a80c86b..e7d5d3d 100644 --- a/src/code.c +++ b/src/code.c @@ -338,7 +338,7 @@ int code_decode_at(Code * code, char const * section, off_t offset, base) != 0) return -1; if(size != 0) - printf("\n%08lx:\n", (long)offset + (long)base); + printf("\n%08lx:\n", (long)base); for(i = 0; i < calls_cnt; i++) code_print(code, &calls[i]); free(calls); @@ -357,7 +357,7 @@ int code_decode_buffer(Code * code, char const * buffer, size_t size) size_t i; arch_init_buffer(code->arch, buffer, size); - if((ret = arch_decode(code->arch, code, &calls, &calls_cnt)) == 0) + if((ret = arch_decode(code->arch, code, &calls, &calls_cnt, 0)) == 0) { for(i = 0; i < calls_cnt; i++) code_print(code, &calls[i]); @@ -429,7 +429,7 @@ int code_print(Code * code, ArchInstructionCall * call) if(arch_seek(code->arch, call->offset, SEEK_SET) < 0) return -1; - printf("%8lx:", (long)call->base + (long)call->offset); + printf("%8lx:", (long)call->base); for(i = 0; i < call->size; i++) { if(arch_read(code->arch, &u8, sizeof(u8)) != sizeof(u8))