summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2008-09-14 20:54:43 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2008-09-14 20:54:43 (GMT)
commit06cf576b280cbabb73a956161693a63ee846f57b (patch)
tree3ac4b32e869cc8aaa1d4b7429d7d4a12f9a8ae7f
parentab1489b6a6ef1f09957f6f805f143fceb42f6a08 (diff)
Made the program able to disassemble a simple binary completely.
git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@30 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a
-rw-r--r--ChangeLog48
-rw-r--r--src/arch/operand.c132
-rw-r--r--src/arch/operand.h6
-rw-r--r--src/arch/processor.c5
-rw-r--r--src/arch/x86/Makefile.am3
-rw-r--r--src/arch/x86/instruction.h38
-rw-r--r--src/arch/x86/op_add.c62
-rw-r--r--src/arch/x86/op_call.c52
-rw-r--r--src/arch/x86/op_cmp.c210
-rw-r--r--src/arch/x86/op_jump.c159
-rw-r--r--src/arch/x86/op_mov.c171
-rw-r--r--src/arch/x86/op_sar.c92
-rw-r--r--src/arch/x86/op_sub.c65
-rw-r--r--src/arch/x86/op_test.c266
-rw-r--r--src/arch/x86/opcodes.h39
-rw-r--r--src/arch/x86/operand.c55
-rw-r--r--src/arch/x86/operand.h8
-rw-r--r--src/arch/x86/processor.c24
18 files changed, 1418 insertions, 17 deletions
diff --git a/ChangeLog b/ChangeLog
index 4955b49..5433440 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,51 @@
+2008-09-14 Cyrille Bagard <nocbos@gmail.com>
+
+ * src/arch/operand.c:
+ * src/arch/operand.h:
+ Add an alternate function to read immediate values.
+
+ * src/arch/processor.c:
+ Print a message when decoding unknown opcode.
+
+ * src/arch/x86/instruction.h:
+ Register new identifiers for the following opcodes: add, call, cmp, je,
+ jne, jmp, mov, sar and sub.
+
+ * src/arch/x86/Makefile.am:
+ Add op_cmp.c, op_jump.c and op_sar.c to libarchx86_a_SOURCES.
+
+ * src/arch/x86/op_add.c:
+ * src/arch/x86/op_call.c:
+ Improve the support of these opcodes.
+
+ * src/arch/x86/op_cmp.c:
+ New entry: handle some cmp opcodes.
+
+ * src/arch/x86/opcodes.h:
+ Register new functions for the following opcodes: add, call, cmp, je,
+ jne, jmp, mov, sar and sub.
+
+ * src/arch/x86/operand.c:
+ * src/arch/x86/operand.h:
+ Fix some mistakes when reading rm8 operands and add a way to read the
+ rel8 one.
+
+ * src/arch/x86/op_jump.c:
+ New entry: handle some jump opcodes.
+
+ * src/arch/x86/op_mov.c:
+ Improve the support of this opcode.
+
+ * src/arch/x86/op_sar.c:
+ New entry: handle one sar opcode.
+
+ * src/arch/x86/op_sub.c:
+ * src/arch/x86/op_test.c:
+ Improve the support of these opcodes.
+
+ * src/arch/x86/processor.c:
+ Decode the new instructions. Fix a mistake for X86_OP_PUSH_CONTENT.
+
2008-09-12 Cyrille Bagard <nocbos@gmail.com>
* src/arch/processor.c:
diff --git a/src/arch/operand.c b/src/arch/operand.c
index e24a3e0..53e652c 100644
--- a/src/arch/operand.c
+++ b/src/arch/operand.c
@@ -24,6 +24,7 @@
#include "operand.h"
+#include <stdarg.h>
#include <stdio.h>
@@ -90,6 +91,83 @@ void print_db_operand(const asm_operand *operand, char *buffer, size_t len, AsmS
/******************************************************************************
* *
+* Paramètres : size = taille de l'opérande souhaitée. *
+* data = flux de données à analyser. *
+* pos = position courante dans ce flux. [OUT] *
+* len = taille totale des données à analyser. *
+* ... = adresse où placer la valeur lue. [OUT] *
+* *
+* Description : Lit une valeur (signée ou non) sur x bits. *
+* *
+* Retour : true si l'opération s'est effectuée avec succès, false sinon.*
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool read_imm_value(AsmOperandSize size, const uint8_t *data, off_t *pos, off_t len, ...)
+{
+ va_list ap; /* Récupération d'argument */
+ uint8_t *val8; /* Valeur sur 8 bits */
+ uint16_t *val16; /* Valeur sur 16 bits */
+ uint32_t *val32; /* Valeur sur 32 bits */
+ uint64_t *val64; /* Valeur sur 64 bits */
+
+ /* Vérifications sanitaires */
+ switch (size)
+ {
+ case AOS_8_BITS:
+ if ((len - *pos) < 1) return false;
+ break;
+ case AOS_16_BITS:
+ if ((len - *pos) < 2) return false;
+ break;
+ case AOS_32_BITS:
+ if ((len - *pos) < 4) return false;
+ break;
+ case AOS_64_BITS:
+ if ((len - *pos) < 8) return false;
+ break;
+ }
+
+ va_start(ap, len);
+
+ switch (size)
+ {
+ case AOS_8_BITS:
+ val8 = va_arg(ap, uint8_t *);
+ *val8 = data[*pos];
+ *pos += 1;
+ break;
+ case AOS_16_BITS:
+ val16 = va_arg(ap, uint16_t *);
+ *val16 = data[*pos] | (uint16_t)data[*pos + 1] << 8;
+ *pos += 2;
+ break;
+ case AOS_32_BITS:
+ val32 = va_arg(ap, uint32_t *);
+ *val32 = data[*pos] | (uint32_t)data[*pos + 1] << 8
+ | (uint32_t)data[*pos + 2] << 16 | (uint32_t)data[*pos + 3] << 24;
+ *pos += 4;
+ break;
+ case AOS_64_BITS:
+ val64 = va_arg(ap, uint64_t *);
+ *val64 = data[*pos] | (uint64_t)data[*pos + 1] << 8 | (uint64_t)data[*pos + 2] << 16
+ | (uint64_t)data[*pos + 3] << 24 | (uint64_t)data[*pos + 4] << 32 | (uint64_t)data[*pos + 5] << 40
+ | (uint64_t)data[*pos + 6] << 48 | (uint64_t)data[*pos + 7] << 56;
+ *pos += 8;
+ break;
+ }
+
+ va_end(ap);
+
+ return true;
+
+}
+
+
+/******************************************************************************
+* *
* Paramètres : operand = structure dont le contenu est à définir. *
* size = taille de l'opérande souhaitée. *
* data = flux de données à analyser. *
@@ -158,6 +236,60 @@ bool fill_imm_operand(asm_operand *operand, AsmOperandSize size, const uint8_t *
* *
* Paramètres : operand = structure dont le contenu est à définir. *
* size = taille de l'opérande souhaitée. *
+* ... = valeur à utiliser. *
+* *
+* Description : Crée une opérande contenant une valeur sur x bits. *
+* *
+* Retour : true si l'opération s'est effectuée avec succès, false sinon.*
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool fill_imm_operand_with_value(asm_operand *operand, AsmOperandSize size, ...)
+{
+ va_list ap; /* Récupération d'argument */
+ const uint8_t *val8; /* Valeur sur 8 bits */
+ const uint16_t *val16; /* Valeur sur 16 bits */
+ const uint32_t *val32; /* Valeur sur 32 bits */
+ const uint64_t *val64; /* Valeur sur 64 bits */
+
+ operand->type = AOT_IMM;
+ operand->size = size;
+
+ va_start(ap, size);
+
+ switch (size)
+ {
+ case AOS_8_BITS:
+ val8 = va_arg(ap, const uint8_t *);
+ operand->value.val8 = *val8;
+ break;
+ case AOS_16_BITS:
+ val16 = va_arg(ap, const uint16_t *);
+ operand->value.val16 = *val16;
+ break;
+ case AOS_32_BITS:
+ val32 = va_arg(ap, const uint32_t *);
+ operand->value.val32 = *val32;
+ break;
+ case AOS_64_BITS:
+ val64 = va_arg(ap, const uint64_t *);
+ operand->value.val64 = *val64;
+ break;
+ }
+
+ va_end(ap);
+
+ return true;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : operand = structure dont le contenu est à définir. *
+* size = taille de l'opérande souhaitée. *
* data = flux de données à analyser. *
* pos = position courante dans ce flux. [OUT] *
* len = taille totale des données à analyser. *
diff --git a/src/arch/operand.h b/src/arch/operand.h
index 1067518..e913059 100644
--- a/src/arch/operand.h
+++ b/src/arch/operand.h
@@ -62,9 +62,15 @@ bool fill_db_operand(asm_operand *, uint8_t);
/* Traduit une opérande de type 'db' en texte. */
void print_db_operand(const asm_operand *, char *, size_t, AsmSyntax);
+/* Lit une valeur (signée ou non) sur x bits. */
+bool read_imm_value(AsmOperandSize, const uint8_t *, off_t *, off_t, ...);
+
/* Crée une opérande contenant une valeur sur x bits. */
bool fill_imm_operand(asm_operand *, AsmOperandSize, const uint8_t *, off_t *, off_t);
+/* Crée une opérande contenant une valeur sur x bits. */
+bool fill_imm_operand_with_value(asm_operand *, AsmOperandSize, ...);
+
/* Crée une opérande contenant une valeur relative sur x bits. */
bool fill_relimm_operand(asm_operand *, AsmOperandSize, const uint8_t *, off_t *, off_t, uint64_t);
diff --git a/src/arch/processor.c b/src/arch/processor.c
index 0afca2c..373222f 100644
--- a/src/arch/processor.c
+++ b/src/arch/processor.c
@@ -60,9 +60,10 @@ asm_instr *decode_instruction(const asm_processor *proc, const uint8_t *data, of
if (result == NULL)
+ {
+ printf("err while decoding opcode 0x%0hhx at 0x%08llx\n", data[*pos], offset);
result = create_db_instruction(data, pos, len);
-
-
+ }
diff --git a/src/arch/x86/Makefile.am b/src/arch/x86/Makefile.am
index b074f69..139bcde 100644
--- a/src/arch/x86/Makefile.am
+++ b/src/arch/x86/Makefile.am
@@ -7,10 +7,12 @@ libarchx86_a_SOURCES = \
op_add.c \
op_and.c \
op_call.c \
+ op_cmp.c \
op_dec.c \
op_hlt.c \
op_inc.c \
op_int.c \
+ op_jump.c \
op_lea.c \
op_leave.c \
op_nop.c \
@@ -19,6 +21,7 @@ libarchx86_a_SOURCES = \
op_pop.c \
op_push.c \
op_ret.c \
+ op_sar.c \
op_sbb.c \
op_sub.c \
op_test.c \
diff --git a/src/arch/x86/instruction.h b/src/arch/x86/instruction.h
index af4f7cf..68a5fff 100644
--- a/src/arch/x86/instruction.h
+++ b/src/arch/x86/instruction.h
@@ -38,8 +38,12 @@ typedef struct _asm_x86_instr asm_x86_instr;
/* Enumération de tous les opcodes */
typedef enum _X86Opcodes
{
+ X86_OP_SUB_R1632_RM1632, /* sub ([0x66] 0x29) */
+
X86_OP_XOR_REG1632, /* xor ([0x66] 0x31) */
+ X86_OP_CMP_RM1632_R1632, /* cmp ([0x66] 0x39) */
+
X86_OP_INC_E_AX, /* inc ([0x66] 0x40) */
X86_OP_INC_E_CX, /* inc ([0x66] 0x41) */
X86_OP_INC_E_DX, /* inc ([0x66] 0x42) */
@@ -78,19 +82,27 @@ typedef enum _X86Opcodes
X86_OP_PUSH_IMM1632, /* push ([0x66] 0x68) */
- X86_OP_MOV_REG1632, /* mov ([0x66] 0x89) */
+ X86_OP_JE_8, /* je (0x74) */
+ X86_OP_JNE_8, /* jne (0x75) */
+
+ X86_OP_CMP_RM8_IMM8, /* cmp (0x80 7) */
+
+ X86_OP_ADD_IMM1632_REG1632, /* add ([0x66] 0x81 0) */
- 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_ADD8_REG1632, /* add ([0x66] 0x83 0) */
+ X86_OP_OR8_REG1632, /* or ([0x66] 0x83 1) */
+ X86_OP_ADC8_REG1632, /* adc ([0x66] 0x83 2) */
+ X86_OP_SBB8_REG1632, /* sbb ([0x66] 0x83 3) */
+ X86_OP_AND8_REG1632, /* and ([0x66] 0x83 4) */
+ X86_OP_SUB8_REG1632, /* sub ([0x66] 0x83 5) */
+ X86_OP_XOR8_REG1632, /* xor ([0x66] 0x83 6) */
+ X86_OP_CMP_RM1632_IMM8, /* cmp ([0x66] 0x08 7) */
X86_OP_TEST_RM8, /* test ([0x66] 0x84) */
X86_OP_TEST_RM1632, /* test ([0x66] 0x85) */
+ X86_OP_MOV_REG1632, /* mov ([0x66] 0x89) */
+
X86_OP_MOV_FROM_CONTENT1632, /* mov ([0x66] 0x8b) */
X86_OP_LEA, /* lea ([0x66] 0x8d) */ /* 66 ? */
@@ -99,6 +111,8 @@ typedef enum _X86Opcodes
X86_OP_MOV_MOFFS_TO_AL, /* mov (0xa0) */
X86_OP_MOV_MOFFS_TO_E_AX, /* mov ([0x66] 0xa1) */
+ X86_OP_MOV_AL_TO_MOFFS, /* mov (0xa2) */
+ X86_OP_MOV_E_AX_TO_MOFFS, /* mov ([0x66] 0xa3) */
X86_OP_TEST_AL, /* test (0xa8) */
X86_OP_TEST_E_AX, /* test ([0x66] 0xa9) */
@@ -112,8 +126,11 @@ typedef enum _X86Opcodes
X86_OP_MOV_E_SI, /* mov ([0x66] 0xbe) */
X86_OP_MOV_E_DI, /* mov ([0x66] 0xbf) */
+ X86_OP_SAR_RM1632_IMM8, /* sar ([0x66 0xc1 7) */
+
X86_OP_RET, /* ret (0xc3) */
+ X86_OP_MOV_IMM8_TO_RM8, /* mov (0xc6) */
X86_OP_MOV_TO_CONTENT1632, /* mov ([0x66] 0xc7) */
X86_OP_LEAVE, /* leave (0xc9) */
@@ -122,9 +139,12 @@ typedef enum _X86Opcodes
X86_OP_CALL, /* call (0xe8) */
+ X86_OP_JMP_8, /* jmp (0xeb) */
+
X86_OP_HLT, /* hlt (0xf4) */
- X86_OP_PUSH_CONTENT, /* push ([0x66] 0xff) */ /* 66 ? */
+ X86_OP_CALL_RM1632, /* call ([0x66] 0xff 2) */
+ X86_OP_PUSH_CONTENT, /* push ([0x66] 0xff 6) */ /* 66 ? */
X86_OP_COUNT
diff --git a/src/arch/x86/op_add.c b/src/arch/x86/op_add.c
index 99a30fc..bab7f03 100644
--- a/src/arch/x86/op_add.c
+++ b/src/arch/x86/op_add.c
@@ -96,3 +96,65 @@ asm_x86_instr *read_instr_add8_with_reg1632(const uint8_t *data, off_t *pos, off
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 'add' (16 ou 32 bits). *
+* *
+* Retour : Instruction mise en place ou NULL. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+asm_x86_instr *x86_read_instr_add_imm1632_to_rm1632(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)++];
+
+ reg = x86_create_rm1632_operand(data, pos, len, oprsize == AOS_32_BITS, true);
+ if (reg == NULL)
+ {
+ free(result);
+ return NULL;
+ }
+
+ value = create_new_x86_operand();
+ if (!fill_imm_operand(ASM_OPERAND(value), oprsize, 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_call.c b/src/arch/x86/op_call.c
index 61d9874..f7330ca 100644
--- a/src/arch/x86/op_call.c
+++ b/src/arch/x86/op_call.c
@@ -81,3 +81,55 @@ asm_x86_instr *read_instr_call(const uint8_t *data, off_t *pos, off_t len, uint6
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 'call' (16 ou 32 bits). *
+* *
+* Retour : Instruction mise en place ou NULL. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+asm_x86_instr *x86_read_instr_call_rm1632(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; /* Elément à appeler */
+
+ 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)++;
+ offset++;
+ }
+ else oprsize = get_x86_current_operand_size(proc);
+
+ ASM_INSTRUCTION(result)->opcode = data[(*pos)++];
+
+ reg = x86_create_rm1632_operand(data, pos, len, oprsize == AOS_32_BITS, true);
+ if (reg == NULL)
+ {
+ free(result);
+ return NULL;
+ }
+
+ ASM_INSTRUCTION(result)->operands = (asm_operand **)calloc(1, sizeof(asm_operand *));
+ ASM_INSTRUCTION(result)->operands_count = 1;
+
+ ASM_INSTRUCTION(result)->operands[0] = ASM_OPERAND(reg);
+
+ return result;
+
+}
diff --git a/src/arch/x86/op_cmp.c b/src/arch/x86/op_cmp.c
new file mode 100644
index 0000000..9e5bcc5
--- /dev/null
+++ b/src/arch/x86/op_cmp.c
@@ -0,0 +1,210 @@
+
+/* OpenIDA - Outil d'analyse de fichiers binaires
+ * op_cmp.c - décodage des comparaisons d'opérandes
+ *
+ * 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 'cmp' (8 bits). *
+* *
+* Retour : Instruction mise en place ou NULL. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+asm_x86_instr *x86_read_instr_cmp_rm8_with_imm8(const uint8_t *data, off_t *pos, off_t len, uint64_t offset, const asm_x86_processor *proc)
+{
+ asm_x86_instr *result; /* Instruction à retourner */
+ asm_x86_operand *reg; /* Registre de destination */
+ asm_x86_operand *value; /* Valeur portée */
+
+ result = (asm_x86_instr *)calloc(1, sizeof(asm_x86_instr));
+
+ ASM_INSTRUCTION(result)->opcode = data[(*pos)++];
+
+ reg = x86_create_rm8_operand(data, pos, len, true);
+ if (reg == NULL)
+ {
+ free(result);
+ return NULL;
+ }
+
+ 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;
+
+}
+
+
+/******************************************************************************
+* *
+* 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 'cmp' (8 bits). *
+* *
+* Retour : Instruction mise en place ou NULL. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+asm_x86_instr *x86_read_instr_cmp_rm1632_with_imm8(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 porté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)++];
+
+ reg = x86_create_rm1632_operand(data, pos, len, oprsize == AOS_32_BITS, true);
+ if (reg == NULL)
+ {
+ free(result);
+ return NULL;
+ }
+
+ 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;
+
+}
+
+
+/******************************************************************************
+* *
+* 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 'cmp' (16 ou 32 bits). *
+* *
+* Retour : Instruction mise en place ou NULL. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+asm_x86_instr *x86_read_instr_cmp_rm1632_with_r1632(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 */
+ off_t reg1_pos; /* POsition après lecture #1 */
+ asm_x86_operand *reg1; /* Registre de destination */
+ asm_x86_operand *reg2; /* Registre de source */
+
+ 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)++];
+
+ reg1_pos = *pos;
+ reg1 = x86_create_rm1632_operand(data, &reg1_pos, len, oprsize == AOS_32_BITS, true);
+ if (reg1 == NULL)
+ {
+ free(result);
+ return NULL;
+ }
+
+ reg2 = x86_create_r1632_operand(data[*pos], oprsize == AOS_32_BITS, false);
+ if (reg2 == NULL)
+ {
+ free(result);
+ free(reg1);
+ return NULL;
+ }
+
+ *pos = reg1_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;
+
+}
diff --git a/src/arch/x86/op_jump.c b/src/arch/x86/op_jump.c
new file mode 100644
index 0000000..bcfcb0f
--- /dev/null
+++ b/src/arch/x86/op_jump.c
@@ -0,0 +1,159 @@
+
+/* OpenIDA - Outil d'analyse de fichiers binaires
+ * op_jump.c - décodage des sauts conditionnels
+ *
+ * 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 'je' (petit saut). *
+* *
+* Retour : Instruction mise en place ou NULL. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+asm_x86_instr *read_instr_je_8(const uint8_t *data, off_t *pos, off_t len, uint64_t offset, const asm_x86_processor *proc)
+{
+ asm_x86_instr *result; /* Instruction à retourner */
+ asm_x86_operand *address; /* Adresse visée réelle */
+
+ result = (asm_x86_instr *)calloc(1, sizeof(asm_x86_instr));
+
+ ASM_INSTRUCTION(result)->opcode = data[(*pos)++];
+
+ /* TODO : 64bits */
+ address = x86_create_rel8_operand_in_32b(offset + 1, data, pos, len);
+ if (address == NULL)
+ {
+ free(result);
+ return NULL;
+ }
+
+ ASM_INSTRUCTION(result)->operands = (asm_operand **)calloc(1, sizeof(asm_operand *));
+ ASM_INSTRUCTION(result)->operands_count = 1;
+
+ ASM_INSTRUCTION(result)->operands[0] = ASM_OPERAND(address);
+
+ 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 'jne' (petit saut). *
+* *
+* Retour : Instruction mise en place ou NULL. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+asm_x86_instr *read_instr_jne_8(const uint8_t *data, off_t *pos, off_t len, uint64_t offset, const asm_x86_processor *proc)
+{
+ asm_x86_instr *result; /* Instruction à retourner */
+ asm_x86_operand *address; /* Adresse visée réelle */
+
+ result = (asm_x86_instr *)calloc(1, sizeof(asm_x86_instr));
+
+ ASM_INSTRUCTION(result)->opcode = data[(*pos)++];
+
+ /* TODO : 64bits */
+ address = x86_create_rel8_operand_in_32b(offset + 1, data, pos, len);
+ if (address == NULL)
+ {
+ free(result);
+ return NULL;
+ }
+
+ ASM_INSTRUCTION(result)->operands = (asm_operand **)calloc(1, sizeof(asm_operand *));
+ ASM_INSTRUCTION(result)->operands_count = 1;
+
+ ASM_INSTRUCTION(result)->operands[0] = ASM_OPERAND(address);
+
+ 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 'jmp' (petit saut). *
+* *
+* Retour : Instruction mise en place ou NULL. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+asm_x86_instr *read_instr_jmp_8(const uint8_t *data, off_t *pos, off_t len, uint64_t offset, const asm_x86_processor *proc)
+{
+ asm_x86_instr *result; /* Instruction à retourner */
+ asm_x86_operand *address; /* Adresse visée réelle */
+
+ result = (asm_x86_instr *)calloc(1, sizeof(asm_x86_instr));
+
+ ASM_INSTRUCTION(result)->opcode = data[(*pos)++];
+
+ /* TODO : 64bits */
+ address = x86_create_rel8_operand_in_32b(offset + 1, data, pos, len);
+ if (address == NULL)
+ {
+ free(result);
+ return NULL;
+ }
+
+ ASM_INSTRUCTION(result)->operands = (asm_operand **)calloc(1, sizeof(asm_operand *));
+ ASM_INSTRUCTION(result)->operands_count = 1;
+
+ ASM_INSTRUCTION(result)->operands[0] = ASM_OPERAND(address);
+
+ return result;
+
+}
diff --git a/src/arch/x86/op_mov.c b/src/arch/x86/op_mov.c
index 388d67e..f5a8825 100644
--- a/src/arch/x86/op_mov.c
+++ b/src/arch/x86/op_mov.c
@@ -38,7 +38,7 @@
* offset = adresse virtuelle de l'instruction. *
* proc = architecture ciblée par le désassemblage. *
* *
-* Description : Décode une instruction de type 'mov al, ...' (8 bits). *
+* Description : Décode une instruction de type 'mov ..., al' (8 bits). *
* *
* Retour : Instruction mise en place ou NULL. *
* *
@@ -46,10 +46,175 @@
* *
******************************************************************************/
-asm_x86_instr *read_instr_mov_moffs8_to_al(const uint8_t *data, off_t *pos, off_t len, uint64_t offset, const asm_x86_processor *proc)
+asm_x86_instr *read_instr_mov_al_to_moffs8(const uint8_t *data, off_t *pos, off_t len, uint64_t offset, const asm_x86_processor *proc)
+{
+ asm_x86_instr *result; /* Instruction à retourner */
+ asm_x86_operand *value; /* Valeur portée */
+ asm_x86_operand *reg; /* Registre de source */
+
+ result = (asm_x86_instr *)calloc(1, sizeof(asm_x86_instr));
+
+ ASM_INSTRUCTION(result)->opcode = data[(*pos)++];
+
+ value = x86_create_moffs8_operand(data, pos, len);
+ if (value == NULL)
+ {
+ free(result);
+ return NULL;
+ }
+
+ reg = x86_create_r8_operand(0x00, true);
+ if (reg == NULL)
+ {
+ 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(value);
+ ASM_INSTRUCTION(result)->operands[1] = ASM_OPERAND(reg);
+
+ 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 ..., [e]ax' (16/32 bits).*
+* *
+* Retour : Instruction mise en place ou NULL. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+asm_x86_instr *read_instr_mov_e_ax_to_moffs1632(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 *value; /* Valeur portée */
+ asm_x86_operand *reg; /* Registre de source */
+
+ 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)++];
+
+ value = x86_create_moffs1632_operand(data, pos, len, oprsize == AOS_32_BITS);
+ if (value == NULL)
+ {
+ free(result);
+ return NULL;
+ }
+
+ reg = x86_create_r1632_operand(0x00, oprsize == AOS_32_BITS, true);
+ if (reg == NULL)
+ {
+ 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(value);
+ ASM_INSTRUCTION(result)->operands[1] = ASM_OPERAND(reg);
+
+ 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' (8 bits). *
+* *
+* Retour : Instruction mise en place ou NULL. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+asm_x86_instr *read_instr_mov_imm8_to_rm8(const uint8_t *data, off_t *pos, off_t len, uint64_t offset, const asm_x86_processor *proc)
+{
+ asm_x86_instr *result; /* Instruction à retourner */
+ asm_x86_operand *reg; /* Registre de destination */
+ asm_x86_operand *value; /* Valeur portée */
+
+ result = (asm_x86_instr *)calloc(1, sizeof(asm_x86_instr));
+
+ ASM_INSTRUCTION(result)->opcode = data[(*pos)++];
+
+ reg = x86_create_rm8_operand(data, pos, len, true);
+ if (reg == NULL)
+ {
+ free(result);
+ return NULL;
+ }
+
+ 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;
+
+}
+
+
+/******************************************************************************
+* *
+* 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 al, ...' (8 bits). *
+* *
+* Retour : Instruction mise en place ou NULL. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+asm_x86_instr *read_instr_mov_moffs8_to_al(const uint8_t *data, off_t *pos, off_t len, uint64_t offset, const asm_x86_processor *proc)
+{
+ asm_x86_instr *result; /* Instruction à retourner */
asm_x86_operand *reg; /* Registre de destination */
asm_x86_operand *value; /* Valeur portée */
@@ -148,6 +313,8 @@ asm_x86_instr *read_instr_mov_moffs1632_to_e_ax(const uint8_t *data, off_t *pos,
+
+
/******************************************************************************
* *
* Paramètres : data = flux de données à analyser. *
diff --git a/src/arch/x86/op_sar.c b/src/arch/x86/op_sar.c
new file mode 100644
index 0000000..187c2bb
--- /dev/null
+++ b/src/arch/x86/op_sar.c
@@ -0,0 +1,92 @@
+
+/* OpenIDA - Outil d'analyse de fichiers binaires
+ * op_cmp.c - décodage des comparaisons d'opérandes
+ *
+ * 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 'sar' (8 bits). *
+* *
+* Retour : Instruction mise en place ou NULL. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+asm_x86_instr *x86_read_instr_sar_rm1632_with_imm8(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 porté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)++];
+
+ reg = x86_create_rm1632_operand(data, pos, len, oprsize == AOS_32_BITS, true);
+ if (reg == NULL)
+ {
+ free(result);
+ return NULL;
+ }
+
+ 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
index a323aa8..f14e4a9 100644
--- a/src/arch/x86/op_sub.c
+++ b/src/arch/x86/op_sub.c
@@ -96,3 +96,68 @@ asm_x86_instr *read_instr_sub8_with_reg1632(const uint8_t *data, off_t *pos, off
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 'sub' (16 ou 32 bits). *
+* *
+* Retour : Instruction mise en place ou NULL. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+asm_x86_instr *x86_read_instr_sub_r1632_to_rm1632(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 */
+ off_t reg1_pos; /* POsition après lecture #1 */
+ asm_x86_operand *reg1; /* Registre de destination */
+ asm_x86_operand *reg2; /* Registre de source */
+
+ 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)++];
+
+ reg1_pos = *pos;
+ reg1 = x86_create_rm1632_operand(data, &reg1_pos, len, oprsize == AOS_32_BITS, true);
+ if (reg1 == NULL)
+ {
+ free(result);
+ return NULL;
+ }
+
+ reg2 = x86_create_r1632_operand(data[*pos], oprsize == AOS_32_BITS, false);
+ if (reg2 == NULL)
+ {
+ free(result);
+ free(reg1);
+ return NULL;
+ }
+
+ *pos = reg1_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;
+
+}
diff --git a/src/arch/x86/op_test.c b/src/arch/x86/op_test.c
new file mode 100644
index 0000000..9231838
--- /dev/null
+++ b/src/arch/x86/op_test.c
@@ -0,0 +1,266 @@
+
+/* OpenIDA - Outil d'analyse de fichiers binaires
+ * op_test.c - décodage des comparaisons 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 'test al, ...' (8 bits). *
+* *
+* Retour : Instruction mise en place ou NULL. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+asm_x86_instr *read_instr_test_al(const uint8_t *data, off_t *pos, off_t len, uint64_t offset, const asm_x86_processor *proc)
+{
+ asm_x86_instr *result; /* Instruction à retourner */
+ asm_x86_operand *reg; /* Registre de destination */
+ asm_x86_operand *value; /* Valeur portée */
+
+ result = (asm_x86_instr *)calloc(1, sizeof(asm_x86_instr));
+
+ ASM_INSTRUCTION(result)->opcode = data[(*pos)++];
+
+ reg = x86_create_r8_operand(0x00, true);
+ if (reg == NULL)
+ {
+ free(result);
+ return NULL;
+ }
+
+ 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;
+
+}
+
+
+/******************************************************************************
+* *
+* 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 'test [e]ax, ...' (16/32b). *
+* *
+* Retour : Instruction mise en place ou NULL. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+asm_x86_instr *read_instr_test_e_ax(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 porté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)++];
+
+ reg = x86_create_r1632_operand(0x00, oprsize == AOS_32_BITS, true);
+ if (reg == NULL)
+ {
+ free(result);
+ return NULL;
+ }
+
+ value = create_new_x86_operand();
+ if (!fill_imm_operand(ASM_OPERAND(value), oprsize, 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;
+
+}
+
+
+/******************************************************************************
+* *
+* 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 'test' (8 bits). *
+* *
+* Retour : Instruction mise en place ou NULL. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+asm_x86_instr *read_instr_test_rm8(const uint8_t *data, off_t *pos, off_t len, uint64_t offset, const asm_x86_processor *proc)
+{
+ asm_x86_instr *result; /* Instruction à retourner */
+ off_t reg1_pos; /* POsition après lecture #1 */
+ asm_x86_operand *reg1; /* Registre de destination */
+ asm_x86_operand *reg2; /* Registre de source */
+
+ result = (asm_x86_instr *)calloc(1, sizeof(asm_x86_instr));
+
+ ASM_INSTRUCTION(result)->opcode = data[(*pos)++];
+
+ reg1_pos = *pos;
+ reg1 = x86_create_rm8_operand(data, &reg1_pos, len, true);
+ if (reg1 == NULL)
+ {
+ free(result);
+ return NULL;
+ }
+
+ reg2 = x86_create_r8_operand(data[*pos], false);
+ if (reg2 == NULL)
+ {
+ free(result);
+ free(reg1);
+ return NULL;
+ }
+
+ *pos = reg1_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 'test' (16 ou 32 bits). *
+* *
+* Retour : Instruction mise en place ou NULL. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+asm_x86_instr *read_instr_test_rm1632(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 */
+ off_t reg1_pos; /* POsition après lecture #1 */
+ asm_x86_operand *reg1; /* Registre de destination */
+ asm_x86_operand *reg2; /* Registre de source */
+
+ 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)++];
+
+ reg1_pos = *pos;
+ reg1 = x86_create_rm1632_operand(data, &reg1_pos, len, oprsize == AOS_32_BITS, true);
+ if (reg1 == NULL)
+ {
+ free(result);
+ return NULL;
+ }
+
+ reg2 = x86_create_r1632_operand(data[*pos], oprsize == AOS_32_BITS, false);
+ if (reg2 == NULL)
+ {
+ free(result);
+ free(reg1);
+ return NULL;
+ }
+
+ *pos = reg1_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;
+
+}
diff --git a/src/arch/x86/opcodes.h b/src/arch/x86/opcodes.h
index 09fed4e..ef5c66c 100644
--- a/src/arch/x86/opcodes.h
+++ b/src/arch/x86/opcodes.h
@@ -40,12 +40,27 @@ asm_x86_instr *read_instr_adc8_with_reg1632(const uint8_t *, off_t *, off_t, uin
/* 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 'add' (16 ou 32 bits). */
+asm_x86_instr *x86_read_instr_add_imm1632_to_rm1632(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 *);
+/* Décode une instruction de type 'call' (16 ou 32 bits). */
+asm_x86_instr *x86_read_instr_call_rm1632(const uint8_t *, off_t *, off_t, uint64_t, const asm_x86_processor *);
+
+/* Décode une instruction de type 'cmp' (8 bits). */
+asm_x86_instr *x86_read_instr_cmp_rm8_with_imm8(const uint8_t *, off_t *, off_t, uint64_t, const asm_x86_processor *);
+
+/* Décode une instruction de type 'cmp' (8 bits). */
+asm_x86_instr *x86_read_instr_cmp_rm1632_with_imm8(const uint8_t *, off_t *, off_t, uint64_t, const asm_x86_processor *);
+
+/* Décode une instruction de type 'cmp' (16 ou 32 bits). */
+asm_x86_instr *x86_read_instr_cmp_rm1632_with_r1632(const uint8_t *, off_t *, off_t, uint64_t, const asm_x86_processor *);
+
/* Décode une instruction de type 'dec'. */
asm_x86_instr *read_instr_dec_1632(const uint8_t *, off_t *, off_t, uint64_t, const asm_x86_processor *);
@@ -58,12 +73,30 @@ asm_x86_instr *read_instr_inc_1632(const uint8_t *, off_t *, off_t, uint64_t, co
/* Décode une instruction de type 'int'. */
asm_x86_instr *read_instr_int(const uint8_t *, off_t *, off_t, uint64_t, const asm_x86_processor *);
+/* Décode une instruction de type 'je' (petit saut). */
+asm_x86_instr *read_instr_je_8(const uint8_t *, off_t *, off_t, uint64_t, const asm_x86_processor *);
+
+/* Décode une instruction de type 'jne' (petit saut). */
+asm_x86_instr *read_instr_jne_8(const uint8_t *, off_t *, off_t, uint64_t, const asm_x86_processor *);
+
+/* Décode une instruction de type 'jump' (petit saut). */
+asm_x86_instr *read_instr_jmp_8(const uint8_t *, off_t *, off_t, uint64_t, const asm_x86_processor *);
+
/* Décode une instruction de type 'lea' (16 ou 32 bits). */
asm_x86_instr *read_instr_lea(const uint8_t *, off_t *, off_t, uint64_t, const asm_x86_processor *);
/* Décode une instruction de type 'leave'. */
asm_x86_instr *read_instr_leave(const uint8_t *, off_t *, off_t, uint64_t, const asm_x86_processor *);
+/* Décode une instruction de type 'mov ..., al' (8 bits). */
+asm_x86_instr *read_instr_mov_al_to_moffs8(const uint8_t *, off_t *, off_t, uint64_t, const asm_x86_processor *);
+
+/* Décode une instruction de type 'mov ..., [e]ax' (16/32 bits). */
+asm_x86_instr *read_instr_mov_e_ax_to_moffs1632(const uint8_t *, off_t *, off_t, uint64_t, const asm_x86_processor *);
+
+/* Décode une instruction de type 'mov' (8 bits). */
+asm_x86_instr *read_instr_mov_imm8_to_rm8(const uint8_t *, off_t *, off_t, uint64_t, const asm_x86_processor *);
+
/* Décode une instruction de type 'mov al, ...' (8 bits). */
asm_x86_instr *read_instr_mov_moffs8_to_al(const uint8_t *, off_t *, off_t, uint64_t, const asm_x86_processor *);
@@ -103,12 +136,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 'sar' (8 bits). */
+asm_x86_instr *x86_read_instr_sar_rm1632_with_imm8(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 'sub' (16 ou 32 bits). */
+asm_x86_instr *x86_read_instr_sub_r1632_to_rm1632(const uint8_t *, off_t *, off_t, uint64_t, const asm_x86_processor *);
+
/* Décode une instruction de type 'test al, ...' (8 bits). */
asm_x86_instr *read_instr_test_al(const uint8_t *, off_t *, off_t, uint64_t, const asm_x86_processor *);
diff --git a/src/arch/x86/operand.c b/src/arch/x86/operand.c
index 281c139..10a908e 100644
--- a/src/arch/x86/operand.c
+++ b/src/arch/x86/operand.c
@@ -505,7 +505,7 @@ asm_x86_operand *x86_create_rm8_operand(const uint8_t *data, off_t *pos, off_t l
free(result);
result = create_new_x86_operand();
- if (!fill_imm_operand(ASM_OPERAND(result), AOS_8_BITS, data, pos, len))
+ if (!fill_imm_operand(ASM_OPERAND(result), AOS_32_BITS/* FIXME! 16/32 */, data, pos, len))
{
free(result);
return NULL;
@@ -573,7 +573,7 @@ asm_x86_operand *x86_create_rm8_operand(const uint8_t *data, off_t *pos, off_t l
case 0x80:
result->displacement = create_new_x86_operand();
- if (!fill_imm_operand(ASM_OPERAND(result->displacement), AOS_8_BITS, data, pos, len))
+ if (!fill_imm_operand(ASM_OPERAND(result->displacement), AOS_32_BITS/* FIXME ! 16/32 */, data, pos, len))
{
free(result->displacement);
free(result);
@@ -1188,3 +1188,54 @@ void x86_print_moffs_operand(const asm_x86_operand *operand, char *buffer, size_
}
}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* OPERANDES D'ADRESSES RELATIVES */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : data = flux de données à analyser. *
+* pos = position courante dans ce flux. [OUT] *
+* len = taille totale des données à analyser. *
+* *
+* Description : Crée une opérande à partir d'une adresse relative (8 bits). *
+* *
+* Retour : Opérande mise en place ou NULL. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+asm_x86_operand *x86_create_rel8_operand_in_32b(uint64_t base, const uint8_t *data, off_t *pos, off_t len)
+{
+ asm_x86_operand *result; /* Emplacement à retourner */
+ off_t init_pos; /* Position avant lecture */
+ int8_t offset; /* Décallage à appliquer */
+ uint32_t address; /* Adresse finale visée */
+
+ result = create_new_x86_operand();
+
+ init_pos = *pos;
+ address = base;
+
+ if (!read_imm_value(AOS_8_BITS, data, pos, len, &offset))
+ {
+ free(result);
+ return NULL;
+ }
+
+ address = base + (*pos - init_pos) + offset;
+
+ if (!fill_imm_operand_with_value(ASM_OPERAND(result), AOS_32_BITS, &address))
+ {
+ free(result);
+ return NULL;
+ }
+
+ return result;
+
+}
diff --git a/src/arch/x86/operand.h b/src/arch/x86/operand.h
index 42e0f56..04c0cb6 100644
--- a/src/arch/x86/operand.h
+++ b/src/arch/x86/operand.h
@@ -86,4 +86,12 @@ void x86_print_moffs_operand(const asm_x86_operand *, char *, size_t, AsmSyntax)
+/* ------------------------- OPERANDES D'ADRESSES RELATIVES ------------------------- */
+
+
+/* Crée une opérande à partir d'une adresse relative (8 bits). */
+asm_x86_operand *x86_create_rel8_operand_in_32b(uint64_t, const uint8_t *, off_t *, off_t);
+
+
+
#endif /* _ARCH_X86_OPERAND_H */
diff --git a/src/arch/x86/processor.c b/src/arch/x86/processor.c
index 7243064..e7ff753 100644
--- a/src/arch/x86/processor.c
+++ b/src/arch/x86/processor.c
@@ -194,8 +194,12 @@ AsmOperandSize switch_x86_operand_size(const asm_x86_processor *proc)
void x86_register_instructions(asm_x86_processor *proc)
{
+ register_opcode(proc->opcodes[X86_OP_SUB_R1632_RM1632], 0x66, 0x29, "sub", x86_read_instr_sub_r1632_to_rm1632);
+
register_opcode(proc->opcodes[X86_OP_XOR_REG1632], 0x00/*0x66*/, 0x31, "xor", read_instr_xor_with_reg1632);
+ register_opcode(proc->opcodes[X86_OP_CMP_RM1632_R1632], 0x66, 0x39, "cmp", x86_read_instr_cmp_rm1632_with_r1632);
+
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);
@@ -234,6 +238,10 @@ void x86_register_instructions(asm_x86_processor *proc)
register_opcode(proc->opcodes[X86_OP_PUSH_IMM1632], 0x66, 0x68, "push", read_instr_push_imm1632);
+ register_opcode_with_ext(proc->opcodes[X86_OP_CMP_RM8_IMM8], 0x00, 0x80, 7, "cmp", x86_read_instr_cmp_rm8_with_imm8);
+
+ register_opcode_with_ext(proc->opcodes[X86_OP_ADD_IMM1632_REG1632], 0x66, 0x81, 0, "add", x86_read_instr_add_imm1632_to_rm1632);
+
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);
@@ -241,6 +249,10 @@ void x86_register_instructions(asm_x86_processor *proc)
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_with_ext(proc->opcodes[X86_OP_CMP_RM1632_IMM8], 0x66, 0x83, 7, "cmp", x86_read_instr_cmp_rm1632_with_imm8);
+
+ register_opcode(proc->opcodes[X86_OP_JE_8], 0x00, 0x74, "je", read_instr_je_8);
+ register_opcode(proc->opcodes[X86_OP_JNE_8], 0x00, 0x75, "jne", read_instr_jne_8);
register_opcode(proc->opcodes[X86_OP_TEST_RM8], 0x00, 0x84, "test", read_instr_test_rm8);
register_opcode(proc->opcodes[X86_OP_TEST_RM1632], 0x66, 0x85, "test", read_instr_test_rm1632);
@@ -253,8 +265,10 @@ void x86_register_instructions(asm_x86_processor *proc)
register_opcode(proc->opcodes[X86_OP_NOP], 0x00, 0x90, "nop", read_instr_nop);
- register_opcode(proc->opcodes[X86_OP_MOV_MOFFS_TO_AL], 0x66, 0xa0, "mov", read_instr_mov_moffs8_to_al);
+ register_opcode(proc->opcodes[X86_OP_MOV_MOFFS_TO_AL], 0x00, 0xa0, "mov", read_instr_mov_moffs8_to_al);
register_opcode(proc->opcodes[X86_OP_MOV_MOFFS_TO_E_AX], 0x66, 0xa1, "mov", read_instr_mov_moffs1632_to_e_ax);
+ register_opcode(proc->opcodes[X86_OP_MOV_AL_TO_MOFFS], 0x00, 0xa2, "mov", read_instr_mov_al_to_moffs8);
+ register_opcode(proc->opcodes[X86_OP_MOV_E_AX_TO_MOFFS], 0x66, 0xa3, "mov", read_instr_mov_e_ax_to_moffs1632);
register_opcode(proc->opcodes[X86_OP_TEST_AL], 0x00, 0xa8, "test", read_instr_test_al);
register_opcode(proc->opcodes[X86_OP_TEST_E_AX], 0x66, 0xa9, "test", read_instr_test_e_ax);
@@ -268,8 +282,11 @@ void x86_register_instructions(asm_x86_processor *proc)
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_with_ext(proc->opcodes[X86_OP_SAR_RM1632_IMM8], 0x66, 0xc1, 7, "sar", x86_read_instr_sar_rm1632_with_imm8);
+
register_opcode(proc->opcodes[X86_OP_RET], 0x00, 0xc3, "ret", read_instr_ret);
+ register_opcode(proc->opcodes[X86_OP_MOV_IMM8_TO_RM8], 0x00, 0xc6, "mov", read_instr_mov_imm8_to_rm8);
register_opcode(proc->opcodes[X86_OP_MOV_TO_CONTENT1632], 0x66, 0xc7, "mov", read_instr_mov_to_content_1632);
register_opcode(proc->opcodes[X86_OP_LEAVE], 0x00, 0xc9, "leave", read_instr_leave);
@@ -279,9 +296,12 @@ void x86_register_instructions(asm_x86_processor *proc)
register_opcode(proc->opcodes[X86_OP_CALL], 0x00, 0xe8, "call", read_instr_call);
+ register_opcode(proc->opcodes[X86_OP_JMP_8], 0x00, 0xeb, "jmp", read_instr_jmp_8);
+
register_opcode(proc->opcodes[X86_OP_HLT], 0x00, 0xf4, "hlt", read_instr_hlt);
- register_opcode(proc->opcodes[X86_OP_PUSH_CONTENT], 0x66, 0xff, "push", read_instr_push_content);
+ register_opcode_with_ext(proc->opcodes[X86_OP_CALL_RM1632], 0x66, 0xff, 2, "call", x86_read_instr_call_rm1632);
+ register_opcode_with_ext(proc->opcodes[X86_OP_PUSH_CONTENT], 0x66, 0xff, 6, "push", read_instr_push_content);
}