DBGFDisas.cpp revision 50f998bb47f333d10515d4c12ad01a4e92a0747b
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync/* $Id$ */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync/** @file
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * DBGF - Debugger Facility, Disassembler.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync/*
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * Copyright (C) 2006-2007 Oracle Corporation
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync *
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * available from http://www.virtualbox.org. This file is free software;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * you can redistribute it and/or modify it under the terms of the GNU
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * General Public License (GPL) as published by the Free Software
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync/*******************************************************************************
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync* Header Files *
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync*******************************************************************************/
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync#define LOG_GROUP LOG_GROUP_DBGF
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync#include <VBox/vmm/dbgf.h>
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync#include <VBox/vmm/selm.h>
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync#include <VBox/vmm/mm.h>
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync#include <VBox/vmm/pgm.h>
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync#include <VBox/vmm/cpum.h>
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync#include "DBGFInternal.h"
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync#include <VBox/dis.h>
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync#include <VBox/err.h>
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync#include <VBox/param.h>
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync#include <VBox/vmm/vm.h>
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync#include "internal/pgm.h"
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync#include <VBox/log.h>
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync#include <iprt/assert.h>
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync#include <iprt/string.h>
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync#include <iprt/alloca.h>
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync#include <iprt/ctype.h>
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync/*******************************************************************************
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync* Structures and Typedefs *
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync*******************************************************************************/
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync/**
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * Structure used when disassembling and instructions in DBGF.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * This is used so the reader function can get the stuff it needs.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsynctypedef struct
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync{
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /** The core structure. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync DISCPUSTATE Cpu;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /** The VM handle. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync PVM pVM;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /** The VMCPU handle. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync PVMCPU pVCpu;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /** The address space for resolving symbol. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync RTDBGAS hAs;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /** Pointer to the first byte in the segment. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync RTGCUINTPTR GCPtrSegBase;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /** Pointer to the byte after the end of the segment. (might have wrapped!) */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync RTGCUINTPTR GCPtrSegEnd;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /** The size of the segment minus 1. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync RTGCUINTPTR cbSegLimit;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /** The guest paging mode. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync PGMMODE enmMode;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /** Pointer to the current page - R3 Ptr. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync void const *pvPageR3;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /** Pointer to the current page - GC Ptr. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync RTGCPTR pvPageGC;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /** Pointer to the next instruction (relative to GCPtrSegBase). */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync RTGCUINTPTR GCPtrNext;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /** The lock information that PGMPhysReleasePageMappingLock needs. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync PGMPAGEMAPLOCK PageMapLock;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /** Whether the PageMapLock is valid or not. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync bool fLocked;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /** 64 bits mode or not. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync bool f64Bits;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync} DBGFDISASSTATE, *PDBGFDISASSTATE;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync/*******************************************************************************
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync* Internal Functions *
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync*******************************************************************************/
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsyncstatic DECLCALLBACK(int) dbgfR3DisasInstrRead(RTUINTPTR pSrc, uint8_t *pDest, uint32_t size, void *pvUserdata);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync/**
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * Calls the disassembler with the proper reader functions and such for disa
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync *
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * @returns VBox status code.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * @param pVM VM handle
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * @param pVCpu VMCPU handle
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * @param pSelInfo The selector info.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * @param enmMode The guest paging mode.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * @param fFlags DBGF_DISAS_FLAGS_XXX.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * @param GCPtr The GC pointer (selector offset).
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * @param pState The disas CPU state.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsyncstatic int dbgfR3DisasInstrFirst(PVM pVM, PVMCPU pVCpu, PDBGFSELINFO pSelInfo, PGMMODE enmMode,
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync RTGCPTR GCPtr, uint32_t fFlags, PDBGFDISASSTATE pState)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync{
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync pState->GCPtrSegBase = pSelInfo->GCPtrBase;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync pState->GCPtrSegEnd = pSelInfo->cbLimit + 1 + (RTGCUINTPTR)pSelInfo->GCPtrBase;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync pState->cbSegLimit = pSelInfo->cbLimit;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync pState->enmMode = enmMode;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync pState->pvPageGC = 0;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync pState->pvPageR3 = NULL;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync pState->hAs = pSelInfo->fFlags & DBGFSELINFO_FLAGS_HYPER /** @todo Deal more explicitly with RC in DBGFR3Disas*. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync ? DBGF_AS_RC_AND_GC_GLOBAL
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync : DBGF_AS_GLOBAL;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync pState->pVM = pVM;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync pState->pVCpu = pVCpu;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync pState->fLocked = false;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync pState->f64Bits = enmMode >= PGMMODE_AMD64 && pSelInfo->u.Raw.Gen.u1Long;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync DISCPUMODE enmCpuMode;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync switch (fFlags & DBGF_DISAS_FLAGS_MODE_MASK)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync {
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync default:
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync AssertFailed();
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync case DBGF_DISAS_FLAGS_DEFAULT_MODE:
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync enmCpuMode = pState->f64Bits
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync ? CPUMODE_64BIT
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync : pSelInfo->u.Raw.Gen.u1DefBig
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync ? CPUMODE_32BIT
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync : CPUMODE_16BIT;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync break;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync case DBGF_DISAS_FLAGS_16BIT_MODE:
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync case DBGF_DISAS_FLAGS_16BIT_REAL_MODE:
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync enmCpuMode = CPUMODE_16BIT;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync break;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync case DBGF_DISAS_FLAGS_32BIT_MODE:
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync enmCpuMode = CPUMODE_32BIT;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync break;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync case DBGF_DISAS_FLAGS_64BIT_MODE:
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync enmCpuMode = CPUMODE_64BIT;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync break;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync }
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync uint32_t cbInstr;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync int rc = DISCoreOneEx(GCPtr,
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync enmCpuMode,
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync dbgfR3DisasInstrRead,
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync &pState->Cpu,
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync &pState->Cpu,
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync &cbInstr);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync if (RT_SUCCESS(rc))
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync {
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync pState->GCPtrNext = GCPtr + cbInstr;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync return VINF_SUCCESS;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync }
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /* cleanup */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync if (pState->fLocked)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync {
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync PGMPhysReleasePageMappingLock(pVM, &pState->PageMapLock);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync pState->fLocked = false;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync }
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync return rc;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync}
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync#if 0
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync/**
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * Calls the disassembler for disassembling the next instruction.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync *
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * @returns VBox status code.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * @param pState The disas CPU state.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsyncstatic int dbgfR3DisasInstrNext(PDBGFDISASSTATE pState)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync{
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync uint32_t cbInstr;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync int rc = DISInstr(&pState->Cpu, (void *)pState->GCPtrNext, 0, &cbInstr, NULL);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync if (RT_SUCCESS(rc))
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync {
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync pState->GCPtrNext = GCPtr + cbInstr;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync return VINF_SUCCESS;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync }
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync return rc;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync}
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync#endif
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync/**
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * Done with the disassembler state, free associated resources.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync *
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * @param pState The disas CPU state ++.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsyncstatic void dbgfR3DisasInstrDone(PDBGFDISASSTATE pState)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync{
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync if (pState->fLocked)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync {
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync PGMPhysReleasePageMappingLock(pState->pVM, &pState->PageMapLock);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync pState->fLocked = false;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync }
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync}
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync/**
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * Instruction reader.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync *
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * @returns VBox status code. (Why this is a int32_t and not just an int is also beyond me.)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * @param PtrSrc Address to read from.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * In our case this is relative to the selector pointed to by the 2nd user argument of uDisCpu.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * @param pu8Dst Where to store the bytes.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * @param cbRead Number of bytes to read.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * @param uDisCpu Pointer to the disassembler cpu state. (Why this is a VBOXHUINTPTR is beyond me...)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * In this context it's always pointer to the Core of a DBGFDISASSTATE.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsyncstatic DECLCALLBACK(int) dbgfR3DisasInstrRead(RTUINTPTR PtrSrc, uint8_t *pu8Dst, uint32_t cbRead, void *pvDisCpu)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync{
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync PDBGFDISASSTATE pState = (PDBGFDISASSTATE)pvDisCpu;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync Assert(cbRead > 0);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync for (;;)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync {
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync RTGCUINTPTR GCPtr = PtrSrc + pState->GCPtrSegBase;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /* Need to update the page translation? */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync if ( !pState->pvPageR3
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync || (GCPtr >> PAGE_SHIFT) != (pState->pvPageGC >> PAGE_SHIFT))
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync {
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync int rc = VINF_SUCCESS;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /* translate the address */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync pState->pvPageGC = GCPtr & PAGE_BASE_GC_MASK;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync if (MMHyperIsInsideArea(pState->pVM, pState->pvPageGC))
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync {
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync pState->pvPageR3 = MMHyperRCToR3(pState->pVM, (RTRCPTR)pState->pvPageGC);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync if (!pState->pvPageR3)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync rc = VERR_INVALID_POINTER;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync }
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync else
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync {
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync if (pState->fLocked)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync PGMPhysReleasePageMappingLock(pState->pVM, &pState->PageMapLock);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync if (pState->enmMode <= PGMMODE_PROTECTED)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync rc = PGMPhysGCPhys2CCPtrReadOnly(pState->pVM, pState->pvPageGC, &pState->pvPageR3, &pState->PageMapLock);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync else
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync rc = PGMPhysGCPtr2CCPtrReadOnly(pState->pVCpu, pState->pvPageGC, &pState->pvPageR3, &pState->PageMapLock);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync pState->fLocked = RT_SUCCESS_NP(rc);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync }
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync if (RT_FAILURE(rc))
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync {
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync pState->pvPageR3 = NULL;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync return rc;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync }
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync }
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /* check the segment limit */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync if (!pState->f64Bits && PtrSrc > pState->cbSegLimit)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync return VERR_OUT_OF_SELECTOR_BOUNDS;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /* calc how much we can read */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync uint32_t cb = PAGE_SIZE - (GCPtr & PAGE_OFFSET_MASK);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync if (!pState->f64Bits)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync {
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync RTGCUINTPTR cbSeg = pState->GCPtrSegEnd - GCPtr;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync if (cb > cbSeg && cbSeg)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync cb = cbSeg;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync }
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync if (cb > cbRead)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync cb = cbRead;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /* read and advance */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync memcpy(pu8Dst, (char *)pState->pvPageR3 + (GCPtr & PAGE_OFFSET_MASK), cb);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync cbRead -= cb;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync if (!cbRead)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync return VINF_SUCCESS;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync pu8Dst += cb;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync PtrSrc += cb;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync }
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync}
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync/**
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * @copydoc FNDISGETSYMBOL
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsyncstatic DECLCALLBACK(int) dbgfR3DisasGetSymbol(PCDISCPUSTATE pCpu, uint32_t u32Sel, RTUINTPTR uAddress, char *pszBuf, size_t cchBuf, RTINTPTR *poff, void *pvUser)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync{
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync PDBGFDISASSTATE pState = (PDBGFDISASSTATE)pCpu;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync PCDBGFSELINFO pSelInfo = (PCDBGFSELINFO)pvUser;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync DBGFADDRESS Addr;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync RTDBGSYMBOL Sym;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync RTGCINTPTR off;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync int rc;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync if ( DIS_FMT_SEL_IS_REG(u32Sel)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync ? DIS_FMT_SEL_GET_REG(u32Sel) == DIS_SELREG_CS
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync : pSelInfo->Sel == DIS_FMT_SEL_GET_VALUE(u32Sel))
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync {
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync rc = DBGFR3AddrFromSelInfoOff(pState->pVM, &Addr, pSelInfo, uAddress);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync if (RT_SUCCESS(rc))
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync rc = DBGFR3AsSymbolByAddr(pState->pVM, pState->hAs, &Addr, &off, &Sym, NULL /*phMod*/);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync }
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync else
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync rc = VERR_SYMBOL_NOT_FOUND; /** @todo implement this */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync if (RT_SUCCESS(rc))
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync {
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync size_t cchName = strlen(Sym.szName);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync if (cchName >= cchBuf)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync cchName = cchBuf - 1;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync memcpy(pszBuf, Sym.szName, cchName);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync pszBuf[cchName] = '\0';
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync *poff = off;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync }
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync return rc;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync}
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync/**
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * Disassembles the one instruction according to the specified flags and
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * address, internal worker executing on the EMT of the specified virtual CPU.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync *
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * @returns VBox status code.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * @param pVM The VM handle.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * @param pVCpu The virtual CPU handle.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * @param Sel The code selector. This used to determine the 32/16 bit ness and
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * calculation of the actual instruction address.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * @param pGCPtr Pointer to the variable holding the code address
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * relative to the base of Sel.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * @param fFlags Flags controlling where to start and how to format.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * A combination of the DBGF_DISAS_FLAGS_* \#defines.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * @param pszOutput Output buffer.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * @param cbOutput Size of the output buffer.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * @param pcbInstr Where to return the size of the instruction.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsyncstatic DECLCALLBACK(int)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsyncdbgfR3DisasInstrExOnVCpu(PVM pVM, PVMCPU pVCpu, RTSEL Sel, PRTGCPTR pGCPtr, uint32_t fFlags,
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync char *pszOutput, uint32_t cbOutput, uint32_t *pcbInstr)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync{
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VMCPU_ASSERT_EMT(pVCpu);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync RTGCPTR GCPtr = *pGCPtr;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /*
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * Get the Sel and GCPtr if fFlags requests that.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync PCCPUMCTXCORE pCtxCore = NULL;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync PCPUMSELREGHID pHiddenSel = NULL;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync int rc;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync if (fFlags & (DBGF_DISAS_FLAGS_CURRENT_GUEST | DBGF_DISAS_FLAGS_CURRENT_HYPER))
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync {
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync if (fFlags & DBGF_DISAS_FLAGS_CURRENT_GUEST)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync pCtxCore = CPUMGetGuestCtxCore(pVCpu);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync else
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync pCtxCore = CPUMGetHyperCtxCore(pVCpu);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync Sel = pCtxCore->cs;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync pHiddenSel = (CPUMSELREGHID *)&pCtxCore->csHid;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync GCPtr = pCtxCore->rip;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync }
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /*
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * Read the selector info - assume no stale selectors and nasty stuff like that.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * Since the selector flags in the CPUMCTX structures aren't up to date unless
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * we recently visited REM, we'll not search for the selector there.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync DBGFSELINFO SelInfo;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync const PGMMODE enmMode = PGMGetGuestMode(pVCpu);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync bool fRealModeAddress = false;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync if ( pHiddenSel
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync && ( (fFlags & DBGF_DISAS_FLAGS_HID_SEL_REGS_VALID)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync || CPUMAreHiddenSelRegsValid(pVCpu)))
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync {
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync SelInfo.Sel = Sel;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync SelInfo.SelGate = 0;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync SelInfo.GCPtrBase = pHiddenSel->u64Base;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync SelInfo.cbLimit = pHiddenSel->u32Limit;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync SelInfo.fFlags = PGMMODE_IS_LONG_MODE(enmMode)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync ? DBGFSELINFO_FLAGS_LONG_MODE
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync : enmMode != PGMMODE_REAL && (!pCtxCore || !pCtxCore->eflags.Bits.u1VM)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync ? DBGFSELINFO_FLAGS_PROT_MODE
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync : DBGFSELINFO_FLAGS_REAL_MODE;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync SelInfo.u.Raw.au32[0] = 0;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync SelInfo.u.Raw.au32[1] = 0;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync SelInfo.u.Raw.Gen.u16LimitLow = 0xffff;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync SelInfo.u.Raw.Gen.u4LimitHigh = 0xf;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync SelInfo.u.Raw.Gen.u1Present = pHiddenSel->Attr.n.u1Present;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync SelInfo.u.Raw.Gen.u1Granularity = pHiddenSel->Attr.n.u1Granularity;;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync SelInfo.u.Raw.Gen.u1DefBig = pHiddenSel->Attr.n.u1DefBig;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync SelInfo.u.Raw.Gen.u1Long = pHiddenSel->Attr.n.u1Long;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync SelInfo.u.Raw.Gen.u1DescType = pHiddenSel->Attr.n.u1DescType;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync SelInfo.u.Raw.Gen.u4Type = pHiddenSel->Attr.n.u4Type;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync fRealModeAddress = !!(SelInfo.fFlags & DBGFSELINFO_FLAGS_REAL_MODE);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync }
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync else if (Sel == DBGF_SEL_FLAT)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync {
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync SelInfo.Sel = Sel;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync SelInfo.SelGate = 0;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync SelInfo.GCPtrBase = 0;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync SelInfo.cbLimit = ~0;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync SelInfo.fFlags = PGMMODE_IS_LONG_MODE(enmMode)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync ? DBGFSELINFO_FLAGS_LONG_MODE
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync : enmMode != PGMMODE_REAL
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync ? DBGFSELINFO_FLAGS_PROT_MODE
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync : DBGFSELINFO_FLAGS_REAL_MODE;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync SelInfo.u.Raw.au32[0] = 0;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync SelInfo.u.Raw.au32[1] = 0;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync SelInfo.u.Raw.Gen.u16LimitLow = 0xffff;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync SelInfo.u.Raw.Gen.u4LimitHigh = 0xf;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync if ( (fFlags & DBGF_DISAS_FLAGS_HID_SEL_REGS_VALID)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync || CPUMAreHiddenSelRegsValid(pVCpu))
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync { /* Assume the current CS defines the execution mode. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync pCtxCore = CPUMGetGuestCtxCore(pVCpu);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync pHiddenSel = (CPUMSELREGHID *)&pCtxCore->csHid;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync SelInfo.u.Raw.Gen.u1Present = pHiddenSel->Attr.n.u1Present;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync SelInfo.u.Raw.Gen.u1Granularity = pHiddenSel->Attr.n.u1Granularity;;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync SelInfo.u.Raw.Gen.u1DefBig = pHiddenSel->Attr.n.u1DefBig;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync SelInfo.u.Raw.Gen.u1Long = pHiddenSel->Attr.n.u1Long;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync SelInfo.u.Raw.Gen.u1DescType = pHiddenSel->Attr.n.u1DescType;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync SelInfo.u.Raw.Gen.u4Type = pHiddenSel->Attr.n.u4Type;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync }
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync else
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync {
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync SelInfo.u.Raw.Gen.u1Present = 1;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync SelInfo.u.Raw.Gen.u1Granularity = 1;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync SelInfo.u.Raw.Gen.u1DefBig = 1;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync SelInfo.u.Raw.Gen.u1DescType = 1;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync SelInfo.u.Raw.Gen.u4Type = X86_SEL_TYPE_EO;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync }
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync }
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync else if ( !(fFlags & DBGF_DISAS_FLAGS_CURRENT_HYPER)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync && ( (pCtxCore && pCtxCore->eflags.Bits.u1VM)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync || enmMode == PGMMODE_REAL
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync || (fFlags & DBGF_DISAS_FLAGS_MODE_MASK) == DBGF_DISAS_FLAGS_16BIT_REAL_MODE
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync )
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync )
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync { /* V86 mode or real mode - real mode addressing */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync SelInfo.Sel = Sel;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync SelInfo.SelGate = 0;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync SelInfo.GCPtrBase = Sel * 16;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync SelInfo.cbLimit = ~0;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync SelInfo.fFlags = DBGFSELINFO_FLAGS_REAL_MODE;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync SelInfo.u.Raw.au32[0] = 0;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync SelInfo.u.Raw.au32[1] = 0;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync SelInfo.u.Raw.Gen.u16LimitLow = 0xffff;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync SelInfo.u.Raw.Gen.u4LimitHigh = 0xf;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync SelInfo.u.Raw.Gen.u1Present = 1;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync SelInfo.u.Raw.Gen.u1Granularity = 1;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync SelInfo.u.Raw.Gen.u1DefBig = 0; /* 16 bits */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync SelInfo.u.Raw.Gen.u1DescType = 1;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync SelInfo.u.Raw.Gen.u4Type = X86_SEL_TYPE_EO;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync fRealModeAddress = true;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync }
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync else
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync {
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync rc = SELMR3GetSelectorInfo(pVM, pVCpu, Sel, &SelInfo);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync if (RT_FAILURE(rc))
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync {
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync RTStrPrintf(pszOutput, cbOutput, "Sel=%04x -> %Rrc\n", Sel, rc);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync return rc;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync }
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync }
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /*
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * Disassemble it.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync DBGFDISASSTATE State;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync rc = dbgfR3DisasInstrFirst(pVM, pVCpu, &SelInfo, enmMode, GCPtr, fFlags, &State);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync if (RT_FAILURE(rc))
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync {
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync RTStrPrintf(pszOutput, cbOutput, "Disas -> %Rrc\n", rc);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync return rc;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync }
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /*
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * Format it.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync char szBuf[512];
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync DISFormatYasmEx(&State.Cpu, szBuf, sizeof(szBuf),
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync DIS_FMT_FLAGS_RELATIVE_BRANCH,
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync fFlags & DBGF_DISAS_FLAGS_NO_SYMBOLS ? NULL : dbgfR3DisasGetSymbol,
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync &SelInfo);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /*
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * Print it to the user specified buffer.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync if (fFlags & DBGF_DISAS_FLAGS_NO_BYTES)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync {
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync if (fFlags & DBGF_DISAS_FLAGS_NO_ADDRESS)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync RTStrPrintf(pszOutput, cbOutput, "%s", szBuf);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync else if (fRealModeAddress)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync RTStrPrintf(pszOutput, cbOutput, "%04x:%04x %s", Sel, (unsigned)GCPtr, szBuf);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync else if (Sel == DBGF_SEL_FLAT)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync {
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync if (enmMode >= PGMMODE_AMD64)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync RTStrPrintf(pszOutput, cbOutput, "%RGv %s", GCPtr, szBuf);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync else
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync RTStrPrintf(pszOutput, cbOutput, "%08RX32 %s", (uint32_t)GCPtr, szBuf);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync }
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync else
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync {
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync if (enmMode >= PGMMODE_AMD64)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync RTStrPrintf(pszOutput, cbOutput, "%04x:%RGv %s", Sel, GCPtr, szBuf);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync else
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync RTStrPrintf(pszOutput, cbOutput, "%04x:%08RX32 %s", Sel, (uint32_t)GCPtr, szBuf);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync }
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync }
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync else
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync {
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync uint32_t cbBits = State.Cpu.opsize;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync uint8_t *pau8Bits = (uint8_t *)alloca(cbBits);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync rc = dbgfR3DisasInstrRead(GCPtr, pau8Bits, cbBits, &State);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync AssertRC(rc);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync if (fFlags & DBGF_DISAS_FLAGS_NO_ADDRESS)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync RTStrPrintf(pszOutput, cbOutput, "%.*Rhxs%*s %s",
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync cbBits, pau8Bits, cbBits < 8 ? (8 - cbBits) * 3 : 0, "",
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync szBuf);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync else if (fRealModeAddress)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync RTStrPrintf(pszOutput, cbOutput, "%04x:%04x %.*Rhxs%*s %s",
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync Sel, (unsigned)GCPtr,
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync cbBits, pau8Bits, cbBits < 8 ? (8 - cbBits) * 3 : 0, "",
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync szBuf);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync else if (Sel == DBGF_SEL_FLAT)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync {
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync if (enmMode >= PGMMODE_AMD64)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync RTStrPrintf(pszOutput, cbOutput, "%RGv %.*Rhxs%*s %s",
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync GCPtr,
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync cbBits, pau8Bits, cbBits < 8 ? (8 - cbBits) * 3 : 0, "",
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync szBuf);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync else
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync RTStrPrintf(pszOutput, cbOutput, "%08RX32 %.*Rhxs%*s %s",
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync (uint32_t)GCPtr,
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync cbBits, pau8Bits, cbBits < 8 ? (8 - cbBits) * 3 : 0, "",
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync szBuf);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync }
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync else
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync {
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync if (enmMode >= PGMMODE_AMD64)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync RTStrPrintf(pszOutput, cbOutput, "%04x:%RGv %.*Rhxs%*s %s",
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync Sel, GCPtr,
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync cbBits, pau8Bits, cbBits < 8 ? (8 - cbBits) * 3 : 0, "",
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync szBuf);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync else
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync RTStrPrintf(pszOutput, cbOutput, "%04x:%08RX32 %.*Rhxs%*s %s",
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync Sel, (uint32_t)GCPtr,
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync cbBits, pau8Bits, cbBits < 8 ? (8 - cbBits) * 3 : 0, "",
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync szBuf);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync }
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync }
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync if (pcbInstr)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync *pcbInstr = State.Cpu.opsize;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync dbgfR3DisasInstrDone(&State);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync return VINF_SUCCESS;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync}
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync/**
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * Disassembles the one instruction according to the specified flags and address.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync *
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * @returns VBox status code.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * @param pVM VM handle.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * @param idCpu The ID of virtual CPU.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * @param Sel The code selector. This used to determine the 32/16 bit ness and
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * calculation of the actual instruction address.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * @param GCPtr The code address relative to the base of Sel.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * @param fFlags Flags controlling where to start and how to format.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * A combination of the DBGF_DISAS_FLAGS_* \#defines.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * @param pszOutput Output buffer. This will always be properly
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * terminated if @a cbOutput is greater than zero.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * @param cbOutput Size of the output buffer.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * @param pcbInstr Where to return the size of the instruction.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync *
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * @remarks May have to switch to the EMT of the virtual CPU in order to do
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * address conversion.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsyncVMMR3DECL(int) DBGFR3DisasInstrEx(PVM pVM, VMCPUID idCpu, RTSEL Sel, RTGCPTR GCPtr, uint32_t fFlags,
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync char *pszOutput, uint32_t cbOutput, uint32_t *pcbInstr)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync{
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync AssertReturn(cbOutput > 0, VERR_INVALID_PARAMETER);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync *pszOutput = '\0';
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync AssertReturn(idCpu < pVM->cCpus, VERR_INVALID_CPU_ID);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync AssertReturn(!(fFlags & ~DBGF_DISAS_FLAGS_VALID_MASK), VERR_INVALID_PARAMETER);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync AssertReturn((fFlags & DBGF_DISAS_FLAGS_MODE_MASK) <= DBGF_DISAS_FLAGS_64BIT_MODE, VERR_INVALID_PARAMETER);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /*
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * Optimize the common case where we're called on the EMT of idCpu since
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * we're using this all the time when logging.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync int rc;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync PVMCPU pVCpu = VMMGetCpu(pVM);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync if ( pVCpu
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync && pVCpu->idCpu == idCpu)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync rc = dbgfR3DisasInstrExOnVCpu(pVM, pVCpu, Sel, &GCPtr, fFlags, pszOutput, cbOutput, pcbInstr);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync else
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync rc = VMR3ReqPriorityCallWait(pVM, idCpu, (PFNRT)dbgfR3DisasInstrExOnVCpu, 8,
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync pVM, VMMGetCpuById(pVM, idCpu), Sel, &GCPtr, fFlags, pszOutput, cbOutput, pcbInstr);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync return rc;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync}
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync/**
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * Disassembles the current guest context instruction.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * All registers and data will be displayed. Addresses will be attempted resolved to symbols.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync *
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * @returns VBox status code.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * @param pVCpu VMCPU handle.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * @param pszOutput Output buffer. This will always be properly
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * terminated if @a cbOutput is greater than zero.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * @param cbOutput Size of the output buffer.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsyncVMMR3DECL(int) DBGFR3DisasInstrCurrent(PVMCPU pVCpu, char *pszOutput, uint32_t cbOutput)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync{
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync AssertReturn(cbOutput > 0, VERR_INVALID_PARAMETER);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync *pszOutput = '\0';
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync AssertReturn(pVCpu, VERR_INVALID_CONTEXT);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync return DBGFR3DisasInstrEx(pVCpu->pVMR3, pVCpu->idCpu, 0, 0,
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync DBGF_DISAS_FLAGS_CURRENT_GUEST | DBGF_DISAS_FLAGS_DEFAULT_MODE,
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync pszOutput, cbOutput, NULL);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync}
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync/**
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * Disassembles the current guest context instruction and writes it to the log.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * All registers and data will be displayed. Addresses will be attempted resolved to symbols.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync *
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * @returns VBox status code.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * @param pVCpu VMCPU handle.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * @param pszPrefix Short prefix string to the disassembly string. (optional)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsyncVMMR3DECL(int) DBGFR3DisasInstrCurrentLogInternal(PVMCPU pVCpu, const char *pszPrefix)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync{
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync char szBuf[256];
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync szBuf[0] = '\0';
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync int rc = DBGFR3DisasInstrCurrent(pVCpu, &szBuf[0], sizeof(szBuf));
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync if (RT_FAILURE(rc))
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync RTStrPrintf(szBuf, sizeof(szBuf), "DBGFR3DisasInstrCurrentLog failed with rc=%Rrc\n", rc);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync if (pszPrefix && *pszPrefix)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync RTLogPrintf("%s-CPU%d: %s\n", pszPrefix, pVCpu->idCpu, szBuf);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync else
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync RTLogPrintf("%s\n", szBuf);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync return rc;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync}
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync/**
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * Disassembles the specified guest context instruction and writes it to the log.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * Addresses will be attempted resolved to symbols.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync *
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * @returns VBox status code.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * @param pVM VM handle.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * @param pVCpu The virtual CPU handle, defaults to CPU 0 if NULL.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * @param Sel The code selector. This used to determine the 32/16 bit-ness and
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * calculation of the actual instruction address.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * @param GCPtr The code address relative to the base of Sel.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsyncVMMR3DECL(int) DBGFR3DisasInstrLogInternal(PVMCPU pVCpu, RTSEL Sel, RTGCPTR GCPtr)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync{
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync char szBuf[256];
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync int rc = DBGFR3DisasInstrEx(pVCpu->pVMR3, pVCpu->idCpu, Sel, GCPtr, DBGF_DISAS_FLAGS_DEFAULT_MODE,
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync &szBuf[0], sizeof(szBuf), NULL);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync if (RT_FAILURE(rc))
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync RTStrPrintf(szBuf, sizeof(szBuf), "DBGFR3DisasInstrLog(, %RTsel, %RGv) failed with rc=%Rrc\n", Sel, GCPtr, rc);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync RTLogPrintf("%s\n", szBuf);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync return rc;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync}
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync