Index: trunk/src/VBox/VMM/VMMR3/DBGFR3Type.cpp
===================================================================
--- trunk/src/VBox/VMM/VMMR3/DBGFR3Type.cpp	(revision 61671)
+++ trunk/src/VBox/VMM/VMMR3/DBGFR3Type.cpp	(revision 61671)
@@ -0,0 +1,1040 @@
+/* $Id$ */
+/** @file
+ * DBGF - Debugger Facility, Type Management.
+ */
+
+/*
+ * Copyright (C) 2016 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.
+ */
+
+
+/** @page pg_dbgf_type    DBGFType - Type Management
+ *
+ * The type management system is intended to ease retrieval of values from
+ * structures in the guest OS without having to take care of the size of pointers.
+ */
+
+
+/*********************************************************************************************************************************
+*   Header Files                                                                                                                 *
+*********************************************************************************************************************************/
+#define LOG_GROUP LOG_GROUP_DBGF
+#include <VBox/vmm/dbgf.h>
+#include "DBGFInternal.h"
+#include <VBox/vmm/mm.h>
+#include <VBox/vmm/uvm.h>
+#include <VBox/err.h>
+#include <VBox/log.h>
+
+#include <iprt/assert.h>
+#include <iprt/thread.h>
+#include <iprt/param.h>
+
+
+/*********************************************************************************************************************************
+*   Defined Constants And Macros                                                                                                 *
+*********************************************************************************************************************************/
+
+/** Locks the type database for writing. */
+#define DBGF_TYPE_DB_LOCK_WRITE(pUVM) \
+    do { \
+        int rcSem = RTSemRWRequestWrite((pUVM)->dbgf.s.hTypeDbLock, RT_INDEFINITE_WAIT); \
+        AssertRC(rcSem); \
+    } while (0)
+
+/** Unlocks the type database after writing. */
+#define DBGF_TYPE_DB_UNLOCK_WRITE(pUVM) \
+    do { \
+        int rcSem = RTSemRWReleaseWrite((pUVM)->dbgf.s.hTypeDbLock); \
+        AssertRC(rcSem); \
+    } while (0)
+
+/** Locks the type database for reading. */
+#define DBGF_TYPE_DB_LOCK_READ(pUVM) \
+    do { \
+        int rcSem = RTSemRWRequestRead((pUVM)->dbgf.s.hTypeDbLock, RT_INDEFINITE_WAIT); \
+        AssertRC(rcSem); \
+    } while (0)
+
+/** Unlocks the type database after reading. */
+#define DBGF_TYPE_DB_UNLOCK_READ(pUVM) \
+    do { \
+        int rcSem = RTSemRWReleaseRead((pUVM)->dbgf.s.hTypeDbLock); \
+        AssertRC(rcSem); \
+    } while (0)
+
+/*********************************************************************************************************************************
+*   Structures and Typedefs                                                                                                      *
+*********************************************************************************************************************************/
+
+/**
+ * DBGF registered type.
+ */
+typedef struct DBGFTYPE
+{
+    /** String space core. */
+    RTSTRSPACECORE          Core;
+    /** Pointer to the registration structure, NULL means builtin type. */
+    PCDBGFTYPEREG           pReg;
+    /** How often the type is referenced by other types. */
+    volatile uint32_t       cRefs;
+    /** Size of the type. */
+    size_t                  cbType;
+    /** Builtin type if pReg is NULL (otherwise it is invalid). */
+    DBGFTYPEBUILTIN         enmTypeBuiltin;
+} DBGFTYPE;
+/** Pointer to a DBGF type. */
+typedef DBGFTYPE *PDBGFTYPE;
+
+
+/*********************************************************************************************************************************
+*   Internal Functions                                                                                                           *
+*********************************************************************************************************************************/
+
+static int dbgfR3TypeParseBufferByType(PUVM pUVM, PDBGFTYPE pType, uint8_t *pbBuf, size_t cbBuf,
+                                       PDBGFTYPEVAL *ppVal, size_t *pcbParsed);
+
+/**
+ * Looks up a type by the identifier.
+ *
+ * @returns Pointer to the type structure on success, NULL otherwise.
+ * @param   pUVM                The user mode VM handle.
+ * @param   pszType             The type identifier.
+ */
+static PDBGFTYPE dbgfR3TypeLookup(PUVM pUVM, const char *pszType)
+{
+    PRTSTRSPACE pTypeSpace = &pUVM->dbgf.s.TypeSpace;
+    return (PDBGFTYPE)RTStrSpaceGet(pTypeSpace, pszType);
+}
+
+/**
+ * Calculate the size of the given type.
+ *
+ * @returns VBox status code.
+ * @param   pUVM                The user mode VM handle.
+ * @param   pType               The type to calculate the size for.
+ * @param   fCalcNested         Flag whether to calculate the size for nested
+ *                              structs if the sizes are 0.
+ */
+static int dbgfR3TypeCalcSize(PUVM pUVM, PDBGFTYPE pType, bool fCalcNested)
+{
+    int rc = VINF_SUCCESS;
+
+    /* Builtin types are never recalculated. */
+    if (pType->pReg)
+    {
+        switch (pType->pReg->enmVariant)
+        {
+            case DBGFTYPEVARIANT_STRUCT:
+            {
+                size_t cbType = 0;
+
+                /* Go through the members and update size. */
+                for (uint32_t i = 0; i < pType->pReg->cMembers && RT_SUCCESS(rc); i++)
+                {
+                    PCDBGFTYPEREGMEMBER pMember = &pType->pReg->paMembers[i];
+
+                    if (pMember->fFlags & DBGFTYPEREGMEMBER_F_POINTER)
+                    {
+                        /* Use the current pointer size. */
+                        PDBGFTYPE pTypeMember = dbgfR3TypeLookup(pUVM, "ptr_t");
+                        if (RT_LIKELY(pTypeMember))
+                        {
+                            if (pMember->fFlags & DBGFTYPEREGMEMBER_F_ARRAY)
+                                cbType += pMember->cElements * pTypeMember->cbType;
+                            else
+                                cbType += pTypeMember->cbType;
+                        }
+                    }
+                    else
+                    {
+                        PDBGFTYPE pTypeMember = dbgfR3TypeLookup(pUVM, pMember->pszType);
+                        if (RT_LIKELY(pTypeMember))
+                        {
+                            if (   pTypeMember->cbType == 0
+                                && fCalcNested)
+                                rc = dbgfR3TypeCalcSize(pUVM, pTypeMember, fCalcNested);
+
+                            if (RT_SUCCESS(rc))
+                            {
+                                if (pMember->fFlags & DBGFTYPEREGMEMBER_F_ARRAY)
+                                    cbType += pMember->cElements * pTypeMember->cbType;
+                                else
+                                    cbType += pTypeMember->cbType;
+                            }
+                        }
+                        else
+                            rc = VERR_INVALID_STATE;
+                    }
+                }
+
+                if (RT_SUCCESS(rc))
+                    pType->cbType = cbType;
+                break;
+            }
+            case DBGFTYPEVARIANT_UNION:
+            {
+                /* Get size of the biggest member and use that one. */
+                size_t cbType = 0;
+
+                for (uint32_t i = 0; i < pType->pReg->cMembers && RT_SUCCESS(rc); i++)
+                {
+                    PCDBGFTYPEREGMEMBER pMember = &pType->pReg->paMembers[i];
+
+                    if (pMember->fFlags & DBGFTYPEREGMEMBER_F_POINTER)
+                    {
+                        /* Use the current pointer size. */
+                        PDBGFTYPE pTypeMember = dbgfR3TypeLookup(pUVM, "ptr_t");
+                        if (RT_LIKELY(pTypeMember))
+                        {
+                            if (pMember->fFlags & DBGFTYPEREGMEMBER_F_ARRAY)
+                                cbType = RT_MAX(cbType, pMember->cElements * pTypeMember->cbType);
+                            else
+                                cbType = RT_MAX(cbType, pTypeMember->cbType);
+                        }
+                    }
+                    else
+                    {
+                        PDBGFTYPE pTypeMember = dbgfR3TypeLookup(pUVM, pMember->pszType);
+                        if (RT_LIKELY(pTypeMember))
+                        {
+                            if (   pTypeMember->cbType == 0
+                                && fCalcNested)
+                                rc = dbgfR3TypeCalcSize(pUVM, pTypeMember, fCalcNested);
+
+                            if (RT_SUCCESS(rc))
+                            {
+                                if (pMember->fFlags & DBGFTYPEREGMEMBER_F_ARRAY)
+                                    cbType = RT_MAX(cbType, pMember->cElements * pTypeMember->cbType);
+                                else
+                                    cbType = RT_MAX(cbType, pTypeMember->cbType);
+                            }
+                        }
+                        else
+                            rc = VERR_INVALID_STATE;
+                    }
+                }
+
+                if (RT_SUCCESS(rc))
+                    pType->cbType = cbType;
+                break;
+            }
+            case DBGFTYPEVARIANT_ALIAS:
+            {
+                /* Get the size of the alias. */
+                PDBGFTYPE pAliased = dbgfR3TypeLookup(pUVM, pType->pReg->pszAliasedType);
+                if (RT_LIKELY(pAliased))
+                {
+                    if (   pAliased->cbType == 0
+                        && fCalcNested)
+                        rc = dbgfR3TypeCalcSize(pUVM, pAliased, fCalcNested);
+
+                    if (RT_SUCCESS(rc))
+                        pType->cbType = pAliased->cbType;
+                }
+                else
+                    rc = VERR_INVALID_STATE;
+                break;
+            }
+            default:
+                AssertMsgFailedBreakStmt(("Invalid type variant: %d", pType->pReg->enmVariant),
+                                         rc = VERR_INVALID_STATE);
+        }
+    }
+
+    return rc;
+}
+
+/**
+ * Callback for clearing the size of all non built-in types.
+ *
+ * @returns VBox status code.
+ * @param   pStr                The type structure.
+ * @param   pvUser              The user mode VM handle.
+ */
+static DECLCALLBACK(int) dbgfR3TypeTraverseClearSize(PRTSTRSPACECORE pStr, void *pvUser)
+{
+    PDBGFTYPE pType = (PDBGFTYPE)pStr;
+
+    if (pType->pReg)
+        pType->cbType = 0;
+
+    NOREF(pvUser);
+    return VINF_SUCCESS;
+}
+
+/**
+ * Callback for calculating the size of all non built-in types.
+ *
+ * @returns VBox status code.
+ * @param   pStr                The type structure.
+ * @param   pvUser              The user mode VM handle.
+ */
+static DECLCALLBACK(int) dbgfR3TypeTraverseCalcSize(PRTSTRSPACECORE pStr, void *pvUser)
+{
+    PDBGFTYPE pType = (PDBGFTYPE)pStr;
+
+    if (    pType->pReg
+        && !pType->cbType)
+        dbgfR3TypeCalcSize((PUVM)pvUser, pType, true /* fCalcNested */);
+
+    return VINF_SUCCESS;
+}
+
+/**
+ * Recalculate the sizes of all registered non builtin types.
+ *
+ * @returns VBox status code.
+ * @param   pUVM                The user mode VM handle.
+ */
+static int dbgfR3TypeRecalculateAllSizes(PUVM pUVM)
+{
+    int rc = VINF_SUCCESS;
+
+    /*
+     * Clear the sizes of all non builtin types to 0 first so we know which type we
+     * visited later on.
+     */
+    rc = RTStrSpaceEnumerate(&pUVM->dbgf.s.TypeSpace, dbgfR3TypeTraverseClearSize, pUVM);
+    if (RT_SUCCESS(rc))
+    {
+        /* Now recalculate the size. */
+        rc = RTStrSpaceEnumerate(&pUVM->dbgf.s.TypeSpace, dbgfR3TypeTraverseCalcSize, pUVM);
+    }
+
+    return rc;
+}
+
+/**
+ * Validates a given type registration.
+ *
+ * @returns VBox status code.
+ * @param   pUVM                The user mode VM handle.
+ * @param   pReg                The type registration structure.
+ */
+static int dbgfR3TypeValidate(PUVM pUVM, PCDBGFTYPEREG pReg)
+{
+    int rc = VINF_SUCCESS;
+
+    switch (pReg->enmVariant)
+    {
+        case DBGFTYPEVARIANT_ALIAS:
+            if (   pReg->cMembers > 0
+                || pReg->paMembers
+                || !pReg->pszAliasedType)
+                rc = VERR_INVALID_PARAMETER;
+            else
+            {
+                PDBGFTYPE pAlias = dbgfR3TypeLookup(pUVM, pReg->pszAliasedType);
+                if (RT_UNLIKELY(!pAlias))
+                    rc = VERR_NOT_FOUND;
+            }
+            break;
+        case DBGFTYPEVARIANT_STRUCT:
+        case DBGFTYPEVARIANT_UNION:
+            if (!pReg->pszAliasedType)
+            {
+                for (uint32_t i = 0; i < pReg->cMembers; i++)
+                {
+                    PCDBGFTYPEREGMEMBER pMember = &pReg->paMembers[i];
+
+                    /* Use the current pointer size. */
+                    PDBGFTYPE pTypeMember = dbgfR3TypeLookup(pUVM, pMember->pszType);
+                    if (RT_UNLIKELY(!pTypeMember))
+                    {
+                        rc = VERR_NOT_FOUND;
+                        break;
+                    }
+
+                    if (pMember->fFlags & DBGFTYPEREGMEMBER_F_ARRAY)
+                    {
+                        if (pMember->cElements == 0)
+                            rc = VERR_INVALID_PARAMETER;
+                    }
+                    else if (pMember->cElements != 0)
+                        rc = VERR_INVALID_PARAMETER;
+                }
+            }
+            else
+                rc = VERR_INVALID_PARAMETER;
+            break;
+        default:
+            AssertMsgFailedBreakStmt(("Invalid type variant: %d", pReg->enmVariant),
+                                     rc = VERR_INVALID_PARAMETER);
+    }
+
+    return rc;
+}
+
+/**
+ * Retains or releases the reference counters to referenced types for the given
+ * type registration structure.
+ *
+ * @returns VBox status code.
+ * @param   pUVM                The user mode VM handle.
+ * @param   pReg                The type registration structure.
+ * @param   fRetain             Flag whether to retain or release references.
+ */
+static int dbgfR3TypeUpdateRefCnts(PUVM pUVM, PCDBGFTYPEREG pReg, bool fRetain)
+{
+    int rc = VINF_SUCCESS;
+
+    switch (pReg->enmVariant)
+    {
+        case DBGFTYPEVARIANT_ALIAS:
+        {
+            AssertPtr(pReg->pszAliasedType);
+
+            PDBGFTYPE pAlias = dbgfR3TypeLookup(pUVM, pReg->pszAliasedType);
+            AssertPtr(pAlias);
+
+            if (fRetain)
+                pAlias->cRefs++;
+            else
+                pAlias->cRefs--;
+            break;
+        }
+        case DBGFTYPEVARIANT_STRUCT:
+        case DBGFTYPEVARIANT_UNION:
+        {
+            for (uint32_t i = 0; i < pReg->cMembers; i++)
+            {
+                PCDBGFTYPEREGMEMBER pMember = &pReg->paMembers[i];
+
+                /* Use the current pointer size. */
+                PDBGFTYPE pTypeMember = dbgfR3TypeLookup(pUVM, pMember->pszType);
+                AssertPtr(pTypeMember);
+
+                if (fRetain)
+                    pTypeMember->cRefs++;
+                else
+                    pTypeMember->cRefs--;
+            }
+            break;
+        }
+        default:
+            AssertMsgFailedBreakStmt(("Invalid type variant: %d", pReg->enmVariant),
+                                     rc = VERR_INVALID_PARAMETER);
+    }
+
+    return rc;
+}
+
+/**
+ * Registers a single type in the database.
+ *
+ * @returns VBox status code.
+ * @retval VERR_ALREADY_EXISTS if the type exists already.
+ * @param   pUVM                The user mode VM handle.
+ * @param   pReg                The type registration structure.
+ */
+static int dbgfR3TypeRegister(PUVM pUVM, PCDBGFTYPEREG pReg)
+{
+    int rc = VINF_SUCCESS;
+
+    LogFlowFunc(("pUVM=%#p pReg=%#p{%s}\n", pUVM, pReg, pReg->pszType));
+
+    if (dbgfR3TypeLookup(pUVM, pReg->pszType) == NULL)
+    {
+        rc = dbgfR3TypeValidate(pUVM, pReg);
+        if (RT_SUCCESS(rc))
+        {
+            PDBGFTYPE pType = (PDBGFTYPE)MMR3HeapAllocZU(pUVM, MM_TAG_DBGF_TYPE, sizeof(DBGFTYPE));
+            if (RT_LIKELY(pType))
+            {
+                pType->Core.pszString = pReg->pszType;
+                pType->pReg           = pReg;
+                pType->cRefs          = 0;
+                pType->enmTypeBuiltin = DBGFTYPEBUILTIN_INVALID;
+                rc = dbgfR3TypeCalcSize(pUVM, pType, false /* fCalcNested */);
+                if (RT_SUCCESS(rc))
+                {
+                    rc = dbgfR3TypeUpdateRefCnts(pUVM, pReg, true /* fRetain */);
+                    if (RT_SUCCESS(rc))
+                    {
+                        bool fSucc = RTStrSpaceInsert(&pUVM->dbgf.s.TypeSpace, &pType->Core);
+                        Assert(fSucc);
+                        if (!fSucc)
+                        {
+                            dbgfR3TypeUpdateRefCnts(pUVM, pReg, false /* fRetain */);
+                            rc = VERR_ALREADY_EXISTS;
+                        }
+                    }
+                }
+
+                if (RT_FAILURE(rc))
+                    MMR3HeapFree(pType);
+            }
+            else
+                rc = VERR_NO_MEMORY;
+        }
+    }
+    else
+        rc = VERR_ALREADY_EXISTS;
+
+    LogFlowFunc(("-> rc=%Rrc\n", rc));
+    return rc;
+}
+
+/**
+ * Registers a new built-in type 
+ *
+ * @returns VBox status code.
+ * @param   pUVM                The user mode VM handle.
+ * @param   enmTypeBuiltin      The builtin type enum.
+ * @param   cbType              Size of the type in bytes.
+ * @param   pszType             The type identifier for the builtin type.
+ */
+static int dbgfR3TypeRegisterBuiltin(PUVM pUVM, DBGFTYPEBUILTIN enmTypeBuiltin,
+                                     size_t cbType, const char *pszType)
+{
+    LogFlowFunc(("pUVM=%#p enmBuiltin=%d pszType=%s\n", pUVM, enmTypeBuiltin, pszType));
+
+    AssertReturn(!dbgfR3TypeLookup(pUVM, pszType), VERR_INVALID_STATE);
+
+    int rc = VINF_SUCCESS;
+    PDBGFTYPE pType = (PDBGFTYPE)MMR3HeapAllocZU(pUVM, MM_TAG_DBGF_TYPE, sizeof(DBGFTYPE));
+    if (RT_LIKELY(pType))
+    {
+        pType->Core.pszString = pszType;
+        pType->pReg           = NULL;
+        pType->cRefs          = 0;
+        pType->cbType         = cbType;
+        pType->enmTypeBuiltin = enmTypeBuiltin;
+        bool fSucc = RTStrSpaceInsert(&pUVM->dbgf.s.TypeSpace, &pType->Core);
+        Assert(fSucc);
+        if (!fSucc)
+            rc = VERR_ALREADY_EXISTS;
+
+        if (RT_FAILURE(rc))
+            MMR3HeapFree(pType);
+    }
+    else
+        rc = VERR_NO_MEMORY;
+
+    return rc;
+}
+
+/**
+ * Registers builtin types.
+ *
+ * @returns VBox status code.
+ * @param   pUVM                The user mode VM handle.
+ */
+static int dbgfTypeRegisterBuiltinTypes(PUVM pUVM)
+{
+    int rc = dbgfR3TypeRegisterBuiltin(pUVM, DBGFTYPEBUILTIN_UINT8,  sizeof(uint8_t),  "uint8_t");
+    if (RT_SUCCESS(rc))
+        rc = dbgfR3TypeRegisterBuiltin(pUVM, DBGFTYPEBUILTIN_INT8,   sizeof(int8_t),   "int8_t");
+    if (RT_SUCCESS(rc))
+        rc = dbgfR3TypeRegisterBuiltin(pUVM, DBGFTYPEBUILTIN_UINT16, sizeof(uint16_t), "uint16_t");
+    if (RT_SUCCESS(rc))
+        rc = dbgfR3TypeRegisterBuiltin(pUVM, DBGFTYPEBUILTIN_INT16,  sizeof(int16_t),  "int16_t");
+    if (RT_SUCCESS(rc))
+        rc = dbgfR3TypeRegisterBuiltin(pUVM, DBGFTYPEBUILTIN_UINT32, sizeof(uint32_t), "uint32_t");
+    if (RT_SUCCESS(rc))
+        rc = dbgfR3TypeRegisterBuiltin(pUVM, DBGFTYPEBUILTIN_INT32,  sizeof(int32_t),  "int32_t");
+    if (RT_SUCCESS(rc))
+        rc = dbgfR3TypeRegisterBuiltin(pUVM, DBGFTYPEBUILTIN_UINT64, sizeof(uint64_t), "uint64_t");
+    if (RT_SUCCESS(rc))
+        rc = dbgfR3TypeRegisterBuiltin(pUVM, DBGFTYPEBUILTIN_INT64,  sizeof(int64_t),  "int64_t");
+    if (RT_SUCCESS(rc))
+        rc = dbgfR3TypeRegisterBuiltin(pUVM, DBGFTYPEBUILTIN_PTR32,  sizeof(uint32_t), "ptr32_t");
+    if (RT_SUCCESS(rc))
+        rc = dbgfR3TypeRegisterBuiltin(pUVM, DBGFTYPEBUILTIN_PTR64,  sizeof(uint64_t), "ptr64_t");
+    if (RT_SUCCESS(rc))
+        rc = dbgfR3TypeRegisterBuiltin(pUVM, DBGFTYPEBUILTIN_PTR,                   0, "ptr_t");
+    if (RT_SUCCESS(rc))
+        rc = dbgfR3TypeRegisterBuiltin(pUVM, DBGFTYPEBUILTIN_SIZE,                  0, "size_t");
+
+    return rc;
+}
+
+/**
+ * Parses a single entry for a given type and assigns the value from the byte buffer
+ * to the value entry.
+ *
+ * @returns VBox status code.
+ * @param   pUVM                The user mode VM handle.
+ * @param   pMember             The type member.
+ * @param   pValEntry           The value entry holding the value on success.
+ * @param   pbBuf               The raw byte buffer.
+ * @param   cbBuf               Size of the byte buffer.
+ * @param   pcbParsed           Where to store the amount of consumed bytes on success.
+ */
+static int dbgfR3TypeParseEntry(PUVM pUVM, PCDBGFTYPEREGMEMBER pMember, PDBGFTYPEVALENTRY pValEntry,
+                                uint8_t *pbBuf, size_t cbBuf, size_t *pcbParsed)
+{
+    int rc = VINF_SUCCESS;
+    PDBGFTYPE pTypeMember = dbgfR3TypeLookup(pUVM, pMember->pszType);
+    uint32_t cValBufs = 1;
+    size_t cbParsed = 0;
+    PDBGFTYPEVALBUF pValBuf = &pValEntry->Buf.Val;
+
+    AssertPtrReturn(pTypeMember, VERR_INVALID_STATE);
+
+    if (pMember->fFlags & DBGFTYPEREGMEMBER_F_ARRAY)
+    {
+        cValBufs = pMember->cElements;
+        pValBuf = (PDBGFTYPEVALBUF)MMR3HeapAllocZU(pUVM, MM_TAG_DBGF_TYPE, cValBufs * sizeof(DBGFTYPEVALBUF));
+        if (RT_UNLIKELY(!pValBuf))
+            rc = VERR_NO_MEMORY;
+
+        pValEntry->Buf.pVal = pValBuf;
+        pValEntry->cEntries = cValBufs;
+    }
+
+    if (RT_SUCCESS(rc))
+    {
+        for (uint32_t iValBuf = 0; iValBuf < cValBufs && RT_SUCCESS(rc); iValBuf++)
+        {
+            size_t cbThisParsed = 0;
+
+            if (pTypeMember->pReg)
+            {
+                /* Compound or aliased type */
+                rc = dbgfR3TypeParseBufferByType(pUVM, pTypeMember, pbBuf, cbBuf,
+                                                 &pValBuf->pVal, &cbThisParsed);
+                if (RT_SUCCESS(rc))
+                    pValEntry->enmType = DBGFTYPEBUILTIN_COMPOUND;
+            }
+            else
+            {
+                void *pvVal = NULL;
+
+                switch (pTypeMember->enmTypeBuiltin)
+                {
+                    case DBGFTYPEBUILTIN_UINT8:
+                        pvVal = &pValBuf->u8;
+                        cbThisParsed = 1;
+                        break;
+                    case DBGFTYPEBUILTIN_INT8:
+                        pvVal = &pValBuf->i8;
+                        cbThisParsed = 1;
+                        break;
+                    case DBGFTYPEBUILTIN_UINT16:
+                        pvVal = &pValBuf->u16;
+                        cbThisParsed = 2;
+                        break;
+                    case DBGFTYPEBUILTIN_INT16:
+                        pvVal = &pValBuf->i16;
+                        cbThisParsed = 2;
+                        break;
+                    case DBGFTYPEBUILTIN_UINT32:
+                        pvVal = &pValBuf->u32;
+                        cbThisParsed = 4;
+                        break;
+                    case DBGFTYPEBUILTIN_INT32:
+                        pvVal = &pValBuf->i32;
+                        cbThisParsed = 4;
+                        break;
+                    case DBGFTYPEBUILTIN_UINT64:
+                        pvVal = &pValBuf->u64;
+                        cbThisParsed = 8;
+                        break;
+                    case DBGFTYPEBUILTIN_INT64:
+                        pvVal = &pValBuf->i64;
+                        cbThisParsed = 8;
+                        break;
+                    case DBGFTYPEBUILTIN_PTR32:
+                        pvVal = &pValBuf->GCPtr;
+                        cbThisParsed = 4;
+                        break;
+                    case DBGFTYPEBUILTIN_PTR64:
+                        pvVal = &pValBuf->GCPtr;
+                        cbThisParsed = 8;
+                        break;
+                    case DBGFTYPEBUILTIN_PTR:
+                        pvVal = &pValBuf->GCPtr;
+                        cbThisParsed = pTypeMember->cbType;
+                        break;
+                    case DBGFTYPEBUILTIN_FLOAT32:
+                    case DBGFTYPEBUILTIN_FLOAT64:
+                    case DBGFTYPEBUILTIN_COMPOUND:
+                    default:
+                        AssertMsgFailedBreakStmt(("Invalid built-in type specified: %d\n", pTypeMember->enmTypeBuiltin),
+                                                 rc = VERR_INVALID_STATE);
+                }
+
+                if (RT_SUCCESS(rc))
+                {
+                    pValEntry->enmType = pTypeMember->enmTypeBuiltin;
+                    if (cbBuf >= cbThisParsed)
+                        memcpy(pvVal, pbBuf, cbThisParsed);
+                    else
+                        rc = VERR_BUFFER_OVERFLOW;
+                }
+            }
+
+            pValBuf++;
+            cbParsed += cbThisParsed;
+            pbBuf    += cbThisParsed;
+            cbBuf    -= cbThisParsed;
+        }
+    }
+
+    if (   RT_FAILURE(rc)
+        && cValBufs > 1)
+        MMR3HeapFree(pValBuf);
+
+    if (RT_SUCCESS(rc))
+    {
+        pValEntry->cEntries = cValBufs;
+        *pcbParsed = cbParsed;
+    }
+
+    return rc;
+}
+
+/**
+ * Parses the given byte buffer and returns the value based no the type information.
+ *
+ * @returns VBox status code.
+ * @param   pUVM                The user mode VM handle.
+ * @param   pType               The type information.
+ * @param   pbBuf               The byte buffer to parse.
+ * @param   cbBuf               Size of the buffer.
+ * @param   ppVal               Where to store the pointer to the value on success.
+ * @param   pcbParsed           How many bytes of the buffer we consumed.
+ */
+static int dbgfR3TypeParseBufferByType(PUVM pUVM, PDBGFTYPE pType, uint8_t *pbBuf, size_t cbBuf,
+                                       PDBGFTYPEVAL *ppVal, size_t *pcbParsed)
+{
+    int rc = VINF_SUCCESS;
+    uint32_t cEntries = pType->pReg ? pType->pReg->cMembers : 1;
+    PDBGFTYPEVAL pVal = (PDBGFTYPEVAL)MMR3HeapAllocZU(pUVM, MM_TAG_DBGF_TYPE,
+                                                      RT_OFFSETOF(DBGFTYPEVAL, aEntries[cEntries]));
+    if (RT_LIKELY(pVal))
+    {
+        size_t cbParsed = 0;
+
+        pVal->pTypeReg = pType->pReg;
+        for (uint32_t i = 0; i < cEntries && RT_SUCCESS(rc); i++)
+        {
+            PCDBGFTYPEREGMEMBER pMember = &pType->pReg->paMembers[i];
+            PDBGFTYPEVALENTRY pValEntry = &pVal->aEntries[i];
+            rc = dbgfR3TypeParseEntry(pUVM, pMember, pValEntry, pbBuf, cbBuf, &cbParsed);
+            if (RT_SUCCESS(rc))
+            {
+                pbBuf += cbParsed;
+                cbBuf -= cbParsed;
+            }
+        }
+
+        if (RT_SUCCESS(rc))
+        {
+            pVal->cEntries = cEntries;
+            *pcbParsed = cbParsed;
+            *ppVal     = pVal;
+        }
+        else
+            MMR3HeapFree(pVal); /** @todo: Leak for embedded structs. */
+    }
+    else
+        rc = VERR_NO_MEMORY;
+
+    return rc;
+}
+
+/**
+ * Initializes the type database.
+ *
+ * @returns VBox status code.
+ * @param   pUVM                The user mode VM handle.
+ */
+DECLHIDDEN(int)  dbgfR3TypeInit(PUVM pUVM)
+{
+    int  rc   = VINF_SUCCESS;
+    if (!pUVM->dbgf.s.fTypeDbInitialized)
+    {
+        rc = RTSemRWCreate(&pUVM->dbgf.s.hTypeDbLock);
+        if (RT_SUCCESS(rc))
+        {
+            rc = dbgfTypeRegisterBuiltinTypes(pUVM);
+            if (RT_FAILURE(rc))
+            {
+                RTSemRWDestroy(pUVM->dbgf.s.hTypeDbLock);
+                pUVM->dbgf.s.hTypeDbLock = NIL_RTSEMRW;
+            }
+        }
+        pUVM->dbgf.s.fTypeDbInitialized = RT_SUCCESS(rc);
+    }
+    return rc;
+}
+
+/**
+ * Terminates the type database.
+ *
+ * @param   pUVM                The user mode VM handle.
+ */
+DECLHIDDEN(void) dbgfR3TypeTerm(PUVM pUVM)
+{
+    RTSemRWDestroy(pUVM->dbgf.s.hTypeDbLock);
+    pUVM->dbgf.s.hTypeDbLock = NIL_RTSEMRW;
+    pUVM->dbgf.s.fTypeDbInitialized = false;
+}
+
+/**
+ * Registers a new type for lookup.
+ *
+ * @returns VBox status code.
+ * @retval  VERR_ALREADY_EXISTS if the type exists already.
+ * @param   pUVM                The user mode VM handle.
+ * @param   cTypes              Number of types to register.
+ * @param   paTypes             The array of type registration structures to register.
+ */
+VMMR3DECL(int) DBGFR3TypeRegister(PUVM pUVM, uint32_t cTypes, PCDBGFTYPEREG paTypes)
+{
+    UVM_ASSERT_VALID_EXT_RETURN(pUVM, VERR_INVALID_VM_HANDLE);
+    AssertReturn(cTypes > 0, VERR_INVALID_PARAMETER);
+    AssertPtrReturn(paTypes, VERR_INVALID_POINTER);
+
+    int rc = VINF_SUCCESS;
+    if (!pUVM->dbgf.s.fTypeDbInitialized)
+    {
+        rc = dbgfR3TypeInit(pUVM);
+        if (RT_FAILURE(rc))
+            return rc;
+    }
+
+    DBGF_TYPE_DB_LOCK_WRITE(pUVM);
+    for (uint32_t i = 0; i < cTypes && RT_SUCCESS(rc); i++)
+    {
+        rc = dbgfR3TypeRegister(pUVM, &paTypes[i]);
+        if (   RT_FAILURE(rc)
+            && i > 0)
+        {
+            /* Deregister types in reverse order. */
+            do
+            {
+                int rc2 = DBGFR3TypeDeregister(pUVM, paTypes[i].pszType);
+                AssertRC(rc2);
+                i--;
+            } while (i > 0);
+
+            break;
+        }
+    }
+    DBGF_TYPE_DB_UNLOCK_WRITE(pUVM);
+
+    return rc;
+}
+
+/**
+ * Deregisters a previously registered type.
+ *
+ * @returns VBox status code.
+ * @param   VERR_NOT_FOUND if the type is not known.
+ * @param   VERR_RESOURCE_IN_USE if the type is used by another type.
+ * @param   pUVM                The user mode VM handle.
+ * @param   pszType             The type identifier to deregister.
+ */
+VMMR3DECL(int) DBGFR3TypeDeregister(PUVM pUVM, const char *pszType)
+{
+    UVM_ASSERT_VALID_EXT_RETURN(pUVM, VERR_INVALID_VM_HANDLE);
+    AssertPtrReturn(pszType, VERR_INVALID_POINTER);
+
+    DBGF_TYPE_DB_LOCK_WRITE(pUVM);
+    int rc = VINF_SUCCESS;
+    PDBGFTYPE pType = dbgfR3TypeLookup(pUVM, pszType);
+    if (pType)
+    {
+        if (!pType->cRefs)
+        {
+            
+        }
+        else
+            rc = VERR_RESOURCE_IN_USE;
+    }
+    else
+        rc = VERR_NOT_FOUND;
+    DBGF_TYPE_DB_UNLOCK_WRITE(pUVM);
+
+    return rc;
+}
+
+/**
+ * Return the type registration structure for the given type identifier.
+ *
+ * @returns VBox status code.
+ * @retval  VERR_NOT_FOUND if the type is not known.
+ * @param   pUVM                The user mode VM handle.
+ * @param   pszType             The type identifier to get the registration structure from.
+ * @param   ppTypeReg           Where to store the type registration structure on success.
+ */
+VMMR3DECL(int) DBGFR3TypeQueryReg(PUVM pUVM, const char *pszType, PCDBGFTYPEREG *ppTypeReg)
+{
+    UVM_ASSERT_VALID_EXT_RETURN(pUVM, VERR_INVALID_VM_HANDLE);
+    AssertPtrReturn(pszType, VERR_INVALID_POINTER);
+    AssertPtrReturn(ppTypeReg, VERR_INVALID_POINTER);
+
+    DBGF_TYPE_DB_LOCK_READ(pUVM);
+    int rc = VINF_SUCCESS;
+    PDBGFTYPE pType = dbgfR3TypeLookup(pUVM, pszType);
+    if (pType)
+        *ppTypeReg = pType->pReg;
+    else
+        rc = VERR_NOT_FOUND;
+    DBGF_TYPE_DB_UNLOCK_READ(pUVM);
+
+    return rc;
+}
+
+/**
+ * Queries the size a given type would occupy in memory.
+ *
+ * @returns VBox status code.
+ * @retval  VERR_NOT_FOUND if the type is not known.
+ * @param   pUVM                The user mode VM handle.
+ * @param   pszType             The type identifier.
+ * @param   pcbType             Where to store the amount of memory occupied in bytes.
+ */
+VMMR3DECL(int) DBGFR3TypeQuerySize(PUVM pUVM, const char *pszType, size_t *pcbType)
+{
+    LogFlowFunc(("pUVM=%#p pszType=%s pcbType=%#p\n", pUVM, pszType, pcbType));
+    UVM_ASSERT_VALID_EXT_RETURN(pUVM, VERR_INVALID_VM_HANDLE);
+    AssertPtrReturn(pszType, VERR_INVALID_POINTER);
+    AssertPtrReturn(pcbType, VERR_INVALID_POINTER);
+
+    DBGF_TYPE_DB_LOCK_READ(pUVM);
+    int rc = VINF_SUCCESS;
+    PDBGFTYPE pType = dbgfR3TypeLookup(pUVM, pszType);
+    if (pType)
+        *pcbType = pType->cbType;
+    else
+        rc = VERR_NOT_FOUND;
+    DBGF_TYPE_DB_UNLOCK_READ(pUVM);
+
+    return rc;
+}
+
+/**
+ * Sets the size of the given type in bytes.
+ *
+ * @returns VBox status code.
+ * @retval  VERR_NOT_FOUND if the type is not known.
+ * @retval  VERR_NOT_SUPPORTED if changing the size of this type is not supported.
+ * @param   pUVM                The user mode VM handle.
+ * @param   pszType             The type identifier.
+ * @param   cbType              The size of the type in bytes.
+ *
+ * @note: This currently works only for the builtin pointer type without the explicit
+ *        size (ptr_t or DBGFTYPEBUILTIN_PTR).
+ */
+VMMR3DECL(int) DBGFR3TypeSetSize(PUVM pUVM, const char *pszType, size_t cbType)
+{
+    LogFlowFunc(("pUVM=%#p pszType=%s cbType=%zu\n", pUVM, pszType, cbType));
+    UVM_ASSERT_VALID_EXT_RETURN(pUVM, VERR_INVALID_VM_HANDLE);
+    AssertPtrReturn(pszType, VERR_INVALID_POINTER);
+    AssertReturn(cbType > 0, VERR_INVALID_PARAMETER);
+
+    DBGF_TYPE_DB_LOCK_WRITE(pUVM);
+    int rc = VINF_SUCCESS;
+    PDBGFTYPE pType = dbgfR3TypeLookup(pUVM, pszType);
+    if (pType)
+    {
+        if (   !pType->pReg
+            && (   pType->enmTypeBuiltin == DBGFTYPEBUILTIN_PTR
+                || pType->enmTypeBuiltin == DBGFTYPEBUILTIN_SIZE))
+        {
+            if (pType->cbType != cbType)
+            {
+                pType->cbType = cbType;
+                rc = dbgfR3TypeRecalculateAllSizes(pUVM);
+            }
+        }
+        else
+            rc = VERR_NOT_SUPPORTED;
+    }
+    else
+        rc = VERR_NOT_FOUND;
+    DBGF_TYPE_DB_UNLOCK_WRITE(pUVM);
+
+    return rc;
+}
+
+/**
+ * Returns the value of a memory buffer at the given address formatted for the given
+ * type.
+ *
+ * @returns VBox status code.
+ * @retval  VERR_NOT_FOUND if the type is not known.
+ * @param   pUVM                The user mode VM handle.
+ * @param   pAddress            The address to start reading from.
+ * @param   pszType             The type identifier.
+ * @param   ppVal               Where to store the pointer to the value structure
+ *                              on success.
+ */
+VMMR3DECL(int) DBGFR3TypeQueryValByType(PUVM pUVM, PCDBGFADDRESS pAddress, const char *pszType,
+                                        PDBGFTYPEVAL *ppVal)
+{
+    LogFlowFunc(("pUVM=%#p pAddress=%#p pszType=%s ppVal=%#p\n", pUVM, pAddress, pszType, ppVal));
+    UVM_ASSERT_VALID_EXT_RETURN(pUVM, VERR_INVALID_VM_HANDLE);
+    AssertPtrReturn(pAddress, VERR_INVALID_POINTER);
+    AssertPtrReturn(pszType, VERR_INVALID_POINTER);
+    AssertPtrReturn(ppVal, VERR_INVALID_POINTER);
+
+    DBGF_TYPE_DB_LOCK_READ(pUVM);
+    int rc = VINF_SUCCESS;
+    PDBGFTYPE pType = dbgfR3TypeLookup(pUVM, pszType);
+    if (pType)
+    {
+        uint8_t *pbBuf = (uint8_t *)MMR3HeapAllocZU(pUVM, MM_TAG_DBGF_TYPE, pType->cbType);
+        if (RT_LIKELY(pbBuf))
+        {
+            rc = DBGFR3MemRead(pUVM, 0 /*idCpu*/, pAddress, pbBuf, pType->cbType);
+            if (RT_SUCCESS(rc))
+            {
+                /* Parse the buffer based on the type. */
+                size_t cbParsed = 0;
+                rc = dbgfR3TypeParseBufferByType(pUVM, pType, pbBuf, pType->cbType,
+                                                 ppVal, &cbParsed);
+            }
+ 
+            MMR3HeapFree(pbBuf);
+        }
+        else
+            rc = VERR_NO_MEMORY;
+    }
+    else
+        rc = VERR_NOT_FOUND;
+    DBGF_TYPE_DB_UNLOCK_READ(pUVM);
+
+    return rc;
+}
+
+/**
+ * Frees all acquired resources of a value previously obtained with
+ * DBGFR3TypeQueryValByType().
+ *
+ * @returns nothing.
+ * @param   pVal                The value to free.
+ */
+VMMR3DECL(void) DBGFR3TypeValFree(PDBGFTYPEVAL pVal)
+{
+    AssertPtrReturnVoid(pVal);
+
+    for (uint32_t i = 0; i < pVal->cEntries; i++)
+    {
+        PDBGFTYPEVAL pValEntry = &pVal->aEntries[i];
+        PDBGFVALBUF pValBuf = pValEntry->cEntries > 1 ? pValEntry->Buf.pVal : &pValEntry->Buf.Val;
+
+        if (pValEntry->enmType == DBGFTYPEBUILTIN_COMPOUND)
+            for (uint32_t iBuf = 0; iBuf < pValEntry->cEntries; iBuf++)
+                DBGFR3TypeValFree(pValBuf->pVal);
+
+        if (pValEntry->cEntries > 1)
+            MMR3HeapFree(pValEntry->Buf.pVal);
+    }
+
+    MMR3HeapFree(pVal);
+}
+
