From 8a24516f7fa9e193db6a649f48a215a08ab835d4 Mon Sep 17 00:00:00 2001 From: Pierre Pronchery Date: Sat, 23 Apr 2011 07:46:35 +0000 Subject: [PATCH] Decoding some more i386 --- include/Asm/arch.h | 10 +++--- src/arch.c | 50 +++++++++++++++++++++++++++--- src/arch.h | 3 +- src/arch/i386.h | 77 +++++++++++++++++++++++++++++++++++++++++++++- 4 files changed, 129 insertions(+), 11 deletions(-) diff --git a/include/Asm/arch.h b/include/Asm/arch.h index 5d8115e..a6d7ac4 100644 --- a/include/Asm/arch.h +++ b/include/Asm/arch.h @@ -119,15 +119,15 @@ typedef struct _ArchOperand /* AOT_DREGISTER */ struct { - char * name; + char const * name; int64_t offset; } dregister; /* AOT_DREGISTER2 */ struct { - char * name; - char * name2; + char const * name; + char const * name2; } dregister2; /* AOT_IMMEDIATE */ @@ -140,7 +140,7 @@ typedef struct _ArchOperand /* AOT_REGISTER */ struct { - char * name; + char const * name; } _register; /* FIXME complete */ } value; @@ -181,6 +181,8 @@ typedef struct _ArchPluginHelper char const * (*get_filename)(Arch * arch); ArchInstruction * (*get_instruction_by_opcode)(Arch * arch, uint8_t size, uint32_t opcode); + ArchRegister * (*get_register_by_id_size)(Arch * arch, uint32_t id, + uint32_t size); ArchRegister * (*get_register_by_name_size)(Arch * arch, char const * name, uint32_t size); diff --git a/src/arch.c b/src/arch.c index 17d8f4a..0fca8ec 100644 --- a/src/arch.c +++ b/src/arch.c @@ -386,13 +386,15 @@ ArchRegister * arch_get_register(Arch * arch, size_t index) } -/* arch_get_register_by_id */ -ArchRegister * arch_get_register_by_id(Arch * arch, unsigned int id) +/* arch_get_register_by_id_size */ +ArchRegister * arch_get_register_by_id_size(Arch * arch, uint32_t id, + uint32_t size) { size_t i; for(i = 0; i < arch->registers_cnt; i++) - if(arch->plugin->registers[i].id == id) + if(arch->plugin->registers[i].id == id + && arch->plugin->registers[i].size == size) return &arch->plugin->registers[i]; return NULL; } @@ -449,8 +451,44 @@ int arch_decode(Arch * arch) static void _decode_print(ArchInstructionCall * call) { - /* FIXME really implement */ - printf("\t%s\n", call->name); + char const * sep = "\t"; + size_t i; + ArchOperand * ao; + char const * name; + + printf("\t%s", call->name); + for(i = 0; i < call->operands_cnt; i++) + { + ao = &call->operands[i]; + switch(AO_GET_TYPE(call->operands[i].type)) + { + case AOT_DREGISTER: + name = ao->value.dregister.name; + printf("%s[%%%s + $0x%lx]", sep, name, + ao->value.dregister.offset); + sep = ", "; + break; + case AOT_DREGISTER2: + name = ao->value.dregister2.name; + printf("%s[%%%s + %%%s]", sep, name, + ao->value.dregister2.name2); + sep = ", "; + break; + case AOT_IMMEDIATE: + printf("%s%s$0x%lx", sep, + ao->value.immediate.negative + ? "-" : "", + ao->value.immediate.value); + sep = ", "; + break; + case AOT_REGISTER: + name = call->operands[i].value._register.name; + printf("%s%%%s", sep, name); + sep = ", "; + break; + } + } + putchar('\n'); } @@ -482,6 +520,7 @@ int arch_init(Arch * arch, char const * filename, FILE * fp) arch->helper.arch = arch; arch->helper.get_filename = _arch_get_filename; arch->helper.get_instruction_by_opcode = arch_get_instruction_by_opcode; + arch->helper.get_register_by_id_size = arch_get_register_by_id_size; arch->helper.get_register_by_name_size = arch_get_register_by_name_size; arch->helper.read = NULL; arch->helper.write = _arch_write; @@ -503,6 +542,7 @@ int arch_init_buffer(Arch * arch, char const * buffer, size_t size) arch->helper.arch = arch; arch->helper.get_filename = _arch_get_filename; arch->helper.get_instruction_by_opcode = arch_get_instruction_by_opcode; + arch->helper.get_register_by_id_size = arch_get_register_by_id_size; arch->helper.get_register_by_name_size = arch_get_register_by_name_size; arch->helper.write = NULL; arch->helper.read = _arch_read_buffer; diff --git a/src/arch.h b/src/arch.h index a174c08..a29be9b 100644 --- a/src/arch.h +++ b/src/arch.h @@ -43,7 +43,8 @@ ArchInstruction * arch_get_instruction_by_call(Arch * arch, ArchInstructionCall * call); ArchRegister * arch_get_register(Arch * arch, size_t index); -ArchRegister * arch_get_register_by_id(Arch * arch, unsigned int id); +ArchRegister * arch_get_register_by_id_size(Arch * arch, uint32_t id, + uint32_t size); ArchRegister * arch_get_register_by_name(Arch * arch, char const * name); ArchRegister * arch_get_register_by_name_size(Arch * arch, char const * name, uint32_t size); diff --git a/src/arch/i386.h b/src/arch/i386.h index 432ff45..3e7d44f 100644 --- a/src/arch/i386.h +++ b/src/arch/i386.h @@ -30,13 +30,21 @@ static int _i386_write(ArchPlugin * plugin, ArchInstruction * instruction, /* functions */ /* i386_decode */ +static int _decode_dregister(ArchPlugin * plugin, ArchInstructionCall * call, + size_t i); +static int _decode_operand(ArchPlugin * plugin, ArchInstructionCall * call, + size_t i); +static int _decode_register(ArchPlugin * plugin, ArchInstructionCall * call, + size_t i); + static int _i386_decode(ArchPlugin * plugin, ArchInstructionCall * call) { ArchPluginHelper * helper = plugin->helper; ArchInstruction * ai = NULL; uint8_t opcode; + size_t i; - /* FIXME really implement */ + /* FIXME detect end of input */ if(helper->read(helper->arch, &opcode, sizeof(opcode)) != sizeof(opcode)) return -1; @@ -53,6 +61,73 @@ static int _i386_decode(ArchPlugin * plugin, ArchInstructionCall * call) return 0; } call->name = ai->name; + call->operands[0].type = ai->op1; + call->operands[1].type = ai->op2; + call->operands[2].type = ai->op3; + for(i = 0; AO_GET_TYPE(call->operands[i].type) != 0; i++) + if(_decode_operand(plugin, call, i) != 0) + return -1; + call->operands_cnt = i; + return 0; +} + +static int _decode_dregister(ArchPlugin * plugin, ArchInstructionCall * call, + size_t i) +{ + ArchPluginHelper * helper = plugin->helper; + ArchOperandDefinition aod = call->operands[i].type; + ArchRegister * ar; + uint8_t id; + + /* FIXME check the size */ + if(helper->read(helper->arch, &id, sizeof(id)) != sizeof(id)) + return -1; + if((ar = helper->get_register_by_id_size(helper->arch, id, + AO_GET_SIZE(aod))) == NULL) + return -1; + call->operands[i].value.dregister.name = ar->name; + call->operands[i].value.dregister.offset = 0; + return 0; +} + +static int _decode_operand(ArchPlugin * plugin, ArchInstructionCall * call, + size_t i) +{ + switch(AO_GET_TYPE(call->operands[i].type)) + { + /* FIXME implement the rest */ + case AOT_DREGISTER: + return _decode_dregister(plugin, call, i); + case AOT_REGISTER: + return _decode_register(plugin, call, i); + } + return -error_set_code(1, "%s", strerror(ENOSYS)); +} + +static int _decode_register(ArchPlugin * plugin, ArchInstructionCall * call, + size_t i) +{ + ArchPluginHelper * helper = plugin->helper; + ArchOperandDefinition aod = call->operands[i].type; + ArchRegister * ar; + uint8_t id; + + if(AO_GET_FLAGS(aod) & AOF_IMPLICIT) + { + if((ar = helper->get_register_by_id_size(helper->arch, + AO_GET_VALUE(aod), + AO_GET_SIZE(aod))) == NULL) + return -1; + call->operands[i].value._register.name = ar->name; + return 0; + } + /* FIXME check the size */ + if(helper->read(helper->arch, &id, sizeof(id)) != sizeof(id)) + return -1; + if((ar = helper->get_register_by_id_size(helper->arch, id, + AO_GET_SIZE(aod))) == NULL) + return -1; + call->operands[i].value._register.name = ar->name; return 0; }