From 44792f233812e52d50f0549b15e3eef292185c3b Mon Sep 17 00:00:00 2001 From: flobernd Date: Fri, 16 Jun 2017 16:27:37 +0200 Subject: [PATCH] Added semantic decoding of implicit memory operands --- include/Zydis/Internal/InstructionTable.h | 6 +- src/Decoder.c | 75 ++++++++++++++++++++++- src/Formatter.c | 14 ++--- 3 files changed, 83 insertions(+), 12 deletions(-) diff --git a/include/Zydis/Internal/InstructionTable.h b/include/Zydis/Internal/InstructionTable.h index c9d3c72..b32dbb5 100644 --- a/include/Zydis/Internal/InstructionTable.h +++ b/include/Zydis/Internal/InstructionTable.h @@ -248,10 +248,10 @@ enum ZydisImplicitRegisterType enum ZydisImplicitMemBase { - ZYDIS_IMPLMEM_BASE_ASI, - ZYDIS_IMPLMEM_BASE_ADI, + ZYDIS_IMPLMEM_BASE_ABX, ZYDIS_IMPLMEM_BASE_ABP, - ZYDIS_IMPLMEM_BASE_ABX + ZYDIS_IMPLMEM_BASE_ASI, + ZYDIS_IMPLMEM_BASE_ADI }; /* ---------------------------------------------------------------------------------------------- */ diff --git a/src/Decoder.c b/src/Decoder.c index ea04ee1..bf701f0 100644 --- a/src/Decoder.c +++ b/src/Decoder.c @@ -71,6 +71,12 @@ typedef struct ZydisDecoderContext_ * 0 = 16 bit, 1 = 32 bit, 2 = 64 bit */ uint8_t eoszIndex; + /** + * @brief Contains the effective address-size index. + * + * 0 = 16 bit, 1 = 32 bit, 2 = 64 bit + */ + uint8_t easzIndex; /** * @brief Contains some cached REX/XOP/VEX/EVEX/MVEX values to provide uniform access. */ @@ -1249,6 +1255,40 @@ static void ZydisDecodeOperandImplicitMemory(ZydisDecoderContext* context, ZYDIS_ASSERT(operand); ZYDIS_ASSERT(definition); + static const ZydisRegisterClass lookup[3] = + { + ZYDIS_REGCLASS_GPR16, + ZYDIS_REGCLASS_GPR32, + ZYDIS_REGCLASS_GPR64 + }; + + operand->type = ZYDIS_OPERAND_TYPE_MEMORY; + + // TODO: Base action + switch (definition->op.mem.base) + { + case ZYDIS_IMPLMEM_BASE_ABX: + operand->mem.base = ZydisRegisterEncode(lookup[context->easzIndex], 3); + break; + case ZYDIS_IMPLMEM_BASE_ABP: + operand->mem.base = ZydisRegisterEncode(lookup[context->easzIndex], 5); + break; + case ZYDIS_IMPLMEM_BASE_ASI: + operand->mem.base = ZydisRegisterEncode(lookup[context->easzIndex], 6); + break; + case ZYDIS_IMPLMEM_BASE_ADI: + operand->mem.base = ZydisRegisterEncode(lookup[context->easzIndex], 7); + break; + default: + ZYDIS_UNREACHABLE; + } + + if (definition->op.mem.seg) + { + operand->mem.segment = + ZydisRegisterEncode(ZYDIS_REGCLASS_SEGMENT, definition->op.mem.seg - 1); + ZYDIS_ASSERT(operand->mem.segment); + } } /** @@ -1267,8 +1307,6 @@ static ZydisStatus ZydisDecodeOperands(ZydisDecoderContext* context, ZydisInstru ZYDIS_ASSERT(info); ZYDIS_ASSERT(definition); - (void)context; - uint8_t immId = 0; const ZydisOperandDefinition* operand; info->operandCount = ZydisGetOperandDefinitions(definition, &operand); @@ -1290,6 +1328,16 @@ static ZydisStatus ZydisDecodeOperands(ZydisDecoderContext* context, ZydisInstru default: break; } + if (info->operands[i].type) + { + if (info->operands[i].type == ZYDIS_OPERAND_TYPE_MEMORY) + { + //ZYDIS_ASSERT(operand->size[context->eoszIndex]); + info->operands[i].size = operand->size[context->eoszIndex] * 8; + } + ++operand; + continue; + } // Register operands ZydisRegisterClass registerClass = ZYDIS_REGCLASS_INVALID; @@ -1457,6 +1505,9 @@ static ZydisStatus ZydisDecodeOperands(ZydisDecoderContext* context, ZydisInstru // TODO: Always override size for register operands? info->operands[i].size = operand->size[context->eoszIndex] * 8; } + + ++operand; + continue; } // Memory operands @@ -1562,6 +1613,9 @@ static ZydisStatus ZydisDecodeOperands(ZydisDecoderContext* context, ZydisInstru { info->operands[i].mem.disp.value.sqword *= info->avx.compressedDisp8Scale; } + + ++operand; + continue; } // Immediate operands @@ -1572,6 +1626,7 @@ static ZydisStatus ZydisDecodeOperands(ZydisDecoderContext* context, ZydisInstru case ZYDIS_SEMANTIC_OPTYPE_IMM: ZYDIS_ASSERT((immId == 0) || (immId == 1)); info->operands[i].type = ZYDIS_OPERAND_TYPE_IMMEDIATE; + //ZYDIS_ASSERT(operand->size[context->eoszIndex]); info->operands[i].size = operand->size[context->eoszIndex] * 8; info->operands[i].imm.value.uqword = info->details.imm[immId].value.uqword; info->operands[i].imm.isSigned = info->details.imm[immId].isSigned; @@ -1581,6 +1636,7 @@ static ZydisStatus ZydisDecodeOperands(ZydisDecoderContext* context, ZydisInstru default: break; } + ZYDIS_ASSERT(info->operands[i].type == ZYDIS_OPERAND_TYPE_IMMEDIATE); ++operand; } @@ -1737,6 +1793,21 @@ static void ZydisSetEffectiveAddressWidth(ZydisDecoderContext* context, ZydisIns default: ZYDIS_UNREACHABLE; } + + switch (info->addressWidth) + { + case 16: + context->easzIndex = 0; + break; + case 32: + context->easzIndex = 1; + break; + case 64: + context->easzIndex = 2; + break; + default: + ZYDIS_UNREACHABLE; + } } /** diff --git a/src/Formatter.c b/src/Formatter.c index b78db4c..946ce96 100644 --- a/src/Formatter.c +++ b/src/Formatter.c @@ -642,12 +642,12 @@ static ZydisStatus ZydisFormatterPrintDecoratorIntel(ZydisInstructionFormatter* } ZYDIS_CHECK(ZydisStringBufferAppendFormat(buffer, bufEnd - *buffer, ZYDIS_APPENDMODE, " {%s}", reg)); - } - if (info->avx.maskMode == ZYDIS_MASKMODE_ZERO) - { - ZYDIS_CHECK(ZydisStringBufferAppend(buffer, bufEnd - *buffer, - ZYDIS_STRBUF_APPEND_MODE_DEFAULT, " {z}")); - } + if (info->avx.maskMode == ZYDIS_MASKMODE_ZERO) + { + ZYDIS_CHECK(ZydisStringBufferAppend(buffer, bufEnd - *buffer, + ZYDIS_STRBUF_APPEND_MODE_DEFAULT, " {z}")); + } + } } else { if (info->operands[operand->id].type == ZYDIS_OPERAND_TYPE_MEMORY) @@ -782,7 +782,7 @@ static ZydisStatus ZydisFormatterFormatInstrIntel(ZydisInstructionFormatter* for if (bufPreOperand == *buffer) { - // Omit whole operands, if the buffer did not change during the formatting-callback + // Omit whole operand, if the buffer did not change during the formatting-callback *buffer = bufRestore; *buffer[0] = 0; } else