Disasm.cpp revision 8e0e890db9d2c1d2de5e8b6a7b3f5ca706070ec5
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync/** @file
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync *
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync * VBox disassembler:
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync * Main
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync */
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync/*
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync * Copyright (C) 2006-2007 Sun Microsystems, Inc.
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync *
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 *
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
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync/*******************************************************************************
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync* Header Files *
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync*******************************************************************************/
b8ae33177906f4130b85b7c861cae0e78ed4859bvboxsync#ifdef USING_VISUAL_STUDIO
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync# include <stdafx.h>
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync#endif
b8ae33177906f4130b85b7c861cae0e78ed4859bvboxsync#include <VBox/dis.h>
50453af238fcec34bf98f91cc4c32bf57f738bd3vboxsync#include <VBox/disopcode.h>
f2490dbf97c8247439446844458461b00e50beb0vboxsync#include <VBox/err.h>
35d8d2372afb180daa0ba01af33a1922511d6b07vboxsync#include <iprt/assert.h>
482a222498aae619afda0255a7edf4ebda97268cvboxsync#include <iprt/string.h>
d5bf937d132098565e18a0d1fc408fb777c5e5b6vboxsync#include "DisasmInternal.h"
d5bf937d132098565e18a0d1fc408fb777c5e5b6vboxsync#include "DisasmTables.h"
d5bf937d132098565e18a0d1fc408fb777c5e5b6vboxsync
21293ca6a2967f796ed30a6c8492911619476a48vboxsync
d5bf937d132098565e18a0d1fc408fb777c5e5b6vboxsync/**
35d8d2372afb180daa0ba01af33a1922511d6b07vboxsync * Disassembles a code block.
d5bf937d132098565e18a0d1fc408fb777c5e5b6vboxsync *
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 *
f7c0f913c4c22ee18059ff97055442566d0f14a1vboxsync *
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.
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync */
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsyncDISDECL(int) DISBlock(PDISCPUSTATE pCpu, RTUINTPTR pvCodeBlock, unsigned cbMax, unsigned *pSize)
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync{
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync unsigned i = 0;
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync char szOutput[256];
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync while (i < cbMax)
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync {
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync unsigned cbInstr;
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync int rc = DISInstr(pCpu, pvCodeBlock + i, 0, &cbInstr, szOutput);
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync if (RT_FAILURE(rc))
57b49c1557a310ee615bc0ee79dd2a2e92319a1bvboxsync return rc;
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync i += cbInstr;
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync }
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync
f2490dbf97c8247439446844458461b00e50beb0vboxsync if (pSize)
f2490dbf97c8247439446844458461b00e50beb0vboxsync *pSize = i;
f2490dbf97c8247439446844458461b00e50beb0vboxsync return true;
f2490dbf97c8247439446844458461b00e50beb0vboxsync}
f2490dbf97c8247439446844458461b00e50beb0vboxsync
f2490dbf97c8247439446844458461b00e50beb0vboxsync/**
f2490dbf97c8247439446844458461b00e50beb0vboxsync * Disassembles one instruction
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync *
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 *
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync * @todo Define output callback.
ee5869bb73f07de9c139dc6a608836a7b5767933vboxsync */
f6dde23cd488aee26203b38ec67220270f5c4273vboxsyncDISDECL(int) DISInstr(PDISCPUSTATE pCpu, RTUINTPTR pu8Instruction, unsigned u32EipOffset, unsigned *pcbSize,
f6dde23cd488aee26203b38ec67220270f5c4273vboxsync char *pszOutput)
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync{
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync return DISInstrEx(pCpu, pu8Instruction, u32EipOffset, pcbSize, pszOutput, OPTYPE_ALL);
dc311b529996345ea65d51c87b60b6849642d894vboxsync}
b8ae33177906f4130b85b7c861cae0e78ed4859bvboxsync
ee5869bb73f07de9c139dc6a608836a7b5767933vboxsync/**
e52c9984c4f6b8ea141bc50a3bdaf31941d8cd7dvboxsync * Disassembles one instruction; only fully disassembly an instruction if it matches the filter criteria
dc311b529996345ea65d51c87b60b6849642d894vboxsync *
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
482a222498aae619afda0255a7edf4ebda97268cvboxsync *
d19316699d7f91959d88c850fd7e0d64840f39a7vboxsync * @todo Define output callback.
482a222498aae619afda0255a7edf4ebda97268cvboxsync */
d020036eb167a2f97f5010276fda5daa3f4773b3vboxsyncDISDECL(int) DISInstrEx(PDISCPUSTATE pCpu, RTUINTPTR pu8Instruction, unsigned u32EipOffset, unsigned *pcbSize,
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync char *pszOutput, unsigned uFilter)
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync{
25c5ce7baf4b227ea80250c46d427d0e9fdab4c1vboxsync unsigned i = 0, prefixbytes;
25c5ce7baf4b227ea80250c46d427d0e9fdab4c1vboxsync unsigned idx, inc;
d91dc86210d602f51a4701762488a5e696c80a45vboxsync const OPCODE *paOneByteMap;
d91dc86210d602f51a4701762488a5e696c80a45vboxsync#ifdef __L4ENV__
2c1d8cd8efdd4c486ff681135035d24111b03af8vboxsync jmp_buf jumpbuffer;
59d96bafa78f7257869e30b88f2f98142ef5928evboxsync#endif
c4d6c81bd0de216d0f42db2e477b1d788fbaefb4vboxsync
a96ed55e8e1b248965a3d29d6e4c3116979e887bvboxsync //reset instruction settings
35d8d2372afb180daa0ba01af33a1922511d6b07vboxsync pCpu->prefix = PREFIX_NONE;
35d8d2372afb180daa0ba01af33a1922511d6b07vboxsync pCpu->enmPrefixSeg = DIS_SELREG_DS;
35d8d2372afb180daa0ba01af33a1922511d6b07vboxsync pCpu->ModRM.u = 0;
35d8d2372afb180daa0ba01af33a1922511d6b07vboxsync pCpu->SIB.u = 0;
35d8d2372afb180daa0ba01af33a1922511d6b07vboxsync pCpu->lastprefix = 0;
b8ae33177906f4130b85b7c861cae0e78ed4859bvboxsync pCpu->param1.parval = 0;
b8ae33177906f4130b85b7c861cae0e78ed4859bvboxsync pCpu->param2.parval = 0;
b8ae33177906f4130b85b7c861cae0e78ed4859bvboxsync pCpu->param3.parval = 0;
b8ae33177906f4130b85b7c861cae0e78ed4859bvboxsync pCpu->param1.szParam[0] = 0;
7a2986a2fdd00cd130bcda05a53575fb58874754vboxsync pCpu->param2.szParam[0] = 0;
b8ae33177906f4130b85b7c861cae0e78ed4859bvboxsync pCpu->param3.szParam[0] = 0;
b8ae33177906f4130b85b7c861cae0e78ed4859bvboxsync pCpu->param1.size = 0;
b8ae33177906f4130b85b7c861cae0e78ed4859bvboxsync pCpu->param2.size = 0;
b8ae33177906f4130b85b7c861cae0e78ed4859bvboxsync pCpu->param3.size = 0;
6b9316bfe743cc7d2ee00d925f4ab455bc224e86vboxsync pCpu->param1.flags = 0;
b8ae33177906f4130b85b7c861cae0e78ed4859bvboxsync pCpu->param2.flags = 0;
6b9316bfe743cc7d2ee00d925f4ab455bc224e86vboxsync pCpu->param3.flags = 0;
6b9316bfe743cc7d2ee00d925f4ab455bc224e86vboxsync pCpu->uFilter = uFilter;
b8ae33177906f4130b85b7c861cae0e78ed4859bvboxsync pCpu->pfnDisasmFnTable = pfnFullDisasm;
d5bf937d132098565e18a0d1fc408fb777c5e5b6vboxsync
d76ca6cbea4e45aa218c74e33c784bde5e997ffcvboxsync if (pszOutput)
d76ca6cbea4e45aa218c74e33c784bde5e997ffcvboxsync *pszOutput = '\0';
d76ca6cbea4e45aa218c74e33c784bde5e997ffcvboxsync
d76ca6cbea4e45aa218c74e33c784bde5e997ffcvboxsync if (pCpu->mode == CPUMODE_64BIT)
d76ca6cbea4e45aa218c74e33c784bde5e997ffcvboxsync {
7a71f66d53a7dcdf19a7a357e99e560fda812dc3vboxsync paOneByteMap = g_aOneByteMapX64;
35d8d2372afb180daa0ba01af33a1922511d6b07vboxsync pCpu->addrmode = CPUMODE_64BIT;
7a71f66d53a7dcdf19a7a357e99e560fda812dc3vboxsync pCpu->opmode = CPUMODE_32BIT;
6b9316bfe743cc7d2ee00d925f4ab455bc224e86vboxsync }
35d8d2372afb180daa0ba01af33a1922511d6b07vboxsync else
21293ca6a2967f796ed30a6c8492911619476a48vboxsync {
35d8d2372afb180daa0ba01af33a1922511d6b07vboxsync paOneByteMap = g_aOneByteMapX86;
35d8d2372afb180daa0ba01af33a1922511d6b07vboxsync pCpu->addrmode = pCpu->mode;
35d8d2372afb180daa0ba01af33a1922511d6b07vboxsync pCpu->opmode = pCpu->mode;
35d8d2372afb180daa0ba01af33a1922511d6b07vboxsync }
21293ca6a2967f796ed30a6c8492911619476a48vboxsync
21293ca6a2967f796ed30a6c8492911619476a48vboxsync prefixbytes = 0;
21293ca6a2967f796ed30a6c8492911619476a48vboxsync#ifndef __L4ENV__ /* Unfortunately, we have no exception handling in l4env */
21293ca6a2967f796ed30a6c8492911619476a48vboxsync try
2c1d8cd8efdd4c486ff681135035d24111b03af8vboxsync#else
35d8d2372afb180daa0ba01af33a1922511d6b07vboxsync pCpu->pJumpBuffer = &jumpbuffer;
35d8d2372afb180daa0ba01af33a1922511d6b07vboxsync if (setjmp(jumpbuffer) == 0)
35d8d2372afb180daa0ba01af33a1922511d6b07vboxsync#endif
6b9316bfe743cc7d2ee00d925f4ab455bc224e86vboxsync {
7a71f66d53a7dcdf19a7a357e99e560fda812dc3vboxsync while(1)
f2490dbf97c8247439446844458461b00e50beb0vboxsync {
d20e5d189feff7841cc3f40e5c9cca8c86b45eb5vboxsync uint8_t codebyte = DISReadByte(pCpu, pu8Instruction+i);
f2490dbf97c8247439446844458461b00e50beb0vboxsync uint8_t opcode = paOneByteMap[codebyte].opcode;
f2490dbf97c8247439446844458461b00e50beb0vboxsync
f2490dbf97c8247439446844458461b00e50beb0vboxsync /* Hardcoded assumption about OP_* values!! */
f2490dbf97c8247439446844458461b00e50beb0vboxsync if (opcode <= OP_LAST_PREFIX)
f2490dbf97c8247439446844458461b00e50beb0vboxsync {
f2490dbf97c8247439446844458461b00e50beb0vboxsync /* The REX prefix must precede the opcode byte(s). Any other placement is ignored. */
6b9316bfe743cc7d2ee00d925f4ab455bc224e86vboxsync if (opcode != OP_REX)
6b9316bfe743cc7d2ee00d925f4ab455bc224e86vboxsync {
db85b6b8ce514217c1fb35d04b0854a65dc299f3vboxsync pCpu->lastprefix = opcode;
db85b6b8ce514217c1fb35d04b0854a65dc299f3vboxsync pCpu->prefix &= ~PREFIX_REX;
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync }
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync switch(opcode)
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync {
4831e82ecaa3c813398d2f343e9d38ee34a3acf4vboxsync case OP_INVALID:
4831e82ecaa3c813398d2f343e9d38ee34a3acf4vboxsync#if 0 //defined (DEBUG_Sander)
4831e82ecaa3c813398d2f343e9d38ee34a3acf4vboxsync AssertMsgFailed(("Invalid opcode!!\n"));
40becad9511726726c5959a8ad8b62fb3e1c020cvboxsync#endif
40becad9511726726c5959a8ad8b62fb3e1c020cvboxsync return VERR_DIS_INVALID_OPCODE;
4831e82ecaa3c813398d2f343e9d38ee34a3acf4vboxsync
50453af238fcec34bf98f91cc4c32bf57f738bd3vboxsync // segment override prefix byte
2c1d8cd8efdd4c486ff681135035d24111b03af8vboxsync case OP_SEG:
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 if ( pCpu->mode != CPUMODE_64BIT
eeb2d581c99b451fb1a26a5870af65981dc9cd5dvboxsync || pCpu->enmPrefixSeg >= DIS_SELREG_FS)
f32de6c198a491c28ace2b4c53f8d04a79fd6d69vboxsync {
f32de6c198a491c28ace2b4c53f8d04a79fd6d69vboxsync pCpu->prefix |= PREFIX_SEG;
0ce6ae9d6efed5d54222a13bbdabce9e688e4447vboxsync }
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync i += sizeof(uint8_t);
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync prefixbytes++;
c4d6c81bd0de216d0f42db2e477b1d788fbaefb4vboxsync continue; //fetch the next byte
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync // lock prefix byte
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync case OP_LOCK:
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync pCpu->prefix |= PREFIX_LOCK;
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync i += sizeof(uint8_t);
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync prefixbytes++;
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync continue; //fetch the next byte
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync // address size override prefix byte
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync case OP_ADDRSIZE:
ea743ed8b8effc9f3647b76eb109c45788052fa0vboxsync pCpu->prefix |= PREFIX_ADDRSIZE;
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync if (pCpu->mode == CPUMODE_16BIT)
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync pCpu->addrmode = CPUMODE_32BIT;
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync else
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync if (pCpu->mode == CPUMODE_32BIT)
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync pCpu->addrmode = CPUMODE_16BIT;
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync else
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync pCpu->addrmode = CPUMODE_32BIT; /* 64 bits */
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync i += sizeof(uint8_t);
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync prefixbytes++;
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync continue; //fetch the next byte
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync // operand size override prefix byte
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync case OP_OPSIZE:
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync pCpu->prefix |= PREFIX_OPSIZE;
23ab2e25f17cdd6af9c0448ee70905a8c1c82896vboxsync if (pCpu->mode == CPUMODE_16BIT)
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync pCpu->opmode = CPUMODE_32BIT;
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync else
f6dde23cd488aee26203b38ec67220270f5c4273vboxsync pCpu->opmode = CPUMODE_16BIT; /* for 32 and 64 bits mode (there is no 32 bits operand size override prefix) */
4831e82ecaa3c813398d2f343e9d38ee34a3acf4vboxsync
40becad9511726726c5959a8ad8b62fb3e1c020cvboxsync i += sizeof(uint8_t);
40becad9511726726c5959a8ad8b62fb3e1c020cvboxsync prefixbytes++;
43e9355f77c0463e7ace350984bb5a09fb8c50a1vboxsync continue; //fetch the next byte
611af5c9fc04865215e86b6e4906c9dfdfb6a381vboxsync
d07e901177d22a8f66c66f155c423a524ac07776vboxsync // rep and repne are not really prefixes, but we'll treat them as such
d07e901177d22a8f66c66f155c423a524ac07776vboxsync case OP_REPE:
d07e901177d22a8f66c66f155c423a524ac07776vboxsync pCpu->prefix |= PREFIX_REP;
d07e901177d22a8f66c66f155c423a524ac07776vboxsync i += sizeof(uint8_t);
d07e901177d22a8f66c66f155c423a524ac07776vboxsync prefixbytes += sizeof(uint8_t);
d07e901177d22a8f66c66f155c423a524ac07776vboxsync continue; //fetch the next byte
d07e901177d22a8f66c66f155c423a524ac07776vboxsync
f48fe310f85f13db0140bef980de1f56c2007957vboxsync case OP_REPNE:
f48fe310f85f13db0140bef980de1f56c2007957vboxsync pCpu->prefix |= PREFIX_REPNE;
f48fe310f85f13db0140bef980de1f56c2007957vboxsync i += sizeof(uint8_t);
f48fe310f85f13db0140bef980de1f56c2007957vboxsync prefixbytes += sizeof(uint8_t);
1b186b95b77faa977d3651bbfc13afb3f13e0225vboxsync continue; //fetch the next byte
40becad9511726726c5959a8ad8b62fb3e1c020cvboxsync
0b10203d41681eb80716c97a34ed6c3b6d5318ccvboxsync case OP_REX:
611af5c9fc04865215e86b6e4906c9dfdfb6a381vboxsync Assert(pCpu->mode == CPUMODE_64BIT);
d4f7483a46e1c44ae5fcc4195be291545ae720a4vboxsync /* REX prefix byte */
d4f7483a46e1c44ae5fcc4195be291545ae720a4vboxsync pCpu->prefix |= PREFIX_REX;
d4f7483a46e1c44ae5fcc4195be291545ae720a4vboxsync pCpu->prefix_rex = PREFIX_REX_OP_2_FLAGS(paOneByteMap[codebyte].param1);
d4f7483a46e1c44ae5fcc4195be291545ae720a4vboxsync i += sizeof(uint8_t);
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync prefixbytes += sizeof(uint8_t);
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync
f9cac318205d74ee5b35dabcf2bd39118f6293d7vboxsync if (pCpu->prefix_rex & PREFIX_REX_FLAGS_W)
4831e82ecaa3c813398d2f343e9d38ee34a3acf4vboxsync pCpu->opmode = CPUMODE_64BIT; /* overrides size prefix byte */
d91dc86210d602f51a4701762488a5e696c80a45vboxsync continue; //fetch the next byte
4831e82ecaa3c813398d2f343e9d38ee34a3acf4vboxsync }
50453af238fcec34bf98f91cc4c32bf57f738bd3vboxsync }
4831e82ecaa3c813398d2f343e9d38ee34a3acf4vboxsync
f9cac318205d74ee5b35dabcf2bd39118f6293d7vboxsync idx = i;
f9cac318205d74ee5b35dabcf2bd39118f6293d7vboxsync i += sizeof(uint8_t); //first opcode byte
4831e82ecaa3c813398d2f343e9d38ee34a3acf4vboxsync
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync pCpu->opcode = codebyte;
f7c0f913c4c22ee18059ff97055442566d0f14a1vboxsync /* Prefix byte(s) is/are part of the instruction. */
f7c0f913c4c22ee18059ff97055442566d0f14a1vboxsync pCpu->opaddr = pu8Instruction + idx + u32EipOffset - prefixbytes;
f7c0f913c4c22ee18059ff97055442566d0f14a1vboxsync
db85b6b8ce514217c1fb35d04b0854a65dc299f3vboxsync inc = ParseInstruction(pu8Instruction + i, &paOneByteMap[pCpu->opcode], pCpu);
db85b6b8ce514217c1fb35d04b0854a65dc299f3vboxsync
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync pCpu->opsize = prefixbytes + inc + sizeof(uint8_t);
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync
3221ae1f7bf53d9cccdd578099f55f782dba1447vboxsync if(pszOutput) {
3221ae1f7bf53d9cccdd578099f55f782dba1447vboxsync disasmSprintf(pszOutput, pu8Instruction+i-1-prefixbytes, pCpu, &pCpu->param1, &pCpu->param2, &pCpu->param3);
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync }
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync i += inc;
5e3a885d489b1c99d79d576813f8f321bae46927vboxsync prefixbytes = 0;
break;
}
}
#ifndef __L4ENV__
catch(...)
#else
else /* setjmp has returned a non-zero value: an exception occured */
#endif
{
if (pcbSize)
*pcbSize = 0;
return VERR_DIS_GEN_FAILURE;
}
if (pcbSize)
*pcbSize = i;
if (pCpu->prefix & PREFIX_LOCK)
disValidateLockSequence(pCpu);
return VINF_SUCCESS;
}
//*****************************************************************************
//*****************************************************************************
char *DbgBytesToString(PDISCPUSTATE pCpu, RTUINTPTR pBytes, int size, char *pszOutput)
{
char szByte[4];
int len = strlen(pszOutput);
int i;
for(i = len; i < 40; i++)
{
strcat(pszOutput, " ");
}
strcat(pszOutput, " [");
for(i = 0; i < size; i++)
{
RTStrPrintf(szByte, sizeof(szByte), "%02X ", DISReadByte(pCpu, pBytes+i));
RTStrPrintf(&pszOutput[strlen(pszOutput)], 64, szByte);
}
len = strlen(pszOutput);
pszOutput[len - 1] = 0; //cut off last space
strcat(pszOutput, "]");
return pszOutput;
}
//*****************************************************************************
//*****************************************************************************
void disasmSprintf(char *pszOutput, RTUINTPTR pu8Instruction, PDISCPUSTATE pCpu, OP_PARAMETER *pParam1, OP_PARAMETER *pParam2, OP_PARAMETER *pParam3)
{
const char *lpszFormat = pCpu->pszOpcode;
int param = 1;
RTStrPrintf(pszOutput, 64, "%08X: ", (unsigned)pCpu->opaddr);
if(pCpu->prefix & PREFIX_LOCK)
{
RTStrPrintf(&pszOutput[strlen(pszOutput)], 64, "lock ");
}
if(pCpu->prefix & PREFIX_REP)
{
RTStrPrintf(&pszOutput[strlen(pszOutput)], 64, "rep(e) ");
}
else
if(pCpu->prefix & PREFIX_REPNE)
{
RTStrPrintf(&pszOutput[strlen(pszOutput)], 64, "repne ");
}
if(!strcmp("Invalid Opcode", lpszFormat))
{
RTStrPrintf(&pszOutput[strlen(pszOutput)], 64, "Invalid Opcode [%02X][%02X]", DISReadByte(pCpu, pu8Instruction), DISReadByte(pCpu, pu8Instruction+1) );
}
else
while(*lpszFormat)
{
switch(*lpszFormat)
{
case '%':
switch(*(lpszFormat+1))
{
case 'J': //Relative jump offset
{
int32_t disp;
AssertMsg(param == 1, ("Invalid branch parameter nr"));
if(pParam1->flags & USE_IMMEDIATE8_REL)
{
disp = (int32_t)(char)pParam1->parval;
}
else
if(pParam1->flags & USE_IMMEDIATE16_REL)
{
disp = (int32_t)(uint16_t)pParam1->parval;
}
else
if(pParam1->flags & USE_IMMEDIATE32_REL)
{
disp = (int32_t)pParam1->parval;
}
else
if(pParam1->flags & USE_IMMEDIATE64_REL)
{
/* @todo: is this correct? */
disp = (int32_t)pParam1->parval;
}
else
{
AssertMsgFailed(("Oops!\n"));
return;
}
uint32_t addr = (uint32_t)(pCpu->opaddr + pCpu->opsize) + disp;
RTStrPrintf(&pszOutput[strlen(pszOutput)], 64, "[%08X]", addr);
}
//no break;
case 'A': //direct address
case 'C': //control register
case 'D': //debug register
case 'E': //ModRM specifies parameter
case 'F': //Eflags register
case 'G': //ModRM selects general register
case 'I': //Immediate data
case 'M': //ModRM may only refer to memory
case 'O': //No ModRM byte
case 'P': //ModRM byte selects MMX register
case 'Q': //ModRM byte selects MMX register or memory address
case 'R': //ModRM byte may only refer to a general register
case 'S': //ModRM byte selects a segment register
case 'T': //ModRM byte selects a test register
case 'V': //ModRM byte selects an XMM/SSE register
case 'W': //ModRM byte selects an XMM/SSE register or a memory address
case 'X': //DS:SI
case 'Y': //ES:DI
switch(param)
{
case 1:
RTStrPrintf(&pszOutput[strlen(pszOutput)], 64, pParam1->szParam);
break;
case 2:
RTStrPrintf(&pszOutput[strlen(pszOutput)], 64, pParam2->szParam);
break;
case 3:
RTStrPrintf(&pszOutput[strlen(pszOutput)], 64, pParam3->szParam);
break;
}
break;
case 'e': //register based on operand size (e.g. %eAX)
if(pCpu->opmode == CPUMODE_32BIT)
RTStrPrintf(&pszOutput[strlen(pszOutput)], 64, "E");
if(pCpu->opmode == CPUMODE_64BIT)
RTStrPrintf(&pszOutput[strlen(pszOutput)], 64, "R");
RTStrPrintf(&pszOutput[strlen(pszOutput)], 64, "%c%c", lpszFormat[2], lpszFormat[3]);
break;
default:
AssertMsgFailed(("Oops!\n"));
break;
}
//Go to the next parameter in the format string
while(*lpszFormat && *lpszFormat != ',') lpszFormat++;
if(*lpszFormat == ',') lpszFormat--;
break;
case ',':
param++;
//no break
default:
RTStrPrintf(&pszOutput[strlen(pszOutput)], 64, "%c", *lpszFormat);
break;
}
if(*lpszFormat) lpszFormat++;
}
DbgBytesToString(pCpu, pu8Instruction, pCpu->opsize, pszOutput);
RTStrPrintf(&pszOutput[strlen(pszOutput)], 64, "\n");
}
//*****************************************************************************
//*****************************************************************************