Implemented segment prefix encoding, refactoring

- Moved memory operand encoding into dedicated function
This commit is contained in:
Joel Höner 2017-01-21 23:53:50 +01:00
parent 87e80346f4
commit b3c8d44bda
1 changed files with 149 additions and 102 deletions

View File

@ -415,6 +415,7 @@ static ZydisStatus ZydisPrepareRegOperand(ZydisEncoderContext* ctx,
ZydisRegister reg, char topBitLoc) ZydisRegister reg, char topBitLoc)
{ {
int16_t regID = ZydisRegisterGetId(reg); int16_t regID = ZydisRegisterGetId(reg);
//ZydisRegisterClass clazz = ZydisRegisterGetClass(reg);
if (regID == -1) return ZYDIS_STATUS_INVALID_PARAMETER; if (regID == -1) return ZYDIS_STATUS_INVALID_PARAMETER;
uint8_t lowerBits = (regID & 0x07) >> 0; uint8_t lowerBits = (regID & 0x07) >> 0;
@ -479,33 +480,22 @@ static ZydisStatus ZydisPrepareRegOperand(ZydisEncoderContext* ctx,
return ZYDIS_STATUS_SUCCESS; return ZYDIS_STATUS_SUCCESS;
} }
static ZydisStatus ZydisPrepareOperand(ZydisEncoderContext* ctx, static ZydisBool ZydisIsStackReg(ZydisRegister reg)
{
return reg == ZYDIS_REGISTER_SP ||
reg == ZYDIS_REGISTER_ESP ||
reg == ZYDIS_REGISTER_RSP ||
reg == ZYDIS_REGISTER_BP ||
reg == ZYDIS_REGISTER_EBP ||
reg == ZYDIS_REGISTER_RBP;
}
static ZydisStatus ZydisPrepareMemoryOperand(ZydisEncoderContext* ctx,
ZydisOperandInfo* operand, const ZydisEncoderTableOperand* tableEntry) ZydisOperandInfo* operand, const ZydisEncoderTableOperand* tableEntry)
{ {
switch (tableEntry->encoding)
{
case ZYDIS_OPERAND_ENCODING_NONE:
break; // Nothing to do.
case ZYDIS_OPERAND_ENCODING_REG:
{
ZYDIS_CHECK(ZydisPrepareRegOperand(ctx, operand->reg, 'R'));
} break;
case ZYDIS_OPERAND_ENCODING_RM:
case ZYDIS_OPERAND_ENCODING_RM_CD2:
case ZYDIS_OPERAND_ENCODING_RM_CD4:
case ZYDIS_OPERAND_ENCODING_RM_CD8:
case ZYDIS_OPERAND_ENCODING_RM_CD16:
case ZYDIS_OPERAND_ENCODING_RM_CD32:
case ZYDIS_OPERAND_ENCODING_RM_CD64:
{
// TODO: MMX registers
// TODO: rBP // TODO: rBP
// TODO: RIP relative addressing // TODO: RIP relative addressing
// TODO: Segment prefixes
// Memory operand?
if (operand->type == ZYDIS_OPERAND_TYPE_MEMORY)
{
// Absolute memory access? // Absolute memory access?
if (operand->mem.base == ZYDIS_REGISTER_NONE) if (operand->mem.base == ZYDIS_REGISTER_NONE)
{ {
@ -529,13 +519,43 @@ static ZydisStatus ZydisPrepareOperand(ZydisEncoderContext* ctx,
ctx->info->attributes |= ZYDIS_ATTRIB_HAS_SIB; ctx->info->attributes |= ZYDIS_ATTRIB_HAS_SIB;
} }
ctx->info->attributes |= ZYDIS_ATTRIB_HAS_MODRM; return ZYDIS_STATUS_SUCCESS;
break;
} }
// Base register? // Process base register.
ZYDIS_CHECK(ZydisPrepareRegOperand(ctx, operand->mem.base, 'B')); ZYDIS_CHECK(ZydisPrepareRegOperand(ctx, operand->mem.base, 'B'));
// Segment prefix required?
switch (operand->mem.segment)
{
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? // SIB byte required?
if (operand->mem.index || operand->mem.scale) if (operand->mem.index || operand->mem.scale)
{ {
@ -603,6 +623,33 @@ static ZydisStatus ZydisPrepareOperand(ZydisEncoderContext* ctx,
{ {
ctx->info->details.modrm.mod = 0x00 /* no disp */; ctx->info->details.modrm.mod = 0x00 /* no disp */;
} }
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:
{
ZYDIS_CHECK(ZydisPrepareRegOperand(ctx, operand->reg, 'R'));
} break;
case ZYDIS_OPERAND_ENCODING_RM:
case ZYDIS_OPERAND_ENCODING_RM_CD2:
case ZYDIS_OPERAND_ENCODING_RM_CD4:
case ZYDIS_OPERAND_ENCODING_RM_CD8:
case ZYDIS_OPERAND_ENCODING_RM_CD16:
case ZYDIS_OPERAND_ENCODING_RM_CD32:
case ZYDIS_OPERAND_ENCODING_RM_CD64:
{
// Memory operand?
if (operand->type == ZYDIS_OPERAND_TYPE_MEMORY)
{
ZYDIS_CHECK(ZydisPrepareMemoryOperand(ctx, operand, tableEntry));
} }
// Nope, register. // Nope, register.
else if (operand->type == ZYDIS_OPERAND_TYPE_REGISTER) else if (operand->type == ZYDIS_OPERAND_TYPE_REGISTER)