diff options
Diffstat (limited to 'src/arch/x86/operand.c')
-rw-r--r-- | src/arch/x86/operand.c | 1458 |
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; |