begin working on instruction matching

This commit is contained in:
mykola2312 2024-08-16 09:41:41 +03:00
parent 4bfa581481
commit b636bc8891

View file

@ -1,5 +1,6 @@
#include "rtdisasm.h" #include "rtdisasm.h"
#include "rtdisasm_table.h" #include "rtdisasm_table.h"
#include <string.h>
// prefix definitions. must be declared with macro in order // prefix definitions. must be declared with macro in order
// to be readable later in prefix table // to be readable later in prefix table
@ -44,6 +45,16 @@ static int is_std_prefix(const uint8_t prefix)
return 0; return 0;
} }
#define VEX_2BYTE 0xC5
#define VEX_3BYTE 0xC4
static int test_vex_prefix(const uint8_t vex_first)
{
if (vex_first == VEX_2BYTE) return 2;
else if (vex_first == VEX_3BYTE) return 3;
else return 0;
}
#define REX_SIG 0b01000000 #define REX_SIG 0b01000000
#define REX_MASK 0b11110000 #define REX_MASK 0b11110000
#define REX_VALUE_MASK 0b00001111 #define REX_VALUE_MASK 0b00001111
@ -69,18 +80,33 @@ static int test_rex_prefix(const uint8_t rex)
return -1; return -1;
} }
// returns -1 if reached end, 0 if no instruction found, const instruction_t* find_instruction(const uint8_t* cur, unsigned type, int vex, int rex)
// and non-zero is actual instruction length
static int match_instruction(const uint8_t* cur, const uint8_t* const end, instruction_t* ins)
{ {
// test if its rex prefix, if so we will look specifically for for (unsigned i = 0; i < rtdisasm_table_len; i++)
// instructions with rex prefix
int rex = test_rex_prefix(*cur);
if (rex != -1)
{ {
// it's rex, so advance 1 byte const instruction_t* ins = &rtdisasm_table[i];
if (++cur == end) return -1;
if (ins->config.type != type) continue;
// check rex if instruction does rex, and if provided rex is not -1
if (rex != -1 && type == INSTRUCTION_STD
&& ins->config.has_rex && ins->std.rex != rex)
{
// rex doesn't match, skip instruction
continue;
} }
// compare opcodes
if (memcmp(cur, &ins->opcode, ins->opcode_len))
{
// opcodes don't match up, skip
continue;
}
// for now, everything looks good, so that's our instruction
return ins;
}
return NULL;
} }
int rtdisasm_analyze_single(const uint8_t* code, uint8_t size) int rtdisasm_analyze_single(const uint8_t* code, uint8_t size)
@ -92,8 +118,29 @@ int rtdisasm_analyze_single(const uint8_t* code, uint8_t size)
// skip standard prefixes // skip standard prefixes
while (is_std_prefix(*cur)) while (is_std_prefix(*cur))
{ {
if (++cur == end) return 0; if (++cur == end) return -1;
} }
// now we need to taste instructions unsigned type = INSTRUCTION_STD;
// first, we need to test vex prefix, because only then comes the rex
int vex = test_vex_prefix(*cur);
if (vex)
{
// it's vex, lets advance 2 or 3 bytes
cur += vex;
if (cur >= end) return -1;
type = INSTRUCTION_VEX;
}
// test if its rex prefix, if so we will look specifically for
// instructions with rex prefix
int rex = test_rex_prefix(*cur);
if (rex != -1)
{
// it's rex, so advance 1 byte
if (++cur >= end) return -1;
}
const instruction_t* ins = find_instruction(cur, type, vex, rex);
} }