summaryrefslogtreecommitdiff
path: root/src/arch/x86/operand.c
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2009-05-17 22:59:55 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2009-05-17 22:59:55 (GMT)
commit4d0ff0c23862c242d533d9b2d34e8812ef99ad61 (patch)
tree3b8504b8d3946a8bc9a702b819138ab1e5501be6 /src/arch/x86/operand.c
parent96cb6971ee3ca529958b8cb1e8e55a6eb4e60eae (diff)
Used only the new format of processor/instructions/operands for x86.
git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@64 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a
Diffstat (limited to 'src/arch/x86/operand.c')
-rw-r--r--src/arch/x86/operand.c1458
1 files changed, 498 insertions, 960 deletions
diff --git a/src/arch/x86/operand.c b/src/arch/x86/operand.c
index 38e1468..1424b3e 100644
--- a/src/arch/x86/operand.c
+++ b/src/arch/x86/operand.c
@@ -29,1315 +29,868 @@
#include <stdio.h>
+#include "registers.h"
+#include "../immediate.h"
#include "../operand.h"
#include "../operand-int.h"
+#include "../../common/extstr.h"
-#define MAX(a, b) ((a) > (b) ? (a) : (b))
+/* ---------------------- COQUILLE VIDE POUR LES OPERANDES X86 ---------------------- */
-
-/* Liste des registres 8 bits */
-typedef enum _X868bRegister
+/* Définition d'un opérande de la x86 (instance) */
+struct _GX86Operand
{
- X86_REG8_AL = 0, /* Registre AL */
- X86_REG8_CL = 1, /* Registre AL */
- X86_REG8_DL = 2, /* Registre AL */
- X86_REG8_BL = 3, /* Registre AL */
- X86_REG8_AH = 4, /* Registre AH */
- X86_REG8_CH = 5, /* Registre AH */
- X86_REG8_DH = 6, /* Registre AH */
- X86_REG8_BH = 7, /* Registre AH */
+ GArchOperand parent; /* Instance parente */
- X86_REG8_NONE /* Aucun registre */
+};
-} X868bRegister;
-/* Liste des registres 16 bits */
-typedef enum _X8616bRegister
+/* Définition d'un opérande de la x86 (classe) */
+struct _GX86OperandClass
{
- X86_REG16_AX = 0, /* Registre AX */
- X86_REG16_CX = 1, /* Registre AX */
- X86_REG16_DX = 2, /* Registre AX */
- X86_REG16_BX = 3, /* Registre AX */
- X86_REG16_SP = 4, /* Registre SP */
- X86_REG16_BP = 5, /* Registre BP */
- X86_REG16_SI = 6, /* Registre SI */
- X86_REG16_DI = 7, /* Registre DI */
+ GArchOperandClass parent; /* Classe parente */
- X86_REG16_NONE /* Aucun registre */
+};
-} X8616bRegister;
-/* Liste des registres 32 bits */
-typedef enum _X8632bRegister
-{
- X86_REG32_EAX = 0, /* Registre EAX */
- X86_REG32_ECX = 1, /* Registre EAX */
- X86_REG32_EDX = 2, /* Registre EAX */
- X86_REG32_EBX = 3, /* Registre EAX */
- X86_REG32_ESP = 4, /* Registre ESP */
- X86_REG32_EBP = 5, /* Registre EBP */
- X86_REG32_ESI = 6, /* Registre ESI */
- X86_REG32_EDI = 7, /* Registre EDI */
+/* Initialise la classe des opérandes x86 de base. */
+static void g_x86_operand_class_init(GX86OperandClass *);
- X86_REG32_NONE /* Aucun registre */
+/* Initialise une instance d'opérande de base pour la x86. */
+static void g_x86_operand_init(GX86Operand *);
-} X8632bRegister;
-/* Registre X86 */
-typedef union _x86_register
-{
- X868bRegister reg8; /* Registre 8 bits */
- X8616bRegister reg16; /* Registre 16 bits */
- X8632bRegister reg32; /* Registre 32 bits */
+/* ------------------------ OPERANDES VISANT UN REGISTRE X86 ------------------------ */
+
-} x86_register;
+/* Définition d'un opérande visant un registre x86 (instance) */
+struct _GX86RegisterOperand
+{
+ GX86Operand parent; /* Instance parente */
+ x86_register *reg; /* Registre représenté */
+};
-/* Définition d'une opérande x86 */
-struct _asm_x86_operand
+/* Définition d'un opérande visant un registre x86 (classe) */
+struct _GX86RegisterOperandClass
{
- asm_operand base; /* A laisser en premier */
+ GX86OperandClass parent; /* Classe parente */
- x86_register rindex; /* Registre servant d'indice */
+};
- bool content; /* Contenu d'un registre */
- uint8_t scale; /* Puissance de deux */
- x86_register rbase; /* Registre de base */
- asm_operand *displacement; /* Décallage supplémentaire */
+/* Initialise la classe des opérandes de registre x86. */
+static void g_x86_register_operand_class_init(GX86RegisterOperandClass *);
-};
+/* Initialise une instance d'opérande de registre x86. */
+static void g_x86_register_operand_init(GX86RegisterOperand *);
+/* Traduit un opérande en version humainement lisible. */
+static char *g_x86_register_operand_get_text(const GX86RegisterOperand *, const exe_format *, AsmSyntax);
-#define NULL ((void *)0)
+/* ----------------------- OPERANDES COMPLEXES DE TYPE MOD/RM ----------------------- */
-/* Récupère l'indentifiant interne d'un registre. */
-bool get_x86_register(x86_register *, AsmOperandSize, uint8_t);
+/* Définition d'un opérande x86 de type ModRM (instance) */
+struct _GX86ModRMOperand
+{
+ GX86Operand parent; /* Instance parente */
+ uint8_t scale; /* Puissance de deux */
+ x86_register *index; /* Registre servant d'indice */
+ x86_register *base; /* Registre de base */
+ GImmOperand *displacement; /* Décallage supplémentaire */
-/* Traduit une opérande de registre en texte. */
-void _x86_print_reg_operand(const x86_register *reg, AsmOperandSize, char *, size_t, AsmSyntax);
+};
+/* Définition d'un opérande x86 de type ModRM (classe) */
+struct _GX86ModRMOperandClass
+{
+ GX86OperandClass parent; /* Classe parente */
+};
-/* Crée une opérande renvoyant vers un registre 16 ou 32 bits. */
-asm_x86_operand *x86_create_r1632_operand_from_opcode(uint8_t, bool, uint8_t);
+/* Initialise la classe des opérandes x86 de type ModRM. */
+static void g_x86_mod_rm_operand_class_init(GX86ModRMOperandClass *);
+/* Initialise une instance d'opérande x86 de type ModRM. */
+static void g_x86_mod_rm_operand_init(GX86ModRMOperand *);
+/* Traduit un opérande en version humainement lisible. */
+static char *g_x86_mod_rm_operand_get_text(const GX86ModRMOperand *, const exe_format *, AsmSyntax);
-/******************************************************************************
-* *
-* Paramètres : - *
-* *
-* Description : Crée une opérande vierge pour x86. *
-* *
-* Retour : Opérande nouvellement créée. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
+/* ------------------------- OPERANDES D'ADRESSES RELATIVES ------------------------- */
-asm_x86_operand *create_new_x86_operand(void)
+
+/* Définition d'un opérande x86 d'adresse relative (instance) */
+struct _GX86RelativeOperand
{
- asm_x86_operand *result; /* Structure à retourner */
+ GX86Operand parent; /* Instance parente */
- result = (asm_x86_operand *)calloc(1, sizeof(asm_x86_operand));
+ GImmOperand *immediate; /* Adresse visée reconstituée */
- result->scale = 0;
- result->rbase.reg32 = X86_REG32_NONE;
+};
- return result;
+/* Définition d'un opérande x86 d'adresse relative (classe) */
+struct _GX86RelativeOperandClass
+{
+ GX86OperandClass parent; /* Classe parente */
-}
+};
+/* Initialise la classe des opérandes x86 d'adresse relative. */
+static void g_x86_relative_operand_class_init(GX86RelativeOperandClass *);
+/* Initialise une instance d'opérande x86 d'adresse relative. */
+static void g_x86_relative_operand_init(GX86RelativeOperand *);
+/* Traduit un opérande en version humainement lisible. */
+static char *g_x86_relative_operand_get_text(const GX86RelativeOperand *, const exe_format *, AsmSyntax);
-/******************************************************************************
-* *
-* Paramètres : reg = registre à définir. [OUT] *
-* size = indique la taille du registre. *
-* value = valeur correspondant au registre. *
-* *
-* Description : Récupère l'indentifiant interne d'un registre. *
-* *
-* Retour : true si la définition est opérée, false sinon. *
-* *
-* Remarques : -  *
-* *
-******************************************************************************/
+/* ------------------------ OPERANDES D'EMPLACEMENTS MEMOIRE ------------------------ */
+
-bool get_x86_register(x86_register *reg, AsmOperandSize size, uint8_t value)
+/* Définition d'un opérande visant un emplacement mémoire x86 (instance) */
+struct _GX86MOffsOperand
{
- switch (size)
- {
- case AOS_8_BITS:
- switch (value)
- {
- case 0 ... 7:
- reg->reg8 = (X868bRegister)value;
- break;
- default:
- return false;
- break;
- }
- break;
+ GX86Operand parent; /* Instance parente */
- case AOS_16_BITS:
- switch (value)
- {
- case 0 ... 7:
- reg->reg16 = (X8616bRegister)value;
- break;
- default:
- return false;
- break;
- }
- break;
+ GImmOperand *offset; /* Adresse mémoire visée */
- case AOS_32_BITS:
- switch (value)
- {
- case 0 ... 7:
- reg->reg32 = (X8632bRegister)value;
- break;
- default:
- return false;
- break;
- }
- break;
+};
- case AOS_64_BITS:
- return false;
- break;
+/* Définition d'un opérande visant un emplacement mémoire x86 (classe) */
+struct _GX86MOffsOperandClass
+{
+ GX86OperandClass parent; /* Classe parente */
- }
+};
- return true;
-}
+/* Initialise la classe des opérandes d'emplacement mémoire x86. */
+static void g_x86_moffs_operand_class_init(GX86MOffsOperandClass *);
+
+/* Initialise une instance d'opérande d'emplacement mémoire x86. */
+static void g_x86_moffs_operand_init(GX86MOffsOperand *);
+
+/* Traduit un opérande en version humainement lisible. */
+static char *g_x86_moffs_operand_get_text(const GX86MOffsOperand *, const exe_format *, AsmSyntax);
+/* ---------------------------------------------------------------------------------- */
+/* COQUILLE VIDE POUR LES OPERANDES X86 */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini par la GLib pour un opérande de x86. */
+G_DEFINE_TYPE(GX86Operand, g_x86_operand, G_TYPE_ARCH_OPERAND);
/******************************************************************************
* *
-* Paramètres : data = donnée à analyser. *
-* is_reg32 = indique si le registre est un registre 32 bits. *
-* base = valeur du premier registre. *
+* Paramètres : klass = classe à initialiser. *
* *
-* Description : Crée une opérande renvoyant vers un registre 16 ou 32 bits. *
+* Description : Initialise la classe des opérandes x86 de base. *
* *
-* Retour : Opérande mise en place ou NULL. *
+* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
-asm_x86_operand *x86_create_reg1632_operand(uint8_t data, bool is_reg32, uint8_t base)
+static void g_x86_operand_class_init(GX86OperandClass *klass)
{
- asm_x86_operand *result; /* Registre à retourner */
-
- result = create_new_x86_operand();
-
- ASM_OPERAND(result)->type = AOT_REG;
- ASM_OPERAND(result)->size = (is_reg32 ? AOS_32_BITS : AOS_16_BITS);
-
- if (!get_x86_register(&result->rindex, ASM_OPERAND(result)->size, data - base))
- {
- free(result);
- return NULL;
- }
-
- return result;
}
/******************************************************************************
* *
-* 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. *
+* Paramètres : operand = instance à initialiser. *
* *
-* Description : Crée une opérande renvoyant vers un registre 16 ou 32 bits. *
+* Description : Initialise une instance d'opérande de registre x86. *
* *
-* Retour : Opérande mise en place ou NULL. *
+* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
-asm_x86_operand *x86_create_reg1632_operand_from_modrm(uint8_t data, bool is_reg32, bool first)
+static void g_x86_operand_init(GX86Operand *operand)
{
- asm_x86_operand *result; /* Registre à retourner */
- uint8_t reg; /* Transcription du registre */
- if (first) reg = data & 0x07;
- else reg = (data & 0x38) >> 3;
+}
- result = create_new_x86_operand();
- ASM_OPERAND(result)->type = AOT_REG;
- ASM_OPERAND(result)->size = (is_reg32 ? AOS_32_BITS : AOS_16_BITS);
- if (!get_x86_register(&result->rindex, ASM_OPERAND(result)->size, reg))
- {
- free(result);
- return NULL;
- }
+/* ---------------------------------------------------------------------------------- */
+/* OPERANDES VISANT UN REGISTRE X86 */
+/* ---------------------------------------------------------------------------------- */
- return result;
-}
+/* Indique le type défini par la GLib pour un opérande de registre x86. */
+G_DEFINE_TYPE(GX86RegisterOperand, g_x86_register_operand, G_TYPE_X86_OPERAND);
/******************************************************************************
* *
-* Paramètres : data = flux de données à analyser. *
-* pos = position courante dans ce flux. [OUT] *
-* len = taille totale des données à analyser. *
-* is_reg32 = indique si le registre est un registre 32 bits. *
-* first = indique la partie du ModR/M à traiter. *
+* Paramètres : klass = classe à initialiser. *
* *
-* Description : Crée une opérande renvoyant vers un contenu 16 ou 32 bits. *
+* Description : Initialise la classe des opérandes de registre x86. *
* *
-* Retour : Opérande mise en place ou NULL. *
+* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
-asm_x86_operand *x86_create_content1632_operand(const uint8_t *data, off_t *pos, off_t len, bool is_reg32, bool first)
+static void g_x86_register_operand_class_init(GX86RegisterOperandClass *klass)
{
- asm_x86_operand *result; /* Registre à retourner */
- uint8_t mod; /* Modificateur présent */
- /* Pas de contenu */
- mod = (data[*pos] & 0xc0);
- if (mod == 0xc0) return NULL;
-
- result = x86_create_reg1632_operand_from_modrm(data[*pos], is_reg32, first);
- if (result == NULL) return NULL;
-
- result->content = true;
-
- (*pos)++;
+}
- /* Vieille astuce de l'emplacement mémoire fixe ? */
- if (result->rindex.reg32 == X86_REG32_EBP && mod == 0x00)
- {
- free(result);
- result = create_new_x86_operand();
- if (!fill_imm_operand(ASM_OPERAND(result), AOS_32_BITS/* FIXME ? */, data, pos, len))
- {
- (*pos)--;
- free(result);
- return NULL;
- }
+/******************************************************************************
+* *
+* Paramètres : operand = instance à initialiser. *
+* *
+* Description : Initialise une instance d'opérande de registre x86. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
- return result;
+static void g_x86_register_operand_init(GX86RegisterOperand *operand)
+{
+ GArchOperand *parent; /* Instance parente */
- }
+ parent = G_ARCH_OPERAND(operand);
- /* A la recherche d'un SIB */
- if (result->rindex.reg32 == X86_REG32_ESP)
- {
- if (!get_x86_register(&result->rbase, ASM_OPERAND(result)->size, data[*pos] & 0x07))
- {
- (*pos)--;
- free(result);
- return NULL;
- }
+ parent->get_text = (get_operand_text_fc)g_x86_register_operand_get_text;
- if (!get_x86_register(&result->rindex, ASM_OPERAND(result)->size, (data[*pos] & 0x38) >> 3))
- {
- (*pos)--;
- free(result);
- return NULL;
- }
+}
- result->scale = ((data[*pos] & 0xc0) >> 6);
- if (result->rindex.reg32 == X86_REG32_ESP)
- {
- result->rindex.reg32 = result->rbase.reg32;
- result->rbase.reg32 = X86_REG32_NONE;
- }
+/******************************************************************************
+* *
+* Paramètres : data = flux de données à analyser. *
+* pos = position courante dans ce flux. [OUT] *
+* len = taille totale des données à analyser. *
+* size = taille de l'opérande, et donc du registre. *
+* base = indice du premier registre. *
+* *
+* Description : Crée un opérande visant un registre X86. *
+* *
+* Retour : Opérande mis en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
- (*pos)++;
+GArchOperand *g_x86_register_operand_new_from_opcode(const bin_t *data, off_t *pos, off_t len, AsmOperandSize size, bin_t base)
+{
+ GX86RegisterOperand *result; /* Structure à retourner */
+ x86_register *reg; /* Registre lu */
- }
+ reg = get_x86_register(size, data[*pos] - base);
- /* Décallage supplémentaire ? */
- switch (mod)
+ if (reg != NULL)
{
- case 0x00:
- if (result->rbase.reg32 == X86_REG32_EBP)
- {
- result->rbase.reg32 = X86_REG32_NONE;
+ (*pos)++;
- result->displacement = create_new_x86_operand();
- if (!fill_imm_operand(ASM_OPERAND(result->displacement), ASM_OPERAND(result)->size, data, pos, len))
- {
- (*pos) -= 2;
- free(result->displacement);
- free(result);
- return NULL;
- }
+ result = g_object_new(G_TYPE_X86_REGISTER_OPERAND, NULL);
- }
- break;
-
- case 0x40:
- result->displacement = create_new_x86_operand();
- if (!fill_imm_operand(ASM_OPERAND(result->displacement), AOS_8_BITS_SIGNED, data, pos, len))
- {
- (*pos) -= 2;
- free(result->displacement);
- free(result);
- return NULL;
- }
- break;
-
- case 0x80:
- result->displacement = create_new_x86_operand();
- if (!fill_imm_operand(ASM_OPERAND(result->displacement), AOS_32_BITS_SIGNED, data, pos, len))
- {
- (*pos) -= 2;
- free(result->displacement);
- free(result);
- return NULL;
- }
- break;
+ result->reg = reg;
}
+ else result = NULL;
- return result;
+ return G_ARCH_OPERAND(result);
}
-
-
-
/******************************************************************************
* *
-* Paramètres : data = donnée à analyser. *
+* Paramètres : data = flux de données à analyser. *
+* pos = position courante dans ce flux. [OUT] *
+* len = taille totale des données à analyser. *
+* size = taille de l'opérande, et donc du registre. *
* first = indique la partie du ModR/M à traiter. *
* *
-* Description : Crée une opérande renvoyant vers un registre 8 bits. *
+* Description : Crée un opérande visant un registre X86. *
* *
-* Retour : Opérande mise en place ou NULL. *
+* Retour : Opérande mis en place. *
* *
* Remarques : - *
* *
******************************************************************************/
-asm_x86_operand *x86_create_r8_operand(uint8_t data, bool first)
+GArchOperand *g_x86_register_operand_new_from_mod_rm(const bin_t *data, off_t *pos, off_t len, AsmOperandSize size, bool first)
{
- asm_x86_operand *result; /* Registre à retourner */
- uint8_t reg; /* Transcription du registre */
+ GX86RegisterOperand *result; /* Structure à retourner */
+ bin_t index; /* Registre lu */
+ x86_register *reg; /* Registre créé */
- if (first) reg = data & 0x07;
- else reg = (data & 0x38) >> 3;
+ if (first) index = data[*pos] & 0x07;
+ else index = (data[*pos] & 0x38) >> 3;
- result = create_new_x86_operand();
+ reg = get_x86_register(size, index);
- ASM_OPERAND(result)->type = AOT_REG;
- ASM_OPERAND(result)->size = AOS_8_BITS;
-
- if (!get_x86_register(&result->rindex, ASM_OPERAND(result)->size, reg))
+ if (reg != NULL)
{
- free(result);
- return NULL;
+ (*pos)++;
+
+ result = g_object_new(G_TYPE_X86_REGISTER_OPERAND, NULL);
+
+ result->reg = reg;
+
}
+ else result = NULL;
- return result;
+ return G_ARCH_OPERAND(result);
}
/******************************************************************************
* *
-* Paramètres : data = flux de données à analyser. *
-* pos = position courante dans ce flux. [OUT] *
-* len = taille totale des données à analyser. *
+* Paramètres : index = indice du registre visé. *
+* size = taille de l'opérande, et donc du registre. *
* *
-* Description : Crée une opérande à partir d'un registre/une mémoire 8 bits. *
+* Description : Crée un opérande visant un registre X86 donnée. *
* *
-* Retour : Opérande mise en place ou NULL. *
+* Retour : Opérande mis en place. *
* *
* Remarques : - *
* *
******************************************************************************/
-asm_x86_operand *x86_create_rm8_operand(const uint8_t *data, off_t *pos, off_t len, ...)
+GArchOperand *g_x86_register_operand_new_from_index(bin_t index, AsmOperandSize size)
{
- asm_x86_operand *result; /* Registre à retourner */
- uint8_t mod; /* Modificateur présent */
-
- /* Registre simple... */
+ GX86RegisterOperand *result; /* Structure à retourner */
+ x86_register *reg; /* Registre lu */
- result = x86_create_r8_operand(data[*pos], true);
- if (result == NULL) return NULL;
+ reg = get_x86_register(size, index);
- mod = (data[*pos] & 0xc0);
-
- (*pos)++;
-
- if (mod == 0xc0) return result;
-
- result->content = true;
-
- /* Vieille astuce de l'emplacement mémoire fixe ? */
- if (result->rindex.reg8 == X86_REG8_CH && mod == 0x00)
+ if (reg != NULL)
{
- free(result);
+ result = g_object_new(G_TYPE_X86_REGISTER_OPERAND, NULL);
- result = create_new_x86_operand();
- if (!fill_imm_operand(ASM_OPERAND(result), AOS_32_BITS/* FIXME! 16/32 */, data, pos, len))
- {
- free(result);
- return NULL;
- }
-
- return result;
+ result->reg = reg;
}
+ else result = NULL;
- /* A la recherche d'un SIB */
- if (result->rindex.reg8 == X86_REG8_AH)
- {
- if (!get_x86_register(&result->rbase, ASM_OPERAND(result)->size, data[*pos] & 0x07))
- {
- free(result);
- return NULL;
- }
+ return G_ARCH_OPERAND(result);
- if (!get_x86_register(&result->rindex, ASM_OPERAND(result)->size, (data[*pos] & 0x38) >> 3))
- {
- free(result);
- return NULL;
- }
-
- result->scale = ((data[*pos] & 0xc0) >> 6);
+}
- if (result->rindex.reg8 == X86_REG8_AH)
- {
- result->rindex.reg8 = result->rbase.reg8;
- result->rbase.reg8 = X86_REG8_NONE;
- }
- (*pos)++;
+/******************************************************************************
+* *
+* Paramètres : operand = opérande à traiter. *
+* format = format du binaire manipulé. *
+* syntax = type de représentation demandée. *
+* *
+* Description : Traduit un opérande en version humainement lisible. *
+* *
+* Retour : Chaîne de caractères à libérer de la mémoire. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
- }
+static char *g_x86_register_operand_get_text(const GX86RegisterOperand *operand, const exe_format *format, AsmSyntax syntax)
+{
+ char *result; /* Chaîne à retourner */
- /* Décallage supplémentaire ? */
- switch (mod)
- {
- case 0x00:
- if (result->rbase.reg8 == X86_REG8_CH)
- {
- result->rbase.reg8 = X86_REG8_NONE;
+ result = x86_register_as_text(operand->reg, syntax);
- result->displacement = create_new_x86_operand();
- if (!fill_imm_operand(ASM_OPERAND(result->displacement), ASM_OPERAND(result)->size, data, pos, len))
- {
- free(result->displacement);
- free(result);
- return NULL;
- }
+ return result;
- }
- break;
+}
- case 0x40:
- result->displacement = create_new_x86_operand();
- if (!fill_imm_operand(ASM_OPERAND(result->displacement), AOS_8_BITS_SIGNED, data, pos, len))
- {
- free(result->displacement);
- free(result);
- return NULL;
- }
- break;
- case 0x80:
- result->displacement = create_new_x86_operand();
- if (!fill_imm_operand(ASM_OPERAND(result->displacement), AOS_32_BITS/* FIXME ! 16/32 */, data, pos, len))
- {
- free(result->displacement);
- free(result);
- return NULL;
- }
- break;
- }
+/* ---------------------------------------------------------------------------------- */
+/* OPERANDES COMPLEXES DE TYPE MOD/RM */
+/* ---------------------------------------------------------------------------------- */
- return result;
-}
+/* Indique le type défini par la GLib pour un opérande x86 de type ModRM. */
+G_DEFINE_TYPE(GX86ModRMOperand, g_x86_mod_rm_operand, G_TYPE_ARCH_OPERAND);
/******************************************************************************
* *
-* 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. *
+* Paramètres : klass = classe à initialiser. *
* *
-* Description : Crée une opérande renvoyant vers un registre 16 ou 32 bits. *
+* Description : Initialise la classe des opérandes x86 de type ModRM. *
* *
-* Retour : Opérande mise en place ou NULL. *
+* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
-asm_x86_operand *x86_create_r1632_operand(uint8_t data, bool is_reg32, bool first)
+static void g_x86_mod_rm_operand_class_init(GX86ModRMOperandClass *klass)
{
- asm_x86_operand *result; /* Registre à retourner */
- uint8_t reg; /* Transcription du registre */
-
- if (first) reg = data & 0x07;
- else reg = (data & 0x38) >> 3;
-
- result = create_new_x86_operand();
-
- ASM_OPERAND(result)->type = AOT_REG;
- ASM_OPERAND(result)->size = (is_reg32 ? AOS_32_BITS : AOS_16_BITS);
-
- if (!get_x86_register(&result->rindex, ASM_OPERAND(result)->size, reg))
- {
- free(result);
- return NULL;
- }
-
- return result;
}
/******************************************************************************
* *
-* Paramètres : data = donnée à analyser. *
-* is_reg32 = indique si le registre est un registre 32 bits. *
-* base = valeur du premier registre. *
+* Paramètres : operand = instance à initialiser. *
* *
-* Description : Crée une opérande renvoyant vers un registre 16 ou 32 bits. *
+* Description : Initialise une instance d'opérande x86 de type ModRM. *
* *
-* Retour : Opérande mise en place ou NULL. *
+* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
-asm_x86_operand *x86_create_r1632_operand_from_opcode(uint8_t data, bool is_reg32, uint8_t base)
+static void g_x86_mod_rm_operand_init(GX86ModRMOperand *operand)
{
- asm_x86_operand *result; /* Registre à retourner */
-
- result = create_new_x86_operand();
+ GArchOperand *parent; /* Instance parente */
- ASM_OPERAND(result)->type = AOT_REG;
- ASM_OPERAND(result)->size = (is_reg32 ? AOS_32_BITS : AOS_16_BITS);
+ parent = G_ARCH_OPERAND(operand);
- if (!get_x86_register(&result->rindex, ASM_OPERAND(result)->size, data - base))
- {
- free(result);
- return NULL;
- }
-
- return result;
+ parent->get_text = (get_operand_text_fc)g_x86_mod_rm_operand_get_text;
}
/******************************************************************************
* *
-* Paramètres : data = flux de données à analyser. *
-* pos = position courante dans ce flux. [OUT] *
-* len = taille totale des données à analyser. *
-* is_reg32 = indique si le registre est un registre 32 bits. *
+* Paramètres : data = flux de données à analyser. *
+* pos = position courante dans ce flux. [OUT] *
+* len = taille totale des données à analyser. *
+* size = taille de l'opérande, et donc du registre. *
* *
-* Description : Crée une opérande à partir d'un registre/une mémoire 16/32b. *
+* Description : Crée un opérande x86 de type ModRM. *
* *
-* Retour : Opérande mise en place ou NULL. *
+* Retour : Opérande mis en place. *
* *
* Remarques : - *
* *
******************************************************************************/
-asm_x86_operand *x86_create_rm1632_operand(const uint8_t *data, off_t *pos, off_t len, bool is_reg32, ...)
+GArchOperand *g_x86_mod_rm_operand_new(const bin_t *data, off_t *pos, off_t len, AsmOperandSize size)
{
- asm_x86_operand *result; /* Registre à retourner */
+ GX86ModRMOperand *result; /* Structure à retourner */
uint8_t mod; /* Modificateur présent */
-
- /* Registre simple... */
-
- result = x86_create_r1632_operand(data[*pos], is_reg32, true);
- if (result == NULL) return NULL;
+ x86_register *reg; /* Registre lu */
mod = (data[*pos] & 0xc0);
- (*pos)++;
+ if (mod == 0xc0)
+ return g_x86_register_operand_new_from_mod_rm(data, pos, len, size, true);
- if (mod == 0xc0) return result;
+ reg = get_x86_register(size, data[*pos] & 0x07);
+ if (reg == NULL) return NULL;
- result->content = true;
+ (*pos)++;
/* Vieille astuce de l'emplacement mémoire fixe ? */
- if (result->rindex.reg32 == X86_REG32_EBP && mod == 0x00)
- {
- free(result);
-
- result = create_new_x86_operand();
- if (!fill_imm_operand(ASM_OPERAND(result), AOS_32_BITS/* FIXME ? */, data, pos, len))
- {
- free(result);
- return NULL;
- }
+ if (is_x86_register_base_pointer(reg) && mod == 0x00)
+ return g_imm_operand_new_from_data(MDS_32_BITS/* FIXME */, data, pos, len, SRE_LITTLE);
- return result;
-
- }
+ result = g_object_new(G_TYPE_X86_MOD_RM_OPERAND, NULL);
/* A la recherche d'un SIB */
- if (result->rindex.reg32 == X86_REG32_ESP)
+ if (is_x86_register_stack_pointer(reg))
{
- if (!get_x86_register(&result->rbase, ASM_OPERAND(result)->size, data[*pos] & 0x07))
- {
- free(result);
- return NULL;
- }
+ free_x86_register(reg);
- if (!get_x86_register(&result->rindex, ASM_OPERAND(result)->size, (data[*pos] & 0x38) >> 3))
- {
- free(result);
- return NULL;
- }
+ result->base = get_x86_register(size, data[*pos] & 0x07);
+ if (result->base == NULL) goto gxmron_error;
+
+ result->index = get_x86_register(size, (data[*pos] & 0x38) >> 3);
+ if (result->base == NULL) goto gxmron_error;
result->scale = ((data[*pos] & 0xc0) >> 6);
- if (result->rindex.reg32 == X86_REG32_ESP)
+ if (is_x86_register_stack_pointer(result->index))
{
- result->rindex.reg32 = result->rbase.reg32;
- result->rbase.reg32 = X86_REG32_NONE;
+ result->index = result->base;
+ free_x86_register(result->base);
+ result->base = NULL;
}
(*pos)++;
}
+ else result->index = reg;
+
/* Décallage supplémentaire ? */
switch (mod)
{
case 0x00:
- if (result->rbase.reg32 == X86_REG32_EBP)
+ if (result->base != NULL && is_x86_register_base_pointer(result->base))
{
- result->rbase.reg32 = X86_REG32_NONE;
+ free_x86_register(result->base);
+ result->base = NULL;
- result->displacement = create_new_x86_operand();
- if (!fill_imm_operand(ASM_OPERAND(result->displacement), ASM_OPERAND(result)->size, data, pos, len))
- {
- free(result->displacement);
- free(result);
- return NULL;
- }
+ result->displacement = g_imm_operand_new_from_data(size/* FIXME : !convert mds/aos */, data, pos, len, SRE_LITTLE);
+ if (result->displacement == NULL) goto gxmron_error;
}
break;
case 0x40:
- result->displacement = create_new_x86_operand();
- if (!fill_imm_operand(ASM_OPERAND(result->displacement), AOS_8_BITS_SIGNED, data, pos, len))
- {
- free(result->displacement);
- free(result);
- return NULL;
- }
+ result->displacement = g_imm_operand_new_from_data(MDS_8_BITS_SIGNED, data, pos, len, SRE_LITTLE);
+ if (result->displacement == NULL) goto gxmron_error;
break;
case 0x80:
- result->displacement = create_new_x86_operand();
- if (!fill_imm_operand(ASM_OPERAND(result->displacement), AOS_32_BITS_SIGNED, data, pos, len))
- {
- free(result->displacement);
- free(result);
- return NULL;
- }
+ result->displacement = g_imm_operand_new_from_data(MDS_32_BITS_SIGNED/* FIXME ! 16/32 */, data, pos, len, SRE_LITTLE);
+ if (result->displacement == NULL) goto gxmron_error;
break;
}
- return result;
-
-}
-
-
-
-
-
-
-
-
+ return G_ARCH_OPERAND(result);
+ gxmron_error:
-
-
-/******************************************************************************
-* *
-* Paramètres : reg = registre à imprimer. *
-* size = indique la taille du registre. *
-* buffer = tampon de sortie mis à disposition. [OUT] *
-* len = taille de ce tampon. *
-* syntax = type de représentation demandée. *
-* *
-* Description : Traduit une opérande de registre en texte. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-void _x86_print_reg_operand(const x86_register *reg, AsmOperandSize size, char *buffer, size_t len, AsmSyntax syntax)
-{
- switch (syntax)
- {
- case ASX_INTEL:
- switch (size)
- {
- case AOS_8_BITS:
- switch (reg->reg8)
- {
- case X86_REG8_AL:
- snprintf(buffer, len, "al");
- break;
- case X86_REG8_CL:
- snprintf(buffer, len, "cl");
- break;
- case X86_REG8_DL:
- snprintf(buffer, len, "dl");
- break;
- case X86_REG8_BL:
- snprintf(buffer, len, "bl");
- break;
- case X86_REG8_AH:
- snprintf(buffer, len, "ah");
- break;
- case X86_REG8_CH:
- snprintf(buffer, len, "ch");
- break;
- case X86_REG8_DH:
- snprintf(buffer, len, "dh");
- break;
- case X86_REG8_BH:
- snprintf(buffer, len, "bh");
- break;
- case X86_REG8_NONE:
- /* Ne devrait jamais arriver */
- break;
- }
- break;
-
- case AOS_16_BITS:
- switch (reg->reg16)
- {
- case X86_REG16_AX:
- snprintf(buffer, len, "ax");
- break;
- case X86_REG16_CX:
- snprintf(buffer, len, "cx");
- break;
- case X86_REG16_DX:
- snprintf(buffer, len, "dx");
- break;
- case X86_REG16_BX:
- snprintf(buffer, len, "bx");
- break;
- case X86_REG16_SP:
- snprintf(buffer, len, "sp");
- break;
- case X86_REG16_BP:
- snprintf(buffer, len, "bp");
- break;
- case X86_REG16_SI:
- snprintf(buffer, len, "si");
- break;
- case X86_REG16_DI:
- snprintf(buffer, len, "di");
- break;
- case X86_REG16_NONE:
- /* Ne devrait jamais arriver */
- break;
- }
- break;
-
- case AOS_32_BITS:
- switch (reg->reg32)
- {
- case X86_REG32_EAX:
- snprintf(buffer, len, "eax");
- break;
- case X86_REG32_ECX:
- snprintf(buffer, len, "ecx");
- break;
- case X86_REG32_EDX:
- snprintf(buffer, len, "edx");
- break;
- case X86_REG32_EBX:
- snprintf(buffer, len, "ebx");
- break;
- case X86_REG32_ESP:
- snprintf(buffer, len, "esp");
- break;
- case X86_REG32_EBP:
- snprintf(buffer, len, "ebp");
- break;
- case X86_REG32_ESI:
- snprintf(buffer, len, "esi");
- break;
- case X86_REG32_EDI:
- snprintf(buffer, len, "edi");
- break;
- case X86_REG32_NONE:
- /* Ne devrait jamais arriver */
- break;
- }
- break;
-
- case AOS_64_BITS:
- break;
-
- }
- break;
-
- case ASX_ATT:
- switch (size)
- {
- case AOS_8_BITS:
- switch (reg->reg8)
- {
- case X86_REG8_AL:
- snprintf(buffer, len, "%%al");
- break;
- case X86_REG8_CL:
- snprintf(buffer, len, "%%cl");
- break;
- case X86_REG8_DL:
- snprintf(buffer, len, "%%dl");
- break;
- case X86_REG8_BL:
- snprintf(buffer, len, "%%bl");
- break;
- case X86_REG8_AH:
- snprintf(buffer, len, "%%ah");
- break;
- case X86_REG8_CH:
- snprintf(buffer, len, "%%ch");
- break;
- case X86_REG8_DH:
- snprintf(buffer, len, "%%dh");
- break;
- case X86_REG8_BH:
- snprintf(buffer, len, "%%bh");
- break;
- case X86_REG8_NONE:
- /* Ne devrait jamais arriver */
- break;
- }
- break;
-
- case AOS_16_BITS:
- switch (reg->reg16)
- {
- case X86_REG16_AX:
- snprintf(buffer, len, "%%ax");
- break;
- case X86_REG16_CX:
- snprintf(buffer, len, "%%cx");
- break;
- case X86_REG16_DX:
- snprintf(buffer, len, "%%dx");
- break;
- case X86_REG16_BX:
- snprintf(buffer, len, "%%bx");
- break;
- case X86_REG16_SP:
- snprintf(buffer, len, "%%sp");
- break;
- case X86_REG16_BP:
- snprintf(buffer, len, "%%bp");
- break;
- case X86_REG16_SI:
- snprintf(buffer, len, "%%si");
- break;
- case X86_REG16_DI:
- snprintf(buffer, len, "%%di");
- break;
- case X86_REG16_NONE:
- /* Ne devrait jamais arriver */
- break;
- }
- break;
-
- case AOS_32_BITS:
- switch (reg->reg32)
- {
- case X86_REG32_EAX:
- snprintf(buffer, len, "%%eax");
- break;
- case X86_REG32_ECX:
- snprintf(buffer, len, "%%ecx");
- break;
- case X86_REG32_EDX:
- snprintf(buffer, len, "%%edx");
- break;
- case X86_REG32_EBX:
- snprintf(buffer, len, "%%ebx");
- break;
- case X86_REG32_ESP:
- snprintf(buffer, len, "%%esp");
- break;
- case X86_REG32_EBP:
- snprintf(buffer, len, "%%ebp");
- break;
- case X86_REG32_ESI:
- snprintf(buffer, len, "%%esi");
- break;
- case X86_REG32_EDI:
- snprintf(buffer, len, "%%edi");
- break;
- case X86_REG32_NONE:
- /* Ne devrait jamais arriver */
- break;
- }
- break;
-
- case AOS_64_BITS:
- break;
-
- }
- break;
-
- }
+ /* FIXME free(result);*/
+ return NULL;
}
/******************************************************************************
* *
-* Paramètres : operand = instruction à traiter. *
-* buffer = tampon de sortie mis à disposition. [OUT] *
-* len = taille de ce tampon. *
+* Paramètres : operand = opérande à traiter. *
+* format = format du binaire manipulé. *
* syntax = type de représentation demandée. *
* *
-* Description : Traduit une opérande de registre en texte. *
+* Description : Traduit un opérande en version humainement lisible. *
* *
-* Retour : - *
+* Retour : Chaîne de caractères à libérer de la mémoire. *
* *
* Remarques : - *
* *
******************************************************************************/
-void x86_print_reg_operand(const asm_x86_operand *operand, char *buffer, size_t len, AsmSyntax syntax)
+static char *g_x86_mod_rm_operand_get_text(const GX86ModRMOperand *operand, const exe_format *format, AsmSyntax syntax)
{
- size_t pos; /* Position de traitement */
+ char *result; /* Chaîne à retourner */
+ char *tmp; /* Chaîne de registre */
switch (syntax)
{
case ASX_INTEL:
- if (operand->content)
- {
- strcpy(buffer, "[");
+ result = (char *)calloc(1 + 10 + 2, sizeof(char));
- if (operand->scale > 0)
- snprintf(&buffer[1], len - 1, "%d*", (int)pow(2, operand->scale));
+ strcpy(result, "[");
- pos = strlen(buffer);
+ if (operand->scale > 0)
+ snprintf(&result[1], 12, "%d*", (int)pow(2, operand->scale));
- }
- else pos = 0;
+ tmp = x86_register_as_text(operand->index, syntax);
+ result = stradd(result, tmp);
+ free(tmp);
-
- _x86_print_reg_operand(&operand->rindex, ASM_OPERAND(operand)->size, &buffer[pos], len - pos, syntax);
-
- if (operand->rbase.reg32 != X86_REG32_NONE)
+ if (operand->base != NULL)
{
- strcat(buffer, "+"); /* TODO: n */
- pos = strlen(buffer);
+ result = stradd(result, "+");
- _x86_print_reg_operand(&operand->rbase, ASM_OPERAND(operand)->size, &buffer[pos], len - pos, syntax);
+ tmp = x86_register_as_text(operand->base, syntax);
+ result = stradd(result, tmp);
+ free(tmp);
}
-
if (operand->displacement != NULL)
{
- if (is_imm_operand_negative(operand->displacement)) strcat(buffer, "-");
- else strcat(buffer, "+");
- pos = strlen(buffer);
+ if (g_imm_operand_is_negative(operand->displacement)) result = stradd(result, "-");
+ else result = stradd(result, "+");
- print_imm_operand(operand->displacement, &buffer[pos], len - pos, syntax);
+ tmp = g_arch_operand_get_text(G_ARCH_OPERAND(operand->displacement), format, syntax);
+ result = stradd(result, tmp);
+ free(tmp);
}
-
-
- if (operand->content) strcat(buffer, "]");
+ result = stradd(result, "]");
break;
case ASX_ATT:
+ result = strdup("[modRM]");
break;
}
-}
+ return result;
+}
+/* ---------------------------------------------------------------------------------- */
+/* OPERANDES D'ADRESSES RELATIVES */
+/* ---------------------------------------------------------------------------------- */
+/* Indique le type défini par la GLib pour un opérande x86 d'adresse relative. */
+G_DEFINE_TYPE(GX86RelativeOperand, g_x86_relative_operand, G_TYPE_X86_OPERAND);
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des opérandes x86 d'adresse relative. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+static void g_x86_relative_operand_class_init(GX86RelativeOperandClass *klass)
+{
-/* ---------------------------------------------------------------------------------- */
-/* OPERANDES D'EMPLACEMENTS MEMOIRE */
-/* ---------------------------------------------------------------------------------- */
+}
/******************************************************************************
* *
-* Paramètres : data = flux de données à analyser. *
-* pos = position courante dans ce flux. [OUT] *
-* len = taille totale des données à analyser. *
+* Paramètres : operand = instance à initialiser. *
* *
-* Description : Crée une opérande à partir d'un emplacement mémoire 8 bits. *
+* Description : Initialise une instance d'opérande x86 d'adresse relative. *
* *
-* Retour : Opérande mise en place ou NULL. *
+* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
-asm_x86_operand *x86_create_moffs8_operand(const uint8_t *data, off_t *pos, off_t len)
+static void g_x86_relative_operand_init(GX86RelativeOperand *operand)
{
- asm_x86_operand *result; /* Emplacement à retourner */
-
- result = create_new_x86_operand();
-
- if (!fill_imm_operand(ASM_OPERAND(result), AOS_8_BITS, data, pos, len))
- {
- free(result);
- return NULL;
- }
+ GArchOperand *parent; /* Instance parente */
- ASM_OPERAND(result)->type = AOT_MOFFS;
+ parent = G_ARCH_OPERAND(operand);
- return result;
+ parent->get_text = (get_operand_text_fc)g_x86_relative_operand_get_text;
}
/******************************************************************************
* *
-* Paramètres : data = flux de données à analyser. *
-* pos = position courante dans ce flux. [OUT] *
-* len = taille totale des données à analyser. *
-* is_reg32 = indique si le registre est un registre 32 bits. *
+* Paramètres : data = flux de données à analyser. *
+* pos = position courante dans ce flux. [OUT] *
+* len = taille totale des données à analyser. *
+* size = taille de l'opérande, et donc du registre. *
+* base = indice du premier registre. *
* *
-* Description : Crée une opérande à partir d'un emplacement mémoire 16/32b. *
+* Description : Crée un opérande X86 d'adresse relative. *
* *
-* Retour : Opérande mise en place ou NULL. *
+* Retour : Opérande mis en place. *
* *
* Remarques : - *
* *
******************************************************************************/
-asm_x86_operand *x86_create_moffs1632_operand(const uint8_t *data, off_t *pos, off_t len, bool is_reg32)
+GArchOperand *g_x86_relative_operand_new(const bin_t *data, off_t *pos, off_t len, AsmOperandSize size, vmpa_t base)
{
- asm_x86_operand *result; /* Emplacement à retourner */
+ GX86RelativeOperand *result; /* Structure à retourner */
+ off_t init_pos; /* Position avant lecture */
+ uint8_t val8; /* Valeur sur 8 bits */
+ uint16_t val16; /* Valeur sur 16 bits */
+ uint32_t val32; /* Valeur sur 32 bits */
+ uint32_t address32; /* Adresse finale visée */
- result = create_new_x86_operand();
+ init_pos = *pos;
- if (!fill_imm_operand(ASM_OPERAND(result), is_reg32 ? AOS_32_BITS : AOS_16_BITS, data, pos, len))
+ switch (size)
{
- free(result);
- return NULL;
+ case AOS_8_BITS_UNSIGNED:
+ read_u8(&val8, data, pos, len, SRE_LITTLE);
+ address32 = val8;
+ break;
+ case AOS_16_BITS_UNSIGNED:
+ read_u16(&val16, data, pos, len, SRE_LITTLE);
+ address32 = val16;
+ break;
+ case AOS_32_BITS_UNSIGNED:
+ read_u32(&val32, data, pos, len, SRE_LITTLE);
+ address32 = val32;
+ break;
+ default:
+ return NULL;
+ break;
}
- ASM_OPERAND(result)->type = AOT_MOFFS;
+ address32 += base + (*pos - init_pos);
- return result;
+ result = g_object_new(G_TYPE_X86_RELATIVE_OPERAND, NULL);
+ result->immediate = g_imm_operand_new_from_value(AOS_32_BITS/*FIXME*/, address32);
+
+ return G_ARCH_OPERAND(result);
}
/******************************************************************************
* *
-* Paramètres : operand = instruction à traiter. *
-* buffer = tampon de sortie mis à disposition. [OUT] *
-* len = taille de ce tampon. *
+* Paramètres : operand = opérande à traiter. *
+* format = format du binaire manipulé. *
* syntax = type de représentation demandée. *
* *
-* Description : Traduit une opérande d'emplacement mémoire en texte. *
+* Description : Traduit un opérande en version humainement lisible. *
* *
-* Retour : - *
+* Retour : Chaîne de caractères à libérer de la mémoire. *
* *
* Remarques : - *
* *
******************************************************************************/
-void x86_print_moffs_operand(const asm_x86_operand *operand, char *buffer, size_t len, AsmSyntax syntax)
+static char *g_x86_relative_operand_get_text(const GX86RelativeOperand *operand, const exe_format *format, AsmSyntax syntax)
{
- switch (syntax)
- {
- case ASX_INTEL:
- if (len > 3)
- {
- strcpy(buffer, "ds:");
- print_imm_operand(ASM_OPERAND(operand), &buffer[3], len - 3, ASX_INTEL);
- }
- break;
+ char *result; /* Chaîne à retourner */
- case ASX_ATT:
- print_imm_operand(ASM_OPERAND(operand), buffer, len, ASX_INTEL);
- break;
+ result = g_arch_operand_get_text(operand->immediate, format, syntax);
- }
+ return result;
}
/* ---------------------------------------------------------------------------------- */
-/* OPERANDES D'ADRESSES RELATIVES */
+/* OPERANDES D'EMPLACEMENTS MEMOIRE */
/* ---------------------------------------------------------------------------------- */
+/* Indique le type défini par la GLib pour un opérande d'emplacement mémoire x86. */
+G_DEFINE_TYPE(GX86MOffsOperand, g_x86_moffs_operand, G_TYPE_X86_OPERAND);
+
+
/******************************************************************************
* *
-* Paramètres : data = flux de données à analyser. *
-* pos = position courante dans ce flux. [OUT] *
-* len = taille totale des données à analyser. *
+* Paramètres : klass = classe à initialiser. *
* *
-* Description : Crée une opérande à partir d'une adresse relative (8 bits). *
+* Description : Initialise la classe des opérandes d'emplacement mémoire x86.*
* *
-* Retour : Opérande mise en place ou NULL. *
+* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
-asm_x86_operand *x86_create_rel8_operand_in_32b(uint64_t base, const uint8_t *data, off_t *pos, off_t len)
+static void g_x86_moffs_operand_class_init(GX86MOffsOperandClass *klass)
{
- 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;
- }
+/******************************************************************************
+* *
+* Paramètres : operand = instance à initialiser. *
+* *
+* Description : Initialise une instance d'opérande d'emplacement mémoire x86.*
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
- address = base + (*pos - init_pos) + offset;
+static void g_x86_moffs_operand_init(GX86MOffsOperand *operand)
+{
+ GArchOperand *parent; /* Instance parente */
- if (!fill_imm_operand_with_value(ASM_OPERAND(result), AOS_32_BITS, &address))
- {
- free(result);
- return NULL;
- }
+ parent = G_ARCH_OPERAND(operand);
- return result;
+ parent->get_text = (get_operand_text_fc)g_x86_moffs_operand_get_text;
}
/******************************************************************************
* *
-* Paramètres : data = flux de données à analyser. *
-* pos = position courante dans ce flux. [OUT] *
-* len = taille totale des données à analyser. *
-* is_reg32 = indique si le registre est un registre 32 bits. *
+* Paramètres : data = flux de données à analyser. *
+* pos = position courante dans ce flux. [OUT] *
+* len = taille totale des données à analyser. *
+* size = taille de l'opérande, et donc du registre. *
* *
-* Description : Crée une opérande à partir d'une adresse relative (16/32b). *
+* Description : Crée un opérande d'emplacement mémoire x86. *
* *
-* Retour : Opérande mise en place ou NULL. *
+* Retour : Opérande mis en place. *
* *
* Remarques : - *
* *
******************************************************************************/
-asm_x86_operand *x86_create_rel1632_operand_in_32b(uint64_t base, const uint8_t *data, off_t *pos, off_t len, bool is_reg32)
+GArchOperand *g_x86_moffs_operand_new(const bin_t *data, off_t *pos, off_t len, AsmOperandSize size)
{
- asm_x86_operand *result; /* Emplacement à retourner */
- off_t init_pos; /* Position avant lecture */
- int32_t offset32; /* Décallage 32b à appliquer */
- int16_t offset16; /* Décallage 16b à appliquer */
- uint32_t address; /* Adresse finale visée */
+ GX86MOffsOperand *result; /* Structure à retourner */
+ GImmOperand *offset; /* Emplacement lu */
- result = create_new_x86_operand();
+ result = NULL;
- init_pos = *pos;
- address = base;
+ offset = g_imm_operand_new_from_data(size/* FIXME : !convert mds/aos */, data, pos, len, SRE_LITTLE);
- if (is_reg32)
+ if (offset != NULL)
{
- if (!read_imm_value(AOS_32_BITS, data, pos, len, &offset32))
- {
- free(result);
- return NULL;
- }
+ result = g_object_new(G_TYPE_X86_MOFFS_OPERAND, NULL);
+ result->offset = offset;
+ }
- address = base + (*pos - init_pos) + offset32;
+ return G_ARCH_OPERAND(result);
- }
- else
- {
- if (!read_imm_value(AOS_16_BITS, data, pos, len, &offset16))
- {
- free(result);
- return NULL;
- }
+}
- address = base + (*pos - init_pos) + offset16;
- }
+/******************************************************************************
+* *
+* Paramètres : operand = opérande à traiter. *
+* format = format du binaire manipulé. *
+* syntax = type de représentation demandée. *
+* *
+* Description : Traduit un opérande en version humainement lisible. *
+* *
+* Retour : Chaîne de caractères à libérer de la mémoire. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
- if (!fill_imm_operand_with_value(ASM_OPERAND(result), AOS_32_BITS, &address))
- {
- free(result);
- return NULL;
- }
+static char *g_x86_moffs_operand_get_text(const GX86MOffsOperand *operand, const exe_format *format, AsmSyntax syntax)
+{
+ char *result; /* Chaîne à retourner */
+
+ result = g_arch_operand_get_text(operand->offset, format, syntax);
+
+ result = strprep(result, "ds:");
return result;
@@ -1367,13 +920,13 @@ asm_x86_operand *x86_create_rel1632_operand_in_32b(uint64_t base, const uint8_t
* *
******************************************************************************/
-bool x86_read_one_operand(asm_x86_instr *instr, const uint8_t *data, off_t *pos, off_t len, X86OperandType type, ...)
+bool x86_read_one_operand(GArchInstruction *instr, const bin_t *data, off_t *pos, off_t len, X86OperandType type, ...)
{
va_list ap; /* Liste des compléments */
AsmOperandSize oprsize; /* Taille des opérandes */
- uint64_t offset; /* Adresse courante */
- uint8_t base; /* Indice du premier registre */
- asm_x86_operand *op; /* Opérande unique décodé */
+ vmpa_t offset; /* Adresse courante */
+ bin_t base; /* Indice du premier registre */
+ GArchOperand *op; /* Opérande unique décodé */
va_start(ap, type);
@@ -1382,72 +935,60 @@ bool x86_read_one_operand(asm_x86_instr *instr, const uint8_t *data, off_t *pos,
switch (type)
{
case X86_OTP_IMM8:
- op = create_new_x86_operand();
- if (!fill_imm_operand(ASM_OPERAND(op), AOS_8_BITS, data, pos, len))
- {
- free(op);
- op = NULL;
- }
+ op = g_imm_operand_new_from_data(MDS_8_BITS, data, pos, len, SRE_LITTLE);
break;
case X86_OTP_IMM1632:
- oprsize = va_arg(ap, AsmOperandSize);
- op = create_new_x86_operand();
- if (!fill_imm_operand(ASM_OPERAND(op), oprsize, data, pos, len))
- {
- free(op);
- op = NULL;
- }
+ if (oprsize == AOS_UNDEFINED) oprsize = va_arg(ap, AsmOperandSize);
+ op = g_imm_operand_new_from_data(oprsize == AOS_32_BITS ? MDS_32_BITS : MDS_16_BITS, data, pos, len, SRE_LITTLE);
break;
case X86_OTP_REL8:
- offset = va_arg(ap, uint64_t);
- /* TODO : 64bits */
- op = x86_create_rel8_operand_in_32b(offset + 1, data, pos, len);
+ offset = va_arg(ap, vmpa_t);
+ op = g_x86_relative_operand_new(data, pos, len, AOS_8_BITS, offset + 1);
break;
case X86_OTP_REL1632:
oprsize = va_arg(ap, AsmOperandSize);
- offset = va_arg(ap, uint64_t);
- /* TODO : 64bits */
- op = x86_create_rel1632_operand_in_32b(offset + 1, data, pos, len, oprsize == AOS_32_BITS);
+ offset = va_arg(ap, vmpa_t);
+ op = g_x86_relative_operand_new(data, pos, len, oprsize, offset + 1);
break;
case X86_OTP_R8:
- op = x86_create_r8_operand(data[(*pos)++], true);
+ op = g_x86_register_operand_new_from_mod_rm(data, pos, len, AOS_8_BITS, true);
break;
case X86_OTP_R1632:
oprsize = va_arg(ap, AsmOperandSize);
- op = x86_create_r1632_operand(data[(*pos)++], oprsize == AOS_32_BITS, true);
+ op = g_x86_register_operand_new_from_mod_rm(data, pos, len, oprsize, true);
break;
case X86_OTP_OP_R1632:
oprsize = va_arg(ap, AsmOperandSize);
- base = (uint8_t)va_arg(ap, int);
- op = x86_create_r1632_operand_from_opcode(data[(*pos)++], oprsize == AOS_32_BITS, base);
+ base = (bin_t)va_arg(ap, int);
+ op = g_x86_register_operand_new_from_opcode(data, pos, len, oprsize, base);
break;
case X86_OTP_RM8:
- op = x86_create_rm8_operand(data, pos, len);
+ op = g_x86_mod_rm_operand_new(data, pos, len, AOS_8_BITS);
break;
case X86_OTP_RM1632:
oprsize = va_arg(ap, AsmOperandSize);
- op = x86_create_rm1632_operand(data, pos, len, oprsize == AOS_32_BITS);
+ op = g_x86_mod_rm_operand_new(data, pos, len, oprsize);
break;
case X86_OTP_CL:
- op = x86_create_r8_operand(0x01, true);
+ op = g_x86_register_operand_new_from_index(0x01, AOS_8_BITS);
break;
case X86_OTP_AL:
- op = x86_create_r8_operand(0x00, true);
+ op = g_x86_register_operand_new_from_index(0x00, AOS_8_BITS);
break;
case X86_OTP_E_AX:
oprsize = va_arg(ap, AsmOperandSize);
- op = x86_create_r1632_operand(0x00, oprsize == AOS_32_BITS, true);
+ op = g_x86_register_operand_new_from_index(0x00, oprsize);
break;
}
@@ -1456,12 +997,7 @@ bool x86_read_one_operand(asm_x86_instr *instr, const uint8_t *data, off_t *pos,
if (op == NULL) return false;
- /* Assemblage final */
-
- ASM_INSTRUCTION(instr)->operands = (asm_operand **)calloc(1, sizeof(asm_operand *));
- ASM_INSTRUCTION(instr)->operands_count = 1;
-
- ASM_INSTRUCTION(instr)->operands[0] = ASM_OPERAND(op);
+ g_arch_instruction_attach_one_operand(instr, op);
return true;
@@ -1486,16 +1022,17 @@ bool x86_read_one_operand(asm_x86_instr *instr, const uint8_t *data, off_t *pos,
* *
******************************************************************************/
-bool x86_read_two_operands(asm_x86_instr *instr, const uint8_t *data, off_t *pos, off_t len, X86OperandType type1, X86OperandType type2, ...)
+bool x86_read_two_operands(GArchInstruction *instr, const bin_t *data, off_t *pos, off_t len, X86OperandType type1, X86OperandType type2, ...)
{
va_list ap; /* Liste des compléments */
AsmOperandSize oprsize; /* Taille des opérandes */
bool op1_first; /* Position de l'opérande #1 */
bool op2_first; /* Position de l'opérande #2 */
off_t op1_pos; /* Position après lecture #1 */
- asm_x86_operand *op1; /* Premier opérande décodé */
+ bin_t base; /* Indice du premier registre */
+ GArchOperand *op1; /* Premier opérande décodé */
off_t op2_pos; /* Position après lecture #2 */
- asm_x86_operand *op2; /* Second opérande décodé */
+ GArchOperand *op2; /* Second opérande décodé */
va_start(ap, type2);
@@ -1523,44 +1060,59 @@ bool x86_read_two_operands(asm_x86_instr *instr, const uint8_t *data, off_t *pos
switch (type1)
{
+ case X86_OTP_IMM8:
+ op1 = g_imm_operand_new_from_data(MDS_8_BITS, data, &op1_pos, len, SRE_LITTLE);
+ break;
+
+ case X86_OTP_IMM1632:
+ if (oprsize == AOS_UNDEFINED) oprsize = va_arg(ap, AsmOperandSize);
+ op1 = g_imm_operand_new_from_data(oprsize == AOS_32_BITS ? MDS_32_BITS : MDS_16_BITS, data, &op1_pos, len, SRE_LITTLE);
+ break;
+
case X86_OTP_MOFFS8:
- op1 = x86_create_moffs8_operand(data, &op1_pos, len);
+ op1 = g_x86_moffs_operand_new(data, &op1_pos, len, AOS_8_BITS);
break;
case X86_OTP_MOFFS1632:
oprsize = va_arg(ap, AsmOperandSize);
- op1 = x86_create_moffs1632_operand(data, &op1_pos, len, oprsize == AOS_32_BITS);
+ op1 = g_x86_moffs_operand_new(data, &op1_pos, len, oprsize);
break;
case X86_OTP_R8:
- op1 = x86_create_r8_operand(data[op1_pos++], op1_first);
+ op1 = g_x86_register_operand_new_from_mod_rm(data, &op1_pos, len, AOS_8_BITS, op1_first);
break;
case X86_OTP_R1632:
oprsize = va_arg(ap, AsmOperandSize);
- op1 = x86_create_r1632_operand(data[op1_pos++], oprsize == AOS_32_BITS, op1_first);
+ op1 = g_x86_register_operand_new_from_mod_rm(data, &op1_pos, len, oprsize, op1_first);
+ break;
+
+ case X86_OTP_OP_R1632:
+ oprsize = va_arg(ap, AsmOperandSize);
+ base = (bin_t)va_arg(ap, int);
+ op1 = g_x86_register_operand_new_from_opcode(data, &op1_pos, len, oprsize, base);
break;
case X86_OTP_RM8:
- op1 = x86_create_rm8_operand(data, &op1_pos, len);
+ op1 = g_x86_mod_rm_operand_new(data, &op1_pos, len, AOS_8_BITS);
break;
case X86_OTP_RM1632:
oprsize = va_arg(ap, AsmOperandSize);
- op1 = x86_create_rm1632_operand(data, &op1_pos, len, oprsize == AOS_32_BITS);
+ op1 = g_x86_mod_rm_operand_new(data, &op1_pos, len, oprsize);
break;
case X86_OTP_CL:
- op1 = x86_create_r8_operand(0x01, op1_first);
+ op1 = g_x86_register_operand_new_from_index(0x01, AOS_8_BITS);
break;
case X86_OTP_AL:
- op1 = x86_create_r8_operand(0x00, op1_first);
+ op1 = g_x86_register_operand_new_from_index(0x00, AOS_8_BITS);
break;
case X86_OTP_E_AX:
oprsize = va_arg(ap, AsmOperandSize);
- op1 = x86_create_r1632_operand(0x00, oprsize == AOS_32_BITS, op1_first);
+ op1 = g_x86_register_operand_new_from_index(0x00, oprsize);
break;
}
@@ -1580,62 +1132,52 @@ bool x86_read_two_operands(asm_x86_instr *instr, const uint8_t *data, off_t *pos
switch (type2)
{
case X86_OTP_IMM8:
- op2 = create_new_x86_operand();
- if (!fill_imm_operand(ASM_OPERAND(op2), AOS_8_BITS, data, &op2_pos, len))
- {
- free(op2);
- op2 = NULL;
- }
+ op2 = g_imm_operand_new_from_data(MDS_8_BITS, data, &op2_pos, len, SRE_LITTLE);
break;
case X86_OTP_IMM1632:
if (oprsize == AOS_UNDEFINED) oprsize = va_arg(ap, AsmOperandSize);
- op2 = create_new_x86_operand();
- if (!fill_imm_operand(ASM_OPERAND(op2), oprsize, data, &op2_pos, len))
- {
- free(op2);
- op2 = NULL;
- }
+ op2 = g_imm_operand_new_from_data(oprsize == AOS_32_BITS ? MDS_32_BITS : MDS_16_BITS, data, &op2_pos, len, SRE_LITTLE);
break;
case X86_OTP_MOFFS8:
- op2 = x86_create_moffs8_operand(data, &op2_pos, len);
+ op2 = g_x86_moffs_operand_new(data, &op2_pos, len, AOS_8_BITS);
break;
case X86_OTP_MOFFS1632:
if (oprsize == AOS_UNDEFINED) oprsize = va_arg(ap, AsmOperandSize);
- op2 = x86_create_moffs1632_operand(data, &op2_pos, len, oprsize == AOS_32_BITS);
+ op2 = g_x86_moffs_operand_new(data, &op2_pos, len, oprsize);
break;
case X86_OTP_R8:
- op2 = x86_create_r8_operand(data[op2_pos++], op2_first);
+ op2 = g_x86_register_operand_new_from_mod_rm(data, &op2_pos, len, AOS_8_BITS, op2_first);
break;
case X86_OTP_R1632:
if (oprsize == AOS_UNDEFINED) oprsize = va_arg(ap, AsmOperandSize);
- op2 = x86_create_r1632_operand(data[op2_pos++], oprsize == AOS_32_BITS, op2_first);
+ op2 = g_x86_register_operand_new_from_mod_rm(data, &op2_pos, len, oprsize, op2_first);
break;
case X86_OTP_RM8:
- op2 = x86_create_rm8_operand(data, &op2_pos, len);
+ op2 = g_x86_mod_rm_operand_new(data, &op2_pos, len, AOS_8_BITS);
break;
case X86_OTP_RM1632:
if (oprsize == AOS_UNDEFINED) oprsize = va_arg(ap, AsmOperandSize);
- op2 = x86_create_rm1632_operand(data, &op2_pos, len, oprsize == AOS_32_BITS);
+ op2 = g_x86_mod_rm_operand_new(data, &op2_pos, len, oprsize);
break;
case X86_OTP_CL:
- op2 = x86_create_r8_operand(0x01, op2_first);
+ op2 = g_x86_register_operand_new_from_index(0x01, AOS_8_BITS);
break;
case X86_OTP_AL:
- op2 = x86_create_r8_operand(0x00, op2_first);
+ op2 = g_x86_register_operand_new_from_index(0x00, AOS_8_BITS);
break;
case X86_OTP_E_AX:
if (oprsize == AOS_UNDEFINED) oprsize = va_arg(ap, AsmOperandSize);
- op2 = x86_create_r1632_operand(0x00, oprsize == AOS_32_BITS, op2_first);
+ op2 = g_x86_register_operand_new_from_index(0x00, oprsize);
break;
}
@@ -1653,11 +1195,7 @@ bool x86_read_two_operands(asm_x86_instr *instr, const uint8_t *data, off_t *pos
*pos = MAX(op1_pos, op2_pos);
- ASM_INSTRUCTION(instr)->operands = (asm_operand **)calloc(2, sizeof(asm_operand *));
- ASM_INSTRUCTION(instr)->operands_count = 2;
-
- ASM_INSTRUCTION(instr)->operands[0] = ASM_OPERAND(op1);
- ASM_INSTRUCTION(instr)->operands[1] = ASM_OPERAND(op2);
+ g_arch_instruction_attach_two_operands(instr, op1, op2);
return true;