summaryrefslogtreecommitdiff
path: root/src/arch/x86/instruction.c
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2010-08-16 23:04:49 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2010-08-16 23:04:49 (GMT)
commit9ed927a6b6405633a82f378438c533fd0112f16d (patch)
tree69875ffb288bf0dcd57a3b7cee546eca85115914 /src/arch/x86/instruction.c
parentdb70af80e01199bd2329f0363b9f7769dee1a783 (diff)
Supported several extra x86 instructions.
git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@181 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a
Diffstat (limited to 'src/arch/x86/instruction.c')
-rw-r--r--src/arch/x86/instruction.c148
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;