VirtualBox

Changeset 19757 in vbox


Ignore:
Timestamp:
May 15, 2009 11:37:31 PM (16 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
47378
Message:

VMM,IPRT,DBGC: Debug address spaces.

Location:
trunk
Files:
11 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/VBox/dbgf.h

    r19639 r19757  
    3838
    3939#include <iprt/stdarg.h>
     40#include <iprt/dbg.h>
    4041
    4142__BEGIN_DECLS
     
    586587typedef const DBGFLINE *PCDBGFLINE;
    587588
     589/** @name Address spaces aliases.
     590 * @{ */
     591/** The guest global address space. */
     592#define DBGF_AS_GLOBAL              ((RTDBGAS)-1)
     593/** The guest kernel address space.
     594 * This is usually resolves to the same as DBGF_AS_GLOBAL. */
     595#define DBGF_AS_KERNEL              ((RTDBGAS)-2)
     596/** The physical address space. */
     597#define DBGF_AS_PHYS                ((RTDBGAS)-3)
     598/** Raw-mode context. */
     599#define DBGF_AS_RC                  ((RTDBGAS)-4)
     600/** Ring-0 context. */
     601#define DBGF_AS_R0                  ((RTDBGAS)-5)
     602/** Raw-mode context and then global guest context.
     603 * When used for looking up information, it works as if the call was first made
     604 * with DBGF_AS_RC and then on failure with DBGF_AS_GLOBAL. When called for
     605 * making address space changes, it works as if DBGF_AS_RC was used. */
     606#define DBGF_AS_RC_AND_GC_GLOBAL    ((RTDBGAS)-6)
     607
     608/** The first special one. */
     609#define DBGF_AS_FIRST               DBGF_AS_RC_AND_GC_GLOBAL
     610/** The last special one. */
     611#define DBGF_AS_LAST                DBGF_AS_GLOBAL
     612/** The number of special address space handles. */
     613#define DBGF_AS_COUNT               ((uintptr_t)DBGF_AS_LAST - (uintptr_t)DBGF_AS_FIRST + 1U)
     614/** Converts an alias handle to an array index. */
     615#define DBGF_AS_ALIAS_2_INDEX(hAlias) \
     616    ( (uintptr_t)(hAlias) - (uintptr_t)DBGF_AS_FIRST )
     617/** Predicat macro that check if the specified handle is an alias. */
     618#define DBGF_AS_IS_ALIAS(hAlias) \
     619    ( DBGF_AS_ALIAS_2_INDEX(hAlias)  <  DBGF_AS_COUNT )
     620/** Predicat macro that check if the specified alias is a fixed one or not. */
     621#define DBGF_AS_IS_FIXED_ALIAS(hAlias) \
     622    ( DBGF_AS_ALIAS_2_INDEX(hAlias)  <  (uintptr_t)DBGF_AS_PHYS - (uintptr_t)DBGF_AS_FIRST + 1U )
     623
     624/** @} */
     625
     626VMMR3DECL(int)          DBGFR3AsAdd(PVM pVM, RTDBGAS hDbgAs, RTPROCESS ProcId);
     627VMMR3DECL(int)          DBGFR3AsDelete(PVM pVM, RTDBGAS hDbgAs);
     628VMMR3DECL(int)          DBGFR3AsSetAlias(PVM pVM, RTDBGAS hAlias, RTDBGAS hAliasFor);
     629VMMR3DECL(RTDBGAS)      DBGFR3AsResolve(PVM pVM, RTDBGAS hAlias);
     630VMMR3DECL(RTDBGAS)      DBGFR3AsResolveAndRetain(PVM pVM, RTDBGAS hAlias);
     631VMMR3DECL(RTDBGAS)      DBGFR3AsQueryByName(PVM pVM, const char *pszName);
     632VMMR3DECL(RTDBGAS)      DBGFR3AsQueryByPid(PVM pVM, RTPROCESS ProcId);
     633
     634VMMR3DECL(int)          DBGFR3AsLoadImage(PVM pVM, RTDBGAS hDbgAs, const char *pszFilename, const char *pszModName, PCDBGFADDRESS pModAddress, RTDBGSEGIDX iModSeg, uint32_t fFlags);
     635VMMR3DECL(int)          DBGFR3AsLoadMap(PVM pVM, RTDBGAS hDbgAs, const char *pszFilename, const char *pszModName, PCDBGFADDRESS pModAddress, RTDBGSEGIDX iModSeg, RTGCUINTPTR uSubtrahend, uint32_t fFlags);
     636VMMR3DECL(int)          DBGFR3AsLinkModule(PVM pVM, RTDBGAS hDbgAs, RTDBGMOD hMod, PCDBGFADDRESS pModAddress, RTDBGSEGIDX iModSeg, uint32_t fFlags);
     637
     638/* The following are soon to be obsoleted: */
    588639VMMR3DECL(int)          DBGFR3ModuleLoad(PVM pVM, const char *pszFilename, RTGCUINTPTR AddressDelta, const char *pszName, RTGCUINTPTR ModuleAddress, unsigned cbImage);
    589640VMMR3DECL(void)         DBGFR3ModuleRelocate(PVM pVM, RTGCUINTPTR OldImageBase, RTGCUINTPTR NewImageBase, RTGCUINTPTR cbImage,
  • trunk/include/VBox/mm.h

    r19682 r19757  
    6666
    6767    MM_TAG_DBGF,
     68    MM_TAG_DBGF_AS,
    6869    MM_TAG_DBGF_INFO,
    6970    MM_TAG_DBGF_LINE,
  • trunk/include/iprt/dbg.h

    r19561 r19757  
    4242/** NIL debug segment index. */
    4343#define NIL_RTDBGSEGIDX     UINT32_C(0xffffffff)
     44/** The last normal segment index. */
     45#define RTDBGSEGIDX_LAST    UINT32_C(0xffffffef)
    4446/** Special segment index that indicates that the offset is a relative
    4547 * virtual address (RVA). I.e. an offset from the start of the module. */
     
    144146
    145147/**
    146  * Destroys the address space.
    147  *
    148  * This means unlinking all the modules it currently contains, potentially
     148 * Retains a reference to the address space.
     149 *
     150 * @returns New reference count, UINT32_MAX on invalid handle (asserted).
     151 *
     152 * @param   hDbgAs          The address space handle.
     153 *
     154 * @remarks Will not take any locks.
     155 */
     156RTDECL(uint32_t) RTDbgAsRetain(RTDBGAS hDbgAs);
     157
     158/**
     159 * Release a reference to the address space.
     160 *
     161 * When the reference count reaches zero, the address space is destroyed.
     162 * That means unlinking all the modules it currently contains, potentially
    149163 * causing some or all of them to be destroyed as they are managed by
    150164 * reference counting.
    151165 *
    152  * @returns IPRT status code.
    153  *
    154  * @param   hDbgAs          The address space handle. A NIL handle will
    155  *                          be quietly ignored.
    156  */
    157 RTDECL(int) RTDbgAsDestroy(RTDBGAS hDbgAs);
     166 * @returns New reference count, UINT32_MAX on invalid handle (asserted).
     167 *
     168 * @param   hDbgAs          The address space handle. The NIL handle is quietly
     169 *                          ignored and 0 is returned.
     170 *
     171 * @remarks Will not take any locks.
     172 */
     173RTDECL(uint32_t) RTDbgAsRelease(RTDBGAS hDbgAs);
    158174
    159175/**
     
    164180 *
    165181 * @param   hDbgAs          The address space handle.
     182 *
     183 * @remarks Will not take any locks.
    166184 */
    167185RTDECL(const char *) RTDbgAsName(RTDBGAS hDbgAs);
     
    174192 *
    175193 * @param   hDbgAs          The address space handle.
     194 *
     195 * @remarks Will not take any locks.
    176196 */
    177197RTDECL(RTUINTPTR) RTDbgAsFirstAddr(RTDBGAS hDbgAs);
     
    184204 *
    185205 * @param   hDbgAs          The address space handle.
     206 *
     207 * @remarks Will not take any locks.
    186208 */
    187209RTDECL(RTUINTPTR) RTDbgAsLastAddr(RTDBGAS hDbgAs);
     
    196218 *
    197219 * @param   hDbgAs          The address space handle.
     220 *
     221 * @remarks Will not take any locks.
    198222 */
    199223RTDECL(uint32_t) RTDbgAsModuleCount(RTDBGAS hDbgAs);
     224
     225/** @name Flags for RTDbgAsModuleLink and RTDbgAsModuleLinkSeg
     226 * @{ */
     227/** Replace all conflicting module.
     228 * (The conflicting modules will be removed the address space and their
     229 * references released.) */
     230#define RTDBGASLINK_FLAGS_REPLACE       RT_BIT_32(0)
     231/** Mask containing the valid flags. */
     232#define RTDBGASLINK_FLAGS_VALID_MASK    UINT32_C(0x00000001)
     233/** @} */
    200234
    201235/**
     
    212246 * @param   hDbgMod         The module handle of the module to be linked in.
    213247 * @param   ImageAddr       The address to link the module at.
    214  */
    215 RTDECL(int) RTDbgAsModuleLink(RTDBGAS hDbgAs, RTDBGMOD hDbgMod, RTUINTPTR ImageAddr);
     248 * @param   fFlags          See RTDBGASLINK_FLAGS_*.
     249 */
     250RTDECL(int) RTDbgAsModuleLink(RTDBGAS hDbgAs, RTDBGMOD hDbgMod, RTUINTPTR ImageAddr, uint32_t fFlags);
    216251
    217252/**
     
    230265 *                          linked in.
    231266 * @param   SegAddr         The address to link the segment at.
    232  */
    233 RTDECL(int) RTDbgAsModuleLinkSeg(RTDBGAS hDbgAs, RTDBGMOD hDbgMod, RTDBGSEGIDX iSeg, RTUINTPTR SegAddr);
     267 * @param   fFlags          See RTDBGASLINK_FLAGS_*.
     268 */
     269RTDECL(int) RTDbgAsModuleLinkSeg(RTDBGAS hDbgAs, RTDBGMOD hDbgMod, RTDBGSEGIDX iSeg, RTUINTPTR SegAddr, uint32_t fFlags);
    234270
    235271/**
     
    414450 * @{
    415451 */
    416 RTDECL(int)         RTDbgModCreate(PRTDBGMOD phDbgMod, const char *pszName, const char *pszImgFile, const char *pszDbgFile);
    417 RTDECL(int)         RTDbgModDestroy(RTDBGMOD hDbgMod);
     452RTDECL(int)         RTDbgModCreate(PRTDBGMOD phDbgMod, const char *pszName, RTUINTPTR cb, uint32_t fFlags);
     453RTDECL(int)         RTDbgModCreateFromImage(PRTDBGMOD phDbgMod, const char *pszFilename, const char *pszName, uint32_t fFlags);
     454RTDECL(int)         RTDbgModCreateFromMap(PRTDBGMOD phDbgMod, const char *pszFilename, const char *pszName, RTUINTPTR uSubtrahend, uint32_t fFlags);
    418455RTDECL(uint32_t)    RTDbgModRetain(RTDBGMOD hDbgMod);
    419456RTDECL(uint32_t)    RTDbgModRelease(RTDBGMOD hDbgMod);
  • trunk/src/VBox/Runtime/common/dbg/dbgas.cpp

    r19566 r19757  
    3535#include <iprt/asm.h>
    3636#include <iprt/avl.h>
     37#include <iprt/assert.h>
     38#include <iprt/err.h>
     39#include <iprt/mem.h>
     40#include <iprt/param.h>
    3741#include <iprt/string.h>
    38 
    39 #include <iprt/mem.h>
    40 #include <iprt/err.h>
    41 #include <iprt/assert.h>
    42 #include <iprt/param.h>
    43 //#include "internal/dbg.h"
     42#include <iprt/semaphore.h>
    4443#include "internal/magics.h"
    4544
     
    102101    /** Magic value (RTDBGAS_MAGIC). */
    103102    uint32_t            u32Magic;
     103    /** The number of reference to this address space. */
     104    uint32_t volatile   cRefs;
     105    /** Handle of the read-write lock. */
     106    RTSEMRW             hLock;
    104107    /** Number of modules in the module address space. */
    105108    uint32_t            cModules;
     
    132135        AssertPtrReturn((pDbgAs), (rc)); \
    133136        AssertReturn((pDbgAs)->u32Magic == RTDBGAS_MAGIC, (rc)); \
     137        AssertReturn((pDbgAs)->cRefs > 0, (rc)); \
     138    } while (0)
     139
     140/** Locks the address space for reading. */
     141#define RTDBGAS_LOCK_READ(pDbgAs) \
     142    do { \
     143        int rcLock = RTSemRWRequestRead((pDbgAs)->hLock, RT_INDEFINITE_WAIT); \
     144        AssertRC(rcLock); \
     145    } while (0)
     146
     147/** Unlocks the address space after reading. */
     148#define RTDBGAS_UNLOCK_READ(pDbgAs) \
     149    do { \
     150        int rcLock = RTSemRWReleaseRead((pDbgAs)->hLock); \
     151        AssertRC(rcLock); \
     152    } while (0)
     153
     154/** Locks the address space for writing. */
     155#define RTDBGAS_LOCK_WRITE(pDbgAs) \
     156    do { \
     157        int rcLock = RTSemRWRequestWrite((pDbgAs)->hLock, RT_INDEFINITE_WAIT); \
     158        AssertRC(rcLock); \
     159    } while (0)
     160
     161/** Unlocks the address space after writing. */
     162#define RTDBGAS_UNLOCK_WRITE(pDbgAs) \
     163    do { \
     164        int rcLock = RTSemRWReleaseWrite((pDbgAs)->hLock); \
     165        AssertRC(rcLock); \
    134166    } while (0)
    135167
     
    139171*******************************************************************************/
    140172static void rtDbgAsModuleUnlinkMod(PRTDBGASINT pDbgAs, PRTDBGASMOD pMod);
     173static void rtDbgAsModuleUnlinkByMap(PRTDBGASINT pDbgAs, PRTDBGASMAP pMap);
    141174
    142175
     
    170203    /* initalize it. */
    171204    pDbgAs->u32Magic    = RTDBGAS_MAGIC;
     205    pDbgAs->cRefs       = 1;
     206    pDbgAs->hLock       = NIL_RTSEMRW;
    172207    pDbgAs->cModules    = 0;
    173208    pDbgAs->paModules   = NULL;
     
    178213    pDbgAs->LastAddr    = LastAddr;
    179214    memcpy(pDbgAs->szName, pszName, cchName + 1);
    180 
    181     *phDbgAs = pDbgAs;
    182     return VINF_SUCCESS;
     215    int rc = RTSemRWCreate(&pDbgAs->hLock);
     216    if (RT_SUCCESS(rc))
     217    {
     218        *phDbgAs = pDbgAs;
     219        return VINF_SUCCESS;
     220    }
     221
     222    pDbgAs->u32Magic = 0;
     223    RTMemFree(pDbgAs);
     224    return rc;
    183225}
    184226
     
    269311 * reference counting.
    270312 *
    271  * @returns IPRT status code.
    272  *
    273  * @param   hDbgAs          The address space handle. A NIL handle will
    274  *                          be quietly ignored.
    275  */
    276 RTDECL(int) RTDbgAsDestroy(RTDBGAS hDbgAs)
    277 {
    278     /*
    279      * Validate input.
    280      */
    281     if (hDbgAs == NIL_RTDBGAS)
    282         return VINF_SUCCESS;
    283     PRTDBGASINT pDbgAs = hDbgAs;
    284     RTDBGAS_VALID_RETURN_RC(pDbgAs, VERR_INVALID_HANDLE);
    285 
     313 * @param   pDbgAs          The address space instance to be destroyed.
     314 */
     315static void rtDbgAsDestroy(PRTDBGASINT pDbgAs)
     316{
    286317    /*
    287318     * Mark the address space invalid and release all the modules.
     
    302333
    303334    RTMemFree(pDbgAs);
    304 
    305     return VINF_SUCCESS;
     335}
     336
     337
     338/**
     339 * Retains a reference to the address space.
     340 *
     341 * @returns New reference count, UINT32_MAX on invalid handle (asserted).
     342 *
     343 * @param   hDbgAs          The address space handle.
     344 *
     345 * @remarks Will not take any locks.
     346 */
     347RTDECL(uint32_t) RTDbgAsRetain(RTDBGAS hDbgAs)
     348{
     349    PRTDBGASINT pDbgAs = hDbgAs;
     350    RTDBGAS_VALID_RETURN_RC(pDbgAs, UINT32_MAX);
     351    return ASMAtomicIncU32(&pDbgAs->cRefs);
     352}
     353
     354
     355/**
     356 * Release a reference to the address space.
     357 *
     358 * When the reference count reaches zero, the address space is destroyed.
     359 * That means unlinking all the modules it currently contains, potentially
     360 * causing some or all of them to be destroyed as they are managed by
     361 * reference counting.
     362 *
     363 * @returns New reference count, UINT32_MAX on invalid handle (asserted).
     364 *
     365 * @param   hDbgAs          The address space handle. The NIL handle is quietly
     366 *                          ignored and 0 is returned.
     367 *
     368 * @remarks Will not take any locks.
     369 */
     370RTDECL(uint32_t) RTDbgAsRelease(RTDBGAS hDbgAs)
     371{
     372    if (hDbgAs == NIL_RTDBGAS)
     373        return 0;
     374    PRTDBGASINT pDbgAs = hDbgAs;
     375    RTDBGAS_VALID_RETURN_RC(pDbgAs, UINT32_MAX);
     376
     377    uint32_t cRefs = ASMAtomicDecU32(&pDbgAs->cRefs);
     378    if (!cRefs)
     379        rtDbgAsDestroy(pDbgAs);
     380    return cRefs;
    306381}
    307382
     
    314389 *
    315390 * @param   hDbgAs          The address space handle.
     391 *
     392 * @remarks Will not take any locks.
    316393 */
    317394RTDECL(const char *) RTDbgAsName(RTDBGAS hDbgAs)
     
    330407 *
    331408 * @param   hDbgAs          The address space handle.
     409 *
     410 * @remarks Will not take any locks.
    332411 */
    333412RTDECL(RTUINTPTR) RTDbgAsFirstAddr(RTDBGAS hDbgAs)
     
    346425 *
    347426 * @param   hDbgAs          The address space handle.
     427 *
     428 * @remarks Will not take any locks.
    348429 */
    349430RTDECL(RTUINTPTR) RTDbgAsLastAddr(RTDBGAS hDbgAs)
     
    363444 *
    364445 * @param   hDbgAs          The address space handle.
    365  */
    366 RTDECL(uint32_t)    RTDbgAsModuleCount(RTDBGAS hDbgAs)
     446 *
     447 * @remarks Will not take any locks.
     448 */
     449RTDECL(uint32_t) RTDbgAsModuleCount(RTDBGAS hDbgAs)
    367450{
    368451    PRTDBGASINT pDbgAs = hDbgAs;
     
    382465 * @param   cb              The size of what we're linking.
    383466 * @param   pszName         The name of the module.
     467 * @param   fFlags          See RTDBGASLINK_FLAGS_*.
     468 *
     469 * @remarks The caller must have locked the address space for writing.
    384470 */
    385471int rtDbgAsModuleLinkCommon(PRTDBGASINT pDbgAs, RTDBGMOD hDbgMod, RTDBGSEGIDX iSeg,
    386                             RTUINTPTR Addr, RTUINTPTR cb, const char *pszName)
     472                            RTUINTPTR Addr, RTUINTPTR cb, const char *pszName, uint32_t fFlags)
    387473{
    388474    /*
    389475     * Check that the requested space is undisputed.
    390476     */
    391    PRTDBGASMAP pAdjMod = (PRTDBGASMAP)RTAvlrUIntPtrGetBestFit(&pDbgAs->MapTree, Addr, false /* fAbove */);
    392    if (     pAdjMod
    393        &&   pAdjMod->Core.KeyLast >= Addr)
    394        return VERR_ADDRESS_CONFLICT;
    395    pAdjMod = (PRTDBGASMAP)RTAvlrUIntPtrGetBestFit(&pDbgAs->MapTree, Addr, true /* fAbove */);
    396    if (     pAdjMod
    397        &&   pAdjMod->Core.Key >= Addr + cb - 1)
    398        return VERR_ADDRESS_CONFLICT;
     477    for (;;)
     478    {
     479        PRTDBGASMAP pAdjMod = (PRTDBGASMAP)RTAvlrUIntPtrGetBestFit(&pDbgAs->MapTree, Addr, false /* fAbove */);
     480        if (     pAdjMod
     481            &&   pAdjMod->Core.KeyLast >= Addr)
     482        {
     483            if (!(fFlags & RTDBGASLINK_FLAGS_REPLACE))
     484                return VERR_ADDRESS_CONFLICT;
     485            rtDbgAsModuleUnlinkByMap(pDbgAs, pAdjMod);
     486            continue;
     487        }
     488        pAdjMod = (PRTDBGASMAP)RTAvlrUIntPtrGetBestFit(&pDbgAs->MapTree, Addr, true /* fAbove */);
     489        if (     pAdjMod
     490            &&   pAdjMod->Core.Key >= Addr + cb - 1)
     491        {
     492            if (!(fFlags & RTDBGASLINK_FLAGS_REPLACE))
     493                return VERR_ADDRESS_CONFLICT;
     494            rtDbgAsModuleUnlinkByMap(pDbgAs, pAdjMod);
     495            continue;
     496        }
     497        break;
     498    }
    399499
    400500    /*
     
    491591
    492592
    493 
    494 
    495593/**
    496594 * Links a module into the address space at the give address.
     
    506604 * @param   hDbgMod         The module handle of the module to be linked in.
    507605 * @param   ImageAddr       The address to link the module at.
    508  */
    509 RTDECL(int) RTDbgAsModuleLink(RTDBGAS hDbgAs, RTDBGMOD hDbgMod, RTUINTPTR ImageAddr)
     606 * @param   fFlags          See RTDBGASLINK_FLAGS_*.
     607 */
     608RTDECL(int) RTDbgAsModuleLink(RTDBGAS hDbgAs, RTDBGMOD hDbgMod, RTUINTPTR ImageAddr, uint32_t fFlags)
    510609{
    511610    /*
     
    526625        ||  ImageAddr + cb - 1  < ImageAddr)
    527626        return VERR_OUT_OF_RANGE;
     627    AssertReturn(!(fFlags & ~RTDBGASLINK_FLAGS_VALID_MASK), VERR_INVALID_PARAMETER);
    528628
    529629    /*
    530630     * Invoke worker common with RTDbgAsModuleLinkSeg.
    531631     */
    532     return rtDbgAsModuleLinkCommon(pDbgAs, hDbgMod, NIL_RTDBGSEGIDX, ImageAddr, cb, pszName);
     632    RTDBGAS_LOCK_WRITE(pDbgAs);
     633    int rc = rtDbgAsModuleLinkCommon(pDbgAs, hDbgMod, NIL_RTDBGSEGIDX, ImageAddr, cb, pszName, fFlags);
     634    RTDBGAS_UNLOCK_WRITE(pDbgAs);
     635    return rc;
    533636}
    534637
     
    549652 *                          linked in.
    550653 * @param   SegAddr         The address to link the segment at.
    551  */
    552 RTDECL(int) RTDbgAsModuleLinkSeg(RTDBGAS hDbgAs, RTDBGMOD hDbgMod, RTDBGSEGIDX iSeg, RTUINTPTR SegAddr)
     654 * @param   fFlags          See RTDBGASLINK_FLAGS_*.
     655 */
     656RTDECL(int) RTDbgAsModuleLinkSeg(RTDBGAS hDbgAs, RTDBGMOD hDbgMod, RTDBGSEGIDX iSeg, RTUINTPTR SegAddr, uint32_t fFlags)
    553657{
    554658    /*
     
    569673        ||  SegAddr + cb - 1  < SegAddr)
    570674        return VERR_OUT_OF_RANGE;
     675    AssertReturn(!(fFlags & ~RTDBGASLINK_FLAGS_VALID_MASK), VERR_INVALID_PARAMETER);
    571676
    572677    /*
    573678     * Invoke worker common with RTDbgAsModuleLinkSeg.
    574679     */
    575     return rtDbgAsModuleLinkCommon(pDbgAs, hDbgMod, iSeg, SegAddr, cb, pszName);
     680    RTDBGAS_LOCK_WRITE(pDbgAs);
     681    int rc = rtDbgAsModuleLinkCommon(pDbgAs, hDbgMod, iSeg, SegAddr, cb, pszName, fFlags);
     682    RTDBGAS_UNLOCK_WRITE(pDbgAs);
     683    return rc;
    576684}
    577685
     
    582690 * @param   pDbgAs          Pointer to the address space instance data.
    583691 * @param   pMod            The module to unlink.
     692 *
     693 * @remarks The caller must have locked the address space for writing.
    584694 */
    585695static void rtDbgAsModuleUnlinkMod(PRTDBGASINT pDbgAs, PRTDBGASMOD pMod)
     
    636746 * @param   pDbgAs          Pointer to the address space instance data.
    637747 * @param   pMap            The map to unlink and free.
     748 *
     749 * @remarks The caller must have locked the address space for writing.
    638750 */
    639751static void rtDbgAsModuleUnlinkMap(PRTDBGASINT pDbgAs, PRTDBGASMAP pMap)
     
    669781
    670782/**
    671  * Unlinks all the mappings of a module from the address space.
    672  *
    673  * @returns IPRT status code.
    674  * @retval  VERR_NOT_FOUND if the module wasn't found.
    675  *
    676  * @param   hDbgAs          The address space handle.
    677  * @param   hDbgMod         The module handle of the module to be unlinked.
    678  */
    679 RTDECL(int) RTDbgAsModuleUnlink(RTDBGAS hDbgAs, RTDBGMOD hDbgMod)
    680 {
    681     /*
    682      * Validate input.
    683      */
    684     PRTDBGASINT pDbgAs = hDbgAs;
    685     RTDBGAS_VALID_RETURN_RC(pDbgAs, VERR_INVALID_HANDLE);
    686     if (hDbgMod == NIL_RTDBGMOD)
    687         return VINF_SUCCESS;
    688 
    689     PRTDBGASMOD pMod = (PRTDBGASMOD)RTAvlPVGet(&pDbgAs->ModTree, hDbgMod);
    690     if (!pMod)
    691         return VERR_NOT_FOUND;
    692 
    693     /*
    694      * Unmap all but
    695      */
    696     while (pMod->pMapHead)
    697         rtDbgAsModuleUnlinkMap(pDbgAs, pMod->pMapHead);
    698     rtDbgAsModuleUnlinkMod(pDbgAs, pMod);
    699     return VINF_SUCCESS;
    700 }
    701 
    702 
    703 /**
    704  * Unlinks the mapping at the specified address.
    705  *
    706  * @returns IPRT status code.
    707  * @retval  VERR_NOT_FOUND if no module or segment is mapped at that address.
    708  *
    709  * @param   hDbgAs          The address space handle.
    710  * @param   Addr            The address within the mapping to be unlinked.
    711  */
    712 RTDECL(int) RTDbgAsModuleUnlinkByAddr(RTDBGAS hDbgAs, RTUINTPTR Addr)
    713 {
    714     /*
    715      * Validate input.
    716      */
    717     PRTDBGASINT pDbgAs = hDbgAs;
    718     RTDBGAS_VALID_RETURN_RC(pDbgAs, VERR_INVALID_HANDLE);
    719     PRTDBGASMAP pMap = (PRTDBGASMAP)RTAvlrUIntPtrRangeGet(&pDbgAs->MapTree, Addr);
    720     if (pMap)
    721         return VERR_NOT_FOUND;
    722 
     783 * Worker for RTDbgAsModuleUnlinkByAddr and rtDbgAsModuleLinkCommon that
     784 * unlinks a single mapping and releases the module if it's the last one.
     785 *
     786 * @param   pDbgAs      The address space instance.
     787 * @param   pMap        The mapping to unlink.
     788 *
     789 * @remarks The caller must have locked the address space for writing.
     790 */
     791static void rtDbgAsModuleUnlinkByMap(PRTDBGASINT pDbgAs, PRTDBGASMAP pMap)
     792{
    723793    /*
    724794     * Unlink it from the address space.
     
    729799    if (!pMod->pMapHead)
    730800        rtDbgAsModuleUnlinkMod(pDbgAs, pMod);
     801}
     802
     803
     804/**
     805 * Unlinks all the mappings of a module from the address space.
     806 *
     807 * @returns IPRT status code.
     808 * @retval  VERR_NOT_FOUND if the module wasn't found.
     809 *
     810 * @param   hDbgAs          The address space handle.
     811 * @param   hDbgMod         The module handle of the module to be unlinked.
     812 */
     813RTDECL(int) RTDbgAsModuleUnlink(RTDBGAS hDbgAs, RTDBGMOD hDbgMod)
     814{
     815    /*
     816     * Validate input.
     817     */
     818    PRTDBGASINT pDbgAs = hDbgAs;
     819    RTDBGAS_VALID_RETURN_RC(pDbgAs, VERR_INVALID_HANDLE);
     820    if (hDbgMod == NIL_RTDBGMOD)
     821        return VINF_SUCCESS;
     822
     823    RTDBGAS_LOCK_WRITE(pDbgAs);
     824    PRTDBGASMOD pMod = (PRTDBGASMOD)RTAvlPVGet(&pDbgAs->ModTree, hDbgMod);
     825    if (!pMod)
     826    {
     827        RTDBGAS_UNLOCK_WRITE(pDbgAs);
     828        return VERR_NOT_FOUND;
     829    }
     830
     831    /*
     832     * Unmap all everything and release the module.
     833     */
     834    while (pMod->pMapHead)
     835        rtDbgAsModuleUnlinkMap(pDbgAs, pMod->pMapHead);
     836    rtDbgAsModuleUnlinkMod(pDbgAs, pMod);
     837
     838    RTDBGAS_UNLOCK_WRITE(pDbgAs);
     839    return VINF_SUCCESS;
     840}
     841
     842
     843/**
     844 * Unlinks the mapping at the specified address.
     845 *
     846 * @returns IPRT status code.
     847 * @retval  VERR_NOT_FOUND if no module or segment is mapped at that address.
     848 *
     849 * @param   hDbgAs          The address space handle.
     850 * @param   Addr            The address within the mapping to be unlinked.
     851 */
     852RTDECL(int) RTDbgAsModuleUnlinkByAddr(RTDBGAS hDbgAs, RTUINTPTR Addr)
     853{
     854    /*
     855     * Validate input.
     856     */
     857    PRTDBGASINT pDbgAs = hDbgAs;
     858    RTDBGAS_VALID_RETURN_RC(pDbgAs, VERR_INVALID_HANDLE);
     859
     860    RTDBGAS_LOCK_WRITE(pDbgAs);
     861    PRTDBGASMAP pMap = (PRTDBGASMAP)RTAvlrUIntPtrRangeGet(&pDbgAs->MapTree, Addr);
     862    if (pMap)
     863    {
     864        RTDBGAS_UNLOCK_WRITE(pDbgAs);
     865        return VERR_NOT_FOUND;
     866    }
     867
     868    /*
     869     * Hand it to
     870     */
     871    rtDbgAsModuleUnlinkByMap(pDbgAs, pMap);
     872
     873    RTDBGAS_UNLOCK_WRITE(pDbgAs);
    731874    return VINF_SUCCESS;
    732875}
     
    754897    PRTDBGASINT pDbgAs = hDbgAs;
    755898    RTDBGAS_VALID_RETURN_RC(pDbgAs, NIL_RTDBGMOD);
     899
     900    RTDBGAS_LOCK_READ(pDbgAs);
    756901    if (iModule >= pDbgAs->cModules)
     902    {
     903        RTDBGAS_UNLOCK_READ(pDbgAs);
    757904        return NIL_RTDBGMOD;
     905    }
    758906
    759907    /*
     
    762910    RTDBGMOD hMod = (RTDBGMOD)pDbgAs->paModules[iModule].Core.Key;
    763911    RTDbgModRetain(hMod);
     912
     913    RTDBGAS_UNLOCK_READ(pDbgAs);
    764914    return hMod;
    765915}
     
    789939    PRTDBGASINT pDbgAs = hDbgAs;
    790940    RTDBGAS_VALID_RETURN_RC(pDbgAs, VERR_INVALID_HANDLE);
     941
     942    RTDBGAS_LOCK_READ(pDbgAs);
    791943    PRTDBGASMAP pMap = (PRTDBGASMAP)RTAvlrUIntPtrRangeGet(&pDbgAs->MapTree, Addr);
    792944    if (pMap)
     945    {
     946        RTDBGAS_UNLOCK_READ(pDbgAs);
    793947        return VERR_NOT_FOUND;
     948    }
    794949
    795950    /*
     
    806961    if (piSeg)
    807962        *piSeg = pMap->iSeg;
     963
     964    RTDBGAS_UNLOCK_READ(pDbgAs);
    808965    return VINF_SUCCESS;
    809966}
     
    832989    RTDBGAS_VALID_RETURN_RC(pDbgAs, VERR_INVALID_HANDLE);
    833990    AssertPtrReturn(phMod, VERR_INVALID_POINTER);
     991
     992    RTDBGAS_LOCK_READ(pDbgAs);
    834993    PRTDBGASNAME pName = (PRTDBGASNAME)RTStrSpaceGet(&pDbgAs->NameSpace, pszName);
    835994    if (!pName)
     995    {
     996        RTDBGAS_UNLOCK_READ(pDbgAs);
    836997        return VERR_NOT_FOUND;
     998    }
    837999
    8381000    PRTDBGASMOD pMod = pName->pHead;
     
    8411003        pMod = pMod->pNextName;
    8421004        if (!pMod)
     1005        {
     1006            RTDBGAS_UNLOCK_READ(pDbgAs);
    8431007            return VERR_OUT_OF_RANGE;
     1008        }
    8441009    }
    8451010
     
    8501015    RTDbgModRetain(hMod);
    8511016    *phMod = hMod;
     1017
     1018    RTDBGAS_UNLOCK_READ(pDbgAs);
    8521019    return VINF_SUCCESS;
     1020}
     1021
     1022
     1023/**
     1024 * Internal worker that looks up and retains a module.
     1025 *
     1026 * @returns Module handle, NIL_RTDBGMOD if not found.
     1027 * @param   pDbgAs          The address space instance data.
     1028 * @param   Addr            Address within the module.
     1029 * @param   piSeg           where to return the segment index.
     1030 * @param   poffSeg         Where to return the segment offset.
     1031 */
     1032DECLINLINE(RTDBGMOD) rtDbgAsModuleByAddr(PRTDBGASINT pDbgAs, RTUINTPTR Addr, PRTDBGSEGIDX piSeg, PRTUINTPTR poffSeg)
     1033{
     1034    RTDBGMOD hMod = NIL_RTDBGMOD;
     1035
     1036    RTDBGAS_LOCK_READ(pDbgAs);
     1037    PRTDBGASMAP pMap = (PRTDBGASMAP)RTAvlrUIntPtrRangeGet(&pDbgAs->MapTree, Addr);
     1038    if (pMap)
     1039    {
     1040        hMod = (RTDBGMOD)pMap->pMod->Core.Key;
     1041        RTDbgModRetain(hMod);
     1042        *piSeg = pMap->iSeg;
     1043        *poffSeg = Addr - pMap->Core.Key;
     1044    }
     1045    RTDBGAS_UNLOCK_READ(pDbgAs);
     1046
     1047    return hMod;
    8531048}
    8541049
     
    8691064{
    8701065    /*
    871      * Validate input.
     1066    * Validate input and resolve the address.
    8721067     */
    8731068    PRTDBGASINT pDbgAs = hDbgAs;
    8741069    RTDBGAS_VALID_RETURN_RC(pDbgAs, VERR_INVALID_HANDLE);
    875     PRTDBGASMAP pMap = (PRTDBGASMAP)RTAvlrUIntPtrRangeGet(&pDbgAs->MapTree, Addr);
    876     if (pMap)
     1070
     1071    RTDBGSEGIDX iSeg;
     1072    RTUINTPTR offSeg;
     1073    RTDBGMOD hMod = rtDbgAsModuleByAddr(pDbgAs, Addr, &iSeg, &offSeg);
     1074    if (hMod == NIL_RTDBGMOD)
    8771075        return VERR_NOT_FOUND;
    8781076
     
    8801078     * Forward the call.
    8811079     */
    882     RTDBGMOD hMod = (RTDBGMOD)pMap->pMod->Core.Key;
    883     return RTDbgModSymbolAdd(hMod, pszSymbol, pMap->iSeg, Addr - pMap->Core.Key, cb);
     1080    int rc = RTDbgModSymbolAdd(hMod, pszSymbol, iSeg, offSeg, cb);
     1081    RTDbgModRelease(hMod);
     1082    return rc;
    8841083}
    8851084
     
    9011100{
    9021101    /*
    903      * Validate input.
     1102     * Validate input and resolve the address.
    9041103     */
    9051104    PRTDBGASINT pDbgAs = hDbgAs;
    9061105    RTDBGAS_VALID_RETURN_RC(pDbgAs, VERR_INVALID_HANDLE);
    907     PRTDBGASMAP pMap = (PRTDBGASMAP)RTAvlrUIntPtrRangeGet(&pDbgAs->MapTree, Addr);
    908     if (pMap)
     1106
     1107    RTDBGSEGIDX iSeg;
     1108    RTUINTPTR offSeg;
     1109    RTDBGMOD hMod = rtDbgAsModuleByAddr(pDbgAs, Addr, &iSeg, &offSeg);
     1110    if (hMod == NIL_RTDBGMOD)
    9091111        return VERR_NOT_FOUND;
    9101112
     
    9121114     * Forward the call.
    9131115     */
    914     RTDBGMOD hMod = (RTDBGMOD)pMap->pMod->Core.Key;
    915     return RTDbgModSymbolByAddr(hMod, pMap->iSeg, Addr - pMap->Core.Key, poffDisp, pSymbol);
     1116    int rc = RTDbgModSymbolByAddr(hMod, iSeg, offSeg, poffDisp, pSymbol);
     1117    RTDbgModRelease(hMod);
     1118    return rc;
    9161119}
    9171120
     
    9341137{
    9351138    /*
    936      * Validate input.
     1139     * Validate input and resolve the address.
    9371140     */
    9381141    PRTDBGASINT pDbgAs = hDbgAs;
    9391142    RTDBGAS_VALID_RETURN_RC(pDbgAs, VERR_INVALID_HANDLE);
    940     PRTDBGASMAP pMap = (PRTDBGASMAP)RTAvlrUIntPtrRangeGet(&pDbgAs->MapTree, Addr);
    941     if (pMap)
     1143
     1144    RTDBGSEGIDX iSeg;
     1145    RTUINTPTR offSeg;
     1146    RTDBGMOD hMod = rtDbgAsModuleByAddr(pDbgAs, Addr, &iSeg, &offSeg);
     1147    if (hMod == NIL_RTDBGMOD)
    9421148        return VERR_NOT_FOUND;
    9431149
     
    9451151     * Forward the call.
    9461152     */
    947     RTDBGMOD hMod = (RTDBGMOD)pMap->pMod->Core.Key;
    948     return RTDbgModSymbolByAddrA(hMod, pMap->iSeg, Addr - pMap->Core.Key, poffDisp, ppSymbol);
     1153    int rc = RTDbgModSymbolByAddrA(hMod, iSeg, offSeg, poffDisp, ppSymbol);
     1154    RTDbgModRelease(hMod);
     1155    return rc;
     1156}
     1157
     1158
     1159/**
     1160 * Creates a snapshot of the module table on the temporary heap.
     1161 *
     1162 * The caller must release all the module handles before freeing the table
     1163 * using RTMemTmpFree.
     1164 *
     1165 * @returns Module table snaphot.
     1166 * @param   pDbgAs          The address space instance data.
     1167 * @param   pcModules       Where to return the number of modules.
     1168 */
     1169DECLINLINE(PRTDBGMOD) rtDbgAsSnapshotModuleTable(PRTDBGASINT pDbgAs, uint32_t *pcModules)
     1170{
     1171    RTDBGAS_LOCK_READ(pDbgAs);
     1172
     1173    uint32_t iMod = *pcModules = pDbgAs->cModules;
     1174    PRTDBGMOD paModules = (PRTDBGMOD)RTMemTmpAlloc(sizeof(paModules[0]) * RT_MAX(iMod, 1));
     1175    if (paModules)
     1176    {
     1177        while (iMod-- > 0)
     1178        {
     1179            RTDBGMOD hMod = paModules[iMod];
     1180            paModules[iMod] = hMod;
     1181            RTDbgModRetain(hMod);
     1182        }
     1183    }
     1184
     1185    RTDBGAS_UNLOCK_READ(pDbgAs);
     1186    return paModules;
    9491187}
    9501188
     
    9731211     * Iterate the modules, looking for the symbol.
    9741212     */
    975     for (uint32_t i = 0; i < pDbgAs->cModules; i++)
    976     {
    977         RTDBGMOD hMod = (RTDBGMOD)pDbgAs->paModules[i].Core.Key;
    978         int rc = RTDbgModSymbolByName(hMod, pszSymbol, pSymbol);
     1213    uint32_t cModules;
     1214    PRTDBGMOD paModules = rtDbgAsSnapshotModuleTable(pDbgAs, &cModules);
     1215    if (!paModules)
     1216        return VERR_NO_TMP_MEMORY;
     1217
     1218    for (uint32_t i = 0; i < cModules; i++)
     1219    {
     1220        int rc = RTDbgModSymbolByName(paModules[i], pszSymbol, pSymbol);
     1221        RTDbgModRelease(paModules[i]);
    9791222        if (RT_SUCCESS(rc))
     1223        {
     1224            for (i = i + 1; i < cModules; i++)
     1225                RTDbgModRelease(paModules[i]);
     1226            RTMemTmpFree(paModules);
    9801227            return rc;
    981     }
     1228        }
     1229    }
     1230
     1231    RTMemTmpFree(paModules);
    9821232    return VERR_SYMBOL_NOT_FOUND;
    9831233}
     
    10091259     * Iterate the modules, looking for the symbol.
    10101260     */
    1011     for (uint32_t i = 0; i < pDbgAs->cModules; i++)
    1012     {
    1013         RTDBGMOD hMod = (RTDBGMOD)pDbgAs->paModules[i].Core.Key;
    1014         int rc = RTDbgModSymbolByNameA(hMod, pszSymbol, ppSymbol);
     1261    uint32_t cModules;
     1262    PRTDBGMOD paModules = rtDbgAsSnapshotModuleTable(pDbgAs, &cModules);
     1263    if (!paModules)
     1264        return VERR_NO_TMP_MEMORY;
     1265
     1266    for (uint32_t i = 0; i < cModules; i++)
     1267    {
     1268        int rc = RTDbgModSymbolByNameA(paModules[i], pszSymbol, ppSymbol);
     1269        RTDbgModRelease(paModules[i]);
    10151270        if (RT_SUCCESS(rc))
     1271        {
     1272            for (i = i + 1; i < cModules; i++)
     1273                RTDbgModRelease(paModules[i]);
     1274            RTMemTmpFree(paModules);
    10161275            return rc;
    1017     }
     1276        }
     1277    }
     1278
     1279    RTMemTmpFree(paModules);
    10181280    return VERR_SYMBOL_NOT_FOUND;
    10191281}
     
    10361298{
    10371299    /*
    1038      * Validate input.
     1300     * Validate input and resolve the address.
    10391301     */
    10401302    PRTDBGASINT pDbgAs = hDbgAs;
    10411303    RTDBGAS_VALID_RETURN_RC(pDbgAs, VERR_INVALID_HANDLE);
    1042     PRTDBGASMAP pMap = (PRTDBGASMAP)RTAvlrUIntPtrRangeGet(&pDbgAs->MapTree, Addr);
    1043     if (pMap)
     1304
     1305    RTDBGSEGIDX iSeg;
     1306    RTUINTPTR offSeg;
     1307    RTDBGMOD hMod = rtDbgAsModuleByAddr(pDbgAs, Addr, &iSeg, &offSeg);
     1308    if (hMod == NIL_RTDBGMOD)
    10441309        return VERR_NOT_FOUND;
    10451310
     
    10471312     * Forward the call.
    10481313     */
    1049     RTDBGMOD hMod = (RTDBGMOD)pMap->pMod->Core.Key;
    1050     return RTDbgModLineByAddr(hMod, pMap->iSeg, Addr - pMap->Core.Key, poffDisp, pLine);
     1314    int rc = RTDbgModLineByAddr(hMod, iSeg, offSeg, poffDisp, pLine);
     1315    RTDbgModRelease(hMod);
     1316    return rc;
    10511317}
    10521318
     
    10691335{
    10701336    /*
    1071      * Validate input.
     1337     * Validate input and resolve the address.
    10721338     */
    10731339    PRTDBGASINT pDbgAs = hDbgAs;
    10741340    RTDBGAS_VALID_RETURN_RC(pDbgAs, VERR_INVALID_HANDLE);
    1075     PRTDBGASMAP pMap = (PRTDBGASMAP)RTAvlrUIntPtrRangeGet(&pDbgAs->MapTree, Addr);
    1076     if (pMap)
     1341
     1342    RTDBGSEGIDX iSeg;
     1343    RTUINTPTR offSeg;
     1344    RTDBGMOD hMod = rtDbgAsModuleByAddr(pDbgAs, Addr, &iSeg, &offSeg);
     1345    if (hMod == NIL_RTDBGMOD)
    10771346        return VERR_NOT_FOUND;
    10781347
     
    10801349     * Forward the call.
    10811350     */
    1082     RTDBGMOD hMod = (RTDBGMOD)pMap->pMod->Core.Key;
    1083     return RTDbgModLineByAddrA(hMod, pMap->iSeg, Addr - pMap->Core.Key, poffDisp, ppLine);
    1084 }
    1085 
     1351    int rc = RTDbgModLineByAddrA(hMod, iSeg, offSeg, poffDisp, ppLine);
     1352    RTDbgModRelease(hMod);
     1353    return rc;
     1354}
     1355
  • trunk/src/VBox/Runtime/common/dbg/dbgmod.cpp

    r19566 r19757  
    4545
    4646
    47 RTDECL(int)         RTDbgModCreate(PRTDBGMOD phDbgMod, const char *pszName, const char *pszImgFile, const char *pszDbgFile)
     47RTDECL(int)         RTDbgModCreate(PRTDBGMOD phDbgMod, const char *pszName, RTUINTPTR cb, uint32_t fFlags)
     48{
     49    return VERR_NOT_IMPLEMENTED;
     50}
     51
     52RTDECL(int)         RTDbgModCreateFromImage(PRTDBGMOD phDbgMod, const char *pszFilename, const char *pszName, uint32_t fFlags)
     53{
     54    return VERR_NOT_IMPLEMENTED;
     55}
     56
     57RTDECL(int)         RTDbgModCreateFromMap(PRTDBGMOD phDbgMod, const char *pszFilename, const char *pszName, RTUINTPTR uSubtrahend, uint32_t fFlags)
    4858{
    4959    return VERR_NOT_IMPLEMENTED;
  • trunk/src/VBox/VMM/DBGF.cpp

    r19423 r19757  
    138138{
    139139    int rc = dbgfR3InfoInit(pVM);
     140    if (RT_SUCCESS(rc))
     141        rc = dbgfR3AsInit(pVM);
    140142    if (RT_SUCCESS(rc))
    141143        rc = dbgfR3SymInit(pVM);
     
    208210     */
    209211    dbgfR3OSTerm(pVM);
     212    dbgfR3AsTerm(pVM);
    210213    dbgfR3InfoTerm(pVM);
    211214    return VINF_SUCCESS;
     
    223226VMMR3DECL(void) DBGFR3Relocate(PVM pVM, RTGCINTPTR offDelta)
    224227{
     228    dbgfR3AsRelocate(pVM, offDelta);
    225229}
    226230
  • trunk/src/VBox/VMM/DBGFAddrSpace.cpp

    r12677 r19757  
    3838 */
    3939
    40 
     40/*******************************************************************************
     41*   Header Files                                                               *
     42*******************************************************************************/
     43#define LOG_GROUP LOG_GROUP_DBGF
     44#include <VBox/dbgf.h>
     45#include <VBox/mm.h>
     46#include "DBGFInternal.h"
     47#include <VBox/vm.h>
     48#include <VBox/err.h>
     49#include <VBox/log.h>
     50
     51#include <iprt/assert.h>
     52#include <iprt/ctype.h>
     53#include <iprt/env.h>
     54#include <iprt/path.h>
     55#include <iprt/param.h>
     56
     57
     58/*******************************************************************************
     59*   Structures and Typedefs                                                    *
     60*******************************************************************************/
     61/**
     62 * Address space database node.
     63 */
     64typedef struct DBGFASDBNODE
     65{
     66    /** The node core for DBGF::AsHandleTree, the key is the address space handle. */
     67    AVLPVNODECORE   HandleCore;
     68    /** The node core for DBGF::AsPidTree, the key is the process id. */
     69    AVLU32NODECORE  PidCore;
     70    /** The node core for DBGF::AsNameSpace, the string is the address space name. */
     71    RTSTRSPACECORE  NameCore;
     72
     73} DBGFASDBNODE;
     74/** Pointer to an address space database node. */
     75typedef DBGFASDBNODE *PDBGFASDBNODE;
     76
     77
     78/**
     79 * For dbgfR3AsLoadImageOpenData and dbgfR3AsLoadMapOpenData.
     80 */
     81typedef struct DBGFR3ASLOADOPENDATA
     82{
     83    const char *pszModName;
     84    RTGCUINTPTR uSubtrahend;
     85    uint32_t fFlags;
     86    RTDBGMOD hMod;
     87} DBGFR3ASLOADOPENDATA;
     88
     89/**
     90 * Callback for dbgfR3AsSearchPath and dbgfR3AsSearchEnvPath.
     91 *
     92 * @returns VBox status code. If success, then the search is completed.
     93 * @param   pszFilename     The file name under evaluation.
     94 * @param   pvUser          The user argument.
     95 */
     96typedef int FNDBGFR3ASSEARCHOPEN(const char *pszFilename, void *pvUser);
     97/** Pointer to a FNDBGFR3ASSEARCHOPEN. */
     98typedef FNDBGFR3ASSEARCHOPEN *PFNDBGFR3ASSEARCHOPEN;
     99
     100
     101/*******************************************************************************
     102*   Defined Constants And Macros                                               *
     103*******************************************************************************/
     104/** Locks the address space database for writing. */
     105#define DBGF_AS_DB_LOCK_WRITE(pVM) \
     106    do { \
     107        int rcSem = RTSemRWRequestWrite((pVM)->dbgf.s.hAsDbLock, RT_INDEFINITE_WAIT); \
     108        AssertRC(rcSem); \
     109    } while (0)
     110
     111/** Unlocks the address space database after writing. */
     112#define DBGF_AS_DB_UNLOCK_WRITE(pVM) \
     113    do { \
     114        int rcSem = RTSemRWReleaseWrite((pVM)->dbgf.s.hAsDbLock); \
     115        AssertRC(rcSem); \
     116    } while (0)
     117
     118/** Locks the address space database for reading. */
     119#define DBGF_AS_DB_LOCK_READ(pVM) \
     120    do { \
     121        int rcSem = RTSemRWRequestRead((pVM)->dbgf.s.hAsDbLock, RT_INDEFINITE_WAIT); \
     122        AssertRC(rcSem); \
     123    } while (0)
     124
     125/** Unlocks the address space database after reading. */
     126#define DBGF_AS_DB_UNLOCK_READ(pVM) \
     127    do { \
     128        int rcSem = RTSemRWReleaseRead((pVM)->dbgf.s.hAsDbLock); \
     129        AssertRC(rcSem); \
     130    } while (0)
     131
     132
     133
     134/**
     135 * Initializes the address space parts of DBGF.
     136 *
     137 * @returns VBox status code.
     138 * @param   pVM             The VM handle.
     139 */
     140int dbgfR3AsInit(PVM pVM)
     141{
     142    /*
     143     * Create the semaphore.
     144     */
     145    int rc = RTSemRWCreate(&pVM->dbgf.s.hAsDbLock);
     146    AssertRCReturn(rc, rc);
     147
     148    /*
     149     * Create the standard address spaces.
     150     */
     151    RTDBGAS hDbgAs;
     152    rc = RTDbgAsCreate(&hDbgAs, 0, RTRCPTR_MAX, "Global");
     153    AssertRCReturn(rc, rc);
     154    rc = DBGFR3AsAdd(pVM, hDbgAs, NIL_RTPROCESS);
     155    AssertRCReturn(rc, rc);
     156    RTDbgAsRetain(hDbgAs);
     157    pVM->dbgf.s.ahAsAliases[DBGF_AS_ALIAS_2_INDEX(DBGF_AS_GLOBAL)] = hDbgAs;
     158
     159    RTDbgAsRetain(hDbgAs);
     160    pVM->dbgf.s.ahAsAliases[DBGF_AS_ALIAS_2_INDEX(DBGF_AS_KERNEL)] = hDbgAs;
     161
     162    rc = RTDbgAsCreate(&hDbgAs, 0, RTRCPTR_MAX, "Physical");
     163    AssertRCReturn(rc, rc);
     164    rc = DBGFR3AsAdd(pVM, hDbgAs, NIL_RTPROCESS);
     165    AssertRCReturn(rc, rc);
     166    RTDbgAsRetain(hDbgAs);
     167    pVM->dbgf.s.ahAsAliases[DBGF_AS_ALIAS_2_INDEX(DBGF_AS_PHYS)] = hDbgAs;
     168
     169    rc = RTDbgAsCreate(&hDbgAs, 0, RTRCPTR_MAX, "HyperRawMode");
     170    AssertRCReturn(rc, rc);
     171    rc = DBGFR3AsAdd(pVM, hDbgAs, NIL_RTPROCESS);
     172    AssertRCReturn(rc, rc);
     173    RTDbgAsRetain(hDbgAs);
     174    pVM->dbgf.s.ahAsAliases[DBGF_AS_ALIAS_2_INDEX(DBGF_AS_RC)] = hDbgAs;
     175    RTDbgAsRetain(hDbgAs);
     176    pVM->dbgf.s.ahAsAliases[DBGF_AS_ALIAS_2_INDEX(DBGF_AS_RC_AND_GC_GLOBAL)] = hDbgAs;
     177
     178    rc = RTDbgAsCreate(&hDbgAs, 0, RTRCPTR_MAX, "HyperRing0");
     179    AssertRCReturn(rc, rc);
     180    rc = DBGFR3AsAdd(pVM, hDbgAs, NIL_RTPROCESS);
     181    AssertRCReturn(rc, rc);
     182    RTDbgAsRetain(hDbgAs);
     183    pVM->dbgf.s.ahAsAliases[DBGF_AS_ALIAS_2_INDEX(DBGF_AS_R0)] = hDbgAs;
     184
     185    return VINF_SUCCESS;
     186}
     187
     188
     189/**
     190 * Callback used by dbgfR3AsTerm / RTAvlPVDestroy to release an address space.
     191 *
     192 * @returns 0.
     193 * @param   pNode           The address space database node.
     194 * @param   pvIgnore        NULL.
     195 */
     196static DECLCALLBACK(int) dbgfR3AsTermDestroyNode(PAVLPVNODECORE pNode, void *pvIgnore)
     197{
     198    PDBGFASDBNODE pDbNode = (PDBGFASDBNODE)pNode;
     199    RTDbgAsRelease((RTDBGAS)pDbNode->HandleCore.Key);
     200    pDbNode->HandleCore.Key = NIL_RTDBGAS;
     201    /* Don't bother freeing it here as MM will free it soon and MM is much at
     202       it when doing it wholesale instead of piecemeal. */
     203    NOREF(pvIgnore);
     204    return 0;
     205}
     206
     207
     208/**
     209 * Terminates the address space parts of DBGF.
     210 *
     211 * @param   pVM             The VM handle.
     212 */
     213void dbgfR3AsTerm(PVM pVM)
     214{
     215    /*
     216     * Create the semaphore.
     217     */
     218    int rc = RTSemRWDestroy(pVM->dbgf.s.hAsDbLock);
     219    AssertRC(rc);
     220    pVM->dbgf.s.hAsDbLock = NIL_RTSEMRW;
     221
     222    /*
     223     * Release all the address spaces.
     224     */
     225    RTAvlPVDestroy(&pVM->dbgf.s.AsHandleTree, dbgfR3AsTermDestroyNode, NULL);
     226    for (size_t i = 0; i < RT_ELEMENTS(pVM->dbgf.s.ahAsAliases); i++)
     227    {
     228        RTDbgAsRelease(pVM->dbgf.s.ahAsAliases[i]);
     229        pVM->dbgf.s.ahAsAliases[i] = NIL_RTDBGAS;
     230    }
     231}
     232
     233
     234/**
     235 * Relocates the RC address space.
     236 *
     237 * @param   pVM             The VM handle.
     238 * @param   offDelta        The relocation delta.
     239 */
     240void dbgfR3AsRelocate(PVM pVM, RTGCUINTPTR offDelta)
     241{
     242    /** @todo */
     243}
     244
     245
     246/**
     247 * Adds the address space to the database.
     248 *
     249 * @returns VBox status code.
     250 * @param   pVM             The VM handle.
     251 * @param   hDbgAs          The address space handle. The reference of the
     252 *                          caller will NOT be consumed.
     253 * @param   ProcId          The process id or NIL_RTPROCESS.
     254 */
     255VMMR3DECL(int) DBGFR3AsAdd(PVM pVM, RTDBGAS hDbgAs, RTPROCESS ProcId)
     256{
     257    /*
     258     * Input validation.
     259     */
     260    VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE);
     261    const char *pszName = RTDbgAsName(hDbgAs);
     262    if (!pszName)
     263        return VERR_INVALID_HANDLE;
     264    uint32_t cRefs = RTDbgAsRetain(hDbgAs);
     265    if (cRefs == UINT32_MAX)
     266        return VERR_INVALID_HANDLE;
     267
     268    /*
     269     * Allocate a tracking node.
     270     */
     271    int rc = VERR_NO_MEMORY;
     272    PDBGFASDBNODE pDbNode = (PDBGFASDBNODE)MMR3HeapAlloc(pVM, MM_TAG_DBGF_AS, sizeof(*pDbNode));
     273    if (pDbNode)
     274    {
     275        pDbNode->HandleCore.Key = hDbgAs;
     276        pDbNode->PidCore.Key = NIL_RTPROCESS;
     277        pDbNode->NameCore.pszString = pszName;
     278        pDbNode->NameCore.cchString = strlen(pszName);
     279        DBGF_AS_DB_LOCK_WRITE(pVM);
     280        if (RTStrSpaceInsert(&pVM->dbgf.s.AsNameSpace, &pDbNode->NameCore))
     281        {
     282            if (RTAvlPVInsert(&pVM->dbgf.s.AsHandleTree, &pDbNode->HandleCore))
     283            {
     284                DBGF_AS_DB_UNLOCK_WRITE(pVM);
     285                return VINF_SUCCESS;
     286            }
     287
     288            /* bail out */
     289            RTStrSpaceRemove(&pVM->dbgf.s.AsNameSpace, pszName);
     290        }
     291        DBGF_AS_DB_UNLOCK_WRITE(pVM);
     292        MMR3HeapFree(pDbNode);
     293    }
     294    RTDbgAsRelease(hDbgAs);
     295    return rc;
     296}
     297
     298
     299/**
     300 * Delete an address space from the database.
     301 *
     302 * The address space must not be engaged as any of the standard aliases.
     303 *
     304 * @returns VBox status code.
     305 * @retval  VERR_SHARING_VIOLATION if in use as an alias.
     306 * @retval  VERR_NOT_FOUND if not found in the address space database.
     307 *
     308 * @param   pVM             The VM handle.
     309 * @param   hDbgAs          The address space handle. Aliases are not allowed.
     310 */
     311VMMR3DECL(int) DBGFR3AsDelete(PVM pVM, RTDBGAS hDbgAs)
     312{
     313    /*
     314     * Input validation. Retain the address space so it can be released outside
     315     * the lock as well as validated.
     316     */
     317    VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE);
     318    if (hDbgAs == NIL_RTDBGAS)
     319        return VINF_SUCCESS;
     320    uint32_t cRefs = RTDbgAsRetain(hDbgAs);
     321    if (cRefs == UINT32_MAX)
     322        return VERR_INVALID_HANDLE;
     323    RTDbgAsRelease(hDbgAs);
     324
     325    DBGF_AS_DB_LOCK_WRITE(pVM);
     326
     327    /*
     328     * You cannot delete any of the aliases.
     329     */
     330    for (size_t i = 0; i < RT_ELEMENTS(pVM->dbgf.s.ahAsAliases); i++)
     331        if (pVM->dbgf.s.ahAsAliases[i] == hDbgAs)
     332        {
     333            DBGF_AS_DB_UNLOCK_WRITE(pVM);
     334            return VERR_SHARING_VIOLATION;
     335        }
     336
     337    /*
     338     * Ok, try remove it from the database.
     339     */
     340    PDBGFASDBNODE pDbNode = (PDBGFASDBNODE)RTAvlPVRemove(&pVM->dbgf.s.AsHandleTree, hDbgAs);
     341    if (!pDbNode)
     342    {
     343        DBGF_AS_DB_UNLOCK_WRITE(pVM);
     344        return VERR_NOT_FOUND;
     345    }
     346    RTStrSpaceRemove(&pVM->dbgf.s.AsNameSpace, pDbNode->NameCore.pszString);
     347    if (pDbNode->PidCore.Key != NIL_RTPROCESS)
     348        RTAvlU32Remove(&pVM->dbgf.s.AsPidTree, pDbNode->PidCore.Key);
     349
     350    DBGF_AS_DB_UNLOCK_WRITE(pVM);
     351
     352    /*
     353     * Free the resources.
     354     */
     355    RTDbgAsRelease(hDbgAs);
     356    MMR3HeapFree(pDbNode);
     357
     358    return VINF_SUCCESS;
     359}
     360
     361
     362/**
     363 * Changes an alias to point to a new address space.
     364 *
     365 * Not all the aliases can be changed, currently it's only DBGF_AS_GLOBAL
     366 * and DBGF_AS_KERNEL.
     367 *
     368 * @returns VBox status code.
     369 * @param   pVM             The VM handle.
     370 * @param   hAlias          The alias to change.
     371 * @param   hAliasFor       The address space hAlias should be an alias for.
     372 *                          This can be an alias. The caller's reference to
     373 *                          this address space will NOT be consumed.
     374 */
     375VMMR3DECL(int) DBGFR3AsSetAlias(PVM pVM, RTDBGAS hAlias, RTDBGAS hAliasFor)
     376{
     377    /*
     378     * Input validation.
     379     */
     380    VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE);
     381    AssertMsgReturn(!DBGF_AS_IS_ALIAS(hAlias), ("%p\n", hAlias), VERR_INVALID_PARAMETER);
     382    AssertMsgReturn(!DBGF_AS_IS_FIXED_ALIAS(hAlias), ("%p\n", hAlias), VERR_INVALID_PARAMETER);
     383    RTDBGAS hRealAliasFor = DBGFR3AsResolveAndRetain(pVM, hAlias);
     384    if (hRealAliasFor == NIL_RTDBGAS)
     385        return VERR_INVALID_HANDLE;
     386
     387    /*
     388     * Make sure the handle has is already in the database.
     389     */
     390    int rc = VERR_NOT_FOUND;
     391    DBGF_AS_DB_LOCK_WRITE(pVM);
     392    if (RTAvlPVGet(&pVM->dbgf.s.AsHandleTree, hRealAliasFor))
     393    {
     394        /*
     395         * Update the alias table and release the current address space.
     396         */
     397        RTDBGAS hAsOld;
     398        ASMAtomicXchgHandle(&pVM->dbgf.s.ahAsAliases[DBGF_AS_ALIAS_2_INDEX(hAlias)], hRealAliasFor, &hAsOld);
     399        uint32_t cRefs = RTDbgAsRelease(hAsOld);
     400        Assert(cRefs > 0);
     401        Assert(cRefs != UINT32_MAX);
     402        rc = VINF_SUCCESS;
     403    }
     404    DBGF_AS_DB_UNLOCK_WRITE(pVM);
     405
     406    return rc;
     407}
     408
     409
     410/**
     411 * Resolves the address space handle into a real handle if it's an alias.
     412 *
     413 * @returns Real address space handle. NIL_RTDBGAS if invalid handle.
     414 *
     415 * @param   pVM             The VM handle.
     416 * @param   hAlias          The possibly address space alias.
     417 *
     418 * @remarks Doesn't take any locks.
     419 */
     420VMMR3DECL(RTDBGAS) DBGFR3AsResolve(PVM pVM, RTDBGAS hAlias)
     421{
     422    VM_ASSERT_VALID_EXT_RETURN(pVM, NULL);
     423    AssertCompile(NIL_RTDBGAS == (RTDBGAS)0);
     424
     425    uintptr_t   iAlias = DBGF_AS_ALIAS_2_INDEX(hAlias);
     426    if (iAlias < DBGF_AS_COUNT)
     427        ASMAtomicReadHandle(&pVM->dbgf.s.ahAsAliases[iAlias], &hAlias);
     428    return hAlias;
     429}
     430
     431
     432/**
     433 * Resolves the address space handle into a real handle if it's an alias,
     434 * and retains whatever it is.
     435 *
     436 * @returns Real address space handle. NIL_RTDBGAS if invalid handle.
     437 *
     438 * @param   pVM             The VM handle.
     439 * @param   hAlias          The possibly address space alias.
     440 */
     441VMMR3DECL(RTDBGAS) DBGFR3AsResolveAndRetain(PVM pVM, RTDBGAS hAlias)
     442{
     443    VM_ASSERT_VALID_EXT_RETURN(pVM, NULL);
     444    AssertCompile(NIL_RTDBGAS == (RTDBGAS)0);
     445
     446    uint32_t    cRefs;
     447    uintptr_t   iAlias = DBGF_AS_ALIAS_2_INDEX(hAlias);
     448    if (iAlias < DBGF_AS_COUNT)
     449    {
     450        if (DBGF_AS_IS_FIXED_ALIAS(hAlias))
     451        {
     452            /* Won't ever change, no need to grab the lock. */
     453            hAlias = pVM->dbgf.s.ahAsAliases[iAlias];
     454            cRefs = RTDbgAsRetain(hAlias);
     455        }
     456        else
     457        {
     458            /* May change, grab the lock so we can read it safely. */
     459            DBGF_AS_DB_LOCK_READ(pVM);
     460            hAlias = pVM->dbgf.s.ahAsAliases[iAlias];
     461            cRefs = RTDbgAsRetain(hAlias);
     462            DBGF_AS_DB_UNLOCK_READ(pVM);
     463        }
     464    }
     465    else
     466        /* Not an alias, just retain it. */
     467        cRefs = RTDbgAsRetain(hAlias);
     468
     469    return cRefs != UINT32_MAX ? hAlias : NIL_RTDBGAS;
     470}
     471
     472
     473/**
     474 * Query an address space by name.
     475 *
     476 * @returns Retained address space handle if found, NIL_RTDBGAS if not.
     477 *
     478 * @param   pVM         The VM handle.
     479 * @param   pszName     The name.
     480 */
     481VMMR3DECL(RTDBGAS) DBGFR3AsQueryByName(PVM pVM, const char *pszName)
     482{
     483    /*
     484     * Validate the input.
     485     */
     486    VM_ASSERT_VALID_EXT_RETURN(pVM, NIL_RTDBGAS);
     487    AssertPtrReturn(pszName, NIL_RTDBGAS);
     488    AssertReturn(*pszName, NIL_RTDBGAS);
     489
     490    /*
     491     * Look it up in the string space and retain the result.
     492     */
     493    RTDBGAS hDbgAs = NIL_RTDBGAS;
     494    DBGF_AS_DB_LOCK_READ(pVM);
     495
     496    PRTSTRSPACECORE pNode = RTStrSpaceGet(&pVM->dbgf.s.AsNameSpace, pszName);
     497    if (pNode)
     498    {
     499        PDBGFASDBNODE pDbNode = RT_FROM_MEMBER(pNode, DBGFASDBNODE, NameCore);
     500        hDbgAs = (RTDBGAS)pDbNode->HandleCore.Key;
     501        uint32_t cRefs = RTDbgAsRetain(hDbgAs);
     502        if (RT_UNLIKELY(cRefs == UINT32_MAX))
     503            hDbgAs = NIL_RTDBGAS;
     504    }
     505    DBGF_AS_DB_UNLOCK_READ(pVM);
     506
     507    return hDbgAs;
     508}
     509
     510
     511/**
     512 * Query an address space by process ID.
     513 *
     514 * @returns Retained address space handle if found, NIL_RTDBGAS if not.
     515 *
     516 * @param   pVM         The VM handle.
     517 * @param   ProcId      The process ID.
     518 */
     519VMMR3DECL(RTDBGAS) DBGFR3AsQueryByPid(PVM pVM, RTPROCESS ProcId)
     520{
     521    /*
     522     * Validate the input.
     523     */
     524    VM_ASSERT_VALID_EXT_RETURN(pVM, NIL_RTDBGAS);
     525    AssertReturn(ProcId != NIL_RTPROCESS, NIL_RTDBGAS);
     526
     527    /*
     528     * Look it up in the PID tree and retain the result.
     529     */
     530    RTDBGAS hDbgAs = NIL_RTDBGAS;
     531    DBGF_AS_DB_LOCK_READ(pVM);
     532
     533    PAVLU32NODECORE pNode = RTAvlU32Get(&pVM->dbgf.s.AsPidTree, ProcId);
     534    if (pNode)
     535    {
     536        PDBGFASDBNODE pDbNode = RT_FROM_MEMBER(pNode, DBGFASDBNODE, PidCore);
     537        hDbgAs = (RTDBGAS)pDbNode->HandleCore.Key;
     538        uint32_t cRefs = RTDbgAsRetain(hDbgAs);
     539        if (RT_UNLIKELY(cRefs == UINT32_MAX))
     540            hDbgAs = NIL_RTDBGAS;
     541    }
     542    DBGF_AS_DB_UNLOCK_READ(pVM);
     543
     544    return hDbgAs;
     545}
     546
     547
     548/**
     549 * Searches for the file in the path.
     550 *
     551 * The file is first tested without any path modification, then we walk the path
     552 * looking in each directory.
     553 *
     554 * @returns VBox status code.
     555 * @param   pszFilename     The file to search for.
     556 * @param   pszPath         The search path.
     557 * @param   pfnOpen         The open callback function.
     558 * @param   pvUser          User argument for the callback.
     559 */
     560static int dbgfR3AsSearchPath(const char *pszFilename, const char *pszPath, PFNDBGFR3ASSEARCHOPEN pfnOpen, void *pvUser)
     561{
     562    char szFound[RTPATH_MAX];
     563
     564    /* Check the filename length. */
     565    size_t const    cchFilename = strlen(pszFilename);
     566    if (cchFilename >= sizeof(szFound))
     567        return VERR_FILENAME_TOO_LONG;
     568    const char     *pszName = RTPathFilename(pszFilename);
     569    if (!pszName)
     570        return VERR_IS_A_DIRECTORY;
     571    size_t const    cchName = strlen(pszName);
     572
     573    /*
     574     * Try default location first.
     575     */
     576    memcpy(szFound, pszFilename, cchFilename + 1);
     577    int rc = pfnOpen(szFound, pvUser);
     578    if (RT_SUCCESS(rc))
     579        return rc;
     580
     581    /*
     582     * Walk the search path.
     583     */
     584    const char *psz = pszPath;
     585    while (*psz)
     586    {
     587        /* Skip leading blanks - no directories with leading spaces, thank you. */
     588        while (RT_C_IS_BLANK(*psz))
     589            psz++;
     590
     591        /* Fine the end of this element. */
     592        const char *pszNext;
     593        const char *pszEnd = strchr(psz, ';');
     594        if (!pszEnd)
     595            pszEnd = pszNext = strchr(psz, '\0');
     596        else
     597            pszNext = pszEnd + 1;
     598        if (pszEnd != psz)
     599        {
     600            size_t const cch = pszEnd - psz;
     601            if (cch + 1 + cchName < sizeof(szFound))
     602            {
     603                /** @todo RTPathCompose, RTPathComposeN(). This code isn't right
     604                 * for 'E:' on DOS systems. It may also create unwanted double slashes. */
     605                memcpy(szFound, psz, cch);
     606                szFound[cch] = '/';
     607                memcpy(szFound + cch + 1, pszName, cchName + 1);
     608                int rc2 = pfnOpen(szFound, pvUser);
     609                if (RT_SUCCESS(rc2))
     610                    return rc2;
     611                if (    rc2 != rc
     612                    &&  (   rc == VERR_FILE_NOT_FOUND
     613                         || rc == VERR_OPEN_FAILED))
     614                    rc = rc2;
     615            }
     616        }
     617
     618        /* advance */
     619        psz = pszNext;
     620    }
     621
     622    /*
     623     * Walk the path once again, this time do a depth search.
     624     */
     625    /** @todo do a depth search using the specified path. */
     626
     627    /* failed */
     628    return rc;
     629}
     630
     631
     632/**
     633 * Same as dbgfR3AsSearchEnv, except that the path is taken from the environment.
     634 *
     635 * It the environment variable doesn't exist, the current directory is searched instead.
     636 *
     637 * @returns VBox status code.
     638 * @param   pszFilename     The filename.
     639 * @param   pszEnvVar       The environment variable name.
     640 * @param   pfnOpen         The open callback function.
     641 * @param   pvUser          User argument for the callback.
     642 */
     643static int dbgfR3AsSearchEnvPath(const char *pszFilename, const char *pszEnvVar, PFNDBGFR3ASSEARCHOPEN pfnOpen, void *pvUser)
     644{
     645    const char *pszPath = RTEnvGet(pszEnvVar);
     646    if (!pszPath)
     647        pszPath = ".";
     648    return dbgfR3AsSearchPath(pszFilename, pszPath, pfnOpen, pvUser);
     649}
     650
     651
     652/**
     653 * Callback function used by DBGFR3AsLoadImage.
     654 *
     655 * @returns VBox status code.
     656 * @param   pszFilename     The filename under evaluation.
     657 * @param   pvUser          Use arguments (DBGFR3ASLOADOPENDATA).
     658 */
     659static DECLCALLBACK(int) dbgfR3AsLoadImageOpen(const char *pszFilename, void *pvUser)
     660{
     661    DBGFR3ASLOADOPENDATA *pData = (DBGFR3ASLOADOPENDATA *)pvUser;
     662    return RTDbgModCreateFromImage(&pData->hMod, pszFilename, pData->pszModName, pData->fFlags);
     663}
     664
     665
     666/**
     667 * Load symbols from an executable module into the specified address space.
     668 *
     669 * If an module exist at the specified address it will be replaced by this
     670 * call, otherwise a new module is created.
     671 *
     672 * @returns VBox status code.
     673 *
     674 * @param   pVM             The VM handle.
     675 * @param   hDbgAs          The address space.
     676 * @param   pszFilename     The filename of the executable module.
     677 * @param   pszModName      The module name. If NULL, then then the file name
     678 *                          base is used (no extension or nothing).
     679 * @param   pModAddress     The load address of the module.
     680 * @param   iModSeg         The segment to load, pass NIL_RTDBGSEGIDX to load
     681 *                          the whole image.
     682 * @param   fFlags          Flags reserved for future extensions, must be 0.
     683 */
     684VMMR3DECL(int) DBGFR3AsLoadImage(PVM pVM, RTDBGAS hDbgAs, const char *pszFilename, const char *pszModName, PCDBGFADDRESS pModAddress, RTDBGSEGIDX iModSeg, uint32_t fFlags)
     685{
     686    /*
     687     * Validate input
     688     */
     689    AssertPtrReturn(pszFilename, VERR_INVALID_POINTER);
     690    AssertReturn(*pszFilename, VERR_INVALID_PARAMETER);
     691    AssertReturn(DBGFR3AddrIsValid(pVM, pModAddress), VERR_INVALID_PARAMETER);
     692    AssertReturn(fFlags == 0, VERR_INVALID_PARAMETER);
     693    RTDBGAS hRealAS = DBGFR3AsResolveAndRetain(pVM, hDbgAs);
     694    if (hRealAS == NIL_RTDBGAS)
     695        return VERR_INVALID_HANDLE;
     696
     697    /*
     698     * Do the work.
     699     */
     700    DBGFR3ASLOADOPENDATA Data;
     701    Data.pszModName = pszModName;
     702    Data.uSubtrahend = 0;
     703    Data.fFlags = 0;
     704    Data.hMod = NIL_RTDBGMOD;
     705    int rc = dbgfR3AsSearchEnvPath(pszFilename, "VBOXDBG_IMAGE_PATH", dbgfR3AsLoadImageOpen, &Data);
     706    if (RT_FAILURE(rc))
     707        rc = dbgfR3AsSearchEnvPath(pszFilename, "VBOXDBG_PATH", dbgfR3AsLoadImageOpen, &Data);
     708    if (RT_SUCCESS(rc))
     709    {
     710        rc = DBGFR3AsLinkModule(pVM, hRealAS, Data.hMod, pModAddress, iModSeg, 0);
     711        if (RT_FAILURE(rc))
     712            RTDbgModRelease(Data.hMod);
     713    }
     714
     715    RTDbgAsRelease(hRealAS);
     716    return rc;
     717}
     718
     719
     720/**
     721 * Callback function used by DBGFR3AsLoadMap.
     722 *
     723 * @returns VBox status code.
     724 * @param   pszFilename     The filename under evaluation.
     725 * @param   pvUser          Use arguments (DBGFR3ASLOADOPENDATA).
     726 */
     727static DECLCALLBACK(int) dbgfR3AsLoadMapOpen(const char *pszFilename, void *pvUser)
     728{
     729    DBGFR3ASLOADOPENDATA *pData = (DBGFR3ASLOADOPENDATA *)pvUser;
     730    return RTDbgModCreateFromMap(&pData->hMod, pszFilename, pData->pszModName, pData->uSubtrahend, pData->fFlags);
     731}
     732
     733
     734/**
     735 * Load symbols from a map file into a module at the specified address space.
     736 *
     737 * If an module exist at the specified address it will be replaced by this
     738 * call, otherwise a new module is created.
     739 *
     740 * @returns VBox status code.
     741 *
     742 * @param   pVM             The VM handle.
     743 * @param   hDbgAs          The address space.
     744 * @param   pszFilename     The map file.
     745 * @param   pszModName      The module name. If NULL, then then the file name
     746 *                          base is used (no extension or nothing).
     747 * @param   pModAddress     The load address of the module.
     748 * @param   iModSeg         The segment to load, pass NIL_RTDBGSEGIDX to load
     749 *                          the whole image.
     750 * @param   uSubtrahend     Value to to subtract from the symbols in the map
     751 *                          file. This is useful for the linux System.map and
     752 *                          /proc/kallsyms.
     753 * @param   fFlags          Flags reserved for future extensions, must be 0.
     754 */
     755VMMR3DECL(int) DBGFR3AsLoadMap(PVM pVM, RTDBGAS hDbgAs, const char *pszFilename, const char *pszModName,
     756                               PCDBGFADDRESS pModAddress, RTDBGSEGIDX iModSeg, RTGCUINTPTR uSubtrahend, uint32_t fFlags)
     757{
     758    /*
     759     * Validate input
     760     */
     761    AssertPtrReturn(pszFilename, VERR_INVALID_POINTER);
     762    AssertReturn(*pszFilename, VERR_INVALID_PARAMETER);
     763    AssertReturn(DBGFR3AddrIsValid(pVM, pModAddress), VERR_INVALID_PARAMETER);
     764    AssertReturn(fFlags == 0, VERR_INVALID_PARAMETER);
     765    RTDBGAS hRealAS = DBGFR3AsResolveAndRetain(pVM, hDbgAs);
     766    if (hRealAS == NIL_RTDBGAS)
     767        return VERR_INVALID_HANDLE;
     768
     769    /*
     770     * Do the work.
     771     */
     772    DBGFR3ASLOADOPENDATA Data;
     773    Data.pszModName = pszModName;
     774    Data.uSubtrahend = uSubtrahend;
     775    Data.fFlags = 0;
     776    Data.hMod = NIL_RTDBGMOD;
     777    int rc = dbgfR3AsSearchEnvPath(pszFilename, "VBOXDBG_MAP_PATH", dbgfR3AsLoadImageOpen, &Data);
     778    if (RT_FAILURE(rc))
     779        rc = dbgfR3AsSearchEnvPath(pszFilename, "VBOXDBG_PATH", dbgfR3AsLoadImageOpen, &Data);
     780    if (RT_SUCCESS(rc))
     781    {
     782        rc = DBGFR3AsLinkModule(pVM, hRealAS, Data.hMod, pModAddress, iModSeg, 0);
     783        if (RT_FAILURE(rc))
     784            RTDbgModRelease(Data.hMod);
     785    }
     786
     787    RTDbgAsRelease(hRealAS);
     788    return rc;
     789}
     790
     791
     792/**
     793 * Wrapper around RTDbgAsModuleLink, RTDbgAsModuleLinkSeg and DBGFR3AsResolve.
     794 *
     795 * @returns VBox status code.
     796 * @param   pVM             The VM handle.
     797 * @param   hDbgAs          The address space handle.
     798 * @param   hMod            The module handle.
     799 * @param   pModAddress     The link address.
     800 * @param   iModSeg         The segment to link, NIL_RTDBGSEGIDX for the entire image.
     801 * @param   fFlags          Flags to pass to the link functions, see RTDBGASLINK_FLAGS_*.
     802 */
     803VMMR3DECL(int) DBGFR3AsLinkModule(PVM pVM, RTDBGAS hDbgAs, RTDBGMOD hMod, PCDBGFADDRESS pModAddress, RTDBGSEGIDX iModSeg, uint32_t fFlags)
     804{
     805    /*
     806     * Input validation.
     807     */
     808    VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE);
     809    AssertReturn(DBGFR3AddrIsValid(pVM, pModAddress), VERR_INVALID_PARAMETER);
     810    RTDBGAS hRealAS = DBGFR3AsResolveAndRetain(pVM, hDbgAs);
     811    if (hRealAS == NIL_RTDBGAS)
     812        return VERR_INVALID_HANDLE;
     813
     814    /*
     815     * Do the job.
     816     */
     817    int rc;
     818    if (iModSeg == NIL_RTDBGSEGIDX)
     819        rc = RTDbgAsModuleLink(hRealAS, hMod, pModAddress->FlatPtr, fFlags);
     820    else
     821        rc = RTDbgAsModuleLinkSeg(hRealAS, hMod, iModSeg, pModAddress->FlatPtr, fFlags);
     822
     823    RTDbgAsRelease(hRealAS);
     824    return rc;
     825}
     826
  • trunk/src/VBox/VMM/DBGFInternal.h

    r19286 r19757  
    262262    DBGFBP                  aBreakpoints[32];
    263263
     264    /** The address space database lock. */
     265    RTSEMRW                 hAsDbLock;
     266    /** The address space handle database.      (Protected by hAsDbLock.) */
     267    R3PTRTYPE(AVLPVTREE)    AsHandleTree;
     268    /** The address space process id database.  (Protected by hAsDbLock.) */
     269    R3PTRTYPE(AVLU32TREE)   AsPidTree;
     270    /** The address space name database.        (Protected by hAsDbLock.) */
     271    R3PTRTYPE(RTSTRSPACE)   AsNameSpace;
     272    /** Special address space aliases.          (Protected by hAsDbLock.) */
     273    RTDBGAS volatile        ahAsAliases[DBGF_AS_COUNT];
     274
    264275    /** The current Guest OS digger. */
    265276    R3PTRTYPE(PDBGFOS)      pCurOS;
     
    300311
    301312
    302 extern int  dbgfR3InfoInit(PVM pVM);
    303 extern int  dbgfR3InfoTerm(PVM pVM);
    304 extern void dbgfR3OSTerm(PVM pVM);
    305 extern int  dbgfR3SymInit(PVM pVM);
    306 extern int  dbgfR3SymTerm(PVM pVM);
    307 extern int  dbgfR3BpInit(PVM pVM);
     313int  dbgfR3AsInit(PVM pVM);
     314void dbgfR3AsTerm(PVM pVM);
     315void dbgfR3AsRelocate(PVM pVM, RTGCUINTPTR offDelta);
     316int  dbgfR3InfoInit(PVM pVM);
     317int  dbgfR3InfoTerm(PVM pVM);
     318void dbgfR3OSTerm(PVM pVM);
     319int  dbgfR3SymInit(PVM pVM);
     320int  dbgfR3SymTerm(PVM pVM);
     321int  dbgfR3BpInit(PVM pVM);
    308322
    309323
  • trunk/src/VBox/VMM/DBGFModule.cpp

    r12677 r19757  
    3838 */
    3939
    40 
     40#if 0
     41#include <VBox/dbgf.h>
     42
     43
     44/** Special segment number that indicates that the offset is a relative
     45 * virtual address (RVA). I.e. an offset from the start of the module. */
     46#define DBGF_SEG_RVA UINT32_C(0xfffffff0)
     47
     48/** @defgroup grp_dbgf_dbginfo Debug Info Types
     49 * @{ */
     50/** Other format. */
     51#define DBGF_DBGINFO_OTHER      RT_BIT_32(0)
     52/** Stabs. */
     53#define DBGF_DBGINFO_STABS      RT_BIT_32(1)
     54/** Debug With Arbitrary Record Format (DWARF). */
     55#define DBGF_DBGINFO_DWARF      RT_BIT_32(2)
     56/** Microsoft Codeview debug info. */
     57#define DBGF_DBGINFO_CODEVIEW   RT_BIT_32(3)
     58/** Watcom debug info. */
     59#define DBGF_DBGINFO_WATCOM     RT_BIT_32(4)
     60/** IBM High Level Language debug info. */
     61#define DBGF_DBGINFO_HLL        RT_BIT_32(5)
     62/** Old OS/2 and Windows symbol file. */
     63#define DBGF_DBGINFO_SYM        RT_BIT_32(6)
     64/** Map file. */
     65#define DBGF_DBGINFO_MAP        RT_BIT_32(7)
     66/** @} */
     67
     68/** @defgroup grp_dbgf_exeimg Executable Image Types
     69 * @{ */
     70/** Some other format. */
     71#define DBGF_EXEIMG_OTHER       RT_BIT_32(0)
     72/** Portable Executable. */
     73#define DBGF_EXEIMG_PE          RT_BIT_32(1)
     74/** Linear eXecutable. */
     75#define DBGF_EXEIMG_LX          RT_BIT_32(2)
     76/** Linear Executable. */
     77#define DBGF_EXEIMG_LE          RT_BIT_32(3)
     78/** New Executable. */
     79#define DBGF_EXEIMG_NE          RT_BIT_32(4)
     80/** DOS Executable (Mark Zbikowski). */
     81#define DBGF_EXEIMG_MZ          RT_BIT_32(5)
     82/** COM Executable. */
     83#define DBGF_EXEIMG_COM         RT_BIT_32(6)
     84/** a.out Executable. */
     85#define DBGF_EXEIMG_AOUT        RT_BIT_32(7)
     86/** Executable and Linkable Format. */
     87#define DBGF_EXEIMG_ELF         RT_BIT_32(8)
     88/** Mach-O Executable (including FAT ones). */
     89#define DBGF_EXEIMG_MACHO       RT_BIT_32(9)
     90/** @} */
     91
     92/** Pointer to a module. */
     93typedef struct DBGFMOD *PDBGFMOD;
     94
     95
     96/**
     97 * Virtual method table for executable image interpreters.
     98 */
     99typedef struct DBGFMODVTIMG
     100{
     101    /** Magic number (DBGFMODVTIMG_MAGIC). */
     102    uint32_t    u32Magic;
     103    /** Mask of supported debug info types, see grp_dbgf_exeimg.
     104     * Used to speed up the search for a suitable interpreter. */
     105    uint32_t    fSupports;
     106    /** The name of the interpreter. */
     107    const char *pszName;
     108
     109    /**
     110     * Try open the image.
     111     *
     112     * This combines probing and opening.
     113     *
     114     * @returns VBox status code. No informational returns defined.
     115     *
     116     * @param   pMod        Pointer to the module that is being opened.
     117     *
     118     *                      The DBGFMOD::pszDbgFile member will point to
     119     *                      the filename of any debug info we're aware of
     120     *                      on input. Also, or alternatively, it is expected
     121     *                      that the interpreter will look for debug info in
     122     *                      the executable image file when present and that it
     123     *                      may ask the image interpreter for this when it's
     124     *                      around.
     125     *
     126     *                      Upon successful return the method is expected to
     127     *                      initialize pDbgOps and pvDbgPriv.
     128     */
     129    DECLCALLBACKMEMBER(int, pfnTryOpen)(PDBGFMOD pMod);
     130
     131    /**
     132     * Close the interpreter, freeing all associated resources.
     133     *
     134     * The caller sets the pDbgOps and pvDbgPriv DBGFMOD members
     135     * to NULL upon return.
     136     *
     137     * @param   pMod        Pointer to the module structure.
     138     */
     139    DECLCALLBACKMEMBER(int, pfnClose)(PDBGFMOD pMod);
     140
     141} DBGFMODVTIMG
     142
     143/**
     144 * Virtual method table for debug info interpreters.
     145 */
     146typedef struct DBGFMODVTDBG
     147{
     148    /** Magic number (DBGFMODVTDBG_MAGIC). */
     149    uint32_t    u32Magic;
     150    /** Mask of supported debug info types, see grp_dbgf_dbginfo.
     151     * Used to speed up the search for a suitable interpreter. */
     152    uint32_t    fSupports;
     153    /** The name of the interpreter. */
     154    const char *pszName;
     155
     156    /**
     157     * Try open the image.
     158     *
     159     * This combines probing and opening.
     160     *
     161     * @returns VBox status code. No informational returns defined.
     162     *
     163     * @param   pMod        Pointer to the module that is being opened.
     164     *
     165     *                      The DBGFMOD::pszDbgFile member will point to
     166     *                      the filename of any debug info we're aware of
     167     *                      on input. Also, or alternatively, it is expected
     168     *                      that the interpreter will look for debug info in
     169     *                      the executable image file when present and that it
     170     *                      may ask the image interpreter for this when it's
     171     *                      around.
     172     *
     173     *                      Upon successful return the method is expected to
     174     *                      initialize pDbgOps and pvDbgPriv.
     175     */
     176    DECLCALLBACKMEMBER(int, pfnTryOpen)(PDBGFMOD pMod);
     177
     178    /**
     179     * Close the interpreter, freeing all associated resources.
     180     *
     181     * The caller sets the pDbgOps and pvDbgPriv DBGFMOD members
     182     * to NULL upon return.
     183     *
     184     * @param   pMod        Pointer to the module structure.
     185     */
     186    DECLCALLBACKMEMBER(int, pfnClose)(PDBGFMOD pMod);
     187
     188    /**
     189     * Queries symbol information by symbol name.
     190     *
     191     * @returns VBox status code.
     192     * @retval  VINF_SUCCESS on success, no informational status code.
     193     * @retval  VERR_DBGF_NO_SYMBOLS if there aren't any symbols.
     194     * @retval  VERR_SYMBOL_NOT_FOUND if no suitable symbol was found.
     195     *
     196     * @param   pMod        Pointer to the module structure.
     197     * @param   pszSymbol   The symbol name.
     198     * @para    pSymbol     Where to store the symbol information.
     199     */
     200    DECLCALLBACKMEMBER(int, pfnSymbolByName)(PDBGFMOD pMod, const char *pszSymbol, PDBGFSYMBOL pSymbol);
     201
     202    /**
     203     * Queries symbol information by address.
     204     *
     205     * The returned symbol is what the debug info interpreter consideres the symbol
     206     * most applicable to the specified address. This usually means a symbol with an
     207     * address equal or lower than the requested.
     208     *
     209     * @returns VBox status code.
     210     * @retval  VINF_SUCCESS on success, no informational status code.
     211     * @retval  VERR_DBGF_NO_SYMBOLS if there aren't any symbols.
     212     * @retval  VERR_SYMBOL_NOT_FOUND if no suitable symbol was found.
     213     *
     214     * @param   pMod        Pointer to the module structure.
     215     * @param   iSeg        The segment number (0-based). DBGF_SEG_RVA can be used.
     216     * @param   off         The offset into the segment.
     217     * @param   poffDisp    Where to store the distance between the specified address
     218     *                      and the returned symbol. Optional.
     219     * @param   pSymbol     Where to store the symbol information.
     220     */
     221    DECLCALLBACKMEMBER(int, pfnSymbolByAddr)(PDBGFMOD pMod, uint32_t iSeg, RTGCUINTPTR off, PRTGCINTPTR poffDisp, PDBGFSYMBOL pSymbol);
     222
     223    /**
     224     * Queries line number information by address.
     225     *
     226     * @returns VBox status code.
     227     * @retval  VINF_SUCCESS on success, no informational status code.
     228     * @retval  VERR_DBGF_NO_LINE_NUMBERS if there aren't any line numbers.
     229     * @retval  VERR_DBGF_LINE_NOT_FOUND if no suitable line number was found.
     230     *
     231     * @param   pMod        Pointer to the module structure.
     232     * @param   iSeg        The segment number (0-based). DBGF_SEG_RVA can be used.
     233     * @param   off         The offset into the segment.
     234     * @param   poffDisp    Where to store the distance between the specified address
     235     *                      and the returned line number. Optional.
     236     * @param   pLine       Where to store the information about the closest line number.
     237     */
     238    DECLCALLBACKMEMBER(int, pfnLineByAddr)(PDBGFMOD pMod, uint32_t iSeg, RTGCUINTPTR off, PRTGCINTPTR poffDisp, PDBGFLINE pLine);
     239
     240    /**
     241     * Adds a symbol to the module (optional).
     242     *
     243     * This method is used to implement DBGFR3SymbolAdd.
     244     *
     245     * @returns VBox status code.
     246     * @retval  VERR_NOT_SUPPORTED if the interpreter doesn't support this feature.
     247     *
     248     * @param   pMod        Pointer to the module structure.
     249     * @param   pszSymbol   The symbol name.
     250     * @param   iSeg        The segment number (0-based). DBGF_SEG_RVA can be used.
     251     * @param   off         The offset into the segment.
     252     * @param   cbSymbol    The area covered by the symbol. 0 is fine.
     253     */
     254    DECLCALLBACKMEMBER(int, pfnSymbolAdd)(PDBGFMOD pMod, const char *pszSymbol, uint32_t iSeg, RTGCUINTPTR off, RTUINT cbSymbol);
     255
     256    /** For catching initialization errors (DBGFMODVTDBG_MAGIC). */
     257    uint32_t    u32EndMagic;
     258} DBGFMODVTDBG;
     259
     260#define DBGFMODVTDBG_MAGIC 123
     261
     262/**
     263 * Module.
     264 */
     265typedef struct DBGFMOD
     266{
     267    /** Magic value (DBGFMOD_MAGIC). */
     268    uint32_t        u32Magic;
     269    /** The number of address spaces this module is currently linked into.
     270     * This is used to perform automatic cleanup and sharing. */
     271    uint32_t        cLinks;
     272    /** The module name (short). */
     273    const char     *pszName;
     274    /** The module filename. Can be NULL. */
     275    const char     *pszImgFile;
     276    /** The debug info file (if external). Can be NULL. */
     277    const char     *pszDbgFile;
     278
     279    /** The method table for the executable image interpreter. */
     280    PCDBGFMODVTIMG  pImgVt;
     281    /** Pointer to the private data of the executable image interpreter. */
     282    void           *pvImgPriv;
     283
     284    /** The method table for the debug info interpreter. */
     285    PCDBGFMODVTDBG  pDbgVt;
     286    /** Pointer to the private data of the debug info interpreter. */
     287    void           *pvDbgPriv;
     288
     289} DBGFMOD;
     290
     291#define DBGFMOD_MAGIC   0x12345678
     292
     293#endif
     294
  • trunk/src/VBox/VMM/MMHeap.cpp

    r18287 r19757  
    719719
    720720        TAG2STR(DBGF);
     721        TAG2STR(DBGF_AS);
    721722        TAG2STR(DBGF_INFO);
    722723        TAG2STR(DBGF_LINE);
  • trunk/src/VBox/VMM/Makefile.kmk

    r19297 r19757  
    5353        DBGF.cpp \
    5454        DBGFAddr.cpp \
     55        DBGFAddrSpace.cpp \
    5556        DBGFBp.cpp \
    5657        DBGFDisas.cpp \
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette