Major changes to the instruction decoder

- Decoupled semantic operand decoding (optional) from physical instruction decoding
- Several optimizations of the internal structures
- Further preparations for MVEX-support
This commit is contained in:
flobernd 2017-06-12 19:16:01 +02:00
parent e5e5899f72
commit 8740b1e50f
20 changed files with 48043 additions and 39538 deletions

View File

@ -37,7 +37,6 @@
#include <Zydis/Zydis.h>
#include "FormatHelper.h"
#include <stdlib.h>
#include <time.h>
/* ============================================================================================== */
/* Static data */
@ -173,7 +172,8 @@ static ZydisStatus ZydisFormatterFormatOperandImm(ZydisInstructionFormatter* for
/* Helper functions */
/* ============================================================================================== */
void disassembleBuffer(uint8_t* data, size_t length, ZydisBool installHooks)
void disassembleBuffer(ZydisInstructionDecoder* decoder, uint8_t* data, size_t length,
ZydisBool installHooks)
{
ZydisInstructionFormatter formatter;
ZydisFormatterInitInstructionFormatterEx(&formatter, ZYDIS_FORMATTER_STYLE_INTEL,
@ -195,7 +195,7 @@ void disassembleBuffer(uint8_t* data, size_t length, ZydisBool installHooks)
ZydisInstructionInfo info;
char buffer[256];
while (ZYDIS_SUCCESS(
ZydisDecode(ZYDIS_OPERATING_MODE_64BIT, data, length, instructionPointer, &info)))
ZydisDecoderDecodeBuffer(decoder, data, length, instructionPointer, &info)))
{
data += info.length;
length -= info.length;
@ -210,6 +210,8 @@ void disassembleBuffer(uint8_t* data, size_t length, ZydisBool installHooks)
/* Entry point */
/* ============================================================================================== */
#include <Zydis/Internal/InstructionTable.h>
int main()
{
@ -218,16 +220,20 @@ int main()
// cmpps xmm1, xmm4, 0x03
0x0F, 0xC2, 0xCC, 0x03,
// vcmpord_spd xmm1, xmm2, xmm3
// vcmppd xmm1, xmm2, xmm3, 0x17
0xC5, 0xE9, 0xC2, 0xCB, 0x17,
// vcmpps k2 {k7}, zmm2, dword ptr ds:[rax + rbx*4 + 0x100] {1to16}, 0x0F
0x62, 0xF1, 0x6C, 0x5F, 0xC2, 0x54, 0x98, 0x40, 0x0F
};
disassembleBuffer(&data[0], sizeof(data), ZYDIS_FALSE);
ZydisInstructionDecoder decoder;
ZydisDecoderInitInstructionDecoder(
&decoder, ZYDIS_MACHINE_MODE_LONG_64, ZYDIS_ADDRESS_WIDTH_INVALID);
disassembleBuffer(&decoder, &data[0], sizeof(data), ZYDIS_FALSE);
puts("");
disassembleBuffer(&data[0], sizeof(data), ZYDIS_TRUE);
disassembleBuffer(&decoder, &data[0], sizeof(data), ZYDIS_TRUE);
getchar();
return 0;

View File

@ -51,10 +51,23 @@ typedef uint32_t ZydisDecodeGranularity;
enum ZydisDecodeGranularities
{
ZYDIS_DECODE_GRANULARITY_DEFAULT,
/**
* @brief Minimal instruction decoding without semantic operand analysis.
*/
ZYDIS_DECODE_GRANULARITY_MINIMAL,
ZYDIS_DECODE_GRANULARITY_FULL
};
/**
* @brief Defines the @c ZydisInstructionDecoder datatype.
*/
typedef struct ZydisInstructionDecoder_
{
ZydisMachineMode machineMode;
ZydisAddressWidth addressWidth;
ZydisDecodeGranularity decodeGranularity;
} ZydisInstructionDecoder;
/* ---------------------------------------------------------------------------------------------- */
/* ============================================================================================== */
@ -62,36 +75,45 @@ enum ZydisDecodeGranularities
/* ============================================================================================== */
/**
* @brief Decodes the instruction in the given input @c buffer.
* @brief Initializes the given @c ZydisInstructionDecoder instance.
*
* @param operatingMode The desired operating mode.
* @param buffer A pointer to the input buffer.
* @param bufferLen The length of the input buffer.
* @param instructionPointer The instruction-pointer.
* @param info A pointer to the @c ZydisInstructionInfo struct, that receives the
* details about the decoded instruction.
* @param decoder A pointer to the @c ZydisInstructionDecoder instance.
* @param machineMode The machine mode.
* @param addressWidth The address width.
*
* @return A zydis status code.
* @return A zydis status code.
*/
ZYDIS_EXPORT ZydisStatus ZydisDecode(ZydisOperatingMode operatingMode, const void* buffer,
size_t bufferLen, uint64_t instructionPointer, ZydisInstructionInfo* info);
ZYDIS_EXPORT ZydisStatus ZydisDecoderInitInstructionDecoder(ZydisInstructionDecoder* decoder,
ZydisMachineMode machineMode, ZydisAddressWidth addressWidth);
/**
* @brief Initializes the given @c ZydisInstructionDecoder instance.
*
* @param decoder A pointer to the @c ZydisInstructionDecoder instance.
* @param machineMode The machine mode.
* @param addressWidth The address width.
* @param decodeGranularity The decode granularity.
*
* @return A zydis status code.
*/
ZYDIS_EXPORT ZydisStatus ZydisDecoderInitInstructionDecoderEx(ZydisInstructionDecoder* decoder,
ZydisMachineMode machineMode, ZydisAddressWidth addressWidth,
ZydisDecodeGranularity decodeGranularity);
/**
* @brief Decodes the instruction in the given input @c buffer.
*
* @param operatingMode The desired operating mode.
* @param decoder A pointer to the @c ZydisInstructionDecoder instance.
* @param buffer A pointer to the input buffer.
* @param bufferLen The length of the input buffer.
* @param instructionPointer The instruction-pointer.
* @param granularity The granularity to decode with.
* @param info A pointer to the @c ZydisInstructionInfo struct, that receives the
* details about the decoded instruction.
*
* @return A zydis status code.
*/
ZYDIS_EXPORT ZydisStatus ZydisDecodeEx(ZydisOperatingMode operatingMode, const void* buffer,
size_t bufferLen, uint64_t instructionPointer, ZydisDecodeGranularity granularity,
ZydisInstructionInfo* info);
ZYDIS_EXPORT ZydisStatus ZydisDecoderDecodeBuffer(ZydisInstructionDecoder* decoder,
const void* buffer, size_t bufferLen, uint64_t instructionPointer, ZydisInstructionInfo* info);
/* ============================================================================================== */

View File

@ -119,11 +119,13 @@
#define ZYDIS_ASSERT(condition) assert(condition)
#if defined(ZYDIS_MSVC) && defined(ZYDIS_RELEASE)
# define ZYDIS_UNREACHABLE
#elif defined(ZYDIS_GNUC) && defined(ZYDIS_RELEASE)
# if __has_builtin(__builtin_unreachable)
# define ZYDIS_UNREACHABLE __builtin_unreachable()
#if defined(ZYDIS_RELEASE)
# if defined(ZYDIS_GNUC)
# if __has_builtin(__builtin_unreachable)
# define ZYDIS_UNREACHABLE __builtin_unreachable()
# else
# define ZYDIS_UNREACHABLE
# endif
# else
# define ZYDIS_UNREACHABLE
# endif

View File

@ -392,22 +392,64 @@ typedef struct ZydisOperandInfo_
/* ============================================================================================== */
/* ---------------------------------------------------------------------------------------------- */
/* Disassembler mode */
/* Machine mode */
/* ---------------------------------------------------------------------------------------------- */
/**
* @brief Defines the @c ZydisOperatingMode datatype.
* @brief Defines the @c ZydisMachineMode datatype.
*/
typedef uint8_t ZydisOperatingMode;
typedef uint8_t ZydisMachineMode;
/**
* @brief Values that represent operating modes.
* @brief Values that represent machine modes.
*/
enum ZydisOperatingModes
enum ZydisMachineModes
{
ZYDIS_OPERATING_MODE_16BIT = 16,
ZYDIS_OPERATING_MODE_32BIT = 32,
ZYDIS_OPERATING_MODE_64BIT = 64
ZYDIS_MACHINE_MODE_INVALID = 0,
/**
* @brief 64 bit mode.
*/
ZYDIS_MACHINE_MODE_LONG_64 = 64,
/**
* @brief 32 bit protected mode.
*/
ZYDIS_MACHINE_MODE_LONG_COMPAT_32 = 32,
/**
* @brief 16 bit protected mode.
*/
ZYDIS_MACHINE_MODE_LONG_COMPAT_16 = 16,
/**
* @brief 32 bit protected mode.
*/
ZYDIS_MACHINE_MODE_LEGACY_32 = 32,
/**
* @brief 16 bit protected mode.
*/
ZYDIS_MACHINE_MODE_LEGACY_16 = 16,
/**
* @brief 16 bit real mode.
*/
ZYDIS_MACHINE_MODE_REAL_16 = 16
};
/* ---------------------------------------------------------------------------------------------- */
/* Address width */
/* ---------------------------------------------------------------------------------------------- */
/**
* @brief Defines the @c ZydisAddressWidth datatype.
*/
typedef uint8_t ZydisAddressWidth;
/**
* @brief Values that represent address widths.
*/
enum ZydisAddressWidths
{
ZYDIS_ADDRESS_WIDTH_INVALID = 0,
ZYDIS_ADDRESS_WIDTH_16 = 16,
ZYDIS_ADDRESS_WIDTH_32 = 32,
ZYDIS_ADDRESS_WIDTH_64 = 64
};
/* ---------------------------------------------------------------------------------------------- */
@ -425,25 +467,29 @@ typedef uint8_t ZydisInstructionEncoding;
enum ZydisInstructionEncodings
{
/**
* @brief The instruction uses the default operand-encoding.
* @brief The instruction uses the default encoding.
*/
ZYDIS_INSTRUCTION_ENCODING_DEFAULT = 0x00,
/**
* @brief The instruction uses the AMD 3DNow operand-encoding.
* @brief The instruction uses the AMD 3DNow-encoding.
*/
ZYDIS_INSTRUCTION_ENCODING_3DNOW = 0x01,
/**
* @brief The instruction uses the AMD XOP operand-encoding.
* @brief The instruction uses the AMD XOP-encoding.
*/
ZYDIS_INSTRUCTION_ENCODING_XOP = 0x02,
/**
* @brief The instruction uses the VEX operand-encoding.
* @brief The instruction uses the VEX-encoding.
*/
ZYDIS_INSTRUCTION_ENCODING_VEX = 0x03,
/**
* @brief The instruction uses the EVEX operand-encoding.
* @brief The instruction uses the EVEX-encoding.
*/
ZYDIS_INSTRUCTION_ENCODING_EVEX = 0x04
ZYDIS_INSTRUCTION_ENCODING_EVEX = 0x04,
/**
* @brief The instruction uses the MVEX-encoding.
*/
ZYDIS_INSTRUCTION_ENCODING_MVEX = 0x05
};
/* ---------------------------------------------------------------------------------------------- */
@ -461,12 +507,13 @@ typedef uint8_t ZydisOpcodeMap;
enum ZydisOpcodeMaps
{
ZYDIS_OPCODE_MAP_DEFAULT = 0x00,
ZYDIS_OPCODE_MAP_0F = 0x01,
ZYDIS_OPCODE_MAP_0F38 = 0x02,
ZYDIS_OPCODE_MAP_0F3A = 0x03,
ZYDIS_OPCODE_MAP_XOP8 = 0x04,
ZYDIS_OPCODE_MAP_XOP9 = 0x05,
ZYDIS_OPCODE_MAP_XOPA = 0x06
ZYDIS_OPCODE_MAP_EX0 = 0x01,
ZYDIS_OPCODE_MAP_0F = 0x02,
ZYDIS_OPCODE_MAP_0F38 = 0x03,
ZYDIS_OPCODE_MAP_0F3A = 0x04,
ZYDIS_OPCODE_MAP_XOP8 = 0x05,
ZYDIS_OPCODE_MAP_XOP9 = 0x06,
ZYDIS_OPCODE_MAP_XOPA = 0x07
};
/* ---------------------------------------------------------------------------------------------- */
@ -565,11 +612,11 @@ typedef uint64_t ZydisInstructionAttributes;
/**
* @brief The instruction accepts the operand-size prefix (0x66).
*/
#define ZYDIS_ATTRIB_ACCEPTS_OPERANDSIZE 0x0000000000040000
#define ZYDIS_ATTRIB_ACCEPTS_OPERANDSIZE 0x0000000000040000 // TODO: Remove
/**
* @brief The instruction accepts the address-size prefix (0x67).
*/
#define ZYDIS_ATTRIB_ACCEPTS_ADDRESSSIZE 0x0000000000080000
#define ZYDIS_ATTRIB_ACCEPTS_ADDRESSSIZE 0x0000000000080000 // TODO: Remove
/**
* @brief The instruction has the lock prefix (0xF0).
*/
@ -783,9 +830,9 @@ enum ZydisAVXRoundingModes
typedef struct ZydisInstructionInfo_
{
/**
* @brief The operating mode used to decode this instruction.
* @brief The machine mode used to decode this instruction.
*/
ZydisOperatingMode mode;
ZydisMachineMode machineMode;
/**
* @brief The instruction-mnemonic.
*/
@ -810,6 +857,14 @@ typedef struct ZydisInstructionInfo_
* @brief The instruction-opcode.
*/
uint8_t opcode;
/**
* @brief The effective operand size.
*/
uint8_t operandSize;
/**
* @brief The effective address width.
*/
uint8_t addressWidth;
/**
* @brief The number of instruction-operands.
*/
@ -875,7 +930,8 @@ typedef struct ZydisInstructionInfo_
*/
struct
{
uint8_t data[ZYDIS_MAX_INSTRUCTION_LENGTH - 1]; // TODO:
uint8_t data[ZYDIS_MAX_INSTRUCTION_LENGTH - 1];
uint8_t count;
uint8_t hasF0;
uint8_t hasF3;
uint8_t hasF2;
@ -1140,7 +1196,7 @@ typedef struct ZydisInstructionInfo_
/**
* @brief Embedded opmask register specifier.
*/
uint8_t aaa;
uint8_t kkk;
} mvex;
/**
* @brief Detailed info about the ModRM-byte.
@ -1198,6 +1254,12 @@ typedef struct ZydisInstructionInfo_
* @brief Signals, if the immediate value is signed.
*/
ZydisBool isSigned;
/**
* @brief Signals, if the immediate value contains a relative offset. You can use
* @c ZydisUtilsCalcAbsoluteTargetAddress to determine the absolute address
* value.
*/
ZydisBool isRelative;
/**
* @brief The immediate value.
*/

View File

@ -1,25 +0,0 @@
typedef struct ZydisInstructionDefinition_
{
uint32_t mnemonic : 11;
uint32_t operandsId : 9;
uint32_t evexContext : 2;
uint32_t evexMaskPolicy : 2;
uint32_t evexZeroMaskAccepted : 1;
uint32_t acceptsLock : 1;
uint32_t acceptsREP : 1;
uint32_t acceptsREPEREPNE : 1;
uint32_t acceptsBOUND : 1;
uint32_t acceptsXACQUIRE : 1;
uint32_t acceptsXRELEASE : 1;
uint32_t acceptsHLEWithoutLock : 1;
uint32_t acceptsBranchHints : 1;
#ifdef ZYDIS_ENABLE_FEATURE_IMPLICITLY_USED_REGISTERS
uint8_t implicitRegistersId : 8;
#endif
#ifdef ZYDIS_ENABLE_FEATURE_AFFECTED_FLAGS
uint8_t affectedFlagsId : 8;
#endif
#ifdef ZYDIS_ENABLE_FEATURE_CPUID
uint8_t cpuidId : 8;
#endif
} ZydisInstructionDefinition;

View File

@ -0,0 +1,20 @@
static const ZydisInstructionParts instructionClassMap[] =
{
/*00*/ { 0, { { 0, 0, 0 } }, { { { 0, 0, 0 }, ZYDIS_FALSE, ZYDIS_FALSE }, { { 0, 0, 0 }, ZYDIS_FALSE, ZYDIS_FALSE } } },
/*01*/ { 0 | ZYDIS_INSTRPART_FLAG_HAS_IMM0, { { 0, 0, 0 } }, { { { 8, 8, 8 }, ZYDIS_TRUE, ZYDIS_FALSE }, { { 0, 0, 0 }, ZYDIS_FALSE, ZYDIS_FALSE } } },
/*02*/ { 0 | ZYDIS_INSTRPART_FLAG_HAS_MODRM, { { 0, 0, 0 } }, { { { 0, 0, 0 }, ZYDIS_FALSE, ZYDIS_FALSE }, { { 0, 0, 0 }, ZYDIS_FALSE, ZYDIS_FALSE } } },
/*03*/ { 0 | ZYDIS_INSTRPART_FLAG_HAS_IMM0, { { 0, 0, 0 } }, { { { 16, 32, 32 }, ZYDIS_TRUE, ZYDIS_FALSE }, { { 0, 0, 0 }, ZYDIS_FALSE, ZYDIS_FALSE } } },
/*04*/ { 0 | ZYDIS_INSTRPART_FLAG_HAS_MODRM | ZYDIS_INSTRPART_FLAG_HAS_IMM0, { { 0, 0, 0 } }, { { { 8, 8, 8 }, ZYDIS_TRUE, ZYDIS_FALSE }, { { 0, 0, 0 }, ZYDIS_FALSE, ZYDIS_FALSE } } },
/*05*/ { 0 | ZYDIS_INSTRPART_FLAG_HAS_MODRM | ZYDIS_INSTRPART_FLAG_HAS_IMM0, { { 0, 0, 0 } }, { { { 16, 32, 32 }, ZYDIS_TRUE, ZYDIS_FALSE }, { { 0, 0, 0 }, ZYDIS_FALSE, ZYDIS_FALSE } } },
/*06*/ { 0 | ZYDIS_INSTRPART_FLAG_HAS_MODRM | ZYDIS_INSTRPART_FLAG_HAS_IMM0, { { 0, 0, 0 } }, { { { 8, 8, 8 }, ZYDIS_FALSE, ZYDIS_FALSE }, { { 0, 0, 0 }, ZYDIS_FALSE, ZYDIS_FALSE } } },
/*07*/ { 0 | ZYDIS_INSTRPART_FLAG_HAS_IMM0 | ZYDIS_INSTRPART_FLAG_HAS_IMM1, { { 0, 0, 0 } }, { { { 16, 32, 32 }, ZYDIS_TRUE, ZYDIS_TRUE }, { { 16, 16, 16 }, ZYDIS_FALSE, ZYDIS_FALSE } } },
/*08*/ { 0 | ZYDIS_INSTRPART_FLAG_HAS_IMM0, { { 0, 0, 0 } }, { { { 16, 32, 32 }, ZYDIS_TRUE, ZYDIS_TRUE }, { { 0, 0, 0 }, ZYDIS_FALSE, ZYDIS_FALSE } } },
/*09*/ { 0 | ZYDIS_INSTRPART_FLAG_HAS_IMM0, { { 0, 0, 0 } }, { { { 32, 32, 32 }, ZYDIS_TRUE, ZYDIS_TRUE }, { { 0, 0, 0 }, ZYDIS_FALSE, ZYDIS_FALSE } } },
/*0A*/ { 0 | ZYDIS_INSTRPART_FLAG_HAS_IMM0 | ZYDIS_INSTRPART_FLAG_HAS_IMM1, { { 0, 0, 0 } }, { { { 16, 16, 16 }, ZYDIS_FALSE, ZYDIS_FALSE }, { { 8, 8, 8 }, ZYDIS_FALSE, ZYDIS_FALSE } } },
/*0B*/ { 0 | ZYDIS_INSTRPART_FLAG_HAS_IMM0, { { 0, 0, 0 } }, { { { 8, 8, 8 }, ZYDIS_FALSE, ZYDIS_FALSE }, { { 0, 0, 0 }, ZYDIS_FALSE, ZYDIS_FALSE } } },
/*0C*/ { 0 | ZYDIS_INSTRPART_FLAG_HAS_IMM0, { { 0, 0, 0 } }, { { { 8, 8, 8 }, ZYDIS_TRUE, ZYDIS_TRUE }, { { 0, 0, 0 }, ZYDIS_FALSE, ZYDIS_FALSE } } },
/*0D*/ { 0 | ZYDIS_INSTRPART_FLAG_HAS_DISP, { { 16, 32, 64 } }, { { { 0, 0, 0 }, ZYDIS_FALSE, ZYDIS_FALSE }, { { 0, 0, 0 }, ZYDIS_FALSE, ZYDIS_FALSE } } },
/*0E*/ { 0 | ZYDIS_INSTRPART_FLAG_HAS_IMM0, { { 0, 0, 0 } }, { { { 16, 32, 64 }, ZYDIS_FALSE, ZYDIS_FALSE }, { { 0, 0, 0 }, ZYDIS_FALSE, ZYDIS_FALSE } } },
/*0F*/ { 0 | ZYDIS_INSTRPART_FLAG_HAS_IMM0, { { 0, 0, 0 } }, { { { 16, 16, 16 }, ZYDIS_FALSE, ZYDIS_FALSE }, { { 0, 0, 0 }, ZYDIS_FALSE, ZYDIS_FALSE } } },
/*10*/ { 0 | ZYDIS_INSTRPART_FLAG_HAS_MODRM | ZYDIS_INSTRPART_FLAG_HAS_IMM0, { { 0, 0, 0 } }, { { { 32, 32, 32 }, ZYDIS_FALSE, ZYDIS_FALSE }, { { 0, 0, 0 }, ZYDIS_FALSE, ZYDIS_FALSE } } }
};

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -39,10 +39,6 @@ extern "C" {
/* Enums and types */
/* ============================================================================================== */
/* ---------------------------------------------------------------------------------------------- */
/* Generated types */
/* ---------------------------------------------------------------------------------------------- */
// MSVC does not like types other than (un-)signed int for bitfields
#ifdef ZYDIS_MSVC
# pragma warning(push)
@ -51,47 +47,188 @@ extern "C" {
#pragma pack(push, 1)
/**
* @brief Defines the @c ZydisInstructionTableNodeType datatype.
*/
typedef uint8_t ZydisInstructionTableNodeType;
/* ---------------------------------------------------------------------------------------------- */
/* Instruction tree */
/* ---------------------------------------------------------------------------------------------- */
/**
* @brief Defines the @c ZydisInstructionTableNodeValue datatype.
*/
typedef uint16_t ZydisInstructionTableNodeValue;
* @brief Defines the @c ZydisInstructionTreeNodeType datatype.
*/
typedef uint8_t ZydisInstructionTreeNodeType;
/**
* @brief Defines the @c ZydisInstructionTableNode struct.
* @brief Defines the @c ZydisInstructionTreeNodeValue datatype.
*/
typedef uint16_t ZydisInstructionTreeNodeValue;
/**
* @brief Defines the @c ZydisInstructionTreeNode struct.
*
* This struct is static for now, because its size is sufficient to encode up to 65535
* instruction filters (what is about 10 times more than we currently need).
*/
typedef struct ZydisInstructionTableNode_
typedef struct ZydisInstructionTreeNode_
{
ZydisInstructionTableNodeType type;
ZydisInstructionTableNodeValue value;
} ZydisInstructionTableNode;
ZydisInstructionTreeNodeType type;
ZydisInstructionTreeNodeValue value;
} ZydisInstructionTreeNode;
/**
* @brief Defines the @c ZydisSemanticOperandType datatype.
* @brief Values that represent zydis instruction tree node types.
*/
typedef uint8_t ZydisSemanticOperandType;
enum ZydisInstructionTreeNodeTypes
{
ZYDIS_NODETYPE_INVALID = 0x00,
/**
* @brief Reference to an instruction-definition.
*/
ZYDIS_NODETYPE_DEFINITION_MASK = 0x80,
/**
* @brief Reference to an XOP-map filter.
*/
ZYDIS_NODETYPE_FILTER_XOP = 0x01,
/**
* @brief Reference to an VEX-map filter.
*/
ZYDIS_NODETYPE_FILTER_VEX = 0x02,
/**
* @brief Reference to an EVEX/MVEX-map filter.
*/
ZYDIS_NODETYPE_FILTER_EMVEX = 0x03,
/**
* @brief Reference to an opcode filter.
*/
ZYDIS_NODETYPE_FILTER_OPCODE = 0x04,
/**
* @brief Reference to an instruction-mode filter.
*/
ZYDIS_NODETYPE_FILTER_MODE = 0x05,
/**
* @brief Reference to an compacted instruction-mode filter.
*/
ZYDIS_NODETYPE_FILTER_MODE_COMPACT = 0x06,
/**
* @brief Reference to a ModRM.mod filter.
*/
ZYDIS_NODETYPE_FILTER_MODRM_MOD = 0x07,
/**
* @brief Reference to a compacted ModRM.mod filter.
*/
ZYDIS_NODETYPE_FILTER_MODRM_MOD_COMPACT = 0x08,
/**
* @brief Reference to a ModRM.reg filter.
*/
ZYDIS_NODETYPE_FILTER_MODRM_REG = 0x09,
/**
* @brief Reference to a ModRM.rm filter.
*/
ZYDIS_NODETYPE_FILTER_MODRM_RM = 0x0A,
/**
* @brief Reference to a mandatory-prefix filter.
*/
ZYDIS_NODETYPE_FILTER_MANDATORY_PREFIX = 0x0B,
/**
* @brief Reference to an operand-size filter.
*/
ZYDIS_NODETYPE_FILTER_OPERAND_SIZE = 0x0C,
/**
* @brief Reference to an address-size filter.
*/
ZYDIS_NODETYPE_FILTER_ADDRESS_SIZE = 0x0D,
/**
* @brief Reference to a vector-length filter.
*/
ZYDIS_NODETYPE_FILTER_VECTOR_LENGTH = 0x0E,
/**
* @brief Reference to an REX/VEX/EVEX.W filter.
*/
ZYDIS_NODETYPE_FILTER_REX_W = 0x0F,
/**
* @brief Reference to an REX/VEX/EVEX.B filter.
*/
ZYDIS_NODETYPE_FILTER_REX_B = 0x10,
/**
* @brief Reference to an EVEX.b filter.
*/
ZYDIS_NODETYPE_FILTER_EVEX_B = 0x11,
/**
* @brief Reference to an MVEX.E filter.
*/
ZYDIS_NODETYPE_FILTER_MVEX_E = 0x12,
};
/* ---------------------------------------------------------------------------------------------- */
/* Operand definition */
/* ---------------------------------------------------------------------------------------------- */
/**
* @brief Defines the @c ZydisOperandDefinition struct.
*
* This struct is static for now, because adding more operand-types oder encodings requires
* code changes anyways.
*/
typedef struct ZydisOperandDefinition_
{
ZydisSemanticOperandType type : 7;
ZydisOperandEncoding encoding : 5;
ZydisOperandAction action : 3;
int dummy;
} ZydisOperandDefinition;
#include <Zydis/Internal/GeneratedTypes.inc>
/* ---------------------------------------------------------------------------------------------- */
/* Instruction definition */
/* ---------------------------------------------------------------------------------------------- */
#define ZYDIS_INSTRUCTION_DEFINITION_BASE \
ZydisInstructionMnemonic mnemonic : 11; \
uint8_t operandCount : 4; \
uint16_t operandReference : 15; \
uint8_t operandSizeMap : 3
/**
* @brief Defines the @c ZydisInstructionDefinition struct.
*/
typedef struct ZydisInstructionDefinition_
{
ZYDIS_INSTRUCTION_DEFINITION_BASE;
} ZydisInstructionDefinition;
typedef struct ZydisInstructionDefinitionDEFAULT_
{
ZYDIS_INSTRUCTION_DEFINITION_BASE;
ZydisBool acceptsLock : 1;
ZydisBool acceptsREP : 1;
ZydisBool acceptsREPEREPZ : 1;
ZydisBool acceptsREPNEREPNZ : 1;
ZydisBool acceptsBOUND : 1;
ZydisBool acceptsXACQUIRE : 1;
ZydisBool acceptsXRELEASE : 1;
ZydisBool acceptsHLEWithoutLock : 1;
ZydisBool acceptsBranchHints : 1;
ZydisBool acceptsSegment : 1;
} ZydisInstructionDefinitionDEFAULT;
typedef struct ZydisInstructionDefinition3DNOW_
{
ZydisInstructionDefinition base;
} ZydisInstructionDefinition3DNOW;
typedef struct ZydisInstructionDefinitionXOP_
{
ZydisInstructionDefinition base;
} ZydisInstructionDefinitionXOP;
typedef struct ZydisInstructionDefinitionVEX_
{
ZydisInstructionDefinition base;
} ZydisInstructionDefinitionVEX;
typedef struct ZydisInstructionDefinitionEVEX_
{
ZydisInstructionDefinition base;
} ZydisInstructionDefinitionEVEX;
typedef struct ZydisInstructionDefinitionMVEX_
{
ZydisInstructionDefinition base;
} ZydisInstructionDefinitionMVEX;
/* ---------------------------------------------------------------------------------------------- */
#pragma pack(pop)
@ -100,217 +237,80 @@ typedef struct ZydisOperandDefinition_
#endif
/* ---------------------------------------------------------------------------------------------- */
/* Instruction Table */
/* Physical instruction info */
/* ---------------------------------------------------------------------------------------------- */
/**
* @brief Values that represent zydis instruction table node types.
* @brief Defines the @c ZydisInstructionPartFlags datatype.
*/
enum ZydisInstructionTableNodeTypes
{
ZYDIS_NODETYPE_INVALID = 0x00,
/**
* @brief Reference to an instruction-definition with 0 operands.
*/
ZYDIS_NODETYPE_DEFINITION_0OP = 0x01,
/**
* @brief Reference to an instruction-definition with 1 operands.
*/
ZYDIS_NODETYPE_DEFINITION_1OP = 0x02,
/**
* @brief Reference to an instruction-definition with 2 operands.
*/
ZYDIS_NODETYPE_DEFINITION_2OP = 0x03,
/**
* @brief Reference to an instruction-definition with 3 operands.
*/
ZYDIS_NODETYPE_DEFINITION_3OP = 0x04,
/**
* @brief Reference to an instruction-definition with 4 operands.
*/
ZYDIS_NODETYPE_DEFINITION_4OP = 0x05,
/**
* @brief Reference to an instruction-definition with 5 operands.
*/
ZYDIS_NODETYPE_DEFINITION_5OP = 0x06,
/**
* @brief Reference to an opcode filter.
*/
ZYDIS_NODETYPE_FILTER_OPCODE = 0x07,
/**
* @brief Reference to an VEX/EVEX-map filter.
*/
ZYDIS_NODETYPE_FILTER_VEX = 0x08,
/**
* @brief Reference to an XOP-map filter.
*/
ZYDIS_NODETYPE_FILTER_XOP = 0x09,
/**
* @brief Reference to an instruction-mode filter.
*/
ZYDIS_NODETYPE_FILTER_MODE = 0x0A,
/**
* @brief Reference to a mandatory-prefix filter.
*/
ZYDIS_NODETYPE_FILTER_MANDATORYPREFIX = 0x0B,
/**
* @brief Reference to a ModRM.mod filter.
*/
ZYDIS_NODETYPE_FILTER_MODRMMOD = 0x0C,
/**
* @brief Reference to a ModRM.reg filter.
*/
ZYDIS_NODETYPE_FILTER_MODRMREG = 0x0D,
/**
* @brief Reference to a ModRM.rm filter.
*/
ZYDIS_NODETYPE_FILTER_MODRMRM = 0x0E,
/**
* @brief Reference to an operand-size filter.
*/
ZYDIS_NODETYPE_FILTER_OPERANDSIZE = 0x0F,
/**
* @brief Reference to an address-size filter.
*/
ZYDIS_NODETYPE_FILTER_ADDRESSSIZE = 0x10,
/**
* @brief Reference to an REX/VEX/EVEX.w filter.
*/
ZYDIS_NODETYPE_FILTER_REXW = 0x11,
/**
* @brief Reference to an VEX/EVEX.l filter.
*/
ZYDIS_NODETYPE_FILTER_VEXL = 0x12,
/**
* @brief Reference to an EVEX.l' filter.
*/
ZYDIS_NODETYPE_FILTER_EVEXL2 = 0x13,
/**
* @brief Reference to an EVEX.b filter.
*/
ZYDIS_NODETYPE_FILTER_EVEXB = 0x14
};
/* ---------------------------------------------------------------------------------------------- */
/* Operand definition */
/* ---------------------------------------------------------------------------------------------- */
typedef uint8_t ZydisInstructionPartFlags;
/**
* @brief Values that represent semantic operand types.
* @brief The instruction has an optional modrm byte.
*/
enum ZydisSemanticOperandTypes
{
ZYDIS_SEM_OPERAND_TYPE_UNUSED,
ZYDIS_SEM_OPERAND_TYPE_GPR8,
ZYDIS_SEM_OPERAND_TYPE_GPR16,
ZYDIS_SEM_OPERAND_TYPE_GPR32,
ZYDIS_SEM_OPERAND_TYPE_GPR64,
ZYDIS_SEM_OPERAND_TYPE_FPR,
ZYDIS_SEM_OPERAND_TYPE_VR64,
ZYDIS_SEM_OPERAND_TYPE_VR128,
ZYDIS_SEM_OPERAND_TYPE_VR256,
ZYDIS_SEM_OPERAND_TYPE_VR512,
ZYDIS_SEM_OPERAND_TYPE_TR,
ZYDIS_SEM_OPERAND_TYPE_CR,
ZYDIS_SEM_OPERAND_TYPE_DR,
ZYDIS_SEM_OPERAND_TYPE_SREG,
ZYDIS_SEM_OPERAND_TYPE_MSKR,
ZYDIS_SEM_OPERAND_TYPE_BNDR,
ZYDIS_SEM_OPERAND_TYPE_MEM,
ZYDIS_SEM_OPERAND_TYPE_MEM8,
ZYDIS_SEM_OPERAND_TYPE_MEM16,
ZYDIS_SEM_OPERAND_TYPE_MEM32,
ZYDIS_SEM_OPERAND_TYPE_MEM64,
ZYDIS_SEM_OPERAND_TYPE_MEM80,
ZYDIS_SEM_OPERAND_TYPE_MEM128,
ZYDIS_SEM_OPERAND_TYPE_MEM256,
ZYDIS_SEM_OPERAND_TYPE_MEM512,
ZYDIS_SEM_OPERAND_TYPE_MEM32_BCST2,
ZYDIS_SEM_OPERAND_TYPE_MEM32_BCST4,
ZYDIS_SEM_OPERAND_TYPE_MEM32_BCST8,
ZYDIS_SEM_OPERAND_TYPE_MEM32_BCST16,
ZYDIS_SEM_OPERAND_TYPE_MEM64_BCST2,
ZYDIS_SEM_OPERAND_TYPE_MEM64_BCST4,
ZYDIS_SEM_OPERAND_TYPE_MEM64_BCST8,
ZYDIS_SEM_OPERAND_TYPE_MEM64_BCST16,
ZYDIS_SEM_OPERAND_TYPE_MEM32_VSIBX,
ZYDIS_SEM_OPERAND_TYPE_MEM32_VSIBY,
ZYDIS_SEM_OPERAND_TYPE_MEM32_VSIBZ,
ZYDIS_SEM_OPERAND_TYPE_MEM64_VSIBX,
ZYDIS_SEM_OPERAND_TYPE_MEM64_VSIBY,
ZYDIS_SEM_OPERAND_TYPE_MEM64_VSIBZ,
ZYDIS_SEM_OPERAND_TYPE_M1616,
ZYDIS_SEM_OPERAND_TYPE_M1632,
ZYDIS_SEM_OPERAND_TYPE_M1664,
ZYDIS_SEM_OPERAND_TYPE_MEM112,
ZYDIS_SEM_OPERAND_TYPE_MEM224,
ZYDIS_SEM_OPERAND_TYPE_IMM8,
ZYDIS_SEM_OPERAND_TYPE_IMM16,
ZYDIS_SEM_OPERAND_TYPE_IMM32,
ZYDIS_SEM_OPERAND_TYPE_IMM64,
ZYDIS_SEM_OPERAND_TYPE_IMM8U,
ZYDIS_SEM_OPERAND_TYPE_REL8,
ZYDIS_SEM_OPERAND_TYPE_REL16,
ZYDIS_SEM_OPERAND_TYPE_REL32,
ZYDIS_SEM_OPERAND_TYPE_REL64,
ZYDIS_SEM_OPERAND_TYPE_PTR1616,
ZYDIS_SEM_OPERAND_TYPE_PTR1632,
ZYDIS_SEM_OPERAND_TYPE_PTR1664,
ZYDIS_SEM_OPERAND_TYPE_MOFFS16,
ZYDIS_SEM_OPERAND_TYPE_MOFFS32,
ZYDIS_SEM_OPERAND_TYPE_MOFFS64,
ZYDIS_SEM_OPERAND_TYPE_SRCIDX8,
ZYDIS_SEM_OPERAND_TYPE_SRCIDX16,
ZYDIS_SEM_OPERAND_TYPE_SRCIDX32,
ZYDIS_SEM_OPERAND_TYPE_SRCIDX64,
ZYDIS_SEM_OPERAND_TYPE_DSTIDX8,
ZYDIS_SEM_OPERAND_TYPE_DSTIDX16,
ZYDIS_SEM_OPERAND_TYPE_DSTIDX32,
ZYDIS_SEM_OPERAND_TYPE_DSTIDX64,
ZYDIS_SEM_OPERAND_TYPE_FIXED1,
ZYDIS_SEM_OPERAND_TYPE_AL,
ZYDIS_SEM_OPERAND_TYPE_CL,
ZYDIS_SEM_OPERAND_TYPE_AX,
ZYDIS_SEM_OPERAND_TYPE_DX,
ZYDIS_SEM_OPERAND_TYPE_EAX,
ZYDIS_SEM_OPERAND_TYPE_ECX,
ZYDIS_SEM_OPERAND_TYPE_RAX,
ZYDIS_SEM_OPERAND_TYPE_ES,
ZYDIS_SEM_OPERAND_TYPE_CS,
ZYDIS_SEM_OPERAND_TYPE_SS,
ZYDIS_SEM_OPERAND_TYPE_DS,
ZYDIS_SEM_OPERAND_TYPE_GS,
ZYDIS_SEM_OPERAND_TYPE_FS,
ZYDIS_SEM_OPERAND_TYPE_ST0
};
/* ---------------------------------------------------------------------------------------------- */
/* Instruction definition */
/* ---------------------------------------------------------------------------------------------- */
#define ZYDIS_INSTRPART_FLAG_HAS_MODRM 0x01
/**
* @brief Values that represent zydis EVEX.b-contexts.
* @brief The instruction has an optional displacement value.
*/
enum ZydisEvexBFunctionalities
{
ZYDIS_EVEX_CONTEXT_INVALID,
ZYDIS_EVEX_CONTEXT_BC,
ZYDIS_EVEX_CONTEXT_RC,
ZYDIS_EVEX_CONTEXT_SAE
};
#define ZYDIS_INSTRPART_FLAG_HAS_DISP 0x02
/* ---------------------------------------------------------------------------------------------- */
/**
* @brief The instruction has an optional immediate value.
*/
#define ZYDIS_INSTRPART_FLAG_HAS_IMM0 0x04
/**
* @brief The instruction has a second optional immediate value.
*/
#define ZYDIS_INSTRPART_FLAG_HAS_IMM1 0x08
typedef struct ZydisInstructionParts_
{
/**
* @brief
*/
ZydisInstructionPartFlags flags;
/**
* @brief Displacement info.
*/
struct
{
/**
* @brief The size of the displacement value.
*/
uint8_t size[3];
} disp;
/**
* @brief Immediate info.
*/
struct
{
/**
* @brief The size of the immediate value.
*/
uint8_t size[3];
/**
* @brief Signals, if the value is signed.
*/
ZydisBool isSigned;
/**
* @brief Signals, if the value is a relative offset.
*/
ZydisBool isRelative;
} imm[2];
} ZydisInstructionParts;
/* ============================================================================================== */
/* Functions */
/* ============================================================================================== */
/**
* @brief Returns the root node of the instruction table.
* @brief Returns the root node of the instruction tree.
*
* @return The root node of the instruction table.
* @return The root node of the instruction tree.
*/
ZYDIS_NO_EXPORT const ZydisInstructionTableNode* ZydisInstructionTableGetRootNode();
ZYDIS_NO_EXPORT const ZydisInstructionTreeNode* ZydisInstructionTreeGetRootNode();
/**
* @brief Returns the child node of @c parent specified by @c index.
@ -320,25 +320,39 @@ ZYDIS_NO_EXPORT const ZydisInstructionTableNode* ZydisInstructionTableGetRootNod
*
* @return The specified child node.
*/
ZYDIS_NO_EXPORT const ZydisInstructionTableNode* ZydisInstructionTableGetChildNode(
const ZydisInstructionTableNode* parent, uint16_t index);
ZYDIS_NO_EXPORT const ZydisInstructionTreeNode* ZydisInstructionTreeGetChildNode(
const ZydisInstructionTreeNode* parent, uint16_t index);
/**
* @brief Returns the instruction- and operand-definition that is linked to the given @c node.
*
* @param node The instruction definition node.
* @param definition A pointer to a variable that receives a pointer to the
* instruction-definition.
*/
ZYDIS_NO_EXPORT void ZydisGetInstructionDefinition(const ZydisInstructionTreeNode* node,
const ZydisInstructionDefinition** definition);
/**
* @brief Returns information about optional instruction parts for the instruction that is linked
* to the given @c node.
*
* @param node The instruction definition node.
* @param info A pointer to the @c ZydisInstructionParts struct.
*/
ZYDIS_NO_EXPORT void ZydisGetOptionalInstructionParts(const ZydisInstructionTreeNode* node,
const ZydisInstructionParts** info);
/**
* @brief Returns the instruction- and operand-definition that is linked to the given @c node.
*
* @param definition A pointer to the instruction-definition.
* @param operands A pointer to a variable that receives a pointer to the first
* operand-definition of the instruction.
* @param operandCount A pointer to a variable that receives the number of operand-definitions
* for the instruction.
*
* @return @c TRUE, if @c node contained a valid instruction-definition, @c FALSE if not.
*
* @return The number of operands for the given instruction-definition.
*/
ZYDIS_NO_EXPORT ZydisBool ZydisInstructionTableGetDefinition(const ZydisInstructionTableNode* node,
const ZydisInstructionDefinition** definition, const ZydisOperandDefinition** operands,
uint8_t* operandCount);
ZYDIS_NO_EXPORT uint8_t ZydisGetOperandDefinitions(const ZydisInstructionDefinition* definition,
const ZydisOperandDefinition** operands);
/* ============================================================================================== */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -29,7 +29,6 @@
#include <Zydis/Defines.h>
#include <Zydis/Types.h>
#include <Zydis/Status.h>
#ifdef __cplusplus
extern "C" {

View File

@ -113,7 +113,7 @@ enum ZydisRegisters
// Instruction-pointer registers
ZYDIS_REGISTER_RIP, ZYDIS_REGISTER_EIP, ZYDIS_REGISTER_IP,
// Special registers
ZYDIS_REGISTER_MXCSR, ZYDIS_REGISTER_PKRU, ZYDIS_REGISTER_XCR0,
ZYDIS_REGISTER_MXCSR, ZYDIS_REGISTER_PKRU, ZYDIS_REGISTER_XCR0,
// Segment registers
ZYDIS_REGISTER_ES, ZYDIS_REGISTER_SS, ZYDIS_REGISTER_CS, ZYDIS_REGISTER_DS,
ZYDIS_REGISTER_FS, ZYDIS_REGISTER_GS,

View File

@ -92,21 +92,27 @@ enum ZydisStatusCode
*/
ZYDIS_STATUS_ILLEGAL_LOCK,
/**
* @brief A legacy-prefix (F2, F3, 66) was found while decoding a XOP/VEX/EVEX instruction.
* @brief A legacy-prefix (F2, F3, 66) was found while decoding a XOP/VEX/EVEX/MVEX
* instruction.
*/
ZYDIS_STATUS_ILLEGAL_LEGACY_PFX,
/**
* @brief A rex-prefix was found while decoding a XOP/VEX/EVEX instruction.
* @brief A rex-prefix was found while decoding a XOP/VEX/EVEX/MVEX instruction.
*/
ZYDIS_STATUS_ILLEGAL_REX,
/**
* @brief An invalid opcode-map value was found while decoding a XOP/VEX/EVEX-prefix.
* @brief An invalid opcode-map value was found while decoding a XOP/VEX/EVEX/MVEX-prefix.
*/
ZYDIS_STATUS_INVALID_MAP,
/**
* @brief An error occured while decoding the EVEX-prefix.
*/
ZYDIS_STATUS_MALFORMED_EVEX,
/**
* @brief An error occured while decoding the MVEX-prefix.
*/
ZYDIS_STATUS_MALFORMED_MVEX, // TODO: Do we need this?
// TODO:
ZYDIS_STATUS_INVALID_MASK,
ZYDIS_STATUS_INVALID_VSIB,

File diff suppressed because it is too large Load Diff

View File

@ -391,13 +391,13 @@ static ZydisStatus ZydisFormatterPrintAddressIntel(ZydisInstructionFormatter* fo
return ZYDIS_STATUS_INVALID_PARAMETER;
}
switch (info->mode)
switch (info->machineMode)
{
case ZYDIS_OPERATING_MODE_16BIT:
case ZYDIS_OPERATING_MODE_32BIT:
case 16:
case 32:
return ZydisStringBufferAppendFormat(buffer, bufferLen, ZYDIS_STRBUF_APPEND_MODE_DEFAULT,
"0x%08"PRIX64, address);
case ZYDIS_OPERATING_MODE_64BIT:
case 64:
return ZydisStringBufferAppendFormat(buffer, bufferLen, ZYDIS_STRBUF_APPEND_MODE_DEFAULT,
"0x%016"PRIX64, address);
default:

View File

@ -35,36 +35,6 @@
/* Forward declarations */
/* ---------------------------------------------------------------------------------------------- */
/**
* @brief Contains all opcode filters.
*
* Indexed by the numeric value of the opcode.
*/
extern const ZydisInstructionTableNode filterOpcode[][256];
/**
* @brief Contains all VEX-map filters.
*
* Index values:
* 0 = LES, LDS or BOUND instruction (default encoding)
* 1 = 0F
* 2 = 0F38
* 3 = 0F3A
* 4 = 66
* 5 = 66_0F
* 6 = 66_0F38
* 7 = 66_0F3A
* 8 = F3
* 9 = F3_0F
* A = F3_0F38
* B = F3_0F3A
* C = F2
* D = F2_0F
* E = F2_0F38
* F = F2_0F3A
*/
extern const ZydisInstructionTableNode filterVEX[][16];
/**
* @brief Contains all XOP-map filters.
*
@ -74,264 +44,267 @@ extern const ZydisInstructionTableNode filterVEX[][16];
* 2 = xop9
* 3 = xopA
*/
extern const ZydisInstructionTableNode filterXOP[][4];
extern const ZydisInstructionTreeNode filtersXOP[][4];
/**
* @brief Contains all VEX-map filters.
*
* Index values:
* 00 = LES or LDS instruction (default encoding)
* 01 = VEX MAP0
* 02 = 0F
* 03 = 0F38
* 04 = 0F3A
* 05 = 66
* 06 = 66_0F
* 07 = 66_0F38
* 08 = 66_0F3A
* 09 = F3
* 0A = F3_0F
* 0B = F3_0F38
* 0C = F3_0F3A
* 0D = F2
* 0E = F2_0F
* 0F = F2_0F38
* 10 = F2_0F3A
*/
extern const ZydisInstructionTreeNode filtersVEX[][17];
/**
* @brief Contains all EVEX/MVEX-map filters.
*
* Index values:
* 00 = BOUND instruction (default encoding)
* 01 = EVEX MAP0
* 02 = EVEX 0F
* 03 = EVEX 0F38
* 04 = EVEX 0F3A
* 05 = EVEX 66
* 06 = EVEX 66_0F
* 07 = EVEX 66_0F38
* 08 = EVEX 66_0F3A
* 09 = EVEX F3
* 0A = EVEX F3_0F
* 0B = EVEX F3_0F38
* 0C = EVEX F3_0F3A
* 0D = EVEX EVEX F2
* 0E = EVEX F2_0F
* 0F = EVEX
* 10 = EVEX F2_0F3A
* 11 = MVEX MAP0
* 12 = MVEX 0F
* 13 = MVEX 0F38
* 14 = MVEX 0F3A
* 15 = MVEX 66
* 16 = MVEX 66_0F
* 17 = MVEX 66_0F38
* 18 = MVEX 66_0F3A
* 19 = MVEX F3
* 1A = MVEX F3_0F
* 1B = MVEX F3_0F38
* 1C = MVEX F3_0F3A
* 1D = MVEX EVEX F2
* 1E = MVEX F2_0F
* 1F = MVEX F2_0F38
* 20 = MVEX F2_0F3A
*/
extern const ZydisInstructionTreeNode filtersEMVEX[][33];
/**
* @brief Contains all opcode filters.
*
* Indexed by the numeric value of the opcode.
*/
extern const ZydisInstructionTreeNode filtersOpcode[][256];
/**
* @brief Contains all instruction-mode filters.
*
* Index values:
* 0 = 64 bit mode required
* 1 = 64 bit mode excluded
* 0 = 16 bit mode
* 1 = 32 bit mode
* 2 = 64 bit mode
*/
extern const ZydisInstructionTableNode filterMode[][2];
extern const ZydisInstructionTreeNode filtersMode[][3];
/**
* @brief Contains all compacted instruction-mode filters.
*
* Index values:
* 0 = 64 bit mode
* 1 = not 64 bit mode
*/
extern const ZydisInstructionTreeNode filtersModeCompact[][2];
/**
* @brief Contains all ModRM.mod filters.
*
* Indexed by the ordinal value of the ModRM.mod field.
*/
extern const ZydisInstructionTreeNode filtersModrmMod[][4];
/**
* @brief Contains all compacted ModRM.mod filters.
*
* Index values:
* 0 = [ModRM.mod == 11] = register
* 1 = [ModRM.mod == !11] = memory
*/
extern const ZydisInstructionTreeNode filtersModrmModCompact[][2];
/**
* @brief Contains all ModRM.reg filters.
*
* Indexed by the numeric value of the ModRM.reg field.
*/
extern const ZydisInstructionTreeNode filtersModrmReg[][8];
/**
* @brief Contains all ModRM.rm filters.
*
* Indexed by the numeric value of the ModRM.rm field.
*/
extern const ZydisInstructionTreeNode filtersModrmRm[][8];
/**
* @brief Contains all mandatory-prefix switch tables.
*
* Index values:
* 0 = none
* 1 = 66
* 2 = F3
* 3 = F2
* 0 = ignored (prefixes are not interpreted as mandatory-prefix)
* 1 = none
* 2 = 66
* 3 = F3
* 4 = F2
*/
extern const ZydisInstructionTableNode filterMandatoryPrefix[][4];
/**
* @brief Contains all ModRM.mod filters.
*
* Index values:
* 0 = [modrm_mod == !11] = memory
* 1 = [modrm_mod == 11] = register
*/
extern const ZydisInstructionTableNode filterModrmMod[][2];
/**
* @brief Contains all ModRM.reg filters.
*
* Indexed by the numeric value of the modrm_reg field.
*/
extern const ZydisInstructionTableNode filterModrmReg[][8];
/**
* @brief Contains all ModRM.rm filters.
*
* Indexed by the numeric value of the modrm_rm field.
*/
extern const ZydisInstructionTableNode filterModrmRm[][8];
extern const ZydisInstructionTreeNode filtersMandatoryPrefix[][5];
/**
* @brief Contains all operand-size filters.
*
* Index values:
* 0 = 16bit = 0x66 prefix in 32 bit mode
* 1 = 32bit = 0x66 prefix in 16 bit mode
* 0 = 16 bit
* 1 = 32 bit
* 2 = 64 bit
*/
extern const ZydisInstructionTableNode filterOperandSize[][2];
extern const ZydisInstructionTreeNode filtersOperandSize[][3];
/**
* @brief Contains all address-size filters.
*
* Index values:
* 0 = 16
* 1 = 32
* 2 = 64
* 0 = 16 bit
* 1 = 32 bit
* 2 = 64 bit
*/
extern const ZydisInstructionTableNode filterAddressSize[][3];
extern const ZydisInstructionTreeNode filtersAddressSize[][3];
/**
* @brief Contains all vector-length filters.
*
* Index values:
* 0 = 128 bit
* 1 = 256 bit
* 2 = 512 bit
*/
extern const ZydisInstructionTreeNode filtersVectorLength[][3];
/**
* @brief Contains all REX/VEX/EVEX.w filters.
*
* Indexed by the numeric value of the REX/VEX/EVEX.w field.
*/
extern const ZydisInstructionTableNode filterREXW[][2];
extern const ZydisInstructionTreeNode filtersREXW[][2];
/**
* @brief Contains all VEX.l filters.
* @brief Contains all REX/VEX/EVEX.B filters.
*
* Indexed by the numeric value of the VEX/EVEX.l field.
* Indexed by the numeric value of the REX/VEX/EVEX.B field.
*/
extern const ZydisInstructionTableNode filterVEXL[][2];
/**
* @brief Contains all EVEX.l' filters.
*
* Indexed by the numeric value of the EVEX.l' field.
*/
extern const ZydisInstructionTableNode filterEVEXL2[][2];
extern const ZydisInstructionTreeNode filtersREXB[][2];
/**
* @brief Contains all EVEX.b filters.
*
* Indexed by the numeric value of the EVEX.b field.
*/
extern const ZydisInstructionTableNode filterEVEXB[][2];
extern const ZydisInstructionTreeNode filtersEVEXB[][2];
/**
* @brief Contains all MVEX.E filters.
*
* Indexed by the numeric value of the MVEX.E field.
*/
extern const ZydisInstructionTreeNode filtersMVEXE[][2];
/* ---------------------------------------------------------------------------------------------- */
/**
* @brief Contains all operand-definitions with 1 operands.
* @brief Contains all operand-definitions.
*/
extern const ZydisOperandDefinition operandDefinitions1[][1];
/**
* @brief Contains all operand-definitions with 2 operands.
*/
extern const ZydisOperandDefinition operandDefinitions2[][2];
/**
* @brief Contains all operand-definitions with 3 operands.
*/
extern const ZydisOperandDefinition operandDefinitions3[][3];
/**
* @brief Contains all operand-definitions with 4 operands.
*/
extern const ZydisOperandDefinition operandDefinitions4[][4];
/**
* @brief Contains all operand-definitions with 5 operands.
*/
extern const ZydisOperandDefinition operandDefinitions5[][5];
extern const ZydisOperandDefinition operandDefinitions[];
/* ---------------------------------------------------------------------------------------------- */
/**
* @brief Contains all instruction-definitions.
* @brief Contains all instruction-definitions with @c DEFAULT encoding.
*/
extern const ZydisInstructionDefinition instructionDefinitions[];
extern const ZydisInstructionDefinitionDEFAULT instructionDefinitionsDEFAULT[];
/**
* @brief Contains all instruction-definitions with @c 3DNOW encoding.
*/
extern const ZydisInstructionDefinition3DNOW instructionDefinitions3DNOW[];
/**
* @brief Contains all instruction-definitions with @c XOP encoding.
*/
extern const ZydisInstructionDefinitionXOP instructionDefinitionsXOP[];
/**
* @brief Contains all instruction-definitions with @c VEX encoding.
*/
extern const ZydisInstructionDefinitionVEX instructionDefinitionsVEX[];
/**
* @brief Contains all instruction-definitions with @c EVEX encoding.
*/
extern const ZydisInstructionDefinitionEVEX instructionDefinitionsEVEX[];
/**
* @brief Contains all instruction-definitions with @c MVEX encoding.
*/
extern const ZydisInstructionDefinitionMVEX instructionDefinitionsMVEX[];
/* ---------------------------------------------------------------------------------------------- */
/* Functions */
/* Physical instruction encodings */
/* ---------------------------------------------------------------------------------------------- */
const ZydisInstructionTableNode* ZydisInstructionTableGetRootNode()
{
static const ZydisInstructionTableNode root = { ZYDIS_NODETYPE_FILTER_OPCODE, 0x00000000 };
return &root;
}
const ZydisInstructionTableNode* ZydisInstructionTableGetChildNode(
const ZydisInstructionTableNode* parent, uint16_t index)
{
switch (parent->type)
{
case ZYDIS_NODETYPE_FILTER_OPCODE:
ZYDIS_ASSERT(index < 256);
return &filterOpcode[parent->value][index];
case ZYDIS_NODETYPE_FILTER_VEX:
ZYDIS_ASSERT(index < 16);
return &filterVEX[parent->value][index];
case ZYDIS_NODETYPE_FILTER_XOP:
ZYDIS_ASSERT(index < 4);
return &filterXOP[parent->value][index];
case ZYDIS_NODETYPE_FILTER_MODE:
ZYDIS_ASSERT(index < 3);
return &filterMode[parent->value][index];
case ZYDIS_NODETYPE_FILTER_MANDATORYPREFIX:
ZYDIS_ASSERT(index < 4);
return &filterMandatoryPrefix[parent->value][index];
case ZYDIS_NODETYPE_FILTER_MODRMMOD:
ZYDIS_ASSERT(index < 2);
return &filterModrmMod[parent->value][index];
case ZYDIS_NODETYPE_FILTER_MODRMREG:
ZYDIS_ASSERT(index < 8);
return &filterModrmReg[parent->value][index];
case ZYDIS_NODETYPE_FILTER_MODRMRM:
ZYDIS_ASSERT(index < 8);
return &filterModrmRm[parent->value][index];
case ZYDIS_NODETYPE_FILTER_OPERANDSIZE:
ZYDIS_ASSERT(index < 2);
return &filterOperandSize[parent->value][index];
case ZYDIS_NODETYPE_FILTER_ADDRESSSIZE:
ZYDIS_ASSERT(index < 3);
return &filterAddressSize[parent->value][index];
case ZYDIS_NODETYPE_FILTER_REXW:
ZYDIS_ASSERT(index < 2);
return &filterREXW[parent->value][index];
case ZYDIS_NODETYPE_FILTER_VEXL:
ZYDIS_ASSERT(index < 2);
return &filterVEXL[parent->value][index];
case ZYDIS_NODETYPE_FILTER_EVEXL2:
ZYDIS_ASSERT(index < 2);
return &filterEVEXL2[parent->value][index];
case ZYDIS_NODETYPE_FILTER_EVEXB:
ZYDIS_ASSERT(index < 2);
return &filterEVEXB[parent->value][index];
default:
ZYDIS_UNREACHABLE;
}
static const ZydisInstructionTableNode invalid = { ZYDIS_NODETYPE_INVALID, 0x00000000 };
return &invalid;
}
ZydisBool ZydisInstructionTableGetDefinition(const ZydisInstructionTableNode* node,
const ZydisInstructionDefinition** definition, const ZydisOperandDefinition** operands,
uint8_t* operandCount)
{
*definition = &instructionDefinitions[node->value];
switch (node->type)
{
case ZYDIS_NODETYPE_DEFINITION_0OP:
*operandCount = 0;
break;
case ZYDIS_NODETYPE_DEFINITION_1OP:
*operandCount = 1;
*operands = operandDefinitions1[(*definition)->operandsId];
break;
case ZYDIS_NODETYPE_DEFINITION_2OP:
*operandCount = 2;
*operands = operandDefinitions2[(*definition)->operandsId];
break;
case ZYDIS_NODETYPE_DEFINITION_3OP:
*operandCount = 3;
*operands = operandDefinitions3[(*definition)->operandsId];
break;
case ZYDIS_NODETYPE_DEFINITION_4OP:
*operandCount = 4;
*operands = operandDefinitions4[(*definition)->operandsId];
break;
case ZYDIS_NODETYPE_DEFINITION_5OP:
*operandCount = 5;
*operands = operandDefinitions5[(*definition)->operandsId];
break;
default:
ZYDIS_UNREACHABLE;
//return ZYDIS_FALSE;
}
return ZYDIS_TRUE;
}
#include <Zydis/Internal/InstructionClassMap.inc>
/* ---------------------------------------------------------------------------------------------- */
/* Main instruction-table */
/* Instruction tree */
/* ---------------------------------------------------------------------------------------------- */
#define ZYDIS_INVALID \
{ ZYDIS_NODETYPE_INVALID, 0x00000000 }
#define ZYDIS_FILTER(type, id) \
{ type, id }
#define ZYDIS_DEFINITION_0OP(id) \
{ ZYDIS_NODETYPE_DEFINITION_0OP, id }
#define ZYDIS_DEFINITION_1OP(id) \
{ ZYDIS_NODETYPE_DEFINITION_1OP, id }
#define ZYDIS_DEFINITION_2OP(id) \
{ ZYDIS_NODETYPE_DEFINITION_2OP, id }
#define ZYDIS_DEFINITION_3OP(id) \
{ ZYDIS_NODETYPE_DEFINITION_3OP, id }
#define ZYDIS_DEFINITION_4OP(id) \
{ ZYDIS_NODETYPE_DEFINITION_4OP, id }
#define ZYDIS_DEFINITION_5OP(id) \
{ ZYDIS_NODETYPE_DEFINITION_5OP, id }
#define ZYDIS_DEFINITION(encoding, instrclass, id) \
{ ZYDIS_NODETYPE_DEFINITION_MASK | instrclass, (encoding << 13) | id }
#include <Zydis/Internal/InstructionFilters.inc>
#undef ZYDIS_INVALID
#undef ZYDIS_FILTER
#undef ZYDIS_DEFINITION_0OP
#undef ZYDIS_DEFINITION_1OP
#undef ZYDIS_DEFINITION_2OP
#undef ZYDIS_DEFINITION_3OP
#undef ZYDIS_DEFINITION_4OP
#undef ZYDIS_DEFINITION_5OP
#undef ZYDIS_DEFINITION
/* ---------------------------------------------------------------------------------------------- */
/* Instruction definitions */
/* ---------------------------------------------------------------------------------------------- */
#include <Zydis/Internal/InstructionDefinitions.inc>
/* ---------------------------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------------------------- */
/* Operand definitions */
@ -344,10 +317,137 @@ ZydisBool ZydisInstructionTableGetDefinition(const ZydisInstructionTableNode* no
#undef ZYDIS_OPERAND_DEFINITION
/* ---------------------------------------------------------------------------------------------- */
/* Instruction definitions */
/* ---------------------------------------------------------------------------------------------- */
/* ============================================================================================== */
/* Functions */
/* ============================================================================================== */
#include <Zydis/Internal/InstructionDefinitions.inc>
const ZydisInstructionTreeNode* ZydisInstructionTreeGetRootNode()
{
static const ZydisInstructionTreeNode root = { ZYDIS_NODETYPE_FILTER_OPCODE, 0x00000000 };
return &root;
}
const ZydisInstructionTreeNode* ZydisInstructionTreeGetChildNode(
const ZydisInstructionTreeNode* parent, uint16_t index)
{
switch (parent->type)
{
case ZYDIS_NODETYPE_FILTER_XOP:
ZYDIS_ASSERT(index < 4);
return &filtersXOP[parent->value][index];
case ZYDIS_NODETYPE_FILTER_VEX:
ZYDIS_ASSERT(index < 17);
return &filtersVEX[parent->value][index];
case ZYDIS_NODETYPE_FILTER_EMVEX:
ZYDIS_ASSERT(index < 33);
return &filtersEMVEX[parent->value][index];
case ZYDIS_NODETYPE_FILTER_OPCODE:
ZYDIS_ASSERT(index < 256);
return &filtersOpcode[parent->value][index];
case ZYDIS_NODETYPE_FILTER_MODE:
ZYDIS_ASSERT(index < 4);
return &filtersMode[parent->value][index];
case ZYDIS_NODETYPE_FILTER_MODE_COMPACT:
ZYDIS_ASSERT(index < 3);
return &filtersModeCompact[parent->value][index];
case ZYDIS_NODETYPE_FILTER_MODRM_MOD:
ZYDIS_ASSERT(index < 4);
return &filtersModrmMod[parent->value][index];
case ZYDIS_NODETYPE_FILTER_MODRM_MOD_COMPACT:
ZYDIS_ASSERT(index < 2);
return &filtersModrmModCompact[parent->value][index];
case ZYDIS_NODETYPE_FILTER_MODRM_REG:
ZYDIS_ASSERT(index < 8);
return &filtersModrmReg[parent->value][index];
case ZYDIS_NODETYPE_FILTER_MODRM_RM:
ZYDIS_ASSERT(index < 8);
return &filtersModrmRm[parent->value][index];
case ZYDIS_NODETYPE_FILTER_MANDATORY_PREFIX:
ZYDIS_ASSERT(index < 5);
return &filtersMandatoryPrefix[parent->value][index];
case ZYDIS_NODETYPE_FILTER_OPERAND_SIZE:
ZYDIS_ASSERT(index < 3);
return &filtersOperandSize[parent->value][index];
case ZYDIS_NODETYPE_FILTER_ADDRESS_SIZE:
ZYDIS_ASSERT(index < 3);
return &filtersAddressSize[parent->value][index];
case ZYDIS_NODETYPE_FILTER_VECTOR_LENGTH:
ZYDIS_ASSERT(index < 3);
return &filtersVectorLength[parent->value][index];
case ZYDIS_NODETYPE_FILTER_REX_W:
ZYDIS_ASSERT(index < 2);
return &filtersREXW[parent->value][index];
case ZYDIS_NODETYPE_FILTER_REX_B:
ZYDIS_ASSERT(index < 2);
return &filtersREXB[parent->value][index];
case ZYDIS_NODETYPE_FILTER_EVEX_B:
ZYDIS_ASSERT(index < 2);
return &filtersEVEXB[parent->value][index];
case ZYDIS_NODETYPE_FILTER_MVEX_E:
ZYDIS_ASSERT(index < 2);
return &filtersMVEXE[parent->value][index];
default:
ZYDIS_UNREACHABLE;
}
static const ZydisInstructionTreeNode invalid = { ZYDIS_NODETYPE_INVALID, 0x00000000 };
return &invalid;
}
void ZydisGetInstructionDefinition(const ZydisInstructionTreeNode* node,
const ZydisInstructionDefinition** definition)
{
ZYDIS_ASSERT(node->type & ZYDIS_NODETYPE_DEFINITION_MASK);
switch ((node->value >> 13) & 0x07)
{
case ZYDIS_INSTRUCTION_ENCODING_DEFAULT:
*definition =
(ZydisInstructionDefinition*)&instructionDefinitionsDEFAULT[node->value & 0x1FFF];
break;
case ZYDIS_INSTRUCTION_ENCODING_3DNOW:
*definition =
(ZydisInstructionDefinition*)&instructionDefinitions3DNOW[node->value & 0x1FFF];
break;
case ZYDIS_INSTRUCTION_ENCODING_XOP:
*definition =
(ZydisInstructionDefinition*)&instructionDefinitionsXOP[node->value & 0x1FFF];
break;
case ZYDIS_INSTRUCTION_ENCODING_VEX:
*definition =
(ZydisInstructionDefinition*)&instructionDefinitionsVEX[node->value & 0x1FFF];
break;
case ZYDIS_INSTRUCTION_ENCODING_EVEX:
*definition =
(ZydisInstructionDefinition*)&instructionDefinitionsEVEX[node->value & 0x1FFF];
break;
case ZYDIS_INSTRUCTION_ENCODING_MVEX:
*definition =
(ZydisInstructionDefinition*)&instructionDefinitionsMVEX[node->value & 0x1FFF];
break;
default:
ZYDIS_UNREACHABLE;
}
}
void ZydisGetOptionalInstructionParts(const ZydisInstructionTreeNode* node,
const ZydisInstructionParts** info)
{
ZYDIS_ASSERT(node->type & ZYDIS_NODETYPE_DEFINITION_MASK);
uint8_t class = (node->type) & 0x7F;
ZYDIS_ASSERT(class < ZYDIS_ARRAY_SIZE(instructionClassMap));
*info = &instructionClassMap[class];
}
uint8_t ZydisGetOperandDefinitions(const ZydisInstructionDefinition* definition,
const ZydisOperandDefinition** operands)
{
if (definition->operandCount == 0)
{
*operands = NULL;
return 0;
}
ZYDIS_ASSERT(definition->operandReference != 0xFFFF);
*operands = &operandDefinitions[definition->operandReference];
return definition->operandCount;
}
/* ============================================================================================== */

View File

@ -30,10 +30,7 @@
/* Mnemonic strings */
/* ============================================================================================== */
static const char* mnemonicStrings[] =
{
#include <Zydis/Internal/MnemonicStrings.inc>
};
/* ============================================================================================== */
/* Exported functions */
@ -41,7 +38,7 @@ static const char* mnemonicStrings[] =
const char* ZydisMnemonicGetString(ZydisInstructionMnemonic mnemonic)
{
if (mnemonic > (sizeof(mnemonicStrings) / sizeof(mnemonicStrings[0])) - 1)
if (mnemonic > ZYDIS_ARRAY_SIZE(mnemonicStrings) - 1)
{
return NULL;
}

View File

@ -66,16 +66,16 @@ ZydisStatus ZydisUtilsCalcAbsoluteTargetAddress(const ZydisInstructionInfo* info
{
*address =
(uint64_t)((int64_t)info->instrPointer + info->length + operand->imm.value.sqword);
switch (info->mode)
switch (info->machineMode)
{
case ZYDIS_OPERATING_MODE_16BIT:
case ZYDIS_OPERATING_MODE_32BIT:
case 16:
case 32:
if (operand->size == 16)
{
*address &= 0xFFFF;
}
break;
case ZYDIS_OPERATING_MODE_64BIT:
case 64:
break;
default:
return ZYDIS_STATUS_INVALID_PARAMETER;