diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/arch/x86/Makefile.am | 7 | ||||
| -rw-r--r-- | src/arch/x86/instruction.h | 149 | ||||
| -rw-r--r-- | src/arch/x86/op_adc.c | 98 | ||||
| -rw-r--r-- | src/arch/x86/op_add.c | 98 | ||||
| -rw-r--r-- | src/arch/x86/op_and.c | 98 | ||||
| -rw-r--r-- | src/arch/x86/op_mov.c | 67 | ||||
| -rw-r--r-- | src/arch/x86/op_or.c | 98 | ||||
| -rw-r--r-- | src/arch/x86/op_sbb.c | 98 | ||||
| -rw-r--r-- | src/arch/x86/op_sub.c | 98 | ||||
| -rw-r--r-- | src/arch/x86/op_xor.c | 165 | ||||
| -rw-r--r-- | src/arch/x86/opcodes.h | 27 | ||||
| -rw-r--r-- | src/arch/x86/operand.c | 59 | ||||
| -rw-r--r-- | src/arch/x86/operand.h | 3 | ||||
| -rw-r--r-- | src/arch/x86/processor.c | 223 | 
14 files changed, 1085 insertions, 203 deletions
| 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 <http://www.gnu.org/licenses/>. + */ + + +#include <malloc.h> + + +#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 <http://www.gnu.org/licenses/>. + */ + + +#include <malloc.h> + + +#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 <http://www.gnu.org/licenses/>. + */ + + +#include <malloc.h> + + +#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 <http://www.gnu.org/licenses/>. + */ + + +#include <malloc.h> + + +#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 <http://www.gnu.org/licenses/>. + */ + + +#include <malloc.h> + + +#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 <http://www.gnu.org/licenses/>. + */ + + +#include <malloc.h> + + +#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 <http://www.gnu.org/licenses/>. + */ + + +#include <malloc.h> + + +#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); | 
