diff options
author | Cyrille Bagard <nocbos@gmail.com> | 2009-10-07 00:22:10 (GMT) |
---|---|---|
committer | Cyrille Bagard <nocbos@gmail.com> | 2009-10-07 00:22:10 (GMT) |
commit | daa0084325d4e748f334a223e1cd3800120e6055 (patch) | |
tree | 9f8bfe9296e1a4f6aa945418293f895303b771e2 /src/arch/x86/operand.c | |
parent | d9be16271ab3fbb95d6c95baa92242358f0e7dfd (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.c | 381 |
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; } |