mirror of https://github.com/x64dbg/zydis
Added encoding of opcode bits into ModRM
This commit is contained in:
parent
1faec66a66
commit
eb64a23231
|
@ -78,10 +78,11 @@ typedef struct ZydisEncoderTableEntry_
|
||||||
ZydisEncoderTableOperand operands[5];
|
ZydisEncoderTableOperand operands[5];
|
||||||
ZydisOpcodeMap map;
|
ZydisOpcodeMap map;
|
||||||
ZydisInstructionAttributes attribs;
|
ZydisInstructionAttributes attribs;
|
||||||
ZydisModRMMod modRmMod;
|
ZydisModRMMod modRmReg;
|
||||||
ZydisModeConstraint modeConstraint;
|
ZydisModeConstraint modeConstraint;
|
||||||
ZydisPrefixBit prefixBits;
|
ZydisPrefixBit prefixBits;
|
||||||
uint8_t mandatoryPrefix; // 0x00 = None
|
uint8_t mandatoryPrefix; // 0x00 = None
|
||||||
|
uint8_t modrmReg; // 0xFF = None
|
||||||
} ZydisEncoderTableEntry;
|
} ZydisEncoderTableEntry;
|
||||||
|
|
||||||
struct ZydisPrefixAcceptMapping
|
struct ZydisPrefixAcceptMapping
|
||||||
|
@ -419,6 +420,8 @@ static ZydisStatus ZydisPrepareOpcode(ZydisEncoderContext* ctx)
|
||||||
static ZydisStatus ZydisSimplifyOperandType(ZydisSemanticOperandType semType,
|
static ZydisStatus ZydisSimplifyOperandType(ZydisSemanticOperandType semType,
|
||||||
ZydisOperandType* simpleType)
|
ZydisOperandType* simpleType)
|
||||||
{
|
{
|
||||||
|
ZYDIS_ASSERT(simpleType);
|
||||||
|
|
||||||
// TODO: Better mapping, this is just for testing.
|
// TODO: Better mapping, this is just for testing.
|
||||||
switch (semType)
|
switch (semType)
|
||||||
{
|
{
|
||||||
|
@ -454,6 +457,8 @@ static ZydisStatus ZydisSimplifyOperandType(ZydisSemanticOperandType semType,
|
||||||
static ZydisStatus ZydisPrepareRegOperand(ZydisEncoderContext* ctx,
|
static ZydisStatus ZydisPrepareRegOperand(ZydisEncoderContext* ctx,
|
||||||
ZydisRegister reg, char topBitLoc)
|
ZydisRegister reg, char topBitLoc)
|
||||||
{
|
{
|
||||||
|
ZYDIS_ASSERT(ctx);
|
||||||
|
|
||||||
int16_t regID = ZydisRegisterGetId(reg);
|
int16_t regID = ZydisRegisterGetId(reg);
|
||||||
if (regID == -1) return ZYDIS_STATUS_INVALID_PARAMETER;
|
if (regID == -1) return ZYDIS_STATUS_INVALID_PARAMETER;
|
||||||
|
|
||||||
|
@ -539,6 +544,10 @@ static ZydisBool ZydisIsStackReg(ZydisRegister reg)
|
||||||
static ZydisStatus ZydisPrepareMemoryOperand(ZydisEncoderContext* ctx,
|
static ZydisStatus ZydisPrepareMemoryOperand(ZydisEncoderContext* ctx,
|
||||||
ZydisOperandInfo* operand, const ZydisEncoderTableOperand* tableEntry)
|
ZydisOperandInfo* operand, const ZydisEncoderTableOperand* tableEntry)
|
||||||
{
|
{
|
||||||
|
ZYDIS_ASSERT(ctx);
|
||||||
|
ZYDIS_ASSERT(operand);
|
||||||
|
ZYDIS_ASSERT(tableEntry);
|
||||||
|
|
||||||
// TODO: RIP relative addressing
|
// TODO: RIP relative addressing
|
||||||
|
|
||||||
// Absolute memory access?
|
// Absolute memory access?
|
||||||
|
@ -727,12 +736,17 @@ static ZydisStatus ZydisPrepareMemoryOperand(ZydisEncoderContext* ctx,
|
||||||
static ZydisStatus ZydisPrepareOperand(ZydisEncoderContext* ctx,
|
static ZydisStatus ZydisPrepareOperand(ZydisEncoderContext* ctx,
|
||||||
ZydisOperandInfo* operand, const ZydisEncoderTableOperand* tableEntry)
|
ZydisOperandInfo* operand, const ZydisEncoderTableOperand* tableEntry)
|
||||||
{
|
{
|
||||||
|
ZYDIS_ASSERT(ctx);
|
||||||
|
ZYDIS_ASSERT(operand);
|
||||||
|
ZYDIS_ASSERT(tableEntry);
|
||||||
|
|
||||||
switch (tableEntry->encoding)
|
switch (tableEntry->encoding)
|
||||||
{
|
{
|
||||||
case ZYDIS_OPERAND_ENCODING_NONE:
|
case ZYDIS_OPERAND_ENCODING_NONE:
|
||||||
break; // Nothing to do.
|
break; // Nothing to do.
|
||||||
case ZYDIS_OPERAND_ENCODING_REG:
|
case ZYDIS_OPERAND_ENCODING_REG:
|
||||||
{
|
{
|
||||||
|
ZYDIS_ASSERT(!ctx->info->details.modrm.reg);
|
||||||
ZYDIS_CHECK(ZydisPrepareRegOperand(ctx, operand->reg, 'R'));
|
ZYDIS_CHECK(ZydisPrepareRegOperand(ctx, operand->reg, 'R'));
|
||||||
} break;
|
} break;
|
||||||
case ZYDIS_OPERAND_ENCODING_RM:
|
case ZYDIS_OPERAND_ENCODING_RM:
|
||||||
|
@ -743,6 +757,12 @@ static ZydisStatus ZydisPrepareOperand(ZydisEncoderContext* ctx,
|
||||||
case ZYDIS_OPERAND_ENCODING_RM_CD32:
|
case ZYDIS_OPERAND_ENCODING_RM_CD32:
|
||||||
case ZYDIS_OPERAND_ENCODING_RM_CD64:
|
case ZYDIS_OPERAND_ENCODING_RM_CD64:
|
||||||
{
|
{
|
||||||
|
ZYDIS_ASSERT(!ctx->info->details.modrm.mod);
|
||||||
|
ZYDIS_ASSERT(!ctx->info->details.modrm.rm);
|
||||||
|
ZYDIS_ASSERT(!ctx->info->details.sib.base);
|
||||||
|
ZYDIS_ASSERT(!ctx->info->details.sib.index);
|
||||||
|
ZYDIS_ASSERT(!ctx->info->details.sib.scale);
|
||||||
|
|
||||||
// Memory operand?
|
// Memory operand?
|
||||||
if (operand->type == ZYDIS_OPERAND_TYPE_MEMORY)
|
if (operand->type == ZYDIS_OPERAND_TYPE_MEMORY)
|
||||||
{
|
{
|
||||||
|
@ -811,6 +831,8 @@ static ZydisStatus ZydisPrepareOperand(ZydisEncoderContext* ctx,
|
||||||
|
|
||||||
static ZydisStatus ZydisPrepareMandatoryPrefixes(ZydisEncoderContext* ctx)
|
static ZydisStatus ZydisPrepareMandatoryPrefixes(ZydisEncoderContext* ctx)
|
||||||
{
|
{
|
||||||
|
ZYDIS_ASSERT(ctx);
|
||||||
|
|
||||||
// Is a prefix mandatory? 0x00 is a sentinel value for `None` in the table.
|
// Is a prefix mandatory? 0x00 is a sentinel value for `None` in the table.
|
||||||
if (ctx->matchingEntry->mandatoryPrefix != 0x00)
|
if (ctx->matchingEntry->mandatoryPrefix != 0x00)
|
||||||
{
|
{
|
||||||
|
@ -847,6 +869,8 @@ static ZydisStatus ZydisPrepareMandatoryPrefixes(ZydisEncoderContext* ctx)
|
||||||
|
|
||||||
static ZydisStatus ZydisDeriveEncodingForOp(ZydisOperandDefinition* operand)
|
static ZydisStatus ZydisDeriveEncodingForOp(ZydisOperandDefinition* operand)
|
||||||
{
|
{
|
||||||
|
ZYDIS_ASSERT(operand);
|
||||||
|
|
||||||
switch (operand->type)
|
switch (operand->type)
|
||||||
{
|
{
|
||||||
default:
|
default:
|
||||||
|
@ -969,6 +993,12 @@ ZydisStatus ZydisEncoderEncodeInstruction(void* buffer, size_t* bufferLen,
|
||||||
// Prepare opcode.
|
// Prepare opcode.
|
||||||
ZYDIS_CHECK(ZydisPrepareOpcode(&ctx));
|
ZYDIS_CHECK(ZydisPrepareOpcode(&ctx));
|
||||||
|
|
||||||
|
// Some instructions have additional opcode bits encoded in ModRM.reg.
|
||||||
|
if (ctx.matchingEntry->modRmReg != 0xFF)
|
||||||
|
{
|
||||||
|
ctx.info->details.modrm.reg = ctx.matchingEntry->modRmReg;
|
||||||
|
}
|
||||||
|
|
||||||
// Analyze and prepare operands.
|
// Analyze and prepare operands.
|
||||||
if (info->operandCount > ZYDIS_ARRAY_SIZE(info->operands))
|
if (info->operandCount > ZYDIS_ARRAY_SIZE(info->operands))
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue