/** * Duplicates a line. * * @returns VBox status code. * @param pVM The VM handle. * @param pLine The line to duplicate. */ static PDBGFLINE dbgfR3LineDup(PVM pVM, PCDBGFLINE pLine) { size_t cb = strlen(pLine->szFilename) + RT_OFFSETOF(DBGFLINE, szFilename[1]); PDBGFLINE pDup = (PDBGFLINE)MMR3HeapAlloc(pVM, MM_TAG_DBGF_LINE_DUP, cb); if (pDup) memcpy(pDup, pLine, cb); return pDup; }
/** * Handle registration worker. * This allocates the structure, initializes the common fields and inserts into the list. * Upon successful return the we're inside the crit sect and the caller must leave it. * * @returns VBox status code. * @param pVM Pointer to the VM. * @param pszName The identifier of the info. * @param pszDesc The description of the info and any arguments the handler may take. * @param fFlags The flags. * @param ppInfo Where to store the created */ static int dbgfR3InfoRegister(PVM pVM, const char *pszName, const char *pszDesc, uint32_t fFlags, PDBGFINFO *ppInfo) { /* * Validate. */ AssertPtrReturn(pszName, VERR_INVALID_POINTER); AssertReturn(*pszName, VERR_INVALID_PARAMETER); AssertPtrReturn(pszDesc, VERR_INVALID_POINTER); AssertMsgReturn(!(fFlags & ~(DBGFINFO_FLAGS_RUN_ON_EMT)), ("fFlags=%#x\n", fFlags), VERR_INVALID_PARAMETER); /* * Allocate and initialize. */ int rc; size_t cchName = strlen(pszName) + 1; PDBGFINFO pInfo = (PDBGFINFO)MMR3HeapAlloc(pVM, MM_TAG_DBGF_INFO, RT_OFFSETOF(DBGFINFO, szName[cchName])); if (pInfo) { pInfo->enmType = DBGFINFOTYPE_INVALID; pInfo->fFlags = fFlags; pInfo->pszDesc = pszDesc; pInfo->cchName = cchName - 1; memcpy(pInfo->szName, pszName, cchName); /* lazy init */ rc = VINF_SUCCESS; if (!RTCritSectIsInitialized(&pVM->dbgf.s.InfoCritSect)) rc = dbgfR3InfoInit(pVM); if (RT_SUCCESS(rc)) { /* * Insert in alphabetical order. */ rc = RTCritSectEnter(&pVM->dbgf.s.InfoCritSect); AssertRC(rc); PDBGFINFO pPrev = NULL; PDBGFINFO pCur; for (pCur = pVM->dbgf.s.pInfoFirst; pCur; pPrev = pCur, pCur = pCur->pNext) if (strcmp(pszName, pCur->szName) < 0) break; pInfo->pNext = pCur; if (pPrev) pPrev->pNext = pInfo; else pVM->dbgf.s.pInfoFirst = pInfo; *ppInfo = pInfo; return VINF_SUCCESS; } MMR3HeapFree(pInfo); } else rc = VERR_NO_MEMORY; return rc; }
/** * Initializes the symbol tree. */ static int dbgfR3SymbolInit(PVM pVM) { PDBGFSYM pSym = (PDBGFSYM)MMR3HeapAlloc(pVM, MM_TAG_DBGF_SYMBOL, sizeof(*pSym)); if (pSym) { pSym->Core.Key = 0; pSym->Core.KeyLast = ~0; pSym->pModule = NULL; pSym->szName[0] = '\0'; if (RTAvlrGCPtrInsert(&pVM->dbgf.s.SymbolTree, &pSym->Core)) return VINF_SUCCESS; AssertReleaseMsgFailed(("Failed to insert %RGv-%RGv!\n", pSym->Core.Key, pSym->Core.KeyLast)); return VERR_INTERNAL_ERROR; } return VERR_NO_MEMORY; }
/** * 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. */ VMMR3DECL(int) DBGFR3AsAdd(PVM pVM, RTDBGAS hDbgAs, RTPROCESS ProcId) { /* * Input validation. */ VM_ASSERT_VALID_EXT_RETURN(pVM, 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)MMR3HeapAlloc(pVM, 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)) { if (RTAvlPVInsert(&pVM->dbgf.s.AsHandleTree, &pDbNode->HandleCore)) { DBGF_AS_DB_UNLOCK_WRITE(pVM); return VINF_SUCCESS; } /* bail out */ RTStrSpaceRemove(&pVM->dbgf.s.AsNameSpace, pszName); } DBGF_AS_DB_UNLOCK_WRITE(pVM); MMR3HeapFree(pDbNode); } RTDbgAsRelease(hDbgAs); return rc; }
/** * Insert a record into the symbol tree. */ static int dbgfR3SymbolInsert(PVM pVM, const char *pszName, RTGCPTR Address, size_t cb, PDBGFMOD pModule) { /* * Make the address space node. */ size_t cchName = strlen(pszName) + 1; PDBGFSYM pSym = (PDBGFSYM)MMR3HeapAlloc(pVM, MM_TAG_DBGF_SYMBOL, RT_OFFSETOF(DBGFSYM, szName[cchName])); if (pSym) { pSym->Core.Key = Address; pSym->Core.KeyLast = Address + cb; pSym->pModule = pModule; memcpy(pSym->szName, pszName, cchName); PDBGFSYM pOld = (PDBGFSYM)RTAvlrGCPtrRangeGet(&pVM->dbgf.s.SymbolTree, (RTGCPTR)Address); if (pOld) { pSym->Core.KeyLast = pOld->Core.KeyLast; if (pOld->Core.Key == pSym->Core.Key) { pOld = (PDBGFSYM)RTAvlrGCPtrRemove(&pVM->dbgf.s.SymbolTree, (RTGCPTR)Address); AssertRelease(pOld); MMR3HeapFree(pOld); } else pOld->Core.KeyLast = Address - 1; if (RTAvlrGCPtrInsert(&pVM->dbgf.s.SymbolTree, &pSym->Core)) { /* * Make the name space node. */ PDBGFSYMSPACE pName = (PDBGFSYMSPACE)RTStrSpaceGet(pVM->dbgf.s.pSymbolSpace, pszName); if (!pName) { /* make new symbol space node. */ pName = (PDBGFSYMSPACE)MMR3HeapAlloc(pVM, MM_TAG_DBGF_SYMBOL, sizeof(*pName) + cchName); if (pName) { pName->Core.pszString = (char *)memcpy(pName + 1, pszName, cchName); pName->pSym = pSym; if (RTStrSpaceInsert(pVM->dbgf.s.pSymbolSpace, &pName->Core)) return VINF_SUCCESS; } else return VINF_SUCCESS; } else { /* Add to existing symbol name. */ pSym->pNext = pName->pSym; pName->pSym = pSym; return VINF_SUCCESS; } } AssertReleaseMsgFailed(("Failed to insert %RGv-%RGv!\n", pSym->Core.Key, pSym->Core.KeyLast)); } else AssertMsgFailed(("pOld! %RGv %s\n", pSym->Core.Key, pszName)); return VERR_INTERNAL_ERROR; } return VERR_NO_MEMORY; }