From 1249cf6e2c0ed87e1c593e488beedbbfe153ff00 Mon Sep 17 00:00:00 2001 From: Cyrille Bagard Date: Sun, 3 Aug 2008 15:35:43 +0000 Subject: Read registers from the ModR/M encoding. git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@13 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a --- ChangeLog | 33 +++++++ src/arch/x86/Makefile.am | 7 ++ src/arch/x86/instruction.h | 149 ++++++++++++------------------ src/arch/x86/op_adc.c | 98 ++++++++++++++++++++ src/arch/x86/op_add.c | 98 ++++++++++++++++++++ src/arch/x86/op_and.c | 98 ++++++++++++++++++++ src/arch/x86/op_mov.c | 67 ++++++++++++++ src/arch/x86/op_or.c | 98 ++++++++++++++++++++ src/arch/x86/op_sbb.c | 98 ++++++++++++++++++++ src/arch/x86/op_sub.c | 98 ++++++++++++++++++++ src/arch/x86/op_xor.c | 165 +++++++++++++++++++++++++++++++++ src/arch/x86/opcodes.h | 27 ++++++ src/arch/x86/operand.c | 59 ++++++++++++ src/arch/x86/operand.h | 3 + src/arch/x86/processor.c | 223 +++++++++++++++++++++++---------------------- 15 files changed, 1118 insertions(+), 203 deletions(-) create mode 100644 src/arch/x86/op_adc.c create mode 100644 src/arch/x86/op_add.c create mode 100644 src/arch/x86/op_and.c create mode 100644 src/arch/x86/op_or.c create mode 100644 src/arch/x86/op_sbb.c create mode 100644 src/arch/x86/op_sub.c create mode 100644 src/arch/x86/op_xor.c diff --git a/ChangeLog b/ChangeLog index 66c77d7..8a8a99b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,36 @@ +2008-08-03 Cyrille Bagard + + * src/arch/x86/instruction.h: + Remove all the identifiers for the prefix '0x66'. + + * src/arch/x86/Makefile.am: + Add op_(adc|add|and|or|sbb|sub|xor).c to libarchx86_a_SOURCES. + + * src/arch/x86/op_adc.c: + * src/arch/x86/op_add.c: + * src/arch/x86/op_and.c: + New entries: support more opcodes. + + * src/arch/x86/opcodes.h: + Register the new opcodes. + + * src/arch/x86/operand.c: + * src/arch/x86/operand.h: + Read registers from the ModR/M encoding. + + * src/arch/x86/op_mov.c: + Support the 'mov' opcode from a register to another one. + + * src/arch/x86/op_or.c: + * src/arch/x86/op_sbb.c: + * src/arch/x86/op_sub.c: + * src/arch/x86/op_xor.c: + New entries: support more opcodes. + + * src/arch/x86/processor.c: + Handle opcode extension. Improve the way that instructions with prefix + are handled, and thus decrease the amount of lines of code. + 2008-08-01 Cyrille Bagard * src/arch/x86/instruction.h: diff --git a/src/arch/x86/Makefile.am b/src/arch/x86/Makefile.am index 0a32def..aba9e5b 100644 --- a/src/arch/x86/Makefile.am +++ b/src/arch/x86/Makefile.am @@ -3,6 +3,9 @@ lib_LIBRARIES = libarchx86.a libarchx86_a_SOURCES = \ instruction.h \ + op_adc.c \ + op_add.c \ + op_and.c \ op_call.c \ op_dec.c \ op_hlt.c \ @@ -11,9 +14,13 @@ libarchx86_a_SOURCES = \ op_leave.c \ op_nop.c \ op_mov.c \ + op_or.c \ op_pop.c \ op_push.c \ op_ret.c \ + op_sbb.c \ + op_sub.c \ + op_xor.c \ opcodes.h \ operand.h operand.c \ processor.h processor.c diff --git a/src/arch/x86/instruction.h b/src/arch/x86/instruction.h index af1c5bc..9f89a9e 100644 --- a/src/arch/x86/instruction.h +++ b/src/arch/x86/instruction.h @@ -38,54 +38,66 @@ typedef struct _asm_x86_instr asm_x86_instr; /* Enumération de tous les opcodes */ typedef enum _X86Opcodes { - X86_OP_INC_EAX, /* inc (0x40) */ - X86_OP_INC_ECX, /* inc (0x41) */ - X86_OP_INC_EDX, /* inc (0x42) */ - X86_OP_INC_EBX, /* inc (0x43) */ - X86_OP_INC_ESP, /* inc (0x44) */ - X86_OP_INC_EBP, /* inc (0x45) */ - X86_OP_INC_ESI, /* inc (0x46) */ - X86_OP_INC_EDI, /* inc (0x47) */ - - X86_OP_DEC_EAX, /* dec (0x48) */ - X86_OP_DEC_ECX, /* dec (0x49) */ - X86_OP_DEC_EDX, /* dec (0x4a) */ - X86_OP_DEC_EBX, /* dec (0x4b) */ - X86_OP_DEC_ESP, /* dec (0x4c) */ - X86_OP_DEC_EBP, /* dec (0x4d) */ - X86_OP_DEC_ESI, /* dec (0x4e) */ - X86_OP_DEC_EDI, /* dec (0x4f) */ - - X86_OP_PUSH_EAX, /* push (0x50) */ - X86_OP_PUSH_ECX, /* push (0x51) */ - X86_OP_PUSH_EDX, /* push (0x52) */ - X86_OP_PUSH_EBX, /* push (0x53) */ - X86_OP_PUSH_ESP, /* push (0x54) */ - X86_OP_PUSH_EBP, /* push (0x55) */ - X86_OP_PUSH_ESI, /* push (0x56) */ - X86_OP_PUSH_EDI, /* push (0x57) */ - - X86_OP_POP_EAX, /* pop (0x58) */ - X86_OP_POP_ECX, /* pop (0x59) */ - X86_OP_POP_EDX, /* pop (0x5a) */ - X86_OP_POP_EBX, /* pop (0x5b) */ - X86_OP_POP_ESP, /* pop (0x5c) */ - X86_OP_POP_EBP, /* pop (0x5d) */ - X86_OP_POP_ESI, /* pop (0x5e) */ - X86_OP_POP_EDI, /* pop (0x5f) */ - - X86_OP_PUSH_IMM32, /* push (0x68) */ + X86_OP_XOR_REG1632, /* xor ([0x66] 0x31) */ + + X86_OP_INC_E_AX, /* inc ([0x66] 0x40) */ + X86_OP_INC_E_CX, /* inc ([0x66] 0x41) */ + X86_OP_INC_E_DX, /* inc ([0x66] 0x42) */ + X86_OP_INC_E_BX, /* inc ([0x66] 0x43) */ + X86_OP_INC_E_SP, /* inc ([0x66] 0x44) */ + X86_OP_INC_E_BP, /* inc ([0x66] 0x45) */ + X86_OP_INC_E_SI, /* inc ([0x66] 0x46) */ + X86_OP_INC_E_DI, /* inc ([0x66] 0x47) */ + + X86_OP_DEC_E_AX, /* dec ([0x66] 0x48) */ + X86_OP_DEC_E_CX, /* dec ([0x66] 0x49) */ + X86_OP_DEC_E_DX, /* dec ([0x66] 0x4a) */ + X86_OP_DEC_E_BX, /* dec ([0x66] 0x4b) */ + X86_OP_DEC_E_SP, /* dec ([0x66] 0x4c) */ + X86_OP_DEC_E_BP, /* dec ([0x66] 0x4d) */ + X86_OP_DEC_E_SI, /* dec ([0x66] 0x4e) */ + X86_OP_DEC_E_DI, /* dec ([0x66] 0x4f) */ + + X86_OP_PUSH_E_AX, /* push ([0x66] 0x50) */ + X86_OP_PUSH_E_CX, /* push ([0x66] 0x51) */ + X86_OP_PUSH_E_DX, /* push ([0x66] 0x52) */ + X86_OP_PUSH_E_BX, /* push ([0x66] 0x53) */ + X86_OP_PUSH_E_SP, /* push ([0x66] 0x54) */ + X86_OP_PUSH_E_BP, /* push ([0x66] 0x55) */ + X86_OP_PUSH_E_SI, /* push ([0x66] 0x56) */ + X86_OP_PUSH_E_DI, /* push ([0x66] 0x57) */ + + X86_OP_POP_E_AX, /* pop ([0x66] 0x58) */ + X86_OP_POP_E_CX, /* pop ([0x66] 0x59) */ + X86_OP_POP_E_DX, /* pop ([0x66] 0x5a) */ + X86_OP_POP_E_BX, /* pop ([0x66] 0x5b) */ + X86_OP_POP_E_SP, /* pop ([0x66] 0x5c) */ + X86_OP_POP_E_BP, /* pop ([0x66] 0x5d) */ + X86_OP_POP_E_SI, /* pop ([0x66] 0x5e) */ + X86_OP_POP_E_DI, /* pop ([0x66] 0x5f) */ + + X86_OP_PUSH_IMM1632, /* push ([0x66] 0x68) */ + + X86_OP_MOV_REG1632, /* mov ([0x66] 0x89) */ + + X86_OP_ADD8_REG1632, /* add ([0x66] 0x83) */ + X86_OP_OR8_REG1632, /* or ([0x66] 0x83) */ + X86_OP_ADC8_REG1632, /* adc ([0x66] 0x83) */ + X86_OP_SBB8_REG1632, /* sbb ([0x66] 0x83) */ + X86_OP_AND8_REG1632, /* and ([0x66] 0x83) */ + X86_OP_SUB8_REG1632, /* sub ([0x66] 0x83) */ + X86_OP_XOR8_REG1632, /* xor ([0x66] 0x83) */ X86_OP_NOP, /* nop (0x90) */ - X86_OP_MOV_AX, /* mov (0xb8) */ - X86_OP_MOV_CX, /* mov (0xb9) */ - X86_OP_MOV_DX, /* mov (0xba) */ - X86_OP_MOV_BX, /* mov (0xbb) */ - X86_OP_MOV_SP, /* mov (0xbc) */ - X86_OP_MOV_BP, /* mov (0xbd) */ - X86_OP_MOV_SI, /* mov (0xbe) */ - X86_OP_MOV_DI, /* mov (0xbf) */ + X86_OP_MOV_E_AX, /* mov ([0x66] 0xb8) */ + X86_OP_MOV_E_CX, /* mov ([0x66] 0xb9) */ + X86_OP_MOV_E_DX, /* mov ([0x66] 0xba) */ + X86_OP_MOV_E_BX, /* mov ([0x66] 0xbb) */ + X86_OP_MOV_E_SP, /* mov ([0x66] 0xbc) */ + X86_OP_MOV_E_BP, /* mov ([0x66] 0xbd) */ + X86_OP_MOV_E_SI, /* mov ([0x66] 0xbe) */ + X86_OP_MOV_E_DI, /* mov ([0x66] 0xbf) */ X86_OP_RET, /* ret (0xc3) */ X86_OP_LEAVE, /* leave (0xc9) */ @@ -96,53 +108,6 @@ typedef enum _X86Opcodes X86_OP_HLT, /* hlt (0xf4) */ - X86_OP_INC_AX, /* inc (0x66 0x40) */ - X86_OP_INC_CX, /* inc (0x66 0x41) */ - X86_OP_INC_DX, /* inc (0x66 0x42) */ - X86_OP_INC_BX, /* inc (0x66 0x43) */ - X86_OP_INC_SP, /* inc (0x66 0x44) */ - X86_OP_INC_BP, /* inc (0x66 0x45) */ - X86_OP_INC_SI, /* inc (0x66 0x46) */ - X86_OP_INC_DI, /* inc (0x66 0x47) */ - - X86_OP_DEC_AX, /* dec (0x66 0x48) */ - X86_OP_DEC_CX, /* dec (0x66 0x49) */ - X86_OP_DEC_DX, /* dec (0x66 0x4a) */ - X86_OP_DEC_BX, /* dec (0x66 0x4b) */ - X86_OP_DEC_SP, /* dec (0x66 0x4c) */ - X86_OP_DEC_BP, /* dec (0x66 0x4d) */ - X86_OP_DEC_SI, /* dec (0x66 0x4e) */ - X86_OP_DEC_DI, /* dec (0x66 0x4f) */ - - X86_OP_PUSH_AX, /* push (0x66 0x50) */ - X86_OP_PUSH_CX, /* push (0x66 0x51) */ - X86_OP_PUSH_DX, /* push (0x66 0x52) */ - X86_OP_PUSH_BX, /* push (0x66 0x53) */ - X86_OP_PUSH_SP, /* push (0x66 0x54) */ - X86_OP_PUSH_BP, /* push (0x66 0x55) */ - X86_OP_PUSH_SI, /* push (0x66 0x56) */ - X86_OP_PUSH_DI, /* push (0x66 0x57) */ - - X86_OP_POP_AX, /* pop (0x66 0x58) */ - X86_OP_POP_CX, /* pop (0x66 0x59) */ - X86_OP_POP_DX, /* pop (0x66 0x5a) */ - X86_OP_POP_BX, /* pop (0x66 0x5b) */ - X86_OP_POP_SP, /* pop (0x66 0x5c) */ - X86_OP_POP_BP, /* pop (0x66 0x5d) */ - X86_OP_POP_SI, /* pop (0x66 0x5e) */ - X86_OP_POP_DI, /* pop (0x66 0x5f) */ - - X86_OP_PUSH_IMM16, /* push (0x66 0x68) */ - - X86_OP_MOV_EAX, /* mov (0x66 0xb8) */ - X86_OP_MOV_ECX, /* mov (0x66 0xb9) */ - X86_OP_MOV_EDX, /* mov (0x66 0xba) */ - X86_OP_MOV_EBX, /* mov (0x66 0xbb) */ - X86_OP_MOV_ESP, /* mov (0x66 0xbc) */ - X86_OP_MOV_EBP, /* mov (0x66 0xbd) */ - X86_OP_MOV_ESI, /* mov (0x66 0xbe) */ - X86_OP_MOV_EDI, /* mov (0x66 0xbf) */ - X86_OP_COUNT } X86Opcodes; diff --git a/src/arch/x86/op_adc.c b/src/arch/x86/op_adc.c new file mode 100644 index 0000000..8eab0f5 --- /dev/null +++ b/src/arch/x86/op_adc.c @@ -0,0 +1,98 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * op_adc.c - décodage des additions avec retenue + * + * Copyright (C) 2008 Cyrille Bagard + * + * This file is part of OpenIDA. + * + * OpenIDA is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * OpenIDA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Foobar. If not, see . + */ + + +#include + + +#include "../instruction-int.h" +#include "opcodes.h" +#include "operand.h" + + + +/****************************************************************************** +* * +* Paramètres : data = flux de données à analyser. * +* pos = position courante dans ce flux. [OUT] * +* len = taille totale des données à analyser. * +* offset = adresse virtuelle de l'instruction. * +* proc = architecture ciblée par le désassemblage. * +* * +* Description : Décode une instruction de type 'adc' (16 ou 32 bits). * +* * +* Retour : Instruction mise en place ou NULL. * +* * +* Remarques : - * +* * +******************************************************************************/ + +asm_x86_instr *read_instr_adc8_with_reg1632(const uint8_t *data, off_t *pos, off_t len, uint64_t offset, const asm_x86_processor *proc) +{ + asm_x86_instr *result; /* Instruction à retourner */ + AsmOperandSize oprsize; /* Taille des opérandes */ + asm_x86_operand *reg; /* Registre de destination */ + asm_x86_operand *value; /* Valeur empilée */ + + result = (asm_x86_instr *)calloc(1, sizeof(asm_x86_instr)); + + /* Utilisation des registres 32 bits ? */ + if (data[*pos] == 0x66) + { + oprsize = switch_x86_operand_size(proc); + (*pos)++; + } + else oprsize = get_x86_current_operand_size(proc); + + ASM_INSTRUCTION(result)->opcode = data[(*pos)++]; + + /* TODO ! */ + if ((data[*pos] & 0xc0) != 0xc0) + return NULL; + + reg = x86_create_reg1632_operand_from_modrm(data[*pos], oprsize == AOS_32_BITS, false); + if (reg == NULL) + { + free(result); + return NULL; + } + + (*pos)++; + + value = create_new_x86_operand(); + if (!fill_imm_operand(ASM_OPERAND(value), AOS_8_BITS, data, pos, len)) + { + free(reg); + free(value); + free(result); + return NULL; + } + + ASM_INSTRUCTION(result)->operands = (asm_operand **)calloc(2, sizeof(asm_operand *)); + ASM_INSTRUCTION(result)->operands_count = 2; + + ASM_INSTRUCTION(result)->operands[0] = ASM_OPERAND(reg); + ASM_INSTRUCTION(result)->operands[1] = ASM_OPERAND(value); + + return result; + +} diff --git a/src/arch/x86/op_add.c b/src/arch/x86/op_add.c new file mode 100644 index 0000000..99a30fc --- /dev/null +++ b/src/arch/x86/op_add.c @@ -0,0 +1,98 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * op_add.c - décodage des additions + * + * Copyright (C) 2008 Cyrille Bagard + * + * This file is part of OpenIDA. + * + * OpenIDA is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * OpenIDA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Foobar. If not, see . + */ + + +#include + + +#include "../instruction-int.h" +#include "opcodes.h" +#include "operand.h" + + + +/****************************************************************************** +* * +* Paramètres : data = flux de données à analyser. * +* pos = position courante dans ce flux. [OUT] * +* len = taille totale des données à analyser. * +* offset = adresse virtuelle de l'instruction. * +* proc = architecture ciblée par le désassemblage. * +* * +* Description : Décode une instruction de type 'add' (16 ou 32 bits). * +* * +* Retour : Instruction mise en place ou NULL. * +* * +* Remarques : - * +* * +******************************************************************************/ + +asm_x86_instr *read_instr_add8_with_reg1632(const uint8_t *data, off_t *pos, off_t len, uint64_t offset, const asm_x86_processor *proc) +{ + asm_x86_instr *result; /* Instruction à retourner */ + AsmOperandSize oprsize; /* Taille des opérandes */ + asm_x86_operand *reg; /* Registre de destination */ + asm_x86_operand *value; /* Valeur empilée */ + + result = (asm_x86_instr *)calloc(1, sizeof(asm_x86_instr)); + + /* Utilisation des registres 32 bits ? */ + if (data[*pos] == 0x66) + { + oprsize = switch_x86_operand_size(proc); + (*pos)++; + } + else oprsize = get_x86_current_operand_size(proc); + + ASM_INSTRUCTION(result)->opcode = data[(*pos)++]; + + /* TODO ! */ + if ((data[*pos] & 0xc0) != 0xc0) + return NULL; + + reg = x86_create_reg1632_operand_from_modrm(data[*pos], oprsize == AOS_32_BITS, false); + if (reg == NULL) + { + free(result); + return NULL; + } + + (*pos)++; + + value = create_new_x86_operand(); + if (!fill_imm_operand(ASM_OPERAND(value), AOS_8_BITS, data, pos, len)) + { + free(reg); + free(value); + free(result); + return NULL; + } + + ASM_INSTRUCTION(result)->operands = (asm_operand **)calloc(2, sizeof(asm_operand *)); + ASM_INSTRUCTION(result)->operands_count = 2; + + ASM_INSTRUCTION(result)->operands[0] = ASM_OPERAND(reg); + ASM_INSTRUCTION(result)->operands[1] = ASM_OPERAND(value); + + return result; + +} diff --git a/src/arch/x86/op_and.c b/src/arch/x86/op_and.c new file mode 100644 index 0000000..e220b4c --- /dev/null +++ b/src/arch/x86/op_and.c @@ -0,0 +1,98 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * op_and.c - décodage des ET logiques + * + * Copyright (C) 2008 Cyrille Bagard + * + * This file is part of OpenIDA. + * + * OpenIDA is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * OpenIDA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Foobar. If not, see . + */ + + +#include + + +#include "../instruction-int.h" +#include "opcodes.h" +#include "operand.h" + + + +/****************************************************************************** +* * +* Paramètres : data = flux de données à analyser. * +* pos = position courante dans ce flux. [OUT] * +* len = taille totale des données à analyser. * +* offset = adresse virtuelle de l'instruction. * +* proc = architecture ciblée par le désassemblage. * +* * +* Description : Décode une instruction de type 'and' (16 ou 32 bits). * +* * +* Retour : Instruction mise en place ou NULL. * +* * +* Remarques : - * +* * +******************************************************************************/ + +asm_x86_instr *read_instr_and8_with_reg1632(const uint8_t *data, off_t *pos, off_t len, uint64_t offset, const asm_x86_processor *proc) +{ + asm_x86_instr *result; /* Instruction à retourner */ + AsmOperandSize oprsize; /* Taille des opérandes */ + asm_x86_operand *reg; /* Registre de destination */ + asm_x86_operand *value; /* Valeur empilée */ + + result = (asm_x86_instr *)calloc(1, sizeof(asm_x86_instr)); + + /* Utilisation des registres 32 bits ? */ + if (data[*pos] == 0x66) + { + oprsize = switch_x86_operand_size(proc); + (*pos)++; + } + else oprsize = get_x86_current_operand_size(proc); + + ASM_INSTRUCTION(result)->opcode = data[(*pos)++]; + + /* TODO ! */ + if ((data[*pos] & 0xc0) != 0xc0) + return NULL; + + reg = x86_create_reg1632_operand_from_modrm(data[*pos], oprsize == AOS_32_BITS, false); + if (reg == NULL) + { + free(result); + return NULL; + } + + (*pos)++; + + value = create_new_x86_operand(); + if (!fill_imm_operand(ASM_OPERAND(value), AOS_8_BITS, data, pos, len)) + { + free(reg); + free(value); + free(result); + return NULL; + } + + ASM_INSTRUCTION(result)->operands = (asm_operand **)calloc(2, sizeof(asm_operand *)); + ASM_INSTRUCTION(result)->operands_count = 2; + + ASM_INSTRUCTION(result)->operands[0] = ASM_OPERAND(reg); + ASM_INSTRUCTION(result)->operands[1] = ASM_OPERAND(value); + + return result; + +} diff --git a/src/arch/x86/op_mov.c b/src/arch/x86/op_mov.c index e14a2f7..f0a5fce 100644 --- a/src/arch/x86/op_mov.c +++ b/src/arch/x86/op_mov.c @@ -46,6 +46,73 @@ * * ******************************************************************************/ +asm_x86_instr *read_instr_mov_with_reg1632(const uint8_t *data, off_t *pos, off_t len, uint64_t offset, const asm_x86_processor *proc) +{ + asm_x86_instr *result; /* Instruction à retourner */ + AsmOperandSize oprsize; /* Taille des opérandes */ + asm_x86_operand *reg2; /* Registre de source */ + asm_x86_operand *reg1; /* Registre de destination */ + + result = (asm_x86_instr *)calloc(1, sizeof(asm_x86_instr)); + + /* Utilisation des registres 32 bits ? */ + if (data[*pos] == 0x66) + { + oprsize = switch_x86_operand_size(proc); + (*pos)++; + } + else oprsize = get_x86_current_operand_size(proc); + + ASM_INSTRUCTION(result)->opcode = data[(*pos)++]; + + /* TODO ! */ + if ((data[*pos] & 0xc0) != 0xc0) + return NULL; + + reg1 = x86_create_reg1632_operand_from_modrm(data[*pos], oprsize == AOS_32_BITS, true); + if (reg1 == NULL) + { + free(result); + return NULL; + } + + reg2 = x86_create_reg1632_operand_from_modrm(data[*pos], oprsize == AOS_32_BITS, false); + if (reg2 == NULL) + { + free(result); + free(reg1); + return NULL; + } + + (*pos)++; + + ASM_INSTRUCTION(result)->operands = (asm_operand **)calloc(2, sizeof(asm_operand *)); + ASM_INSTRUCTION(result)->operands_count = 2; + + ASM_INSTRUCTION(result)->operands[0] = ASM_OPERAND(reg1); + ASM_INSTRUCTION(result)->operands[1] = ASM_OPERAND(reg2); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : data = flux de données à analyser. * +* pos = position courante dans ce flux. [OUT] * +* len = taille totale des données à analyser. * +* offset = adresse virtuelle de l'instruction. * +* proc = architecture ciblée par le désassemblage. * +* * +* Description : Décode une instruction de type 'mov' (16 ou 32 bits). * +* * +* Retour : Instruction mise en place ou NULL. * +* * +* Remarques : - * +* * +******************************************************************************/ + asm_x86_instr *read_instr_mov_to_1632(const uint8_t *data, off_t *pos, off_t len, uint64_t offset, const asm_x86_processor *proc) { asm_x86_instr *result; /* Instruction à retourner */ diff --git a/src/arch/x86/op_or.c b/src/arch/x86/op_or.c new file mode 100644 index 0000000..a092448 --- /dev/null +++ b/src/arch/x86/op_or.c @@ -0,0 +1,98 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * op_or.c - décodage des OU logiques + * + * Copyright (C) 2008 Cyrille Bagard + * + * This file is part of OpenIDA. + * + * OpenIDA is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * OpenIDA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Foobar. If not, see . + */ + + +#include + + +#include "../instruction-int.h" +#include "opcodes.h" +#include "operand.h" + + + +/****************************************************************************** +* * +* Paramètres : data = flux de données à analyser. * +* pos = position courante dans ce flux. [OUT] * +* len = taille totale des données à analyser. * +* offset = adresse virtuelle de l'instruction. * +* proc = architecture ciblée par le désassemblage. * +* * +* Description : Décode une instruction de type 'or' (16 ou 32 bits). * +* * +* Retour : Instruction mise en place ou NULL. * +* * +* Remarques : - * +* * +******************************************************************************/ + +asm_x86_instr *read_instr_or8_with_reg1632(const uint8_t *data, off_t *pos, off_t len, uint64_t offset, const asm_x86_processor *proc) +{ + asm_x86_instr *result; /* Instruction à retourner */ + AsmOperandSize oprsize; /* Taille des opérandes */ + asm_x86_operand *reg; /* Registre de destination */ + asm_x86_operand *value; /* Valeur empilée */ + + result = (asm_x86_instr *)calloc(1, sizeof(asm_x86_instr)); + + /* Utilisation des registres 32 bits ? */ + if (data[*pos] == 0x66) + { + oprsize = switch_x86_operand_size(proc); + (*pos)++; + } + else oprsize = get_x86_current_operand_size(proc); + + ASM_INSTRUCTION(result)->opcode = data[(*pos)++]; + + /* TODO ! */ + if ((data[*pos] & 0xc0) != 0xc0) + return NULL; + + reg = x86_create_reg1632_operand_from_modrm(data[*pos], oprsize == AOS_32_BITS, false); + if (reg == NULL) + { + free(result); + return NULL; + } + + (*pos)++; + + value = create_new_x86_operand(); + if (!fill_imm_operand(ASM_OPERAND(value), AOS_8_BITS, data, pos, len)) + { + free(reg); + free(value); + free(result); + return NULL; + } + + ASM_INSTRUCTION(result)->operands = (asm_operand **)calloc(2, sizeof(asm_operand *)); + ASM_INSTRUCTION(result)->operands_count = 2; + + ASM_INSTRUCTION(result)->operands[0] = ASM_OPERAND(reg); + ASM_INSTRUCTION(result)->operands[1] = ASM_OPERAND(value); + + return result; + +} diff --git a/src/arch/x86/op_sbb.c b/src/arch/x86/op_sbb.c new file mode 100644 index 0000000..9286448 --- /dev/null +++ b/src/arch/x86/op_sbb.c @@ -0,0 +1,98 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * op_sbb.c - décodage des soustractions avec retenue + * + * Copyright (C) 2008 Cyrille Bagard + * + * This file is part of OpenIDA. + * + * OpenIDA is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * OpenIDA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Foobar. If not, see . + */ + + +#include + + +#include "../instruction-int.h" +#include "opcodes.h" +#include "operand.h" + + + +/****************************************************************************** +* * +* Paramètres : data = flux de données à analyser. * +* pos = position courante dans ce flux. [OUT] * +* len = taille totale des données à analyser. * +* offset = adresse virtuelle de l'instruction. * +* proc = architecture ciblée par le désassemblage. * +* * +* Description : Décode une instruction de type 'sbb' (16 ou 32 bits). * +* * +* Retour : Instruction mise en place ou NULL. * +* * +* Remarques : - * +* * +******************************************************************************/ + +asm_x86_instr *read_instr_sbb8_with_reg1632(const uint8_t *data, off_t *pos, off_t len, uint64_t offset, const asm_x86_processor *proc) +{ + asm_x86_instr *result; /* Instruction à retourner */ + AsmOperandSize oprsize; /* Taille des opérandes */ + asm_x86_operand *reg; /* Registre de destination */ + asm_x86_operand *value; /* Valeur empilée */ + + result = (asm_x86_instr *)calloc(1, sizeof(asm_x86_instr)); + + /* Utilisation des registres 32 bits ? */ + if (data[*pos] == 0x66) + { + oprsize = switch_x86_operand_size(proc); + (*pos)++; + } + else oprsize = get_x86_current_operand_size(proc); + + ASM_INSTRUCTION(result)->opcode = data[(*pos)++]; + + /* TODO ! */ + if ((data[*pos] & 0xc0) != 0xc0) + return NULL; + + reg = x86_create_reg1632_operand_from_modrm(data[*pos], oprsize == AOS_32_BITS, false); + if (reg == NULL) + { + free(result); + return NULL; + } + + (*pos)++; + + value = create_new_x86_operand(); + if (!fill_imm_operand(ASM_OPERAND(value), AOS_8_BITS, data, pos, len)) + { + free(reg); + free(value); + free(result); + return NULL; + } + + ASM_INSTRUCTION(result)->operands = (asm_operand **)calloc(2, sizeof(asm_operand *)); + ASM_INSTRUCTION(result)->operands_count = 2; + + ASM_INSTRUCTION(result)->operands[0] = ASM_OPERAND(reg); + ASM_INSTRUCTION(result)->operands[1] = ASM_OPERAND(value); + + return result; + +} diff --git a/src/arch/x86/op_sub.c b/src/arch/x86/op_sub.c new file mode 100644 index 0000000..a323aa8 --- /dev/null +++ b/src/arch/x86/op_sub.c @@ -0,0 +1,98 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * op_sub.c - décodage des soustractions + * + * Copyright (C) 2008 Cyrille Bagard + * + * This file is part of OpenIDA. + * + * OpenIDA is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * OpenIDA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Foobar. If not, see . + */ + + +#include + + +#include "../instruction-int.h" +#include "opcodes.h" +#include "operand.h" + + + +/****************************************************************************** +* * +* Paramètres : data = flux de données à analyser. * +* pos = position courante dans ce flux. [OUT] * +* len = taille totale des données à analyser. * +* offset = adresse virtuelle de l'instruction. * +* proc = architecture ciblée par le désassemblage. * +* * +* Description : Décode une instruction de type 'sub' (16 ou 32 bits). * +* * +* Retour : Instruction mise en place ou NULL. * +* * +* Remarques : - * +* * +******************************************************************************/ + +asm_x86_instr *read_instr_sub8_with_reg1632(const uint8_t *data, off_t *pos, off_t len, uint64_t offset, const asm_x86_processor *proc) +{ + asm_x86_instr *result; /* Instruction à retourner */ + AsmOperandSize oprsize; /* Taille des opérandes */ + asm_x86_operand *reg; /* Registre de destination */ + asm_x86_operand *value; /* Valeur empilée */ + + result = (asm_x86_instr *)calloc(1, sizeof(asm_x86_instr)); + + /* Utilisation des registres 32 bits ? */ + if (data[*pos] == 0x66) + { + oprsize = switch_x86_operand_size(proc); + (*pos)++; + } + else oprsize = get_x86_current_operand_size(proc); + + ASM_INSTRUCTION(result)->opcode = data[(*pos)++]; + + /* TODO ! */ + if ((data[*pos] & 0xc0) != 0xc0) + return NULL; + + reg = x86_create_reg1632_operand_from_modrm(data[*pos], oprsize == AOS_32_BITS, false); + if (reg == NULL) + { + free(result); + return NULL; + } + + (*pos)++; + + value = create_new_x86_operand(); + if (!fill_imm_operand(ASM_OPERAND(value), AOS_8_BITS, data, pos, len)) + { + free(reg); + free(value); + free(result); + return NULL; + } + + ASM_INSTRUCTION(result)->operands = (asm_operand **)calloc(2, sizeof(asm_operand *)); + ASM_INSTRUCTION(result)->operands_count = 2; + + ASM_INSTRUCTION(result)->operands[0] = ASM_OPERAND(reg); + ASM_INSTRUCTION(result)->operands[1] = ASM_OPERAND(value); + + return result; + +} diff --git a/src/arch/x86/op_xor.c b/src/arch/x86/op_xor.c new file mode 100644 index 0000000..ae97022 --- /dev/null +++ b/src/arch/x86/op_xor.c @@ -0,0 +1,165 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * op_xor.c - décodage des OU exclusifs + * + * Copyright (C) 2008 Cyrille Bagard + * + * This file is part of OpenIDA. + * + * OpenIDA is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * OpenIDA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Foobar. If not, see . + */ + + +#include + + +#include "../instruction-int.h" +#include "opcodes.h" +#include "operand.h" + + + +/****************************************************************************** +* * +* Paramètres : data = flux de données à analyser. * +* pos = position courante dans ce flux. [OUT] * +* len = taille totale des données à analyser. * +* offset = adresse virtuelle de l'instruction. * +* proc = architecture ciblée par le désassemblage. * +* * +* Description : Décode une instruction de type 'xor' (16 ou 32 bits). * +* * +* Retour : Instruction mise en place ou NULL. * +* * +* Remarques : - * +* * +******************************************************************************/ + +asm_x86_instr *read_instr_xor_with_reg1632(const uint8_t *data, off_t *pos, off_t len, uint64_t offset, const asm_x86_processor *proc) +{ + asm_x86_instr *result; /* Instruction à retourner */ + AsmOperandSize oprsize; /* Taille des opérandes */ + asm_x86_operand *reg2; /* Registre de source */ + asm_x86_operand *reg1; /* Registre de destination */ + + result = (asm_x86_instr *)calloc(1, sizeof(asm_x86_instr)); + + /* Utilisation des registres 32 bits ? */ + if (data[*pos] == 0x66) + { + oprsize = switch_x86_operand_size(proc); + (*pos)++; + } + else oprsize = get_x86_current_operand_size(proc); + + ASM_INSTRUCTION(result)->opcode = data[(*pos)++]; + + /* TODO ! */ + if ((data[*pos] & 0xc0) != 0xc0) + return NULL; + + reg1 = x86_create_reg1632_operand_from_modrm(data[*pos], oprsize == AOS_32_BITS, true); + if (reg1 == NULL) + { + free(result); + return NULL; + } + + reg2 = x86_create_reg1632_operand_from_modrm(data[*pos], oprsize == AOS_32_BITS, false); + if (reg2 == NULL) + { + free(result); + free(reg1); + return NULL; + } + + (*pos)++; + + ASM_INSTRUCTION(result)->operands = (asm_operand **)calloc(2, sizeof(asm_operand *)); + ASM_INSTRUCTION(result)->operands_count = 2; + + ASM_INSTRUCTION(result)->operands[0] = ASM_OPERAND(reg1); + ASM_INSTRUCTION(result)->operands[1] = ASM_OPERAND(reg2); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : data = flux de données à analyser. * +* pos = position courante dans ce flux. [OUT] * +* len = taille totale des données à analyser. * +* offset = adresse virtuelle de l'instruction. * +* proc = architecture ciblée par le désassemblage. * +* * +* Description : Décode une instruction de type 'xor' (16 ou 32 bits). * +* * +* Retour : Instruction mise en place ou NULL. * +* * +* Remarques : - * +* * +******************************************************************************/ + +asm_x86_instr *read_instr_xor8_with_reg1632(const uint8_t *data, off_t *pos, off_t len, uint64_t offset, const asm_x86_processor *proc) +{ + asm_x86_instr *result; /* Instruction à retourner */ + AsmOperandSize oprsize; /* Taille des opérandes */ + asm_x86_operand *reg; /* Registre de destination */ + asm_x86_operand *value; /* Valeur empilée */ + + result = (asm_x86_instr *)calloc(1, sizeof(asm_x86_instr)); + + /* Utilisation des registres 32 bits ? */ + if (data[*pos] == 0x66) + { + oprsize = switch_x86_operand_size(proc); + (*pos)++; + } + else oprsize = get_x86_current_operand_size(proc); + + ASM_INSTRUCTION(result)->opcode = data[(*pos)++]; + + /* TODO ! */ + if ((data[*pos] & 0xc0) != 0xc0) + return NULL; + + reg = x86_create_reg1632_operand_from_modrm(data[*pos], oprsize == AOS_32_BITS, false); + if (reg == NULL) + { + free(result); + return NULL; + } + + (*pos)++; + + value = create_new_x86_operand(); + if (!fill_imm_operand(ASM_OPERAND(value), AOS_8_BITS, data, pos, len)) + { + free(reg); + free(value); + free(result); + return NULL; + } + + ASM_INSTRUCTION(result)->operands = (asm_operand **)calloc(2, sizeof(asm_operand *)); + ASM_INSTRUCTION(result)->operands_count = 2; + + ASM_INSTRUCTION(result)->operands[0] = ASM_OPERAND(reg); + ASM_INSTRUCTION(result)->operands[1] = ASM_OPERAND(value); + + return result; + +} diff --git a/src/arch/x86/opcodes.h b/src/arch/x86/opcodes.h index a75de7e..6cf6d3c 100644 --- a/src/arch/x86/opcodes.h +++ b/src/arch/x86/opcodes.h @@ -34,6 +34,15 @@ +/* Décode une instruction de type 'adc' (16 ou 32 bits). */ +asm_x86_instr *read_instr_adc8_with_reg1632(const uint8_t *, off_t *, off_t, uint64_t, const asm_x86_processor *); + +/* Décode une instruction de type 'add' (16 ou 32 bits). */ +asm_x86_instr *read_instr_add8_with_reg1632(const uint8_t *, off_t *, off_t, uint64_t, const asm_x86_processor *); + +/* Décode une instruction de type 'and' (16 ou 32 bits). */ +asm_x86_instr *read_instr_and8_with_reg1632(const uint8_t *, off_t *, off_t, uint64_t, const asm_x86_processor *); + /* Décode une instruction de type 'call'. */ asm_x86_instr *read_instr_call(const uint8_t *, off_t *, off_t, uint64_t, const asm_x86_processor *); @@ -55,9 +64,15 @@ asm_x86_instr *read_instr_leave(const uint8_t *, off_t *, off_t, uint64_t, const /* Décode une instruction de type 'mov' (16 ou 32 bits). */ asm_x86_instr *read_instr_mov_to_1632(const uint8_t *, off_t *, off_t, uint64_t, const asm_x86_processor *); +/* Décode une instruction de type 'mov' (16 ou 32 bits). */ +asm_x86_instr *read_instr_mov_with_reg1632(const uint8_t *, off_t *, off_t, uint64_t, const asm_x86_processor *); + /* Décode une instruction de type 'nop'. */ asm_x86_instr *read_instr_nop(const uint8_t *, off_t *, off_t, uint64_t, const asm_x86_processor *); +/* Décode une instruction de type 'or' (16 ou 32 bits). */ +asm_x86_instr *read_instr_or8_with_reg1632(const uint8_t *, off_t *, off_t, uint64_t, const asm_x86_processor *); + /* Décode une instruction de type 'pop' (16 ou 32 bits). */ asm_x86_instr *read_instr_pop_reg1632(const uint8_t *, off_t *, off_t, uint64_t, const asm_x86_processor *); @@ -70,6 +85,18 @@ asm_x86_instr *read_instr_push_reg1632(const uint8_t *, off_t *, off_t, uint64_t /* Décode une instruction de type 'ret'. */ asm_x86_instr *read_instr_ret(const uint8_t *, off_t *, off_t, uint64_t, const asm_x86_processor *); +/* Décode une instruction de type 'sbb'. */ +asm_x86_instr *read_instr_sbb8_with_reg1632(const uint8_t *, off_t *, off_t, uint64_t, const asm_x86_processor *); + +/* Décode une instruction de type 'sub'. */ +asm_x86_instr *read_instr_sub8_with_reg1632(const uint8_t *, off_t *, off_t, uint64_t, const asm_x86_processor *); + +/* Décode une instruction de type 'xor' (16 ou 32 bits). */ +asm_x86_instr *read_instr_xor_with_reg1632(const uint8_t *, off_t *, off_t, uint64_t, const asm_x86_processor *); + +/* Décode une instruction de type 'xor' (16 ou 32 bits). */ +asm_x86_instr *read_instr_xor8_with_reg1632(const uint8_t *, off_t *, off_t, uint64_t, const asm_x86_processor *); + #endif /* _ARCH_X86_OPCODES_H */ diff --git a/src/arch/x86/operand.c b/src/arch/x86/operand.c index 4b8eef8..3eaefd2 100644 --- a/src/arch/x86/operand.c +++ b/src/arch/x86/operand.c @@ -183,6 +183,65 @@ asm_x86_operand *x86_create_reg1632_operand(uint8_t data, bool is_reg32, uint8_t /****************************************************************************** * * +* Paramètres : data = donnée à analyser. * +* is_reg32 = indique si le registre est un registre 32 bits. * +* first = indique la partie du ModR/M à traiter. * +* * +* Description : Crée une opérande renvoyant vers un registre 16 ou 32 bits. * +* * +* Retour : Opérande mise en place ou NULL. * +* * +* Remarques : - * +* * +******************************************************************************/ + +asm_x86_operand *x86_create_reg1632_operand_from_modrm(uint8_t data, bool is_reg32, bool first) +{ + asm_x86_operand *result; /* Registre à retourner */ + uint8_t reg; /* Transcription du registre */ + X8616bRegister reg16; /* Registre 16 bits */ + X8632bRegister reg32; /* Registre 32 bits */ + + if (first) reg = data & 0x07; + else reg = (data & 0x38) >> 3; + + if (is_reg32) + switch (reg) + { + case 0 ... 7: + reg32 = (X8632bRegister)reg; + break; + default: + return NULL; + break; + } + + else + switch (reg) + { + case 0 ... 7: + reg16 = (X8616bRegister)reg; + break; + default: + return NULL; + break; + } + + result = create_new_x86_operand(); + + ASM_OPERAND(result)->type = AOT_REG; + ASM_OPERAND(result)->size = (is_reg32 ? AOS_32_BITS : AOS_16_BITS); + + if (is_reg32) result->x86_value.reg32 = reg32; + else result->x86_value.reg16 = reg16; + + return result; + +} + + +/****************************************************************************** +* * * Paramètres : operand = instruction à traiter. * * buffer = tampon de sortie mis à disposition. [OUT] * * len = taille de ce tampon. * diff --git a/src/arch/x86/operand.h b/src/arch/x86/operand.h index ebbdd50..e6eb3cc 100644 --- a/src/arch/x86/operand.h +++ b/src/arch/x86/operand.h @@ -45,6 +45,9 @@ asm_x86_operand *create_new_x86_operand(void); /* Crée une opérande renvoyant vers un registre 16 ou 32 bits. */ asm_x86_operand *x86_create_reg1632_operand(uint8_t, bool, uint8_t); +/* Crée une opérande renvoyant vers un registre 16 ou 32 bits. */ +asm_x86_operand *x86_create_reg1632_operand_from_modrm(uint8_t, bool, bool); + /*Traduit une opérande de registre en texte. */ void x86_print_reg_operand(const asm_x86_operand *, char *, size_t, AsmSyntax); diff --git a/src/arch/x86/processor.c b/src/arch/x86/processor.c index 487e4a0..0014652 100644 --- a/src/arch/x86/processor.c +++ b/src/arch/x86/processor.c @@ -43,19 +43,44 @@ typedef struct _x86_opcode { uint8_t prefix; /* préfixe eventuel */ uint8_t opcode; /* Opcode seul */ + uint8_t op_ext; /* Extension de l'opcode */ + + bool opt_prefix; /* Préfixe optionnel ? */ + bool has_op_ext; /* Ext. à prendre en compte ? */ + const char *name; /* Désignation humaine */ read_instr read; /* Décodage de l'instruction */ } x86_opcode; -#define register_opcode(target, pre, bin, n, func) \ -do {\ -target.prefix = pre; \ -target.opcode = bin; \ -target.name = n; \ -target.read = func; \ -} while (0) +#define EXT_OPCODE_MASK 0x38 + + +#define register_opcode(target, _prefix, _opcode, _name, _read) \ + do { \ + target.prefix = _prefix; \ + target.opcode = _opcode; \ + target.opt_prefix = true; \ + target.has_op_ext = false; \ + target.name = _name; \ + target.read = _read; \ + } while (0) + +#define register_opcode_with_ext(target, _prefix, _opcode, _ext, _name, _read) \ + do { \ + target.prefix = _prefix; \ + target.opcode = _opcode; \ + target.op_ext = _ext << 3; \ + target.opt_prefix = true; \ + target.has_op_ext = true; \ + target.name = _name; \ + target.read = _read; \ + } while (0) + + + + /* Définition générique d'une architecture */ @@ -169,59 +194,67 @@ AsmOperandSize switch_x86_operand_size(const asm_x86_processor *proc) void x86_register_instructions(asm_x86_processor *proc) { - /* TODO : voir pour une inversion avec le mode 16 bits ! */ - - register_opcode(proc->opcodes[X86_OP_INC_EAX], 0x00, 0x40, "inc", read_instr_inc_1632); - register_opcode(proc->opcodes[X86_OP_INC_ECX], 0x00, 0x41, "inc", read_instr_inc_1632); - register_opcode(proc->opcodes[X86_OP_INC_EDX], 0x00, 0x42, "inc", read_instr_inc_1632); - register_opcode(proc->opcodes[X86_OP_INC_EBX], 0x00, 0x43, "inc", read_instr_inc_1632); - register_opcode(proc->opcodes[X86_OP_INC_ESP], 0x00, 0x44, "inc", read_instr_inc_1632); - register_opcode(proc->opcodes[X86_OP_INC_EBP], 0x00, 0x45, "inc", read_instr_inc_1632); - register_opcode(proc->opcodes[X86_OP_INC_ESI], 0x00, 0x46, "inc", read_instr_inc_1632); - register_opcode(proc->opcodes[X86_OP_INC_EDI], 0x00, 0x47, "inc", read_instr_inc_1632); - - register_opcode(proc->opcodes[X86_OP_DEC_EAX], 0x00, 0x48, "dec", read_instr_dec_1632); - register_opcode(proc->opcodes[X86_OP_DEC_ECX], 0x00, 0x49, "dec", read_instr_dec_1632); - register_opcode(proc->opcodes[X86_OP_DEC_EDX], 0x00, 0x4a, "dec", read_instr_dec_1632); - register_opcode(proc->opcodes[X86_OP_DEC_EBX], 0x00, 0x4b, "dec", read_instr_dec_1632); - register_opcode(proc->opcodes[X86_OP_DEC_ESP], 0x00, 0x4c, "dec", read_instr_dec_1632); - register_opcode(proc->opcodes[X86_OP_DEC_EBP], 0x00, 0x4d, "dec", read_instr_dec_1632); - register_opcode(proc->opcodes[X86_OP_DEC_ESI], 0x00, 0x4e, "dec", read_instr_dec_1632); - register_opcode(proc->opcodes[X86_OP_DEC_EDI], 0x00, 0x4f, "dec", read_instr_dec_1632); - - register_opcode(proc->opcodes[X86_OP_PUSH_EAX], 0x00, 0x50, "push", read_instr_push_reg1632); - register_opcode(proc->opcodes[X86_OP_PUSH_ECX], 0x00, 0x51, "push", read_instr_push_reg1632); - register_opcode(proc->opcodes[X86_OP_PUSH_EDX], 0x00, 0x52, "push", read_instr_push_reg1632); - register_opcode(proc->opcodes[X86_OP_PUSH_EBX], 0x00, 0x53, "push", read_instr_push_reg1632); - register_opcode(proc->opcodes[X86_OP_PUSH_ESP], 0x00, 0x54, "push", read_instr_push_reg1632); - register_opcode(proc->opcodes[X86_OP_PUSH_EBP], 0x00, 0x55, "push", read_instr_push_reg1632); - register_opcode(proc->opcodes[X86_OP_PUSH_ESI], 0x00, 0x56, "push", read_instr_push_reg1632); - register_opcode(proc->opcodes[X86_OP_PUSH_EDI], 0x00, 0x57, "push", read_instr_push_reg1632); - - register_opcode(proc->opcodes[X86_OP_POP_EAX], 0x00, 0x58, "pop", read_instr_pop_reg1632); - register_opcode(proc->opcodes[X86_OP_POP_ECX], 0x00, 0x59, "pop", read_instr_pop_reg1632); - register_opcode(proc->opcodes[X86_OP_POP_EDX], 0x00, 0x5a, "pop", read_instr_pop_reg1632); - register_opcode(proc->opcodes[X86_OP_POP_EBX], 0x00, 0x5b, "pop", read_instr_pop_reg1632); - register_opcode(proc->opcodes[X86_OP_POP_ESP], 0x00, 0x5c, "pop", read_instr_pop_reg1632); - register_opcode(proc->opcodes[X86_OP_POP_EBP], 0x00, 0x5d, "pop", read_instr_pop_reg1632); - register_opcode(proc->opcodes[X86_OP_POP_ESI], 0x00, 0x5e, "pop", read_instr_pop_reg1632); - register_opcode(proc->opcodes[X86_OP_POP_EDI], 0x00, 0x5f, "pop", read_instr_pop_reg1632); - - register_opcode(proc->opcodes[X86_OP_PUSH_IMM32], 0x00, 0x68, "push", read_instr_push_imm1632); - + register_opcode(proc->opcodes[X86_OP_XOR_REG1632], 0x00/*0x66*/, 0x31, "xor", read_instr_xor_with_reg1632); + + register_opcode(proc->opcodes[X86_OP_INC_E_AX], 0x66, 0x40, "inc", read_instr_inc_1632); + register_opcode(proc->opcodes[X86_OP_INC_E_CX], 0x66, 0x41, "inc", read_instr_inc_1632); + register_opcode(proc->opcodes[X86_OP_INC_E_DX], 0x66, 0x42, "inc", read_instr_inc_1632); + register_opcode(proc->opcodes[X86_OP_INC_E_BX], 0x66, 0x43, "inc", read_instr_inc_1632); + register_opcode(proc->opcodes[X86_OP_INC_E_SP], 0x66, 0x44, "inc", read_instr_inc_1632); + register_opcode(proc->opcodes[X86_OP_INC_E_BP], 0x66, 0x45, "inc", read_instr_inc_1632); + register_opcode(proc->opcodes[X86_OP_INC_E_SI], 0x66, 0x46, "inc", read_instr_inc_1632); + register_opcode(proc->opcodes[X86_OP_INC_E_DI], 0x66, 0x47, "inc", read_instr_inc_1632); + + register_opcode(proc->opcodes[X86_OP_DEC_E_AX], 0x66, 0x48, "dec", read_instr_dec_1632); + register_opcode(proc->opcodes[X86_OP_DEC_E_CX], 0x66, 0x49, "dec", read_instr_dec_1632); + register_opcode(proc->opcodes[X86_OP_DEC_E_DX], 0x66, 0x4a, "dec", read_instr_dec_1632); + register_opcode(proc->opcodes[X86_OP_DEC_E_BX], 0x66, 0x4b, "dec", read_instr_dec_1632); + register_opcode(proc->opcodes[X86_OP_DEC_E_SP], 0x66, 0x4c, "dec", read_instr_dec_1632); + register_opcode(proc->opcodes[X86_OP_DEC_E_BP], 0x66, 0x4d, "dec", read_instr_dec_1632); + register_opcode(proc->opcodes[X86_OP_DEC_E_SI], 0x66, 0x4e, "dec", read_instr_dec_1632); + register_opcode(proc->opcodes[X86_OP_DEC_E_DI], 0x66, 0x4f, "dec", read_instr_dec_1632); + + register_opcode(proc->opcodes[X86_OP_PUSH_E_AX], 0x66, 0x50, "push", read_instr_push_reg1632); + register_opcode(proc->opcodes[X86_OP_PUSH_E_CX], 0x66, 0x51, "push", read_instr_push_reg1632); + register_opcode(proc->opcodes[X86_OP_PUSH_E_DX], 0x66, 0x52, "push", read_instr_push_reg1632); + register_opcode(proc->opcodes[X86_OP_PUSH_E_BX], 0x66, 0x53, "push", read_instr_push_reg1632); + register_opcode(proc->opcodes[X86_OP_PUSH_E_SP], 0x66, 0x54, "push", read_instr_push_reg1632); + register_opcode(proc->opcodes[X86_OP_PUSH_E_BP], 0x66, 0x55, "push", read_instr_push_reg1632); + register_opcode(proc->opcodes[X86_OP_PUSH_E_SI], 0x66, 0x56, "push", read_instr_push_reg1632); + register_opcode(proc->opcodes[X86_OP_PUSH_E_DI], 0x66, 0x57, "push", read_instr_push_reg1632); + + register_opcode(proc->opcodes[X86_OP_POP_E_AX], 0x66, 0x58, "pop", read_instr_pop_reg1632); + register_opcode(proc->opcodes[X86_OP_POP_E_CX], 0x66, 0x59, "pop", read_instr_pop_reg1632); + register_opcode(proc->opcodes[X86_OP_POP_E_DX], 0x66, 0x5a, "pop", read_instr_pop_reg1632); + register_opcode(proc->opcodes[X86_OP_POP_E_BX], 0x66, 0x5b, "pop", read_instr_pop_reg1632); + register_opcode(proc->opcodes[X86_OP_POP_E_SP], 0x66, 0x5c, "pop", read_instr_pop_reg1632); + register_opcode(proc->opcodes[X86_OP_POP_E_BP], 0x66, 0x5d, "pop", read_instr_pop_reg1632); + register_opcode(proc->opcodes[X86_OP_POP_E_SI], 0x66, 0x5e, "pop", read_instr_pop_reg1632); + register_opcode(proc->opcodes[X86_OP_POP_E_DI], 0x66, 0x5f, "pop", read_instr_pop_reg1632); + + register_opcode(proc->opcodes[X86_OP_PUSH_IMM1632], 0x66, 0x68, "push", read_instr_push_imm1632); + + + register_opcode(proc->opcodes[X86_OP_MOV_REG1632], 0x66, 0x89, "mov", read_instr_mov_with_reg1632); + + register_opcode_with_ext(proc->opcodes[X86_OP_ADD8_REG1632], 0x66, 0x83, 0, "add", read_instr_add8_with_reg1632); + register_opcode_with_ext(proc->opcodes[X86_OP_OR8_REG1632], 0x66, 0x83, 1, "or", read_instr_or8_with_reg1632); + register_opcode_with_ext(proc->opcodes[X86_OP_ADC8_REG1632], 0x66, 0x83, 2, "adc", read_instr_adc8_with_reg1632); + register_opcode_with_ext(proc->opcodes[X86_OP_SBB8_REG1632], 0x66, 0x83, 3, "sbb", read_instr_sbb8_with_reg1632); + register_opcode_with_ext(proc->opcodes[X86_OP_AND8_REG1632], 0x66, 0x83, 4, "and", read_instr_and8_with_reg1632); + register_opcode_with_ext(proc->opcodes[X86_OP_SUB8_REG1632], 0x66, 0x83, 5, "sub", read_instr_sub8_with_reg1632); + register_opcode_with_ext(proc->opcodes[X86_OP_XOR8_REG1632], 0x66, 0x83, 6, "xor", read_instr_xor8_with_reg1632); register_opcode(proc->opcodes[X86_OP_NOP], 0x00, 0x90, "nop", read_instr_nop); - - register_opcode(proc->opcodes[X86_OP_MOV_AX], 0x00, 0xb8, "mov", read_instr_mov_to_1632); - register_opcode(proc->opcodes[X86_OP_MOV_CX], 0x00, 0xb9, "mov", read_instr_mov_to_1632); - register_opcode(proc->opcodes[X86_OP_MOV_DX], 0x00, 0xba, "mov", read_instr_mov_to_1632); - register_opcode(proc->opcodes[X86_OP_MOV_BX], 0x00, 0xbb, "mov", read_instr_mov_to_1632); - register_opcode(proc->opcodes[X86_OP_MOV_SP], 0x00, 0xbc, "mov", read_instr_mov_to_1632); - register_opcode(proc->opcodes[X86_OP_MOV_BP], 0x00, 0xbd, "mov", read_instr_mov_to_1632); - register_opcode(proc->opcodes[X86_OP_MOV_SI], 0x00, 0xbe, "mov", read_instr_mov_to_1632); - register_opcode(proc->opcodes[X86_OP_MOV_DI], 0x00, 0xbf, "mov", read_instr_mov_to_1632); - + register_opcode(proc->opcodes[X86_OP_MOV_E_AX], 0x66, 0xb8, "mov", read_instr_mov_to_1632); + register_opcode(proc->opcodes[X86_OP_MOV_E_CX], 0x66, 0xb9, "mov", read_instr_mov_to_1632); + register_opcode(proc->opcodes[X86_OP_MOV_E_DX], 0x66, 0xba, "mov", read_instr_mov_to_1632); + register_opcode(proc->opcodes[X86_OP_MOV_E_BX], 0x66, 0xbb, "mov", read_instr_mov_to_1632); + register_opcode(proc->opcodes[X86_OP_MOV_E_SP], 0x66, 0xbc, "mov", read_instr_mov_to_1632); + register_opcode(proc->opcodes[X86_OP_MOV_E_BP], 0x66, 0xbd, "mov", read_instr_mov_to_1632); + register_opcode(proc->opcodes[X86_OP_MOV_E_SI], 0x66, 0xbe, "mov", read_instr_mov_to_1632); + register_opcode(proc->opcodes[X86_OP_MOV_E_DI], 0x66, 0xbf, "mov", read_instr_mov_to_1632); register_opcode(proc->opcodes[X86_OP_RET], 0x00, 0xc3, "ret", read_instr_ret); register_opcode(proc->opcodes[X86_OP_LEAVE], 0x00, 0xc9, "leave", read_instr_leave); @@ -234,54 +267,6 @@ void x86_register_instructions(asm_x86_processor *proc) register_opcode(proc->opcodes[X86_OP_HLT], 0x00, 0xf4, "hlt", read_instr_hlt); - register_opcode(proc->opcodes[X86_OP_INC_AX], 0x66, 0x40, "inc", read_instr_inc_1632); - register_opcode(proc->opcodes[X86_OP_INC_CX], 0x66, 0x41, "inc", read_instr_inc_1632); - register_opcode(proc->opcodes[X86_OP_INC_DX], 0x66, 0x42, "inc", read_instr_inc_1632); - register_opcode(proc->opcodes[X86_OP_INC_BX], 0x66, 0x43, "inc", read_instr_inc_1632); - register_opcode(proc->opcodes[X86_OP_INC_SP], 0x66, 0x44, "inc", read_instr_inc_1632); - register_opcode(proc->opcodes[X86_OP_INC_BP], 0x66, 0x45, "inc", read_instr_inc_1632); - register_opcode(proc->opcodes[X86_OP_INC_SI], 0x66, 0x46, "inc", read_instr_inc_1632); - register_opcode(proc->opcodes[X86_OP_INC_DI], 0x66, 0x47, "inc", read_instr_inc_1632); - - register_opcode(proc->opcodes[X86_OP_DEC_AX], 0x66, 0x48, "dec", read_instr_dec_1632); - register_opcode(proc->opcodes[X86_OP_DEC_CX], 0x66, 0x49, "dec", read_instr_dec_1632); - register_opcode(proc->opcodes[X86_OP_DEC_DX], 0x66, 0x4a, "dec", read_instr_dec_1632); - register_opcode(proc->opcodes[X86_OP_DEC_BX], 0x66, 0x4b, "dec", read_instr_dec_1632); - register_opcode(proc->opcodes[X86_OP_DEC_SP], 0x66, 0x4c, "dec", read_instr_dec_1632); - register_opcode(proc->opcodes[X86_OP_DEC_BP], 0x66, 0x4d, "dec", read_instr_dec_1632); - register_opcode(proc->opcodes[X86_OP_DEC_SI], 0x66, 0x4e, "dec", read_instr_dec_1632); - register_opcode(proc->opcodes[X86_OP_DEC_DI], 0x66, 0x4f, "dec", read_instr_dec_1632); - - register_opcode(proc->opcodes[X86_OP_PUSH_AX], 0x66, 0x50, "push", read_instr_push_reg1632); - register_opcode(proc->opcodes[X86_OP_PUSH_CX], 0x66, 0x51, "push", read_instr_push_reg1632); - register_opcode(proc->opcodes[X86_OP_PUSH_DX], 0x66, 0x52, "push", read_instr_push_reg1632); - register_opcode(proc->opcodes[X86_OP_PUSH_BX], 0x66, 0x53, "push", read_instr_push_reg1632); - register_opcode(proc->opcodes[X86_OP_PUSH_SP], 0x66, 0x54, "push", read_instr_push_reg1632); - register_opcode(proc->opcodes[X86_OP_PUSH_BP], 0x66, 0x55, "push", read_instr_push_reg1632); - register_opcode(proc->opcodes[X86_OP_PUSH_SI], 0x66, 0x56, "push", read_instr_push_reg1632); - register_opcode(proc->opcodes[X86_OP_PUSH_DI], 0x66, 0x57, "push", read_instr_push_reg1632); - - register_opcode(proc->opcodes[X86_OP_POP_AX], 0x66, 0x58, "pop", read_instr_pop_reg1632); - register_opcode(proc->opcodes[X86_OP_POP_CX], 0x66, 0x59, "pop", read_instr_pop_reg1632); - register_opcode(proc->opcodes[X86_OP_POP_DX], 0x66, 0x5a, "pop", read_instr_pop_reg1632); - register_opcode(proc->opcodes[X86_OP_POP_BX], 0x66, 0x5b, "pop", read_instr_pop_reg1632); - register_opcode(proc->opcodes[X86_OP_POP_SP], 0x66, 0x5c, "pop", read_instr_pop_reg1632); - register_opcode(proc->opcodes[X86_OP_POP_BP], 0x66, 0x5d, "pop", read_instr_pop_reg1632); - register_opcode(proc->opcodes[X86_OP_POP_SI], 0x66, 0x5e, "pop", read_instr_pop_reg1632); - register_opcode(proc->opcodes[X86_OP_POP_DI], 0x66, 0x5f, "pop", read_instr_pop_reg1632); - - register_opcode(proc->opcodes[X86_OP_PUSH_IMM16], 0x66, 0x68, "push", read_instr_push_imm1632); - - register_opcode(proc->opcodes[X86_OP_MOV_EAX], 0x66, 0xb8, "mov", read_instr_mov_to_1632); - register_opcode(proc->opcodes[X86_OP_MOV_ECX], 0x66, 0xb9, "mov", read_instr_mov_to_1632); - register_opcode(proc->opcodes[X86_OP_MOV_EDX], 0x66, 0xba, "mov", read_instr_mov_to_1632); - register_opcode(proc->opcodes[X86_OP_MOV_EBX], 0x66, 0xbb, "mov", read_instr_mov_to_1632); - register_opcode(proc->opcodes[X86_OP_MOV_ESP], 0x66, 0xbc, "mov", read_instr_mov_to_1632); - register_opcode(proc->opcodes[X86_OP_MOV_EBP], 0x66, 0xbd, "mov", read_instr_mov_to_1632); - register_opcode(proc->opcodes[X86_OP_MOV_ESI], 0x66, 0xbe, "mov", read_instr_mov_to_1632); - register_opcode(proc->opcodes[X86_OP_MOV_EDI], 0x66, 0xbf, "mov", read_instr_mov_to_1632); - - } @@ -307,20 +292,36 @@ asm_instr *x86_fetch_instruction(const asm_x86_processor *proc, const uint8_t *d { asm_x86_instr *result; /* Résultat à faire remonter */ X86Opcodes i; /* Boucle de parcours */ + off_t tmp; /* Tête de lecture */ result = NULL; for (i = 0; i < X86_OP_COUNT; i++) { - if ((proc->opcodes[i].prefix > 0 && data[*pos] == proc->opcodes[i].prefix && data[*pos + 1] == proc->opcodes[i].opcode) - || (proc->opcodes[i].prefix == 0 && data[*pos] == proc->opcodes[i].opcode)) + if (proc->opcodes[i].prefix > 0 && data[*pos] == proc->opcodes[i].prefix && data[*pos + 1] == proc->opcodes[i].opcode) + { + tmp = *pos + 2; + goto find_instr; + } + + if (proc->opcodes[i].opt_prefix && data[*pos] == proc->opcodes[i].opcode) { - result = proc->opcodes[i].read(data, pos, len, offset, proc); - if (result != NULL) result->type = i; - else printf("err while decoding :: [0x%02hhx] 0x%02hhx\n", proc->opcodes[i].prefix, proc->opcodes[i].opcode); - break; + tmp = *pos + 1; + goto find_instr; } + continue; + + find_instr: + + if (proc->opcodes[i].has_op_ext && (data[tmp] & EXT_OPCODE_MASK) != proc->opcodes[i].op_ext) + continue; + + result = proc->opcodes[i].read(data, pos, len, offset, proc); + if (result != NULL) result->type = i; + else printf("err while decoding :: [0x%02hhx] 0x%02hhx\n", proc->opcodes[i].prefix, proc->opcodes[i].opcode); + break; + } return ASM_INSTRUCTION(result); -- cgit v0.11.2-87-g4458