summaryrefslogtreecommitdiff
path: root/src/arch/x86/operand.c
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2009-10-07 00:22:10 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2009-10-07 00:22:10 (GMT)
commitdaa0084325d4e748f334a223e1cd3800120e6055 (patch)
tree9f8bfe9296e1a4f6aa945418293f895303b771e2 /src/arch/x86/operand.c
parentd9be16271ab3fbb95d6c95baa92242358f0e7dfd (diff)
Created a function to load n x86 operands and supported extra x86 opcodes.
git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@128 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a
Diffstat (limited to 'src/arch/x86/operand.c')
-rw-r--r--src/arch/x86/operand.c381
1 files changed, 123 insertions, 258 deletions
diff --git a/src/arch/x86/operand.c b/src/arch/x86/operand.c
index eb6f5f3..d0e923f 100644
--- a/src/arch/x86/operand.c
+++ b/src/arch/x86/operand.c
@@ -512,7 +512,7 @@ GArchOperand *g_x86_mod_rm_operand_new(const bin_t *data, off_t *pos, off_t len,
if (g_x86_register_is_base_pointer(reg) && mod == 0x00)
{
/* FIXME *///free_x86_register(reg);
- return g_imm_operand_new_from_data(MDS_32_BITS/* FIXME */, data, pos, len, SRE_LITTLE);
+ return g_imm_operand_new_from_data(MDS_32_BITS/* FIXME */, data, pos, len, SRE_LITTLE /*FIXME*/);
}
result = g_object_new(G_TYPE_X86_MOD_RM_OPERAND, NULL);
@@ -552,19 +552,19 @@ GArchOperand *g_x86_mod_rm_operand_new(const bin_t *data, off_t *pos, off_t len,
/* FIXME *///free_x86_register(result->base);
result->base = NULL;
- result->displacement = g_imm_operand_new_from_data(size/* FIXME : !convert mds/aos */, data, pos, len, SRE_LITTLE);
+ result->displacement = g_imm_operand_new_from_data(size/* FIXME : !convert mds/aos */, data, pos, len, SRE_LITTLE /* FIXME */);
if (result->displacement == NULL) goto gxmron_error;
}
break;
case 0x40:
- result->displacement = g_imm_operand_new_from_data(MDS_8_BITS_SIGNED, data, pos, len, SRE_LITTLE);
+ result->displacement = g_imm_operand_new_from_data(MDS_8_BITS_SIGNED, data, pos, len, SRE_LITTLE /* FIXME */);
if (result->displacement == NULL) goto gxmron_error;
break;
case 0x80:
- result->displacement = g_imm_operand_new_from_data(MDS_32_BITS_SIGNED/* FIXME ! 16/32 */, data, pos, len, SRE_LITTLE);
+ result->displacement = g_imm_operand_new_from_data(MDS_32_BITS_SIGNED/* FIXME ! 16/32 */, data, pos, len, SRE_LITTLE /* FIXME */);
if (result->displacement == NULL) goto gxmron_error;
break;
@@ -805,15 +805,15 @@ GArchOperand *g_x86_relative_operand_new(const bin_t *data, off_t *pos, off_t le
switch (size)
{
case AOS_8_BITS_UNSIGNED:
- read_s8(&val8, data, pos, len, SRE_LITTLE);
+ read_s8(&val8, data, pos, len, SRE_LITTLE /* FIXME */);
address = base + (*pos - init_pos) + val8;
break;
case AOS_16_BITS_UNSIGNED:
- read_s16(&val16, data, pos, len, SRE_LITTLE);
+ read_s16(&val16, data, pos, len, SRE_LITTLE /* FIXME */);
address = base + (*pos - init_pos) + val16;
break;
case AOS_32_BITS_UNSIGNED:
- read_s32(&val32, data, pos, len, SRE_LITTLE);
+ read_s32(&val32, data, pos, len, SRE_LITTLE /* FIXME */);
address = base + (*pos - init_pos) + val32;
break;
default:
@@ -945,7 +945,7 @@ GArchOperand *g_x86_moffs_operand_new(const bin_t *data, off_t *pos, off_t len,
result = NULL;
- offset = g_imm_operand_new_from_data(size/* FIXME : !convert mds/aos */, data, pos, len, SRE_LITTLE);
+ offset = g_imm_operand_new_from_data(size/* FIXME : !convert mds/aos */, data, pos, len, SRE_LITTLE /* FIXME */);
if (offset != NULL)
{
@@ -997,10 +997,10 @@ static void g_x86_moffs_operand_add_to_gtk_buffer(const GX86MOffsOperand *operan
* data = flux de données à analyser. *
* pos = position courante dans ce flux. [OUT] *
* len = taille totale des données à analyser. *
-* type = type de l'opérande. *
+* count = quantité d'opérandes à lire. *
* ... = éventuelle(s) information(s) complémentaire(s). *
* *
-* Description : Procède à la lecture d'un opérande donné. *
+* Description : Procède à la lecture de trois opérandes donnés. *
* *
* Retour : Bilan de l'opération : true en cas de succès, false sinon. *
* *
@@ -1008,135 +1008,39 @@ static void g_x86_moffs_operand_add_to_gtk_buffer(const GX86MOffsOperand *operan
* *
******************************************************************************/
-bool x86_read_one_operand(GArchInstruction *instr, const bin_t *data, off_t *pos, off_t len, X86OperandType type, ...)
+bool _x86_read_operands(GArchInstruction *instr, const bin_t *data, off_t *pos, off_t len, unsigned int count, ...)
{
+ bool result; /* Bilan à retourner */
va_list ap; /* Liste des compléments */
+ X86OperandType types[MAX_OPERANDS]; /* Type des opérandes */
+ unsigned int i; /* Boucle de parcours */
+ bool op1_first; /* Position de l'opérande #1 */
+ bool op2_first; /* Position de l'opérande #2 */
AsmOperandSize oprsize; /* Taille des opérandes */
+ off_t op_pos[MAX_OPERANDS]; /* Position après lecture */
vmpa_t offset; /* Adresse courante */
bin_t base; /* Indice du premier registre */
GArchOperand *op; /* Opérande unique décodé */
- va_start(ap, type);
-
- /* Lecture du premier opérande */
-
- switch (type)
- {
- case X86_OTP_IMM8:
- 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 = 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, 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, vmpa_t);
- op = g_x86_relative_operand_new(data, pos, len, oprsize, offset + 1);
- break;
-
- case X86_OTP_R8:
- 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 = g_x86_register_operand_new_from_mod_rm(data, pos, len, oprsize, true);
- break;
-
- case X86_OTP_OP_R8:
- base = (bin_t)va_arg(ap, int);
- op = g_x86_register_operand_new_from_opcode(data, pos, len, AOS_8_BITS, base);
- break;
-
- case X86_OTP_OP_R1632:
- oprsize = va_arg(ap, AsmOperandSize);
- 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 = g_x86_mod_rm_operand_new(data, pos, len, AOS_8_BITS);
- break;
-
- case X86_OTP_RM1632:
- oprsize = va_arg(ap, AsmOperandSize);
- op = g_x86_mod_rm_operand_new(data, pos, len, oprsize);
- break;
-
- case X86_OTP_CL:
- op = g_x86_register_operand_new_from_index(0x01, AOS_8_BITS);
- break;
-
- case X86_OTP_AL:
- op = g_x86_register_operand_new_from_index(0x00, AOS_8_BITS);
- break;
-
- case X86_OTP_E_AX:
- oprsize = va_arg(ap, AsmOperandSize);
- op = g_x86_register_operand_new_from_index(0x00, oprsize);
- break;
-
- }
-
- va_end(ap);
-
- if (op == NULL) return false;
-
- g_arch_instruction_attach_one_operand(instr, op);
-
- return true;
-
-}
+ if (count > MAX_OPERANDS) return false;
+ result = true;
-/******************************************************************************
-* *
-* Paramètres : instr = instruction dont la définition est à compléter. [OUT]*
-* data = flux de données à analyser. *
-* pos = position courante dans ce flux. [OUT] *
-* len = taille totale des données à analyser. *
-* type1 = type du premier opérande. *
-* type2 = type du second opérande. *
-* ... = éventuelle(s) information(s) complémentaire(s). *
-* *
-* Description : Procède à la lecture de deux opérandes donnés. *
-* *
-* Retour : Bilan de l'opération : true en cas de succès, false sinon. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
+ va_start(ap, count);
-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 */
- bin_t base; /* Indice du premier registre */
- GArchOperand *op1; /* Premier opérande décodé */
- off_t op2_pos; /* Position après lecture #2 */
- GArchOperand *op2; /* Second opérande décodé */
+ /* Types à charger */
- va_start(ap, type2);
+ for (i = 0; i < count; i++)
+ types[i] = va_arg(ap, AsmOperandSize);
- oprsize = AOS_UNDEFINED;
+ /* Initialisations */
- if (type1 & X86_OTP_RM_TYPE)
+ if (types[0] & X86_OTP_RM_TYPE)
{
op1_first = true;
op2_first = false;
}
- else if (type2 & X86_OTP_RM_TYPE)
+ else if (types[1] & X86_OTP_RM_TYPE)
{
op1_first = false;
op2_first = true;
@@ -1147,154 +1051,115 @@ bool x86_read_two_operands(GArchInstruction *instr, const bin_t *data, off_t *po
op2_first = false;
}
- /* Lecture du premier opérande */
-
- op1_pos = *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 = g_x86_moffs_operand_new(data, &op1_pos, len, AOS_8_BITS);
- break;
-
- case X86_OTP_MOFFS1632:
- oprsize = va_arg(ap, AsmOperandSize);
- op1 = g_x86_moffs_operand_new(data, &op1_pos, len, oprsize);
- break;
-
- case X86_OTP_R8:
- 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 = g_x86_register_operand_new_from_mod_rm(data, &op1_pos, len, oprsize, op1_first);
- break;
-
- case X86_OTP_OP_R8:
- base = (bin_t)va_arg(ap, int);
- op1 = g_x86_register_operand_new_from_opcode(data, &op1_pos, len, AOS_8_BITS, base);
- 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 = g_x86_mod_rm_operand_new(data, &op1_pos, len, AOS_8_BITS);
- break;
-
- case X86_OTP_RM1632:
- oprsize = va_arg(ap, AsmOperandSize);
- op1 = g_x86_mod_rm_operand_new(data, &op1_pos, len, oprsize);
- break;
-
- case X86_OTP_CL:
- op1 = g_x86_register_operand_new_from_index(0x01, AOS_8_BITS);
- break;
-
- case X86_OTP_AL:
- op1 = g_x86_register_operand_new_from_index(0x00, AOS_8_BITS);
- break;
-
- case X86_OTP_E_AX:
- oprsize = va_arg(ap, AsmOperandSize);
- op1 = g_x86_register_operand_new_from_index(0x00, oprsize);
- break;
-
- }
-
- if (op1 == NULL)
- {
- va_end(ap);
- return false;
- }
-
- /* Lecture du second opérande */
+ oprsize = AOS_UNDEFINED;
- if ((type1 & X86_OTP_REG_TYPE || type1 & X86_OTP_RM_TYPE) && (type2 & X86_OTP_IMM_TYPE))
- op2_pos = op1_pos;
- else op2_pos = *pos;
+ /* Lecture des opérandes */
- switch (type2)
+ for (i = 0; i < count && result; i++)
{
- case X86_OTP_IMM8:
- 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 = 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 = 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 = g_x86_moffs_operand_new(data, &op2_pos, len, oprsize);
- break;
-
- case X86_OTP_R8:
- 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 = g_x86_register_operand_new_from_mod_rm(data, &op2_pos, len, oprsize, op2_first);
- break;
+ /* Tête de lecture */
+ switch (i)
+ {
+ case 0:
+ op_pos[0] = *pos;
+ break;
- case X86_OTP_RM8:
- op2 = g_x86_mod_rm_operand_new(data, &op2_pos, len, AOS_8_BITS);
- break;
+ case 1:
+ if ((types[0] & X86_OTP_REG_TYPE || types[0] & X86_OTP_RM_TYPE) && (types[1] & X86_OTP_IMM_TYPE))
+ op_pos[1] = op_pos[0];
+ else op_pos[1] = *pos;
+ *pos = op_pos[0];
+ break;
- case X86_OTP_RM1632:
- if (oprsize == AOS_UNDEFINED) oprsize = va_arg(ap, AsmOperandSize);
- op2 = g_x86_mod_rm_operand_new(data, &op2_pos, len, oprsize);
- break;
+ case 2 ... MAX_OPERANDS:
+ *pos = MAX(*pos, op_pos[i - 1]);
+ op_pos[i] = *pos;
- case X86_OTP_CL:
- op2 = g_x86_register_operand_new_from_index(0x01, AOS_8_BITS);
- break;
+ }
- case X86_OTP_AL:
- op2 = g_x86_register_operand_new_from_index(0x00, AOS_8_BITS);
- break;
+ /* Lecture */
+ switch (types[i])
+ {
+ case X86_OTP_IMM8:
+ op = g_imm_operand_new_from_data(MDS_8_BITS, data, &op_pos[i], len, SRE_LITTLE /* FIXME */);
+ break;
+
+ case X86_OTP_IMM1632:
+ 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, &op_pos[i], len, SRE_LITTLE /* FIXME */);
+ break;
+
+ case X86_OTP_MOFFS8:
+ op = g_x86_moffs_operand_new(data, &op_pos[i], len, AOS_8_BITS);
+ break;
+
+ case X86_OTP_MOFFS1632:
+ if (oprsize == AOS_UNDEFINED) oprsize = va_arg(ap, AsmOperandSize);
+ op = g_x86_moffs_operand_new(data, &op_pos[i], len, oprsize);
+ break;
+
+ case X86_OTP_REL8:
+ offset = va_arg(ap, vmpa_t);
+ op = g_x86_relative_operand_new(data, &op_pos[i], len, AOS_8_BITS, offset + 1);
+ break;
+
+ case X86_OTP_REL1632:
+ if (oprsize == AOS_UNDEFINED) oprsize = va_arg(ap, AsmOperandSize);
+ offset = va_arg(ap, vmpa_t);
+ op = g_x86_relative_operand_new(data, &op_pos[i], len, oprsize, offset + 1);
+ break;
+
+ case X86_OTP_R8:
+ op = g_x86_register_operand_new_from_mod_rm(data, &op_pos[i], len, AOS_8_BITS, i == 0 ? op1_first : op2_first);
+ break;
+
+ case X86_OTP_R1632:
+ if (oprsize == AOS_UNDEFINED) oprsize = va_arg(ap, AsmOperandSize);
+ op = g_x86_register_operand_new_from_mod_rm(data, &op_pos[i], len, oprsize, i == 0 ? op1_first : op2_first);
+ break;
+
+ case X86_OTP_OP_R8:
+ base = (bin_t)va_arg(ap, int);
+ op = g_x86_register_operand_new_from_opcode(data, &op_pos[i], len, AOS_8_BITS, base);
+ break;
+
+ case X86_OTP_OP_R1632:
+ if (oprsize == AOS_UNDEFINED) oprsize = va_arg(ap, AsmOperandSize);
+ base = (bin_t)va_arg(ap, int);
+ op = g_x86_register_operand_new_from_opcode(data, &op_pos[i], len, oprsize, base);
+ break;
+
+ case X86_OTP_RM8:
+ op = g_x86_mod_rm_operand_new(data, &op_pos[i], len, AOS_8_BITS);
+ break;
+
+ case X86_OTP_RM1632:
+ if (oprsize == AOS_UNDEFINED) oprsize = va_arg(ap, AsmOperandSize);
+ op = g_x86_mod_rm_operand_new(data, &op_pos[i], len, oprsize);
+ break;
+
+ case X86_OTP_CL:
+ op = g_x86_register_operand_new_from_index(0x01, AOS_8_BITS);
+ break;
+
+ case X86_OTP_AL:
+ op = 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);
+ op = g_x86_register_operand_new_from_index(0x00, oprsize);
+ break;
- case X86_OTP_E_AX:
- if (oprsize == AOS_UNDEFINED) oprsize = va_arg(ap, AsmOperandSize);
- op2 = g_x86_register_operand_new_from_index(0x00, oprsize);
- break;
+ }
- }
+ if (op == NULL) result = false;
+ else g_arch_instruction_attach_extra_operand(instr, op);
- if (op2 == NULL)
- {
- free(op1);
- va_end(ap);
- return false;
}
- va_end(ap);
-
- /* Assemblage final */
-
- *pos = MAX(op1_pos, op2_pos);
-
- g_arch_instruction_attach_two_operands(instr, op1, op2);
+ *pos = MAX(*pos, op_pos[i - 1]);
- return true;
+ return result;
}