/** @file
 * DBGF - Debugger Facility.
 */

/*
 * Copyright (C) 2006-2015 Oracle Corporation
 *
 * This file is part of VirtualBox Open Source Edition (OSE), as
 * available from http://www.virtualbox.org. This file is free software;
 * you can redistribute it and/or modify it under the terms of the GNU
 * General Public License (GPL) as published by the Free Software
 * Foundation, in version 2 as it comes in the "COPYING" file of the
 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
 *
 * The contents of this file may alternatively be used under the terms
 * of the Common Development and Distribution License Version 1.0
 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
 * VirtualBox OSE distribution, in which case the provisions of the
 * CDDL are applicable instead of those of the GPL.
 *
 * You may elect to license modified versions of this file under the
 * terms and conditions of either the GPL or the CDDL or both.
 */

#ifndef ___VBox_vmm_dbgf_h
#define ___VBox_vmm_dbgf_h

#include <VBox/types.h>
#include <VBox/log.h>                   /* LOG_ENABLED */
#include <VBox/vmm/vmm.h>
#include <VBox/vmm/dbgfsel.h>

#include <iprt/stdarg.h>
#include <iprt/dbg.h>

RT_C_DECLS_BEGIN


/** @defgroup grp_dbgf     The Debugger Facility API
 * @ingroup grp_vmm
 * @{
 */

#if defined(IN_RC) || defined(IN_RING0)
/** @defgroup grp_dbgf_rz  The RZ DBGF API
 * @{
 */
VMMRZ_INT_DECL(int) DBGFRZTrap01Handler(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, RTGCUINTREG uDr6, bool fAltStepping);
VMMRZ_INT_DECL(int) DBGFRZTrap03Handler(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame);
/** @} */
#endif



#ifdef IN_RING3

/**
 * Mixed address.
 */
typedef struct DBGFADDRESS
{
    /** The flat address. */
    RTGCUINTPTR FlatPtr;
    /** The selector offset address. */
    RTGCUINTPTR off;
    /** The selector. DBGF_SEL_FLAT is a legal value. */
    RTSEL       Sel;
    /** Flags describing further details about the address. */
    uint16_t    fFlags;
} DBGFADDRESS;
/** Pointer to a mixed address. */
typedef DBGFADDRESS *PDBGFADDRESS;
/** Pointer to a const mixed address. */
typedef const DBGFADDRESS *PCDBGFADDRESS;

/** @name DBGFADDRESS Flags.
 * @{ */
/** A 16:16 far address. */
#define DBGFADDRESS_FLAGS_FAR16         0
/** A 16:32 far address. */
#define DBGFADDRESS_FLAGS_FAR32         1
/** A 16:64 far address. */
#define DBGFADDRESS_FLAGS_FAR64         2
/** A flat address. */
#define DBGFADDRESS_FLAGS_FLAT          3
/** A physical address. */
#define DBGFADDRESS_FLAGS_PHYS          4
/** A physical address. */
#define DBGFADDRESS_FLAGS_RING0         5
/** The address type mask. */
#define DBGFADDRESS_FLAGS_TYPE_MASK     7

/** Set if the address is valid. */
#define DBGFADDRESS_FLAGS_VALID         RT_BIT(3)

/** The address is within the hypervisor memoary area (HMA).
 * If not set, the address can be assumed to be a guest address. */
#define DBGFADDRESS_FLAGS_HMA           RT_BIT(4)

/** Checks if the mixed address is flat or not. */
#define DBGFADDRESS_IS_FLAT(pAddress)    ( ((pAddress)->fFlags & DBGFADDRESS_FLAGS_TYPE_MASK) == DBGFADDRESS_FLAGS_FLAT )
/** Checks if the mixed address is flat or not. */
#define DBGFADDRESS_IS_PHYS(pAddress)    ( ((pAddress)->fFlags & DBGFADDRESS_FLAGS_TYPE_MASK) == DBGFADDRESS_FLAGS_PHYS )
/** Checks if the mixed address is far 16:16 or not. */
#define DBGFADDRESS_IS_FAR16(pAddress)   ( ((pAddress)->fFlags & DBGFADDRESS_FLAGS_TYPE_MASK) == DBGFADDRESS_FLAGS_FAR16 )
/** Checks if the mixed address is far 16:32 or not. */
#define DBGFADDRESS_IS_FAR32(pAddress)   ( ((pAddress)->fFlags & DBGFADDRESS_FLAGS_TYPE_MASK) == DBGFADDRESS_FLAGS_FAR32 )
/** Checks if the mixed address is far 16:64 or not. */
#define DBGFADDRESS_IS_FAR64(pAddress)   ( ((pAddress)->fFlags & DBGFADDRESS_FLAGS_TYPE_MASK) == DBGFADDRESS_FLAGS_FAR64 )
/** Checks if the mixed address is valid. */
#define DBGFADDRESS_IS_VALID(pAddress)   ( !!((pAddress)->fFlags & DBGFADDRESS_FLAGS_VALID) )
/** Checks if the address is flagged as within the HMA. */
#define DBGFADDRESS_IS_HMA(pAddress)     ( !!((pAddress)->fFlags & DBGFADDRESS_FLAGS_HMA) )
/** @} */

VMMR3DECL(int)          DBGFR3AddrFromSelOff(PUVM pUVM, VMCPUID idCpu, PDBGFADDRESS pAddress, RTSEL Sel, RTUINTPTR off);
VMMR3DECL(int)          DBGFR3AddrFromSelInfoOff(PUVM pUVM, PDBGFADDRESS pAddress, PCDBGFSELINFO pSelInfo, RTUINTPTR off);
VMMR3DECL(PDBGFADDRESS) DBGFR3AddrFromFlat(PUVM pUVM, PDBGFADDRESS pAddress, RTGCUINTPTR FlatPtr);
VMMR3DECL(PDBGFADDRESS) DBGFR3AddrFromPhys(PUVM pUVM, PDBGFADDRESS pAddress, RTGCPHYS PhysAddr);
VMMR3DECL(bool)         DBGFR3AddrIsValid(PUVM pUVM, PCDBGFADDRESS pAddress);
VMMR3DECL(int)          DBGFR3AddrToPhys(PUVM pUVM, VMCPUID idCpu, PDBGFADDRESS pAddress, PRTGCPHYS pGCPhys);
VMMR3DECL(int)          DBGFR3AddrToHostPhys(PUVM pUVM, VMCPUID idCpu, PDBGFADDRESS pAddress, PRTHCPHYS pHCPhys);
VMMR3DECL(int)          DBGFR3AddrToVolatileR3Ptr(PUVM pUVM, VMCPUID idCpu, PDBGFADDRESS pAddress, bool fReadOnly, void **ppvR3Ptr);
VMMR3DECL(PDBGFADDRESS) DBGFR3AddrAdd(PDBGFADDRESS pAddress, RTGCUINTPTR uAddend);
VMMR3DECL(PDBGFADDRESS) DBGFR3AddrSub(PDBGFADDRESS pAddress, RTGCUINTPTR uSubtrahend);

#endif /* IN_RING3 */



/**
 * VMM Debug Event Type.
 */
typedef enum DBGFEVENTTYPE
{
    /** Halt completed.
     * This notifies that a halt command have been successfully completed.
     */
    DBGFEVENT_HALT_DONE = 0,
    /** Detach completed.
     * This notifies that the detach command have been successfully completed.
     */
    DBGFEVENT_DETACH_DONE,
    /** The command from the debugger is not recognized.
     * This means internal error or half implemented features.
     */
    DBGFEVENT_INVALID_COMMAND,


    /** Fatal error.
     * This notifies a fatal error in the VMM and that the debugger get's a
     * chance to first hand information about the the problem.
     */
    DBGFEVENT_FATAL_ERROR = 100,
    /** Breakpoint Hit.
     * This notifies that a breakpoint installed by the debugger was hit. The
     * identifier of the breakpoint can be found in the DBGFEVENT::u::Bp::iBp member.
     */
    DBGFEVENT_BREAKPOINT,
    /** Breakpoint Hit in the Hypervisor.
     * This notifies that a breakpoint installed by the debugger was hit. The
     * identifier of the breakpoint can be found in the DBGFEVENT::u::Bp::iBp member.
     */
    DBGFEVENT_BREAKPOINT_HYPER,
    /** Assertion in the Hypervisor (breakpoint instruction).
     * This notifies that a breakpoint instruction was hit in the hypervisor context.
     */
    DBGFEVENT_ASSERTION_HYPER,
    /** Single Stepped.
     * This notifies that a single step operation was completed.
     */
    DBGFEVENT_STEPPED,
    /** Single Stepped.
     * This notifies that a hypervisor single step operation was completed.
     */
    DBGFEVENT_STEPPED_HYPER,
    /** The developer have used the DBGFSTOP macro or the PDMDeviceDBGFSTOP function
     * to bring up the debugger at a specific place.
     */
    DBGFEVENT_DEV_STOP,
    /** The VM is powering off.
     * When this notification is received, the debugger thread should detach ASAP.
     */
    DBGFEVENT_POWERING_OFF,

    /** The usual 32-bit hack. */
    DBGFEVENT_32BIT_HACK = 0x7fffffff
} DBGFEVENTTYPE;


/**
 * The context of an event.
 */
typedef enum DBGFEVENTCTX
{
    /** The usual invalid entry. */
    DBGFEVENTCTX_INVALID = 0,
    /** Raw mode. */
    DBGFEVENTCTX_RAW,
    /** Recompiled mode. */
    DBGFEVENTCTX_REM,
    /** VMX / AVT mode. */
    DBGFEVENTCTX_HM,
    /** Hypervisor context. */
    DBGFEVENTCTX_HYPER,
    /** Other mode */
    DBGFEVENTCTX_OTHER,

    /** The usual 32-bit hack */
    DBGFEVENTCTX_32BIT_HACK = 0x7fffffff
} DBGFEVENTCTX;

/**
 * VMM Debug Event.
 */
typedef struct DBGFEVENT
{
    /** Type. */
    DBGFEVENTTYPE   enmType;
    /** Context */
    DBGFEVENTCTX    enmCtx;
    /** Type specific data. */
    union
    {
        /** Fatal error details. */
        struct
        {
            /** The GC return code. */
            int                     rc;
        } FatalError;

        /** Source location. */
        struct
        {
            /** File name. */
            R3PTRTYPE(const char *) pszFile;
            /** Function name. */
            R3PTRTYPE(const char *) pszFunction;
            /** Message. */
            R3PTRTYPE(const char *) pszMessage;
            /** Line number. */
            unsigned                uLine;
        } Src;

        /** Assertion messages. */
        struct
        {
            /** The first message. */
            R3PTRTYPE(const char *) pszMsg1;
            /** The second message. */
            R3PTRTYPE(const char *) pszMsg2;
        } Assert;

        /** Breakpoint. */
        struct DBGFEVENTBP
        {
            /** The identifier of the breakpoint which was hit. */
            RTUINT                  iBp;
        } Bp;
        /** Padding for ensuring that the structure is 8 byte aligned. */
        uint64_t        au64Padding[4];
    } u;
} DBGFEVENT;
/** Pointer to VMM Debug Event. */
typedef DBGFEVENT *PDBGFEVENT;
/** Pointer to const VMM Debug Event. */
typedef const DBGFEVENT *PCDBGFEVENT;

#ifdef IN_RING3 /* The event API only works in ring-3. */

/** @def DBGFSTOP
 * Stops the debugger raising a DBGFEVENT_DEVELOPER_STOP event.
 *
 * @returns VBox status code which must be propagated up to EM if not VINF_SUCCESS.
 * @param   pVM     The cross context VM structure.
 */
# ifdef VBOX_STRICT
#  define DBGFSTOP(pVM)  DBGFR3EventSrc(pVM, DBGFEVENT_DEV_STOP, __FILE__, __LINE__, __PRETTY_FUNCTION__, NULL)
# else
#  define DBGFSTOP(pVM)  VINF_SUCCESS
# endif

VMMR3_INT_DECL(int)     DBGFR3Init(PVM pVM);
VMMR3_INT_DECL(int)     DBGFR3Term(PVM pVM);
VMMR3_INT_DECL(void)    DBGFR3PowerOff(PVM pVM);
VMMR3_INT_DECL(void)    DBGFR3Relocate(PVM pVM, RTGCINTPTR offDelta);
VMMR3_INT_DECL(int)     DBGFR3VMMForcedAction(PVM pVM);
VMMR3DECL(int)          DBGFR3Event(PVM pVM, DBGFEVENTTYPE enmEvent);
VMMR3DECL(int)          DBGFR3EventSrc(PVM pVM, DBGFEVENTTYPE enmEvent, const char *pszFile, unsigned uLine,
                                       const char *pszFunction, const char *pszFormat, ...) RT_IPRT_FORMAT_ATTR_MAYBE_NULL(6, 7);
VMMR3DECL(int)          DBGFR3EventSrcV(PVM pVM, DBGFEVENTTYPE enmEvent, const char *pszFile, unsigned uLine,
                                        const char *pszFunction, const char *pszFormat, va_list args) RT_IPRT_FORMAT_ATTR_MAYBE_NULL(6, 0);
VMMR3_INT_DECL(int)     DBGFR3EventAssertion(PVM pVM, DBGFEVENTTYPE enmEvent, const char *pszMsg1, const char *pszMsg2);
VMMR3_INT_DECL(int)     DBGFR3EventBreakpoint(PVM pVM, DBGFEVENTTYPE enmEvent);
VMMR3_INT_DECL(int)     DBGFR3PrgStep(PVMCPU pVCpu);

VMMR3DECL(int)          DBGFR3Attach(PUVM pUVM);
VMMR3DECL(int)          DBGFR3Detach(PUVM pUVM);
VMMR3DECL(int)          DBGFR3EventWait(PUVM pUVM, RTMSINTERVAL cMillies, PCDBGFEVENT *ppEvent);
VMMR3DECL(int)          DBGFR3Halt(PUVM pUVM);
VMMR3DECL(bool)         DBGFR3IsHalted(PUVM pUVM);
VMMR3DECL(int)          DBGFR3QueryWaitable(PUVM pUVM);
VMMR3DECL(int)          DBGFR3Resume(PUVM pUVM);
VMMR3DECL(int)          DBGFR3Step(PUVM pUVM, VMCPUID idCpu);
VMMR3DECL(int)          DBGFR3InjectNMI(PUVM pUVM, VMCPUID idCpu);

#endif /* IN_RING3 */



/** Breakpoint type. */
typedef enum DBGFBPTYPE
{
    /** Free breakpoint entry. */
    DBGFBPTYPE_FREE = 0,
    /** Debug register. */
    DBGFBPTYPE_REG,
    /** INT 3 instruction. */
    DBGFBPTYPE_INT3,
    /** Recompiler. */
    DBGFBPTYPE_REM,
    /** ensure 32-bit size. */
    DBGFBPTYPE_32BIT_HACK = 0x7fffffff
} DBGFBPTYPE;


/**
 * A Breakpoint.
 */
typedef struct DBGFBP
{
    /** The number of breakpoint hits. */
    uint64_t        cHits;
    /** The hit number which starts to trigger the breakpoint. */
    uint64_t        iHitTrigger;
    /** The hit number which stops triggering the breakpoint (disables it).
     * Use ~(uint64_t)0 if it should never stop. */
    uint64_t        iHitDisable;
    /** The Flat GC address of the breakpoint.
     * (PC register value if REM type?) */
    RTGCUINTPTR     GCPtr;
    /** The breakpoint id. */
    uint32_t        iBp;
    /** The breakpoint status - enabled or disabled. */
    bool            fEnabled;

    /** The breakpoint type. */
    DBGFBPTYPE      enmType;

#if GC_ARCH_BITS == 64
    uint32_t        u32Padding;
#endif

    /** Union of type specific data. */
    union
    {
        /** Debug register data. */
        struct DBGFBPREG
        {
            /** The debug register number. */
            uint8_t     iReg;
            /** The access type (one of the X86_DR7_RW_* value). */
            uint8_t     fType;
            /** The access size. */
            uint8_t     cb;
        } Reg;
        /** Recompiler breakpoint data. */
        struct DBGFBPINT3
        {
            /** The byte value we replaced by the INT 3 instruction. */
            uint8_t     bOrg;
        } Int3;

        /** Recompiler breakpoint data. */
        struct DBGFBPREM
        {
            /** nothing yet */
            uint8_t fDummy;
        } Rem;
        /** Paddind to ensure that the size is identical on win32 and linux. */
        uint64_t    u64Padding;
    } u;
} DBGFBP;

/** Pointer to a breakpoint. */
typedef DBGFBP *PDBGFBP;
/** Pointer to a const breakpoint. */
typedef const DBGFBP *PCDBGFBP;

#ifdef IN_RING3 /* The breakpoint management API is only available in ring-3. */
VMMR3DECL(int)  DBGFR3BpSet(PUVM pUVM, PCDBGFADDRESS pAddress, uint64_t iHitTrigger, uint64_t iHitDisable, uint32_t *piBp);
VMMR3DECL(int)  DBGFR3BpSetReg(PUVM pUVM, PCDBGFADDRESS pAddress, uint64_t iHitTrigger, uint64_t iHitDisable,
                               uint8_t fType, uint8_t cb, uint32_t *piBp);
VMMR3DECL(int)  DBGFR3BpSetREM(PUVM pUVM, PCDBGFADDRESS pAddress, uint64_t iHitTrigger, uint64_t iHitDisable, uint32_t *piBp);
VMMR3DECL(int)  DBGFR3BpClear(PUVM pUVM, uint32_t iBp);
VMMR3DECL(int)  DBGFR3BpEnable(PUVM pUVM, uint32_t iBp);
VMMR3DECL(int)  DBGFR3BpDisable(PUVM pUVM, uint32_t iBp);

/**
 * Breakpoint enumeration callback function.
 *
 * @returns VBox status code. Any failure will stop the enumeration.
 * @param   pUVM        The user mode VM handle.
 * @param   pvUser      The user argument.
 * @param   pBp         Pointer to the breakpoint information. (readonly)
 */
typedef DECLCALLBACK(int) FNDBGFBPENUM(PUVM pUVM, void *pvUser, PCDBGFBP pBp);
/** Pointer to a breakpoint enumeration callback function. */
typedef FNDBGFBPENUM *PFNDBGFBPENUM;

VMMR3DECL(int)              DBGFR3BpEnum(PUVM pUVM, PFNDBGFBPENUM pfnCallback, void *pvUser);
#endif /* IN_RING3 */

VMM_INT_DECL(RTGCUINTREG)   DBGFBpGetDR7(PVM pVM);
VMM_INT_DECL(RTGCUINTREG)   DBGFBpGetDR0(PVM pVM);
VMM_INT_DECL(RTGCUINTREG)   DBGFBpGetDR1(PVM pVM);
VMM_INT_DECL(RTGCUINTREG)   DBGFBpGetDR2(PVM pVM);
VMM_INT_DECL(RTGCUINTREG)   DBGFBpGetDR3(PVM pVM);
VMM_INT_DECL(bool)          DBGFBpIsHwArmed(PVM pVM);
VMM_INT_DECL(bool)          DBGFBpIsHwIoArmed(PVM pVM);
VMM_INT_DECL(bool)          DBGFIsStepping(PVMCPU pVCpu);
VMM_INT_DECL(VBOXSTRICTRC)  DBGFBpCheckIo(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx, RTIOPORT uIoPort, uint8_t cbValue);


#ifdef IN_RING3 /* The CPU mode API only works in ring-3. */
VMMR3DECL(CPUMMODE)         DBGFR3CpuGetMode(PUVM pUVM, VMCPUID idCpu);
VMMR3DECL(VMCPUID)          DBGFR3CpuGetCount(PUVM pUVM);
VMMR3DECL(bool)             DBGFR3CpuIsIn64BitCode(PUVM pUVM, VMCPUID idCpu);
#endif



#ifdef IN_RING3 /* The info callbacks API only works in ring-3. */

/**
 * Info helper callback structure.
 */
typedef struct DBGFINFOHLP
{
    /**
     * Print formatted string.
     *
     * @param   pHlp        Pointer to this structure.
     * @param   pszFormat   The format string.
     * @param   ...         Arguments.
     */
    DECLCALLBACKMEMBER(void, pfnPrintf)(PCDBGFINFOHLP pHlp, const char *pszFormat, ...) RT_IPRT_FORMAT_ATTR(2, 3);

    /**
     * Print formatted string.
     *
     * @param   pHlp        Pointer to this structure.
     * @param   pszFormat   The format string.
     * @param   args        Argument list.
     */
    DECLCALLBACKMEMBER(void, pfnPrintfV)(PCDBGFINFOHLP pHlp, const char *pszFormat, va_list args) RT_IPRT_FORMAT_ATTR(2, 0);
} DBGFINFOHLP;


/**
 * Info handler, device version.
 *
 * @param   pDevIns     The device instance which registered the info.
 * @param   pHlp        Callback functions for doing output.
 * @param   pszArgs     Argument string. Optional and specific to the handler.
 */
typedef DECLCALLBACK(void) FNDBGFHANDLERDEV(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs);
/** Pointer to a FNDBGFHANDLERDEV function. */
typedef FNDBGFHANDLERDEV  *PFNDBGFHANDLERDEV;

/**
 * Info handler, USB device version.
 *
 * @param   pUsbIns     The USB device instance which registered the info.
 * @param   pHlp        Callback functions for doing output.
 * @param   pszArgs     Argument string. Optional and specific to the handler.
 */
typedef DECLCALLBACK(void) FNDBGFHANDLERUSB(PPDMUSBINS pUsbIns, PCDBGFINFOHLP pHlp, const char *pszArgs);
/** Pointer to a FNDBGFHANDLERUSB function. */
typedef FNDBGFHANDLERUSB  *PFNDBGFHANDLERUSB;

/**
 * Info handler, driver version.
 *
 * @param   pDrvIns     The driver instance which registered the info.
 * @param   pHlp        Callback functions for doing output.
 * @param   pszArgs     Argument string. Optional and specific to the handler.
 */
typedef DECLCALLBACK(void) FNDBGFHANDLERDRV(PPDMDRVINS pDrvIns, PCDBGFINFOHLP pHlp, const char *pszArgs);
/** Pointer to a FNDBGFHANDLERDRV function. */
typedef FNDBGFHANDLERDRV  *PFNDBGFHANDLERDRV;

/**
 * Info handler, internal version.
 *
 * @param   pVM         The cross context VM structure.
 * @param   pHlp        Callback functions for doing output.
 * @param   pszArgs     Argument string. Optional and specific to the handler.
 */
typedef DECLCALLBACK(void) FNDBGFHANDLERINT(PVM pVM, PCDBGFINFOHLP pHlp, const char *pszArgs);
/** Pointer to a FNDBGFHANDLERINT function. */
typedef FNDBGFHANDLERINT  *PFNDBGFHANDLERINT;

/**
 * Info handler, external version.
 *
 * @param   pvUser      User argument.
 * @param   pHlp        Callback functions for doing output.
 * @param   pszArgs     Argument string. Optional and specific to the handler.
 */
typedef DECLCALLBACK(void) FNDBGFHANDLEREXT(void *pvUser, PCDBGFINFOHLP pHlp, const char *pszArgs);
/** Pointer to a FNDBGFHANDLEREXT function. */
typedef FNDBGFHANDLEREXT  *PFNDBGFHANDLEREXT;


/** @name Flags for the info registration functions.
 * @{ */
/** The handler must run on the EMT. */
#define DBGFINFO_FLAGS_RUN_ON_EMT       RT_BIT(0)
/** @} */

VMMR3_INT_DECL(int) DBGFR3InfoRegisterDevice(PVM pVM, const char *pszName, const char *pszDesc, PFNDBGFHANDLERDEV pfnHandler, PPDMDEVINS pDevIns);
VMMR3_INT_DECL(int) DBGFR3InfoRegisterDriver(PVM pVM, const char *pszName, const char *pszDesc, PFNDBGFHANDLERDRV pfnHandler, PPDMDRVINS pDrvIns);
VMMR3_INT_DECL(int) DBGFR3InfoRegisterInternal(PVM pVM, const char *pszName, const char *pszDesc, PFNDBGFHANDLERINT pfnHandler);
VMMR3_INT_DECL(int) DBGFR3InfoRegisterInternalEx(PVM pVM, const char *pszName, const char *pszDesc, PFNDBGFHANDLERINT pfnHandler, uint32_t fFlags);
VMMR3DECL(int)      DBGFR3InfoRegisterExternal(PUVM pUVM, const char *pszName, const char *pszDesc, PFNDBGFHANDLEREXT pfnHandler, void *pvUser);
VMMR3_INT_DECL(int) DBGFR3InfoDeregisterDevice(PVM pVM, PPDMDEVINS pDevIns, const char *pszName);
VMMR3_INT_DECL(int) DBGFR3InfoDeregisterDriver(PVM pVM, PPDMDRVINS pDrvIns, const char *pszName);
VMMR3_INT_DECL(int) DBGFR3InfoDeregisterInternal(PVM pVM, const char *pszName);
VMMR3DECL(int)      DBGFR3InfoDeregisterExternal(PUVM pUVM, const char *pszName);
VMMR3DECL(int)      DBGFR3Info(PUVM pUVM, const char *pszName, const char *pszArgs, PCDBGFINFOHLP pHlp);
VMMR3DECL(int)      DBGFR3InfoEx(PUVM pUVM, VMCPUID idCpu, const char *pszName, const char *pszArgs, PCDBGFINFOHLP pHlp);
VMMR3DECL(int)      DBGFR3InfoLogRel(PUVM pUVM, const char *pszName, const char *pszArgs);
VMMR3DECL(int)      DBGFR3InfoStdErr(PUVM pUVM, const char *pszName, const char *pszArgs);
VMMR3_INT_DECL(int) DBGFR3InfoMulti(PVM pVM, const char *pszIncludePat, const char *pszExcludePat,
                                    const char *pszSepFmt, PCDBGFINFOHLP pHlp);

/** @def DBGFR3_INFO_LOG
 * Display a piece of info writing to the log if enabled.
 *
 * @param   a_pVM       The shared VM handle.
 * @param   a_pszName   The identifier of the info to display.
 * @param   a_pszArgs   Arguments to the info handler.
 */
#ifdef LOG_ENABLED
# define DBGFR3_INFO_LOG(a_pVM, a_pszName, a_pszArgs) \
    do { \
        if (LogIsEnabled()) \
            DBGFR3Info((a_pVM)->pUVM, a_pszName, a_pszArgs, NULL); \
    } while (0)
#else
# define DBGFR3_INFO_LOG(a_pVM, a_pszName, a_pszArgs) do { } while (0)
#endif

/**
 * Enumeration callback for use with DBGFR3InfoEnum.
 *
 * @returns VBox status code.
 *          A status code indicating failure will end the enumeration
 *          and DBGFR3InfoEnum will return with that status code.
 * @param   pUVM        The user mode VM handle.
 * @param   pszName     Info identifier name.
 * @param   pszDesc     The description.
 */
typedef DECLCALLBACK(int) FNDBGFINFOENUM(PUVM pUVM, const char *pszName, const char *pszDesc, void *pvUser);
/** Pointer to a FNDBGFINFOENUM function. */
typedef FNDBGFINFOENUM *PFNDBGFINFOENUM;

VMMR3DECL(int)              DBGFR3InfoEnum(PUVM pUVM, PFNDBGFINFOENUM pfnCallback, void *pvUser);
VMMR3DECL(PCDBGFINFOHLP)    DBGFR3InfoLogHlp(void);
VMMR3DECL(PCDBGFINFOHLP)    DBGFR3InfoLogRelHlp(void);

#endif /* IN_RING3 */


#ifdef IN_RING3 /* The log contrl API only works in ring-3. */
VMMR3DECL(int) DBGFR3LogModifyGroups(PUVM pUVM, const char *pszGroupSettings);
VMMR3DECL(int) DBGFR3LogModifyFlags(PUVM pUVM, const char *pszFlagSettings);
VMMR3DECL(int) DBGFR3LogModifyDestinations(PUVM pUVM, const char *pszDestSettings);
#endif /* IN_RING3 */

#ifdef IN_RING3 /* The debug information management APIs only works in ring-3. */

/** Max length (including '\\0') of a symbol name. */
#define DBGF_SYMBOL_NAME_LENGTH   512

/**
 * Debug symbol.
 */
typedef struct DBGFSYMBOL
{
    /** Symbol value (address). */
    RTGCUINTPTR         Value;
    /** Symbol size. */
    uint32_t            cb;
    /** Symbol Flags. (reserved). */
    uint32_t            fFlags;
    /** Symbol name. */
    char                szName[DBGF_SYMBOL_NAME_LENGTH];
} DBGFSYMBOL;
/** Pointer to debug symbol. */
typedef DBGFSYMBOL *PDBGFSYMBOL;
/** Pointer to const debug symbol. */
typedef const DBGFSYMBOL *PCDBGFSYMBOL;

/**
 * Debug line number information.
 */
typedef struct DBGFLINE
{
    /** Address. */
    RTGCUINTPTR         Address;
    /** Line number. */
    uint32_t            uLineNo;
    /** Filename. */
    char                szFilename[260];
} DBGFLINE;
/** Pointer to debug line number. */
typedef DBGFLINE *PDBGFLINE;
/** Pointer to const debug line number. */
typedef const DBGFLINE *PCDBGFLINE;

/** @name Address spaces aliases.
 * @{ */
/** The guest global address space. */
#define DBGF_AS_GLOBAL              ((RTDBGAS)-1)
/** The guest kernel address space.
 * This is usually resolves to the same as DBGF_AS_GLOBAL. */
#define DBGF_AS_KERNEL              ((RTDBGAS)-2)
/** The physical address space. */
#define DBGF_AS_PHYS                ((RTDBGAS)-3)
/** Raw-mode context. */
#define DBGF_AS_RC                  ((RTDBGAS)-4)
/** Ring-0 context. */
#define DBGF_AS_R0                  ((RTDBGAS)-5)
/** Raw-mode context and then global guest context.
 * When used for looking up information, it works as if the call was first made
 * with DBGF_AS_RC and then on failure with DBGF_AS_GLOBAL. When called for
 * making address space changes, it works as if DBGF_AS_RC was used. */
#define DBGF_AS_RC_AND_GC_GLOBAL    ((RTDBGAS)-6)

/** The first special one. */
#define DBGF_AS_FIRST               DBGF_AS_RC_AND_GC_GLOBAL
/** The last special one. */
#define DBGF_AS_LAST                DBGF_AS_GLOBAL
#endif
/** The number of special address space handles. */
#define DBGF_AS_COUNT               (6U)
#ifdef IN_RING3
/** Converts an alias handle to an array index. */
#define DBGF_AS_ALIAS_2_INDEX(hAlias) \
    ( (uintptr_t)(hAlias) - (uintptr_t)DBGF_AS_FIRST )
/** Predicat macro that check if the specified handle is an alias. */
#define DBGF_AS_IS_ALIAS(hAlias) \
    ( DBGF_AS_ALIAS_2_INDEX(hAlias)  <  DBGF_AS_COUNT )
/** Predicat macro that check if the specified alias is a fixed one or not. */
#define DBGF_AS_IS_FIXED_ALIAS(hAlias) \
    ( DBGF_AS_ALIAS_2_INDEX(hAlias)  <  (uintptr_t)DBGF_AS_PHYS - (uintptr_t)DBGF_AS_FIRST + 1U )

/** @} */

VMMR3DECL(RTDBGCFG)     DBGFR3AsGetConfig(PUVM pUVM);

VMMR3DECL(int)          DBGFR3AsAdd(PUVM pUVM, RTDBGAS hDbgAs, RTPROCESS ProcId);
VMMR3DECL(int)          DBGFR3AsDelete(PUVM pUVM, RTDBGAS hDbgAs);
VMMR3DECL(int)          DBGFR3AsSetAlias(PUVM pUVM, RTDBGAS hAlias, RTDBGAS hAliasFor);
VMMR3DECL(RTDBGAS)      DBGFR3AsResolve(PUVM pUVM, RTDBGAS hAlias);
VMMR3DECL(RTDBGAS)      DBGFR3AsResolveAndRetain(PUVM pUVM, RTDBGAS hAlias);
VMMR3DECL(RTDBGAS)      DBGFR3AsQueryByName(PUVM pUVM, const char *pszName);
VMMR3DECL(RTDBGAS)      DBGFR3AsQueryByPid(PUVM pUVM, RTPROCESS ProcId);

VMMR3DECL(int)          DBGFR3AsLoadImage(PUVM pUVM, RTDBGAS hDbgAs, const char *pszFilename, const char *pszModName,
                                          RTLDRARCH enmArch, PCDBGFADDRESS pModAddress, RTDBGSEGIDX iModSeg, uint32_t fFlags);
VMMR3DECL(int)          DBGFR3AsLoadMap(PUVM pUVM, RTDBGAS hDbgAs, const char *pszFilename, const char *pszModName, PCDBGFADDRESS pModAddress, RTDBGSEGIDX iModSeg, RTGCUINTPTR uSubtrahend, uint32_t fFlags);
VMMR3DECL(int)          DBGFR3AsLinkModule(PUVM pUVM, RTDBGAS hDbgAs, RTDBGMOD hMod, PCDBGFADDRESS pModAddress, RTDBGSEGIDX iModSeg, uint32_t fFlags);
VMMR3DECL(int)          DBGFR3AsUnlinkModuleByName(PUVM pUVM, RTDBGAS hDbgAs, const char *pszModName);

VMMR3DECL(int)          DBGFR3AsSymbolByAddr(PUVM pUVM, RTDBGAS hDbgAs, PCDBGFADDRESS pAddress, uint32_t fFlags,
                                             PRTGCINTPTR poffDisp, PRTDBGSYMBOL pSymbol, PRTDBGMOD phMod);
VMMR3DECL(PRTDBGSYMBOL) DBGFR3AsSymbolByAddrA(PUVM pUVM, RTDBGAS hDbgAs, PCDBGFADDRESS pAddress, uint32_t Flags,
                                              PRTGCINTPTR poffDisp, PRTDBGMOD phMod);
VMMR3DECL(int)          DBGFR3AsSymbolByName(PUVM pUVM, RTDBGAS hDbgAs, const char *pszSymbol, PRTDBGSYMBOL pSymbol, PRTDBGMOD phMod);

VMMR3DECL(int)          DBGFR3AsLineByAddr(PUVM pUVM, RTDBGAS hDbgAs, PCDBGFADDRESS pAddress,
                                           PRTGCINTPTR poffDisp, PRTDBGLINE pLine, PRTDBGMOD phMod);
VMMR3DECL(PRTDBGLINE)   DBGFR3AsLineByAddrA(PUVM pUVM, RTDBGAS hDbgAs, PCDBGFADDRESS pAddress,
                                            PRTGCINTPTR poffDisp, PRTDBGMOD phMod);

#endif /* IN_RING3 */

#ifdef IN_RING3 /* The stack API only works in ring-3. */

/**
 * Return type.
 */
typedef enum DBGFRETRUNTYPE
{
    /** The usual invalid 0 value. */
    DBGFRETURNTYPE_INVALID = 0,
    /** Near 16-bit return. */
    DBGFRETURNTYPE_NEAR16,
    /** Near 32-bit return. */
    DBGFRETURNTYPE_NEAR32,
    /** Near 64-bit return. */
    DBGFRETURNTYPE_NEAR64,
    /** Far 16:16 return. */
    DBGFRETURNTYPE_FAR16,
    /** Far 16:32 return. */
    DBGFRETURNTYPE_FAR32,
    /** Far 16:64 return. */
    DBGFRETURNTYPE_FAR64,
    /** 16-bit iret return (e.g. real or 286 protect mode). */
    DBGFRETURNTYPE_IRET16,
    /** 32-bit iret return. */
    DBGFRETURNTYPE_IRET32,
    /** 32-bit iret return. */
    DBGFRETURNTYPE_IRET32_PRIV,
    /** 32-bit iret return to V86 mode. */
    DBGFRETURNTYPE_IRET32_V86,
    /** @todo 64-bit iret return. */
    DBGFRETURNTYPE_IRET64,
    /** The end of the valid return types. */
    DBGFRETURNTYPE_END,
    /** The usual 32-bit blowup. */
    DBGFRETURNTYPE_32BIT_HACK = 0x7fffffff
} DBGFRETURNTYPE;

/**
 * Figures the size of the return state on the stack.
 *
 * @returns number of bytes. 0 if invalid parameter.
 * @param   enmRetType  The type of return.
 */
DECLINLINE(unsigned) DBGFReturnTypeSize(DBGFRETURNTYPE enmRetType)
{
    switch (enmRetType)
    {
        case DBGFRETURNTYPE_NEAR16:         return 2;
        case DBGFRETURNTYPE_NEAR32:         return 4;
        case DBGFRETURNTYPE_NEAR64:         return 8;
        case DBGFRETURNTYPE_FAR16:          return 4;
        case DBGFRETURNTYPE_FAR32:          return 4;
        case DBGFRETURNTYPE_FAR64:          return 8;
        case DBGFRETURNTYPE_IRET16:         return 6;
        case DBGFRETURNTYPE_IRET32:         return 4*3;
        case DBGFRETURNTYPE_IRET32_PRIV:    return 4*5;
        case DBGFRETURNTYPE_IRET32_V86:     return 4*9;
        case DBGFRETURNTYPE_IRET64:
        default:
            return 0;
    }
}


/** Pointer to stack frame info. */
typedef struct DBGFSTACKFRAME *PDBGFSTACKFRAME;
/** Pointer to const stack frame info. */
typedef struct DBGFSTACKFRAME const  *PCDBGFSTACKFRAME;
/**
 * Info about a stack frame.
 */
typedef struct DBGFSTACKFRAME
{
    /** Frame number. */
    uint32_t        iFrame;
    /** Frame flags. */
    uint32_t        fFlags;
    /** The frame address.
     * The off member is [e|r]bp and the Sel member is ss. */
    DBGFADDRESS     AddrFrame;
    /** The stack address of the frame.
     * The off member is [e|r]sp and the Sel member is ss. */
    DBGFADDRESS     AddrStack;
    /** The program counter (PC) address of the frame.
     * The off member is [e|r]ip and the Sel member is cs. */
    DBGFADDRESS     AddrPC;
    /** Pointer to the symbol nearest the program counter (PC). NULL if not found. */
    PRTDBGSYMBOL    pSymPC;
    /** Pointer to the linnumber nearest the program counter (PC). NULL if not found. */
    PRTDBGLINE      pLinePC;

    /** The return frame address.
     * The off member is [e|r]bp and the Sel member is ss. */
    DBGFADDRESS     AddrReturnFrame;
    /** The return stack address.
     * The off member is [e|r]sp and the Sel member is ss. */
    DBGFADDRESS     AddrReturnStack;
    /** The way this frame returns to the next one. */
    DBGFRETURNTYPE  enmReturnType;

    /** The program counter (PC) address which the frame returns to.
     * The off member is [e|r]ip and the Sel member is cs. */
    DBGFADDRESS     AddrReturnPC;
    /** Pointer to the symbol nearest the return PC. NULL if not found. */
    PRTDBGSYMBOL    pSymReturnPC;
    /** Pointer to the linnumber nearest the return PC. NULL if not found. */
    PRTDBGLINE      pLineReturnPC;

    /** 32-bytes of stack arguments. */
    union
    {
        /** 64-bit view */
        uint64_t    au64[4];
        /** 32-bit view */
        uint32_t    au32[8];
        /** 16-bit view */
        uint16_t    au16[16];
        /** 8-bit view */
        uint8_t     au8[32];
    } Args;

    /** Pointer to the next frame.
     * Might not be used in some cases, so consider it internal. */
    PCDBGFSTACKFRAME pNextInternal;
    /** Pointer to the first frame.
     * Might not be used in some cases, so consider it internal. */
    PCDBGFSTACKFRAME pFirstInternal;
} DBGFSTACKFRAME;

/** @name DBGFSTACKFRAME Flags.
 * @{ */
/** Set if the content of the frame is filled in by DBGFR3StackWalk() and can be used
 * to construct the next frame. */
# define DBGFSTACKFRAME_FLAGS_ALL_VALID RT_BIT(0)
/** This is the last stack frame we can read.
 * This flag is not set if the walk stop because of max dept or recursion. */
# define DBGFSTACKFRAME_FLAGS_LAST      RT_BIT(1)
/** This is the last record because we detected a loop. */
# define DBGFSTACKFRAME_FLAGS_LOOP      RT_BIT(2)
/** This is the last record because we reached the maximum depth. */
# define DBGFSTACKFRAME_FLAGS_MAX_DEPTH RT_BIT(3)
/** 16-bit frame. */
# define DBGFSTACKFRAME_FLAGS_16BIT     RT_BIT(4)
/** 32-bit frame. */
# define DBGFSTACKFRAME_FLAGS_32BIT     RT_BIT(5)
/** 64-bit frame. */
# define DBGFSTACKFRAME_FLAGS_64BIT     RT_BIT(6)
/** @} */

/** @name DBGFCODETYPE
 * @{ */
typedef enum DBGFCODETYPE
{
    /** The usual invalid 0 value. */
    DBGFCODETYPE_INVALID = 0,
    /** Stack walk for guest code. */
    DBGFCODETYPE_GUEST,
    /** Stack walk for hypervisor code. */
    DBGFCODETYPE_HYPER,
    /** Stack walk for ring 0 code. */
    DBGFCODETYPE_RING0,
    /** The usual 32-bit blowup. */
    DBGFCODETYPE_32BIT_HACK = 0x7fffffff
} DBGFCODETYPE;
/** @} */

VMMR3DECL(int)              DBGFR3StackWalkBegin(PUVM pUVM, VMCPUID idCpu, DBGFCODETYPE enmCodeType,
                                                 PCDBGFSTACKFRAME *ppFirstFrame);
VMMR3DECL(int)              DBGFR3StackWalkBeginEx(PUVM pUVM, VMCPUID idCpu, DBGFCODETYPE enmCodeType, PCDBGFADDRESS pAddrFrame,
                                                   PCDBGFADDRESS pAddrStack,PCDBGFADDRESS pAddrPC,
                                                   DBGFRETURNTYPE enmReturnType, PCDBGFSTACKFRAME *ppFirstFrame);
VMMR3DECL(PCDBGFSTACKFRAME) DBGFR3StackWalkNext(PCDBGFSTACKFRAME pCurrent);
VMMR3DECL(void)             DBGFR3StackWalkEnd(PCDBGFSTACKFRAME pFirstFrame);

#endif /* IN_RING3 */


#ifdef IN_RING3 /* The disassembly API only works in ring-3. */

/** @name Flags to pass to DBGFR3DisasInstrEx().
 * @{ */
/** Disassemble the current guest instruction, with annotations. */
#define DBGF_DISAS_FLAGS_CURRENT_GUEST      RT_BIT(0)
/** Disassemble the current hypervisor instruction, with annotations. */
#define DBGF_DISAS_FLAGS_CURRENT_HYPER      RT_BIT(1)
/** No annotations for current context. */
#define DBGF_DISAS_FLAGS_NO_ANNOTATION      RT_BIT(2)
/** No symbol lookup. */
#define DBGF_DISAS_FLAGS_NO_SYMBOLS         RT_BIT(3)
/** No instruction bytes. */
#define DBGF_DISAS_FLAGS_NO_BYTES           RT_BIT(4)
/** No address in the output. */
#define DBGF_DISAS_FLAGS_NO_ADDRESS         RT_BIT(5)
/** Probably a hypervisor instruction. */
#define DBGF_DISAS_FLAGS_HYPER              RT_BIT(6)
/** Disassemble original unpatched bytes (PATM). */
#define DBGF_DISAS_FLAGS_UNPATCHED_BYTES    RT_BIT(7)
/** Annotate patched instructions. */
#define DBGF_DISAS_FLAGS_ANNOTATE_PATCHED   RT_BIT(8)
/** Disassemble in the default mode of the specific context. */
#define DBGF_DISAS_FLAGS_DEFAULT_MODE       UINT32_C(0x00000000)
/** Disassemble in 16-bit mode. */
#define DBGF_DISAS_FLAGS_16BIT_MODE         UINT32_C(0x10000000)
/** Disassemble in 16-bit mode with real mode address translation. */
#define DBGF_DISAS_FLAGS_16BIT_REAL_MODE    UINT32_C(0x20000000)
/** Disassemble in 32-bit mode. */
#define DBGF_DISAS_FLAGS_32BIT_MODE         UINT32_C(0x30000000)
/** Disassemble in 64-bit mode. */
#define DBGF_DISAS_FLAGS_64BIT_MODE         UINT32_C(0x40000000)
/** The disassembly mode mask. */
#define DBGF_DISAS_FLAGS_MODE_MASK          UINT32_C(0x70000000)
/** Mask containing the valid flags. */
#define DBGF_DISAS_FLAGS_VALID_MASK         UINT32_C(0x700001ff)
/** @} */

/** Special flat selector. */
#define DBGF_SEL_FLAT                       1

VMMR3DECL(int)      DBGFR3DisasInstrEx(PUVM pUVM, VMCPUID idCpu, RTSEL Sel, RTGCPTR GCPtr, uint32_t fFlags,
                                       char *pszOutput, uint32_t cbOutput, uint32_t *pcbInstr);
VMMR3_INT_DECL(int) DBGFR3DisasInstrCurrent(PVMCPU pVCpu, char *pszOutput, uint32_t cbOutput);
VMMR3DECL(int)      DBGFR3DisasInstrCurrentLogInternal(PVMCPU pVCpu, const char *pszPrefix);

/** @def DBGFR3_DISAS_INSTR_CUR_LOG
 * Disassembles the current guest context instruction and writes it to the log.
 * All registers and data will be displayed. Addresses will be attempted resolved to symbols.
 */
#ifdef LOG_ENABLED
# define DBGFR3_DISAS_INSTR_CUR_LOG(pVCpu, pszPrefix) \
    do { \
        if (LogIsEnabled()) \
            DBGFR3DisasInstrCurrentLogInternal(pVCpu, pszPrefix); \
    } while (0)
#else
# define DBGFR3_DISAS_INSTR_CUR_LOG(pVCpu, pszPrefix) do { } while (0)
#endif

VMMR3DECL(int) DBGFR3DisasInstrLogInternal(PVMCPU pVCpu, RTSEL Sel, RTGCPTR GCPtr, const char *pszPrefix);

/** @def DBGFR3_DISAS_INSTR_LOG
 * Disassembles the specified guest context instruction and writes it to the log.
 * Addresses will be attempted resolved to symbols.
 * @thread Any EMT.
 */
# ifdef LOG_ENABLED
#  define DBGFR3_DISAS_INSTR_LOG(pVCpu, Sel, GCPtr, pszPrefix) \
    do { \
        if (LogIsEnabled()) \
            DBGFR3DisasInstrLogInternal(pVCpu, Sel, GCPtr, pszPrefix); \
    } while (0)
# else
#  define DBGFR3_DISAS_INSTR_LOG(pVCpu, Sel, GCPtr, pszPrefix) do { } while (0)
# endif
#endif


#ifdef IN_RING3
VMMR3DECL(int) DBGFR3MemScan(PUVM pUVM, VMCPUID idCpu, PCDBGFADDRESS pAddress, RTGCUINTPTR cbRange, RTGCUINTPTR uAlign,
                             const void *pvNeedle, size_t cbNeedle, PDBGFADDRESS pHitAddress);
VMMR3DECL(int) DBGFR3MemRead(PUVM pUVM, VMCPUID idCpu, PCDBGFADDRESS pAddress, void *pvBuf, size_t cbRead);
VMMR3DECL(int) DBGFR3MemReadString(PUVM pUVM, VMCPUID idCpu, PCDBGFADDRESS pAddress, char *pszBuf, size_t cbBuf);
VMMR3DECL(int) DBGFR3MemWrite(PUVM pUVM, VMCPUID idCpu, PCDBGFADDRESS pAddress, void const *pvBuf, size_t cbRead);
#endif


/** @name Flags for DBGFR3PagingDumpEx, PGMR3DumpHierarchyHCEx and
 * PGMR3DumpHierarchyGCEx
 * @{ */
/** The CR3 from the current CPU state. */
#define DBGFPGDMP_FLAGS_CURRENT_CR3     RT_BIT_32(0)
/** The current CPU paging mode (PSE, PAE, LM, EPT, NX). */
#define DBGFPGDMP_FLAGS_CURRENT_MODE    RT_BIT_32(1)
/** Whether PSE is enabled (!DBGFPGDMP_FLAGS_CURRENT_STATE).
 * Same value as X86_CR4_PSE. */
#define DBGFPGDMP_FLAGS_PSE             RT_BIT_32(4) /*  */
/** Whether PAE is enabled (!DBGFPGDMP_FLAGS_CURRENT_STATE).
 * Same value as X86_CR4_PAE. */
#define DBGFPGDMP_FLAGS_PAE             RT_BIT_32(5) /*  */
/** Whether LME is enabled (!DBGFPGDMP_FLAGS_CURRENT_STATE).
 * Same value as MSR_K6_EFER_LME. */
#define DBGFPGDMP_FLAGS_LME             RT_BIT_32(8)
/** Whether nested paging is enabled (!DBGFPGDMP_FLAGS_CURRENT_STATE). */
#define DBGFPGDMP_FLAGS_NP              RT_BIT_32(9)
/** Whether extended nested page tables are enabled
 * (!DBGFPGDMP_FLAGS_CURRENT_STATE). */
#define DBGFPGDMP_FLAGS_EPT             RT_BIT_32(10)
/** Whether no-execution is enabled (!DBGFPGDMP_FLAGS_CURRENT_STATE).
 * Same value as MSR_K6_EFER_NXE. */
#define DBGFPGDMP_FLAGS_NXE             RT_BIT_32(11)
/** Whether to print the CR3. */
#define DBGFPGDMP_FLAGS_PRINT_CR3       RT_BIT_32(27)
/** Whether to print the header. */
#define DBGFPGDMP_FLAGS_HEADER          RT_BIT_32(28)
/** Whether to dump additional page information. */
#define DBGFPGDMP_FLAGS_PAGE_INFO       RT_BIT_32(29)
/** Dump the shadow tables if set.
 * Cannot be used together with DBGFPGDMP_FLAGS_GUEST. */
#define DBGFPGDMP_FLAGS_SHADOW          RT_BIT_32(30)
/** Dump the guest tables if set.
 * Cannot be used together with DBGFPGDMP_FLAGS_SHADOW. */
#define DBGFPGDMP_FLAGS_GUEST           RT_BIT_32(31)
/** Mask of valid bits. */
#define DBGFPGDMP_FLAGS_VALID_MASK      UINT32_C(0xf8000f33)
/** The mask of bits controlling the paging mode. */
#define DBGFPGDMP_FLAGS_MODE_MASK       UINT32_C(0x00000f32)
/** @}  */
VMMDECL(int) DBGFR3PagingDumpEx(PUVM pUVM, VMCPUID idCpu, uint32_t fFlags, uint64_t cr3, uint64_t u64FirstAddr,
                                uint64_t u64LastAddr, uint32_t cMaxDepth, PCDBGFINFOHLP pHlp);


/** @name DBGFR3SelQueryInfo flags.
 * @{ */
/** Get the info from the guest descriptor table. */
#define DBGFSELQI_FLAGS_DT_GUEST            UINT32_C(0)
/** Get the info from the shadow descriptor table.
 * Only works in raw-mode.  */
#define DBGFSELQI_FLAGS_DT_SHADOW           UINT32_C(1)
/** If currently executing in in 64-bit mode, blow up data selectors. */
#define DBGFSELQI_FLAGS_DT_ADJ_64BIT_MODE   UINT32_C(2)
/** @} */
VMMR3DECL(int) DBGFR3SelQueryInfo(PUVM pUVM, VMCPUID idCpu, RTSEL Sel, uint32_t fFlags, PDBGFSELINFO pSelInfo);


/**
 * Register identifiers.
 */
typedef enum DBGFREG
{
    /* General purpose registers: */
    DBGFREG_AL  = 0,
    DBGFREG_AX  = DBGFREG_AL,
    DBGFREG_EAX = DBGFREG_AL,
    DBGFREG_RAX = DBGFREG_AL,

    DBGFREG_CL,
    DBGFREG_CX  = DBGFREG_CL,
    DBGFREG_ECX = DBGFREG_CL,
    DBGFREG_RCX = DBGFREG_CL,

    DBGFREG_DL,
    DBGFREG_DX  = DBGFREG_DL,
    DBGFREG_EDX = DBGFREG_DL,
    DBGFREG_RDX = DBGFREG_DL,

    DBGFREG_BL,
    DBGFREG_BX  = DBGFREG_BL,
    DBGFREG_EBX = DBGFREG_BL,
    DBGFREG_RBX = DBGFREG_BL,

    DBGFREG_SPL,
    DBGFREG_SP  = DBGFREG_SPL,
    DBGFREG_ESP = DBGFREG_SPL,
    DBGFREG_RSP = DBGFREG_SPL,

    DBGFREG_BPL,
    DBGFREG_BP  = DBGFREG_BPL,
    DBGFREG_EBP = DBGFREG_BPL,
    DBGFREG_RBP = DBGFREG_BPL,

    DBGFREG_SIL,
    DBGFREG_SI  = DBGFREG_SIL,
    DBGFREG_ESI = DBGFREG_SIL,
    DBGFREG_RSI = DBGFREG_SIL,

    DBGFREG_DIL,
    DBGFREG_DI  = DBGFREG_DIL,
    DBGFREG_EDI = DBGFREG_DIL,
    DBGFREG_RDI = DBGFREG_DIL,

    DBGFREG_R8,
    DBGFREG_R8B = DBGFREG_R8,
    DBGFREG_R8W = DBGFREG_R8,
    DBGFREG_R8D = DBGFREG_R8,

    DBGFREG_R9,
    DBGFREG_R9B = DBGFREG_R9,
    DBGFREG_R9W = DBGFREG_R9,
    DBGFREG_R9D = DBGFREG_R9,

    DBGFREG_R10,
    DBGFREG_R10B = DBGFREG_R10,
    DBGFREG_R10W = DBGFREG_R10,
    DBGFREG_R10D = DBGFREG_R10,

    DBGFREG_R11,
    DBGFREG_R11B = DBGFREG_R11,
    DBGFREG_R11W = DBGFREG_R11,
    DBGFREG_R11D = DBGFREG_R11,

    DBGFREG_R12,
    DBGFREG_R12B = DBGFREG_R12,
    DBGFREG_R12W = DBGFREG_R12,
    DBGFREG_R12D = DBGFREG_R12,

    DBGFREG_R13,
    DBGFREG_R13B = DBGFREG_R13,
    DBGFREG_R13W = DBGFREG_R13,
    DBGFREG_R13D = DBGFREG_R13,

    DBGFREG_R14,
    DBGFREG_R14B = DBGFREG_R14,
    DBGFREG_R14W = DBGFREG_R14,
    DBGFREG_R14D = DBGFREG_R14,

    DBGFREG_R15,
    DBGFREG_R15B = DBGFREG_R15,
    DBGFREG_R15W = DBGFREG_R15,
    DBGFREG_R15D = DBGFREG_R15,

    /* Segments and other special registers: */
    DBGFREG_CS,
    DBGFREG_CS_ATTR,
    DBGFREG_CS_BASE,
    DBGFREG_CS_LIMIT,

    DBGFREG_DS,
    DBGFREG_DS_ATTR,
    DBGFREG_DS_BASE,
    DBGFREG_DS_LIMIT,

    DBGFREG_ES,
    DBGFREG_ES_ATTR,
    DBGFREG_ES_BASE,
    DBGFREG_ES_LIMIT,

    DBGFREG_FS,
    DBGFREG_FS_ATTR,
    DBGFREG_FS_BASE,
    DBGFREG_FS_LIMIT,

    DBGFREG_GS,
    DBGFREG_GS_ATTR,
    DBGFREG_GS_BASE,
    DBGFREG_GS_LIMIT,

    DBGFREG_SS,
    DBGFREG_SS_ATTR,
    DBGFREG_SS_BASE,
    DBGFREG_SS_LIMIT,

    DBGFREG_IP,
    DBGFREG_EIP = DBGFREG_IP,
    DBGFREG_RIP = DBGFREG_IP,

    DBGFREG_FLAGS,
    DBGFREG_EFLAGS = DBGFREG_FLAGS,
    DBGFREG_RFLAGS = DBGFREG_FLAGS,

    /* FPU: */
    DBGFREG_FCW,
    DBGFREG_FSW,
    DBGFREG_FTW,
    DBGFREG_FOP,
    DBGFREG_FPUIP,
    DBGFREG_FPUCS,
    DBGFREG_FPUDP,
    DBGFREG_FPUDS,
    DBGFREG_MXCSR,
    DBGFREG_MXCSR_MASK,

    DBGFREG_ST0,
    DBGFREG_ST1,
    DBGFREG_ST2,
    DBGFREG_ST3,
    DBGFREG_ST4,
    DBGFREG_ST5,
    DBGFREG_ST6,
    DBGFREG_ST7,

    DBGFREG_MM0,
    DBGFREG_MM1,
    DBGFREG_MM2,
    DBGFREG_MM3,
    DBGFREG_MM4,
    DBGFREG_MM5,
    DBGFREG_MM6,
    DBGFREG_MM7,

    /* SSE: */
    DBGFREG_XMM0,
    DBGFREG_XMM1,
    DBGFREG_XMM2,
    DBGFREG_XMM3,
    DBGFREG_XMM4,
    DBGFREG_XMM5,
    DBGFREG_XMM6,
    DBGFREG_XMM7,
    DBGFREG_XMM8,
    DBGFREG_XMM9,
    DBGFREG_XMM10,
    DBGFREG_XMM11,
    DBGFREG_XMM12,
    DBGFREG_XMM13,
    DBGFREG_XMM14,
    DBGFREG_XMM15,
    /** @todo add XMM aliases. */

    /* System registers: */
    DBGFREG_GDTR_BASE,
    DBGFREG_GDTR_LIMIT,
    DBGFREG_IDTR_BASE,
    DBGFREG_IDTR_LIMIT,
    DBGFREG_LDTR,
    DBGFREG_LDTR_ATTR,
    DBGFREG_LDTR_BASE,
    DBGFREG_LDTR_LIMIT,
    DBGFREG_TR,
    DBGFREG_TR_ATTR,
    DBGFREG_TR_BASE,
    DBGFREG_TR_LIMIT,

    DBGFREG_CR0,
    DBGFREG_CR2,
    DBGFREG_CR3,
    DBGFREG_CR4,
    DBGFREG_CR8,

    DBGFREG_DR0,
    DBGFREG_DR1,
    DBGFREG_DR2,
    DBGFREG_DR3,
    DBGFREG_DR6,
    DBGFREG_DR7,

    /* MSRs: */
    DBGFREG_MSR_IA32_APICBASE,
    DBGFREG_MSR_IA32_CR_PAT,
    DBGFREG_MSR_IA32_PERF_STATUS,
    DBGFREG_MSR_IA32_SYSENTER_CS,
    DBGFREG_MSR_IA32_SYSENTER_EIP,
    DBGFREG_MSR_IA32_SYSENTER_ESP,
    DBGFREG_MSR_IA32_TSC,
    DBGFREG_MSR_K6_EFER,
    DBGFREG_MSR_K6_STAR,
    DBGFREG_MSR_K8_CSTAR,
    DBGFREG_MSR_K8_FS_BASE,
    DBGFREG_MSR_K8_GS_BASE,
    DBGFREG_MSR_K8_KERNEL_GS_BASE,
    DBGFREG_MSR_K8_LSTAR,
    DBGFREG_MSR_K8_SF_MASK,
    DBGFREG_MSR_K8_TSC_AUX,

    /** The number of registers to pass to DBGFR3RegQueryAll. */
    DBGFREG_ALL_COUNT,

    /* Misc aliases that doesn't need be part of the 'all' query: */
    DBGFREG_AH = DBGFREG_ALL_COUNT,
    DBGFREG_CH,
    DBGFREG_DH,
    DBGFREG_BH,
    DBGFREG_GDTR,
    DBGFREG_IDTR,

    /** The end of the registers.  */
    DBGFREG_END,
    /** The usual 32-bit type hack. */
    DBGFREG_32BIT_HACK = 0x7fffffff
} DBGFREG;
/** Pointer to a register identifier. */
typedef DBGFREG *PDBGFREG;
/** Pointer to a const register identifier. */
typedef DBGFREG const *PCDBGFREG;

/**
 * Register value type.
 */
typedef enum DBGFREGVALTYPE
{
    DBGFREGVALTYPE_INVALID = 0,
    /** Unsigned 8-bit register value. */
    DBGFREGVALTYPE_U8,
    /** Unsigned 16-bit register value. */
    DBGFREGVALTYPE_U16,
    /** Unsigned 32-bit register value. */
    DBGFREGVALTYPE_U32,
    /** Unsigned 64-bit register value. */
    DBGFREGVALTYPE_U64,
    /** Unsigned 128-bit register value. */
    DBGFREGVALTYPE_U128,
    /** Long double register value. */
    DBGFREGVALTYPE_R80,
    /** Descriptor table register value. */
    DBGFREGVALTYPE_DTR,
    /** End of the valid register value types. */
    DBGFREGVALTYPE_END,
    /** The usual 32-bit type hack. */
    DBGFREGVALTYPE_32BIT_HACK = 0x7fffffff
} DBGFREGVALTYPE;
/** Pointer to a register value type. */
typedef DBGFREGVALTYPE *PDBGFREGVALTYPE;

/**
 * A generic register value type.
 */
typedef union DBGFREGVAL
{
    uint64_t    au64[2];        /**< The 64-bit array view. First because of the initializer. */
    uint32_t    au32[4];        /**< The 32-bit array view. */
    uint16_t    au16[8];        /**< The 16-bit array view. */
    uint8_t     au8[16];        /**< The 8-bit array view. */

    uint8_t     u8;             /**< The 8-bit view. */
    uint16_t    u16;            /**< The 16-bit view. */
    uint32_t    u32;            /**< The 32-bit view. */
    uint64_t    u64;            /**< The 64-bit view. */
    RTUINT128U  u128;           /**< The 128-bit view. */
    RTFLOAT80U  r80;            /**< The 80-bit floating point view. */
    RTFLOAT80U2 r80Ex;          /**< The 80-bit floating point view v2. */
    /** GDTR or LDTR (DBGFREGVALTYPE_DTR). */
    struct
    {
        /** The table address. */
        uint64_t u64Base;
        /** The table limit (length minus 1). */
        uint32_t u32Limit;
    }           dtr;

    RTUINT128U  u;
} DBGFREGVAL;
/** Pointer to a generic register value type. */
typedef DBGFREGVAL *PDBGFREGVAL;
/** Pointer to a const generic register value type. */
typedef DBGFREGVAL const *PCDBGFREGVAL;

/** Initialize a DBGFREGVAL variable to all zeros.  */
#define DBGFREGVAL_INITIALIZE_ZERO { { 0, 0 } }
/** Initialize a DBGFREGVAL variable to all bits set .  */
#define DBGFREGVAL_INITIALIZE_FFFF { { UINT64_MAX, UINT64_MAX } }


VMMDECL(ssize_t) DBGFR3RegFormatValue(char *pszBuf, size_t cbBuf, PCDBGFREGVAL pValue, DBGFREGVALTYPE enmType, bool fSpecial);
VMMDECL(ssize_t) DBGFR3RegFormatValueEx(char *pszBuf, size_t cbBuf, PCDBGFREGVAL pValue, DBGFREGVALTYPE enmType,
                                        unsigned uBase, signed int cchWidth, signed int cchPrecision, uint32_t fFlags);

/**
 * Register sub-field descriptor.
 */
typedef struct DBGFREGSUBFIELD
{
    /** The name of the sub-field.  NULL is used to terminate the array. */
    const char     *pszName;
    /** The index of the first bit.  Ignored if pfnGet is set. */
    uint8_t         iFirstBit;
    /** The number of bits.  Mandatory. */
    uint8_t         cBits;
    /** The shift count.  Not applied when pfnGet is set, but used to
     * calculate the minimum type. */
    int8_t          cShift;
    /** Sub-field flags, DBGFREGSUBFIELD_FLAGS_XXX.  */
    uint8_t         fFlags;
    /** Getter (optional).
     * @remarks Does not take the device lock or anything like that.
     */
    DECLCALLBACKMEMBER(int, pfnGet)(void *pvUser, struct DBGFREGSUBFIELD const *pSubField, PRTUINT128U puValue);
    /** Setter (optional).
     * @remarks Does not take the device lock or anything like that.
     */
    DECLCALLBACKMEMBER(int, pfnSet)(void *pvUser, struct DBGFREGSUBFIELD const *pSubField, RTUINT128U uValue, RTUINT128U fMask);
} DBGFREGSUBFIELD;
/** Pointer to a const register sub-field descriptor. */
typedef DBGFREGSUBFIELD const *PCDBGFREGSUBFIELD;

/** @name DBGFREGSUBFIELD_FLAGS_XXX
 * @{ */
/** The sub-field is read-only. */
#define DBGFREGSUBFIELD_FLAGS_READ_ONLY     UINT8_C(0x01)
/** @} */

/** Macro for creating a read-write sub-field entry without getters. */
#define DBGFREGSUBFIELD_RW(a_szName, a_iFirstBit, a_cBits, a_cShift) \
    { a_szName, a_iFirstBit, a_cBits, a_cShift, 0 /*fFlags*/, NULL /*pfnGet*/, NULL /*pfnSet*/ }
/** Macro for creating a read-write sub-field entry with getters. */
#define DBGFREGSUBFIELD_RW_SG(a_szName, a_cBits, a_cShift, a_pfnGet, a_pfnSet) \
    { a_szName, 0 /*iFirstBit*/, a_cBits, a_cShift, 0 /*fFlags*/, a_pfnGet, a_pfnSet }
/** Macro for creating a read-only sub-field entry without getters. */
#define DBGFREGSUBFIELD_RO(a_szName, a_iFirstBit, a_cBits, a_cShift) \
    { a_szName, a_iFirstBit, a_cBits, a_cShift, DBGFREGSUBFIELD_FLAGS_READ_ONLY, NULL /*pfnGet*/, NULL /*pfnSet*/ }
/** Macro for creating a terminator sub-field entry.  */
#define DBGFREGSUBFIELD_TERMINATOR() \
    { NULL, 0, 0, 0, 0, NULL, NULL }

/**
 * Register alias descriptor.
 */
typedef struct DBGFREGALIAS
{
    /** The alias name.  NULL is used to terminate the array. */
    const char     *pszName;
    /** Set to a valid type if the alias has a different type. */
    DBGFREGVALTYPE  enmType;
} DBGFREGALIAS;
/** Pointer to a const register alias descriptor. */
typedef DBGFREGALIAS const *PCDBGFREGALIAS;

/**
 * Register descriptor.
 */
typedef struct DBGFREGDESC
{
    /** The normal register name. */
    const char             *pszName;
    /** The register identifier if this is a CPU register. */
    DBGFREG                 enmReg;
    /** The default register type. */
    DBGFREGVALTYPE          enmType;
    /** Flags, see DBGFREG_FLAGS_XXX.  */
    uint32_t                fFlags;
    /** The internal register indicator.
     * For CPU registers this is the offset into the CPUMCTX structure,
     * thuse the 'off' prefix. */
    uint32_t                offRegister;
    /** Getter.
     * @remarks Does not take the device lock or anything like that.
     */
    DECLCALLBACKMEMBER(int, pfnGet)(void *pvUser, struct DBGFREGDESC const *pDesc, PDBGFREGVAL pValue);
    /** Setter.
     * @remarks Does not take the device lock or anything like that.
     */
    DECLCALLBACKMEMBER(int, pfnSet)(void *pvUser, struct DBGFREGDESC const *pDesc, PCDBGFREGVAL pValue, PCDBGFREGVAL pfMask);
    /** Aliases (optional). */
    PCDBGFREGALIAS          paAliases;
    /** Sub fields (optional). */
    PCDBGFREGSUBFIELD       paSubFields;
} DBGFREGDESC;

/** @name Macros for constructing DBGFREGDESC arrays.
 * @{ */
#define DBGFREGDESC_RW(a_szName, a_TypeSuff, a_offRegister, a_pfnGet, a_pfnSet) \
    { a_szName, DBGFREG_END, DBGFREGVALTYPE_##a_TypeSuff, 0 /*fFlags*/,            a_offRegister, a_pfnGet, a_pfnSet, NULL /*paAlises*/, NULL /*paSubFields*/ }
#define DBGFREGDESC_RO(a_szName, a_TypeSuff, a_offRegister, a_pfnGet, a_pfnSet) \
    { a_szName, DBGFREG_END, DBGFREGVALTYPE_##a_TypeSuff, DBGFREG_FLAGS_READ_ONLY, a_offRegister, a_pfnGet, a_pfnSet, NULL /*paAlises*/, NULL /*paSubFields*/ }
#define DBGFREGDESC_RW_A(a_szName, a_TypeSuff, a_offRegister, a_pfnGet, a_pfnSet, a_paAliases) \
    { a_szName, DBGFREG_END, DBGFREGVALTYPE_##a_TypeSuff, 0 /*fFlags*/,            a_offRegister, a_pfnGet, a_pfnSet, a_paAliases, NULL /*paSubFields*/ }
#define DBGFREGDESC_RO_A(a_szName, a_TypeSuff, a_offRegister, a_pfnGet, a_pfnSet, a_paAliases) \
    { a_szName, DBGFREG_END, DBGFREGVALTYPE_##a_TypeSuff, DBGFREG_FLAGS_READ_ONLY, a_offRegister, a_pfnGet, a_pfnSet, a_paAliases, NULL /*paSubFields*/ }
#define DBGFREGDESC_RW_S(a_szName, a_TypeSuff, a_offRegister, a_pfnGet, a_pfnSet, a_paSubFields) \
    { a_szName, DBGFREG_END, DBGFREGVALTYPE_##a_TypeSuff, 0 /*fFlags*/,            a_offRegister, a_pfnGet, a_pfnSet, /*paAliases*/, a_paSubFields }
#define DBGFREGDESC_RO_S(a_szName, a_TypeSuff, a_offRegister, a_pfnGet, a_pfnSet, a_paSubFields) \
    { a_szName, DBGFREG_END, DBGFREGVALTYPE_##a_TypeSuff, DBGFREG_FLAGS_READ_ONLY, a_offRegister, a_pfnGet, a_pfnSet, /*paAliases*/, a_paSubFields }
#define DBGFREGDESC_RW_AS(a_szName, a_TypeSuff, a_offRegister, a_pfnGet, a_pfnSet, a_paAliases, a_paSubFields) \
    { a_szName, DBGFREG_END, DBGFREGVALTYPE_##a_TypeSuff, 0 /*fFlags*/,            a_offRegister, a_pfnGet, a_pfnSet, a_paAliases, a_paSubFields }
#define DBGFREGDESC_RO_AS(a_szName, a_TypeSuff, a_offRegister, a_pfnGet, a_pfnSet, a_paAliases, a_paSubFields) \
    { a_szName, DBGFREG_END, DBGFREGVALTYPE_##a_TypeSuff, DBGFREG_FLAGS_READ_ONLY, a_offRegister, a_pfnGet, a_pfnSet, a_paAliases, a_paSubFields }
#define DBGFREGDESC_TERMINATOR() \
    { NULL, DBGFREG_END, DBGFREGVALTYPE_INVALID, 0, 0, NULL, NULL, NULL, NULL }
/** @} */


/** @name DBGFREG_FLAGS_XXX
 * @{ */
/** The register is read-only. */
#define DBGFREG_FLAGS_READ_ONLY         RT_BIT_32(0)
/** @} */

/**
 * Entry in a batch query or set operation.
 */
typedef struct DBGFREGENTRY
{
    /** The register identifier. */
    DBGFREG         enmReg;
    /** The size of the value in bytes. */
    DBGFREGVALTYPE  enmType;
    /** The register value. The valid view is indicated by enmType. */
    DBGFREGVAL      Val;
} DBGFREGENTRY;
/** Pointer to a register entry in a batch operation. */
typedef DBGFREGENTRY *PDBGFREGENTRY;
/** Pointer to a const register entry in a batch operation. */
typedef DBGFREGENTRY const *PCDBGFREGENTRY;

/** Used with DBGFR3Reg* to indicate the hypervisor register set instead of the
 *  guest. */
#define DBGFREG_HYPER_VMCPUID       UINT32_C(0x01000000)

VMMR3DECL(int) DBGFR3RegCpuQueryU8(  PUVM pUVM, VMCPUID idCpu, DBGFREG enmReg, uint8_t     *pu8);
VMMR3DECL(int) DBGFR3RegCpuQueryU16( PUVM pUVM, VMCPUID idCpu, DBGFREG enmReg, uint16_t    *pu16);
VMMR3DECL(int) DBGFR3RegCpuQueryU32( PUVM pUVM, VMCPUID idCpu, DBGFREG enmReg, uint32_t    *pu32);
VMMR3DECL(int) DBGFR3RegCpuQueryU64( PUVM pUVM, VMCPUID idCpu, DBGFREG enmReg, uint64_t    *pu64);
VMMR3DECL(int) DBGFR3RegCpuQueryU128(PUVM pUVM, VMCPUID idCpu, DBGFREG enmReg, uint128_t   *pu128);
VMMR3DECL(int) DBGFR3RegCpuQueryLrd( PUVM pUVM, VMCPUID idCpu, DBGFREG enmReg, long double *plrd);
VMMR3DECL(int) DBGFR3RegCpuQueryXdtr(PUVM pUVM, VMCPUID idCpu, DBGFREG enmReg, uint64_t *pu64Base, uint16_t *pu16Limit);
#if 0
VMMR3DECL(int) DBGFR3RegCpuQueryBatch(PUVM pUVM,VMCPUID idCpu, PDBGFREGENTRY paRegs, size_t cRegs);
VMMR3DECL(int) DBGFR3RegCpuQueryAll( PUVM pUVM, VMCPUID idCpu, PDBGFREGENTRY paRegs, size_t cRegs);

VMMR3DECL(int) DBGFR3RegCpuSetU8(    PUVM pUVM, VMCPUID idCpu, DBGFREG enmReg, uint8_t     u8);
VMMR3DECL(int) DBGFR3RegCpuSetU16(   PUVM pUVM, VMCPUID idCpu, DBGFREG enmReg, uint16_t    u16);
VMMR3DECL(int) DBGFR3RegCpuSetU32(   PUVM pUVM, VMCPUID idCpu, DBGFREG enmReg, uint32_t    u32);
VMMR3DECL(int) DBGFR3RegCpuSetU64(   PUVM pUVM, VMCPUID idCpu, DBGFREG enmReg, uint64_t    u64);
VMMR3DECL(int) DBGFR3RegCpuSetU128(  PUVM pUVM, VMCPUID idCpu, DBGFREG enmReg, uint128_t   u128);
VMMR3DECL(int) DBGFR3RegCpuSetLrd(   PUVM pUVM, VMCPUID idCpu, DBGFREG enmReg, long double lrd);
VMMR3DECL(int) DBGFR3RegCpuSetBatch( PUVM pUVM, VMCPUID idCpu, PCDBGFREGENTRY paRegs, size_t cRegs);
#endif

VMMR3DECL(const char *) DBGFR3RegCpuName(PUVM pUVM, DBGFREG enmReg, DBGFREGVALTYPE enmType);

VMMR3_INT_DECL(int) DBGFR3RegRegisterCpu(PVM pVM, PVMCPU pVCpu, PCDBGFREGDESC paRegisters, bool fGuestRegs);
VMMR3_INT_DECL(int) DBGFR3RegRegisterDevice(PVM pVM, PCDBGFREGDESC paRegisters, PPDMDEVINS pDevIns,
                                            const char *pszPrefix, uint32_t iInstance);

/**
 * Entry in a named batch query or set operation.
 */
typedef struct DBGFREGENTRYNM
{
    /** The register name. */
    const char     *pszName;
    /** The size of the value in bytes. */
    DBGFREGVALTYPE  enmType;
    /** The register value. The valid view is indicated by enmType. */
    DBGFREGVAL      Val;
} DBGFREGENTRYNM;
/** Pointer to a named register entry in a batch operation. */
typedef DBGFREGENTRYNM *PDBGFREGENTRYNM;
/** Pointer to a const named register entry in a batch operation. */
typedef DBGFREGENTRYNM const *PCDBGFREGENTRYNM;

VMMR3DECL(int) DBGFR3RegNmValidate( PUVM pUVM, VMCPUID idDefCpu, const char *pszReg);

VMMR3DECL(int) DBGFR3RegNmQuery(    PUVM pUVM, VMCPUID idDefCpu, const char *pszReg, PDBGFREGVAL pValue, PDBGFREGVALTYPE penmType);
VMMR3DECL(int) DBGFR3RegNmQueryU8(  PUVM pUVM, VMCPUID idDefCpu, const char *pszReg, uint8_t     *pu8);
VMMR3DECL(int) DBGFR3RegNmQueryU16( PUVM pUVM, VMCPUID idDefCpu, const char *pszReg, uint16_t    *pu16);
VMMR3DECL(int) DBGFR3RegNmQueryU32( PUVM pUVM, VMCPUID idDefCpu, const char *pszReg, uint32_t    *pu32);
VMMR3DECL(int) DBGFR3RegNmQueryU64( PUVM pUVM, VMCPUID idDefCpu, const char *pszReg, uint64_t    *pu64);
VMMR3DECL(int) DBGFR3RegNmQueryU128(PUVM pUVM, VMCPUID idDefCpu, const char *pszReg, PRTUINT128U  pu128);
/*VMMR3DECL(int) DBGFR3RegNmQueryLrd( PUVM pUVM, VMCPUID idDefCpu, const char *pszReg, long double *plrd);*/
VMMR3DECL(int) DBGFR3RegNmQueryXdtr(PUVM pUVM, VMCPUID idDefCpu, const char *pszReg, uint64_t *pu64Base, uint16_t *pu16Limit);
VMMR3DECL(int) DBGFR3RegNmQueryBatch(PUVM pUVM,VMCPUID idDefCpu, PDBGFREGENTRYNM paRegs, size_t cRegs);
VMMR3DECL(int) DBGFR3RegNmQueryAllCount(PUVM pUVM, size_t *pcRegs);
VMMR3DECL(int) DBGFR3RegNmQueryAll( PUVM pUVM,                   PDBGFREGENTRYNM paRegs, size_t cRegs);

VMMR3DECL(int) DBGFR3RegNmSet(      PUVM pUVM, VMCPUID idDefCpu, const char *pszReg, PCDBGFREGVAL pValue, DBGFREGVALTYPE enmType);
VMMR3DECL(int) DBGFR3RegNmSetU8(    PUVM pUVM, VMCPUID idDefCpu, const char *pszReg, uint8_t     u8);
VMMR3DECL(int) DBGFR3RegNmSetU16(   PUVM pUVM, VMCPUID idDefCpu, const char *pszReg, uint16_t    u16);
VMMR3DECL(int) DBGFR3RegNmSetU32(   PUVM pUVM, VMCPUID idDefCpu, const char *pszReg, uint32_t    u32);
VMMR3DECL(int) DBGFR3RegNmSetU64(   PUVM pUVM, VMCPUID idDefCpu, const char *pszReg, uint64_t    u64);
VMMR3DECL(int) DBGFR3RegNmSetU128(  PUVM pUVM, VMCPUID idDefCpu, const char *pszReg, RTUINT128U  u128);
VMMR3DECL(int) DBGFR3RegNmSetLrd(   PUVM pUVM, VMCPUID idDefCpu, const char *pszReg, long double lrd);
VMMR3DECL(int) DBGFR3RegNmSetBatch( PUVM pUVM, VMCPUID idDefCpu, PCDBGFREGENTRYNM paRegs, size_t cRegs);

/** @todo add enumeration methods.  */

VMMR3DECL(int) DBGFR3RegPrintf( PUVM pUVM, VMCPUID idDefCpu, char *pszBuf, size_t cbBuf, const char *pszFormat, ...);
VMMR3DECL(int) DBGFR3RegPrintfV(PUVM pUVM, VMCPUID idDefCpu, char *pszBuf, size_t cbBuf, const char *pszFormat, va_list va);


/**
 * Guest OS digger interface identifier.
 *
 * This is for use together with PDBGFR3QueryInterface and is used to
 * obtain access to optional interfaces.
 */
typedef enum DBGFOSINTERFACE
{
    /** The usual invalid entry. */
    DBGFOSINTERFACE_INVALID = 0,
    /** Process info. */
    DBGFOSINTERFACE_PROCESS,
    /** Thread info. */
    DBGFOSINTERFACE_THREAD,
    /** Kernel message log - DBGFOSIDMESG. */
    DBGFOSINTERFACE_DMESG,
    /** The end of the valid entries. */
    DBGFOSINTERFACE_END,
    /** The usual 32-bit type blowup. */
    DBGFOSINTERFACE_32BIT_HACK = 0x7fffffff
} DBGFOSINTERFACE;
/** Pointer to a Guest OS digger interface identifier. */
typedef DBGFOSINTERFACE *PDBGFOSINTERFACE;
/** Pointer to a const Guest OS digger interface identifier. */
typedef DBGFOSINTERFACE const *PCDBGFOSINTERFACE;


/**
 * Guest OS Digger Registration Record.
 *
 * This is used with the DBGFR3OSRegister() API.
 */
typedef struct DBGFOSREG
{
    /** Magic value (DBGFOSREG_MAGIC). */
    uint32_t u32Magic;
    /** Flags. Reserved. */
    uint32_t fFlags;
    /** The size of the instance data. */
    uint32_t cbData;
    /** Operative System name. */
    char szName[24];

    /**
     * Constructs the instance.
     *
     * @returns VBox status code.
     * @param   pUVM    The user mode VM handle.
     * @param   pvData  Pointer to the instance data.
     */
    DECLCALLBACKMEMBER(int, pfnConstruct)(PUVM pUVM, void *pvData);

    /**
     * Destroys the instance.
     *
     * @param   pUVM    The user mode VM handle.
     * @param   pvData  Pointer to the instance data.
     */
    DECLCALLBACKMEMBER(void, pfnDestruct)(PUVM pUVM, void *pvData);

    /**
     * Probes the guest memory for OS finger prints.
     *
     * No setup or so is performed, it will be followed by a call to pfnInit
     * or pfnRefresh that should take care of that.
     *
     * @returns true if is an OS handled by this module, otherwise false.
     * @param   pUVM    The user mode VM handle.
     * @param   pvData  Pointer to the instance data.
     */
    DECLCALLBACKMEMBER(bool, pfnProbe)(PUVM pUVM, void *pvData);

    /**
     * Initializes a fresly detected guest, loading symbols and such useful stuff.
     *
     * This is called after pfnProbe.
     *
     * @returns VBox status code.
     * @param   pUVM    The user mode VM handle.
     * @param   pvData  Pointer to the instance data.
     */
    DECLCALLBACKMEMBER(int, pfnInit)(PUVM pUVM, void *pvData);

    /**
     * Refreshes symbols and stuff following a redetection of the same OS.
     *
     * This is called after pfnProbe.
     *
     * @returns VBox status code.
     * @param   pUVM    The user mode VM handle.
     * @param   pvData  Pointer to the instance data.
     */
    DECLCALLBACKMEMBER(int, pfnRefresh)(PUVM pUVM, void *pvData);

    /**
     * Terminates an OS when a new (or none) OS has been detected,
     * and before destruction.
     *
     * This is called after pfnProbe and if needed before pfnDestruct.
     *
     * @param   pUVM    The user mode VM handle.
     * @param   pvData  Pointer to the instance data.
     */
    DECLCALLBACKMEMBER(void, pfnTerm)(PUVM pUVM, void *pvData);

    /**
     * Queries the version of the running OS.
     *
     * This is only called after pfnInit().
     *
     * @returns VBox status code.
     * @param   pUVM    The user mode VM handle.
     * @param   pvData      Pointer to the instance data.
     * @param   pszVersion  Where to store the version string.
     * @param   cchVersion  The size of the version string buffer.
     */
    DECLCALLBACKMEMBER(int, pfnQueryVersion)(PUVM pUVM, void *pvData, char *pszVersion, size_t cchVersion);

    /**
     * Queries the pointer to a interface.
     *
     * This is called after pfnProbe.
     *
     * The returned interface must be valid until pfnDestruct is called.  Two calls
     * to this method with the same @a enmIf value must return the same pointer.
     *
     * @returns Pointer to the interface if available, NULL if not available.
     * @param   pUVM    The user mode VM handle.
     * @param   pvData  Pointer to the instance data.
     * @param   enmIf   The interface identifier.
     */
    DECLCALLBACKMEMBER(void *, pfnQueryInterface)(PUVM pUVM, void *pvData, DBGFOSINTERFACE enmIf);

    /** Trailing magic (DBGFOSREG_MAGIC). */
    uint32_t u32EndMagic;
} DBGFOSREG;
/** Pointer to a Guest OS digger registration record. */
typedef DBGFOSREG *PDBGFOSREG;
/** Pointer to a const Guest OS digger registration record. */
typedef DBGFOSREG const *PCDBGFOSREG;

/** Magic value for DBGFOSREG::u32Magic and DBGFOSREG::u32EndMagic. (Hitomi Kanehara) */
#define DBGFOSREG_MAGIC     0x19830808


/**
 * Interface for querying kernel log messages (DBGFOSINTERFACE_DMESG).
 */
typedef struct DBGFOSIDMESG
{
    /** Trailing magic (DBGFOSIDMESG_MAGIC). */
    uint32_t    u32Magic;

    /**
     * Query the kernel log.
     *
     * @returns VBox status code.
     * @retval  VERR_NOT_FOUND if the messages could not be located.
     * @retval  VERR_INVALID_STATE if the messages was found to have unknown/invalid
     *          format.
     * @retval  VERR_BUFFER_OVERFLOW if the buffer isn't large enough, pcbActual
     *          will be set to the required buffer size.  The buffer, however, will
     *          be filled with as much data as it can hold (properly zero terminated
     *          of course).
     *
     * @param   pThis       Pointer to the interface structure.
     * @param   pUVM        The user mode VM handle.
     * @param   fFlags      Flags reserved for future use, MBZ.
     * @param   cMessages   The number of messages to retrieve, counting from the
     *                      end of the log (i.e. like tail), use UINT32_MAX for all.
     * @param   pszBuf      The output buffer.
     * @param   cbBuf       The buffer size.
     * @param   pcbActual   Where to store the number of bytes actually returned,
     *                      including zero terminator.  On VERR_BUFFER_OVERFLOW this
     *                      holds the necessary buffer size.  Optional.
     */
    DECLCALLBACKMEMBER(int, pfnQueryKernelLog)(struct DBGFOSIDMESG *pThis, PUVM pUVM, uint32_t fFlags, uint32_t cMessages,
                                               char *pszBuf, size_t cbBuf, size_t *pcbActual);
    /** Trailing magic (DBGFOSIDMESG_MAGIC). */
    uint32_t    u32EndMagic;
} DBGFOSIDMESG;
/** Pointer to the interface for query kernel log messages (DBGFOSINTERFACE_DMESG). */
typedef DBGFOSIDMESG *PDBGFOSIDMESG;
/** Magic value for DBGFOSIDMESG::32Magic and DBGFOSIDMESG::u32EndMagic. (Kenazburo Oe) */
#define DBGFOSIDMESG_MAGIC UINT32_C(0x19350131)


VMMR3DECL(int)      DBGFR3OSRegister(PUVM pUVM, PCDBGFOSREG pReg);
VMMR3DECL(int)      DBGFR3OSDeregister(PUVM pUVM, PCDBGFOSREG pReg);
VMMR3DECL(int)      DBGFR3OSDetect(PUVM pUVM, char *pszName, size_t cchName);
VMMR3DECL(int)      DBGFR3OSQueryNameAndVersion(PUVM pUVM, char *pszName, size_t cchName, char *pszVersion, size_t cchVersion);
VMMR3DECL(void *)   DBGFR3OSQueryInterface(PUVM pUVM, DBGFOSINTERFACE enmIf);


VMMR3DECL(int)      DBGFR3CoreWrite(PUVM pUVM, const char *pszFilename, bool fReplaceFile);


#ifdef IN_RING3
/** @defgroup grp_dbgf_plug_in      The DBGF Plug-in Interface
 * @{
 */

/** The plug-in module name prefix. */
#define DBGF_PLUG_IN_PREFIX         "DbgPlugIn"

/** The name of the plug-in entry point (FNDBGFPLUGIN) */
#define DBGF_PLUG_IN_ENTRYPOINT     "DbgPlugInEntry"

/**
 * DBGF plug-in operations.
 */
typedef enum DBGFPLUGINOP
{
    /** The usual invalid first value. */
    DBGFPLUGINOP_INVALID,
    /** Initialize the plug-in for a VM, register all the stuff.
     * The plug-in will be unloaded on failure.
     * uArg: The full VirtualBox version, see VBox/version.h. */
    DBGFPLUGINOP_INIT,
    /** Terminate the plug-ing for a VM, deregister all the stuff.
     * The plug-in will be unloaded after this call regardless of the return
     * code. */
    DBGFPLUGINOP_TERM,
    /** The usual 32-bit hack. */
    DBGFPLUGINOP_32BIT_HACK = 0x7fffffff
} DBGFPLUGINOP;

/**
 * DBGF plug-in main entry point.
 *
 * @returns VBox status code.
 *
 * @param   enmOperation    The operation.
 * @param   pUVM            The user mode VM handle. This may be NULL.
 * @param   uArg            Extra argument.
 */
typedef DECLCALLBACK(int) FNDBGFPLUGIN(DBGFPLUGINOP enmOperation, PUVM pUVM, uintptr_t uArg);
/** Pointer to a FNDBGFPLUGIN. */
typedef FNDBGFPLUGIN *PFNDBGFPLUGIN;

/** @copydoc FNDBGFPLUGIN */
DECLEXPORT(int) DbgPlugInEntry(DBGFPLUGINOP enmOperation, PUVM pUVM, uintptr_t uArg);

VMMR3DECL(int)  DBGFR3PlugInLoad(PUVM pUVM, const char *pszPlugIn, char *pszActual, size_t cbActual, PRTERRINFO pErrInfo);
VMMR3DECL(int)  DBGFR3PlugInUnload(PUVM pUVM, const char *pszName);
VMMR3DECL(void) DBGFR3PlugInLoadAll(PUVM pUVM);
VMMR3DECL(void) DBGFR3PlugInUnloadAll(PUVM pUVM);

/** @} */
#endif /* IN_RING3 */


/** @} */


RT_C_DECLS_END

#endif

