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, 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); int16_t regID = ZydisRegisterGetId(reg);
if (regID == -1) return ZYDIS_STATUS_INVALID_PARAMETER; if (regID == -1) return ZYDIS_STATUS_INVALID_PARAMETER;
*regRM = regID & 0x07; uint8_t lowerBits = (regID & 0x07) >> 0;
*rexRB = (regID & 0x08) >> 3; uint8_t topBit = (regID & 0x08) >> 3;
ctx->info->attributes |= ZYDIS_ATTRIB_HAS_MODRM;
if (*rexRB) ctx->info->attributes |= ZYDIS_ATTRIB_HAS_REX; 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; return ZYDIS_STATUS_SUCCESS;
} }
@ -412,7 +464,7 @@ static ZydisStatus ZydisPrepareOperand(ZydisEncoderContext* ctx,
break; // Nothing to do. break; // Nothing to do.
case ZYDIS_OPERAND_ENCODING_REG: case ZYDIS_OPERAND_ENCODING_REG:
{ {
ZYDIS_CHECK(ZydisPrepareRegOperand(ctx, operand->reg, ZYDIS_FALSE)); ZYDIS_CHECK(ZydisPrepareRegOperand(ctx, operand->reg, 'R'));
} break; } break;
case ZYDIS_OPERAND_ENCODING_RM: case ZYDIS_OPERAND_ENCODING_RM:
case ZYDIS_OPERAND_ENCODING_RM_CD2: case ZYDIS_OPERAND_ENCODING_RM_CD2:
@ -428,7 +480,7 @@ static ZydisStatus ZydisPrepareOperand(ZydisEncoderContext* ctx,
// Has base register? // Has base register?
if (operand->mem.base != ZYDIS_REGISTER_NONE) if (operand->mem.base != ZYDIS_REGISTER_NONE)
{ {
ZYDIS_CHECK(ZydisPrepareRegOperand(ctx, operand->reg, ZYDIS_TRUE)); ZYDIS_CHECK(ZydisPrepareRegOperand(ctx, operand->mem.base, 'B'));
} }
else else
{ {
@ -448,8 +500,12 @@ static ZydisStatus ZydisPrepareOperand(ZydisEncoderContext* ctx,
default: return ZYDIS_STATUS_IMPOSSIBLE_INSTRUCTION; // TODO 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; ctx->info->attributes |= ZYDIS_ATTRIB_HAS_SIB;
} }
@ -504,7 +560,7 @@ static ZydisStatus ZydisPrepareOperand(ZydisEncoderContext* ctx,
// Nope, register. // Nope, register.
else if (operand->type == ZYDIS_OPERAND_TYPE_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 */; ctx->info->details.modrm.mod = 0x03 /* reg */;
} }
@ -661,7 +717,7 @@ ZydisStatus ZydisEncoderEncodeInstruction(void* buffer, size_t* bufferLen,
if (info->attributes & ZYDIS_ATTRIB_HAS_MODRM) ZYDIS_CHECK(ZydisEmitModRM(&ctx)); if (info->attributes & ZYDIS_ATTRIB_HAS_MODRM) ZYDIS_CHECK(ZydisEmitModRM(&ctx));
if (info->attributes & ZYDIS_ATTRIB_HAS_SIB ) ZYDIS_CHECK(ZydisEmitSIB (&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.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[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])); if (ctx.immBitSizes[1]) ZYDIS_CHECK(ZydisEmitImm(&ctx, ctx.imms[1], ctx.immBitSizes[1]));