mirror of https://github.com/x64dbg/zydis
Merge branch 'develop' of github.com:zyantific/zyan-disassembler-engine into develop
This commit is contained in:
commit
98d34d0c62
|
@ -36,18 +36,6 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Macros */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Constants */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
#define ZYDIS_MAX_INSTRUCTION_LENGTH 15
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Enums and types */
|
||||
/* ============================================================================================== */
|
||||
|
|
|
@ -120,6 +120,12 @@
|
|||
#define ZYDIS_ASSERT(condition) assert(condition)
|
||||
#define ZYDIS_UNREACHABLE assert(0)
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Utils */
|
||||
/* ============================================================================================== */
|
||||
|
||||
#define ZYDIS_ARRAY_SIZE(arr) (sizeof(arr) / sizeof(arr[0]))
|
||||
|
||||
/* ============================================================================================== */
|
||||
|
||||
#endif /* ZYDIS_DEFINES_H */
|
||||
|
|
|
@ -74,7 +74,7 @@ extern "C" {
|
|||
*
|
||||
* @return A zydis status code.
|
||||
*/
|
||||
ZYDIS_EXPORT ZydisStatus ZydisEncoderEncodeInstruction(void* buffer, size_t bufferLen,
|
||||
ZYDIS_EXPORT ZydisStatus ZydisEncoderEncodeInstruction(void* buffer, size_t* bufferLen,
|
||||
ZydisInstructionInfo* info);
|
||||
|
||||
/* ============================================================================================== */
|
||||
|
|
|
@ -40,6 +40,18 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Macros */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Constants */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
#define ZYDIS_MAX_INSTRUCTION_LENGTH 15
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Operand info */
|
||||
/* ============================================================================================== */
|
||||
|
@ -315,12 +327,12 @@ typedef struct ZydisOperandInfo_
|
|||
int64_t sqword;
|
||||
} value;
|
||||
/**
|
||||
* @brief The physical displacement size.
|
||||
* @brief The physical displacement size, in bits.
|
||||
*/
|
||||
uint8_t dataSize;
|
||||
/**
|
||||
* @brief The offset of the displacement data, relative to the beginning of the
|
||||
* instruction.
|
||||
* instruction, in bytes.
|
||||
*/
|
||||
uint8_t dataOffset;
|
||||
} disp;
|
||||
|
@ -361,12 +373,12 @@ typedef struct ZydisOperandInfo_
|
|||
uint64_t uqword;
|
||||
} value;
|
||||
/**
|
||||
* @brief The physical immediate size.
|
||||
* @brief The physical immediate size, in bits.
|
||||
*/
|
||||
uint8_t dataSize;
|
||||
/**
|
||||
* @brief The offset of the immediate data, relative to the beginning of the
|
||||
* instruction.
|
||||
* instruction, in bytes.
|
||||
*/
|
||||
uint8_t dataOffset;
|
||||
} imm;
|
||||
|
|
539
src/Encoder.c
539
src/Encoder.c
|
@ -25,6 +25,7 @@
|
|||
***************************************************************************************************/
|
||||
|
||||
#include <Zydis/Encoder.h>
|
||||
#include <Zydis/Internal/InstructionTable.h>
|
||||
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
|
@ -36,6 +37,7 @@
|
|||
typedef struct ZydisEncoderTableOperand_
|
||||
{
|
||||
ZydisOperandEncoding encoding;
|
||||
ZydisSemanticOperandType type;
|
||||
} ZydisEncoderTableOperand;
|
||||
|
||||
typedef uint8_t ZydisModRMMod;
|
||||
|
@ -74,34 +76,40 @@ typedef struct ZydisEncoderTableEntry_
|
|||
/**
|
||||
* @brief The encoder context struct.
|
||||
*/
|
||||
typedef struct ZydisInstructionEncoder_
|
||||
typedef struct ZydisEncoderContext_
|
||||
{
|
||||
uint8_t* buffer;
|
||||
size_t bufferLen;
|
||||
size_t writeOffs;
|
||||
ZydisInstructionInfo* info;
|
||||
const ZydisEncoderTableEntry* matchingEntry;
|
||||
} ZydisInstructionEncoder;
|
||||
uint8_t dispBitSize;
|
||||
uint64_t disp;
|
||||
uint8_t immBitSizes[2];
|
||||
uint64_t imms[2];
|
||||
} ZydisEncoderContext;
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Internal helpers */
|
||||
/* ============================================================================================== */
|
||||
|
||||
static ZydisStatus ZydisEmitByte(ZydisInstructionEncoder* encoder, uint8_t byte)
|
||||
static ZydisStatus ZydisEmitByte(ZydisEncoderContext* ctx, uint8_t byte)
|
||||
{
|
||||
if (encoder->writeOffs + 1 >= encoder->bufferLen)
|
||||
if (ctx->writeOffs + 1 >= ctx->bufferLen)
|
||||
{
|
||||
return ZYDIS_STATUS_INSUFFICIENT_BUFFER_SIZE;
|
||||
}
|
||||
|
||||
encoder->buffer[encoder->writeOffs++] = byte;
|
||||
ctx->buffer[ctx->writeOffs++] = byte;
|
||||
return ZYDIS_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static ZydisStatus ZydisEmitImm(ZydisInstructionEncoder* encoder, uint64_t imm, int bits)
|
||||
static ZydisStatus ZydisEmitImm(ZydisEncoderContext* ctx, uint64_t imm, int bits)
|
||||
{
|
||||
ZYDIS_ASSERT(bits == 8 || bits == 16 || bits == 32 || bits == 64);
|
||||
if (encoder->writeOffs + bits / 8 >= encoder->bufferLen)
|
||||
size_t newWriteOffs = ctx->writeOffs + bits / 8;
|
||||
if (newWriteOffs >= ctx->bufferLen ||
|
||||
newWriteOffs > ZYDIS_MAX_INSTRUCTION_LENGTH)
|
||||
{
|
||||
return ZYDIS_STATUS_INSUFFICIENT_BUFFER_SIZE;
|
||||
}
|
||||
|
@ -109,117 +117,118 @@ static ZydisStatus ZydisEmitImm(ZydisInstructionEncoder* encoder, uint64_t imm,
|
|||
// TODO: bswap on big-endian
|
||||
switch (bits)
|
||||
{
|
||||
case 8: *(uint8_t* )&encoder->buffer[encoder->writeOffs++] = (uint8_t )imm; break;
|
||||
case 16: *(uint16_t*)&encoder->buffer[encoder->writeOffs++] = (uint16_t)imm; break;
|
||||
case 32: *(uint32_t*)&encoder->buffer[encoder->writeOffs++] = (uint32_t)imm; break;
|
||||
case 64: *(uint64_t*)&encoder->buffer[encoder->writeOffs++] = (uint64_t)imm; break;
|
||||
case 8: *(uint8_t* )&ctx->buffer[ctx->writeOffs] = (uint8_t )imm; break;
|
||||
case 16: *(uint16_t*)&ctx->buffer[ctx->writeOffs] = (uint16_t)imm; break;
|
||||
case 32: *(uint32_t*)&ctx->buffer[ctx->writeOffs] = (uint32_t)imm; break;
|
||||
case 64: *(uint64_t*)&ctx->buffer[ctx->writeOffs] = (uint64_t)imm; break;
|
||||
default: ZYDIS_UNREACHABLE;
|
||||
}
|
||||
|
||||
ctx->writeOffs = newWriteOffs;
|
||||
return ZYDIS_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static ZydisStatus ZydisEncodeLegacyPrefixes(ZydisInstructionEncoder* encoder)
|
||||
static ZydisStatus ZydisEmitLegacyPrefixes(ZydisEncoderContext* ctx)
|
||||
{
|
||||
ZYDIS_ASSERT(encoder);
|
||||
ZydisInstructionAttributes attribs = encoder->info->attributes;
|
||||
ZYDIS_ASSERT(ctx);
|
||||
ZydisInstructionAttributes attribs = ctx->info->attributes;
|
||||
|
||||
if (attribs & ZYDIS_ATTRIB_HAS_LOCK)
|
||||
{
|
||||
ZYDIS_CHECK(ZydisEmitByte(encoder, 0xF0));
|
||||
ZYDIS_CHECK(ZydisEmitByte(ctx, 0xF0));
|
||||
}
|
||||
if (attribs & (ZYDIS_ATTRIB_HAS_REP | ZYDIS_ATTRIB_HAS_REPE | ZYDIS_ATTRIB_HAS_XRELEASE))
|
||||
{
|
||||
ZYDIS_CHECK(ZydisEmitByte(encoder, 0xF3));
|
||||
ZYDIS_CHECK(ZydisEmitByte(ctx, 0xF3));
|
||||
}
|
||||
if (attribs & (ZYDIS_ATTRIB_HAS_REPNE | ZYDIS_ATTRIB_HAS_BOUND | ZYDIS_ATTRIB_HAS_XACQUIRE))
|
||||
{
|
||||
ZYDIS_CHECK(ZydisEmitByte(encoder, 0xF2));
|
||||
ZYDIS_CHECK(ZydisEmitByte(ctx, 0xF2));
|
||||
}
|
||||
if (attribs & (ZYDIS_ATTRIB_HAS_BRANCH_NOT_TAKEN | ZYDIS_ATTRIB_HAS_SEGMENT_CS))
|
||||
{
|
||||
ZYDIS_CHECK(ZydisEmitByte(encoder, 0x2E));
|
||||
ZYDIS_CHECK(ZydisEmitByte(ctx, 0x2E));
|
||||
}
|
||||
if (attribs & (ZYDIS_ATTRIB_HAS_BRANCH_TAKEN | ZYDIS_ATTRIB_HAS_SEGMENT_DS))
|
||||
{
|
||||
ZYDIS_CHECK(ZydisEmitByte(encoder, 0x3E));
|
||||
ZYDIS_CHECK(ZydisEmitByte(ctx, 0x3E));
|
||||
}
|
||||
if (attribs & ZYDIS_ATTRIB_HAS_SEGMENT_SS)
|
||||
{
|
||||
ZYDIS_CHECK(ZydisEmitByte(encoder, 0x36));
|
||||
ZYDIS_CHECK(ZydisEmitByte(ctx, 0x36));
|
||||
}
|
||||
if (attribs & ZYDIS_ATTRIB_HAS_SEGMENT_ES)
|
||||
{
|
||||
ZYDIS_CHECK(ZydisEmitByte(encoder, 0x26));
|
||||
ZYDIS_CHECK(ZydisEmitByte(ctx, 0x26));
|
||||
}
|
||||
if (attribs & ZYDIS_ATTRIB_HAS_SEGMENT_FS)
|
||||
{
|
||||
ZYDIS_CHECK(ZydisEmitByte(encoder, 0x64));
|
||||
ZYDIS_CHECK(ZydisEmitByte(ctx, 0x64));
|
||||
}
|
||||
if (attribs & ZYDIS_ATTRIB_HAS_SEGMENT_GS)
|
||||
{
|
||||
ZYDIS_CHECK(ZydisEmitByte(encoder, 0x65));
|
||||
ZYDIS_CHECK(ZydisEmitByte(ctx, 0x65));
|
||||
}
|
||||
if (attribs & ZYDIS_ATTRIB_HAS_OPERANDSIZE)
|
||||
{
|
||||
ZYDIS_CHECK(ZydisEmitByte(encoder, 0x66));
|
||||
ZYDIS_CHECK(ZydisEmitByte(ctx, 0x66));
|
||||
}
|
||||
if (attribs & ZYDIS_ATTRIB_HAS_ADDRESSSIZE)
|
||||
{
|
||||
ZYDIS_CHECK(ZydisEmitByte(encoder, 0x67));
|
||||
ZYDIS_CHECK(ZydisEmitByte(ctx, 0x67));
|
||||
}
|
||||
|
||||
return ZYDIS_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static ZydisStatus ZydisEncodeREX(ZydisInstructionEncoder *encoder)
|
||||
static ZydisStatus ZydisEmitREX(ZydisEncoderContext* ctx)
|
||||
{
|
||||
ZYDIS_ASSERT(encoder);
|
||||
ZYDIS_ASSERT(ctx);
|
||||
ZYDIS_CHECK(ZydisEmitByte(
|
||||
encoder,
|
||||
ctx,
|
||||
0x40 |
|
||||
(encoder->info->details.rex.W & 0x01) << 3 |
|
||||
(encoder->info->details.rex.R & 0x01) << 2 |
|
||||
(encoder->info->details.rex.X & 0x01) << 1 |
|
||||
(encoder->info->details.rex.B & 0x01) << 0
|
||||
(ctx->info->details.rex.W & 0x01) << 3 |
|
||||
(ctx->info->details.rex.R & 0x01) << 2 |
|
||||
(ctx->info->details.rex.X & 0x01) << 1 |
|
||||
(ctx->info->details.rex.B & 0x01) << 0
|
||||
));
|
||||
return ZYDIS_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static ZydisStatus ZydisEncodeVEX(ZydisInstructionEncoder *encoder)
|
||||
static ZydisStatus ZydisEmitVEX(ZydisEncoderContext* ctx)
|
||||
{
|
||||
ZYDIS_ASSERT(encoder);
|
||||
ZYDIS_ASSERT(ctx);
|
||||
|
||||
// Write opcode.
|
||||
uint8_t opcode = encoder->info->details.vex.data[0];
|
||||
ZYDIS_CHECK(ZydisEmitByte(encoder, opcode));
|
||||
uint8_t opcode = ctx->info->details.vex.data[0];
|
||||
ZYDIS_CHECK(ZydisEmitByte(ctx, opcode));
|
||||
|
||||
// Write prefix' "operands".
|
||||
switch (opcode)
|
||||
{
|
||||
case 0xC4:
|
||||
ZYDIS_CHECK(ZydisEmitByte(
|
||||
encoder,
|
||||
(encoder->info->details.vex.R & 0x01) << 7 |
|
||||
(encoder->info->details.vex.X & 0x01) << 6 |
|
||||
(encoder->info->details.vex.B & 0x01) << 5 |
|
||||
(encoder->info->details.vex.m_mmmm & 0x1F) << 0
|
||||
ctx,
|
||||
(ctx->info->details.vex.R & 0x01) << 7 |
|
||||
(ctx->info->details.vex.X & 0x01) << 6 |
|
||||
(ctx->info->details.vex.B & 0x01) << 5 |
|
||||
(ctx->info->details.vex.m_mmmm & 0x1F) << 0
|
||||
));
|
||||
ZYDIS_CHECK(ZydisEmitByte(
|
||||
encoder,
|
||||
(encoder->info->details.vex.W & 0x01) << 7 |
|
||||
(encoder->info->details.vex.vvvv & 0x0F) << 3 |
|
||||
(encoder->info->details.vex.L & 0x01) << 2 |
|
||||
(encoder->info->details.vex.pp & 0x03) << 0
|
||||
ctx,
|
||||
(ctx->info->details.vex.W & 0x01) << 7 |
|
||||
(ctx->info->details.vex.vvvv & 0x0F) << 3 |
|
||||
(ctx->info->details.vex.L & 0x01) << 2 |
|
||||
(ctx->info->details.vex.pp & 0x03) << 0
|
||||
));
|
||||
break;
|
||||
case 0xC5:
|
||||
ZYDIS_CHECK(ZydisEmitByte(
|
||||
encoder,
|
||||
(encoder->info->details.vex.R & 0x01) << 7 |
|
||||
(encoder->info->details.vex.vvvv & 0x0F) << 3 |
|
||||
(encoder->info->details.vex.L & 0x01) << 2 |
|
||||
(encoder->info->details.vex.pp & 0x03) << 0
|
||||
ctx,
|
||||
(ctx->info->details.vex.R & 0x01) << 7 |
|
||||
(ctx->info->details.vex.vvvv & 0x0F) << 3 |
|
||||
(ctx->info->details.vex.L & 0x01) << 2 |
|
||||
(ctx->info->details.vex.pp & 0x03) << 0
|
||||
));
|
||||
break;
|
||||
default:
|
||||
|
@ -229,103 +238,99 @@ static ZydisStatus ZydisEncodeVEX(ZydisInstructionEncoder *encoder)
|
|||
return ZYDIS_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static ZydisStatus ZydisEncodeEVEX(ZydisInstructionEncoder *encoder)
|
||||
static ZydisStatus ZydisEmitEVEX(ZydisEncoderContext* ctx)
|
||||
{
|
||||
ZYDIS_ASSERT(encoder);
|
||||
|
||||
ZYDIS_CHECK(ZydisEmitByte(encoder, 0x62));
|
||||
ZYDIS_ASSERT(ctx);
|
||||
ZYDIS_CHECK(ZydisEmitByte(ctx, 0x62));
|
||||
ZYDIS_CHECK(ZydisEmitByte(
|
||||
encoder,
|
||||
(encoder->info->details.evex.R & 0x01) << 7 |
|
||||
(encoder->info->details.evex.X & 0x01) << 6 |
|
||||
(encoder->info->details.evex.B & 0x01) << 5 |
|
||||
(encoder->info->details.evex.R2 & 0x01) << 4 |
|
||||
(encoder->info->details.evex.mm & 0x03) << 0
|
||||
ctx,
|
||||
(ctx->info->details.evex.R & 0x01) << 7 |
|
||||
(ctx->info->details.evex.X & 0x01) << 6 |
|
||||
(ctx->info->details.evex.B & 0x01) << 5 |
|
||||
(ctx->info->details.evex.R2 & 0x01) << 4 |
|
||||
(ctx->info->details.evex.mm & 0x03) << 0
|
||||
));
|
||||
ZYDIS_CHECK(ZydisEmitByte(
|
||||
encoder,
|
||||
(encoder->info->details.evex.W & 0x01) << 7 |
|
||||
(encoder->info->details.evex.vvvv & 0x0F) << 3 |
|
||||
(encoder->info->details.evex.pp & 0x03) << 0
|
||||
ctx,
|
||||
(ctx->info->details.evex.W & 0x01) << 7 |
|
||||
(ctx->info->details.evex.vvvv & 0x0F) << 3 |
|
||||
(ctx->info->details.evex.pp & 0x03) << 0
|
||||
));
|
||||
ZYDIS_CHECK(ZydisEmitByte(
|
||||
encoder,
|
||||
(encoder->info->details.evex.z & 0x01) << 7 |
|
||||
(encoder->info->details.evex.L2 & 0x01) << 6 |
|
||||
(encoder->info->details.evex.L & 0x01) << 5 |
|
||||
(encoder->info->details.evex.b & 0x01) << 4 |
|
||||
(encoder->info->details.evex.V2 & 0x01) << 3 |
|
||||
(encoder->info->details.evex.aaa & 0x07) << 0
|
||||
));
|
||||
|
||||
return ZYDIS_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static ZydisStatus ZydisEncodeXOP(ZydisInstructionEncoder* encoder)
|
||||
{
|
||||
ZYDIS_ASSERT(encoder);
|
||||
|
||||
ZYDIS_CHECK(ZydisEmitByte(encoder, 0x8F));
|
||||
ZYDIS_CHECK(ZydisEmitByte(
|
||||
encoder,
|
||||
(encoder->info->details.xop.R & 0x01) << 7 |
|
||||
(encoder->info->details.xop.X & 0x01) << 6 |
|
||||
(encoder->info->details.xop.B & 0x01) << 5 |
|
||||
(encoder->info->details.xop.m_mmmm & 0x1F) << 0
|
||||
));
|
||||
ZYDIS_CHECK(ZydisEmitByte(
|
||||
encoder,
|
||||
(encoder->info->details.xop.W & 0x01) << 7 |
|
||||
(encoder->info->details.xop.vvvv & 0x0F) << 3 |
|
||||
(encoder->info->details.xop.L & 0x01) << 2 |
|
||||
(encoder->info->details.xop.pp & 0x03) << 0
|
||||
));
|
||||
|
||||
return ZYDIS_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static ZydisStatus ZydisEncodeModRM(ZydisInstructionEncoder* encoder)
|
||||
{
|
||||
ZYDIS_ASSERT(encoder);
|
||||
ZYDIS_CHECK(ZydisEmitByte(
|
||||
encoder,
|
||||
(encoder->info->details.modrm.mod & 0x03) << 6 |
|
||||
(encoder->info->details.modrm.reg & 0x07) << 3 |
|
||||
(encoder->info->details.modrm.rm & 0x07) << 0
|
||||
ctx,
|
||||
(ctx->info->details.evex.z & 0x01) << 7 |
|
||||
(ctx->info->details.evex.L2 & 0x01) << 6 |
|
||||
(ctx->info->details.evex.L & 0x01) << 5 |
|
||||
(ctx->info->details.evex.b & 0x01) << 4 |
|
||||
(ctx->info->details.evex.V2 & 0x01) << 3 |
|
||||
(ctx->info->details.evex.aaa & 0x07) << 0
|
||||
));
|
||||
return ZYDIS_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static ZydisStatus ZydisEncodeSIB(ZydisInstructionEncoder* encoder)
|
||||
static ZydisStatus ZydisEmitXOP(ZydisEncoderContext* ctx)
|
||||
{
|
||||
ZYDIS_ASSERT(encoder);
|
||||
ZYDIS_ASSERT(ctx);
|
||||
ZYDIS_CHECK(ZydisEmitByte(ctx, 0x8F));
|
||||
ZYDIS_CHECK(ZydisEmitByte(
|
||||
encoder,
|
||||
(encoder->info->details.sib.scale & 0x03) << 6 |
|
||||
(encoder->info->details.sib.index & 0x07) << 3 |
|
||||
(encoder->info->details.sib.base & 0x07) << 0
|
||||
ctx,
|
||||
(ctx->info->details.xop.R & 0x01) << 7 |
|
||||
(ctx->info->details.xop.X & 0x01) << 6 |
|
||||
(ctx->info->details.xop.B & 0x01) << 5 |
|
||||
(ctx->info->details.xop.m_mmmm & 0x1F) << 0
|
||||
));
|
||||
ZYDIS_CHECK(ZydisEmitByte(
|
||||
ctx,
|
||||
(ctx->info->details.xop.W & 0x01) << 7 |
|
||||
(ctx->info->details.xop.vvvv & 0x0F) << 3 |
|
||||
(ctx->info->details.xop.L & 0x01) << 2 |
|
||||
(ctx->info->details.xop.pp & 0x03) << 0
|
||||
));
|
||||
return ZYDIS_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static ZydisStatus ZydisEncodeOpcode(ZydisInstructionEncoder* encoder)
|
||||
static ZydisStatus ZydisEmitModRM(ZydisEncoderContext* ctx)
|
||||
{
|
||||
ZYDIS_ASSERT(encoder);
|
||||
ZYDIS_ASSERT(encoder->matchingEntry);
|
||||
ZYDIS_ASSERT(ctx);
|
||||
ZYDIS_CHECK(ZydisEmitByte(
|
||||
ctx,
|
||||
(ctx->info->details.modrm.mod & 0x03) << 6 |
|
||||
(ctx->info->details.modrm.reg & 0x07) << 3 |
|
||||
(ctx->info->details.modrm.rm & 0x07) << 0
|
||||
));
|
||||
return ZYDIS_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static ZydisStatus ZydisEmitSIB(ZydisEncoderContext* ctx)
|
||||
{
|
||||
ZYDIS_ASSERT(ctx);
|
||||
ZYDIS_CHECK(ZydisEmitByte(
|
||||
ctx,
|
||||
(ctx->info->details.sib.scale & 0x03) << 6 |
|
||||
(ctx->info->details.sib.index & 0x07) << 3 |
|
||||
(ctx->info->details.sib.base & 0x07) << 0
|
||||
));
|
||||
return ZYDIS_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static ZydisStatus ZydisEmitOpcode(ZydisEncoderContext* ctx)
|
||||
{
|
||||
ZYDIS_ASSERT(ctx);
|
||||
ZYDIS_ASSERT(ctx->matchingEntry);
|
||||
|
||||
// Put opcode extension prefix(es), if required.
|
||||
switch (encoder->matchingEntry->map)
|
||||
switch (ctx->matchingEntry->map)
|
||||
{
|
||||
case ZYDIS_OPCODE_MAP_0F:
|
||||
ZYDIS_CHECK(ZydisEmitByte(encoder, 0x0F));
|
||||
ZYDIS_CHECK(ZydisEmitByte(ctx, 0x0F));
|
||||
break;
|
||||
case ZYDIS_OPCODE_MAP_0F38:
|
||||
ZYDIS_CHECK(ZydisEmitByte(encoder, 0x0F));
|
||||
ZYDIS_CHECK(ZydisEmitByte(encoder, 0x38));
|
||||
ZYDIS_CHECK(ZydisEmitByte(ctx, 0x0F));
|
||||
ZYDIS_CHECK(ZydisEmitByte(ctx, 0x38));
|
||||
break;
|
||||
case ZYDIS_OPCODE_MAP_0F3A:
|
||||
ZYDIS_CHECK(ZydisEmitByte(encoder, 0x0F));
|
||||
ZYDIS_CHECK(ZydisEmitByte(encoder, 0x3A));
|
||||
ZYDIS_CHECK(ZydisEmitByte(ctx, 0x0F));
|
||||
ZYDIS_CHECK(ZydisEmitByte(ctx, 0x3A));
|
||||
break;
|
||||
case ZYDIS_OPCODE_MAP_XOP8:
|
||||
case ZYDIS_OPCODE_MAP_XOP9:
|
||||
|
@ -339,29 +344,75 @@ static ZydisStatus ZydisEncodeOpcode(ZydisInstructionEncoder* encoder)
|
|||
}
|
||||
|
||||
// Emit actual opcode.
|
||||
ZYDIS_CHECK(ZydisEmitByte(encoder, encoder->matchingEntry->opcode));
|
||||
ZYDIS_CHECK(ZydisEmitByte(ctx, ctx->info->opcode));
|
||||
|
||||
return ZYDIS_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static ZydisStatus ZydisPrepareOperand(ZydisInstructionEncoder* encoder,
|
||||
ZydisOperandInfo* operand)
|
||||
static ZydisStatus ZydisSimplifyOperandType(ZydisSemanticOperandType semType,
|
||||
ZydisOperandType* simpleType)
|
||||
{
|
||||
switch (operand->encoding)
|
||||
// TODO: Better mapping, this is just for testing.
|
||||
switch (semType)
|
||||
{
|
||||
case ZYDIS_SEM_OPERAND_TYPE_GPR8:
|
||||
case ZYDIS_SEM_OPERAND_TYPE_GPR16:
|
||||
case ZYDIS_SEM_OPERAND_TYPE_GPR32:
|
||||
case ZYDIS_SEM_OPERAND_TYPE_GPR64:
|
||||
*simpleType = ZYDIS_OPERAND_TYPE_REGISTER;
|
||||
break;
|
||||
case ZYDIS_SEM_OPERAND_TYPE_IMM8:
|
||||
case ZYDIS_SEM_OPERAND_TYPE_IMM16:
|
||||
case ZYDIS_SEM_OPERAND_TYPE_IMM32:
|
||||
case ZYDIS_SEM_OPERAND_TYPE_IMM64:
|
||||
case ZYDIS_SEM_OPERAND_TYPE_REL8:
|
||||
case ZYDIS_SEM_OPERAND_TYPE_REL16:
|
||||
case ZYDIS_SEM_OPERAND_TYPE_REL32:
|
||||
case ZYDIS_SEM_OPERAND_TYPE_REL64:
|
||||
*simpleType = ZYDIS_OPERAND_TYPE_IMMEDIATE;
|
||||
break;
|
||||
case ZYDIS_SEM_OPERAND_TYPE_MEM8:
|
||||
case ZYDIS_SEM_OPERAND_TYPE_MEM16:
|
||||
case ZYDIS_SEM_OPERAND_TYPE_MEM32:
|
||||
case ZYDIS_SEM_OPERAND_TYPE_MEM64:
|
||||
*simpleType = ZYDIS_OPERAND_TYPE_MEMORY;
|
||||
break;
|
||||
default:
|
||||
return ZYDIS_STATUS_IMPOSSIBLE_INSTRUCTION;
|
||||
}
|
||||
|
||||
return ZYDIS_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static ZydisStatus ZydisPrepareRegOperand(ZydisEncoderContext* ctx,
|
||||
ZydisRegister reg, uint8_t useRM)
|
||||
{
|
||||
uint8_t* regRM = useRM ? &ctx->info->details.modrm.rm
|
||||
: &ctx->info->details.modrm.reg;
|
||||
uint8_t* rexRB = useRM ? &ctx->info->details.rex.B
|
||||
: &ctx->info->details.rex.R;
|
||||
|
||||
int16_t regID = ZydisRegisterGetId(reg);
|
||||
if (regID == -1) return ZYDIS_STATUS_INVALID_PARAMETER;
|
||||
|
||||
*regRM = regID & 0x07;
|
||||
*rexRB = (regID & 0x08) >> 3;
|
||||
ctx->info->attributes |= ZYDIS_ATTRIB_HAS_MODRM;
|
||||
if (*rexRB) ctx->info->attributes |= ZYDIS_ATTRIB_HAS_REX;
|
||||
|
||||
return ZYDIS_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static ZydisStatus ZydisPrepareOperand(ZydisEncoderContext* ctx,
|
||||
ZydisOperandInfo* operand, const ZydisEncoderTableOperand* tableEntry)
|
||||
{
|
||||
switch (tableEntry->encoding)
|
||||
{
|
||||
case ZYDIS_OPERAND_ENCODING_NONE:
|
||||
break; // Nothing to do.
|
||||
case ZYDIS_OPERAND_ENCODING_REG:
|
||||
{
|
||||
int16_t reg = ZydisRegisterGetId(operand->reg);
|
||||
if (reg == -1) return ZYDIS_STATUS_INVALID_PARAMETER;
|
||||
encoder->info->details.modrm.reg = reg & 0x07;
|
||||
encoder->info->details.rex.R = (reg & 0x08) >> 3;
|
||||
encoder->info->attributes |= ZYDIS_ATTRIB_HAS_MODRM;
|
||||
if (encoder->info->details.rex.R)
|
||||
{
|
||||
encoder->info->attributes |= ZYDIS_ATTRIB_HAS_REX;
|
||||
}
|
||||
ZYDIS_CHECK(ZydisPrepareRegOperand(ctx, operand->reg, ZYDIS_FALSE));
|
||||
} break;
|
||||
case ZYDIS_OPERAND_ENCODING_RM:
|
||||
case ZYDIS_OPERAND_ENCODING_RM_CD2:
|
||||
|
@ -372,68 +423,129 @@ static ZydisStatus ZydisPrepareOperand(ZydisInstructionEncoder* encoder,
|
|||
case ZYDIS_OPERAND_ENCODING_RM_CD64:
|
||||
{
|
||||
// Memory operand?
|
||||
if (operand->reg == ZYDIS_REGISTER_NONE)
|
||||
if (operand->type == ZYDIS_OPERAND_TYPE_MEMORY)
|
||||
{
|
||||
int32_t divisor = 1;
|
||||
switch (operand->encoding)
|
||||
// Has base register?
|
||||
if (operand->mem.base != ZYDIS_REGISTER_NONE)
|
||||
{
|
||||
case ZYDIS_OPERAND_ENCODING_RM: divisor = 1; break;
|
||||
case ZYDIS_OPERAND_ENCODING_RM_CD2: divisor = 2; break;
|
||||
case ZYDIS_OPERAND_ENCODING_RM_CD4: divisor = 4; break;
|
||||
case ZYDIS_OPERAND_ENCODING_RM_CD8: divisor = 8; break;
|
||||
case ZYDIS_OPERAND_ENCODING_RM_CD16: divisor = 16; break;
|
||||
case ZYDIS_OPERAND_ENCODING_RM_CD32: divisor = 32; break;
|
||||
case ZYDIS_OPERAND_ENCODING_RM_CD64: divisor = 64; break;
|
||||
default: ZYDIS_UNREACHABLE;
|
||||
ZYDIS_CHECK(ZydisPrepareRegOperand(ctx, operand->reg, ZYDIS_TRUE));
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: Does rm=0x05 work with sbyte disps?
|
||||
ctx->info->details.modrm.rm = 0x05 /* memory */;
|
||||
}
|
||||
|
||||
// Has compressed disp encoding and is compression possible?
|
||||
int32_t* sdword = &operand->mem.disp.value.sdword;
|
||||
encoder->info->details.modrm.mod = 0x02 /* 32 bit disp */;
|
||||
if (divisor != 1 &&
|
||||
*sdword % divisor == 0 &&
|
||||
*sdword / divisor <= INT8_MAX &&
|
||||
*sdword / divisor >= INT8_MIN)
|
||||
// SIB byte required?
|
||||
if (operand->mem.index || operand->mem.scale)
|
||||
{
|
||||
encoder->info->details.modrm.mod = 0x01 /* 8 bit disp */;
|
||||
*sdword /= divisor;
|
||||
switch (operand->mem.scale)
|
||||
{
|
||||
case 1: ctx->info->details.sib.index = 0x01; break;
|
||||
case 2: ctx->info->details.sib.index = 0x02; break;
|
||||
case 4: ctx->info->details.sib.index = 0x03; break;
|
||||
case 8: ctx->info->details.sib.index = 0x04; break;
|
||||
default: return ZYDIS_STATUS_IMPOSSIBLE_INSTRUCTION; // TODO
|
||||
}
|
||||
|
||||
// TODO: base, index
|
||||
|
||||
ctx->info->attributes |= ZYDIS_ATTRIB_HAS_SIB;
|
||||
}
|
||||
// Nope, regular encoding. Does it fit a byte anyway?
|
||||
else if (*sdword <= INT8_MAX && *sdword >= INT8_MIN)
|
||||
|
||||
// Has displacement?
|
||||
if (operand->mem.disp.value.sdword)
|
||||
{
|
||||
encoder->info->details.modrm.mod = 0x01 /* 8 bit disp */;
|
||||
int32_t divisor = 1;
|
||||
switch (tableEntry->encoding)
|
||||
{
|
||||
case ZYDIS_OPERAND_ENCODING_RM: break;
|
||||
case ZYDIS_OPERAND_ENCODING_RM_CD2: divisor = 2; break;
|
||||
case ZYDIS_OPERAND_ENCODING_RM_CD4: divisor = 4; break;
|
||||
case ZYDIS_OPERAND_ENCODING_RM_CD8: divisor = 8; break;
|
||||
case ZYDIS_OPERAND_ENCODING_RM_CD16: divisor = 16; break;
|
||||
case ZYDIS_OPERAND_ENCODING_RM_CD32: divisor = 32; break;
|
||||
case ZYDIS_OPERAND_ENCODING_RM_CD64: divisor = 64; break;
|
||||
default: ZYDIS_UNREACHABLE;
|
||||
}
|
||||
|
||||
// Has compressed disp encoding and is compression possible?
|
||||
int32_t* sdword = &operand->mem.disp.value.sdword;
|
||||
if (divisor != 1 &&
|
||||
*sdword % divisor == 0 &&
|
||||
*sdword / divisor <= INT8_MAX &&
|
||||
*sdword / divisor >= INT8_MIN)
|
||||
{
|
||||
ctx->dispBitSize = 8;
|
||||
ctx->info->details.modrm.mod = 0x01 /* 8 bit disp */;
|
||||
*sdword /= divisor;
|
||||
}
|
||||
// Nope, regular encoding. Does it fit a byte anyway?
|
||||
else if (*sdword <= INT8_MAX && *sdword >= INT8_MIN)
|
||||
{
|
||||
ctx->dispBitSize = 8;
|
||||
ctx->info->details.modrm.mod = 0x01 /* 8 bit disp */;
|
||||
}
|
||||
// No compression possible, emit as 32 bit.
|
||||
else
|
||||
{
|
||||
ctx->dispBitSize = 32;
|
||||
ctx->info->details.modrm.mod = 0x02 /* 32 bit disp */;
|
||||
}
|
||||
|
||||
ctx->disp = *sdword;
|
||||
}
|
||||
// No displacement.
|
||||
else
|
||||
{
|
||||
ctx->info->details.modrm.mod = 0x00 /* no disp */;
|
||||
}
|
||||
}
|
||||
// Nope, register.
|
||||
else
|
||||
else if (operand->type == ZYDIS_OPERAND_TYPE_REGISTER)
|
||||
{
|
||||
int16_t reg = ZydisRegisterGetId(operand->reg);
|
||||
if (reg == -1) return ZYDIS_STATUS_INVALID_PARAMETER;
|
||||
encoder->info->details.modrm.reg = reg & 0x07;
|
||||
encoder->info->details.rex.B = (reg & 0x08) >> 3;
|
||||
encoder->info->attributes |= ZYDIS_ATTRIB_HAS_MODRM;
|
||||
if (encoder->info->details.rex.B)
|
||||
{
|
||||
encoder->info->attributes |= ZYDIS_ATTRIB_HAS_REX;
|
||||
}
|
||||
encoder->info->details.modrm.mod = 0x03;
|
||||
ZYDIS_CHECK(ZydisPrepareRegOperand(ctx, operand->reg, ZYDIS_TRUE));
|
||||
ctx->info->details.modrm.mod = 0x03 /* reg */;
|
||||
}
|
||||
|
||||
ctx->info->attributes |= ZYDIS_ATTRIB_HAS_MODRM;
|
||||
break;
|
||||
}
|
||||
case ZYDIS_OPERAND_ENCODING_OPCODE:
|
||||
break; // TODO
|
||||
{
|
||||
int16_t reg = ZydisRegisterGetId(operand->reg);
|
||||
if (reg == -1) return ZYDIS_STATUS_INVALID_PARAMETER;
|
||||
ctx->info->opcode += reg & 0x0F;
|
||||
ctx->info->details.rex.R = (reg & 0x08) >> 3;
|
||||
if (ctx->info->details.rex.B) ctx->info->attributes |= ZYDIS_ATTRIB_HAS_REX;
|
||||
break;
|
||||
}
|
||||
case ZYDIS_OPERAND_ENCODING_VVVV:
|
||||
break; // TODO
|
||||
case ZYDIS_OPERAND_ENCODING_AAA:
|
||||
break; // TODO
|
||||
case ZYDIS_OPERAND_ENCODING_IMM8_LO:
|
||||
{
|
||||
ctx->immBitSizes[0] = 8;
|
||||
ctx->imms[0] |= operand->imm.value.ubyte & 0x0F;
|
||||
break;
|
||||
}
|
||||
case ZYDIS_OPERAND_ENCODING_IMM8_HI:
|
||||
{
|
||||
ctx->immBitSizes[0] = 8;
|
||||
ctx->imms[0] |= (operand->imm.value.ubyte & 0x0F) << 4;
|
||||
break;
|
||||
}
|
||||
case ZYDIS_OPERAND_ENCODING_IMM8:
|
||||
case ZYDIS_OPERAND_ENCODING_IMM16:
|
||||
case ZYDIS_OPERAND_ENCODING_IMM32:
|
||||
case ZYDIS_OPERAND_ENCODING_IMM64:
|
||||
// Nothing to do here, we put those in a later stage.
|
||||
// TODO: moffs
|
||||
break;
|
||||
{
|
||||
uint8_t immIdx = ctx->immBitSizes[0] ? 1 : 0;
|
||||
ctx->immBitSizes[immIdx] = operand->imm.dataSize;
|
||||
ctx->imms[immIdx] = operand->imm.value.uqword;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
ZYDIS_UNREACHABLE;
|
||||
}
|
||||
|
@ -441,6 +553,17 @@ static ZydisStatus ZydisPrepareOperand(ZydisInstructionEncoder* encoder,
|
|||
return ZYDIS_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static ZydisStatus ZydisDeriveEncodingForOp(ZydisOperandDefinition* operand)
|
||||
{
|
||||
switch (operand->type)
|
||||
{
|
||||
default:
|
||||
return ZYDIS_STATUS_IMPOSSIBLE_INSTRUCTION; // TODO
|
||||
}
|
||||
|
||||
return ZYDIS_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static ZydisStatus ZydisFindMatchingDef(const ZydisInstructionInfo* info,
|
||||
const ZydisEncoderTableEntry** matchingEntry)
|
||||
{
|
||||
|
@ -449,7 +572,7 @@ static ZydisStatus ZydisFindMatchingDef(const ZydisInstructionInfo* info,
|
|||
|
||||
// Locate entries with matching mnemonic.
|
||||
// TODO: do binary search / hash based lookup instead
|
||||
for (size_t i = 0; i < sizeof(kEncoderTable) / sizeof(kEncoderTable[0]); ++i)
|
||||
for (size_t i = 0; i < ZYDIS_ARRAY_SIZE(kEncoderTable); ++i)
|
||||
{
|
||||
const ZydisEncoderTableEntry* curEntry = &kEncoderTable[i];
|
||||
if (curEntry->mnemonic != info->mnemonic ||
|
||||
|
@ -468,7 +591,10 @@ static ZydisStatus ZydisFindMatchingDef(const ZydisInstructionInfo* info,
|
|||
{
|
||||
const ZydisEncoderTableOperand* curEncoderOp = &curEntry->operands[k];
|
||||
const ZydisOperandInfo* curReqOp = &info->operands[k];
|
||||
if (curEncoderOp->encoding != curReqOp->encoding) goto continueTopLevel;
|
||||
if (curReqOp->encoding != curEncoderOp->encoding) goto continueTopLevel;
|
||||
ZydisOperandType simpleType;
|
||||
ZYDIS_CHECK(ZydisSimplifyOperandType(curEncoderOp->type, &simpleType));
|
||||
if (curReqOp->type != simpleType) goto continueTopLevel;
|
||||
}
|
||||
|
||||
// Still here? We found our entry!
|
||||
|
@ -486,45 +612,60 @@ static ZydisStatus ZydisFindMatchingDef(const ZydisInstructionInfo* info,
|
|||
/* Implementation of public functions */
|
||||
/* ============================================================================================== */
|
||||
|
||||
ZydisStatus ZydisEncoderEncodeInstruction(void* buffer, size_t bufferLen,
|
||||
ZydisStatus ZydisEncoderEncodeInstruction(void* buffer, size_t* bufferLen,
|
||||
ZydisInstructionInfo* info)
|
||||
{
|
||||
if (!info) return ZYDIS_STATUS_INVALID_PARAMETER;
|
||||
if (!buffer || !bufferLen) return ZYDIS_STATUS_INSUFFICIENT_BUFFER_SIZE;
|
||||
if (!info || !bufferLen) return ZYDIS_STATUS_INVALID_PARAMETER;
|
||||
if (!buffer || !*bufferLen) return ZYDIS_STATUS_INSUFFICIENT_BUFFER_SIZE;
|
||||
|
||||
ZydisInstructionEncoder encoder;
|
||||
memset(&encoder, 0, sizeof(encoder));
|
||||
ZydisEncoderContext ctx;
|
||||
memset(&ctx, 0, sizeof(ctx));
|
||||
memset(&info->details, 0, sizeof(info->details));
|
||||
encoder.buffer = (uint8_t*)buffer;
|
||||
encoder.bufferLen = bufferLen;
|
||||
encoder.writeOffs = 0;
|
||||
encoder.info = info;
|
||||
ctx.buffer = (uint8_t*)buffer;
|
||||
ctx.bufferLen = *bufferLen;
|
||||
ctx.writeOffs = 0;
|
||||
ctx.info = info;
|
||||
*bufferLen = 0;
|
||||
|
||||
// Mask out attributes that can't be set explicitly by user.
|
||||
info->attributes &= ZYDIS_USER_ENCODABLE_ATTRIB_MASK;
|
||||
|
||||
// Search matching instruction, collect information about what needs to be
|
||||
// encoded, what prefixes are required etc..
|
||||
ZYDIS_CHECK(ZydisFindMatchingDef(info, &encoder.matchingEntry));
|
||||
info->opcode = encoder.matchingEntry->opcode;
|
||||
info->attributes |= encoder.matchingEntry->mandatoryAttribs;
|
||||
// encoded, what prefixes are required, etc.
|
||||
ZYDIS_CHECK(ZydisFindMatchingDef(info, &ctx.matchingEntry));
|
||||
info->opcode = ctx.matchingEntry->opcode;
|
||||
info->attributes |= ctx.matchingEntry->mandatoryAttribs;
|
||||
|
||||
// Analyze and prepare operands.
|
||||
for (size_t i = 0; i < encoder.matchingEntry->operandCount; ++i)
|
||||
if (info->operandCount > ZYDIS_ARRAY_SIZE(info->operands))
|
||||
{
|
||||
ZYDIS_CHECK(ZydisPrepareOperand(&encoder, &info->operands[i]));
|
||||
// TODO: Better status?
|
||||
return ZYDIS_STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < ctx.matchingEntry->operandCount; ++i)
|
||||
{
|
||||
ZYDIS_CHECK(ZydisPrepareOperand(
|
||||
&ctx, &info->operands[i],
|
||||
&ctx.matchingEntry->operands[i]
|
||||
));
|
||||
}
|
||||
|
||||
// Do actual encoding work.
|
||||
ZYDIS_CHECK(ZydisEncodeLegacyPrefixes(&encoder));
|
||||
if (info->attributes & ZYDIS_ATTRIB_HAS_REX ) ZYDIS_CHECK(ZydisEncodeREX (&encoder));
|
||||
if (info->attributes & ZYDIS_ATTRIB_HAS_VEX ) ZYDIS_CHECK(ZydisEncodeVEX (&encoder));
|
||||
if (info->attributes & ZYDIS_ATTRIB_HAS_EVEX ) ZYDIS_CHECK(ZydisEncodeEVEX (&encoder));
|
||||
if (info->attributes & ZYDIS_ATTRIB_HAS_XOP ) ZYDIS_CHECK(ZydisEncodeXOP (&encoder));
|
||||
ZYDIS_CHECK(ZydisEncodeOpcode(&encoder));
|
||||
if (info->attributes & ZYDIS_ATTRIB_HAS_MODRM) ZYDIS_CHECK(ZydisEncodeModRM(&encoder));
|
||||
if (info->attributes & ZYDIS_ATTRIB_HAS_SIB ) ZYDIS_CHECK(ZydisEncodeSIB (&encoder));
|
||||
ZYDIS_CHECK(ZydisEmitLegacyPrefixes(&ctx));
|
||||
if (info->attributes & ZYDIS_ATTRIB_HAS_REX ) ZYDIS_CHECK(ZydisEmitREX (&ctx));
|
||||
if (info->attributes & ZYDIS_ATTRIB_HAS_VEX ) ZYDIS_CHECK(ZydisEmitVEX (&ctx));
|
||||
if (info->attributes & ZYDIS_ATTRIB_HAS_EVEX ) ZYDIS_CHECK(ZydisEmitEVEX (&ctx));
|
||||
if (info->attributes & ZYDIS_ATTRIB_HAS_XOP ) ZYDIS_CHECK(ZydisEmitXOP (&ctx));
|
||||
ZYDIS_CHECK(ZydisEmitOpcode(&ctx));
|
||||
if (info->attributes & ZYDIS_ATTRIB_HAS_MODRM) ZYDIS_CHECK(ZydisEmitModRM(&ctx));
|
||||
if (info->attributes & ZYDIS_ATTRIB_HAS_SIB ) ZYDIS_CHECK(ZydisEmitSIB (&ctx));
|
||||
|
||||
if (ctx.dispBitSize) ZYDIS_CHECK(ZydisEmitImm(&ctx, ctx.disp, ctx.dispBitSize));
|
||||
if (ctx.immBitSizes[0]) ZYDIS_CHECK(ZydisEmitImm(&ctx, ctx.imms[0], ctx.immBitSizes[0]));
|
||||
if (ctx.immBitSizes[1]) ZYDIS_CHECK(ZydisEmitImm(&ctx, ctx.imms[1], ctx.immBitSizes[1]));
|
||||
|
||||
*bufferLen = ctx.writeOffs;
|
||||
return ZYDIS_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
|
|
@ -88,24 +88,30 @@ int main(int argc, char** argv)
|
|||
continue;
|
||||
}
|
||||
|
||||
//char printBuffer[256];
|
||||
//ZydisFormatterFormatInstruction(
|
||||
// &formatter, &info, printBuffer, sizeof(printBuffer)
|
||||
//);
|
||||
//puts(printBuffer);
|
||||
readOffs += info.length;
|
||||
char printBuffer[256];
|
||||
ZydisFormatterFormatInstruction(
|
||||
&formatter, &info, printBuffer, sizeof(printBuffer)
|
||||
);
|
||||
puts(printBuffer);
|
||||
|
||||
// TODO: Remove
|
||||
// DEBUG CODE START
|
||||
//uint8_t encBuffer[15];
|
||||
//ZydisStatus encStatus = ZydisEncoderEncodeInstruction(
|
||||
// encBuffer, sizeof(encBuffer), &info
|
||||
//);
|
||||
//if (!ZYDIS_SUCCESS(encStatus)) {
|
||||
// //__asm int 3;
|
||||
// *(volatile int*)0 = 0;
|
||||
//}
|
||||
uint8_t encBuffer[15];
|
||||
size_t encBufferSize = sizeof(encBuffer);
|
||||
ZydisStatus encStatus = ZydisEncoderEncodeInstruction(
|
||||
encBuffer, &encBufferSize, &info
|
||||
);
|
||||
ZYDIS_ASSERT(ZYDIS_SUCCESS(encStatus));
|
||||
for (size_t i = 0; i < encBufferSize; ++i)
|
||||
{
|
||||
printf("%02X ", encBuffer[i]);
|
||||
}
|
||||
putchar('\n');
|
||||
ZYDIS_ASSERT(encBufferSize == info.length);
|
||||
ZYDIS_ASSERT(!memcmp(encBuffer, readBuf + readOffs, encBufferSize));
|
||||
// DEBUG CODE END
|
||||
|
||||
readOffs += info.length;
|
||||
}
|
||||
|
||||
if (readOffs < sizeof(readBuf))
|
||||
|
|
Loading…
Reference in New Issue