diff options
Diffstat (limited to 'src/VBox/VMM/VMMR3/DBGFAddrSpace.cpp')
| -rw-r--r-- | src/VBox/VMM/VMMR3/DBGFAddrSpace.cpp | 750 |
1 files changed, 476 insertions, 274 deletions
diff --git a/src/VBox/VMM/VMMR3/DBGFAddrSpace.cpp b/src/VBox/VMM/VMMR3/DBGFAddrSpace.cpp index 3861be8f..dbc2c00f 100644 --- a/src/VBox/VMM/VMMR3/DBGFAddrSpace.cpp +++ b/src/VBox/VMM/VMMR3/DBGFAddrSpace.cpp @@ -4,7 +4,7 @@ */ /* - * Copyright (C) 2008 Oracle Corporation + * Copyright (C) 2008-2013 Oracle Corporation * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; @@ -38,9 +38,14 @@ *******************************************************************************/ #define LOG_GROUP LOG_GROUP_DBGF #include <VBox/vmm/dbgf.h> +#include <VBox/vmm/hm.h> #include <VBox/vmm/pdmapi.h> #include <VBox/vmm/mm.h> +#ifdef VBOX_WITH_RAW_MODE +# include <VBox/vmm/patm.h> +#endif #include "DBGFInternal.h" +#include <VBox/vmm/uvm.h> #include <VBox/vmm/vm.h> #include <VBox/err.h> #include <VBox/log.h> @@ -49,6 +54,7 @@ #include <iprt/assert.h> #include <iprt/ctype.h> #include <iprt/env.h> +#include <iprt/mem.h> #include <iprt/path.h> #include <iprt/param.h> @@ -78,10 +84,10 @@ typedef DBGFASDBNODE *PDBGFASDBNODE; */ typedef struct DBGFR3ASLOADOPENDATA { - const char *pszModName; - RTGCUINTPTR uSubtrahend; - uint32_t fFlags; - RTDBGMOD hMod; + const char *pszModName; + RTGCUINTPTR uSubtrahend; + uint32_t fFlags; + RTDBGMOD hMod; } DBGFR3ASLOADOPENDATA; /** @@ -100,30 +106,30 @@ typedef FNDBGFR3ASSEARCHOPEN *PFNDBGFR3ASSEARCHOPEN; * Defined Constants And Macros * *******************************************************************************/ /** Locks the address space database for writing. */ -#define DBGF_AS_DB_LOCK_WRITE(pVM) \ +#define DBGF_AS_DB_LOCK_WRITE(pUVM) \ do { \ - int rcSem = RTSemRWRequestWrite((pVM)->dbgf.s.hAsDbLock, RT_INDEFINITE_WAIT); \ + int rcSem = RTSemRWRequestWrite((pUVM)->dbgf.s.hAsDbLock, RT_INDEFINITE_WAIT); \ AssertRC(rcSem); \ } while (0) /** Unlocks the address space database after writing. */ -#define DBGF_AS_DB_UNLOCK_WRITE(pVM) \ +#define DBGF_AS_DB_UNLOCK_WRITE(pUVM) \ do { \ - int rcSem = RTSemRWReleaseWrite((pVM)->dbgf.s.hAsDbLock); \ + int rcSem = RTSemRWReleaseWrite((pUVM)->dbgf.s.hAsDbLock); \ AssertRC(rcSem); \ } while (0) /** Locks the address space database for reading. */ -#define DBGF_AS_DB_LOCK_READ(pVM) \ +#define DBGF_AS_DB_LOCK_READ(pUVM) \ do { \ - int rcSem = RTSemRWRequestRead((pVM)->dbgf.s.hAsDbLock, RT_INDEFINITE_WAIT); \ + int rcSem = RTSemRWRequestRead((pUVM)->dbgf.s.hAsDbLock, RT_INDEFINITE_WAIT); \ AssertRC(rcSem); \ } while (0) /** Unlocks the address space database after reading. */ -#define DBGF_AS_DB_UNLOCK_READ(pVM) \ +#define DBGF_AS_DB_UNLOCK_READ(pUVM) \ do { \ - int rcSem = RTSemRWReleaseRead((pVM)->dbgf.s.hAsDbLock); \ + int rcSem = RTSemRWReleaseRead((pUVM)->dbgf.s.hAsDbLock); \ AssertRC(rcSem); \ } while (0) @@ -133,14 +139,86 @@ typedef FNDBGFR3ASSEARCHOPEN *PFNDBGFR3ASSEARCHOPEN; * Initializes the address space parts of DBGF. * * @returns VBox status code. - * @param pVM Pointer to the VM. + * @param pUVM The user mode VM handle. */ -int dbgfR3AsInit(PVM pVM) +int dbgfR3AsInit(PUVM pUVM) { + Assert(pUVM->pVM); + /* * Create the semaphore. */ - int rc = RTSemRWCreate(&pVM->dbgf.s.hAsDbLock); + int rc = RTSemRWCreate(&pUVM->dbgf.s.hAsDbLock); + AssertRCReturn(rc, rc); + + /* + * Create the debugging config instance and set it up, defaulting to + * deferred loading in order to keep things fast. + */ + rc = RTDbgCfgCreate(&pUVM->dbgf.s.hDbgCfg, NULL, true /*fNativePaths*/); + AssertRCReturn(rc, rc); + rc = RTDbgCfgChangeUInt(pUVM->dbgf.s.hDbgCfg, RTDBGCFGPROP_FLAGS, RTDBGCFGOP_PREPEND, + RTDBGCFG_FLAGS_DEFERRED); + AssertRCReturn(rc, rc); + + static struct + { + RTDBGCFGPROP enmProp; + const char *pszEnvName; + const char *pszCfgName; + } const s_aProps[] = + { + { RTDBGCFGPROP_FLAGS, "VBOXDBG_FLAGS", "Flags" }, + { RTDBGCFGPROP_PATH, "VBOXDBG_PATH", "Path" }, + { RTDBGCFGPROP_SUFFIXES, "VBOXDBG_SUFFIXES", "Suffixes" }, + { RTDBGCFGPROP_SRC_PATH, "VBOXDBG_SRC_PATH", "SrcPath" }, + }; + PCFGMNODE pCfgDbgf = CFGMR3GetChild(CFGMR3GetRootU(pUVM), "/DBGF"); + for (unsigned i = 0; i < RT_ELEMENTS(s_aProps); i++) + { + char szEnvValue[8192]; + rc = RTEnvGetEx(RTENV_DEFAULT, s_aProps[i].pszEnvName, szEnvValue, sizeof(szEnvValue), NULL); + if (RT_SUCCESS(rc)) + { + rc = RTDbgCfgChangeString(pUVM->dbgf.s.hDbgCfg, s_aProps[i].enmProp, RTDBGCFGOP_PREPEND, szEnvValue); + if (RT_FAILURE(rc)) + return VMR3SetError(pUVM, rc, RT_SRC_POS, + "DBGF Config Error: %s=%s -> %Rrc", s_aProps[i].pszEnvName, szEnvValue, rc); + } + else if (rc != VERR_ENV_VAR_NOT_FOUND) + return VMR3SetError(pUVM, rc, RT_SRC_POS, + "DBGF Config Error: Error querying env.var. %s: %Rrc", s_aProps[i].pszEnvName, rc); + + char *pszCfgValue; + rc = CFGMR3QueryStringAllocDef(pCfgDbgf, s_aProps[i].pszCfgName, &pszCfgValue, NULL); + if (RT_FAILURE(rc)) + return VMR3SetError(pUVM, rc, RT_SRC_POS, + "DBGF Config Error: Querying /DBGF/%s -> %Rrc", s_aProps[i].pszCfgName, rc); + if (pszCfgValue) + { + rc = RTDbgCfgChangeString(pUVM->dbgf.s.hDbgCfg, s_aProps[i].enmProp, RTDBGCFGOP_PREPEND, pszCfgValue); + if (RT_FAILURE(rc)) + return VMR3SetError(pUVM, rc, RT_SRC_POS, + "DBGF Config Error: /DBGF/%s=%s -> %Rrc", s_aProps[i].pszCfgName, pszCfgValue, rc); + } + } + + /* + * Prepend the NoArch and VBoxDbgSyms directories to the path. + */ + char szPath[RTPATH_MAX]; + rc = RTPathAppPrivateNoArch(szPath, sizeof(szPath)); + AssertRCReturn(rc, rc); +#ifdef RT_OS_DARWIN + rc = RTPathAppend(szPath, sizeof(szPath), "../Resources/VBoxDbgSyms/"); +#else + rc = RTDbgCfgChangeString(pUVM->dbgf.s.hDbgCfg, RTDBGCFGPROP_PATH, RTDBGCFGOP_PREPEND, szPath); + AssertRCReturn(rc, rc); + + rc = RTPathAppend(szPath, sizeof(szPath), "VBoxDbgSyms/"); +#endif + AssertRCReturn(rc, rc); + rc = RTDbgCfgChangeString(pUVM->dbgf.s.hDbgCfg, RTDBGCFGPROP_PATH, RTDBGCFGOP_PREPEND, szPath); AssertRCReturn(rc, rc); /* @@ -149,36 +227,36 @@ int dbgfR3AsInit(PVM pVM) RTDBGAS hDbgAs; rc = RTDbgAsCreate(&hDbgAs, 0, RTGCPTR_MAX, "Global"); AssertRCReturn(rc, rc); - rc = DBGFR3AsAdd(pVM, hDbgAs, NIL_RTPROCESS); + rc = DBGFR3AsAdd(pUVM, hDbgAs, NIL_RTPROCESS); AssertRCReturn(rc, rc); RTDbgAsRetain(hDbgAs); - pVM->dbgf.s.ahAsAliases[DBGF_AS_ALIAS_2_INDEX(DBGF_AS_GLOBAL)] = hDbgAs; + pUVM->dbgf.s.ahAsAliases[DBGF_AS_ALIAS_2_INDEX(DBGF_AS_GLOBAL)] = hDbgAs; RTDbgAsRetain(hDbgAs); - pVM->dbgf.s.ahAsAliases[DBGF_AS_ALIAS_2_INDEX(DBGF_AS_KERNEL)] = hDbgAs; + pUVM->dbgf.s.ahAsAliases[DBGF_AS_ALIAS_2_INDEX(DBGF_AS_KERNEL)] = hDbgAs; rc = RTDbgAsCreate(&hDbgAs, 0, RTGCPHYS_MAX, "Physical"); AssertRCReturn(rc, rc); - rc = DBGFR3AsAdd(pVM, hDbgAs, NIL_RTPROCESS); + rc = DBGFR3AsAdd(pUVM, hDbgAs, NIL_RTPROCESS); AssertRCReturn(rc, rc); RTDbgAsRetain(hDbgAs); - pVM->dbgf.s.ahAsAliases[DBGF_AS_ALIAS_2_INDEX(DBGF_AS_PHYS)] = hDbgAs; + pUVM->dbgf.s.ahAsAliases[DBGF_AS_ALIAS_2_INDEX(DBGF_AS_PHYS)] = hDbgAs; rc = RTDbgAsCreate(&hDbgAs, 0, RTRCPTR_MAX, "HyperRawMode"); AssertRCReturn(rc, rc); - rc = DBGFR3AsAdd(pVM, hDbgAs, NIL_RTPROCESS); + rc = DBGFR3AsAdd(pUVM, hDbgAs, NIL_RTPROCESS); AssertRCReturn(rc, rc); RTDbgAsRetain(hDbgAs); - pVM->dbgf.s.ahAsAliases[DBGF_AS_ALIAS_2_INDEX(DBGF_AS_RC)] = hDbgAs; + pUVM->dbgf.s.ahAsAliases[DBGF_AS_ALIAS_2_INDEX(DBGF_AS_RC)] = hDbgAs; RTDbgAsRetain(hDbgAs); - pVM->dbgf.s.ahAsAliases[DBGF_AS_ALIAS_2_INDEX(DBGF_AS_RC_AND_GC_GLOBAL)] = hDbgAs; + pUVM->dbgf.s.ahAsAliases[DBGF_AS_ALIAS_2_INDEX(DBGF_AS_RC_AND_GC_GLOBAL)] = hDbgAs; rc = RTDbgAsCreate(&hDbgAs, 0, RTR0PTR_MAX, "HyperRing0"); AssertRCReturn(rc, rc); - rc = DBGFR3AsAdd(pVM, hDbgAs, NIL_RTPROCESS); + rc = DBGFR3AsAdd(pUVM, hDbgAs, NIL_RTPROCESS); AssertRCReturn(rc, rc); RTDbgAsRetain(hDbgAs); - pVM->dbgf.s.ahAsAliases[DBGF_AS_ALIAS_2_INDEX(DBGF_AS_R0)] = hDbgAs; + pUVM->dbgf.s.ahAsAliases[DBGF_AS_ALIAS_2_INDEX(DBGF_AS_R0)] = hDbgAs; return VINF_SUCCESS; } @@ -206,25 +284,25 @@ static DECLCALLBACK(int) dbgfR3AsTermDestroyNode(PAVLPVNODECORE pNode, void *pvI /** * Terminates the address space parts of DBGF. * - * @param pVM Pointer to the VM. + * @param pUVM The user mode VM handle. */ -void dbgfR3AsTerm(PVM pVM) +void dbgfR3AsTerm(PUVM pUVM) { /* * Create the semaphore. */ - int rc = RTSemRWDestroy(pVM->dbgf.s.hAsDbLock); + int rc = RTSemRWDestroy(pUVM->dbgf.s.hAsDbLock); AssertRC(rc); - pVM->dbgf.s.hAsDbLock = NIL_RTSEMRW; + pUVM->dbgf.s.hAsDbLock = NIL_RTSEMRW; /* * Release all the address spaces. */ - RTAvlPVDestroy(&pVM->dbgf.s.AsHandleTree, dbgfR3AsTermDestroyNode, NULL); - for (size_t i = 0; i < RT_ELEMENTS(pVM->dbgf.s.ahAsAliases); i++) + RTAvlPVDestroy(&pUVM->dbgf.s.AsHandleTree, dbgfR3AsTermDestroyNode, NULL); + for (size_t i = 0; i < RT_ELEMENTS(pUVM->dbgf.s.ahAsAliases); i++) { - RTDbgAsRelease(pVM->dbgf.s.ahAsAliases[i]); - pVM->dbgf.s.ahAsAliases[i] = NIL_RTDBGAS; + RTDbgAsRelease(pUVM->dbgf.s.ahAsAliases[i]); + pUVM->dbgf.s.ahAsAliases[i] = NIL_RTDBGAS; } } @@ -232,13 +310,89 @@ void dbgfR3AsTerm(PVM pVM) /** * Relocates the RC address space. * - * @param pVM Pointer to the VM. - * @param offDelta The relocation delta. + * @param pUVM The user mode VM handle. + * @param offDelta The relocation delta. + */ +void dbgfR3AsRelocate(PUVM pUVM, RTGCUINTPTR offDelta) +{ + /* + * We will relocate the raw-mode context modules by offDelta if they have + * been injected into the the DBGF_AS_RC map. + */ + if ( pUVM->dbgf.s.afAsAliasPopuplated[DBGF_AS_ALIAS_2_INDEX(DBGF_AS_RC)] + && offDelta != 0) + { + RTDBGAS hAs = pUVM->dbgf.s.ahAsAliases[DBGF_AS_ALIAS_2_INDEX(DBGF_AS_RC)]; + + /* Take a snapshot of the modules as we might have overlapping + addresses between the previous and new mapping. */ + RTDbgAsLockExcl(hAs); + uint32_t cModules = RTDbgAsModuleCount(hAs); + if (cModules > 0 && cModules < _4K) + { + struct DBGFASRELOCENTRY + { + RTDBGMOD hDbgMod; + RTRCPTR uOldAddr; + } *paEntries = (struct DBGFASRELOCENTRY *)RTMemTmpAllocZ(sizeof(paEntries[0]) * cModules); + if (paEntries) + { + /* Snapshot. */ + for (uint32_t i = 0; i < cModules; i++) + { + paEntries[i].hDbgMod = RTDbgAsModuleByIndex(hAs, i); + AssertLogRelMsg(paEntries[i].hDbgMod != NIL_RTDBGMOD, ("iModule=%#x\n", i)); + + RTDBGASMAPINFO aMappings[1] = { { 0, 0 } }; + uint32_t cMappings = 1; + int rc = RTDbgAsModuleQueryMapByIndex(hAs, i, &aMappings[0], &cMappings, 0 /*fFlags*/); + if (RT_SUCCESS(rc) && cMappings == 1 && aMappings[0].iSeg == NIL_RTDBGSEGIDX) + paEntries[i].uOldAddr = (RTRCPTR)aMappings[0].Address; + else + AssertLogRelMsgFailed(("iModule=%#x rc=%Rrc cMappings=%#x.\n", i, rc, cMappings)); + } + + /* Unlink them. */ + for (uint32_t i = 0; i < cModules; i++) + { + int rc = RTDbgAsModuleUnlink(hAs, paEntries[i].hDbgMod); + AssertLogRelMsg(RT_SUCCESS(rc), ("iModule=%#x rc=%Rrc hDbgMod=%p\n", i, rc, paEntries[i].hDbgMod)); + } + + /* Link them at the new locations. */ + for (uint32_t i = 0; i < cModules; i++) + { + RTRCPTR uNewAddr = paEntries[i].uOldAddr + offDelta; + int rc = RTDbgAsModuleLink(hAs, paEntries[i].hDbgMod, uNewAddr, + RTDBGASLINK_FLAGS_REPLACE); + AssertLogRelMsg(RT_SUCCESS(rc), + ("iModule=%#x rc=%Rrc hDbgMod=%p %RRv -> %RRv\n", i, rc, paEntries[i].hDbgMod, + paEntries[i].uOldAddr, uNewAddr)); + RTDbgModRelease(paEntries[i].hDbgMod); + } + + RTMemTmpFree(paEntries); + } + else + AssertLogRelMsgFailed(("No memory for %#x modules.\n", cModules)); + } + else + AssertLogRelMsgFailed(("cModules=%#x\n", cModules)); + RTDbgAsUnlockExcl(hAs); + } +} + + +/** + * Gets the IPRT debugging configuration handle (no refs retained). + * + * @returns Config handle or NIL_RTDBGCFG. + * @param pUVM The user mode VM handle. */ -void dbgfR3AsRelocate(PVM pVM, RTGCUINTPTR offDelta) +VMMR3DECL(RTDBGCFG) DBGFR3AsGetConfig(PUVM pUVM) { - /** @todo */ - NOREF(pVM); NOREF(offDelta); + UVM_ASSERT_VALID_EXT_RETURN(pUVM, NIL_RTDBGCFG); + return pUVM->dbgf.s.hDbgCfg; } @@ -246,17 +400,17 @@ void dbgfR3AsRelocate(PVM pVM, RTGCUINTPTR offDelta) * Adds the address space to the database. * * @returns VBox status code. - * @param pVM Pointer to the VM. - * @param hDbgAs The address space handle. The reference of the - * caller will NOT be consumed. - * @param ProcId The process id or NIL_RTPROCESS. + * @param pUVM The user mode VM handle. + * @param hDbgAs The address space handle. The reference of the caller + * will NOT be consumed. + * @param ProcId The process id or NIL_RTPROCESS. */ -VMMR3DECL(int) DBGFR3AsAdd(PVM pVM, RTDBGAS hDbgAs, RTPROCESS ProcId) +VMMR3DECL(int) DBGFR3AsAdd(PUVM pUVM, RTDBGAS hDbgAs, RTPROCESS ProcId) { /* * Input validation. */ - VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE); + UVM_ASSERT_VALID_EXT_RETURN(pUVM, VERR_INVALID_VM_HANDLE); const char *pszName = RTDbgAsName(hDbgAs); if (!pszName) return VERR_INVALID_HANDLE; @@ -268,26 +422,26 @@ VMMR3DECL(int) DBGFR3AsAdd(PVM pVM, RTDBGAS hDbgAs, RTPROCESS ProcId) * Allocate a tracking node. */ int rc = VERR_NO_MEMORY; - PDBGFASDBNODE pDbNode = (PDBGFASDBNODE)MMR3HeapAlloc(pVM, MM_TAG_DBGF_AS, sizeof(*pDbNode)); + PDBGFASDBNODE pDbNode = (PDBGFASDBNODE)MMR3HeapAllocU(pUVM, MM_TAG_DBGF_AS, sizeof(*pDbNode)); if (pDbNode) { pDbNode->HandleCore.Key = hDbgAs; pDbNode->PidCore.Key = ProcId; pDbNode->NameCore.pszString = pszName; pDbNode->NameCore.cchString = strlen(pszName); - DBGF_AS_DB_LOCK_WRITE(pVM); - if (RTStrSpaceInsert(&pVM->dbgf.s.AsNameSpace, &pDbNode->NameCore)) + DBGF_AS_DB_LOCK_WRITE(pUVM); + if (RTStrSpaceInsert(&pUVM->dbgf.s.AsNameSpace, &pDbNode->NameCore)) { - if (RTAvlPVInsert(&pVM->dbgf.s.AsHandleTree, &pDbNode->HandleCore)) + if (RTAvlPVInsert(&pUVM->dbgf.s.AsHandleTree, &pDbNode->HandleCore)) { - DBGF_AS_DB_UNLOCK_WRITE(pVM); + DBGF_AS_DB_UNLOCK_WRITE(pUVM); return VINF_SUCCESS; } /* bail out */ - RTStrSpaceRemove(&pVM->dbgf.s.AsNameSpace, pszName); + RTStrSpaceRemove(&pUVM->dbgf.s.AsNameSpace, pszName); } - DBGF_AS_DB_UNLOCK_WRITE(pVM); + DBGF_AS_DB_UNLOCK_WRITE(pUVM); MMR3HeapFree(pDbNode); } RTDbgAsRelease(hDbgAs); @@ -304,16 +458,16 @@ VMMR3DECL(int) DBGFR3AsAdd(PVM pVM, RTDBGAS hDbgAs, RTPROCESS ProcId) * @retval VERR_SHARING_VIOLATION if in use as an alias. * @retval VERR_NOT_FOUND if not found in the address space database. * - * @param pVM Pointer to the VM. - * @param hDbgAs The address space handle. Aliases are not allowed. + * @param pUVM The user mode VM handle. + * @param hDbgAs The address space handle. Aliases are not allowed. */ -VMMR3DECL(int) DBGFR3AsDelete(PVM pVM, RTDBGAS hDbgAs) +VMMR3DECL(int) DBGFR3AsDelete(PUVM pUVM, RTDBGAS hDbgAs) { /* * Input validation. Retain the address space so it can be released outside * the lock as well as validated. */ - VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE); + UVM_ASSERT_VALID_EXT_RETURN(pUVM, VERR_INVALID_VM_HANDLE); if (hDbgAs == NIL_RTDBGAS) return VINF_SUCCESS; uint32_t cRefs = RTDbgAsRetain(hDbgAs); @@ -321,32 +475,32 @@ VMMR3DECL(int) DBGFR3AsDelete(PVM pVM, RTDBGAS hDbgAs) return VERR_INVALID_HANDLE; RTDbgAsRelease(hDbgAs); - DBGF_AS_DB_LOCK_WRITE(pVM); + DBGF_AS_DB_LOCK_WRITE(pUVM); /* * You cannot delete any of the aliases. */ - for (size_t i = 0; i < RT_ELEMENTS(pVM->dbgf.s.ahAsAliases); i++) - if (pVM->dbgf.s.ahAsAliases[i] == hDbgAs) + for (size_t i = 0; i < RT_ELEMENTS(pUVM->dbgf.s.ahAsAliases); i++) + if (pUVM->dbgf.s.ahAsAliases[i] == hDbgAs) { - DBGF_AS_DB_UNLOCK_WRITE(pVM); + DBGF_AS_DB_UNLOCK_WRITE(pUVM); return VERR_SHARING_VIOLATION; } /* * Ok, try remove it from the database. */ - PDBGFASDBNODE pDbNode = (PDBGFASDBNODE)RTAvlPVRemove(&pVM->dbgf.s.AsHandleTree, hDbgAs); + PDBGFASDBNODE pDbNode = (PDBGFASDBNODE)RTAvlPVRemove(&pUVM->dbgf.s.AsHandleTree, hDbgAs); if (!pDbNode) { - DBGF_AS_DB_UNLOCK_WRITE(pVM); + DBGF_AS_DB_UNLOCK_WRITE(pUVM); return VERR_NOT_FOUND; } - RTStrSpaceRemove(&pVM->dbgf.s.AsNameSpace, pDbNode->NameCore.pszString); + RTStrSpaceRemove(&pUVM->dbgf.s.AsNameSpace, pDbNode->NameCore.pszString); if (pDbNode->PidCore.Key != NIL_RTPROCESS) - RTAvlU32Remove(&pVM->dbgf.s.AsPidTree, pDbNode->PidCore.Key); + RTAvlU32Remove(&pUVM->dbgf.s.AsPidTree, pDbNode->PidCore.Key); - DBGF_AS_DB_UNLOCK_WRITE(pVM); + DBGF_AS_DB_UNLOCK_WRITE(pUVM); /* * Free the resources. @@ -365,21 +519,21 @@ VMMR3DECL(int) DBGFR3AsDelete(PVM pVM, RTDBGAS hDbgAs) * and DBGF_AS_KERNEL. * * @returns VBox status code. - * @param pVM Pointer to the VM. - * @param hAlias The alias to change. - * @param hAliasFor The address space hAlias should be an alias for. - * This can be an alias. The caller's reference to - * this address space will NOT be consumed. + * @param pUVM The user mode VM handle. + * @param hAlias The alias to change. + * @param hAliasFor The address space hAlias should be an alias for. This + * can be an alias. The caller's reference to this address + * space will NOT be consumed. */ -VMMR3DECL(int) DBGFR3AsSetAlias(PVM pVM, RTDBGAS hAlias, RTDBGAS hAliasFor) +VMMR3DECL(int) DBGFR3AsSetAlias(PUVM pUVM, RTDBGAS hAlias, RTDBGAS hAliasFor) { /* * Input validation. */ - VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE); + UVM_ASSERT_VALID_EXT_RETURN(pUVM, VERR_INVALID_VM_HANDLE); AssertMsgReturn(DBGF_AS_IS_ALIAS(hAlias), ("%p\n", hAlias), VERR_INVALID_PARAMETER); AssertMsgReturn(!DBGF_AS_IS_FIXED_ALIAS(hAlias), ("%p\n", hAlias), VERR_INVALID_PARAMETER); - RTDBGAS hRealAliasFor = DBGFR3AsResolveAndRetain(pVM, hAliasFor); + RTDBGAS hRealAliasFor = DBGFR3AsResolveAndRetain(pUVM, hAliasFor); if (hRealAliasFor == NIL_RTDBGAS) return VERR_INVALID_HANDLE; @@ -387,19 +541,19 @@ VMMR3DECL(int) DBGFR3AsSetAlias(PVM pVM, RTDBGAS hAlias, RTDBGAS hAliasFor) * Make sure the handle has is already in the database. */ int rc = VERR_NOT_FOUND; - DBGF_AS_DB_LOCK_WRITE(pVM); - if (RTAvlPVGet(&pVM->dbgf.s.AsHandleTree, hRealAliasFor)) + DBGF_AS_DB_LOCK_WRITE(pUVM); + if (RTAvlPVGet(&pUVM->dbgf.s.AsHandleTree, hRealAliasFor)) { /* * Update the alias table and release the current address space. */ RTDBGAS hAsOld; - ASMAtomicXchgHandle(&pVM->dbgf.s.ahAsAliases[DBGF_AS_ALIAS_2_INDEX(hAlias)], hRealAliasFor, &hAsOld); + ASMAtomicXchgHandle(&pUVM->dbgf.s.ahAsAliases[DBGF_AS_ALIAS_2_INDEX(hAlias)], hRealAliasFor, &hAsOld); uint32_t cRefs = RTDbgAsRelease(hAsOld); Assert(cRefs > 0); Assert(cRefs != UINT32_MAX); NOREF(cRefs); rc = VINF_SUCCESS; } - DBGF_AS_DB_UNLOCK_WRITE(pVM); + DBGF_AS_DB_UNLOCK_WRITE(pUVM); return rc; } @@ -409,15 +563,15 @@ VMMR3DECL(int) DBGFR3AsSetAlias(PVM pVM, RTDBGAS hAlias, RTDBGAS hAliasFor) * @callback_method_impl{FNPDMR3ENUM} */ static DECLCALLBACK(int) dbgfR3AsLazyPopulateR0Callback(PVM pVM, const char *pszFilename, const char *pszName, - RTUINTPTR ImageBase, size_t cbImage, bool fRC, void *pvArg) + RTUINTPTR ImageBase, size_t cbImage, PDMLDRCTX enmCtx, void *pvArg) { NOREF(pVM); NOREF(cbImage); /* Only ring-0 modules. */ - if (!fRC) + if (enmCtx == PDMLDRCTX_RING_0) { RTDBGMOD hDbgMod; - int rc = RTDbgModCreateFromImage(&hDbgMod, pszFilename, pszName, 0 /*fFlags*/); + int rc = RTDbgModCreateFromImage(&hDbgMod, pszFilename, pszName, RTLDRARCH_HOST, pVM->pUVM->dbgf.s.hDbgCfg); if (RT_SUCCESS(rc)) { rc = RTDbgAsModuleLink((RTDBGAS)pvArg, hDbgMod, ImageBase, 0 /*fFlags*/); @@ -434,25 +588,64 @@ static DECLCALLBACK(int) dbgfR3AsLazyPopulateR0Callback(PVM pVM, const char *psz /** + * @callback_method_impl{FNPDMR3ENUM} + */ +static DECLCALLBACK(int) dbgfR3AsLazyPopulateRCCallback(PVM pVM, const char *pszFilename, const char *pszName, + RTUINTPTR ImageBase, size_t cbImage, PDMLDRCTX enmCtx, void *pvArg) +{ + NOREF(pVM); NOREF(cbImage); + + /* Only raw-mode modules. */ + if (enmCtx == PDMLDRCTX_RAW_MODE) + { + RTDBGMOD hDbgMod; + int rc = RTDbgModCreateFromImage(&hDbgMod, pszFilename, pszName, RTLDRARCH_X86_32, pVM->pUVM->dbgf.s.hDbgCfg); + if (RT_SUCCESS(rc)) + { + rc = RTDbgAsModuleLink((RTDBGAS)pvArg, hDbgMod, ImageBase, 0 /*fFlags*/); + if (RT_FAILURE(rc)) + LogRel(("DBGF: Failed to link module \"%s\" into DBGF_AS_RC at %RTptr: %Rrc\n", + pszName, ImageBase, rc)); + } + else + LogRel(("DBGF: RTDbgModCreateFromImage failed with rc=%Rrc for module \"%s\" (%s)\n", + rc, pszName, pszFilename)); + } + return VINF_SUCCESS; +} + + +/** * Lazily populates the specified address space. * - * @param pVM Pointer to the VM. - * @param hAlias The alias. + * @param pUVM The user mode VM handle. + * @param hAlias The alias. */ -static void dbgfR3AsLazyPopulate(PVM pVM, RTDBGAS hAlias) +static void dbgfR3AsLazyPopulate(PUVM pUVM, RTDBGAS hAlias) { - DBGF_AS_DB_LOCK_WRITE(pVM); + DBGF_AS_DB_LOCK_WRITE(pUVM); uintptr_t iAlias = DBGF_AS_ALIAS_2_INDEX(hAlias); - if (!pVM->dbgf.s.afAsAliasPopuplated[iAlias]) + if (!pUVM->dbgf.s.afAsAliasPopuplated[iAlias]) { - RTDBGAS hAs = pVM->dbgf.s.ahAsAliases[iAlias]; - if (hAlias == DBGF_AS_R0) - PDMR3LdrEnumModules(pVM, dbgfR3AsLazyPopulateR0Callback, hAs); - /** @todo what do we do about DBGF_AS_RC? */ + RTDBGAS hDbgAs = pUVM->dbgf.s.ahAsAliases[iAlias]; + if (hAlias == DBGF_AS_R0 && pUVM->pVM) + PDMR3LdrEnumModules(pUVM->pVM, dbgfR3AsLazyPopulateR0Callback, hDbgAs); + else if (hAlias == DBGF_AS_RC && pUVM->pVM && !HMIsEnabled(pUVM->pVM)) + { + LogRel(("DBGF: Lazy init of RC address space\n")); + PDMR3LdrEnumModules(pUVM->pVM, dbgfR3AsLazyPopulateRCCallback, hDbgAs); +#ifdef VBOX_WITH_RAW_MODE + PATMR3DbgPopulateAddrSpace(pUVM->pVM, hDbgAs); +#endif + } + else if (hAlias == DBGF_AS_PHYS && pUVM->pVM) + { + /** @todo Lazy load pc and vga bios symbols or the EFI stuff. */ + } - pVM->dbgf.s.afAsAliasPopuplated[iAlias] = true; + pUVM->dbgf.s.afAsAliasPopuplated[iAlias] = true; } - DBGF_AS_DB_UNLOCK_WRITE(pVM); + DBGF_AS_DB_UNLOCK_WRITE(pUVM); } @@ -461,19 +654,19 @@ static void dbgfR3AsLazyPopulate(PVM pVM, RTDBGAS hAlias) * * @returns Real address space handle. NIL_RTDBGAS if invalid handle. * - * @param pVM Pointer to the VM. - * @param hAlias The possibly address space alias. + * @param pUVM The user mode VM handle. + * @param hAlias The possibly address space alias. * * @remarks Doesn't take any locks. */ -VMMR3DECL(RTDBGAS) DBGFR3AsResolve(PVM pVM, RTDBGAS hAlias) +VMMR3DECL(RTDBGAS) DBGFR3AsResolve(PUVM pUVM, RTDBGAS hAlias) { - VM_ASSERT_VALID_EXT_RETURN(pVM, NULL); + UVM_ASSERT_VALID_EXT_RETURN(pUVM, NULL); AssertCompileNS(NIL_RTDBGAS == (RTDBGAS)0); uintptr_t iAlias = DBGF_AS_ALIAS_2_INDEX(hAlias); if (iAlias < DBGF_AS_COUNT) - ASMAtomicReadHandle(&pVM->dbgf.s.ahAsAliases[iAlias], &hAlias); + ASMAtomicReadHandle(&pUVM->dbgf.s.ahAsAliases[iAlias], &hAlias); return hAlias; } @@ -484,12 +677,12 @@ VMMR3DECL(RTDBGAS) DBGFR3AsResolve(PVM pVM, RTDBGAS hAlias) * * @returns Real address space handle. NIL_RTDBGAS if invalid handle. * - * @param pVM Pointer to the VM. - * @param hAlias The possibly address space alias. + * @param pUVM The user mode VM handle. + * @param hAlias The possibly address space alias. */ -VMMR3DECL(RTDBGAS) DBGFR3AsResolveAndRetain(PVM pVM, RTDBGAS hAlias) +VMMR3DECL(RTDBGAS) DBGFR3AsResolveAndRetain(PUVM pUVM, RTDBGAS hAlias) { - VM_ASSERT_VALID_EXT_RETURN(pVM, NULL); + UVM_ASSERT_VALID_EXT_RETURN(pUVM, NULL); AssertCompileNS(NIL_RTDBGAS == (RTDBGAS)0); uint32_t cRefs; @@ -499,20 +692,20 @@ VMMR3DECL(RTDBGAS) DBGFR3AsResolveAndRetain(PVM pVM, RTDBGAS hAlias) if (DBGF_AS_IS_FIXED_ALIAS(hAlias)) { /* Perform lazy address space population. */ - if (!pVM->dbgf.s.afAsAliasPopuplated[iAlias]) - dbgfR3AsLazyPopulate(pVM, hAlias); + if (!pUVM->dbgf.s.afAsAliasPopuplated[iAlias]) + dbgfR3AsLazyPopulate(pUVM, hAlias); /* Won't ever change, no need to grab the lock. */ - hAlias = pVM->dbgf.s.ahAsAliases[iAlias]; + hAlias = pUVM->dbgf.s.ahAsAliases[iAlias]; cRefs = RTDbgAsRetain(hAlias); } else { /* May change, grab the lock so we can read it safely. */ - DBGF_AS_DB_LOCK_READ(pVM); - hAlias = pVM->dbgf.s.ahAsAliases[iAlias]; + DBGF_AS_DB_LOCK_READ(pUVM); + hAlias = pUVM->dbgf.s.ahAsAliases[iAlias]; cRefs = RTDbgAsRetain(hAlias); - DBGF_AS_DB_UNLOCK_READ(pVM); + DBGF_AS_DB_UNLOCK_READ(pUVM); } } else @@ -528,15 +721,15 @@ VMMR3DECL(RTDBGAS) DBGFR3AsResolveAndRetain(PVM pVM, RTDBGAS hAlias) * * @returns Retained address space handle if found, NIL_RTDBGAS if not. * - * @param pVM Pointer to the VM. + * @param pUVM The user mode VM handle. * @param pszName The name. */ -VMMR3DECL(RTDBGAS) DBGFR3AsQueryByName(PVM pVM, const char *pszName) +VMMR3DECL(RTDBGAS) DBGFR3AsQueryByName(PUVM pUVM, const char *pszName) { /* * Validate the input. */ - VM_ASSERT_VALID_EXT_RETURN(pVM, NIL_RTDBGAS); + UVM_ASSERT_VALID_EXT_RETURN(pUVM, NIL_RTDBGAS); AssertPtrReturn(pszName, NIL_RTDBGAS); AssertReturn(*pszName, NIL_RTDBGAS); @@ -544,9 +737,9 @@ VMMR3DECL(RTDBGAS) DBGFR3AsQueryByName(PVM pVM, const char *pszName) * Look it up in the string space and retain the result. */ RTDBGAS hDbgAs = NIL_RTDBGAS; - DBGF_AS_DB_LOCK_READ(pVM); + DBGF_AS_DB_LOCK_READ(pUVM); - PRTSTRSPACECORE pNode = RTStrSpaceGet(&pVM->dbgf.s.AsNameSpace, pszName); + PRTSTRSPACECORE pNode = RTStrSpaceGet(&pUVM->dbgf.s.AsNameSpace, pszName); if (pNode) { PDBGFASDBNODE pDbNode = RT_FROM_MEMBER(pNode, DBGFASDBNODE, NameCore); @@ -555,8 +748,8 @@ VMMR3DECL(RTDBGAS) DBGFR3AsQueryByName(PVM pVM, const char *pszName) if (RT_UNLIKELY(cRefs == UINT32_MAX)) hDbgAs = NIL_RTDBGAS; } - DBGF_AS_DB_UNLOCK_READ(pVM); + DBGF_AS_DB_UNLOCK_READ(pUVM); return hDbgAs; } @@ -566,24 +759,24 @@ VMMR3DECL(RTDBGAS) DBGFR3AsQueryByName(PVM pVM, const char *pszName) * * @returns Retained address space handle if found, NIL_RTDBGAS if not. * - * @param pVM Pointer to the VM. + * @param pUVM The user mode VM handle. * @param ProcId The process ID. */ -VMMR3DECL(RTDBGAS) DBGFR3AsQueryByPid(PVM pVM, RTPROCESS ProcId) +VMMR3DECL(RTDBGAS) DBGFR3AsQueryByPid(PUVM pUVM, RTPROCESS ProcId) { /* * Validate the input. */ - VM_ASSERT_VALID_EXT_RETURN(pVM, NIL_RTDBGAS); + UVM_ASSERT_VALID_EXT_RETURN(pUVM, NIL_RTDBGAS); AssertReturn(ProcId != NIL_RTPROCESS, NIL_RTDBGAS); /* * Look it up in the PID tree and retain the result. */ RTDBGAS hDbgAs = NIL_RTDBGAS; - DBGF_AS_DB_LOCK_READ(pVM); + DBGF_AS_DB_LOCK_READ(pUVM); - PAVLU32NODECORE pNode = RTAvlU32Get(&pVM->dbgf.s.AsPidTree, ProcId); + PAVLU32NODECORE pNode = RTAvlU32Get(&pUVM->dbgf.s.AsPidTree, ProcId); if (pNode) { PDBGFASDBNODE pDbNode = RT_FROM_MEMBER(pNode, DBGFASDBNODE, PidCore); @@ -592,7 +785,7 @@ VMMR3DECL(RTDBGAS) DBGFR3AsQueryByPid(PVM pVM, RTPROCESS ProcId) if (RT_UNLIKELY(cRefs == UINT32_MAX)) hDbgAs = NIL_RTDBGAS; } - DBGF_AS_DB_UNLOCK_READ(pVM); + DBGF_AS_DB_UNLOCK_READ(pUVM); return hDbgAs; } @@ -716,15 +909,17 @@ static int dbgfR3AsSearchEnvPath(const char *pszFilename, const char *pszEnvVar, * Nothing is done if the CFGM variable isn't set. * * @returns VBox status code. + * @param pUVM The user mode VM handle. * @param pszFilename The filename. * @param pszCfgValue The name of the config variable (under /DBGF/). * @param pfnOpen The open callback function. * @param pvUser User argument for the callback. */ -static int dbgfR3AsSearchCfgPath(PVM pVM, const char *pszFilename, const char *pszCfgValue, PFNDBGFR3ASSEARCHOPEN pfnOpen, void *pvUser) +static int dbgfR3AsSearchCfgPath(PUVM pUVM, const char *pszFilename, const char *pszCfgValue, + PFNDBGFR3ASSEARCHOPEN pfnOpen, void *pvUser) { char *pszPath; - int rc = CFGMR3QueryStringAllocDef(CFGMR3GetChild(CFGMR3GetRoot(pVM), "/DBGF"), pszCfgValue, &pszPath, NULL); + int rc = CFGMR3QueryStringAllocDef(CFGMR3GetChild(CFGMR3GetRootU(pUVM), "/DBGF"), pszCfgValue, &pszPath, NULL); if (RT_FAILURE(rc)) return rc; if (!pszPath) @@ -736,20 +931,6 @@ static int dbgfR3AsSearchCfgPath(PVM pVM, const char *pszFilename, const char *p /** - * Callback function used by DBGFR3AsLoadImage. - * - * @returns VBox status code. - * @param pszFilename The filename under evaluation. - * @param pvUser Use arguments (DBGFR3ASLOADOPENDATA). - */ -static DECLCALLBACK(int) dbgfR3AsLoadImageOpen(const char *pszFilename, void *pvUser) -{ - DBGFR3ASLOADOPENDATA *pData = (DBGFR3ASLOADOPENDATA *)pvUser; - return RTDbgModCreateFromImage(&pData->hMod, pszFilename, pData->pszModName, pData->fFlags); -} - - -/** * Load symbols from an executable module into the specified address space. * * If an module exist at the specified address it will be replaced by this @@ -757,49 +938,40 @@ static DECLCALLBACK(int) dbgfR3AsLoadImageOpen(const char *pszFilename, void *pv * * @returns VBox status code. * - * @param pVM Pointer to the VM. + * @param pUVM The user mode VM handle. * @param hDbgAs The address space. * @param pszFilename The filename of the executable module. * @param pszModName The module name. If NULL, then then the file name * base is used (no extension or nothing). + * @param enmArch The desired architecture, use RTLDRARCH_WHATEVER if + * it's not relevant or known. * @param pModAddress The load address of the module. * @param iModSeg The segment to load, pass NIL_RTDBGSEGIDX to load * the whole image. * @param fFlags Flags reserved for future extensions, must be 0. */ -VMMR3DECL(int) DBGFR3AsLoadImage(PVM pVM, RTDBGAS hDbgAs, const char *pszFilename, const char *pszModName, PCDBGFADDRESS pModAddress, RTDBGSEGIDX iModSeg, uint32_t fFlags) +VMMR3DECL(int) DBGFR3AsLoadImage(PUVM pUVM, RTDBGAS hDbgAs, const char *pszFilename, const char *pszModName, RTLDRARCH enmArch, + PCDBGFADDRESS pModAddress, RTDBGSEGIDX iModSeg, uint32_t fFlags) { /* * Validate input */ + UVM_ASSERT_VALID_EXT_RETURN(pUVM, VERR_INVALID_VM_HANDLE); AssertPtrReturn(pszFilename, VERR_INVALID_POINTER); AssertReturn(*pszFilename, VERR_INVALID_PARAMETER); - AssertReturn(DBGFR3AddrIsValid(pVM, pModAddress), VERR_INVALID_PARAMETER); + AssertReturn(DBGFR3AddrIsValid(pUVM, pModAddress), VERR_INVALID_PARAMETER); AssertReturn(fFlags == 0, VERR_INVALID_PARAMETER); - RTDBGAS hRealAS = DBGFR3AsResolveAndRetain(pVM, hDbgAs); + RTDBGAS hRealAS = DBGFR3AsResolveAndRetain(pUVM, hDbgAs); if (hRealAS == NIL_RTDBGAS) return VERR_INVALID_HANDLE; - /* - * Do the work. - */ - DBGFR3ASLOADOPENDATA Data; - Data.pszModName = pszModName; - Data.uSubtrahend = 0; - Data.fFlags = 0; - Data.hMod = NIL_RTDBGMOD; - int rc = dbgfR3AsSearchCfgPath(pVM, pszFilename, "ImagePath", dbgfR3AsLoadImageOpen, &Data); - if (RT_FAILURE(rc)) - rc = dbgfR3AsSearchEnvPath(pszFilename, "VBOXDBG_IMAGE_PATH", dbgfR3AsLoadImageOpen, &Data); - if (RT_FAILURE(rc)) - rc = dbgfR3AsSearchCfgPath(pVM, pszFilename, "Path", dbgfR3AsLoadImageOpen, &Data); - if (RT_FAILURE(rc)) - rc = dbgfR3AsSearchEnvPath(pszFilename, "VBOXDBG_PATH", dbgfR3AsLoadImageOpen, &Data); + RTDBGMOD hDbgMod; + int rc = RTDbgModCreateFromImage(&hDbgMod, pszFilename, pszModName, enmArch, pUVM->dbgf.s.hDbgCfg); if (RT_SUCCESS(rc)) { - rc = DBGFR3AsLinkModule(pVM, hRealAS, Data.hMod, pModAddress, iModSeg, 0); + rc = DBGFR3AsLinkModule(pUVM, hRealAS, hDbgMod, pModAddress, iModSeg, 0); if (RT_FAILURE(rc)) - RTDbgModRelease(Data.hMod); + RTDbgModRelease(hDbgMod); } RTDbgAsRelease(hRealAS); @@ -808,20 +980,6 @@ VMMR3DECL(int) DBGFR3AsLoadImage(PVM pVM, RTDBGAS hDbgAs, const char *pszFilenam /** - * Callback function used by DBGFR3AsLoadMap. - * - * @returns VBox status code. - * @param pszFilename The filename under evaluation. - * @param pvUser Use arguments (DBGFR3ASLOADOPENDATA). - */ -static DECLCALLBACK(int) dbgfR3AsLoadMapOpen(const char *pszFilename, void *pvUser) -{ - DBGFR3ASLOADOPENDATA *pData = (DBGFR3ASLOADOPENDATA *)pvUser; - return RTDbgModCreateFromMap(&pData->hMod, pszFilename, pData->pszModName, pData->uSubtrahend, pData->fFlags); -} - - -/** * Load symbols from a map file into a module at the specified address space. * * If an module exist at the specified address it will be replaced by this @@ -829,7 +987,7 @@ static DECLCALLBACK(int) dbgfR3AsLoadMapOpen(const char *pszFilename, void *pvUs * * @returns VBox status code. * - * @param pVM Pointer to the VM. + * @param pUVM The user mode VM handle. * @param hDbgAs The address space. * @param pszFilename The map file. * @param pszModName The module name. If NULL, then then the file name @@ -842,40 +1000,28 @@ static DECLCALLBACK(int) dbgfR3AsLoadMapOpen(const char *pszFilename, void *pvUs * /proc/kallsyms. * @param fFlags Flags reserved for future extensions, must be 0. */ -VMMR3DECL(int) DBGFR3AsLoadMap(PVM pVM, RTDBGAS hDbgAs, const char *pszFilename, const char *pszModName, +VMMR3DECL(int) DBGFR3AsLoadMap(PUVM pUVM, RTDBGAS hDbgAs, const char *pszFilename, const char *pszModName, PCDBGFADDRESS pModAddress, RTDBGSEGIDX iModSeg, RTGCUINTPTR uSubtrahend, uint32_t fFlags) { /* * Validate input */ + UVM_ASSERT_VALID_EXT_RETURN(pUVM, VERR_INVALID_VM_HANDLE); AssertPtrReturn(pszFilename, VERR_INVALID_POINTER); AssertReturn(*pszFilename, VERR_INVALID_PARAMETER); - AssertReturn(DBGFR3AddrIsValid(pVM, pModAddress), VERR_INVALID_PARAMETER); + AssertReturn(DBGFR3AddrIsValid(pUVM, pModAddress), VERR_INVALID_PARAMETER); AssertReturn(fFlags == 0, VERR_INVALID_PARAMETER); - RTDBGAS hRealAS = DBGFR3AsResolveAndRetain(pVM, hDbgAs); + RTDBGAS hRealAS = DBGFR3AsResolveAndRetain(pUVM, hDbgAs); if (hRealAS == NIL_RTDBGAS) return VERR_INVALID_HANDLE; - /* - * Do the work. - */ - DBGFR3ASLOADOPENDATA Data; - Data.pszModName = pszModName; - Data.uSubtrahend = uSubtrahend; - Data.fFlags = 0; - Data.hMod = NIL_RTDBGMOD; - int rc = dbgfR3AsSearchCfgPath(pVM, pszFilename, "MapPath", dbgfR3AsLoadMapOpen, &Data); - if (RT_FAILURE(rc)) - rc = dbgfR3AsSearchEnvPath(pszFilename, "VBOXDBG_MAP_PATH", dbgfR3AsLoadMapOpen, &Data); - if (RT_FAILURE(rc)) - rc = dbgfR3AsSearchCfgPath(pVM, pszFilename, "Path", dbgfR3AsLoadMapOpen, &Data); - if (RT_FAILURE(rc)) - rc = dbgfR3AsSearchEnvPath(pszFilename, "VBOXDBG_PATH", dbgfR3AsLoadMapOpen, &Data); + RTDBGMOD hDbgMod; + int rc = RTDbgModCreateFromMap(&hDbgMod, pszFilename, pszModName, uSubtrahend, pUVM->dbgf.s.hDbgCfg); if (RT_SUCCESS(rc)) { - rc = DBGFR3AsLinkModule(pVM, hRealAS, Data.hMod, pModAddress, iModSeg, 0); + rc = DBGFR3AsLinkModule(pUVM, hRealAS, hDbgMod, pModAddress, iModSeg, 0); if (RT_FAILURE(rc)) - RTDbgModRelease(Data.hMod); + RTDbgModRelease(hDbgMod); } RTDbgAsRelease(hRealAS); @@ -887,21 +1033,22 @@ VMMR3DECL(int) DBGFR3AsLoadMap(PVM pVM, RTDBGAS hDbgAs, const char *pszFilename, * Wrapper around RTDbgAsModuleLink, RTDbgAsModuleLinkSeg and DBGFR3AsResolve. * * @returns VBox status code. - * @param pVM Pointer to the VM. + * @param pUVM The user mode VM handle. * @param hDbgAs The address space handle. * @param hMod The module handle. * @param pModAddress The link address. * @param iModSeg The segment to link, NIL_RTDBGSEGIDX for the entire image. * @param fFlags Flags to pass to the link functions, see RTDBGASLINK_FLAGS_*. */ -VMMR3DECL(int) DBGFR3AsLinkModule(PVM pVM, RTDBGAS hDbgAs, RTDBGMOD hMod, PCDBGFADDRESS pModAddress, RTDBGSEGIDX iModSeg, uint32_t fFlags) +VMMR3DECL(int) DBGFR3AsLinkModule(PUVM pUVM, RTDBGAS hDbgAs, RTDBGMOD hMod, PCDBGFADDRESS pModAddress, + RTDBGSEGIDX iModSeg, uint32_t fFlags) { /* * Input validation. */ - VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE); - AssertReturn(DBGFR3AddrIsValid(pVM, pModAddress), VERR_INVALID_PARAMETER); - RTDBGAS hRealAS = DBGFR3AsResolveAndRetain(pVM, hDbgAs); + UVM_ASSERT_VALID_EXT_RETURN(pUVM, VERR_INVALID_VM_HANDLE); + AssertReturn(DBGFR3AddrIsValid(pUVM, pModAddress), VERR_INVALID_PARAMETER); + RTDBGAS hRealAS = DBGFR3AsResolveAndRetain(pUVM, hDbgAs); if (hRealAS == NIL_RTDBGAS) return VERR_INVALID_HANDLE; @@ -920,6 +1067,54 @@ VMMR3DECL(int) DBGFR3AsLinkModule(PVM pVM, RTDBGAS hDbgAs, RTDBGMOD hMod, PCDBGF /** + * Wrapper around RTDbgAsModuleByName and RTDbgAsModuleUnlink. + * + * Unlinks all mappings matching the given module name. + * + * @returns VBox status code. + * @param pUVM The user mode VM handle. + * @param hDbgAs The address space handle. + * @param pszModName The name of the module to unlink. + */ +VMMR3DECL(int) DBGFR3AsUnlinkModuleByName(PUVM pUVM, RTDBGAS hDbgAs, const char *pszModName) +{ + /* + * Input validation. + */ + UVM_ASSERT_VALID_EXT_RETURN(pUVM, VERR_INVALID_VM_HANDLE); + RTDBGAS hRealAS = DBGFR3AsResolveAndRetain(pUVM, hDbgAs); + if (hRealAS == NIL_RTDBGAS) + return VERR_INVALID_HANDLE; + + /* + * Do the job. + */ + RTDBGMOD hMod; + int rc = RTDbgAsModuleByName(hRealAS, pszModName, 0, &hMod); + if (RT_SUCCESS(rc)) + { + for (;;) + { + rc = RTDbgAsModuleUnlink(hRealAS, hMod); + RTDbgModRelease(hMod); + if (RT_FAILURE(rc)) + break; + rc = RTDbgAsModuleByName(hRealAS, pszModName, 0, &hMod); + if (RT_FAILURE_NP(rc)) + { + if (rc == VERR_NOT_FOUND) + rc = VINF_SUCCESS; + break; + } + } + } + + RTDbgAsRelease(hRealAS); + return rc; +} + + +/** * Adds the module name to the symbol name. * * @param pSymbol The symbol info (in/out). @@ -966,17 +1161,18 @@ static void dbgfR3AsSymbolConvert(PRTDBGSYMBOL pSymbol, PCDBGFSYMBOL pDbgfSym) * * @returns VBox status code. See RTDbgAsSymbolByAddr. * - * @param pVM Pointer to the VM. - * @param hDbgAs The address space handle. - * @param pAddress The address to lookup. - * @param poffDisp Where to return the distance between the - * returned symbol and pAddress. Optional. - * @param pSymbol Where to return the symbol information. - * The returned symbol name will be prefixed by - * the module name as far as space allows. - * @param phMod Where to return the module handle. Optional. + * @param pUVM The user mode VM handle. + * @param hDbgAs The address space handle. + * @param pAddress The address to lookup. + * @param fFlags One of the RTDBGSYMADDR_FLAGS_XXX flags. + * @param poffDisp Where to return the distance between the returned + * symbol and pAddress. Optional. + * @param pSymbol Where to return the symbol information. The returned + * symbol name will be prefixed by the module name as + * far as space allows. + * @param phMod Where to return the module handle. Optional. */ -VMMR3DECL(int) DBGFR3AsSymbolByAddr(PVM pVM, RTDBGAS hDbgAs, PCDBGFADDRESS pAddress, +VMMR3DECL(int) DBGFR3AsSymbolByAddr(PUVM pUVM, RTDBGAS hDbgAs, PCDBGFADDRESS pAddress, uint32_t fFlags, PRTGCINTPTR poffDisp, PRTDBGSYMBOL pSymbol, PRTDBGMOD phMod) { /* @@ -984,17 +1180,17 @@ VMMR3DECL(int) DBGFR3AsSymbolByAddr(PVM pVM, RTDBGAS hDbgAs, PCDBGFADDRESS pAddr */ if (hDbgAs == DBGF_AS_RC_AND_GC_GLOBAL) { - int rc = DBGFR3AsSymbolByAddr(pVM, DBGF_AS_RC, pAddress, poffDisp, pSymbol, phMod); + int rc = DBGFR3AsSymbolByAddr(pUVM, DBGF_AS_RC, pAddress, fFlags, poffDisp, pSymbol, phMod); if (RT_FAILURE(rc)) - rc = DBGFR3AsSymbolByAddr(pVM, DBGF_AS_GLOBAL, pAddress, poffDisp, pSymbol, phMod); + rc = DBGFR3AsSymbolByAddr(pUVM, DBGF_AS_GLOBAL, pAddress, fFlags, poffDisp, pSymbol, phMod); return rc; } /* * Input validation. */ - VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE); - AssertReturn(DBGFR3AddrIsValid(pVM, pAddress), VERR_INVALID_PARAMETER); + UVM_ASSERT_VALID_EXT_RETURN(pUVM, VERR_INVALID_VM_HANDLE); + AssertReturn(DBGFR3AddrIsValid(pUVM, pAddress), VERR_INVALID_PARAMETER); AssertPtrNullReturn(poffDisp, VERR_INVALID_POINTER); AssertPtrReturn(pSymbol, VERR_INVALID_POINTER); AssertPtrNullReturn(phMod, VERR_INVALID_POINTER); @@ -1002,7 +1198,7 @@ VMMR3DECL(int) DBGFR3AsSymbolByAddr(PVM pVM, RTDBGAS hDbgAs, PCDBGFADDRESS pAddr *poffDisp = 0; if (phMod) *phMod = NIL_RTDBGMOD; - RTDBGAS hRealAS = DBGFR3AsResolveAndRetain(pVM, hDbgAs); + RTDBGAS hRealAS = DBGFR3AsResolveAndRetain(pUVM, hDbgAs); if (hRealAS == NIL_RTDBGAS) return VERR_INVALID_HANDLE; @@ -1010,49 +1206,13 @@ VMMR3DECL(int) DBGFR3AsSymbolByAddr(PVM pVM, RTDBGAS hDbgAs, PCDBGFADDRESS pAddr * Do the lookup. */ RTDBGMOD hMod; - int rc = RTDbgAsSymbolByAddr(hRealAS, pAddress->FlatPtr, RTDBGSYMADDR_FLAGS_LESS_OR_EQUAL, poffDisp, pSymbol, &hMod); + int rc = RTDbgAsSymbolByAddr(hRealAS, pAddress->FlatPtr, fFlags, poffDisp, pSymbol, &hMod); if (RT_SUCCESS(rc)) { dbgfR3AsSymbolJoinNames(pSymbol, hMod); if (!phMod) RTDbgModRelease(hMod); } - /* Temporary conversions. */ - else if (hDbgAs == DBGF_AS_GLOBAL) - { - DBGFSYMBOL DbgfSym; - rc = DBGFR3SymbolByAddr(pVM, pAddress->FlatPtr, poffDisp, &DbgfSym); - if (RT_SUCCESS(rc)) - dbgfR3AsSymbolConvert(pSymbol, &DbgfSym); - } - else if (hDbgAs == DBGF_AS_R0) - { - RTR0PTR R0PtrMod; - char szNearSym[260]; - RTR0PTR R0PtrNearSym; - RTR0PTR R0PtrNearSym2; - rc = PDMR3LdrQueryR0ModFromPC(pVM, pAddress->FlatPtr, - pSymbol->szName, sizeof(pSymbol->szName) / 2, &R0PtrMod, - &szNearSym[0], sizeof(szNearSym), &R0PtrNearSym, - NULL, 0, &R0PtrNearSym2); - if (RT_SUCCESS(rc)) - { - pSymbol->offSeg = pSymbol->Value = R0PtrNearSym; - pSymbol->cb = R0PtrNearSym2 > R0PtrNearSym ? R0PtrNearSym2 - R0PtrNearSym : 0; - pSymbol->iSeg = 0; - pSymbol->fFlags = 0; - pSymbol->iOrdinal = UINT32_MAX; - size_t offName = strlen(pSymbol->szName); - pSymbol->szName[offName++] = '!'; - size_t cchNearSym = strlen(szNearSym); - if (cchNearSym + offName >= sizeof(pSymbol->szName)) - cchNearSym = sizeof(pSymbol->szName) - offName - 1; - strncpy(&pSymbol->szName[offName], szNearSym, cchNearSym); - pSymbol->szName[offName + cchNearSym] = '\0'; - if (poffDisp) - *poffDisp = pAddress->FlatPtr - pSymbol->Value; - } - } return rc; } @@ -1065,16 +1225,18 @@ VMMR3DECL(int) DBGFR3AsSymbolByAddr(PVM pVM, RTDBGAS hDbgAs, PCDBGFADDRESS pAddr * RTDbgSymbolFree(). NULL is returned if not found or any error * occurs. * - * @param pVM Pointer to the VM. - * @param hDbgAs See DBGFR3AsSymbolByAddr. - * @param pAddress See DBGFR3AsSymbolByAddr. - * @param poffDisp See DBGFR3AsSymbolByAddr. - * @param phMod See DBGFR3AsSymbolByAddr. + * @param pUVM The user mode VM handle. + * @param hDbgAs See DBGFR3AsSymbolByAddr. + * @param pAddress See DBGFR3AsSymbolByAddr. + * @param fFlags See DBGFR3AsSymbolByAddr. + * @param poffDisp See DBGFR3AsSymbolByAddr. + * @param phMod See DBGFR3AsSymbolByAddr. */ -VMMR3DECL(PRTDBGSYMBOL) DBGFR3AsSymbolByAddrA(PVM pVM, RTDBGAS hDbgAs, PCDBGFADDRESS pAddress, PRTGCINTPTR poffDisp, PRTDBGMOD phMod) +VMMR3DECL(PRTDBGSYMBOL) DBGFR3AsSymbolByAddrA(PUVM pUVM, RTDBGAS hDbgAs, PCDBGFADDRESS pAddress, uint32_t fFlags, + PRTGCINTPTR poffDisp, PRTDBGMOD phMod) { RTDBGSYMBOL SymInfo; - int rc = DBGFR3AsSymbolByAddr(pVM, hDbgAs, pAddress, poffDisp, &SymInfo, phMod); + int rc = DBGFR3AsSymbolByAddr(pUVM, hDbgAs, pAddress, fFlags, poffDisp, &SymInfo, phMod); if (RT_SUCCESS(rc)) return RTDbgSymbolDup(&SymInfo); return NULL; @@ -1090,16 +1252,16 @@ VMMR3DECL(PRTDBGSYMBOL) DBGFR3AsSymbolByAddrA(PVM pVM, RTDBGAS hDbgAs, PCDBGFADD * * @returns VBox status code. See RTDbgAsSymbolByAddr. * - * @param pVM Pointer to the VM. - * @param hDbgAs The address space handle. - * @param pszSymbol The symbol to search for, maybe prefixed by a - * module pattern. - * @param pSymbol Where to return the symbol information. - * The returned symbol name will be prefixed by - * the module name as far as space allows. - * @param phMod Where to return the module handle. Optional. + * @param pUVM The user mode VM handle. + * @param hDbgAs The address space handle. + * @param pszSymbol The symbol to search for, maybe prefixed by a + * module pattern. + * @param pSymbol Where to return the symbol information. + * The returned symbol name will be prefixed by + * the module name as far as space allows. + * @param phMod Where to return the module handle. Optional. */ -VMMR3DECL(int) DBGFR3AsSymbolByName(PVM pVM, RTDBGAS hDbgAs, const char *pszSymbol, +VMMR3DECL(int) DBGFR3AsSymbolByName(PUVM pUVM, RTDBGAS hDbgAs, const char *pszSymbol, PRTDBGSYMBOL pSymbol, PRTDBGMOD phMod) { /* @@ -1107,21 +1269,21 @@ VMMR3DECL(int) DBGFR3AsSymbolByName(PVM pVM, RTDBGAS hDbgAs, const char *pszSymb */ if (hDbgAs == DBGF_AS_RC_AND_GC_GLOBAL) { - int rc = DBGFR3AsSymbolByName(pVM, DBGF_AS_RC, pszSymbol, pSymbol, phMod); + int rc = DBGFR3AsSymbolByName(pUVM, DBGF_AS_RC, pszSymbol, pSymbol, phMod); if (RT_FAILURE(rc)) - rc = DBGFR3AsSymbolByName(pVM, DBGF_AS_GLOBAL, pszSymbol, pSymbol, phMod); + rc = DBGFR3AsSymbolByName(pUVM, DBGF_AS_GLOBAL, pszSymbol, pSymbol, phMod); return rc; } /* * Input validation. */ - VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE); + UVM_ASSERT_VALID_EXT_RETURN(pUVM, VERR_INVALID_VM_HANDLE); AssertPtrReturn(pSymbol, VERR_INVALID_POINTER); AssertPtrNullReturn(phMod, VERR_INVALID_POINTER); if (phMod) *phMod = NIL_RTDBGMOD; - RTDBGAS hRealAS = DBGFR3AsResolveAndRetain(pVM, hDbgAs); + RTDBGAS hRealAS = DBGFR3AsResolveAndRetain(pUVM, hDbgAs); if (hRealAS == NIL_RTDBGAS) return VERR_INVALID_HANDLE; @@ -1137,15 +1299,55 @@ VMMR3DECL(int) DBGFR3AsSymbolByName(PVM pVM, RTDBGAS hDbgAs, const char *pszSymb if (!phMod) RTDbgModRelease(hMod); } - /* Temporary conversion. */ - else if (hDbgAs == DBGF_AS_GLOBAL) + + return rc; +} + + +VMMR3DECL(int) DBGFR3AsLineByAddr(PUVM pUVM, RTDBGAS hDbgAs, PCDBGFADDRESS pAddress, + PRTGCINTPTR poffDisp, PRTDBGLINE pLine, PRTDBGMOD phMod) +{ + /* + * Implement the special address space aliases the lazy way. + */ + if (hDbgAs == DBGF_AS_RC_AND_GC_GLOBAL) { - DBGFSYMBOL DbgfSym; - rc = DBGFR3SymbolByName(pVM, pszSymbol, &DbgfSym); - if (RT_SUCCESS(rc)) - dbgfR3AsSymbolConvert(pSymbol, &DbgfSym); + int rc = DBGFR3AsLineByAddr(pUVM, DBGF_AS_RC, pAddress, poffDisp, pLine, phMod); + if (RT_FAILURE(rc)) + rc = DBGFR3AsLineByAddr(pUVM, DBGF_AS_GLOBAL, pAddress, poffDisp, pLine, phMod); + return rc; } - return rc; + /* + * Input validation. + */ + UVM_ASSERT_VALID_EXT_RETURN(pUVM, VERR_INVALID_VM_HANDLE); + AssertReturn(DBGFR3AddrIsValid(pUVM, pAddress), VERR_INVALID_PARAMETER); + AssertPtrNullReturn(poffDisp, VERR_INVALID_POINTER); + AssertPtrReturn(pLine, VERR_INVALID_POINTER); + AssertPtrNullReturn(phMod, VERR_INVALID_POINTER); + if (poffDisp) + *poffDisp = 0; + if (phMod) + *phMod = NIL_RTDBGMOD; + RTDBGAS hRealAS = DBGFR3AsResolveAndRetain(pUVM, hDbgAs); + if (hRealAS == NIL_RTDBGAS) + return VERR_INVALID_HANDLE; + + /* + * Do the lookup. + */ + return RTDbgAsLineByAddr(hRealAS, pAddress->FlatPtr, poffDisp, pLine, phMod); +} + + +VMMR3DECL(PRTDBGLINE) DBGFR3AsLineByAddrA(PUVM pUVM, RTDBGAS hDbgAs, PCDBGFADDRESS pAddress, + PRTGCINTPTR poffDisp, PRTDBGMOD phMod) +{ + RTDBGLINE Line; + int rc = DBGFR3AsLineByAddr(pUVM, hDbgAs, pAddress, poffDisp, &Line, phMod); + if (RT_SUCCESS(rc)) + return RTDbgLineDup(&Line); + return NULL; } |
