Completed SIB encoding

This commit is contained in:
Joel Höner 2017-01-20 00:54:48 +01:00
parent c0f53a3a69
commit 46077709f8
1 changed files with 71 additions and 15 deletions

View File

@ -385,20 +385,72 @@ static ZydisStatus ZydisSimplifyOperandType(ZydisSemanticOperandType semType,
}
static ZydisStatus ZydisPrepareRegOperand(ZydisEncoderContext* ctx,
ZydisRegister reg, uint8_t useRM)
ZydisRegister reg, char topBitLoc)
{
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;
uint8_t lowerBits = (regID & 0x07) >> 0;
uint8_t topBit = (regID & 0x08) >> 3;
switch (topBitLoc)
{
case 'B': ctx->info->details.modrm.rm = lowerBits;
case 'R': ctx->info->details.modrm.reg = lowerBits;
case 'X': ctx->info->details.sib.index = lowerBits;
default: ZYDIS_UNREACHABLE;
}
uint8_t* topBitDst = NULL;
switch (ctx->info->encoding)
{
case ZYDIS_INSTRUCTION_ENCODING_DEFAULT:
case ZYDIS_INSTRUCTION_ENCODING_3DNOW:
switch (topBitLoc)
{
case 'B': topBitDst = &ctx->info->details.rex.B; break;
case 'R': topBitDst = &ctx->info->details.rex.R; break;
case 'X': topBitDst = &ctx->info->details.rex.X; break;
default: ZYDIS_UNREACHABLE;
}
if (topBit) ctx->info->attributes |= ZYDIS_ATTRIB_HAS_REX;
break;
case ZYDIS_INSTRUCTION_ENCODING_VEX:
switch (topBitLoc)
{
case 'B': topBitDst = &ctx->info->details.vex.B; break;
case 'R': topBitDst = &ctx->info->details.vex.R; break;
case 'X': topBitDst = &ctx->info->details.vex.X; break;
default: ZYDIS_UNREACHABLE;
}
topBit = ~topBit;
break;
case ZYDIS_INSTRUCTION_ENCODING_XOP:
switch (topBitLoc)
{
case 'B': topBitDst = &ctx->info->details.xop.B; break;
case 'R': topBitDst = &ctx->info->details.xop.R; break;
case 'X': topBitDst = &ctx->info->details.xop.X; break;
default: ZYDIS_UNREACHABLE;
}
topBit = ~topBit;
break;
case ZYDIS_INSTRUCTION_ENCODING_EVEX:
switch (topBitLoc)
{
case 'B': topBitDst = &ctx->info->details.evex.B; break;
case 'R': topBitDst = &ctx->info->details.evex.R; break;
case 'X': topBitDst = &ctx->info->details.evex.X; break;
default: ZYDIS_UNREACHABLE;
}
topBit = ~topBit;
break;
default:
return ZYDIS_STATUS_IMPOSSIBLE_INSTRUCTION; // TODO
}
*topBitDst = topBit;
return ZYDIS_STATUS_SUCCESS;
}
@ -412,7 +464,7 @@ static ZydisStatus ZydisPrepareOperand(ZydisEncoderContext* ctx,
break; // Nothing to do.
case ZYDIS_OPERAND_ENCODING_REG:
{
ZYDIS_CHECK(ZydisPrepareRegOperand(ctx, operand->reg, ZYDIS_FALSE));
ZYDIS_CHECK(ZydisPrepareRegOperand(ctx, operand->reg, 'R'));
} break;
case ZYDIS_OPERAND_ENCODING_RM:
case ZYDIS_OPERAND_ENCODING_RM_CD2:
@ -428,7 +480,7 @@ static ZydisStatus ZydisPrepareOperand(ZydisEncoderContext* ctx,
// Has base register?
if (operand->mem.base != ZYDIS_REGISTER_NONE)
{
ZYDIS_CHECK(ZydisPrepareRegOperand(ctx, operand->reg, ZYDIS_TRUE));
ZYDIS_CHECK(ZydisPrepareRegOperand(ctx, operand->mem.base, 'B'));
}
else
{
@ -448,8 +500,12 @@ static ZydisStatus ZydisPrepareOperand(ZydisEncoderContext* ctx,
default: return ZYDIS_STATUS_IMPOSSIBLE_INSTRUCTION; // TODO
}
// TODO: base, index
// Base & index register.
ZYDIS_CHECK(ZydisPrepareRegOperand(ctx, operand->mem.base, 'B'));
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->attributes |= ZYDIS_ATTRIB_HAS_SIB;
}
@ -504,7 +560,7 @@ static ZydisStatus ZydisPrepareOperand(ZydisEncoderContext* ctx,
// Nope, register.
else if (operand->type == ZYDIS_OPERAND_TYPE_REGISTER)
{
ZYDIS_CHECK(ZydisPrepareRegOperand(ctx, operand->reg, ZYDIS_TRUE));
ZYDIS_CHECK(ZydisPrepareRegOperand(ctx, operand->reg, 'B'));
ctx->info->details.modrm.mod = 0x03 /* reg */;
}