Fixed decoding of operands with VSIB index-register

This commit is contained in:
flobernd 2017-06-26 03:12:18 +02:00
parent 99de0f3152
commit a1551af657
1 changed files with 27 additions and 33 deletions

View File

@ -1229,17 +1229,20 @@ static ZydisStatus ZydisDecodeOperandRegister(ZydisInstructionInfo* info,
* @param context A pointer to the @c ZydisDecoderContext instance. * @param context A pointer to the @c ZydisDecoderContext instance.
* @param info A pointer to the @c ZydisInstructionInfo struct. * @param info A pointer to the @c ZydisInstructionInfo struct.
* @param operand A pointer to the @c ZydisOperandInfo struct. * @param operand A pointer to the @c ZydisOperandInfo struct.
* @param vsibBaseRegister The base-register for instructions with VSIB addressing.
* *
* @return A zydis status code. * @return A zydis status code.
*/ */
static ZydisStatus ZydisDecodeOperandMemory(ZydisDecoderContext* context, static ZydisStatus ZydisDecodeOperandMemory(ZydisDecoderContext* context,
ZydisInstructionInfo* info, ZydisOperandInfo* operand) ZydisInstructionInfo* info, ZydisOperandInfo* operand, ZydisRegister vsibBaseRegister)
{ {
ZYDIS_ASSERT(context); ZYDIS_ASSERT(context);
ZYDIS_ASSERT(info); ZYDIS_ASSERT(info);
ZYDIS_ASSERT(operand); ZYDIS_ASSERT(operand);
ZYDIS_ASSERT(info->details.modrm.isDecoded); ZYDIS_ASSERT(info->details.modrm.isDecoded);
ZYDIS_ASSERT(info->details.modrm.mod != 3); ZYDIS_ASSERT(info->details.modrm.mod != 3);
ZYDIS_ASSERT(!vsibBaseRegister || ((info->details.modrm.rm == 4) &&
((info->addressWidth == 32) || (info->addressWidth == 64))));
operand->type = ZYDIS_OPERAND_TYPE_MEMORY; operand->type = ZYDIS_OPERAND_TYPE_MEMORY;
@ -1317,6 +1320,11 @@ static ZydisStatus ZydisDecodeOperandMemory(ZydisDecoderContext* context,
operand->mem.base = ZYDIS_REGISTER_EAX + sib_base; operand->mem.base = ZYDIS_REGISTER_EAX + sib_base;
operand->mem.index = ZYDIS_REGISTER_EAX + sib_index; operand->mem.index = ZYDIS_REGISTER_EAX + sib_index;
operand->mem.scale = (1 << info->details.sib.scale) & ~1; operand->mem.scale = (1 << info->details.sib.scale) & ~1;
if (vsibBaseRegister)
{
operand->mem.index = operand->mem.index - ZYDIS_REGISTER_EAX + vsibBaseRegister +
((context->cache.V2 == 1) ? 16 : 0);
} else
if (operand->mem.index == ZYDIS_REGISTER_ESP) if (operand->mem.index == ZYDIS_REGISTER_ESP)
{ {
operand->mem.index = ZYDIS_REGISTER_NONE; operand->mem.index = ZYDIS_REGISTER_NONE;
@ -1366,6 +1374,11 @@ static ZydisStatus ZydisDecodeOperandMemory(ZydisDecoderContext* context,
operand->mem.base = ZYDIS_REGISTER_RAX + sib_base; operand->mem.base = ZYDIS_REGISTER_RAX + sib_base;
operand->mem.index = ZYDIS_REGISTER_RAX + sib_index; operand->mem.index = ZYDIS_REGISTER_RAX + sib_index;
operand->mem.scale = (1 << info->details.sib.scale) & ~1; operand->mem.scale = (1 << info->details.sib.scale) & ~1;
if (vsibBaseRegister)
{
operand->mem.index = operand->mem.index - ZYDIS_REGISTER_RAX + vsibBaseRegister +
((context->cache.V2 == 1) ? 16 : 0);
} else
if (operand->mem.index == ZYDIS_REGISTER_RSP) if (operand->mem.index == ZYDIS_REGISTER_RSP)
{ {
operand->mem.index = ZYDIS_REGISTER_NONE; operand->mem.index = ZYDIS_REGISTER_NONE;
@ -1788,23 +1801,23 @@ static ZydisStatus ZydisDecodeOperands(ZydisDecoderContext* context, ZydisInstru
} }
// Memory operands // Memory operands
ZydisRegister vsibBaseRegister = ZYDIS_REGISTER_NONE;
switch (operand->type) switch (operand->type)
{ {
case ZYDIS_SEMANTIC_OPTYPE_MEM: case ZYDIS_SEMANTIC_OPTYPE_MEM:
ZYDIS_CHECK(ZydisDecodeOperandMemory(context, info, &info->operands[i])); ZYDIS_CHECK(
ZydisDecodeOperandMemory(context, info, &info->operands[i], ZYDIS_REGISTER_NONE));
break; break;
case ZYDIS_SEMANTIC_OPTYPE_MEM_VSIBX: case ZYDIS_SEMANTIC_OPTYPE_MEM_VSIBX:
vsibBaseRegister = ZYDIS_REGISTER_XMM0; ZYDIS_CHECK(
ZYDIS_CHECK(ZydisDecodeOperandMemory(context, info, &info->operands[i])); ZydisDecodeOperandMemory(context, info, &info->operands[i], ZYDIS_REGISTER_XMM0));
break; break;
case ZYDIS_SEMANTIC_OPTYPE_MEM_VSIBY: case ZYDIS_SEMANTIC_OPTYPE_MEM_VSIBY:
vsibBaseRegister = ZYDIS_REGISTER_YMM0; ZYDIS_CHECK(
ZYDIS_CHECK(ZydisDecodeOperandMemory(context, info, &info->operands[i])); ZydisDecodeOperandMemory(context, info, &info->operands[i], ZYDIS_REGISTER_YMM0));
break; break;
case ZYDIS_SEMANTIC_OPTYPE_MEM_VSIBZ: case ZYDIS_SEMANTIC_OPTYPE_MEM_VSIBZ:
vsibBaseRegister = ZYDIS_REGISTER_ZMM0; ZYDIS_CHECK(
ZYDIS_CHECK(ZydisDecodeOperandMemory(context, info, &info->operands[i])); ZydisDecodeOperandMemory(context, info, &info->operands[i], ZYDIS_REGISTER_ZMM0));
break; break;
case ZYDIS_SEMANTIC_OPTYPE_PTR: case ZYDIS_SEMANTIC_OPTYPE_PTR:
ZYDIS_ASSERT((info->details.imm[0].dataSize == 16) || ZYDIS_ASSERT((info->details.imm[0].dataSize == 16) ||
@ -1817,7 +1830,8 @@ static ZydisStatus ZydisDecodeOperands(ZydisDecoderContext* context, ZydisInstru
case ZYDIS_SEMANTIC_OPTYPE_AGEN: case ZYDIS_SEMANTIC_OPTYPE_AGEN:
info->operands[i].action = ZYDIS_OPERAND_ACTION_INVALID; info->operands[i].action = ZYDIS_OPERAND_ACTION_INVALID;
info->operands[i].mem.isAddressGenOnly = ZYDIS_TRUE; info->operands[i].mem.isAddressGenOnly = ZYDIS_TRUE;
ZYDIS_CHECK(ZydisDecodeOperandMemory(context, info, &info->operands[i])); ZYDIS_CHECK(
ZydisDecodeOperandMemory(context, info, &info->operands[i], ZYDIS_REGISTER_NONE));
break; break;
case ZYDIS_SEMANTIC_OPTYPE_MOFFS: case ZYDIS_SEMANTIC_OPTYPE_MOFFS:
ZYDIS_ASSERT(info->details.disp.dataSize); ZYDIS_ASSERT(info->details.disp.dataSize);
@ -1830,26 +1844,6 @@ static ZydisStatus ZydisDecodeOperands(ZydisDecoderContext* context, ZydisInstru
} }
if (info->operands[i].type) if (info->operands[i].type)
{ {
if (vsibBaseRegister)
{
ZYDIS_ASSERT(info->details.modrm.rm == 0x04);
switch (info->addressWidth)
{
case 32:
info->operands[i].mem.index =
info->operands[i].mem.index - ZYDIS_REGISTER_EAX + vsibBaseRegister +
((context->cache.V2 == 1) ? 16 : 0);
break;
case 64:
info->operands[i].mem.index =
info->operands[i].mem.index - ZYDIS_REGISTER_RAX + vsibBaseRegister +
((context->cache.V2 == 1) ? 16 : 0);
break;
default:
ZYDIS_UNREACHABLE;
}
}
if (info->attributes & ZYDIS_ATTRIB_HAS_SEGMENT_CS) if (info->attributes & ZYDIS_ATTRIB_HAS_SEGMENT_CS)
{ {
info->operands[i].mem.segment = ZYDIS_REGISTER_CS; info->operands[i].mem.segment = ZYDIS_REGISTER_CS;