Disasm.cpp revision 8e0e890db9d2c1d2de5e8b6a7b3f5ca706070ec5
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync * VBox disassembler:
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync * Copyright (C) 2006-2007 Sun Microsystems, Inc.
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync * available from http://www.virtualbox.org. This file is free software;
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync * you can redistribute it and/or modify it under the terms of the GNU
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync * General Public License (GPL) as published by the Free Software
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync * Clara, CA 95054 USA or visit http://www.sun.com if you need
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync * additional information or have any questions.
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync/*******************************************************************************
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync* Header Files *
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync*******************************************************************************/
35d8d2372afb180daa0ba01af33a1922511d6b07vboxsync * Disassembles a code block.
d5bf937d132098565e18a0d1fc408fb777c5e5b6vboxsync * @returns VBox error code
d5bf937d132098565e18a0d1fc408fb777c5e5b6vboxsync * @param pCpu Pointer to cpu structure which have DISCPUSTATE::mode
d5bf937d132098565e18a0d1fc408fb777c5e5b6vboxsync * set correctly.
d5bf937d132098565e18a0d1fc408fb777c5e5b6vboxsync * @param pvCodeBlock Pointer to the strunction to disassemble.
d5bf937d132098565e18a0d1fc408fb777c5e5b6vboxsync * @param cbMax Maximum number of bytes to disassemble.
d5bf937d132098565e18a0d1fc408fb777c5e5b6vboxsync * @param pcbSize Where to store the size of the instruction.
f7c0f913c4c22ee18059ff97055442566d0f14a1vboxsync * NULL is allowed.
f7c0f913c4c22ee18059ff97055442566d0f14a1vboxsync * @todo Define output callback.
f7c0f913c4c22ee18059ff97055442566d0f14a1vboxsync * @todo Using signed integers as sizes is a bit odd. There are still
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync * some GCC warnings about mixing signed and unsigend integers.
eeb2d581c99b451fb1a26a5870af65981dc9cd5dvboxsync * @todo Need to extend this interface to include a code address so we
f32de6c198a491c28ace2b4c53f8d04a79fd6d69vboxsync * can dissassemble GC code. Perhaps a new function is better...
f32de6c198a491c28ace2b4c53f8d04a79fd6d69vboxsync * @remark cbMax isn't respected as a boundry. DISInstr() will read beyond cbMax.
0ce6ae9d6efed5d54222a13bbdabce9e688e4447vboxsync * This means *pcbSize >= cbMax sometimes.
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsyncDISDECL(int) DISBlock(PDISCPUSTATE pCpu, RTUINTPTR pvCodeBlock, unsigned cbMax, unsigned *pSize)
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync unsigned i = 0;
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync int rc = DISInstr(pCpu, pvCodeBlock + i, 0, &cbInstr, szOutput);
f2490dbf97c8247439446844458461b00e50beb0vboxsync return true;
f2490dbf97c8247439446844458461b00e50beb0vboxsync * Disassembles one instruction
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync * @returns VBox error code
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync * @param pCpu Pointer to cpu structure which have DISCPUSTATE::mode
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync * set correctly.
e52c9984c4f6b8ea141bc50a3bdaf31941d8cd7dvboxsync * @param pu8Instruction Pointer to the strunction to disassemble.
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync * @param u32EipOffset Offset to add to instruction address to get the real virtual address
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync * @param pcbSize Where to store the size of the instruction.
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync * NULL is allowed.
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync * @param pszOutput Storage for disassembled instruction
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync * @todo Define output callback.
f6dde23cd488aee26203b38ec67220270f5c4273vboxsyncDISDECL(int) DISInstr(PDISCPUSTATE pCpu, RTUINTPTR pu8Instruction, unsigned u32EipOffset, unsigned *pcbSize,
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync return DISInstrEx(pCpu, pu8Instruction, u32EipOffset, pcbSize, pszOutput, OPTYPE_ALL);
e52c9984c4f6b8ea141bc50a3bdaf31941d8cd7dvboxsync * Disassembles one instruction; only fully disassembly an instruction if it matches the filter criteria
dc311b529996345ea65d51c87b60b6849642d894vboxsync * @returns VBox error code
0a3eb63419e41ef10cd135aeb66dcd6bd6f87cdcvboxsync * @param pCpu Pointer to cpu structure which have DISCPUSTATE::mode
dc311b529996345ea65d51c87b60b6849642d894vboxsync * set correctly.
c4d6c81bd0de216d0f42db2e477b1d788fbaefb4vboxsync * @param pu8Instruction Pointer to the strunction to disassemble.
c4d6c81bd0de216d0f42db2e477b1d788fbaefb4vboxsync * @param u32EipOffset Offset to add to instruction address to get the real virtual address
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync * @param pcbSize Where to store the size of the instruction.
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync * NULL is allowed.
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync * @param pszOutput Storage for disassembled instruction
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync * @param uFilter Instruction type filter
d19316699d7f91959d88c850fd7e0d64840f39a7vboxsync * @todo Define output callback.
d020036eb167a2f97f5010276fda5daa3f4773b3vboxsyncDISDECL(int) DISInstrEx(PDISCPUSTATE pCpu, RTUINTPTR pu8Instruction, unsigned u32EipOffset, unsigned *pcbSize,
25c5ce7baf4b227ea80250c46d427d0e9fdab4c1vboxsync unsigned i = 0, prefixbytes;
a96ed55e8e1b248965a3d29d6e4c3116979e887bvboxsync //reset instruction settings
21293ca6a2967f796ed30a6c8492911619476a48vboxsync#ifndef __L4ENV__ /* Unfortunately, we have no exception handling in l4env */
d20e5d189feff7841cc3f40e5c9cca8c86b45eb5vboxsync uint8_t codebyte = DISReadByte(pCpu, pu8Instruction+i);
f2490dbf97c8247439446844458461b00e50beb0vboxsync /* Hardcoded assumption about OP_* values!! */
f2490dbf97c8247439446844458461b00e50beb0vboxsync /* The REX prefix must precede the opcode byte(s). Any other placement is ignored. */
4831e82ecaa3c813398d2f343e9d38ee34a3acf4vboxsync#if 0 //defined (DEBUG_Sander)
50453af238fcec34bf98f91cc4c32bf57f738bd3vboxsync // segment override prefix byte
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync pCpu->enmPrefixSeg = (DIS_SELREG)(paOneByteMap[codebyte].param1 - OP_PARM_REG_SEG_START);
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync /* Segment prefixes for CS, DS, ES and SS are ignored in long mode. */
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync i += sizeof(uint8_t);
c4d6c81bd0de216d0f42db2e477b1d788fbaefb4vboxsync continue; //fetch the next byte
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync // lock prefix byte
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync i += sizeof(uint8_t);
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync continue; //fetch the next byte
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync // address size override prefix byte
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync i += sizeof(uint8_t);
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync continue; //fetch the next byte
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync // operand size override prefix byte
f6dde23cd488aee26203b38ec67220270f5c4273vboxsync pCpu->opmode = CPUMODE_16BIT; /* for 32 and 64 bits mode (there is no 32 bits operand size override prefix) */
40becad9511726726c5959a8ad8b62fb3e1c020cvboxsync i += sizeof(uint8_t);
43e9355f77c0463e7ace350984bb5a09fb8c50a1vboxsync continue; //fetch the next byte
d07e901177d22a8f66c66f155c423a524ac07776vboxsync // rep and repne are not really prefixes, but we'll treat them as such
d07e901177d22a8f66c66f155c423a524ac07776vboxsync i += sizeof(uint8_t);
d07e901177d22a8f66c66f155c423a524ac07776vboxsync continue; //fetch the next byte
f48fe310f85f13db0140bef980de1f56c2007957vboxsync i += sizeof(uint8_t);
1b186b95b77faa977d3651bbfc13afb3f13e0225vboxsync continue; //fetch the next byte
d4f7483a46e1c44ae5fcc4195be291545ae720a4vboxsync /* REX prefix byte */
d4f7483a46e1c44ae5fcc4195be291545ae720a4vboxsync pCpu->prefix_rex = PREFIX_REX_OP_2_FLAGS(paOneByteMap[codebyte].param1);
d4f7483a46e1c44ae5fcc4195be291545ae720a4vboxsync i += sizeof(uint8_t);
4831e82ecaa3c813398d2f343e9d38ee34a3acf4vboxsync pCpu->opmode = CPUMODE_64BIT; /* overrides size prefix byte */
d91dc86210d602f51a4701762488a5e696c80a45vboxsync continue; //fetch the next byte
f7c0f913c4c22ee18059ff97055442566d0f14a1vboxsync /* Prefix byte(s) is/are part of the instruction. */
f7c0f913c4c22ee18059ff97055442566d0f14a1vboxsync pCpu->opaddr = pu8Instruction + idx + u32EipOffset - prefixbytes;
db85b6b8ce514217c1fb35d04b0854a65dc299f3vboxsync inc = ParseInstruction(pu8Instruction + i, &paOneByteMap[pCpu->opcode], pCpu);
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync pCpu->opsize = prefixbytes + inc + sizeof(uint8_t);
3221ae1f7bf53d9cccdd578099f55f782dba1447vboxsync disasmSprintf(pszOutput, pu8Instruction+i-1-prefixbytes, pCpu, &pCpu->param1, &pCpu->param2, &pCpu->param3);
#ifndef __L4ENV__
if (pcbSize)
*pcbSize = 0;
return VERR_DIS_GEN_FAILURE;
if (pcbSize)
*pcbSize = i;
return VINF_SUCCESS;
for(i = 0; i < size; i++)
return pszOutput;
void disasmSprintf(char *pszOutput, RTUINTPTR pu8Instruction, PDISCPUSTATE pCpu, OP_PARAMETER *pParam1, OP_PARAMETER *pParam2, OP_PARAMETER *pParam3)
RTStrPrintf(&pszOutput[strlen(pszOutput)], 64, "Invalid Opcode [%02X][%02X]", DISReadByte(pCpu, pu8Instruction), DISReadByte(pCpu, pu8Instruction+1) );
while(*lpszFormat)
switch(*lpszFormat)
switch(param)
param++;