diff options
Diffstat (limited to 'src/arch/x86/instruction.c')
-rw-r--r-- | src/arch/x86/instruction.c | 148 |
1 files changed, 116 insertions, 32 deletions
diff --git a/src/arch/x86/instruction.c b/src/arch/x86/instruction.c index edbffec..af1d25e 100644 --- a/src/arch/x86/instruction.c +++ b/src/arch/x86/instruction.c @@ -24,6 +24,9 @@ #include "instruction.h" +#include <string.h> + + #include "operand.h" #include "../instruction-int.h" #include "../../common/extstr.h" @@ -39,6 +42,8 @@ struct _GX86Instruction X86Prefix prefixes; /* Préfixes finalement trouvés */ + char *cached_text; /* Nom construit à conserver */ + }; /* Définition générique d'une instruction d'architecture x86 (classe) */ @@ -80,6 +85,8 @@ typedef struct _x86_instruction static x86_instruction _instructions[XOP_COUNT] = { + /* Instructions avec opcode sur un octet */ + [XOP_ADD_RM8_R8] = { false, 0x00, IDX_TO_EXT(-1), "add", XPX_NONE }, [XOP_ADD_RM1632_R1632] = { false, 0x01, IDX_TO_EXT(-1), "add", XPX_OPERAND_SIZE_OVERRIDE }, [XOP_ADD_R8_RM8] = { false, 0x02, IDX_TO_EXT(-1), "add", XPX_NONE }, @@ -94,29 +101,11 @@ static x86_instruction _instructions[XOP_COUNT] = { [XOP_OR_AL_IMM8] = { false, 0x0c, IDX_TO_EXT(-1), "or", XPX_NONE }, - [XOP_JE_REL1632] = { false, 0x84, IDX_TO_EXT(-1), "je", XPX_TWO_BYTES | XPX_OPERAND_SIZE_OVERRIDE }, - [XOP_JNE_REL1632] = { false, 0x85, IDX_TO_EXT(-1), "jne", XPX_TWO_BYTES | XPX_OPERAND_SIZE_OVERRIDE }, - [XOP_JBE_REL1632] = { false, 0x86, IDX_TO_EXT(-1), "jbe", XPX_TWO_BYTES | XPX_OPERAND_SIZE_OVERRIDE }, - [XOP_JA_REL1632] = { false, 0x87, IDX_TO_EXT(-1), "ja", XPX_TWO_BYTES | XPX_OPERAND_SIZE_OVERRIDE }, - - [XOP_JGE_REL1632] = { false, 0x8d, IDX_TO_EXT(-1), "jge", XPX_TWO_BYTES | XPX_OPERAND_SIZE_OVERRIDE }, - [XOP_JLE_REL1632] = { false, 0x8e, IDX_TO_EXT(-1), "jle", XPX_TWO_BYTES | XPX_OPERAND_SIZE_OVERRIDE }, - [XOP_JG_REL1632] = { false, 0x8f, IDX_TO_EXT(-1), "jg", XPX_TWO_BYTES | XPX_OPERAND_SIZE_OVERRIDE }, - - - [XOP_SETE_RM8] = { false, 0x94, IDX_TO_EXT(-1), "sete", XPX_TWO_BYTES }, - [XOP_SETNE_RM8] = { false, 0x95, IDX_TO_EXT(-1), "setne", XPX_TWO_BYTES }, - - [XOP_SETL_RM8] = { false, 0x9c, IDX_TO_EXT(-1), "setl", XPX_TWO_BYTES }, - - - [XOP_MOVZX_R1632_RM8] = { false, 0xb6, IDX_TO_EXT(-1), "movzx", XPX_TWO_BYTES | XPX_OPERAND_SIZE_OVERRIDE }, - [XOP_MOVSX_R1632_RM8] = { false, 0xbe, IDX_TO_EXT(-1), "movsx", XPX_TWO_BYTES | XPX_OPERAND_SIZE_OVERRIDE }, - [XOP_MOVSX_R1632_RM1632] = { false, 0xbf, IDX_TO_EXT(-1), "movsx", XPX_TWO_BYTES | XPX_OPERAND_SIZE_OVERRIDE }, - [XOP_ADC_RM8_R8] = { false, 0x10, IDX_TO_EXT(-1), "adc", XPX_NONE }, + [XOP_SBB_RM1632_R1632] = { false, 0x19, IDX_TO_EXT(-1), "sbb", XPX_OPERAND_SIZE_OVERRIDE }, + [XOP_AND_RM8_R8] = { false, 0x20, IDX_TO_EXT(-1), "and", XPX_NONE }, [XOP_AND_RM1632_R1632] = { false, 0x21, IDX_TO_EXT(-1), "and", XPX_OPERAND_SIZE_OVERRIDE }, @@ -128,6 +117,7 @@ static x86_instruction _instructions[XOP_COUNT] = { [XOP_SUB_RM1632_R1632] = { false, 0x29, IDX_TO_EXT(-1), "sub", XPX_OPERAND_SIZE_OVERRIDE }, [XOP_SUB_R8_RM8] = { false, 0x2a, IDX_TO_EXT(-1), "sub", XPX_NONE }, + [XOP_SUB_R1632_RM1632] = { false, 0x2b, IDX_TO_EXT(-1), "sub", XPX_OPERAND_SIZE_OVERRIDE }, [XOP_SUB_AL_IMM8] = { false, 0x2c, IDX_TO_EXT(-1), "sub", XPX_NONE }, [XOP_SUB_E_AX_IMM1632] = { false, 0x2d, IDX_TO_EXT(-1), "sub", XPX_OPERAND_SIZE_OVERRIDE }, @@ -145,9 +135,12 @@ static x86_instruction _instructions[XOP_COUNT] = { + [XOP_CMP_RM8_R8] = { false, 0x38, IDX_TO_EXT(-1), "cmp", XPX_NONE }, [XOP_CMP_RM1632_R1632] = { false, 0x39, IDX_TO_EXT(-1), "cmp", XPX_OPERAND_SIZE_OVERRIDE }, [XOP_CMP_R1632_RM1632] = { false, 0x3b, IDX_TO_EXT(-1), "cmp", XPX_OPERAND_SIZE_OVERRIDE }, + [XOP_CMP_AL_IMM8] = { false, 0x3c, IDX_TO_EXT(-1), "cmp", XPX_NONE }, + [XOP_CMP_E_AX_IMM1632] = { false, 0x3d, IDX_TO_EXT(-1), "cmp", XPX_OPERAND_SIZE_OVERRIDE }, [XOP_INC_E_AX] = { true, 0x40, IDX_TO_EXT(-1), "inc", XPX_OPERAND_SIZE_OVERRIDE }, @@ -272,6 +265,7 @@ static x86_instruction _instructions[XOP_COUNT] = { [XOP_MOVS_M1632_M1632] = { false, 0xa5, IDX_TO_EXT(-1), "movs", XPX_OPERAND_SIZE_OVERRIDE }, + [XOP_CMPS_M8_M8] = { false, 0xa6, IDX_TO_EXT(-1), "cmps", XPX_NONE }, [XOP_TEST_AL_IMM8] = { false, 0xa8, IDX_TO_EXT(-1), "test", XPX_NONE }, [XOP_TEST_E_AX_IMM1632] = { false, 0xa9, IDX_TO_EXT(-1), "test", XPX_OPERAND_SIZE_OVERRIDE }, @@ -355,7 +349,53 @@ static x86_instruction _instructions[XOP_COUNT] = { [XOP_DEC_RM1632] = { false, 0xff, IDX_TO_EXT(1), "dec", XPX_OPERAND_SIZE_OVERRIDE }, [XOP_CALL_RM1632] = { false, 0xff, IDX_TO_EXT(2), "call", XPX_OPERAND_SIZE_OVERRIDE }, [XOP_JMP_RM1632] = { false, 0xff, IDX_TO_EXT(4), "jmp", XPX_OPERAND_SIZE_OVERRIDE }, - [XOP_PUSH_RM1632] = { false, 0xff, IDX_TO_EXT(6), "push", XPX_OPERAND_SIZE_OVERRIDE } + [XOP_PUSH_RM1632] = { false, 0xff, IDX_TO_EXT(6), "push", XPX_OPERAND_SIZE_OVERRIDE }, + + + + + + + /* Instructions avec opcode sur deux octets */ + + [XOP_JO_REL1632] = { false, 0x80, IDX_TO_EXT(-1), "jo", XPX_TWO_BYTES | XPX_OPERAND_SIZE_OVERRIDE }, + [XOP_JNO_REL1632] = { false, 0x81, IDX_TO_EXT(-1), "jno", XPX_TWO_BYTES | XPX_OPERAND_SIZE_OVERRIDE }, + [XOP_JB_REL1632] = { false, 0x82, IDX_TO_EXT(-1), "jb", XPX_TWO_BYTES | XPX_OPERAND_SIZE_OVERRIDE }, + [XOP_JNB_REL1632] = { false, 0x83, IDX_TO_EXT(-1), "jnb", XPX_TWO_BYTES | XPX_OPERAND_SIZE_OVERRIDE }, + [XOP_JE_REL1632] = { false, 0x84, IDX_TO_EXT(-1), "je", XPX_TWO_BYTES | XPX_OPERAND_SIZE_OVERRIDE }, + [XOP_JNE_REL1632] = { false, 0x85, IDX_TO_EXT(-1), "jne", XPX_TWO_BYTES | XPX_OPERAND_SIZE_OVERRIDE }, + [XOP_JNA_REL1632] = { false, 0x86, IDX_TO_EXT(-1), "jna", XPX_TWO_BYTES | XPX_OPERAND_SIZE_OVERRIDE }, + [XOP_JA_REL1632] = { false, 0x87, IDX_TO_EXT(-1), "ja", XPX_TWO_BYTES | XPX_OPERAND_SIZE_OVERRIDE }, + [XOP_JS_REL1632] = { false, 0x88, IDX_TO_EXT(-1), "js", XPX_TWO_BYTES | XPX_OPERAND_SIZE_OVERRIDE }, + [XOP_JNS_REL1632] = { false, 0x89, IDX_TO_EXT(-1), "jns", XPX_TWO_BYTES | XPX_OPERAND_SIZE_OVERRIDE }, + [XOP_JP_REL1632] = { false, 0x8a, IDX_TO_EXT(-1), "jp", XPX_TWO_BYTES | XPX_OPERAND_SIZE_OVERRIDE }, + [XOP_JNP_REL1632] = { false, 0x8b, IDX_TO_EXT(-1), "jnp", XPX_TWO_BYTES | XPX_OPERAND_SIZE_OVERRIDE }, + [XOP_JL_REL1632] = { false, 0x8c, IDX_TO_EXT(-1), "jl", XPX_TWO_BYTES | XPX_OPERAND_SIZE_OVERRIDE }, + [XOP_JNL_REL1632] = { false, 0x8d, IDX_TO_EXT(-1), "jnl", XPX_TWO_BYTES | XPX_OPERAND_SIZE_OVERRIDE }, + [XOP_JNG_REL1632] = { false, 0x8e, IDX_TO_EXT(-1), "jng", XPX_TWO_BYTES | XPX_OPERAND_SIZE_OVERRIDE }, + [XOP_JG_REL1632] = { false, 0x8f, IDX_TO_EXT(-1), "jg", XPX_TWO_BYTES | XPX_OPERAND_SIZE_OVERRIDE }, + [XOP_SETO_RM8] = { false, 0x90, IDX_TO_EXT(-1), "seto", XPX_TWO_BYTES }, + [XOP_SETNO_RM8] = { false, 0x91, IDX_TO_EXT(-1), "setno", XPX_TWO_BYTES }, + [XOP_SETB_RM8] = { false, 0x92, IDX_TO_EXT(-1), "setn", XPX_TWO_BYTES }, + [XOP_SETNB_RM8] = { false, 0x93, IDX_TO_EXT(-1), "setnb", XPX_TWO_BYTES }, + [XOP_SETE_RM8] = { false, 0x94, IDX_TO_EXT(-1), "sete", XPX_TWO_BYTES }, + [XOP_SETNE_RM8] = { false, 0x95, IDX_TO_EXT(-1), "setne", XPX_TWO_BYTES }, + [XOP_SETNA_RM8] = { false, 0x96, IDX_TO_EXT(-1), "setna", XPX_TWO_BYTES }, + [XOP_SETA_RM8] = { false, 0x97, IDX_TO_EXT(-1), "seta", XPX_TWO_BYTES }, + [XOP_SETS_RM8] = { false, 0x98, IDX_TO_EXT(-1), "sets", XPX_TWO_BYTES }, + [XOP_SETNS_RM8] = { false, 0x99, IDX_TO_EXT(-1), "setns", XPX_TWO_BYTES }, + [XOP_SETP_RM8] = { false, 0x9a, IDX_TO_EXT(-1), "setp", XPX_TWO_BYTES }, + [XOP_SETNP_RM8] = { false, 0x9b, IDX_TO_EXT(-1), "setnp", XPX_TWO_BYTES }, + [XOP_SETL_RM8] = { false, 0x9c, IDX_TO_EXT(-1), "setl", XPX_TWO_BYTES }, + [XOP_SETNL_RM8] = { false, 0x9d, IDX_TO_EXT(-1), "setnl", XPX_TWO_BYTES }, + [XOP_SETNG_RM8] = { false, 0x9e, IDX_TO_EXT(-1), "setng", XPX_TWO_BYTES }, + [XOP_SETG_RM8] = { false, 0x9f, IDX_TO_EXT(-1), "setg", XPX_TWO_BYTES }, + + + + [XOP_MOVZX_R1632_RM8] = { false, 0xb6, IDX_TO_EXT(-1), "movzx", XPX_TWO_BYTES | XPX_OPERAND_SIZE_OVERRIDE }, + [XOP_MOVSX_R1632_RM8] = { false, 0xbe, IDX_TO_EXT(-1), "movsx", XPX_TWO_BYTES | XPX_OPERAND_SIZE_OVERRIDE }, + [XOP_MOVSX_R1632_RM1632] = { false, 0xbf, IDX_TO_EXT(-1), "movsx", XPX_TWO_BYTES | XPX_OPERAND_SIZE_OVERRIDE } }; @@ -364,7 +404,7 @@ static x86_instruction _instructions[XOP_COUNT] = { /* Traduit une instruction en version humainement lisible. */ -static const char *x86_get_instruction_text(const GX86Instruction *, const GExeFormat *, AsmSyntax); +static const char *x86_get_instruction_text(GX86Instruction *, const GExeFormat *, AsmSyntax); /* Informe sur une éventuelle référence à une autre instruction. */ static InstructionLinkType x86_get_instruction_link(const GX86Instruction *, vmpa_t *); @@ -529,9 +569,12 @@ X86Opcodes x86_guess_next_instruction(const bin_t *data, off_t pos, off_t len, X *prefix |= XPX_OPERAND_SIZE_OVERRIDE; break; case 0xf2: + pos++; + extra |= XPX_REPEAT_STR_OPERATION_F2; + break; case 0xf3: pos++; - extra |= XPX_REPEAT_STRING_OPERATION; + extra |= XPX_REPEAT_STR_OPERATION_F3; break; default: goto xgni_look_for; @@ -586,19 +629,60 @@ X86Opcodes x86_guess_next_instruction(const bin_t *data, off_t pos, off_t len, X * * ******************************************************************************/ -static const char *x86_get_instruction_text(const GX86Instruction *instr, const GExeFormat *format, AsmSyntax syntax) +static const char *x86_get_instruction_text(GX86Instruction *instr, const GExeFormat *format, AsmSyntax syntax) { - const char *result; /* Chaîne à retourner */ + char *result; /* Chaîne nouvelle à renvoyer */ + const char *prefix; /* Préfixe à ajouter */ - return _instructions[instr->type].keyword; + if (instr->cached_text != NULL) + return instr->cached_text; result = strdup(_instructions[instr->type].keyword); - /* FIXME : - http://www.intel.com/software/products/documentation/vlin/mergedprojects/analyzer_ec/mergedprojects/reference_olh/mergedProjects/instructions/instruct32_hh/vc276.htm - */ - if (instr->prefixes & XPX_REPEAT_STRING_OPERATION) - result = strprep(result, "rep "/*"repnz "*/); + /** + * Eventuelle répétion de l'instruction. + * cf. "Repeat String Operation Prefix" (Intel 64 and IA-32 Architectures Software Developer’s Manual Volume 2B) + * cf. http://www.intel.com/software/products/documentation/vlin/mergedprojects/analyzer_ec/mergedprojects/reference_olh/mergedProjects/instructions/instruct32_hh/vc276.htm + */ + + if (instr->prefixes & (XPX_REPEAT_STR_OPERATION_F2 | XPX_REPEAT_STR_OPERATION_F3)) + { + prefix = NULL; + + if (instr->prefixes & XPX_REPEAT_STR_OPERATION_F2) + switch (instr->type) + { + case XOP_CMPS_M8_M8: + prefix = "repnz "; + break; + case XOP_SCAS_AL_M8: + prefix = "repnz "; + break; + default: + prefix = NULL; + break; + } + + else if (instr->prefixes & XPX_REPEAT_STR_OPERATION_F3) + switch (instr->type) + { + case XOP_CMPS_M8_M8: + prefix = "repz "; + break; + case XOP_SCAS_AL_M8: + prefix = "repz "; + break; + default: + prefix = NULL; + break; + } + + if (prefix != NULL) + result = strprep(result, prefix); + + } + + instr->cached_text = result; return result; @@ -625,7 +709,7 @@ static InstructionLinkType x86_get_instruction_link(const GX86Instruction *instr switch (instr->type) { - case XOP_JLE_REL1632: + case XOP_JA_REL1632: relative = G_X86_RELATIVE_OPERAND(g_arch_instruction_get_operand(G_ARCH_INSTRUCTION(instr), 0)); if (g_imm_operand_to_vmpa_t(g_x86_relative_operand_get_value(relative), addr)) result = ILT_JUMP_IF_TRUE; else result = ILT_NONE; |