From 412f0659651060fadeb9c1b2cfbe0a91f216b733 Mon Sep 17 00:00:00 2001 From: "BITDEFENDER\\vlutas" Date: Tue, 19 Oct 2021 17:33:15 +0300 Subject: [PATCH] Moved the formatting function in a dedicated source file. Added support for SIDT and RDTSC in bdshemu. --- CMakeLists.txt | 1 + bddisasm/bddisasm.c | 1047 ---------------------------- bddisasm/bddisasm.vcxproj | 1 + bddisasm/bddisasm.vcxproj.filters | 3 + bddisasm/bdformat.c | 1050 +++++++++++++++++++++++++++++ bddisasm/include/nd_crt.h | 7 + bdshemu/bdshemu.c | 36 +- bdshemu_test/bdshemu_test.zip | Bin 80935 -> 74758 bytes inc/version.h | 2 +- 9 files changed, 1098 insertions(+), 1049 deletions(-) create mode 100644 bddisasm/bdformat.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 2c7da76..f6bb614 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -96,6 +96,7 @@ add_library( bddisasm STATIC bddisasm/crt.c bddisasm/bddisasm.c + bddisasm/bdformat.c # Add the headers so they will show up in IDEs. bddisasm/include/instructions.h bddisasm/include/mnemonics.h diff --git a/bddisasm/bddisasm.c b/bddisasm/bddisasm.c index d550dd3..22bc236 100644 --- a/bddisasm/bddisasm.c +++ b/bddisasm/bddisasm.c @@ -8,133 +8,10 @@ // The table definitions. #include "include/tabledefs.h" -// Handy macros. -#define RET_EQ(x, y, z) if ((x) == (y)) { return (z); } -#define RET_GE(x, y, z) if ((x) >= (y)) { return (z); } -#define RET_GT(x, y, z) if ((x) > (y)) { return (z); } - #ifndef UNREFERENCED_PARAMETER #define UNREFERENCED_PARAMETER(P) ((void)(P)) #endif -#ifndef BDDISASM_NO_FORMAT - -static const char *gReg8Bit[] = -{ - "al", "cl", "dl", "bl", "ah", "ch", "dh", "bh", -}; - -static const char *gReg8Bit64[] = -{ - "al", "cl", "dl", "bl", "spl", "bpl", "sil", "dil", - "r8b", "r9b", "r10b", "r11b", "r12b", "r13b", "r14b", "r15b", -}; - -static const char *gReg16Bit[] = -{ - "ax", "cx", "dx", "bx", "sp", "bp", "si", "di", - "r8w", "r9w", "r10w", "r11w", "r12w", "r13w", "r14w", "r15w", -}; - -static const char *gReg32Bit[] = -{ - "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi", - "r8d", "r9d", "r10d", "r11d", "r12d", "r13d", "r14d", "r15d", -}; - -static const char *gReg64Bit[] = -{ - "rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi", - "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15" -}; - -static const char *gRegFpu[] = -{ - "st0", "st1", "st2", "st3", "st4", "st5", "st6", "st7", -}; - -static const char *gRegMmx[] = -{ - "mm0", "mm1", "mm2", "mm3", "mm4", "mm5", "mm6", "mm7", -}; - -static const char *gRegControl[] = -{ - "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", - "cr8", "cr9", "cr10", "cr11", "cr12", "cr13", "cr14", "cr15", -}; - -static const char *gRegDebug[] = -{ - "dr0", "dr1", "dr2", "dr3", "dr4", "dr5", "dr6", "dr7", - "dr8", "dr9", "dr10", "dr11", "dr12", "dr13", "dr14", "dr15", -}; - -static const char *gRegTest[] = -{ - "tr0", "tr1", "tr2", "tr3", "tr4", "tr5", "tr6", "tr7", - "tr8", "tr9", "tr10", "tr11", "tr12", "tr13", "tr14", "tr15", -}; - -static const char *gRegXmm[] = -{ - "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", - "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", - "xmm16", "xmm17", "xmm18", "xmm19", "xmm20", "xmm21", "xmm22", "xmm23", - "xmm24", "xmm25", "xmm26", "xmm27", "xmm28", "xmm29", "xmm30", "xmm31", -}; - -static const char *gRegYmm[] = -{ - "ymm0", "ymm1", "ymm2", "ymm3", "ymm4", "ymm5", "ymm6", "ymm7", - "ymm8", "ymm9", "ymm10", "ymm11", "ymm12", "ymm13", "ymm14", "ymm15", - "ymm16", "ymm17", "ymm18", "ymm19", "ymm20", "ymm21", "ymm22", "ymm23", - "ymm24", "ymm25", "ymm26", "ymm27", "ymm28", "ymm29", "ymm30", "ymm31" -}; - -static const char *gRegZmm[] = -{ - "zmm0", "zmm1", "zmm2", "zmm3", "zmm4", "zmm5", "zmm6", "zmm7", - "zmm8", "zmm9", "zmm10", "zmm11", "zmm12", "zmm13", "zmm14", "zmm15", - "zmm16", "zmm17", "zmm18", "zmm19", "zmm20", "zmm21", "zmm22", "zmm23", - "zmm24", "zmm25", "zmm26", "zmm27", "zmm28", "zmm29", "zmm30", "zmm31", -}; - -static const char *gRegSeg[] = -{ - "es", "cs", "ss", "ds", "fs", "gs", "segr6", "segr7", -}; - -static const char *gRegBound[] = -{ - "bnd0", "bnd1", "bnd2", "bnd3", -}; - -static const char *gRegMask[] = -{ - "k0", "k1", "k2", "k3", "k4", "k5", "k6", "k7", -}; - -static const char *gRegTile[] = -{ - "tmm0", "tmm1", "tmm2", "tmm3", "tmm4", "tmm5", "tmm6", "tmm7", -}; - -static const char *gConditionCodes[] = -{ - "EQ", "LT", "LE", "UNORD", "NEQ", "NLT", "NLE", "ORD", - "EQ_UQ", "NGE", "NGT", "false", "NEQ_OQ", "GE", "GT", "TRUE", - "EQ_OS", "LT_OQ", "LE_OQ", "UNORD_S", "NEQ_US", "NLT_UQ", "NLE_UQ", "ORD_S", - "EQ_US", "NGE_UQ", "NGT_UQ", "FALSE_OS", "NEQ_OS", "GE_OQ", "GT_OQ", "TRUE_US", -}; - -static const char *gEmbeddedRounding[] = -{ - "rn", "rd", "ru", "rz", -}; - -#endif // !BDDISASM_NO_FORMAT - static const uint16_t gOperandMap[] = { @@ -329,52 +206,6 @@ NdGetVersion( } -// -// NdSprintf -// -#ifndef BDDISASM_NO_FORMAT -static NDSTATUS -NdSprintf( - char *Destination, - size_t DestinationSize, - const char *Formatstring, - ... - ) -// -// Wrapper on vsnprintf. -// -{ - int res; - va_list args; - - if (NULL == Destination) - { - return ND_STATUS_INVALID_PARAMETER; - } - - if (NULL == Formatstring) - { - return ND_STATUS_INVALID_PARAMETER; - } - - nd_memzero(Destination, DestinationSize); - - va_start(args, Formatstring); - - // _vsnprintf is used instead of the more secure _vsnprintf_s because the mini-Petru supports just - // the unsecured version, and we depend on it. - res = nd_vsnprintf_s(Destination, DestinationSize, DestinationSize - 1, Formatstring, args); - - va_end(args); - - if ((res < 0) || ((size_t)res >= DestinationSize - 1)) - { - return ND_STATUS_BUFFER_OVERFLOW; - } - - return ND_STATUS_SUCCESS; -} -#endif // !BDDISASM_NO_FORMAT // @@ -4314,884 +4145,6 @@ NdDecode( } -// -// NdToText -// -#ifndef BDDISASM_NO_FORMAT -NDSTATUS -NdToText( - const INSTRUX *Instrux, - uint64_t Rip, - uint32_t BufferSize, - char *Buffer - ) -{ - NDSTATUS status; - char *res, temp[64]; - uint32_t opIndex, opsStored; - const ND_OPERAND *pOp; - bool alignmentStored; - - // pre-init - status = ND_STATUS_SUCCESS; - res = NULL; - opIndex = 0; - opsStored = 0; - pOp = NULL; - alignmentStored = false; - - // Validate args. - if (NULL == Instrux) - { - return ND_STATUS_INVALID_PARAMETER; - } - - if (NULL == Buffer) - { - return ND_STATUS_INVALID_PARAMETER; - } - - if (BufferSize < ND_MIN_BUF_SIZE) - { - return ND_STATUS_INVALID_PARAMETER; - } - - // init the text. - nd_memzero(Buffer, BufferSize); - nd_memzero(temp, sizeof(temp)); - - // First, store the prefixes. - if (Instrux->Rep != 0) - { - // Check for REPZ/REPNZ support, and store prefixes. - if (ND_REPC_SUPPORT(Instrux)) - { - if (Instrux->Rep == ND_PREFIX_G1_REPE_REPZ) - { - res = nd_strcat_s(Buffer, BufferSize, "REPZ "); - RET_EQ(res, NULL, ND_STATUS_BUFFER_OVERFLOW); - } - else if (Instrux->Rep == ND_PREFIX_G1_REPNE_REPNZ) - { - res = nd_strcat_s(Buffer, BufferSize, "REPNZ "); - RET_EQ(res, NULL, ND_STATUS_BUFFER_OVERFLOW); - } - } - - // Check for REP support and store prefixes. - if (ND_REP_SUPPORT(Instrux)) - { - if (Instrux->Rep == ND_PREFIX_G1_REPE_REPZ) - { - res = nd_strcat_s(Buffer, BufferSize, "REP "); - RET_EQ(res, NULL, ND_STATUS_BUFFER_OVERFLOW); - } - else if (Instrux->Rep == ND_PREFIX_G1_REPNE_REPNZ) - { - res = nd_strcat_s(Buffer, BufferSize, "REPNZ "); - RET_EQ(res, NULL, ND_STATUS_BUFFER_OVERFLOW); - } - } - - if (Instrux->IsXreleaseEnabled) - { - res = nd_strcat_s(Buffer, BufferSize, "XRELEASE "); - RET_EQ(res, NULL, ND_STATUS_BUFFER_OVERFLOW); - } - else if (Instrux->IsXacquireEnabled) - { - res = nd_strcat_s(Buffer, BufferSize, "XACQUIRE "); - RET_EQ(res, NULL, ND_STATUS_BUFFER_OVERFLOW); - } - } - - if (Instrux->HasLock) - { - if (ND_LOCK_SUPPORT(Instrux)) - { - res = nd_strcat_s(Buffer, BufferSize, "LOCK "); - RET_EQ(res, NULL, ND_STATUS_BUFFER_OVERFLOW); - } - } - - if (Instrux->Rep == ND_PREFIX_G1_BND) - { - if (ND_BND_SUPPORT(Instrux)) - { - res = nd_strcat_s(Buffer, BufferSize, "BND "); - RET_EQ(res, NULL, ND_STATUS_BUFFER_OVERFLOW); - } - } - - if (Instrux->HasSeg && ND_BHINT_SUPPORT(Instrux)) - { - switch (Instrux->Seg) - { - case ND_PREFIX_G2_BR_TAKEN: - res = nd_strcat_s(Buffer, BufferSize, "BHT "); - RET_EQ(res, NULL, ND_STATUS_BUFFER_OVERFLOW); - break; - - case ND_PREFIX_G2_BR_NOT_TAKEN: - res = nd_strcat_s(Buffer, BufferSize, "BHNT "); - RET_EQ(res, NULL, ND_STATUS_BUFFER_OVERFLOW); - break; - - case ND_PREFIX_G2_BR_ALT: - res = nd_strcat_s(Buffer, BufferSize, "BHALT "); - RET_EQ(res, NULL, ND_STATUS_BUFFER_OVERFLOW); - break; - - default: - break; - } - } - - if (Instrux->HasSeg && ND_DNT_SUPPORT(Instrux)) - { - if (!Instrux->IsCetTracked) - { - res = nd_strcat_s(Buffer, BufferSize, "DNT "); - RET_EQ(res, NULL, ND_STATUS_BUFFER_OVERFLOW); - } - } - - // Store the mnemonic. - res = nd_strcat_s(Buffer, BufferSize, Instrux->Mnemonic); - RET_EQ(res, NULL, ND_STATUS_BUFFER_OVERFLOW); - - // Store condition code, if any. - if (ND_HAS_SSE_CONDITION(Instrux)) - { - res = nd_strcat_s(Buffer, BufferSize, gConditionCodes[Instrux->SseCondition]); - RET_EQ(res, NULL, ND_STATUS_BUFFER_OVERFLOW); - } - - // If there are no explicit operands, we can leave. - if (0 == Instrux->ExpOperandsCount) - { - return ND_STATUS_SUCCESS; - } - - // Now the operands. - for (opIndex = 0; opIndex < Instrux->OperandsCount; opIndex++) - { - status = ND_STATUS_SUCCESS; - - pOp = &Instrux->Operands[opIndex]; - - if (pOp->Type == ND_OP_NOT_PRESENT) - { - break; - } - - if (pOp->Flags.IsDefault) - { - continue; - } - - // If this is a mask operand that has been used as masking for a previous operand, than we - // can safely skip it. We check this by seeing where is the operand encoded. If it's encoded - // in the evex.aaa field, than it is a conventional mask. - if ((pOp->Encoding == ND_OPE_A) && (pOp->Type == ND_OP_REG) && - (pOp->Info.Register.Type == ND_REG_MSK) && (opIndex > 0)) - { - continue; - } - - // Store alignment. - if (!alignmentStored) - { - size_t idx = 0; - - while ((idx < BufferSize) && (Buffer[idx])) - { - idx++; - } - - while ((idx < 9) && (idx + 1 < BufferSize)) - { - Buffer[idx++] = 0x20; - } - - if (idx + 1 < BufferSize) - { - Buffer[idx++] = 0x20; - } - - Buffer[idx] = 0; - - alignmentStored = true; - } - - // Store the comma, if this isn't the first operand. - if (opsStored > 0) - { - res = nd_strcat_s(Buffer, BufferSize, ", "); - RET_EQ(res, NULL, ND_STATUS_BUFFER_OVERFLOW); - } - - opsStored++; - - switch (pOp->Type) - { - case ND_OP_REG: - switch (pOp->Info.Register.Type) - { - case ND_REG_GPR: - { - if (pOp->Info.Register.Reg >= ND_MAX_GPR_REGS) - { - return ND_STATUS_INVALID_INSTRUX; - } - - // General purpose register. - switch (pOp->Info.Register.Size) - { - case ND_SIZE_8BIT: - // 8 bit register. - if ((Instrux->EncMode != ND_ENCM_LEGACY) || Instrux->HasRex) - { - res = nd_strcat_s(Buffer, BufferSize, gReg8Bit64[pOp->Info.Register.Reg]); - RET_EQ(res, NULL, ND_STATUS_BUFFER_OVERFLOW); - } - else - { - res = nd_strcat_s(Buffer, BufferSize, gReg8Bit[pOp->Info.Register.Reg]); - RET_EQ(res, NULL, ND_STATUS_BUFFER_OVERFLOW); - } - break; - - case ND_SIZE_16BIT: - // 16 bit register. - res = nd_strcat_s(Buffer, BufferSize, gReg16Bit[pOp->Info.Register.Reg]); - RET_EQ(res, NULL, ND_STATUS_BUFFER_OVERFLOW); - break; - - case ND_SIZE_32BIT: - // 32 bit register. - res = nd_strcat_s(Buffer, BufferSize, gReg32Bit[pOp->Info.Register.Reg]); - RET_EQ(res, NULL, ND_STATUS_BUFFER_OVERFLOW); - break; - - case ND_SIZE_64BIT: - // 64 bit register. - res = nd_strcat_s(Buffer, BufferSize, gReg64Bit[pOp->Info.Register.Reg]); - RET_EQ(res, NULL, ND_STATUS_BUFFER_OVERFLOW); - break; - - default: - return ND_STATUS_INVALID_INSTRUX; - } - } - break; - - case ND_REG_SEG: - { - if (pOp->Info.Register.Reg >= ND_MAX_SEG_REGS) - { - return ND_STATUS_INVALID_INSTRUX; - } - - res = nd_strcat_s(Buffer, BufferSize, gRegSeg[pOp->Info.Register.Reg]); - RET_EQ(res, NULL, ND_STATUS_BUFFER_OVERFLOW); - } - break; - - case ND_REG_FPU: - { - if (pOp->Info.Register.Reg >= ND_MAX_FPU_REGS) - { - return ND_STATUS_INVALID_INSTRUX; - } - - res = nd_strcat_s(Buffer, BufferSize, gRegFpu[pOp->Info.Register.Reg]); - RET_EQ(res, NULL, ND_STATUS_BUFFER_OVERFLOW); - } - break; - - case ND_REG_MMX: - { - if (pOp->Info.Register.Reg >= ND_MAX_MMX_REGS) - { - return ND_STATUS_INVALID_INSTRUX; - } - - res = nd_strcat_s(Buffer, BufferSize, gRegMmx[pOp->Info.Register.Reg]); - RET_EQ(res, NULL, ND_STATUS_BUFFER_OVERFLOW); - } - break; - - case ND_REG_SSE: - { - if (pOp->Info.Register.Reg >= ND_MAX_SSE_REGS) - { - return ND_STATUS_INVALID_INSTRUX; - } - - switch (pOp->Info.Register.Size) - { - case ND_SIZE_128BIT: - res = nd_strcat_s(Buffer, BufferSize, gRegXmm[pOp->Info.Register.Reg]); - RET_EQ(res, NULL, ND_STATUS_BUFFER_OVERFLOW); - break; - case ND_SIZE_256BIT: - res = nd_strcat_s(Buffer, BufferSize, gRegYmm[pOp->Info.Register.Reg]); - RET_EQ(res, NULL, ND_STATUS_BUFFER_OVERFLOW); - break; - case ND_SIZE_512BIT: - res = nd_strcat_s(Buffer, BufferSize, gRegZmm[pOp->Info.Register.Reg]); - RET_EQ(res, NULL, ND_STATUS_BUFFER_OVERFLOW); - break; - default: - return ND_STATUS_INVALID_INSTRUX; - } - } - break; - - case ND_REG_CR: - { - if (pOp->Info.Register.Reg >= ND_MAX_CR_REGS) - { - return ND_STATUS_INVALID_INSTRUX; - } - - res = nd_strcat_s(Buffer, BufferSize, gRegControl[pOp->Info.Register.Reg]); - RET_EQ(res, NULL, ND_STATUS_BUFFER_OVERFLOW); - } - break; - - case ND_REG_DR: - { - if (pOp->Info.Register.Reg >= ND_MAX_DR_REGS) - { - return ND_STATUS_INVALID_INSTRUX; - } - - res = nd_strcat_s(Buffer, BufferSize, gRegDebug[pOp->Info.Register.Reg]); - RET_EQ(res, NULL, ND_STATUS_BUFFER_OVERFLOW); - } - break; - - case ND_REG_TR: - { - if (pOp->Info.Register.Reg >= ND_MAX_TR_REGS) - { - return ND_STATUS_INVALID_INSTRUX; - } - - res = nd_strcat_s(Buffer, BufferSize, gRegTest[pOp->Info.Register.Reg]); - RET_EQ(res, NULL, ND_STATUS_BUFFER_OVERFLOW); - } - break; - - case ND_REG_BND: - { - // Sanity check. - if (pOp->Info.Register.Reg >= ND_MAX_BND_REGS) - { - return ND_STATUS_INVALID_INSTRUX; - } - - res = nd_strcat_s(Buffer, BufferSize, gRegBound[pOp->Info.Register.Reg]); - RET_EQ(res, NULL, ND_STATUS_BUFFER_OVERFLOW); - } - break; - - case ND_REG_MSK: - { - // Sanity check. - if (pOp->Info.Register.Reg >= ND_MAX_MSK_REGS) - { - return ND_STATUS_INVALID_INSTRUX; - } - - res = nd_strcat_s(Buffer, BufferSize, gRegMask[pOp->Info.Register.Reg]); - RET_EQ(res, NULL, ND_STATUS_BUFFER_OVERFLOW); - } - break; - - case ND_REG_TILE: - { - // Sanity check. - if (pOp->Info.Register.Reg >= ND_MAX_TILE_REGS) - { - return ND_STATUS_INVALID_INSTRUX; - } - - res = nd_strcat_s(Buffer, BufferSize, gRegTile[pOp->Info.Register.Reg]); - RET_EQ(res, NULL, ND_STATUS_BUFFER_OVERFLOW); - } - break; - - default: - break; - } - - if (pOp->Info.Register.Count > 1) - { - status = NdSprintf(temp, sizeof(temp), "+%d", pOp->Info.Register.Count - 1); - if (!ND_SUCCESS(status)) - { - return status; - } - - res = nd_strcat_s(Buffer, BufferSize, temp); - RET_EQ(res, NULL, ND_STATUS_BUFFER_OVERFLOW); - } - - break; - - case ND_OP_BANK: - // Nothing to show. - break; - - case ND_OP_CONST: - { - // Implicit constant - status = NdSprintf(temp, sizeof(temp), "%d", pOp->Info.Constant.Const); - if (!ND_SUCCESS(status)) - { - return status; - } - - res = nd_strcat_s(Buffer, BufferSize, temp); - RET_EQ(res, NULL, ND_STATUS_BUFFER_OVERFLOW); - } - break; - - case ND_OP_IMM: - { - switch (pOp->Size) - { - case 1: - status = NdSprintf(temp, sizeof(temp), "0x%02x", (uint8_t)pOp->Info.Immediate.Imm); - break; - case 2: - status = NdSprintf(temp, sizeof(temp), "0x%04x", (uint16_t)pOp->Info.Immediate.Imm); - break; - case 4: - status = NdSprintf(temp, sizeof(temp), "0x%08x", (uint32_t)pOp->Info.Immediate.Imm); - break; - case 8: - status = NdSprintf(temp, sizeof(temp), "0x%016llx", (uint64_t)pOp->Info.Immediate.Imm); - break; - } - if (!ND_SUCCESS(status)) - { - return status; - } - - res = nd_strcat_s(Buffer, BufferSize, temp); - RET_EQ(res, NULL, ND_STATUS_BUFFER_OVERFLOW); - } - break; - - case ND_OP_OFFS: - { - uint64_t dest = Rip + Instrux->Length + pOp->Info.RelativeOffset.Rel; - - // Truncate to the actual word length. - switch (Instrux->WordLength) - { - case 2: - dest &= 0xFFFF; - break; - case 4: - dest &= 0xFFFFFFFF; - break; - default: - break; - } - - status = NdSprintf(temp, sizeof(temp), "0x%llx", dest); - if (!ND_SUCCESS(status)) - { - return status; - } - - res = nd_strcat_s(Buffer, BufferSize, temp); - RET_EQ(res, NULL, ND_STATUS_BUFFER_OVERFLOW); - } - break; - - case ND_OP_ADDR: - { - switch (Instrux->AddrLength) - { - case 4: - status = NdSprintf(temp, sizeof(temp), "0x%04x:0x%04x", - pOp->Info.Address.BaseSeg, (uint16_t)pOp->Info.Address.Offset); - break; - case 6: - status = NdSprintf(temp, sizeof(temp), "0x%04x:0x%08x", - pOp->Info.Address.BaseSeg, (uint32_t)pOp->Info.Address.Offset); - break; - case 10: - status = NdSprintf(temp, sizeof(temp), "0x%04x:0x%016llx", - pOp->Info.Address.BaseSeg, (uint64_t)pOp->Info.Address.Offset); - break; - default: - return ND_STATUS_INVALID_INSTRUX; - } - - if (!ND_SUCCESS(status)) - { - return status; - } - - res = nd_strcat_s(Buffer, BufferSize, temp); - RET_EQ(res, NULL, ND_STATUS_BUFFER_OVERFLOW); - } - break; - - case ND_OP_MEM: - { - // Prepend the size. For VSIB addressing, store the VSIB element size, not the total accessed size. - ND_OPERAND_SIZE size = pOp->Info.Memory.IsVsib ? pOp->Info.Memory.Vsib.ElemSize : pOp->Size; - - switch (size) - { - case 1: - res = nd_strcat_s(Buffer, BufferSize, "byte ptr "); - RET_EQ(res, NULL, ND_STATUS_BUFFER_OVERFLOW); - break; - case 2: - res = nd_strcat_s(Buffer, BufferSize, "word ptr "); - RET_EQ(res, NULL, ND_STATUS_BUFFER_OVERFLOW); - break; - case 4: - res = nd_strcat_s(Buffer, BufferSize, "dword ptr "); - RET_EQ(res, NULL, ND_STATUS_BUFFER_OVERFLOW); - break; - case 6: - res = nd_strcat_s(Buffer, BufferSize, "fword ptr "); - RET_EQ(res, NULL, ND_STATUS_BUFFER_OVERFLOW); - break; - case 8: - res = nd_strcat_s(Buffer, BufferSize, "qword ptr "); - RET_EQ(res, NULL, ND_STATUS_BUFFER_OVERFLOW); - break; - case 10: - res = nd_strcat_s(Buffer, BufferSize, "tbyte ptr "); - RET_EQ(res, NULL, ND_STATUS_BUFFER_OVERFLOW); - break; - case 16: - res = nd_strcat_s(Buffer, BufferSize, "xmmword ptr "); - RET_EQ(res, NULL, ND_STATUS_BUFFER_OVERFLOW); - break; - case 32: - res = nd_strcat_s(Buffer, BufferSize, "ymmword ptr "); - RET_EQ(res, NULL, ND_STATUS_BUFFER_OVERFLOW); - break; - case 48: - res = nd_strcat_s(Buffer, BufferSize, "m384 ptr "); - RET_EQ(res, NULL, ND_STATUS_BUFFER_OVERFLOW); - break; - case 64: - res = nd_strcat_s(Buffer, BufferSize, "zmmword ptr "); - RET_EQ(res, NULL, ND_STATUS_BUFFER_OVERFLOW); - break; - default: - break; - } - - // Perpend the segment, only if it is overridden via a prefix. - if (pOp->Info.Memory.HasSeg && Instrux->HasSeg) - { - if (pOp->Info.Memory.Seg >= ND_MAX_SEG_REGS) - { - return ND_STATUS_INVALID_INSTRUX; - } - - if ((ND_CODE_64 != Instrux->DefCode) || (NDR_FS == pOp->Info.Memory.Seg) || - (NDR_GS == pOp->Info.Memory.Seg)) - { - res = nd_strcat_s(Buffer, BufferSize, gRegSeg[pOp->Info.Memory.Seg]); - RET_EQ(res, NULL, ND_STATUS_BUFFER_OVERFLOW); - - res = nd_strcat_s(Buffer, BufferSize, ":"); - RET_EQ(res, NULL, ND_STATUS_BUFFER_OVERFLOW); - } - } - - // Prepend the "[" - res = nd_strcat_s(Buffer, BufferSize, "["); - RET_EQ(res, NULL, ND_STATUS_BUFFER_OVERFLOW); - - // Base, if any. - if (pOp->Info.Memory.HasBase) - { - if (pOp->Info.Memory.Base >= ND_MAX_GPR_REGS) - { - return ND_STATUS_INVALID_INSTRUX; - } - - switch (pOp->Info.Memory.BaseSize) - { - case ND_SIZE_8BIT: - res = nd_strcat_s(Buffer, BufferSize, gReg8Bit[pOp->Info.Memory.Base]); - RET_EQ(res, NULL, ND_STATUS_BUFFER_OVERFLOW); - break; - case ND_SIZE_16BIT: - res = nd_strcat_s(Buffer, BufferSize, gReg16Bit[pOp->Info.Memory.Base]); - RET_EQ(res, NULL, ND_STATUS_BUFFER_OVERFLOW); - break; - case ND_SIZE_32BIT: - res = nd_strcat_s(Buffer, BufferSize, gReg32Bit[pOp->Info.Memory.Base]); - RET_EQ(res, NULL, ND_STATUS_BUFFER_OVERFLOW); - break; - case ND_SIZE_64BIT: - res = nd_strcat_s(Buffer, BufferSize, gReg64Bit[pOp->Info.Memory.Base]); - RET_EQ(res, NULL, ND_STATUS_BUFFER_OVERFLOW); - break; - default: - return ND_STATUS_INVALID_INSTRUX; - } - } - - // Index, if any. Special treatment for VSIB addressing. Also, perpend a "+" if base is present. - if (pOp->Info.Memory.HasIndex) - { - if (pOp->Info.Memory.Index >= (pOp->Info.Memory.IsVsib ? ND_MAX_SSE_REGS : ND_MAX_GPR_REGS)) - { - return ND_STATUS_INVALID_INSTRUX; - } - - if (pOp->Info.Memory.HasBase) - { - res = nd_strcat_s(Buffer, BufferSize, "+"); - RET_EQ(res, NULL, ND_STATUS_BUFFER_OVERFLOW); - } - - switch (pOp->Info.Memory.IndexSize) - { - case ND_SIZE_8BIT: - res = nd_strcat_s(Buffer, BufferSize, gReg8Bit[pOp->Info.Memory.Index]); - RET_EQ(res, NULL, ND_STATUS_BUFFER_OVERFLOW); - break; - case ND_SIZE_16BIT: - res = nd_strcat_s(Buffer, BufferSize, gReg16Bit[pOp->Info.Memory.Index]); - RET_EQ(res, NULL, ND_STATUS_BUFFER_OVERFLOW); - break; - case ND_SIZE_32BIT: - res = nd_strcat_s(Buffer, BufferSize, gReg32Bit[pOp->Info.Memory.Index]); - RET_EQ(res, NULL, ND_STATUS_BUFFER_OVERFLOW); - break; - case ND_SIZE_64BIT: - res = nd_strcat_s(Buffer, BufferSize, gReg64Bit[pOp->Info.Memory.Index]); - RET_EQ(res, NULL, ND_STATUS_BUFFER_OVERFLOW); - break; - case ND_SIZE_128BIT: - res = nd_strcat_s(Buffer, BufferSize, gRegXmm[pOp->Info.Memory.Index]); - RET_EQ(res, NULL, ND_STATUS_BUFFER_OVERFLOW); - break; - case ND_SIZE_256BIT: - res = nd_strcat_s(Buffer, BufferSize, gRegYmm[pOp->Info.Memory.Index]); - RET_EQ(res, NULL, ND_STATUS_BUFFER_OVERFLOW); - break; - case ND_SIZE_512BIT: - res = nd_strcat_s(Buffer, BufferSize, gRegZmm[pOp->Info.Memory.Index]); - RET_EQ(res, NULL, ND_STATUS_BUFFER_OVERFLOW); - break; - default: - return ND_STATUS_INVALID_INSTRUX; - } - - // If index is present, scale is also present. - if (pOp->Info.Memory.Scale != 1 && !pOp->Info.Memory.IsMib) - { - status = NdSprintf(temp, sizeof(temp), "*%d", pOp->Info.Memory.Scale); - if (!ND_SUCCESS(status)) - { - return status; - } - - res = nd_strcat_s(Buffer, BufferSize, temp); - RET_EQ(res, NULL, ND_STATUS_BUFFER_OVERFLOW); - } - } - - // Handle displacement. - if (pOp->Info.Memory.HasDisp) - { - uint64_t normDisp, disp; - - disp = pOp->Info.Memory.Disp; - - // If this is direct addressing (O operand) or we don't have base or index, than we don't normalize - // the displacement, since it is used as a direct offset. Note that the second condition also - // includes the RIP-relative case. - if (pOp->Info.Memory.IsDirect || !(pOp->Info.Memory.HasBase || pOp->Info.Memory.HasIndex)) - { - normDisp = disp; - } - else - { - switch (pOp->Info.Memory.DispSize) - { - case 1: - normDisp = ((disp & 0x80) ? ~disp + 1ULL : disp) & 0xFF; - break; - case 2: - normDisp = ((disp & 0x8000) ? ~disp + 1ULL : disp) & 0xFFFF; - break; - case 4: - normDisp = ((disp & 0x80000000) ? ~disp + 1ULL : disp) & 0xFFFFFFFF; - break; - default: - normDisp = disp; - break; - } - - // Handle compressed displacement. It is fine to cast the normDisp to uint32_t, as the - // compressed displacement only works with uint8_t displacements. Also, in this phase, - // the normDisp is converted to a positive quantity, so no sign-extension is needed. - if (pOp->Info.Memory.HasCompDisp) - { - normDisp = (uint64_t)(uint32_t)normDisp * pOp->Info.Memory.CompDispSize; - } - } - - - // Now displacement. - if (pOp->Info.Memory.HasBase || pOp->Info.Memory.HasIndex) - { - res = nd_strcat_s(Buffer, BufferSize, Instrux->SignDisp ? "-" : "+"); - RET_EQ(res, NULL, ND_STATUS_BUFFER_OVERFLOW); - } - - if (pOp->Info.Memory.IsRipRel) - { - uint64_t target = disp + Rip + Instrux->Length; - - if (Instrux->AddrMode == ND_ADDR_32) - { - target &= 0xFFFFFFFF; - } - - status = NdSprintf(temp, sizeof(temp), "rel 0x%llx", target); - } - else - { - uint8_t trimSize; - - trimSize = (Instrux->AddrMode == ND_ADDR_16) ? 2 : ((Instrux->AddrMode == ND_ADDR_32) ? 4 : 8); - - // Truncate the displacement size to the size of the address length. - normDisp = ND_TRIM(trimSize, normDisp); - - status = NdSprintf(temp, sizeof(temp), "0x%llx", normDisp); - } - if (!ND_SUCCESS(status)) - { - return status; - } - - res = nd_strcat_s(Buffer, BufferSize, temp); - RET_EQ(res, NULL, ND_STATUS_BUFFER_OVERFLOW); - } - - // And the ending "]" - res = nd_strcat_s(Buffer, BufferSize, "]"); - RET_EQ(res, NULL, ND_STATUS_BUFFER_OVERFLOW); - } - break; - - default: - return ND_STATUS_INVALID_INSTRUX; - } - - // Handle memory broadcast. - if (pOp->Decorator.HasBroadcast) - { - status = NdSprintf(temp, sizeof(temp), "{1to%d}", pOp->Decorator.Broadcast.Count); - if (!ND_SUCCESS(status)) - { - return status; - } - - res = nd_strcat_s(Buffer, BufferSize, temp); - RET_EQ(res, NULL, ND_STATUS_BUFFER_OVERFLOW); - } - - // Handle masking. - if (pOp->Decorator.HasMask) - { - if (pOp->Decorator.Mask.Msk >= ND_MAX_MSK_REGS) - { - return ND_STATUS_INVALID_INSTRUX; - } - - status = NdSprintf(temp, sizeof(temp), "{%s}", gRegMask[pOp->Decorator.Mask.Msk]); - if (!ND_SUCCESS(status)) - { - return status; - } - - res = nd_strcat_s(Buffer, BufferSize, temp); - RET_EQ(res, NULL, ND_STATUS_BUFFER_OVERFLOW); - } - - // Handle zeroing. Note that zeroing without masking is ignored. - if (pOp->Decorator.HasZero && pOp->Decorator.HasMask) - { - res = nd_strcat_s(Buffer, BufferSize, "{z}"); - RET_EQ(res, NULL, ND_STATUS_BUFFER_OVERFLOW); - } - - // Append Suppress All Exceptions decorator. - if (pOp->Decorator.HasSae && !pOp->Decorator.HasEr) - { - // ER implies SAE, so if we have ER, we will list that. - res = nd_strcat_s(Buffer, BufferSize, ", {sae}"); - RET_EQ(res, NULL, ND_STATUS_BUFFER_OVERFLOW); - } - - // Append Embedded Rounding decorator. - if (pOp->Decorator.HasEr) - { - if (Instrux->RoundingMode >= 4) - { - return ND_STATUS_INVALID_INSTRUX; - } - - status = NdSprintf(temp, sizeof(temp), ", {%s-sae}", gEmbeddedRounding[Instrux->RoundingMode]); - if (!ND_SUCCESS(status)) - { - return status; - } - - res = nd_strcat_s(Buffer, BufferSize, temp); - RET_EQ(res, NULL, ND_STATUS_BUFFER_OVERFLOW); - } - } - - return ND_STATUS_SUCCESS; -} -#else -NDSTATUS -NdToText( - const INSTRUX *Instrux, - uint64_t Rip, - uint32_t BufferSize, - char *Buffer - ) -{ - UNREFERENCED_PARAMETER(Instrux); - UNREFERENCED_PARAMETER(Rip); - - // At least make sure the buffer is NULL-terminated so integrators can use NdToText without checking if the - // BDDISASM_NO_FORMAT macro is defined. This makes switching between versions with formatting and versions without - // formatting easier. - if (Buffer != NULL && BufferSize >= 1) - { - *Buffer = '\0'; - } - - return ND_STATUS_SUCCESS; -} -#endif // !BDDISASM_NO_FORMAT // diff --git a/bddisasm/bddisasm.vcxproj b/bddisasm/bddisasm.vcxproj index e625ea6..ae1cbf3 100644 --- a/bddisasm/bddisasm.vcxproj +++ b/bddisasm/bddisasm.vcxproj @@ -420,6 +420,7 @@ + NotUsing diff --git a/bddisasm/bddisasm.vcxproj.filters b/bddisasm/bddisasm.vcxproj.filters index 5ddd5ae..b4de484 100644 --- a/bddisasm/bddisasm.vcxproj.filters +++ b/bddisasm/bddisasm.vcxproj.filters @@ -27,6 +27,9 @@ Source Files + + Source Files + diff --git a/bddisasm/bdformat.c b/bddisasm/bdformat.c new file mode 100644 index 0000000..fc5842c --- /dev/null +++ b/bddisasm/bdformat.c @@ -0,0 +1,1050 @@ +/* + * Copyright (c) 2020 Bitdefender + * SPDX-License-Identifier: Apache-2.0 + */ +#include "include/nd_crt.h" +#include "../inc/bddisasm.h" + + + +#ifndef BDDISASM_NO_FORMAT + +static const char *gReg8Bit[] = +{ + "al", "cl", "dl", "bl", "ah", "ch", "dh", "bh", +}; + +static const char *gReg8Bit64[] = +{ + "al", "cl", "dl", "bl", "spl", "bpl", "sil", "dil", + "r8b", "r9b", "r10b", "r11b", "r12b", "r13b", "r14b", "r15b", +}; + +static const char *gReg16Bit[] = +{ + "ax", "cx", "dx", "bx", "sp", "bp", "si", "di", + "r8w", "r9w", "r10w", "r11w", "r12w", "r13w", "r14w", "r15w", +}; + +static const char *gReg32Bit[] = +{ + "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi", + "r8d", "r9d", "r10d", "r11d", "r12d", "r13d", "r14d", "r15d", +}; + +static const char *gReg64Bit[] = +{ + "rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi", + "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15" +}; + +static const char *gRegFpu[] = +{ + "st0", "st1", "st2", "st3", "st4", "st5", "st6", "st7", +}; + +static const char *gRegMmx[] = +{ + "mm0", "mm1", "mm2", "mm3", "mm4", "mm5", "mm6", "mm7", +}; + +static const char *gRegControl[] = +{ + "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", + "cr8", "cr9", "cr10", "cr11", "cr12", "cr13", "cr14", "cr15", +}; + +static const char *gRegDebug[] = +{ + "dr0", "dr1", "dr2", "dr3", "dr4", "dr5", "dr6", "dr7", + "dr8", "dr9", "dr10", "dr11", "dr12", "dr13", "dr14", "dr15", +}; + +static const char *gRegTest[] = +{ + "tr0", "tr1", "tr2", "tr3", "tr4", "tr5", "tr6", "tr7", + "tr8", "tr9", "tr10", "tr11", "tr12", "tr13", "tr14", "tr15", +}; + +static const char *gRegXmm[] = +{ + "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", + "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", + "xmm16", "xmm17", "xmm18", "xmm19", "xmm20", "xmm21", "xmm22", "xmm23", + "xmm24", "xmm25", "xmm26", "xmm27", "xmm28", "xmm29", "xmm30", "xmm31", +}; + +static const char *gRegYmm[] = +{ + "ymm0", "ymm1", "ymm2", "ymm3", "ymm4", "ymm5", "ymm6", "ymm7", + "ymm8", "ymm9", "ymm10", "ymm11", "ymm12", "ymm13", "ymm14", "ymm15", + "ymm16", "ymm17", "ymm18", "ymm19", "ymm20", "ymm21", "ymm22", "ymm23", + "ymm24", "ymm25", "ymm26", "ymm27", "ymm28", "ymm29", "ymm30", "ymm31" +}; + +static const char *gRegZmm[] = +{ + "zmm0", "zmm1", "zmm2", "zmm3", "zmm4", "zmm5", "zmm6", "zmm7", + "zmm8", "zmm9", "zmm10", "zmm11", "zmm12", "zmm13", "zmm14", "zmm15", + "zmm16", "zmm17", "zmm18", "zmm19", "zmm20", "zmm21", "zmm22", "zmm23", + "zmm24", "zmm25", "zmm26", "zmm27", "zmm28", "zmm29", "zmm30", "zmm31", +}; + +static const char *gRegSeg[] = +{ + "es", "cs", "ss", "ds", "fs", "gs", "segr6", "segr7", +}; + +static const char *gRegBound[] = +{ + "bnd0", "bnd1", "bnd2", "bnd3", +}; + +static const char *gRegMask[] = +{ + "k0", "k1", "k2", "k3", "k4", "k5", "k6", "k7", +}; + +static const char *gRegTile[] = +{ + "tmm0", "tmm1", "tmm2", "tmm3", "tmm4", "tmm5", "tmm6", "tmm7", +}; + +static const char *gConditionCodes[] = +{ + "EQ", "LT", "LE", "UNORD", "NEQ", "NLT", "NLE", "ORD", + "EQ_UQ", "NGE", "NGT", "false", "NEQ_OQ", "GE", "GT", "TRUE", + "EQ_OS", "LT_OQ", "LE_OQ", "UNORD_S", "NEQ_US", "NLT_UQ", "NLE_UQ", "ORD_S", + "EQ_US", "NGE_UQ", "NGT_UQ", "FALSE_OS", "NEQ_OS", "GE_OQ", "GT_OQ", "TRUE_US", +}; + +static const char *gEmbeddedRounding[] = +{ + "rn", "rd", "ru", "rz", +}; + + + +// +// NdSprintf +// +static NDSTATUS +NdSprintf( + char *Destination, + size_t DestinationSize, + const char *Formatstring, + ... + ) +// +// Wrapper on vsnprintf. +// +{ + int res; + va_list args; + + if (NULL == Destination) + { + return ND_STATUS_INVALID_PARAMETER; + } + + if (NULL == Formatstring) + { + return ND_STATUS_INVALID_PARAMETER; + } + + nd_memzero(Destination, DestinationSize); + + va_start(args, Formatstring); + + // _vsnprintf is used instead of the more secure _vsnprintf_s because the mini-Petru supports just + // the unsecured version, and we depend on it. + res = nd_vsnprintf_s(Destination, DestinationSize, DestinationSize - 1, Formatstring, args); + + va_end(args); + + if ((res < 0) || ((size_t)res >= DestinationSize - 1)) + { + return ND_STATUS_BUFFER_OVERFLOW; + } + + return ND_STATUS_SUCCESS; +} + + +// +// NdToText +// +NDSTATUS +NdToText( + const INSTRUX *Instrux, + uint64_t Rip, + uint32_t BufferSize, + char *Buffer + ) +{ + NDSTATUS status; + char *res, temp[64]; + uint32_t opIndex, opsStored; + const ND_OPERAND *pOp; + bool alignmentStored; + + // pre-init + status = ND_STATUS_SUCCESS; + res = NULL; + opIndex = 0; + opsStored = 0; + pOp = NULL; + alignmentStored = false; + + // Validate args. + if (NULL == Instrux) + { + return ND_STATUS_INVALID_PARAMETER; + } + + if (NULL == Buffer) + { + return ND_STATUS_INVALID_PARAMETER; + } + + if (BufferSize < ND_MIN_BUF_SIZE) + { + return ND_STATUS_INVALID_PARAMETER; + } + + // init the text. + nd_memzero(Buffer, BufferSize); + nd_memzero(temp, sizeof(temp)); + + // First, store the prefixes. + if (Instrux->Rep != 0) + { + // Check for REPZ/REPNZ support, and store prefixes. + if (ND_REPC_SUPPORT(Instrux)) + { + if (Instrux->Rep == ND_PREFIX_G1_REPE_REPZ) + { + res = nd_strcat_s(Buffer, BufferSize, "REPZ "); + RET_EQ(res, NULL, ND_STATUS_BUFFER_OVERFLOW); + } + else if (Instrux->Rep == ND_PREFIX_G1_REPNE_REPNZ) + { + res = nd_strcat_s(Buffer, BufferSize, "REPNZ "); + RET_EQ(res, NULL, ND_STATUS_BUFFER_OVERFLOW); + } + } + + // Check for REP support and store prefixes. + if (ND_REP_SUPPORT(Instrux)) + { + if (Instrux->Rep == ND_PREFIX_G1_REPE_REPZ) + { + res = nd_strcat_s(Buffer, BufferSize, "REP "); + RET_EQ(res, NULL, ND_STATUS_BUFFER_OVERFLOW); + } + else if (Instrux->Rep == ND_PREFIX_G1_REPNE_REPNZ) + { + res = nd_strcat_s(Buffer, BufferSize, "REPNZ "); + RET_EQ(res, NULL, ND_STATUS_BUFFER_OVERFLOW); + } + } + + if (Instrux->IsXreleaseEnabled) + { + res = nd_strcat_s(Buffer, BufferSize, "XRELEASE "); + RET_EQ(res, NULL, ND_STATUS_BUFFER_OVERFLOW); + } + else if (Instrux->IsXacquireEnabled) + { + res = nd_strcat_s(Buffer, BufferSize, "XACQUIRE "); + RET_EQ(res, NULL, ND_STATUS_BUFFER_OVERFLOW); + } + } + + if (Instrux->HasLock) + { + if (ND_LOCK_SUPPORT(Instrux)) + { + res = nd_strcat_s(Buffer, BufferSize, "LOCK "); + RET_EQ(res, NULL, ND_STATUS_BUFFER_OVERFLOW); + } + } + + if (Instrux->Rep == ND_PREFIX_G1_BND) + { + if (ND_BND_SUPPORT(Instrux)) + { + res = nd_strcat_s(Buffer, BufferSize, "BND "); + RET_EQ(res, NULL, ND_STATUS_BUFFER_OVERFLOW); + } + } + + if (Instrux->HasSeg && ND_BHINT_SUPPORT(Instrux)) + { + switch (Instrux->Seg) + { + case ND_PREFIX_G2_BR_TAKEN: + res = nd_strcat_s(Buffer, BufferSize, "BHT "); + RET_EQ(res, NULL, ND_STATUS_BUFFER_OVERFLOW); + break; + + case ND_PREFIX_G2_BR_NOT_TAKEN: + res = nd_strcat_s(Buffer, BufferSize, "BHNT "); + RET_EQ(res, NULL, ND_STATUS_BUFFER_OVERFLOW); + break; + + case ND_PREFIX_G2_BR_ALT: + res = nd_strcat_s(Buffer, BufferSize, "BHALT "); + RET_EQ(res, NULL, ND_STATUS_BUFFER_OVERFLOW); + break; + + default: + break; + } + } + + if (Instrux->HasSeg && ND_DNT_SUPPORT(Instrux)) + { + if (!Instrux->IsCetTracked) + { + res = nd_strcat_s(Buffer, BufferSize, "DNT "); + RET_EQ(res, NULL, ND_STATUS_BUFFER_OVERFLOW); + } + } + + // Store the mnemonic. + res = nd_strcat_s(Buffer, BufferSize, Instrux->Mnemonic); + RET_EQ(res, NULL, ND_STATUS_BUFFER_OVERFLOW); + + // Store condition code, if any. + if (ND_HAS_SSE_CONDITION(Instrux)) + { + res = nd_strcat_s(Buffer, BufferSize, gConditionCodes[Instrux->SseCondition]); + RET_EQ(res, NULL, ND_STATUS_BUFFER_OVERFLOW); + } + + // If there are no explicit operands, we can leave. + if (0 == Instrux->ExpOperandsCount) + { + return ND_STATUS_SUCCESS; + } + + // Now the operands. + for (opIndex = 0; opIndex < Instrux->OperandsCount; opIndex++) + { + status = ND_STATUS_SUCCESS; + + pOp = &Instrux->Operands[opIndex]; + + if (pOp->Type == ND_OP_NOT_PRESENT) + { + break; + } + + if (pOp->Flags.IsDefault) + { + continue; + } + + // If this is a mask operand that has been used as masking for a previous operand, than we + // can safely skip it. We check this by seeing where is the operand encoded. If it's encoded + // in the evex.aaa field, than it is a conventional mask. + if ((pOp->Encoding == ND_OPE_A) && (pOp->Type == ND_OP_REG) && + (pOp->Info.Register.Type == ND_REG_MSK) && (opIndex > 0)) + { + continue; + } + + // Store alignment. + if (!alignmentStored) + { + size_t idx = 0; + + while ((idx < BufferSize) && (Buffer[idx])) + { + idx++; + } + + while ((idx < 9) && (idx + 1 < BufferSize)) + { + Buffer[idx++] = 0x20; + } + + if (idx + 1 < BufferSize) + { + Buffer[idx++] = 0x20; + } + + Buffer[idx] = 0; + + alignmentStored = true; + } + + // Store the comma, if this isn't the first operand. + if (opsStored > 0) + { + res = nd_strcat_s(Buffer, BufferSize, ", "); + RET_EQ(res, NULL, ND_STATUS_BUFFER_OVERFLOW); + } + + opsStored++; + + switch (pOp->Type) + { + case ND_OP_REG: + switch (pOp->Info.Register.Type) + { + case ND_REG_GPR: + { + if (pOp->Info.Register.Reg >= ND_MAX_GPR_REGS) + { + return ND_STATUS_INVALID_INSTRUX; + } + + // General purpose register. + switch (pOp->Info.Register.Size) + { + case ND_SIZE_8BIT: + // 8 bit register. + if ((Instrux->EncMode != ND_ENCM_LEGACY) || Instrux->HasRex) + { + res = nd_strcat_s(Buffer, BufferSize, gReg8Bit64[pOp->Info.Register.Reg]); + RET_EQ(res, NULL, ND_STATUS_BUFFER_OVERFLOW); + } + else + { + res = nd_strcat_s(Buffer, BufferSize, gReg8Bit[pOp->Info.Register.Reg]); + RET_EQ(res, NULL, ND_STATUS_BUFFER_OVERFLOW); + } + break; + + case ND_SIZE_16BIT: + // 16 bit register. + res = nd_strcat_s(Buffer, BufferSize, gReg16Bit[pOp->Info.Register.Reg]); + RET_EQ(res, NULL, ND_STATUS_BUFFER_OVERFLOW); + break; + + case ND_SIZE_32BIT: + // 32 bit register. + res = nd_strcat_s(Buffer, BufferSize, gReg32Bit[pOp->Info.Register.Reg]); + RET_EQ(res, NULL, ND_STATUS_BUFFER_OVERFLOW); + break; + + case ND_SIZE_64BIT: + // 64 bit register. + res = nd_strcat_s(Buffer, BufferSize, gReg64Bit[pOp->Info.Register.Reg]); + RET_EQ(res, NULL, ND_STATUS_BUFFER_OVERFLOW); + break; + + default: + return ND_STATUS_INVALID_INSTRUX; + } + } + break; + + case ND_REG_SEG: + { + if (pOp->Info.Register.Reg >= ND_MAX_SEG_REGS) + { + return ND_STATUS_INVALID_INSTRUX; + } + + res = nd_strcat_s(Buffer, BufferSize, gRegSeg[pOp->Info.Register.Reg]); + RET_EQ(res, NULL, ND_STATUS_BUFFER_OVERFLOW); + } + break; + + case ND_REG_FPU: + { + if (pOp->Info.Register.Reg >= ND_MAX_FPU_REGS) + { + return ND_STATUS_INVALID_INSTRUX; + } + + res = nd_strcat_s(Buffer, BufferSize, gRegFpu[pOp->Info.Register.Reg]); + RET_EQ(res, NULL, ND_STATUS_BUFFER_OVERFLOW); + } + break; + + case ND_REG_MMX: + { + if (pOp->Info.Register.Reg >= ND_MAX_MMX_REGS) + { + return ND_STATUS_INVALID_INSTRUX; + } + + res = nd_strcat_s(Buffer, BufferSize, gRegMmx[pOp->Info.Register.Reg]); + RET_EQ(res, NULL, ND_STATUS_BUFFER_OVERFLOW); + } + break; + + case ND_REG_SSE: + { + if (pOp->Info.Register.Reg >= ND_MAX_SSE_REGS) + { + return ND_STATUS_INVALID_INSTRUX; + } + + switch (pOp->Info.Register.Size) + { + case ND_SIZE_128BIT: + res = nd_strcat_s(Buffer, BufferSize, gRegXmm[pOp->Info.Register.Reg]); + RET_EQ(res, NULL, ND_STATUS_BUFFER_OVERFLOW); + break; + case ND_SIZE_256BIT: + res = nd_strcat_s(Buffer, BufferSize, gRegYmm[pOp->Info.Register.Reg]); + RET_EQ(res, NULL, ND_STATUS_BUFFER_OVERFLOW); + break; + case ND_SIZE_512BIT: + res = nd_strcat_s(Buffer, BufferSize, gRegZmm[pOp->Info.Register.Reg]); + RET_EQ(res, NULL, ND_STATUS_BUFFER_OVERFLOW); + break; + default: + return ND_STATUS_INVALID_INSTRUX; + } + } + break; + + case ND_REG_CR: + { + if (pOp->Info.Register.Reg >= ND_MAX_CR_REGS) + { + return ND_STATUS_INVALID_INSTRUX; + } + + res = nd_strcat_s(Buffer, BufferSize, gRegControl[pOp->Info.Register.Reg]); + RET_EQ(res, NULL, ND_STATUS_BUFFER_OVERFLOW); + } + break; + + case ND_REG_DR: + { + if (pOp->Info.Register.Reg >= ND_MAX_DR_REGS) + { + return ND_STATUS_INVALID_INSTRUX; + } + + res = nd_strcat_s(Buffer, BufferSize, gRegDebug[pOp->Info.Register.Reg]); + RET_EQ(res, NULL, ND_STATUS_BUFFER_OVERFLOW); + } + break; + + case ND_REG_TR: + { + if (pOp->Info.Register.Reg >= ND_MAX_TR_REGS) + { + return ND_STATUS_INVALID_INSTRUX; + } + + res = nd_strcat_s(Buffer, BufferSize, gRegTest[pOp->Info.Register.Reg]); + RET_EQ(res, NULL, ND_STATUS_BUFFER_OVERFLOW); + } + break; + + case ND_REG_BND: + { + // Sanity check. + if (pOp->Info.Register.Reg >= ND_MAX_BND_REGS) + { + return ND_STATUS_INVALID_INSTRUX; + } + + res = nd_strcat_s(Buffer, BufferSize, gRegBound[pOp->Info.Register.Reg]); + RET_EQ(res, NULL, ND_STATUS_BUFFER_OVERFLOW); + } + break; + + case ND_REG_MSK: + { + // Sanity check. + if (pOp->Info.Register.Reg >= ND_MAX_MSK_REGS) + { + return ND_STATUS_INVALID_INSTRUX; + } + + res = nd_strcat_s(Buffer, BufferSize, gRegMask[pOp->Info.Register.Reg]); + RET_EQ(res, NULL, ND_STATUS_BUFFER_OVERFLOW); + } + break; + + case ND_REG_TILE: + { + // Sanity check. + if (pOp->Info.Register.Reg >= ND_MAX_TILE_REGS) + { + return ND_STATUS_INVALID_INSTRUX; + } + + res = nd_strcat_s(Buffer, BufferSize, gRegTile[pOp->Info.Register.Reg]); + RET_EQ(res, NULL, ND_STATUS_BUFFER_OVERFLOW); + } + break; + + default: + break; + } + + if (pOp->Info.Register.Count > 1) + { + status = NdSprintf(temp, sizeof(temp), "+%d", pOp->Info.Register.Count - 1); + if (!ND_SUCCESS(status)) + { + return status; + } + + res = nd_strcat_s(Buffer, BufferSize, temp); + RET_EQ(res, NULL, ND_STATUS_BUFFER_OVERFLOW); + } + + break; + + case ND_OP_BANK: + // Nothing to show. + break; + + case ND_OP_CONST: + { + // Implicit constant + status = NdSprintf(temp, sizeof(temp), "%d", pOp->Info.Constant.Const); + if (!ND_SUCCESS(status)) + { + return status; + } + + res = nd_strcat_s(Buffer, BufferSize, temp); + RET_EQ(res, NULL, ND_STATUS_BUFFER_OVERFLOW); + } + break; + + case ND_OP_IMM: + { + switch (pOp->Size) + { + case 1: + status = NdSprintf(temp, sizeof(temp), "0x%02x", (uint8_t)pOp->Info.Immediate.Imm); + break; + case 2: + status = NdSprintf(temp, sizeof(temp), "0x%04x", (uint16_t)pOp->Info.Immediate.Imm); + break; + case 4: + status = NdSprintf(temp, sizeof(temp), "0x%08x", (uint32_t)pOp->Info.Immediate.Imm); + break; + case 8: + status = NdSprintf(temp, sizeof(temp), "0x%016llx", (uint64_t)pOp->Info.Immediate.Imm); + break; + } + if (!ND_SUCCESS(status)) + { + return status; + } + + res = nd_strcat_s(Buffer, BufferSize, temp); + RET_EQ(res, NULL, ND_STATUS_BUFFER_OVERFLOW); + } + break; + + case ND_OP_OFFS: + { + uint64_t dest = Rip + Instrux->Length + pOp->Info.RelativeOffset.Rel; + + // Truncate to the actual word length. + switch (Instrux->WordLength) + { + case 2: + dest &= 0xFFFF; + break; + case 4: + dest &= 0xFFFFFFFF; + break; + default: + break; + } + + status = NdSprintf(temp, sizeof(temp), "0x%llx", dest); + if (!ND_SUCCESS(status)) + { + return status; + } + + res = nd_strcat_s(Buffer, BufferSize, temp); + RET_EQ(res, NULL, ND_STATUS_BUFFER_OVERFLOW); + } + break; + + case ND_OP_ADDR: + { + switch (Instrux->AddrLength) + { + case 4: + status = NdSprintf(temp, sizeof(temp), "0x%04x:0x%04x", + pOp->Info.Address.BaseSeg, (uint16_t)pOp->Info.Address.Offset); + break; + case 6: + status = NdSprintf(temp, sizeof(temp), "0x%04x:0x%08x", + pOp->Info.Address.BaseSeg, (uint32_t)pOp->Info.Address.Offset); + break; + case 10: + status = NdSprintf(temp, sizeof(temp), "0x%04x:0x%016llx", + pOp->Info.Address.BaseSeg, (uint64_t)pOp->Info.Address.Offset); + break; + default: + return ND_STATUS_INVALID_INSTRUX; + } + + if (!ND_SUCCESS(status)) + { + return status; + } + + res = nd_strcat_s(Buffer, BufferSize, temp); + RET_EQ(res, NULL, ND_STATUS_BUFFER_OVERFLOW); + } + break; + + case ND_OP_MEM: + { + // Prepend the size. For VSIB addressing, store the VSIB element size, not the total accessed size. + ND_OPERAND_SIZE size = pOp->Info.Memory.IsVsib ? pOp->Info.Memory.Vsib.ElemSize : pOp->Size; + + switch (size) + { + case 1: + res = nd_strcat_s(Buffer, BufferSize, "byte ptr "); + RET_EQ(res, NULL, ND_STATUS_BUFFER_OVERFLOW); + break; + case 2: + res = nd_strcat_s(Buffer, BufferSize, "word ptr "); + RET_EQ(res, NULL, ND_STATUS_BUFFER_OVERFLOW); + break; + case 4: + res = nd_strcat_s(Buffer, BufferSize, "dword ptr "); + RET_EQ(res, NULL, ND_STATUS_BUFFER_OVERFLOW); + break; + case 6: + res = nd_strcat_s(Buffer, BufferSize, "fword ptr "); + RET_EQ(res, NULL, ND_STATUS_BUFFER_OVERFLOW); + break; + case 8: + res = nd_strcat_s(Buffer, BufferSize, "qword ptr "); + RET_EQ(res, NULL, ND_STATUS_BUFFER_OVERFLOW); + break; + case 10: + res = nd_strcat_s(Buffer, BufferSize, "tbyte ptr "); + RET_EQ(res, NULL, ND_STATUS_BUFFER_OVERFLOW); + break; + case 16: + res = nd_strcat_s(Buffer, BufferSize, "xmmword ptr "); + RET_EQ(res, NULL, ND_STATUS_BUFFER_OVERFLOW); + break; + case 32: + res = nd_strcat_s(Buffer, BufferSize, "ymmword ptr "); + RET_EQ(res, NULL, ND_STATUS_BUFFER_OVERFLOW); + break; + case 48: + res = nd_strcat_s(Buffer, BufferSize, "m384 ptr "); + RET_EQ(res, NULL, ND_STATUS_BUFFER_OVERFLOW); + break; + case 64: + res = nd_strcat_s(Buffer, BufferSize, "zmmword ptr "); + RET_EQ(res, NULL, ND_STATUS_BUFFER_OVERFLOW); + break; + default: + break; + } + + // Perpend the segment, only if it is overridden via a prefix. + if (pOp->Info.Memory.HasSeg && Instrux->HasSeg) + { + if (pOp->Info.Memory.Seg >= ND_MAX_SEG_REGS) + { + return ND_STATUS_INVALID_INSTRUX; + } + + if ((ND_CODE_64 != Instrux->DefCode) || (NDR_FS == pOp->Info.Memory.Seg) || + (NDR_GS == pOp->Info.Memory.Seg)) + { + res = nd_strcat_s(Buffer, BufferSize, gRegSeg[pOp->Info.Memory.Seg]); + RET_EQ(res, NULL, ND_STATUS_BUFFER_OVERFLOW); + + res = nd_strcat_s(Buffer, BufferSize, ":"); + RET_EQ(res, NULL, ND_STATUS_BUFFER_OVERFLOW); + } + } + + // Prepend the "[" + res = nd_strcat_s(Buffer, BufferSize, "["); + RET_EQ(res, NULL, ND_STATUS_BUFFER_OVERFLOW); + + // Base, if any. + if (pOp->Info.Memory.HasBase) + { + if (pOp->Info.Memory.Base >= ND_MAX_GPR_REGS) + { + return ND_STATUS_INVALID_INSTRUX; + } + + switch (pOp->Info.Memory.BaseSize) + { + case ND_SIZE_8BIT: + res = nd_strcat_s(Buffer, BufferSize, gReg8Bit[pOp->Info.Memory.Base]); + RET_EQ(res, NULL, ND_STATUS_BUFFER_OVERFLOW); + break; + case ND_SIZE_16BIT: + res = nd_strcat_s(Buffer, BufferSize, gReg16Bit[pOp->Info.Memory.Base]); + RET_EQ(res, NULL, ND_STATUS_BUFFER_OVERFLOW); + break; + case ND_SIZE_32BIT: + res = nd_strcat_s(Buffer, BufferSize, gReg32Bit[pOp->Info.Memory.Base]); + RET_EQ(res, NULL, ND_STATUS_BUFFER_OVERFLOW); + break; + case ND_SIZE_64BIT: + res = nd_strcat_s(Buffer, BufferSize, gReg64Bit[pOp->Info.Memory.Base]); + RET_EQ(res, NULL, ND_STATUS_BUFFER_OVERFLOW); + break; + default: + return ND_STATUS_INVALID_INSTRUX; + } + } + + // Index, if any. Special treatment for VSIB addressing. Also, perpend a "+" if base is present. + if (pOp->Info.Memory.HasIndex) + { + if (pOp->Info.Memory.Index >= (pOp->Info.Memory.IsVsib ? ND_MAX_SSE_REGS : ND_MAX_GPR_REGS)) + { + return ND_STATUS_INVALID_INSTRUX; + } + + if (pOp->Info.Memory.HasBase) + { + res = nd_strcat_s(Buffer, BufferSize, "+"); + RET_EQ(res, NULL, ND_STATUS_BUFFER_OVERFLOW); + } + + switch (pOp->Info.Memory.IndexSize) + { + case ND_SIZE_8BIT: + res = nd_strcat_s(Buffer, BufferSize, gReg8Bit[pOp->Info.Memory.Index]); + RET_EQ(res, NULL, ND_STATUS_BUFFER_OVERFLOW); + break; + case ND_SIZE_16BIT: + res = nd_strcat_s(Buffer, BufferSize, gReg16Bit[pOp->Info.Memory.Index]); + RET_EQ(res, NULL, ND_STATUS_BUFFER_OVERFLOW); + break; + case ND_SIZE_32BIT: + res = nd_strcat_s(Buffer, BufferSize, gReg32Bit[pOp->Info.Memory.Index]); + RET_EQ(res, NULL, ND_STATUS_BUFFER_OVERFLOW); + break; + case ND_SIZE_64BIT: + res = nd_strcat_s(Buffer, BufferSize, gReg64Bit[pOp->Info.Memory.Index]); + RET_EQ(res, NULL, ND_STATUS_BUFFER_OVERFLOW); + break; + case ND_SIZE_128BIT: + res = nd_strcat_s(Buffer, BufferSize, gRegXmm[pOp->Info.Memory.Index]); + RET_EQ(res, NULL, ND_STATUS_BUFFER_OVERFLOW); + break; + case ND_SIZE_256BIT: + res = nd_strcat_s(Buffer, BufferSize, gRegYmm[pOp->Info.Memory.Index]); + RET_EQ(res, NULL, ND_STATUS_BUFFER_OVERFLOW); + break; + case ND_SIZE_512BIT: + res = nd_strcat_s(Buffer, BufferSize, gRegZmm[pOp->Info.Memory.Index]); + RET_EQ(res, NULL, ND_STATUS_BUFFER_OVERFLOW); + break; + default: + return ND_STATUS_INVALID_INSTRUX; + } + + // If index is present, scale is also present. + if (pOp->Info.Memory.Scale != 1 && !pOp->Info.Memory.IsMib) + { + status = NdSprintf(temp, sizeof(temp), "*%d", pOp->Info.Memory.Scale); + if (!ND_SUCCESS(status)) + { + return status; + } + + res = nd_strcat_s(Buffer, BufferSize, temp); + RET_EQ(res, NULL, ND_STATUS_BUFFER_OVERFLOW); + } + } + + // Handle displacement. + if (pOp->Info.Memory.HasDisp) + { + uint64_t normDisp, disp; + + disp = pOp->Info.Memory.Disp; + + // If this is direct addressing (O operand) or we don't have base or index, than we don't normalize + // the displacement, since it is used as a direct offset. Note that the second condition also + // includes the RIP-relative case. + if (pOp->Info.Memory.IsDirect || !(pOp->Info.Memory.HasBase || pOp->Info.Memory.HasIndex)) + { + normDisp = disp; + } + else + { + switch (pOp->Info.Memory.DispSize) + { + case 1: + normDisp = ((disp & 0x80) ? ~disp + 1ULL : disp) & 0xFF; + break; + case 2: + normDisp = ((disp & 0x8000) ? ~disp + 1ULL : disp) & 0xFFFF; + break; + case 4: + normDisp = ((disp & 0x80000000) ? ~disp + 1ULL : disp) & 0xFFFFFFFF; + break; + default: + normDisp = disp; + break; + } + + // Handle compressed displacement. It is fine to cast the normDisp to uint32_t, as the + // compressed displacement only works with uint8_t displacements. Also, in this phase, + // the normDisp is converted to a positive quantity, so no sign-extension is needed. + if (pOp->Info.Memory.HasCompDisp) + { + normDisp = (uint64_t)(uint32_t)normDisp * pOp->Info.Memory.CompDispSize; + } + } + + + // Now displacement. + if (pOp->Info.Memory.HasBase || pOp->Info.Memory.HasIndex) + { + res = nd_strcat_s(Buffer, BufferSize, Instrux->SignDisp ? "-" : "+"); + RET_EQ(res, NULL, ND_STATUS_BUFFER_OVERFLOW); + } + + if (pOp->Info.Memory.IsRipRel) + { + uint64_t target = disp + Rip + Instrux->Length; + + if (Instrux->AddrMode == ND_ADDR_32) + { + target &= 0xFFFFFFFF; + } + + status = NdSprintf(temp, sizeof(temp), "rel 0x%llx", target); + } + else + { + uint8_t trimSize; + + trimSize = (Instrux->AddrMode == ND_ADDR_16) ? 2 : ((Instrux->AddrMode == ND_ADDR_32) ? 4 : 8); + + // Truncate the displacement size to the size of the address length. + normDisp = ND_TRIM(trimSize, normDisp); + + status = NdSprintf(temp, sizeof(temp), "0x%llx", normDisp); + } + if (!ND_SUCCESS(status)) + { + return status; + } + + res = nd_strcat_s(Buffer, BufferSize, temp); + RET_EQ(res, NULL, ND_STATUS_BUFFER_OVERFLOW); + } + + // And the ending "]" + res = nd_strcat_s(Buffer, BufferSize, "]"); + RET_EQ(res, NULL, ND_STATUS_BUFFER_OVERFLOW); + } + break; + + default: + return ND_STATUS_INVALID_INSTRUX; + } + + // Handle memory broadcast. + if (pOp->Decorator.HasBroadcast) + { + status = NdSprintf(temp, sizeof(temp), "{1to%d}", pOp->Decorator.Broadcast.Count); + if (!ND_SUCCESS(status)) + { + return status; + } + + res = nd_strcat_s(Buffer, BufferSize, temp); + RET_EQ(res, NULL, ND_STATUS_BUFFER_OVERFLOW); + } + + // Handle masking. + if (pOp->Decorator.HasMask) + { + if (pOp->Decorator.Mask.Msk >= ND_MAX_MSK_REGS) + { + return ND_STATUS_INVALID_INSTRUX; + } + + status = NdSprintf(temp, sizeof(temp), "{%s}", gRegMask[pOp->Decorator.Mask.Msk]); + if (!ND_SUCCESS(status)) + { + return status; + } + + res = nd_strcat_s(Buffer, BufferSize, temp); + RET_EQ(res, NULL, ND_STATUS_BUFFER_OVERFLOW); + } + + // Handle zeroing. Note that zeroing without masking is ignored. + if (pOp->Decorator.HasZero && pOp->Decorator.HasMask) + { + res = nd_strcat_s(Buffer, BufferSize, "{z}"); + RET_EQ(res, NULL, ND_STATUS_BUFFER_OVERFLOW); + } + + // Append Suppress All Exceptions decorator. + if (pOp->Decorator.HasSae && !pOp->Decorator.HasEr) + { + // ER implies SAE, so if we have ER, we will list that. + res = nd_strcat_s(Buffer, BufferSize, ", {sae}"); + RET_EQ(res, NULL, ND_STATUS_BUFFER_OVERFLOW); + } + + // Append Embedded Rounding decorator. + if (pOp->Decorator.HasEr) + { + if (Instrux->RoundingMode >= 4) + { + return ND_STATUS_INVALID_INSTRUX; + } + + status = NdSprintf(temp, sizeof(temp), ", {%s-sae}", gEmbeddedRounding[Instrux->RoundingMode]); + if (!ND_SUCCESS(status)) + { + return status; + } + + res = nd_strcat_s(Buffer, BufferSize, temp); + RET_EQ(res, NULL, ND_STATUS_BUFFER_OVERFLOW); + } + } + + return ND_STATUS_SUCCESS; +} +#else +NDSTATUS +NdToText( + const INSTRUX *Instrux, + uint64_t Rip, + uint32_t BufferSize, + char *Buffer + ) +{ + UNREFERENCED_PARAMETER(Instrux); + UNREFERENCED_PARAMETER(Rip); + + // At least make sure the buffer is NULL-terminated so integrators can use NdToText without checking if the + // BDDISASM_NO_FORMAT macro is defined. This makes switching between versions with formatting and versions without + // formatting easier. + if (Buffer != NULL && BufferSize >= 1) + { + *Buffer = '\0'; + } + + return ND_STATUS_SUCCESS; +} +#endif // !BDDISASM_NO_FORMAT diff --git a/bddisasm/include/nd_crt.h b/bddisasm/include/nd_crt.h index da38ef8..b1281cd 100644 --- a/bddisasm/include/nd_crt.h +++ b/bddisasm/include/nd_crt.h @@ -90,4 +90,11 @@ extern void *nd_memset(void *s, int c, size_t n); #define nd_memzero(Dest, Size) nd_memset((Dest), 0, (Size)) + +// Handy macros. +#define RET_EQ(x, y, z) if ((x) == (y)) { return (z); } +#define RET_GE(x, y, z) if ((x) >= (y)) { return (z); } +#define RET_GT(x, y, z) if ((x) > (y)) { return (z); } + + #endif // ND_CRT_H diff --git a/bdshemu/bdshemu.c b/bdshemu/bdshemu.c index 2de47b0..ef89ca2 100644 --- a/bdshemu/bdshemu.c +++ b/bdshemu/bdshemu.c @@ -1693,8 +1693,18 @@ ShemuPrintContext( Context->Registers.RegR8, Context->Registers.RegR9, Context->Registers.RegR10, Context->Registers.RegR11); shemu_printf(Context, " R12 = 0x%016llx R13 = 0x%016llx R14 = 0x%016llx R15 = 0x%016llx\n", Context->Registers.RegR12, Context->Registers.RegR13, Context->Registers.RegR14, Context->Registers.RegR15); - shemu_printf(Context, " RIP = 0x%016llx RFLAGS = 0x%016llx\n", + shemu_printf(Context, " RIP = 0x%016llx RFLAGS = 0x%016llx ", Context->Registers.RegRip, Context->Registers.RegFlags); + shemu_printf(Context, " CF:%d PF:%d AF:%d ZF:%d SF:%d TF:%d IF:%d DF:%d OF:%d\n", + GET_FLAG(Context, NDR_RFLAG_CF), + GET_FLAG(Context, NDR_RFLAG_PF), + GET_FLAG(Context, NDR_RFLAG_AF), + GET_FLAG(Context, NDR_RFLAG_ZF), + GET_FLAG(Context, NDR_RFLAG_SF), + GET_FLAG(Context, NDR_RFLAG_TF), + GET_FLAG(Context, NDR_RFLAG_IF), + GET_FLAG(Context, NDR_RFLAG_DF), + GET_FLAG(Context, NDR_RFLAG_OF)); shemu_printf(Context, "Emulating: 0x%016llx %s\n", Context->Registers.RegRip, text); } @@ -1711,6 +1721,7 @@ ShemuEmulate( SHEMU_VALUE res = { 0 }, dst = { 0 }, src = { 0 }, rcx = { 0 }, aux = { 0 }; bool stop = false, cf; uint16_t cs = 0; + uint64_t tsc = 0x1248fe7a5c30; if (NULL == Context) { @@ -1753,6 +1764,8 @@ ShemuEmulate( uint64_t rip; uint32_t i; + tsc++; + // Reset all the operands to 0. nd_memzero(&dst, sizeof(dst)); nd_memzero(&src, sizeof(src)); @@ -3058,6 +3071,17 @@ check_far_branch: stop = true; break; + case ND_INS_SIDT: + if (Context->Ring == 0) + { + // Flag this only in ring0, as we treat the SHEMU_FLAG_SIDT as a ring0 specific indicator - it can be + // used to locate the kernel image. + Context->Flags |= SHEMU_FLAG_SIDT; + } + + stop = true; + break; + case ND_INS_AESIMC: case ND_INS_AESDEC: case ND_INS_AESDECLAST: @@ -3096,6 +3120,16 @@ check_far_branch: break; } + case ND_INS_RDTSC: + src.Size = 4; + // Set EAX to lower 32 bits. + src.Value.Dwords[0] = tsc & 0xFFFFFFFF; + SET_OP(Context, 0, &src); + // Set EDX to upper 32 bits. + src.Value.Dwords[0] = tsc >> 32; + SET_OP(Context, 1, &src); + break; + default: return SHEMU_ABORT_UNSUPPORTED_INSTRUX; diff --git a/bdshemu_test/bdshemu_test.zip b/bdshemu_test/bdshemu_test.zip index 5ed1f788ad213275f9f0534e0cdec72c2776f8ea..31cdd817ca3ee35735faf77341fe015399dc2dba 100644 GIT binary patch literal 74758 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