DisasmCore.cpp revision 571c90a734400801da973f986190fac9fc5efd0d
84f746c9015f34e9ab096b87e063d0d6ab7fc7aevboxsync * VBox disassembler:
84f746c9015f34e9ab096b87e063d0d6ab7fc7aevboxsync * Core components
84f746c9015f34e9ab096b87e063d0d6ab7fc7aevboxsync * Copyright (C) 2006-2007 Sun Microsystems, Inc.
84f746c9015f34e9ab096b87e063d0d6ab7fc7aevboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
84f746c9015f34e9ab096b87e063d0d6ab7fc7aevboxsync * available from http://www.virtualbox.org. This file is free software;
84f746c9015f34e9ab096b87e063d0d6ab7fc7aevboxsync * you can redistribute it and/or modify it under the terms of the GNU
84f746c9015f34e9ab096b87e063d0d6ab7fc7aevboxsync * General Public License (GPL) as published by the Free Software
84f746c9015f34e9ab096b87e063d0d6ab7fc7aevboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
84f746c9015f34e9ab096b87e063d0d6ab7fc7aevboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
84f746c9015f34e9ab096b87e063d0d6ab7fc7aevboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
84f746c9015f34e9ab096b87e063d0d6ab7fc7aevboxsync * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
84f746c9015f34e9ab096b87e063d0d6ab7fc7aevboxsync * Clara, CA 95054 USA or visit http://www.sun.com if you need
84f746c9015f34e9ab096b87e063d0d6ab7fc7aevboxsync * additional information or have any questions.
84f746c9015f34e9ab096b87e063d0d6ab7fc7aevboxsync/*******************************************************************************
84f746c9015f34e9ab096b87e063d0d6ab7fc7aevboxsync* Header Files *
84f746c9015f34e9ab096b87e063d0d6ab7fc7aevboxsync*******************************************************************************/
84f746c9015f34e9ab096b87e063d0d6ab7fc7aevboxsync/*******************************************************************************
9b456547aefb8a2e8f5600eba9ec377dbc9b4475vboxsync* Internal Functions *
84f746c9015f34e9ab096b87e063d0d6ab7fc7aevboxsync*******************************************************************************/
9b456547aefb8a2e8f5600eba9ec377dbc9b4475vboxsyncstatic int disCoreOne(PDISCPUSTATE pCpu, RTUINTPTR InstructionAddr, unsigned *pcbInstruction);
9b456547aefb8a2e8f5600eba9ec377dbc9b4475vboxsyncstatic void disasmAddString(char *psz, const char *pszString);
84f746c9015f34e9ab096b87e063d0d6ab7fc7aevboxsyncstatic void disasmAddStringF(char *psz, uint32_t cbString, const char *pszFormat, ...);
9b456547aefb8a2e8f5600eba9ec377dbc9b4475vboxsync# define disasmAddString(psz, pszString) do {} while (0)
84f746c9015f34e9ab096b87e063d0d6ab7fc7aevboxsync# define disasmAddStringF(psz, cbString, pszFormat...) do {} while (0) /* Arg wanna get rid of that warning */
9b456547aefb8a2e8f5600eba9ec377dbc9b4475vboxsyncstatic unsigned QueryModRM(RTUINTPTR pu8CodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu, unsigned *pSibInc = NULL);
84f746c9015f34e9ab096b87e063d0d6ab7fc7aevboxsyncstatic unsigned QueryModRM_SizeOnly(RTUINTPTR pu8CodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu, unsigned *pSibInc = NULL);
84f746c9015f34e9ab096b87e063d0d6ab7fc7aevboxsyncstatic void UseSIB(RTUINTPTR pu8CodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu);
84f746c9015f34e9ab096b87e063d0d6ab7fc7aevboxsyncstatic unsigned ParseSIB_SizeOnly(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu);
84f746c9015f34e9ab096b87e063d0d6ab7fc7aevboxsync/*******************************************************************************
84f746c9015f34e9ab096b87e063d0d6ab7fc7aevboxsync* Global Variables *
84f746c9015f34e9ab096b87e063d0d6ab7fc7aevboxsync*******************************************************************************/
84f746c9015f34e9ab096b87e063d0d6ab7fc7aevboxsync * Parses one instruction.
84f746c9015f34e9ab096b87e063d0d6ab7fc7aevboxsync * The result is found in pCpu.
84f746c9015f34e9ab096b87e063d0d6ab7fc7aevboxsync * @returns Success indicator.
9b456547aefb8a2e8f5600eba9ec377dbc9b4475vboxsync * @param pCpu Pointer to cpu structure which has DISCPUSTATE::mode set correctly.
9b456547aefb8a2e8f5600eba9ec377dbc9b4475vboxsync * @param InstructionAddr Pointer to the instruction to parse.
84f746c9015f34e9ab096b87e063d0d6ab7fc7aevboxsync * @param pcbInstruction Where to store the size of the instruction.
9b456547aefb8a2e8f5600eba9ec377dbc9b4475vboxsync * NULL is allowed.
84f746c9015f34e9ab096b87e063d0d6ab7fc7aevboxsyncDISDECL(int) DISCoreOne(PDISCPUSTATE pCpu, RTUINTPTR InstructionAddr, unsigned *pcbInstruction)
84f746c9015f34e9ab096b87e063d0d6ab7fc7aevboxsync * Reset instruction settings
9b456547aefb8a2e8f5600eba9ec377dbc9b4475vboxsync return RT_SUCCESS(disCoreOne(pCpu, InstructionAddr, pcbInstruction));
9b456547aefb8a2e8f5600eba9ec377dbc9b4475vboxsync * Parses one guest instruction.
9b456547aefb8a2e8f5600eba9ec377dbc9b4475vboxsync * The result is found in pCpu and pcbInstruction.
9b456547aefb8a2e8f5600eba9ec377dbc9b4475vboxsync * @returns VBox status code.
9b456547aefb8a2e8f5600eba9ec377dbc9b4475vboxsync * @param InstructionAddr Address of the instruction to decode. What this means
9b456547aefb8a2e8f5600eba9ec377dbc9b4475vboxsync * is left to the pfnReadBytes function.
9b456547aefb8a2e8f5600eba9ec377dbc9b4475vboxsync * @param enmCpuMode The CPU mode. CPUMODE_32BIT, CPUMODE_16BIT, or CPUMODE_64BIT.
9b456547aefb8a2e8f5600eba9ec377dbc9b4475vboxsync * @param pfnReadBytes Callback for reading instruction bytes.
9b456547aefb8a2e8f5600eba9ec377dbc9b4475vboxsync * @param pvUser User argument for the instruction reader. (Ends up in apvUserData[0].)
9b456547aefb8a2e8f5600eba9ec377dbc9b4475vboxsync * @param pCpu Pointer to cpu structure. Will be initialized.
9b456547aefb8a2e8f5600eba9ec377dbc9b4475vboxsync * @param pcbInstruction Where to store the size of the instruction.
9b456547aefb8a2e8f5600eba9ec377dbc9b4475vboxsync * NULL is allowed.
9b456547aefb8a2e8f5600eba9ec377dbc9b4475vboxsyncDISDECL(int) DISCoreOneEx(RTUINTPTR InstructionAddr, DISCPUMODE enmCpuMode, PFN_DIS_READBYTES pfnReadBytes, void *pvUser,
9b456547aefb8a2e8f5600eba9ec377dbc9b4475vboxsync * Reset instruction settings
unsigned iByte = 0;
unsigned cbInc;
#ifdef IN_RING3
switch (opcode)
case OP_INVALID:
case OP_SEG:
case OP_LOCK:
case OP_ADDRSIZE:
case OP_OPSIZE:
pCpu->opmode = CPUMODE_16BIT; /* for 32 and 64 bits mode (there is no 32 bits operand size override prefix) */
case OP_REPE:
case OP_REPNE:
case OP_REX:
#ifdef IN_RING3
# ifndef __L4ENV__
return VERR_DIS_GEN_FAILURE;
if (pcbInstruction)
return VINF_SUCCESS;
int size = 0;
bool fFiltered = false;
#ifndef DIS_CORE_ONLY
fFiltered = true;
return size;
int index;
#ifndef DIS_CORE_ONLY
return size;
static const char *szSIBBaseReg64[16] = {"RAX", "RCX", "RDX", "RBX", "RSP", "RBP", "RSI", "RDI", "R8", "R9", "R10", "R11", "R12", "R13", "R14", "R15"};
static const char *szSIBIndexReg64[16]= {"RAX", "RCX", "RDX", "RBX", NULL, "RBP", "RSI", "RDI", "R8", "R9", "R10", "R11", "R12", "R13", "R14", "R15"};
const char **ppszSIBIndexReg;
const char **ppszSIBBaseReg;
if (scale != 0)
disasmAddStringF(szTemp, sizeof(szTemp), "%s+%s%s", ppszSIBBaseReg[base], ppszSIBIndexReg[index], szSIBScale[scale]);
unsigned SIB;
return size;
unsigned ParseSIB_SizeOnly(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
unsigned SIB;
return size;
switch (vtype)
switch (vtype)
switch (mod)
switch (mod)
unsigned QueryModRM(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu, unsigned *pSibInc)
unsigned sibinc;
unsigned size = 0;
if (!pSibInc)
*pSibInc = 0;
switch (mod)
size += sizeof(char);
switch (mod)
size += sizeof(char);
return size;
unsigned QueryModRM_SizeOnly(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu, unsigned *pSibInc)
unsigned sibinc;
unsigned size = 0;
if (!pSibInc)
*pSibInc = 0;
switch (mod)
size += sizeof(char);
switch (mod)
size += sizeof(char);
return size;
unsigned ParseIllegal(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
AssertFailed();
return size;
unsigned ParseModRM_SizeOnly(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
return size;
unsigned ParseModFence(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
unsigned ParseImmByte(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
return sizeof(uint8_t);
unsigned ParseImmByte_SizeOnly(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
return sizeof(uint8_t);
unsigned ParseImmByteSX(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
return sizeof(uint8_t);
unsigned ParseImmByteSX_SizeOnly(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
return sizeof(uint8_t);
unsigned ParseImmUshort(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
return sizeof(uint16_t);
unsigned ParseImmUshort_SizeOnly(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
return sizeof(uint16_t);
unsigned ParseImmUlong(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
return sizeof(uint32_t);
unsigned ParseImmUlong_SizeOnly(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
return sizeof(uint32_t);
unsigned ParseImmQword(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
disasmAddStringF(&pParam->szParam[9], sizeof(pParam->szParam)-9, "%08Xh", (uint32_t)(pParam->parval >> 32));
return sizeof(uint64_t);
unsigned ParseImmQword_SizeOnly(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
return sizeof(uint64_t);
return sizeof(uint32_t);
return sizeof(uint64_t);
return sizeof(uint16_t);
unsigned ParseImmV_SizeOnly(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
return sizeof(uint32_t);
return sizeof(uint64_t);
return sizeof(uint16_t);
return sizeof(uint16_t);
return sizeof(uint32_t);
unsigned ParseImmZ_SizeOnly(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
return sizeof(uint16_t);
return sizeof(uint32_t);
unsigned ParseImmBRel(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
unsigned ParseImmBRel_SizeOnly(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
unsigned ParseImmVRel(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
return sizeof(int32_t);
return sizeof(int32_t);
return sizeof(int16_t);
unsigned ParseImmVRel_SizeOnly(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
return sizeof(int16_t);
return sizeof(int32_t);
unsigned ParseImmAddr(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), "0%04X:0%08Xh", (uint32_t)(pParam->parval>>32), (uint32_t)pParam->parval);
return sizeof(uint32_t);
disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), "[0%08X%08Xh]", (uint32_t)(pParam->disp64 >> 32), (uint32_t)pParam->disp64);
return sizeof(uint64_t);
disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), "0%04X:0%04Xh", (uint32_t)(pParam->parval>>16), (uint16_t)pParam->parval );
return sizeof(uint32_t);
return sizeof(uint16_t);
unsigned ParseImmAddr_SizeOnly(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
return sizeof(uint32_t);
return sizeof(uint64_t);
return sizeof(uint32_t);
return sizeof(uint16_t);
unsigned ParseFixedReg(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), (pCpu->addrmode == CPUMODE_32BIT) ? "DS:ESI" : "DS:SI");
disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), (pCpu->addrmode == CPUMODE_32BIT) ? "DS:ESI" : "DS:SI");
disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), (pCpu->addrmode == CPUMODE_32BIT) ? "ES:EDI" : "ES:DI");
disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), (pCpu->addrmode == CPUMODE_32BIT) ? "ES:EDI" : "ES:DI");
unsigned ParseTwoByteEsc(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
return size;
unsigned ParseThreeByteEsc4(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
return size;
unsigned ParseThreeByteEsc5(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
return size;
unsigned ParseNopPause(RTUINTPTR pu8CodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
unsigned size = 0;
return size;
unsigned ParseImmGrpl(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
return size;
unsigned ParseShiftGrp2(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
int idx;
return sizeof(uint8_t);
return size;
return size;
return size;
return size;
#ifdef DEBUG_Sander
#ifdef DEBUG_Sander /* bird, 2005-06-28: Alex is getting this during full installation of win2ksp4. */
return size;
return size;
return size;
return size;
return size;
return size;
return size;
return size;
return size;
return size;
return size;
static const char *szModRMReg8[] = {"AL", "CL", "DL", "BL", "AH", "CH", "DH", "BH", "R8B", "R9B", "R10B", "R11B", "R12B", "R13B", "R14B", "R15B", "SPL", "BPL", "SIL", "DIL"};
static const char *szModRMReg16[] = {"AX", "CX", "DX", "BX", "SP", "BP", "SI", "DI", "R8W", "R9W", "R10W", "R11W", "R12W", "R13W", "R14W", "R15W"};
static const char *szModRMReg32[] = {"EAX", "ECX", "EDX", "EBX", "ESP", "EBP", "ESI", "EDI", "R8D", "R9D", "R10D", "R11D", "R12D", "R13D", "R14D", "R15D"};
static const char *szModRMReg64[] = {"RAX", "RCX", "RDX", "RBX", "RSP", "RBP", "RSI", "RDI", "R8", "R9", "R10", "R11", "R12", "R13", "R14", "R15"};
static const char *szModRMReg1616[8] = {"BX+SI", "BX+DI", "BP+SI", "BP+DI", "SI", "DI", "BP", "BX"};
static const int BaseModRMReg16[8] = { USE_REG_BX, USE_REG_BX, USE_REG_BP, USE_REG_BP, USE_REG_SI, USE_REG_DI, USE_REG_BP, USE_REG_BX};
void disasmModRMReg(PDISCPUSTATE pCpu, PCOPCODE pOp, unsigned idx, POP_PARAMETER pParam, int fRegAddr)
if (fRegAddr)
case CPUMODE_32BIT:
case CPUMODE_64BIT:
case CPUMODE_16BIT:
switch (subtype)
case OP_PARM_b:
case OP_PARM_w:
case OP_PARM_d:
case OP_PARM_q:
#ifdef IN_RING3
#ifdef IN_RING3
case CPUMODE_32BIT:
case CPUMODE_64BIT:
case CPUMODE_16BIT:
switch (subtype)
case OP_PARM_b:
case OP_PARM_w:
case OP_PARM_d:
case OP_PARM_q:
case OP_PARM_dq:
case OP_PARM_p:
case OP_PARM_s:
case OP_PARM_z:
disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), "%s:", szModRMSegReg[pCpu->enmPrefixSeg]);
#ifndef IN_RC
int rc;
return temp;
#ifdef IN_RING0
int rc;
return temp;
#ifdef IN_RING0
int rc;
return temp;
#ifdef IN_RING0
int rc;
return temp;
#ifdef IN_RING0
case OP_BTC:
case OP_BTR:
case OP_BTS:
case OP_CMPXCHG:
case OP_XADD:
case OP_ADC:
case OP_ADD:
case OP_AND:
case OP_DEC:
case OP_INC:
case OP_NEG:
case OP_NOT:
case OP_OR:
case OP_SBB:
case OP_SUB:
case OP_XCHG:
case OP_XOR:
if (pCpu->param1.flags & (USE_BASE | USE_INDEX | USE_DISPLACEMENT64 | USE_DISPLACEMENT32 | USE_DISPLACEMENT16 | USE_DISPLACEMENT8 | USE_RIPDISPLACEMENT32))