/** * Convenience function that combines RTDbgSymbolDup and DBGFR3AsSymbolByAddr. * * @returns Pointer to the symbol on success. This must be free using * RTDbgSymbolFree(). NULL is returned if not found or any error * occurs. * * @param pUVM The user mode VM handle. * @param hDbgAs See DBGFR3AsSymbolByAddr. * @param pAddress See DBGFR3AsSymbolByAddr. * @param poffDisp See DBGFR3AsSymbolByAddr. * @param phMod See DBGFR3AsSymbolByAddr. */ VMMR3DECL(PRTDBGSYMBOL) DBGFR3AsSymbolByAddrA(PUVM pUVM, RTDBGAS hDbgAs, PCDBGFADDRESS pAddress, PRTGCINTPTR poffDisp, PRTDBGMOD phMod) { RTDBGSYMBOL SymInfo; int rc = DBGFR3AsSymbolByAddr(pUVM, hDbgAs, pAddress, poffDisp, &SymInfo, phMod); if (RT_SUCCESS(rc)) return RTDbgSymbolDup(&SymInfo); return NULL; }
/** * Query a symbol by address. * * The returned symbol is the one we consider closes to the specified address. * * @returns VBox status code. See RTDbgAsSymbolByAddr. * * @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(PUVM pUVM, RTDBGAS hDbgAs, PCDBGFADDRESS pAddress, uint32_t fFlags, PRTGCINTPTR poffDisp, PRTDBGSYMBOL pSymbol, PRTDBGMOD phMod) { /* * Implement the special address space aliases the lazy way. */ if (hDbgAs == DBGF_AS_RC_AND_GC_GLOBAL) { int rc = DBGFR3AsSymbolByAddr(pUVM, DBGF_AS_RC, pAddress, fFlags, poffDisp, pSymbol, phMod); if (RT_FAILURE(rc)) rc = DBGFR3AsSymbolByAddr(pUVM, DBGF_AS_GLOBAL, pAddress, fFlags, poffDisp, pSymbol, phMod); 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(pSymbol, 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. */ RTDBGMOD hMod; int rc = RTDbgAsSymbolByAddr(hRealAS, pAddress->FlatPtr, fFlags, poffDisp, pSymbol, &hMod); if (RT_SUCCESS(rc)) { dbgfR3AsSymbolJoinNames(pSymbol, hMod); if (!phMod) RTDbgModRelease(hMod); } return rc; }
/** * Called when a new patch is added or when first populating the address space. * * @param pVM The cross context VM structure. * @param pPatchRec The patch record. */ void patmR3DbgAddPatch(PVM pVM, PPATMPATCHREC pPatchRec) { if ( pVM->patm.s.hDbgModPatchMem != NIL_RTDBGMOD && pPatchRec->patch.pPatchBlockOffset > 0 && !(pPatchRec->patch.flags & PATMFL_GLOBAL_FUNCTIONS)) { /** @todo find a cheap way of checking whether we've already added the patch. * Using a flag would be nice, except I don't want to consider saved * state considerations right now (I don't recall if we're still * depending on structure layout there or not). */ char szName[256]; size_t off = patmR3DbgDescribePatchAsSymbol(pPatchRec, szName, sizeof(szName)); /* If we have a symbol near the guest address, append that. */ if (off + 8 <= sizeof(szName)) { RTDBGSYMBOL Symbol; RTGCINTPTR offDisp; DBGFADDRESS Addr; int rc = DBGFR3AsSymbolByAddr(pVM->pUVM, DBGF_AS_GLOBAL, DBGFR3AddrFromFlat(pVM->pUVM, &Addr, pPatchRec->patch.pPrivInstrGC), RTDBGSYMADDR_FLAGS_LESS_OR_EQUAL | RTDBGSYMADDR_FLAGS_SKIP_ABS_IN_DEFERRED, &offDisp, &Symbol, NULL /*phMod*/); if (RT_SUCCESS(rc)) { szName[off++] = '_'; szName[off++] = '_'; RTStrCopy(&szName[off], sizeof(szName) - off, Symbol.szName); } } /* Add it (may fail due to enable/disable patches). */ RTDbgModSymbolAdd(pVM->patm.s.hDbgModPatchMem, szName, 0 /*iSeg*/, pPatchRec->patch.pPatchBlockOffset, pPatchRec->patch.cbPatchBlockSize, 0 /*fFlags*/, NULL /*piOrdinal*/); } }
/** * Query a symbol by address. * * The returned symbol is the one we consider closes to the specified address. * * @returns VBox status code. See RTDbgAsSymbolByAddr. * * @param pUVM The user mode VM handle. * @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. */ VMMR3DECL(int) DBGFR3AsSymbolByAddr(PUVM pUVM, RTDBGAS hDbgAs, PCDBGFADDRESS pAddress, PRTGCINTPTR poffDisp, PRTDBGSYMBOL pSymbol, PRTDBGMOD phMod) { /* * Implement the special address space aliases the lazy way. */ if (hDbgAs == DBGF_AS_RC_AND_GC_GLOBAL) { int rc = DBGFR3AsSymbolByAddr(pUVM, DBGF_AS_RC, pAddress, poffDisp, pSymbol, phMod); if (RT_FAILURE(rc)) rc = DBGFR3AsSymbolByAddr(pUVM, DBGF_AS_GLOBAL, pAddress, poffDisp, pSymbol, phMod); 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(pSymbol, 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. */ RTDBGMOD hMod; int rc = RTDbgAsSymbolByAddr(hRealAS, pAddress->FlatPtr, RTDBGSYMADDR_FLAGS_LESS_OR_EQUAL, 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(pUVM->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; VM_ASSERT_VALID_EXT_RETURN(pUVM->pVM, VERR_INVALID_VM_HANDLE); rc = PDMR3LdrQueryR0ModFromPC(pUVM->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; }