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
839729bfb2
|
@ -6,21 +6,21 @@ set_property(GLOBAL PROPERTY USE_FOLDERS ON)
|
||||||
|
|
||||||
option(ZYDIS_BUILD_SHARED_LIBS
|
option(ZYDIS_BUILD_SHARED_LIBS
|
||||||
"Build shared libraries rather than static ones"
|
"Build shared libraries rather than static ones"
|
||||||
FALSE)
|
OFF)
|
||||||
option(ZYDIS_FORCE_SHARED_CRT
|
option(ZYDIS_FORCE_SHARED_CRT
|
||||||
"Forces shared linkage against the CRT even when building a static library"
|
"Forces shared linkage against the CRT even when building a static library. MSVC only."
|
||||||
FALSE)
|
OFF)
|
||||||
option(ZYDIS_FEATURE_IMPLICITLY_USED_REGISTERS
|
option(ZYDIS_FEATURE_IMPLICITLY_USED_REGISTERS
|
||||||
"Include information about implicitly used registers"
|
"Include information about implicitly used registers"
|
||||||
TRUE)
|
OFF)
|
||||||
option(ZYDIS_FEATURE_AFFECTED_FLAGS
|
option(ZYDIS_FEATURE_AFFECTED_FLAGS
|
||||||
"Include information about affected flags"
|
"Include information about affected flags"
|
||||||
TRUE)
|
OFF)
|
||||||
option(ZYDIS_FEATURE_CPUID
|
option(ZYDIS_FEATURE_CPUID
|
||||||
"Include information about CPUID feature-flags"
|
"Include information about CPUID feature-flags"
|
||||||
FALSE)
|
OFF)
|
||||||
option(ZYDIS_BUILD_EXAMPLES "Build examples" TRUE)
|
option(ZYDIS_BUILD_EXAMPLES "Build examples" ON)
|
||||||
option(ZYDIS_BUILD_TOOLS "Build tools" TRUE)
|
option(ZYDIS_BUILD_TOOLS "Build tools" ON)
|
||||||
|
|
||||||
if (NOT CONFIGURED_ONCE)
|
if (NOT CONFIGURED_ONCE)
|
||||||
if ("${CMAKE_C_COMPILER_ID}" STREQUAL "GNU" OR
|
if ("${CMAKE_C_COMPILER_ID}" STREQUAL "GNU" OR
|
||||||
|
@ -49,7 +49,7 @@ endif ()
|
||||||
# Library
|
# Library
|
||||||
set(headers
|
set(headers
|
||||||
"include/Zydis/Decoder.h"
|
"include/Zydis/Decoder.h"
|
||||||
"include/Zydis/Encoder.h"
|
#"include/Zydis/Encoder.h"
|
||||||
"include/Zydis/Defines.h"
|
"include/Zydis/Defines.h"
|
||||||
"include/Zydis/Formatter.h"
|
"include/Zydis/Formatter.h"
|
||||||
"include/Zydis/InstructionInfo.h"
|
"include/Zydis/InstructionInfo.h"
|
||||||
|
@ -62,7 +62,7 @@ set(headers
|
||||||
"include/Zydis/Internal/InstructionTable.h")
|
"include/Zydis/Internal/InstructionTable.h")
|
||||||
set(sources
|
set(sources
|
||||||
"src/Decoder.c"
|
"src/Decoder.c"
|
||||||
"src/Encoder.c"
|
#"src/Encoder.c"
|
||||||
"src/Formatter.c"
|
"src/Formatter.c"
|
||||||
"src/InstructionTable.c"
|
"src/InstructionTable.c"
|
||||||
"src/Mnemonic.c"
|
"src/Mnemonic.c"
|
||||||
|
|
|
@ -931,7 +931,7 @@ begin
|
||||||
begin
|
begin
|
||||||
O := NodeData^.Definition.Operands.Operands[I];
|
O := NodeData^.Definition.Operands.Operands[I];
|
||||||
S := S + IntToStr(Integer(O.OperandType)) + ',' + IntToStr(Integer(O.Encoding)) + ',' +
|
S := S + IntToStr(Integer(O.OperandType)) + ',' + IntToStr(Integer(O.Encoding)) + ',' +
|
||||||
IntToStr(Integer(O.AccessMode)) + ',';
|
IntToStr(Integer(O.Action)) + ',';
|
||||||
end;
|
end;
|
||||||
Clipboard.AsText := S;
|
Clipboard.AsText := S;
|
||||||
end;
|
end;
|
||||||
|
@ -959,7 +959,7 @@ begin
|
||||||
O := NodeData^.Definition.Operands.Operands[J];
|
O := NodeData^.Definition.Operands.Operands[J];
|
||||||
O.OperandType := TOperandType(StrToInt(A[I]));
|
O.OperandType := TOperandType(StrToInt(A[I]));
|
||||||
O.Encoding := TOperandEncoding(StrToInt(A[I + 1]));
|
O.Encoding := TOperandEncoding(StrToInt(A[I + 1]));
|
||||||
O.AccessMode := TOperandAccessMode(StrToInt(A[I + 2]));
|
O.Action := TOperandAction(StrToInt(A[I + 2]));
|
||||||
Inc(I, 3);
|
Inc(I, 3);
|
||||||
Inc(J);
|
Inc(J);
|
||||||
end;
|
end;
|
||||||
|
|
|
@ -36,6 +36,7 @@
|
||||||
#include <Zydis/Decoder.h>
|
#include <Zydis/Decoder.h>
|
||||||
#include <Zydis/Formatter.h>
|
#include <Zydis/Formatter.h>
|
||||||
#include <Zydis/Encoder.h>
|
#include <Zydis/Encoder.h>
|
||||||
|
#include <Zydis/Utils.h>
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
|
|
@ -524,7 +524,7 @@ static ZydisStatus ZydisDecodeOperandImmediate(ZydisInstructionDecoder* decoder,
|
||||||
case 32:
|
case 32:
|
||||||
{
|
{
|
||||||
uint32_t data[4] = { 0, 0, 0, 0 };
|
uint32_t data[4] = { 0, 0, 0, 0 };
|
||||||
for (int i = sizeof(data) / sizeof(data[0]); i > 0; --i)
|
for (int i = ZYDIS_ARRAY_SIZE(data); i > 0; --i)
|
||||||
{
|
{
|
||||||
ZYDIS_CHECK(ZydisInputNext(decoder, info, (uint8_t*)&data[i - 1]));
|
ZYDIS_CHECK(ZydisInputNext(decoder, info, (uint8_t*)&data[i - 1]));
|
||||||
}
|
}
|
||||||
|
@ -1255,6 +1255,7 @@ static ZydisStatus ZydisDecodeOperand(ZydisInstructionDecoder* decoder, ZydisIns
|
||||||
case ZYDIS_SEM_OPERAND_TYPE_REL8:
|
case ZYDIS_SEM_OPERAND_TYPE_REL8:
|
||||||
info->attributes |= ZYDIS_ATTRIB_IS_RELATIVE;
|
info->attributes |= ZYDIS_ATTRIB_IS_RELATIVE;
|
||||||
operand->imm.isRelative = ZYDIS_TRUE;
|
operand->imm.isRelative = ZYDIS_TRUE;
|
||||||
|
// Intentional fallthrough.
|
||||||
case ZYDIS_SEM_OPERAND_TYPE_IMM8:
|
case ZYDIS_SEM_OPERAND_TYPE_IMM8:
|
||||||
operand->size = 8;
|
operand->size = 8;
|
||||||
operand->imm.isSigned = ZYDIS_TRUE;
|
operand->imm.isSigned = ZYDIS_TRUE;
|
||||||
|
@ -1266,6 +1267,7 @@ static ZydisStatus ZydisDecodeOperand(ZydisInstructionDecoder* decoder, ZydisIns
|
||||||
case ZYDIS_SEM_OPERAND_TYPE_REL16:
|
case ZYDIS_SEM_OPERAND_TYPE_REL16:
|
||||||
info->attributes |= ZYDIS_ATTRIB_IS_RELATIVE;
|
info->attributes |= ZYDIS_ATTRIB_IS_RELATIVE;
|
||||||
operand->imm.isRelative = ZYDIS_TRUE;
|
operand->imm.isRelative = ZYDIS_TRUE;
|
||||||
|
// Intentional fallthrough.
|
||||||
case ZYDIS_SEM_OPERAND_TYPE_IMM16:
|
case ZYDIS_SEM_OPERAND_TYPE_IMM16:
|
||||||
operand->size = 16;
|
operand->size = 16;
|
||||||
operand->imm.isSigned = ZYDIS_TRUE;
|
operand->imm.isSigned = ZYDIS_TRUE;
|
||||||
|
@ -1280,6 +1282,7 @@ static ZydisStatus ZydisDecodeOperand(ZydisInstructionDecoder* decoder, ZydisIns
|
||||||
case ZYDIS_SEM_OPERAND_TYPE_REL64:
|
case ZYDIS_SEM_OPERAND_TYPE_REL64:
|
||||||
info->attributes |= ZYDIS_ATTRIB_IS_RELATIVE;
|
info->attributes |= ZYDIS_ATTRIB_IS_RELATIVE;
|
||||||
operand->imm.isRelative = ZYDIS_TRUE;
|
operand->imm.isRelative = ZYDIS_TRUE;
|
||||||
|
// Intentional fallthrough.
|
||||||
case ZYDIS_SEM_OPERAND_TYPE_IMM64:
|
case ZYDIS_SEM_OPERAND_TYPE_IMM64:
|
||||||
operand->size = 64;
|
operand->size = 64;
|
||||||
operand->imm.isSigned = ZYDIS_TRUE;
|
operand->imm.isSigned = ZYDIS_TRUE;
|
||||||
|
@ -2383,6 +2386,16 @@ ZydisStatus ZydisDecoderDecodeInstructionEx(ZydisInstructionDecoder* decoder,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// For relative operands, apply instruction length offset.
|
||||||
|
for (size_t i = 0; i < info->operandCount; ++i)
|
||||||
|
{
|
||||||
|
if (info->operands[i].type == ZYDIS_OPERAND_TYPE_IMMEDIATE &&
|
||||||
|
info->operands[i].imm.isRelative)
|
||||||
|
{
|
||||||
|
info->operands[i].imm.value.sqword += info->length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Replace XCHG rAX, rAX with NOP alias
|
// Replace XCHG rAX, rAX with NOP alias
|
||||||
if (info->mnemonic == ZYDIS_MNEMONIC_XCHG)
|
if (info->mnemonic == ZYDIS_MNEMONIC_XCHG)
|
||||||
{
|
{
|
||||||
|
|
223
src/Encoder.c
223
src/Encoder.c
|
@ -78,10 +78,11 @@ typedef struct ZydisEncoderTableEntry_
|
||||||
ZydisEncoderTableOperand operands[5];
|
ZydisEncoderTableOperand operands[5];
|
||||||
ZydisOpcodeMap map;
|
ZydisOpcodeMap map;
|
||||||
ZydisInstructionAttributes attribs;
|
ZydisInstructionAttributes attribs;
|
||||||
ZydisModRMMod modRmMod;
|
|
||||||
ZydisModeConstraint modeConstraint;
|
ZydisModeConstraint modeConstraint;
|
||||||
ZydisPrefixBit prefixBits;
|
ZydisPrefixBit prefixBits;
|
||||||
uint8_t mandatoryPrefix; // 0x00 = None
|
uint8_t mandatoryPrefix; // 0x00 = None
|
||||||
|
uint8_t modrmReg; // 0xFF = None
|
||||||
|
const char* cmt;
|
||||||
} ZydisEncoderTableEntry;
|
} ZydisEncoderTableEntry;
|
||||||
|
|
||||||
struct ZydisPrefixAcceptMapping
|
struct ZydisPrefixAcceptMapping
|
||||||
|
@ -250,8 +251,8 @@ static ZydisStatus ZydisEmitVEX(ZydisEncoderContext* ctx)
|
||||||
ZYDIS_ASSERT(ctx);
|
ZYDIS_ASSERT(ctx);
|
||||||
|
|
||||||
// Can we use short 2-byte VEX encoding?
|
// Can we use short 2-byte VEX encoding?
|
||||||
if (ctx->info->details.vex.X == 1 &&
|
if (ctx->info->details.vex.X == 0 &&
|
||||||
ctx->info->details.vex.B == 1 &&
|
ctx->info->details.vex.B == 0 &&
|
||||||
ctx->info->details.vex.W == 0 &&
|
ctx->info->details.vex.W == 0 &&
|
||||||
ctx->info->details.vex.m_mmmm == 1)
|
ctx->info->details.vex.m_mmmm == 1)
|
||||||
{
|
{
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -467,9 +472,11 @@ static ZydisStatus ZydisPrepareRegOperand(ZydisEncoderContext* ctx,
|
||||||
case 'X': ctx->info->details.sib.index = lowerBits; break;
|
case 'X': ctx->info->details.sib.index = lowerBits; break;
|
||||||
default: ZYDIS_UNREACHABLE;
|
default: ZYDIS_UNREACHABLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// No top bit? Quick exit.
|
||||||
|
if (!topBit) return ZYDIS_STATUS_SUCCESS;
|
||||||
|
|
||||||
uint8_t* topBitDst = NULL;
|
uint8_t* topBitDst = NULL;
|
||||||
|
|
||||||
switch (ctx->info->encoding)
|
switch (ctx->info->encoding)
|
||||||
{
|
{
|
||||||
case ZYDIS_INSTRUCTION_ENCODING_DEFAULT:
|
case ZYDIS_INSTRUCTION_ENCODING_DEFAULT:
|
||||||
|
@ -527,21 +534,73 @@ static ZydisBool ZydisIsBPReg(ZydisRegister reg)
|
||||||
reg == ZYDIS_REGISTER_RBP;
|
reg == ZYDIS_REGISTER_RBP;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ZydisBool ZydisIsStackReg(ZydisRegister reg)
|
static ZydisBool ZydisIsSPReg(ZydisRegister reg)
|
||||||
{
|
{
|
||||||
return reg == ZYDIS_REGISTER_SPL ||
|
return reg == ZYDIS_REGISTER_SPL ||
|
||||||
reg == ZYDIS_REGISTER_SP ||
|
reg == ZYDIS_REGISTER_SP ||
|
||||||
reg == ZYDIS_REGISTER_ESP ||
|
reg == ZYDIS_REGISTER_ESP ||
|
||||||
reg == ZYDIS_REGISTER_RSP ||
|
reg == ZYDIS_REGISTER_RSP;
|
||||||
ZydisIsBPReg(reg);
|
}
|
||||||
|
|
||||||
|
static ZydisBool ZydisIsIPReg(ZydisRegister reg)
|
||||||
|
{
|
||||||
|
return reg == ZYDIS_REGISTER_IP ||
|
||||||
|
reg == ZYDIS_REGISTER_EIP ||
|
||||||
|
reg == ZYDIS_REGISTER_RIP;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ZydisBool ZydisIsStackReg(ZydisRegister reg)
|
||||||
|
{
|
||||||
|
return ZydisIsSPReg(reg) || ZydisIsBPReg(reg);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ZydisStatus ZydisPrepareSegmentPrefix(ZydisEncoderContext* ctx,
|
||||||
|
ZydisRegister segment, ZydisRegister base)
|
||||||
|
{
|
||||||
|
// Segment prefix required?
|
||||||
|
switch (segment)
|
||||||
|
{
|
||||||
|
case ZYDIS_REGISTER_ES:
|
||||||
|
ctx->info->attributes |= ZYDIS_ATTRIB_HAS_SEGMENT_ES;
|
||||||
|
break;
|
||||||
|
case ZYDIS_REGISTER_SS:
|
||||||
|
if (!ZydisIsStackReg(base))
|
||||||
|
{
|
||||||
|
ctx->info->attributes |= ZYDIS_ATTRIB_HAS_SEGMENT_SS;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ZYDIS_REGISTER_CS:
|
||||||
|
ctx->info->attributes |= ZYDIS_ATTRIB_HAS_SEGMENT_CS;
|
||||||
|
break;
|
||||||
|
case ZYDIS_REGISTER_DS:
|
||||||
|
if (ZydisIsStackReg(base))
|
||||||
|
{
|
||||||
|
ctx->info->attributes |= ZYDIS_ATTRIB_HAS_SEGMENT_DS;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ZYDIS_REGISTER_FS:
|
||||||
|
ctx->info->attributes |= ZYDIS_ATTRIB_HAS_SEGMENT_FS;
|
||||||
|
break;
|
||||||
|
case ZYDIS_REGISTER_GS:
|
||||||
|
ctx->info->attributes |= ZYDIS_ATTRIB_HAS_SEGMENT_GS;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return ZYDIS_STATUS_IMPOSSIBLE_INSTRUCTION; // TODO: Better status.
|
||||||
|
}
|
||||||
|
|
||||||
|
return ZYDIS_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ZydisStatus ZydisPrepareMemoryOperand(ZydisEncoderContext* ctx,
|
static ZydisStatus ZydisPrepareMemoryOperand(ZydisEncoderContext* ctx,
|
||||||
ZydisOperandInfo* operand, const ZydisEncoderTableOperand* tableEntry)
|
ZydisOperandInfo* operand, const ZydisEncoderTableOperand* tableEntry)
|
||||||
{
|
{
|
||||||
// TODO: RIP relative addressing
|
ZYDIS_ASSERT(ctx);
|
||||||
|
ZYDIS_ASSERT(operand);
|
||||||
|
ZYDIS_ASSERT(tableEntry);
|
||||||
|
|
||||||
// Absolute memory access?
|
ZYDIS_CHECK(ZydisPrepareSegmentPrefix(ctx, operand->mem.segment, operand->mem.base));
|
||||||
|
|
||||||
|
// Absolute memory access? Special case.
|
||||||
if (operand->mem.base == ZYDIS_REGISTER_NONE)
|
if (operand->mem.base == ZYDIS_REGISTER_NONE)
|
||||||
{
|
{
|
||||||
ctx->disp = operand->mem.disp.value.sdword;
|
ctx->disp = operand->mem.disp.value.sdword;
|
||||||
|
@ -567,6 +626,34 @@ static ZydisStatus ZydisPrepareMemoryOperand(ZydisEncoderContext* ctx,
|
||||||
return ZYDIS_STATUS_SUCCESS;
|
return ZYDIS_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// rIP relative addressing? Special case.
|
||||||
|
if (ZydisIsIPReg(operand->mem.base))
|
||||||
|
{
|
||||||
|
// rIP addressing is only available since AMD64.
|
||||||
|
if (ctx->info->mode != ZYDIS_DISASSEMBLER_MODE_64BIT)
|
||||||
|
{
|
||||||
|
return ZYDIS_STATUS_IMPOSSIBLE_INSTRUCTION; // TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only available with either EIP or RIP, not with IP.
|
||||||
|
if (operand->mem.base == ZYDIS_REGISTER_IP)
|
||||||
|
{
|
||||||
|
return ZYDIS_STATUS_IMPOSSIBLE_INSTRUCTION; // TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx->disp = operand->mem.disp.value.sdword;
|
||||||
|
ctx->dispBitSize = 32;
|
||||||
|
ctx->info->details.modrm.mod = 0x00;
|
||||||
|
ctx->info->details.modrm.rm = 0x05 /* RIP relative mem */;
|
||||||
|
|
||||||
|
if (operand->mem.base == ZYDIS_REGISTER_EIP)
|
||||||
|
{
|
||||||
|
ctx->info->attributes |= ZYDIS_ATTRIB_HAS_ADDRESSSIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ZYDIS_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
// Process base register.
|
// Process base register.
|
||||||
ZYDIS_CHECK(ZydisPrepareRegOperand(ctx, operand->mem.base, 'B'));
|
ZYDIS_CHECK(ZydisPrepareRegOperand(ctx, operand->mem.base, 'B'));
|
||||||
|
|
||||||
|
@ -612,49 +699,13 @@ static ZydisStatus ZydisPrepareMemoryOperand(ZydisEncoderContext* ctx,
|
||||||
return ZYDIS_STATUS_INVALID_PARAMETER; // TODO
|
return ZYDIS_STATUS_INVALID_PARAMETER; // TODO
|
||||||
}
|
}
|
||||||
|
|
||||||
// Segment prefix required?
|
// SIB byte required? rSP can only be encoded with SIB.
|
||||||
switch (operand->mem.segment)
|
if (operand->mem.index || operand->mem.scale || ZydisIsSPReg(operand->mem.base))
|
||||||
{
|
{
|
||||||
case ZYDIS_REGISTER_ES:
|
|
||||||
ctx->info->attributes |= ZYDIS_ATTRIB_HAS_SEGMENT_ES;
|
|
||||||
break;
|
|
||||||
case ZYDIS_REGISTER_SS:
|
|
||||||
ctx->info->attributes |= ZYDIS_ATTRIB_HAS_SEGMENT_SS;
|
|
||||||
break;
|
|
||||||
case ZYDIS_REGISTER_CS:
|
|
||||||
if (!ZydisIsStackReg(operand->mem.base))
|
|
||||||
{
|
|
||||||
ctx->info->attributes |= ZYDIS_ATTRIB_HAS_SEGMENT_CS;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case ZYDIS_REGISTER_DS:
|
|
||||||
if (ZydisIsStackReg(operand->mem.base))
|
|
||||||
{
|
|
||||||
ctx->info->attributes |= ZYDIS_ATTRIB_HAS_SEGMENT_DS;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case ZYDIS_REGISTER_FS:
|
|
||||||
ctx->info->attributes |= ZYDIS_ATTRIB_HAS_SEGMENT_FS;
|
|
||||||
break;
|
|
||||||
case ZYDIS_REGISTER_GS:
|
|
||||||
ctx->info->attributes |= ZYDIS_ATTRIB_HAS_SEGMENT_GS;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return ZYDIS_STATUS_IMPOSSIBLE_INSTRUCTION; // TODO: Better status.
|
|
||||||
}
|
|
||||||
|
|
||||||
// SIB byte required?
|
|
||||||
if (operand->mem.index || operand->mem.scale)
|
|
||||||
{
|
|
||||||
// Base and index register must be of same register class, verify.
|
|
||||||
if (ZydisRegisterGetClass(operand->mem.index) != baseRegClass)
|
|
||||||
{
|
|
||||||
return ZYDIS_STATUS_IMPOSSIBLE_INSTRUCTION; // TODO
|
|
||||||
}
|
|
||||||
|
|
||||||
// Translate scale to SIB format.
|
// Translate scale to SIB format.
|
||||||
switch (operand->mem.scale)
|
switch (operand->mem.scale)
|
||||||
{
|
{
|
||||||
|
case 0: // We take 0 (uninitialized, 0 from memset) as * 1.
|
||||||
case 1: ctx->info->details.sib.scale = 0x00; break;
|
case 1: ctx->info->details.sib.scale = 0x00; break;
|
||||||
case 2: ctx->info->details.sib.scale = 0x01; break;
|
case 2: ctx->info->details.sib.scale = 0x01; break;
|
||||||
case 4: ctx->info->details.sib.scale = 0x02; break;
|
case 4: ctx->info->details.sib.scale = 0x02; break;
|
||||||
|
@ -662,11 +713,25 @@ static ZydisStatus ZydisPrepareMemoryOperand(ZydisEncoderContext* ctx,
|
||||||
default: return ZYDIS_STATUS_IMPOSSIBLE_INSTRUCTION; // TODO
|
default: return ZYDIS_STATUS_IMPOSSIBLE_INSTRUCTION; // TODO
|
||||||
}
|
}
|
||||||
|
|
||||||
// Base & index register.
|
// Move base register info to SIB.
|
||||||
ctx->info->details.sib.base = ctx->info->details.modrm.rm;
|
ctx->info->details.sib.base = ctx->info->details.modrm.rm;
|
||||||
ZYDIS_CHECK(ZydisPrepareRegOperand(ctx, operand->mem.index, 'X'));
|
|
||||||
|
|
||||||
ctx->info->details.modrm.rm = 0x04 /* SIB */;
|
ctx->info->details.modrm.rm = 0x04 /* SIB */;
|
||||||
|
|
||||||
|
// Process index register.
|
||||||
|
if (operand->mem.index != ZYDIS_REGISTER_NONE)
|
||||||
|
{
|
||||||
|
// Base and index register must be of same register class, verify.
|
||||||
|
if (ZydisRegisterGetClass(operand->mem.index) != baseRegClass)
|
||||||
|
{
|
||||||
|
return ZYDIS_STATUS_IMPOSSIBLE_INSTRUCTION; // TODO
|
||||||
|
}
|
||||||
|
ZYDIS_CHECK(ZydisPrepareRegOperand(ctx, operand->mem.index, 'X'));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ctx->info->details.sib.index = 0x04 /* no index */;
|
||||||
|
}
|
||||||
|
|
||||||
ctx->info->attributes |= ZYDIS_ATTRIB_HAS_SIB;
|
ctx->info->attributes |= ZYDIS_ATTRIB_HAS_SIB;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -727,12 +792,33 @@ 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.
|
// For some encodings, we have to switch on the sem op type.
|
||||||
|
switch (tableEntry->type)
|
||||||
|
{
|
||||||
|
case ZYDIS_SEM_OPERAND_TYPE_MOFFS16:
|
||||||
|
case ZYDIS_SEM_OPERAND_TYPE_MOFFS32:
|
||||||
|
case ZYDIS_SEM_OPERAND_TYPE_MOFFS64:
|
||||||
|
ZYDIS_CHECK(ZydisPrepareSegmentPrefix(
|
||||||
|
ctx, operand->mem.segment, ZYDIS_REGISTER_NONE
|
||||||
|
));
|
||||||
|
ctx->imms[0] = operand->mem.disp.value.sqword;
|
||||||
|
ctx->immBitSizes[0] = operand->mem.disp.dataSize;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// Hidden operand, nothing to encode.
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
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 +829,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)
|
||||||
{
|
{
|
||||||
|
@ -762,8 +854,8 @@ static ZydisStatus ZydisPrepareOperand(ZydisEncoderContext* ctx,
|
||||||
{
|
{
|
||||||
int16_t reg = ZydisRegisterGetId(operand->reg);
|
int16_t reg = ZydisRegisterGetId(operand->reg);
|
||||||
if (reg == -1) return ZYDIS_STATUS_INVALID_PARAMETER;
|
if (reg == -1) return ZYDIS_STATUS_INVALID_PARAMETER;
|
||||||
ctx->info->opcode += reg & 0x0F;
|
ctx->info->opcode += reg & 0x07;
|
||||||
ctx->info->details.rex.R = (reg & 0x08) >> 3;
|
ctx->info->details.rex.B = (reg & 0x08) >> 3;
|
||||||
if (ctx->info->details.rex.B) ctx->info->attributes |= ZYDIS_ATTRIB_HAS_REX;
|
if (ctx->info->details.rex.B) ctx->info->attributes |= ZYDIS_ATTRIB_HAS_REX;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -811,6 +903,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 +941,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:
|
||||||
|
@ -885,9 +981,10 @@ static ZydisStatus ZydisFindMatchingDef(const ZydisInstructionInfo* info,
|
||||||
const ZydisEncoderTableOperand* curEncoderOp = &curEntry->operands[k];
|
const ZydisEncoderTableOperand* curEncoderOp = &curEntry->operands[k];
|
||||||
const ZydisOperandInfo* curReqOp = &info->operands[k];
|
const ZydisOperandInfo* curReqOp = &info->operands[k];
|
||||||
if (curReqOp->encoding != curEncoderOp->encoding) goto continueTopLevel;
|
if (curReqOp->encoding != curEncoderOp->encoding) goto continueTopLevel;
|
||||||
ZydisOperandType simpleType;
|
//ZydisOperandType simpleType;
|
||||||
ZYDIS_CHECK(ZydisSimplifyOperandType(curEncoderOp->type, &simpleType));
|
//ZYDIS_CHECK(ZydisSimplifyOperandType(curEncoderOp->type, &simpleType));
|
||||||
if (curReqOp->type != simpleType) goto continueTopLevel;
|
//if (curReqOp->type != simpleType) goto continueTopLevel;
|
||||||
|
if (curReqOp->temp != curEncoderOp->type) goto continueTopLevel;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Still here? We found our entry!
|
// Still here? We found our entry!
|
||||||
|
@ -963,12 +1060,22 @@ ZydisStatus ZydisEncoderEncodeInstruction(void* buffer, size_t* bufferLen,
|
||||||
info->details.evex.B = (pb & ZYDIS_PREFBIT_EVEX_B ) ? 1 : 0;
|
info->details.evex.B = (pb & ZYDIS_PREFBIT_EVEX_B ) ? 1 : 0;
|
||||||
info->details.evex.L2 = (pb & ZYDIS_PREFBIT_EVEX_L2) ? 1 : 0;
|
info->details.evex.L2 = (pb & ZYDIS_PREFBIT_EVEX_L2) ? 1 : 0;
|
||||||
info->details.vex.L = (pb & ZYDIS_PREFBIT_VEX_L ) ? 1 : 0;
|
info->details.vex.L = (pb & ZYDIS_PREFBIT_VEX_L ) ? 1 : 0;
|
||||||
info->details.rex.W = (pb & ZYDIS_PREFBIT_REX_W ) ? 1 : 0;
|
if (pb & ZYDIS_PREFBIT_REX_W)
|
||||||
|
{
|
||||||
|
info->details.rex.W = 1;
|
||||||
|
info->attributes |= ZYDIS_ATTRIB_HAS_REX;
|
||||||
|
}
|
||||||
ZYDIS_CHECK(ZydisPrepareMandatoryPrefixes(&ctx));
|
ZYDIS_CHECK(ZydisPrepareMandatoryPrefixes(&ctx));
|
||||||
|
|
||||||
// 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))
|
||||||
{
|
{
|
||||||
|
|
|
@ -95,6 +95,7 @@ int main(int argc, char** argv)
|
||||||
|
|
||||||
// TODO: Remove
|
// TODO: Remove
|
||||||
// DEBUG CODE START
|
// DEBUG CODE START
|
||||||
|
#if 0
|
||||||
for (size_t i = 0; i < info.length; ++i)
|
for (size_t i = 0; i < info.length; ++i)
|
||||||
{
|
{
|
||||||
printf("%02X ", *(readBuf + readOffs + i));
|
printf("%02X ", *(readBuf + readOffs + i));
|
||||||
|
@ -115,6 +116,7 @@ int main(int argc, char** argv)
|
||||||
putchar('\n');
|
putchar('\n');
|
||||||
ZYDIS_ASSERT(encBufferSize == info.length);
|
ZYDIS_ASSERT(encBufferSize == info.length);
|
||||||
ZYDIS_ASSERT(!memcmp(encBuffer, readBuf + readOffs, encBufferSize));
|
ZYDIS_ASSERT(!memcmp(encBuffer, readBuf + readOffs, encBufferSize));
|
||||||
|
#endif
|
||||||
// DEBUG CODE END
|
// DEBUG CODE END
|
||||||
|
|
||||||
readOffs += info.length;
|
readOffs += info.length;
|
||||||
|
|
Loading…
Reference in New Issue