/** * Delete an address space from the database. * * The address space must not be engaged as any of the standard aliases. * * @returns VBox status code. * @retval VERR_SHARING_VIOLATION if in use as an alias. * @retval VERR_NOT_FOUND if not found in the address space database. * * @param pUVM The user mode VM handle. * @param hDbgAs The address space handle. Aliases are not allowed. */ 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. */ UVM_ASSERT_VALID_EXT_RETURN(pUVM, VERR_INVALID_VM_HANDLE); if (hDbgAs == NIL_RTDBGAS) return VINF_SUCCESS; uint32_t cRefs = RTDbgAsRetain(hDbgAs); if (cRefs == UINT32_MAX) return VERR_INVALID_HANDLE; RTDbgAsRelease(hDbgAs); DBGF_AS_DB_LOCK_WRITE(pUVM); /* * You cannot delete any of the aliases. */ 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(pUVM); return VERR_SHARING_VIOLATION; } /* * Ok, try remove it from the database. */ PDBGFASDBNODE pDbNode = (PDBGFASDBNODE)RTAvlPVRemove(&pUVM->dbgf.s.AsHandleTree, hDbgAs); if (!pDbNode) { DBGF_AS_DB_UNLOCK_WRITE(pUVM); return VERR_NOT_FOUND; } RTStrSpaceRemove(&pUVM->dbgf.s.AsNameSpace, pDbNode->NameCore.pszString); if (pDbNode->PidCore.Key != NIL_RTPROCESS) RTAvlU32Remove(&pUVM->dbgf.s.AsPidTree, pDbNode->PidCore.Key); DBGF_AS_DB_UNLOCK_WRITE(pUVM); /* * Free the resources. */ RTDbgAsRelease(hDbgAs); MMR3HeapFree(pDbNode); return VINF_SUCCESS; }
/** * Lazily populates the specified address space. * * @param pUVM The user mode VM handle. * @param hAlias The alias. */ static void dbgfR3AsLazyPopulate(PUVM pUVM, RTDBGAS hAlias) { DBGF_AS_DB_LOCK_WRITE(pUVM); uintptr_t iAlias = DBGF_AS_ALIAS_2_INDEX(hAlias); if (!pUVM->dbgf.s.afAsAliasPopuplated[iAlias]) { 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. */ } pUVM->dbgf.s.afAsAliasPopuplated[iAlias] = true; } DBGF_AS_DB_UNLOCK_WRITE(pUVM); }
/** * Changes an alias to point to a new address space. * * Not all the aliases can be changed, currently it's only DBGF_AS_GLOBAL * and DBGF_AS_KERNEL. * * @returns VBox status code. * @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(PUVM pUVM, RTDBGAS hAlias, RTDBGAS hAliasFor) { /* * Input validation. */ 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(pUVM, hAliasFor); if (hRealAliasFor == NIL_RTDBGAS) return VERR_INVALID_HANDLE; /* * Make sure the handle has is already in the database. */ int rc = VERR_NOT_FOUND; 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(&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(pUVM); return rc; }
/** * Adds the address space to the database. * * @returns VBox status code. * @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(PUVM pUVM, RTDBGAS hDbgAs, RTPROCESS ProcId) { /* * Input validation. */ UVM_ASSERT_VALID_EXT_RETURN(pUVM, VERR_INVALID_VM_HANDLE); const char *pszName = RTDbgAsName(hDbgAs); if (!pszName) return VERR_INVALID_HANDLE; uint32_t cRefs = RTDbgAsRetain(hDbgAs); if (cRefs == UINT32_MAX) return VERR_INVALID_HANDLE; /* * Allocate a tracking node. */ int rc = VERR_NO_MEMORY; 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(pUVM); if (RTStrSpaceInsert(&pUVM->dbgf.s.AsNameSpace, &pDbNode->NameCore)) { if (RTAvlPVInsert(&pUVM->dbgf.s.AsHandleTree, &pDbNode->HandleCore)) { DBGF_AS_DB_UNLOCK_WRITE(pUVM); return VINF_SUCCESS; } /* bail out */ RTStrSpaceRemove(&pUVM->dbgf.s.AsNameSpace, pszName); } DBGF_AS_DB_UNLOCK_WRITE(pUVM); MMR3HeapFree(pDbNode); } RTDbgAsRelease(hDbgAs); return rc; }
/** * Lazily populates the specified address space. * * @param pUVM The user mode VM handle. * @param hAlias The alias. */ static void dbgfR3AsLazyPopulate(PUVM pUVM, RTDBGAS hAlias) { DBGF_AS_DB_LOCK_WRITE(pUVM); uintptr_t iAlias = DBGF_AS_ALIAS_2_INDEX(hAlias); if (!pUVM->dbgf.s.afAsAliasPopuplated[iAlias]) { RTDBGAS hAs = pUVM->dbgf.s.ahAsAliases[iAlias]; if (hAlias == DBGF_AS_R0 && pUVM->pVM) PDMR3LdrEnumModules(pUVM->pVM, dbgfR3AsLazyPopulateR0Callback, hAs); /** @todo what do we do about DBGF_AS_RC? */ pUVM->dbgf.s.afAsAliasPopuplated[iAlias] = true; } DBGF_AS_DB_UNLOCK_WRITE(pUVM); }