Changeset 41117 in vbox for trunk/src/VBox/HostDrivers/Support
- Timestamp:
- May 2, 2012 2:22:29 PM (13 years ago)
- svn:sync-xref-src-repo-rev:
- 77725
- Location:
- trunk/src/VBox/HostDrivers/Support
- Files:
-
- 1 added
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/HostDrivers/Support/Makefile.kmk
r41092 r41117 87 87 SUPLib.cpp \ 88 88 SUPLibSem.cpp \ 89 SUPLibTracerA.asm \ 89 90 SUPR3HardenedIPRT.cpp \ 90 91 SUPR3HardenedVerify.cpp \ -
trunk/src/VBox/HostDrivers/Support/SUPDrv.c
r41068 r41117 697 697 /*pSession->uTracerData = 0;*/ 698 698 pSession->hTracerCaller = NIL_RTNATIVETHREAD; 699 RTListInit(&pSession->TpProviders); 700 /*pSession->cTpProviders = 0;*/ 701 /*pSession->cTpProbesFiring = 0;*/ 702 RTListInit(&pSession->TpUmods); 703 /*RT_ZERO(pSession->apTpLookupTable);*/ 699 704 700 705 VBOXDRV_SESSION_CREATE(pSession, fUser); … … 1794 1799 PSUPTRACERUMODREG pReq = (PSUPTRACERUMODREG)pReqHdr; 1795 1800 REQ_CHECK_SIZES(SUP_IOCTL_TRACER_UMOD_REG); 1801 if (!RTStrEnd(pReq->u.In.szName, sizeof(pReq->u.In.szName))) 1802 return VERR_INVALID_PARAMETER; 1796 1803 1797 1804 /* execute */ 1798 pReqHdr->rc = supdrvIOCtl_TracerUmodRegister(pDevExt, pSession, pReq->u.In.pVtgHdr, pReq->u.In.szName, pReq->u.In.fFlags); 1805 pReqHdr->rc = supdrvIOCtl_TracerUmodRegister(pDevExt, pSession, 1806 pReq->u.In.R3PtrVtgHdr, pReq->u.In.uVtgHdrAddr, 1807 pReq->u.In.R3PtrStrTab, pReq->u.In.cbStrTab, 1808 pReq->u.In.szName, pReq->u.In.fFlags); 1799 1809 return 0; 1800 1810 } … … 1808 1818 /* execute */ 1809 1819 pReqHdr->rc = supdrvIOCtl_TracerUmodDeregister(pDevExt, pSession, pReq->u.In.pVtgHdr); 1820 return 0; 1821 } 1822 1823 case SUP_CTL_CODE_NO_SIZE(SUP_IOCTL_TRACER_UMOD_FIRE_PROBE): 1824 { 1825 /* validate */ 1826 PSUPTRACERUMODFIREPROBE pReq = (PSUPTRACERUMODFIREPROBE)pReqHdr; 1827 REQ_CHECK_SIZES(SUP_IOCTL_TRACER_UMOD_FIRE_PROBE); 1828 1829 supdrvIOCtl_TracerUmodProbeFire(pDevExt, pSession, &pReq->u.In); 1830 pReqHdr->rc = VINF_SUCCESS; 1810 1831 return 0; 1811 1832 } -
trunk/src/VBox/HostDrivers/Support/SUPDrvIOC.h
r40982 r41117 32 32 */ 33 33 #include <iprt/types.h> 34 #include <VBox/sup.h> 34 35 35 36 /* … … 193 194 * - Remove RTSpinlockReleaseNoInts. 194 195 */ 195 #define SUPDRV_IOC_VERSION 0x001a000 1196 #define SUPDRV_IOC_VERSION 0x001a0002 196 197 197 198 /** SUP_IOCTL_COOKIE. */ … … 1266 1267 struct 1267 1268 { 1268 /** Pointer to the VTG header. */ 1269 RTR3PTR pVtgHdr; 1269 /** The address at which the VTG header actually resides. 1270 * This will differ from R3PtrVtgHdr for raw-mode context 1271 * modules. */ 1272 RTUINTPTR uVtgHdrAddr; 1273 /** The ring-3 pointer of the VTG header. */ 1274 RTR3PTR R3PtrVtgHdr; 1275 /** The ring-3 pointer of the probe location string table. */ 1276 RTR3PTR R3PtrStrTab; 1277 /** The size of the string table. */ 1278 uint32_t cbStrTab; 1270 1279 /** Future flags, MBZ. */ 1271 1280 uint32_t fFlags; … … 1303 1312 1304 1313 1314 /** @name SUP_IOCTL_TRACER_UMOD_FIRE_PROBE 1315 * Fire a probe in a user tracepoint module. 1316 * 1317 * @{ 1318 */ 1319 #define SUP_IOCTL_TRACER_UMOD_FIRE_PROBE SUP_CTL_CODE_SIZE(33, SUP_IOCTL_TRACER_UMOD_FIRE_PROBE_SIZE) 1320 #define SUP_IOCTL_TRACER_UMOD_FIRE_PROBE_SIZE sizeof(SUPTRACERUMODFIREPROBE) 1321 #define SUP_IOCTL_TRACER_UMOD_FIRE_PROBE_SIZE_IN sizeof(SUPTRACERUMODFIREPROBE) 1322 #define SUP_IOCTL_TRACER_UMOD_FIRE_PROBE_SIZE_OUT sizeof(SUPREQHDR) 1323 typedef struct SUPTRACERUMODFIREPROBE 1324 { 1325 /** The header. */ 1326 SUPREQHDR Hdr; 1327 union 1328 { 1329 SUPDRVTRACERUSRCTX In; 1330 } u; 1331 } SUPTRACERUMODFIREPROBE, *PSUPTRACERUMODFIREPROBE; 1332 /** @} */ 1333 1334 1305 1335 #pragma pack() /* paranoia */ 1306 1336 -
trunk/src/VBox/HostDrivers/Support/SUPDrvInternal.h
r41067 r41117 440 440 /** The thread currently actively talking to the tracer. (One at the time!) */ 441 441 RTNATIVETHREAD hTracerCaller; 442 /** List of tracepoint providers associated with the session 443 * (SUPDRVTPPROVIDER). */ 444 RTLISTANCHOR TpProviders; 445 /** The number of providers in TpProviders. */ 446 uint32_t cTpProviders; 447 /** The number of threads active in supdrvIOCtl_TracerUmodProbeFire or 448 * SUPR0TracerUmodProbeFire. */ 449 uint32_t volatile cTpProbesFiring; 450 /** User tracepoint modules (PSUPDRVTRACKERUMOD). */ 451 RTLISTANCHOR TpUmods; 452 /** The user tracepoint module lookup table. */ 453 struct SUPDRVTRACERUMOD *apTpLookupTable[32]; 442 454 #ifndef SUPDRV_AGNOSTIC 443 455 # if defined(RT_OS_DARWIN) … … 559 571 /** The number of session having opened the tracer currently. */ 560 572 uint32_t cTracerOpens; 573 /** The number of threads currently calling into the tracer. */ 574 uint32_t volatile cTracerCallers; 561 575 /** Set if the tracer is being unloaded. */ 562 576 bool fTracerUnloading; 577 /** Hash table for user tracer modules (SUPDRVVTGCOPY). */ 578 RTLISTANCHOR aTrackerUmodHash[128]; 563 579 564 580 /* … … 665 681 void VBOXCALL supdrvTracerModuleUnloading(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage); 666 682 void VBOXCALL supdrvTracerCleanupSession(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession); 683 int VBOXCALL supdrvIOCtl_TracerUmodRegister(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, 684 RTR3PTR R3PtrVtgHdr, RTUINTPTR uVtgHdrAddr, 685 RTR3PTR R3PtrStrTab, uint32_t cbStrTab, 686 const char *pszModName, uint32_t fFlags); 687 int VBOXCALL supdrvIOCtl_TracerUmodDeregister(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, RTR3PTR R3PtrVtgHdr); 688 void VBOXCALL supdrvIOCtl_TracerUmodProbeFire(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, PSUPDRVTRACERUSRCTX pCtx); 667 689 int VBOXCALL supdrvIOCtl_TracerOpen(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, uint32_t uCookie, uintptr_t uArg); 668 690 int VBOXCALL supdrvIOCtl_TracerClose(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession); … … 671 693 DECLASM(void) supdrvTracerProbeFireStub(void); 672 694 673 int VBOXCALL supdrvIOCtl_TracerUmodRegister(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, RTR3PTR pVtgHdr, const char *pszModName, uint32_t fFlags);674 int VBOXCALL supdrvIOCtl_TracerUmodDeregister(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, RTR3PTR pVtgHdr);675 void VBOXCALL supdrvIOCtl_TracerUmodProbeFire(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, PCSUPDRVTRACERUSRCTX pCtx);676 677 695 #ifdef VBOX_WITH_NATIVE_DTRACE 678 696 const SUPDRVTRACERREG * VBOXCALL supdrvDTraceInit(void); -
trunk/src/VBox/HostDrivers/Support/SUPDrvTracer.cpp
r40981 r41117 43 43 #include <iprt/semaphore.h> 44 44 #include <iprt/thread.h> 45 #include <iprt/param.h> 46 #include <iprt/uuid.h> 45 47 46 48 … … 48 50 * Structures and Typedefs * 49 51 *******************************************************************************/ 52 /** Pointer to a user tracer module registration record. */ 53 typedef struct SUPDRVTRACERUMOD *PSUPDRVTRACERUMOD; 54 50 55 /** 51 56 * Data for a tracepoint provider. … … 55 60 /** The entry in the provider list for this image. */ 56 61 RTLISTNODE ListEntry; 62 /** The entry in the per session provider list for this image. */ 63 RTLISTNODE SessionListEntry; 57 64 58 65 /** The core structure. */ … … 65 72 * SUPR0VtgRegisterDrv. NULL if pImage is set. */ 66 73 PSUPDRVSESSION pSession; 74 /** The user tracepoint module associated with this provider. NULL if 75 * pImage is set. */ 76 PSUPDRVTRACERUMOD pUmod; 67 77 68 78 /** Used to indicate that we've called pfnProviderDeregistered already and it … … 83 93 84 94 95 /** 96 * User tracer module VTG data copy. 97 */ 98 typedef struct SUPDRVVTGCOPY 99 { 100 /** Magic (SUDPRVVTGCOPY_MAGIC). */ 101 uint32_t u32Magic; 102 /** Refernece counter (we expect to share a lot of these). */ 103 uint32_t cRefs; 104 /** The size of the */ 105 uint32_t cbStrTab; 106 /** Image type flags. */ 107 uint32_t fFlags; 108 /** Hash list entry (SUPDRVDEVEXT::aTrackerUmodHash). */ 109 RTLISTNODE ListEntry; 110 /** The VTG object header. 111 * The rest of the data follows immediately afterwards. First the object, 112 * then the probe locations and finally the probe location string table. All 113 * pointers are fixed up to point within this data. */ 114 VTGOBJHDR Hdr; 115 } SUPDRVVTGCOPY; 116 /** Pointer to a VTG object copy. */ 117 typedef SUPDRVVTGCOPY *PSUPDRVVTGCOPY; 118 /** Magic value for SUPDRVVTGCOPY. */ 119 #define SUDPRVVTGCOPY_MAGIC UINT32_C(0x00080386) 120 121 122 /** 123 * User tracer module registration record. 124 */ 125 typedef struct SUPDRVTRACERUMOD 126 { 127 /** Magic (SUPDRVTRACERUMOD_MAGIC). */ 128 uint32_t u32Magic; 129 /** List entry. This is anchored in SUPDRVSESSION::UmodList. */ 130 RTLISTNODE ListEntry; 131 /** The address of the ring-3 VTG header. */ 132 RTR3PTR R3PtrVtgHdr; 133 /** Pointer to the ring-0 copy of the VTG data. */ 134 PSUPDRVVTGCOPY pVtgCopy; 135 /** The memory object that locks down the user memory. */ 136 RTR0MEMOBJ hMemObjLock; 137 /** The memory object that maps the locked memory into kernel space. */ 138 RTR0MEMOBJ hMemObjMap; 139 /** Pointer to the probe enabled-count array within the mapping. */ 140 uint32_t *pacProbeEnabled; 141 /** Pointer to the probe location array within the mapping. */ 142 void *pvProbeLocs; 143 /** The address of the ring-3 probe locations. */ 144 RTR3PTR R3PtrProbeLocs; 145 /** The lookup table index. */ 146 uint8_t iLookupTable; 147 /** The module bit count. */ 148 uint8_t cBits; 149 /** The size of a probe location record. */ 150 uint8_t cbProbeLoc; 151 /** The number of probe locations. */ 152 uint32_t cProbeLocs; 153 /** Ring-0 probe location info. */ 154 SUPDRVPROBELOC aProbeLocs[1]; 155 } SUPDRVTRACERUMOD; 156 /** Magic value for SUPDRVVTGCOPY. */ 157 #define SUPDRVTRACERUMOD_MAGIC UINT32_C(0x00080486) 158 159 85 160 /******************************************************************************* 86 161 * Defined Constants And Macros * … … 99 174 /** The address of the current probe fire routine for kernel mode. */ 100 175 PFNRT g_pfnSupdrvProbeFireKernel = supdrvTracerProbeFireStub; 176 177 178 /******************************************************************************* 179 * Internal Functions * 180 *******************************************************************************/ 181 static void supdrvVtgReleaseObjectCopy(PSUPDRVDEVEXT pDevExt, PSUPDRVVTGCOPY pThis); 101 182 102 183 … … 136 217 137 218 138 /** 139 * Validates the VTG data. 140 * 141 * @returns VBox status code. 142 * @param pVtgHdr The VTG object header of the data to validate. 143 * @param cbVtgObj The size of the VTG object. 144 * @param pbImage The image base. For validating the probe 145 * locations. 146 * @param cbImage The image size to go with @a pbImage. 147 */ 148 static int supdrvVtgValidate(PVTGOBJHDR pVtgHdr, size_t cbVtgObj, const uint8_t *pbImage, size_t cbImage) 149 { 150 uintptr_t cbTmp; 151 uintptr_t offTmp; 152 uintptr_t i; 153 uintptr_t cProviders; 154 int rc; 155 156 if (!pbImage || !cbImage) 157 { 158 pbImage = NULL; 159 cbImage = 0; 160 } 161 162 #define MY_VALIDATE_PTR(p, cb, cMin, cMax, cbUnit, rcBase) \ 163 do { \ 164 if ( (cb) >= cbVtgObj \ 165 || (uintptr_t)(p) - (uintptr_t)pVtgHdr > cbVtgObj - (cb) ) \ 166 { \ 167 SUPR0Printf("supdrvVtgValidate: " #rcBase "_TOO_PTR - p=%p cb=%#zx pVtgHdr=%p cbVtgHdr=%#zu line=%u %s\n", \ 168 p, (size_t)(cb), pVtgHdr, cbVtgObj, __LINE__, #p); \ 169 return rcBase ## _PTR; \ 170 } \ 171 if ((cb) < (cMin) * (cbUnit)) \ 172 { \ 173 SUPR0Printf("supdrvVtgValidate: " #rcBase "_TOO_FEW - cb=%#zx cMin=%#zx cbUnit=%#zx line=%u %s\n", \ 174 (size_t)(cb), (size_t)(cMin), (size_t)cbUnit, __LINE__, #p); \ 175 return rcBase ## _TOO_FEW; \ 176 } \ 177 if ((cb) >= (cMax) * (cbUnit)) \ 178 { \ 179 SUPR0Printf("supdrvVtgValidate: " #rcBase "_TOO_MUCH - cb=%#zx cMax=%#zx cbUnit=%#zx line=%u %s\n", \ 180 (size_t)(cb), (size_t)(cMax), (size_t)cbUnit, __LINE__, #p); \ 181 return rcBase ## _TOO_MUCH; \ 182 } \ 183 if ((cb) / (cbUnit) * (cbUnit) != (cb)) \ 184 { \ 185 SUPR0Printf("supdrvVtgValidate: " #rcBase "_NOT_MULTIPLE - cb=%#zx cbUnit=%#zx line=%u %s\n", \ 186 (size_t)(cb), (size_t)cbUnit, __LINE__, #p); \ 187 return rcBase ## _NOT_MULTIPLE; \ 188 } \ 189 } while (0) 219 /** Used by the validation code below. */ 220 #define MY_CHECK_RET(a_Expr, a_rc) \ 221 MY_CHECK_MSG_RET(a_Expr, ("%s: Validation failed on line " RT_XSTR(__LINE__) ": " #a_Expr "\n", __FUNCTION__), a_rc) 222 223 /** Used by the validation code below. */ 224 #define MY_CHECK_MSG_RET(a_Expr, a_PrintfArgs, a_rc) \ 225 do { if (RT_UNLIKELY(!(a_Expr))) { SUPR0Printf a_PrintfArgs; return (a_rc); } } while (0) 226 227 /** Used by the validation code below. */ 190 228 #define MY_WITHIN_IMAGE(p, rc) \ 191 229 do { \ … … 202 240 return (rc); \ 203 241 } while (0) 204 #define MY_VALIDATE_STR(offStrTab) \ 242 243 244 /** 245 * Validates the VTG object header. 246 * 247 * @returns VBox status code. 248 * @param pVtgHdr The header. 249 * @param uVtgHdrAddr The address where the header is actually 250 * loaded. 251 * @param cbVtgObj The alleged size of the header. 252 * @param pbImage The image base, if available. 253 * @param cbImage The image size, if available. 254 * @param fUmod Whether this is a user module. 255 */ 256 static int supdrvVtgValidateHdr(PVTGOBJHDR pVtgHdr, RTUINTPTR uVtgHdrAddr, const uint8_t *pbImage, size_t cbImage, bool fUmod) 257 { 258 struct VTGAREAS 259 { 260 uint32_t off; 261 uint32_t cb; 262 } const *paAreas; 263 unsigned cAreas; 264 unsigned i; 265 uint32_t cbVtgObj; 266 uint32_t off; 267 268 #define MY_VALIDATE_SIZE(cb, cMin, cMax, cbUnit, rcBase) \ 205 269 do { \ 206 if ((offStrTab) >= pVtgHdr->cbStrTab) \ 270 if ((cb) < (cMin) * (cbUnit)) \ 271 { \ 272 SUPR0Printf("supdrvVtgValidateHdr: " #rcBase "_TOO_FEW - cb=%#zx cMin=%#zx cbUnit=%#zx line=%u %s\n", \ 273 (size_t)(cb), (size_t)(cMin), (size_t)cbUnit, __LINE__, #cb); \ 274 return rcBase ## _TOO_FEW; \ 275 } \ 276 if ((cb) >= (cMax) * (cbUnit)) \ 277 { \ 278 SUPR0Printf("supdrvVtgValidateHdr: " #rcBase "_TOO_MUCH - cb=%#zx cMax=%#zx cbUnit=%#zx line=%u %s\n", \ 279 (size_t)(cb), (size_t)(cMax), (size_t)cbUnit, __LINE__, #cb); \ 280 return rcBase ## _TOO_MUCH; \ 281 } \ 282 if ((cb) / (cbUnit) * (cbUnit) != (cb)) \ 283 { \ 284 SUPR0Printf("supdrvVtgValidateHdr: " #rcBase "_NOT_MULTIPLE - cb=%#zx cbUnit=%#zx line=%u %s\n", \ 285 (size_t)(cb), (size_t)cbUnit, __LINE__, #cb); \ 286 return rcBase ## _NOT_MULTIPLE; \ 287 } \ 288 } while (0) 289 290 #define MY_VALIDATE_OFF(off, cb, cMin, cMax, cbUnit, cbAlign, rcBase) \ 291 do { \ 292 if ( (cb) >= cbVtgObj \ 293 || off > cbVtgObj - (cb) ) \ 294 { \ 295 SUPR0Printf("supdrvVtgValidateHdr: " #rcBase "_OFF - off=%#x cb=%#x pVtgHdr=%p cbVtgHdr=%#zx line=%u %s\n", \ 296 (off), (cb), pVtgHdr, cbVtgObj, __LINE__, #off); \ 297 return rcBase ## _OFF; \ 298 } \ 299 if (RT_ALIGN(off, cbAlign) != (off)) \ 300 { \ 301 SUPR0Printf("supdrvVtgValidateHdr: " #rcBase "_OFF - off=%#x align=%#zx line=%u %s\n", \ 302 (off), (size_t)(cbAlign), __LINE__, #off); \ 303 return rcBase ## _OFF; \ 304 } \ 305 MY_VALIDATE_SIZE(cb, cMin, cMax, cbUnit, rcBase); \ 306 } while (0) 307 308 /* 309 * Make sure both pbImage and cbImage are NULL/0 if one if of them is. 310 */ 311 if (!pbImage || !cbImage) 312 { 313 pbImage = NULL; 314 cbImage = 0; 315 cbVtgObj = pVtgHdr->cbObj; 316 } 317 else 318 { 319 MY_WITHIN_IMAGE(pVtgHdr, VERR_SUPDRV_VTG_BAD_HDR_PTR); 320 cbVtgObj = pVtgHdr->cbObj; 321 MY_WITHIN_IMAGE((uint8_t *)pVtgHdr + cbVtgObj - 1, VERR_SUPDRV_VTG_BAD_HDR_PTR); 322 } 323 324 if (cbVtgObj > _1M) 325 { 326 SUPR0Printf("supdrvVtgValidateHdr: VERR_SUPDRV_TRACER_TOO_LARGE - cbVtgObj=%#x\n", cbVtgObj); 327 return VERR_SUPDRV_TRACER_TOO_LARGE; 328 } 329 330 /* 331 * Set the probe location array offset and size members. 332 */ 333 if (!pVtgHdr->offProbeLocs) 334 { 335 uint64_t u64Tmp = pVtgHdr->uProbeLocsEnd.u64 - pVtgHdr->uProbeLocs.u64; 336 if (u64Tmp >= UINT32_MAX) 337 return VERR_SUPDRV_VTG_BAD_HDR_TOO_MUCH; 338 pVtgHdr->cbProbeLocs = (uint32_t)u64Tmp; 339 340 u64Tmp = pVtgHdr->uProbeLocs.u64 - uVtgHdrAddr; 341 if ((int64_t)u64Tmp != (int32_t)u64Tmp) 342 return VERR_SUPDRV_VTG_BAD_HDR_PTR; 343 pVtgHdr->offProbeLocs = (int32_t)u64Tmp; 344 } 345 346 /* 347 * The non-area description fields. 348 */ 349 if (memcmp(pVtgHdr->szMagic, VTGOBJHDR_MAGIC, sizeof(pVtgHdr->szMagic))) 350 return VERR_SUPDRV_VTG_MAGIC; 351 if ( pVtgHdr->cBits != ARCH_BITS 352 && ( !fUmod 353 || ( pVtgHdr->cBits != 32 354 && pVtgHdr->cBits != 64)) ) 355 return VERR_SUPDRV_VTG_BITS; 356 if ( pVtgHdr->au32Reserved1[0] 357 || pVtgHdr->au32Reserved1[1] 358 || pVtgHdr->au32Reserved1[2] 359 || pVtgHdr->au32Reserved1[3]) 360 return VERR_SUPDRV_VTG_BAD_HDR_MISC; 361 if (RTUuidIsNull(&pVtgHdr->Uuid)) 362 return VERR_SUPDRV_VTG_BAD_HDR_MISC; 363 364 /* 365 * Check the individual area descriptors. 366 */ 367 MY_VALIDATE_OFF(pVtgHdr->offStrTab, pVtgHdr->cbStrTab, 4, _1M, sizeof(char), sizeof(uint8_t), VERR_SUPDRV_VTG_BAD_HDR); 368 MY_VALIDATE_OFF(pVtgHdr->offArgLists, pVtgHdr->cbArgLists, 1, _32K, sizeof(uint32_t), sizeof(uint32_t), VERR_SUPDRV_VTG_BAD_HDR); 369 MY_VALIDATE_OFF(pVtgHdr->offProbes, pVtgHdr->cbProbes, 1, _32K, sizeof(VTGDESCPROBE), sizeof(uint32_t), VERR_SUPDRV_VTG_BAD_HDR); 370 MY_VALIDATE_OFF(pVtgHdr->offProviders, pVtgHdr->cbProviders, 1, 16, sizeof(VTGDESCPROVIDER), sizeof(uint32_t), VERR_SUPDRV_VTG_BAD_HDR); 371 MY_VALIDATE_OFF(pVtgHdr->offProbeEnabled, pVtgHdr->cbProbeEnabled, 1, _32K, sizeof(uint32_t), sizeof(uint32_t), VERR_SUPDRV_VTG_BAD_HDR); 372 if (!fUmod) 373 { 374 MY_WITHIN_IMAGE(pVtgHdr->uProbeLocs.p, VERR_SUPDRV_VTG_BAD_HDR_PTR); 375 MY_WITHIN_IMAGE(pVtgHdr->uProbeLocsEnd.p, VERR_SUPDRV_VTG_BAD_HDR_PTR); 376 MY_VALIDATE_SIZE( pVtgHdr->cbProbeLocs, 1, _128K, sizeof(VTGPROBELOC), VERR_SUPDRV_VTG_BAD_HDR); 377 } 378 else 379 { 380 if (pVtgHdr->cBits == 32) 381 MY_VALIDATE_SIZE( pVtgHdr->cbProbeLocs, 1, _8K, sizeof(VTGPROBELOC32), VERR_SUPDRV_VTG_BAD_HDR); 382 else 383 MY_VALIDATE_SIZE( pVtgHdr->cbProbeLocs, 1, _8K, sizeof(VTGPROBELOC64), VERR_SUPDRV_VTG_BAD_HDR); 384 /* Will check later that offProbeLocs are following closely on the 385 enable count array, so no need to validate the offset here. */ 386 } 387 388 /* 389 * Some additional consistency checks. 390 */ 391 if ( pVtgHdr->uProbeLocsEnd.u64 - pVtgHdr->uProbeLocs.u64 != pVtgHdr->cbProbeLocs 392 || (int64_t)(pVtgHdr->uProbeLocs.u64 - uVtgHdrAddr) != pVtgHdr->offProbeLocs) 393 { 394 SUPR0Printf("supdrvVtgValidateHdr: VERR_SUPDRV_VTG_BAD_HDR_MISC - uProbeLocs=%#llx uProbeLocsEnd=%#llx offProbeLocs=%#llx cbProbeLocs=%#x uVtgHdrAddr=%RTptr\n", 395 pVtgHdr->uProbeLocs.u64, pVtgHdr->uProbeLocsEnd.u64, pVtgHdr->offProbeLocs, pVtgHdr->cbProbeLocs, uVtgHdrAddr); 396 return VERR_SUPDRV_VTG_BAD_HDR_MISC; 397 } 398 399 if (pVtgHdr->cbProbes / sizeof(VTGDESCPROBE) != pVtgHdr->cbProbeEnabled / sizeof(uint32_t)) 400 { 401 SUPR0Printf("supdrvVtgValidateHdr: VERR_SUPDRV_VTG_BAD_HDR_MISC - cbProbeEnabled=%#zx cbProbes=%#zx\n", 402 pVtgHdr->cbProbeEnabled, pVtgHdr->cbProbes); 403 return VERR_SUPDRV_VTG_BAD_HDR_MISC; 404 } 405 406 /* 407 * Check that there are no overlapping areas. This is a little bit ugly... 408 */ 409 paAreas = (struct VTGAREAS const *)&pVtgHdr->offStrTab; 410 cAreas = pVtgHdr->offProbeLocs >= 0 ? 6 : 5; 411 off = sizeof(VTGOBJHDR); 412 for (i = 0; i < cAreas; i++) 413 { 414 if (paAreas[i].off < off) 415 { 416 SUPR0Printf("supdrvVtgValidateHdr: VERR_SUPDRV_VTG_BAD_HDR_MISC - overlapping areas %d and %d\n", i, i-1); 417 return VERR_SUPDRV_VTG_BAD_HDR_MISC; 418 } 419 off = paAreas[i].off + paAreas[i].cb; 420 } 421 if ( pVtgHdr->offProbeLocs > 0 422 && (uint32_t)-pVtgHdr->offProbeLocs < pVtgHdr->cbProbeLocs) 423 { 424 SUPR0Printf("supdrvVtgValidateHdr: VERR_SUPDRV_VTG_BAD_HDR_MISC - probe locations overlaps the header\n"); 425 return VERR_SUPDRV_VTG_BAD_HDR_MISC; 426 } 427 428 /* 429 * Check that the object size is correct. 430 */ 431 if (pVtgHdr->cbObj != pVtgHdr->offProbeEnabled + pVtgHdr->cbProbeEnabled) 432 { 433 SUPR0Printf("supdrvVtgValidateHdr: VERR_SUPDRV_VTG_BAD_HDR_MISC - bad header size %#x, expected %#x\n", 434 pVtgHdr->cbObj, pVtgHdr->offProbeEnabled + pVtgHdr->cbProbeEnabled); 435 return VERR_SUPDRV_VTG_BAD_HDR_MISC; 436 } 437 438 439 return VINF_SUCCESS; 440 #undef MY_VALIDATE_OFF 441 #undef MY_VALIDATE_SIZE 442 } 443 444 445 /** 446 * Validates the VTG data. 447 * 448 * @returns VBox status code. 449 * @param pVtgHdr The VTG object header of the data to validate. 450 * @param uVtgHdrAddr The address where the header is actually 451 * loaded. 452 * @param pbImage The image base. For validating the probe 453 * locations. 454 * @param cbImage The image size to go with @a pbImage. 455 * @param fUmod Whether this is a user module. 456 */ 457 static int supdrvVtgValidate(PVTGOBJHDR pVtgHdr, RTUINTPTR uVtgHdrAddr, const uint8_t *pbImage, size_t cbImage, bool fUmod) 458 { 459 uintptr_t offTmp; 460 uintptr_t i; 461 uintptr_t cProviders; 462 int rc; 463 464 if (!pbImage || !cbImage) 465 { 466 pbImage = NULL; 467 cbImage = 0; 468 } 469 470 #define MY_VALIDATE_STR(a_offStrTab) \ 471 do { \ 472 if ((a_offStrTab) >= pVtgHdr->cbStrTab) \ 207 473 return VERR_SUPDRV_VTG_STRTAB_OFF; \ 208 rc = supdrvVtgValidateString( pVtgHdr->pachStrTab + (offStrTab)); \474 rc = supdrvVtgValidateString((char *)pVtgHdr + pVtgHdr->offStrTab + (a_offStrTab)); \ 209 475 if (rc != VINF_SUCCESS) \ 210 476 return rc; \ … … 223 489 * The header. 224 490 */ 225 if (memcmp(pVtgHdr->szMagic, VTGOBJHDR_MAGIC, sizeof(pVtgHdr->szMagic))) 226 return VERR_SUPDRV_VTG_MAGIC; 227 if (pVtgHdr->cBits != ARCH_BITS) 228 return VERR_SUPDRV_VTG_BITS; 229 if (pVtgHdr->u32Reserved0) 230 return VERR_SUPDRV_VTG_BAD_HDR; 231 232 MY_VALIDATE_PTR(pVtgHdr->paProviders, pVtgHdr->cbProviders, 1, 16, sizeof(VTGDESCPROVIDER), VERR_SUPDRV_VTG_BAD_HDR); 233 MY_VALIDATE_PTR(pVtgHdr->paProbes, pVtgHdr->cbProbes, 1, _32K, sizeof(VTGDESCPROBE), VERR_SUPDRV_VTG_BAD_HDR); 234 MY_VALIDATE_PTR(pVtgHdr->pafProbeEnabled, pVtgHdr->cbProbeEnabled, 1, _32K, sizeof(bool), VERR_SUPDRV_VTG_BAD_HDR); 235 MY_VALIDATE_PTR(pVtgHdr->pachStrTab, pVtgHdr->cbStrTab, 4, _1M, sizeof(char), VERR_SUPDRV_VTG_BAD_HDR); 236 MY_VALIDATE_PTR(pVtgHdr->paArgLists, pVtgHdr->cbArgLists, 1, _32K, sizeof(uint32_t), VERR_SUPDRV_VTG_BAD_HDR); 237 238 MY_WITHIN_IMAGE(pVtgHdr->paProbLocs, VERR_SUPDRV_VTG_BAD_HDR_PTR); 239 MY_WITHIN_IMAGE(pVtgHdr->paProbLocsEnd, VERR_SUPDRV_VTG_BAD_HDR_PTR); 240 if ((uintptr_t)pVtgHdr->paProbLocs > (uintptr_t)pVtgHdr->paProbLocsEnd) 241 { 242 SUPR0Printf("supdrvVtgValidate: VERR_SUPDRV_VTG_BAD_HDR_PTR - paProbeLocs=%p > paProbLocsEnd=%p\n", 243 pVtgHdr->paProbLocs, pVtgHdr->paProbLocsEnd); 244 return VERR_SUPDRV_VTG_BAD_HDR_PTR; 245 } 246 cbTmp = (uintptr_t)pVtgHdr->paProbLocsEnd - (uintptr_t)pVtgHdr->paProbLocs; 247 if (cbTmp < sizeof(VTGPROBELOC)) 248 { 249 SUPR0Printf("supdrvVtgValidate: VERR_SUPDRV_VTG_BAD_HDR_TOO_FEW - cbTmp=%#zx paProbeLocs=%p paProbLocsEnd=%p\n", 250 cbTmp, pVtgHdr->paProbLocs, pVtgHdr->paProbLocsEnd); 251 return VERR_SUPDRV_VTG_BAD_HDR_TOO_FEW; 252 } 253 if (cbTmp >= _128K * sizeof(VTGPROBELOC)) 254 { 255 SUPR0Printf("supdrvVtgValidate: VERR_SUPDRV_VTG_BAD_HDR_TOO_MUCH - cbTmp=%#zx paProbeLocs=%p paProbLocsEnd=%p\n", 256 cbTmp, pVtgHdr->paProbLocs, pVtgHdr->paProbLocsEnd); 257 return VERR_SUPDRV_VTG_BAD_HDR_TOO_MUCH; 258 } 259 if (cbTmp / sizeof(VTGPROBELOC) * sizeof(VTGPROBELOC) != cbTmp) 260 { 261 SUPR0Printf("supdrvVtgValidate: VERR_SUPDRV_VTG_BAD_HDR_NOT_MULTIPLE - cbTmp=%#zx cbUnit=%#zx paProbeLocs=%p paProbLocsEnd=%p\n", 262 cbTmp, sizeof(VTGPROBELOC), pVtgHdr->paProbLocs, pVtgHdr->paProbLocsEnd); 263 return VERR_SUPDRV_VTG_BAD_HDR_NOT_MULTIPLE; 264 } 265 266 if (pVtgHdr->cbProbes / sizeof(VTGDESCPROBE) != pVtgHdr->cbProbeEnabled) 267 { 268 SUPR0Printf("supdrvVtgValidate: VERR_SUPDRV_VTG_BAD_HDR - cbProbeEnabled=%#zx cbProbes=%#zx\n", 269 pVtgHdr->cbProbeEnabled, pVtgHdr->cbProbes); 270 return VERR_SUPDRV_VTG_BAD_HDR; 271 } 491 rc = supdrvVtgValidateHdr(pVtgHdr, uVtgHdrAddr, pbImage, cbImage, fUmod); 492 if (RT_FAILURE(rc)) 493 return rc; 272 494 273 495 /* … … 277 499 while (i-- > 0) 278 500 { 279 MY_VALIDATE_STR(pVtgHdr->paProviders[i].offName);280 if (pVtgHdr->paProviders[i].iFirstProbe >= pVtgHdr->cbProbeEnabled) 281 return VERR_SUPDRV_VTG_BAD_PROVIDER;282 if (pVtgHdr->paProviders[i].iFirstProbe + pVtgHdr->paProviders[i].cProbes > pVtgHdr->cbProbeEnabled)283 return VERR_SUPDRV_VTG_BAD_PROVIDER;284 MY_VALIDATE_ATTR(pVtgHdr->paProviders[i].AttrSelf);285 MY_VALIDATE_ATTR(p VtgHdr->paProviders[i].AttrModules);286 MY_VALIDATE_ATTR(p VtgHdr->paProviders[i].AttrFunctions);287 MY_VALIDATE_ATTR(p VtgHdr->paProviders[i].AttrNames);288 MY_VALIDATE_ATTR(p VtgHdr->paProviders[i].AttrArguments);289 if (pVtgHdr->paProviders[i].bReserved)290 return VERR_SUPDRV_VTG_BAD_PROVIDER;501 PCVTGDESCPROVIDER pProvider = (PCVTGDESCPROVIDER)((uintptr_t)pVtgHdr + pVtgHdr->offProviders) + i; 502 503 MY_VALIDATE_STR(pProvider->offName); 504 MY_CHECK_RET(pProvider->iFirstProbe < pVtgHdr->cbProbeEnabled / sizeof(uint32_t), VERR_SUPDRV_VTG_BAD_PROVIDER); 505 MY_CHECK_RET((uint32_t)pProvider->iFirstProbe + pProvider->cProbes <= pVtgHdr->cbProbeEnabled / sizeof(uint32_t), 506 VERR_SUPDRV_VTG_BAD_PROVIDER); 507 MY_VALIDATE_ATTR(pProvider->AttrSelf); 508 MY_VALIDATE_ATTR(pProvider->AttrModules); 509 MY_VALIDATE_ATTR(pProvider->AttrFunctions); 510 MY_VALIDATE_ATTR(pProvider->AttrNames); 511 MY_VALIDATE_ATTR(pProvider->AttrArguments); 512 MY_CHECK_RET(pProvider->bReserved == 0, VERR_SUPDRV_VTG_BAD_PROVIDER); 291 513 } 292 514 … … 297 519 while (i-- > 0) 298 520 { 299 PVTGDESCARGLIST pArgList; 300 unsigned iArg; 301 bool fHaveLargeArgs; 302 303 MY_VALIDATE_STR(pVtgHdr->paProbes[i].offName); 304 if (pVtgHdr->paProbes[i].offArgList >= pVtgHdr->cbArgLists) 521 PCVTGDESCPROBE pProbe = (PCVTGDESCPROBE)( (uintptr_t)pVtgHdr + pVtgHdr->offProbes) + i; 522 PCVTGDESCPROVIDER pProvider = (PCVTGDESCPROVIDER)((uintptr_t)pVtgHdr + pVtgHdr->offProviders) + pProbe->idxProvider; 523 PCVTGDESCARGLIST pArgList = (PCVTGDESCARGLIST)( (uintptr_t)pVtgHdr + pVtgHdr->offArgLists + pProbe->offArgList ); 524 unsigned iArg; 525 bool fHaveLargeArgs; 526 527 528 MY_VALIDATE_STR(pProbe->offName); 529 MY_CHECK_RET(pProbe->offArgList < pVtgHdr->cbArgLists, VERR_SUPDRV_VTG_BAD_PROBE); 530 MY_CHECK_RET((pProbe->offArgList & 3) == 0, VERR_SUPDRV_VTG_BAD_PROBE); 531 MY_CHECK_RET(pProbe->idxEnabled == i, VERR_SUPDRV_VTG_BAD_PROBE); /* The lists are parallel. */ 532 MY_CHECK_RET(pProbe->idxProvider < cProviders, VERR_SUPDRV_VTG_BAD_PROBE); 533 MY_CHECK_RET(i - pProvider->iFirstProbe < pProvider->cProbes, VERR_SUPDRV_VTG_BAD_PROBE); 534 if (pProbe->offObjHdr != (intptr_t)pVtgHdr - (intptr_t)pProbe) 535 { 536 SUPR0Printf("supdrvVtgValidate: VERR_SUPDRV_TRACER_BAD_ARG_FLAGS - iProbe=%u offObjHdr=%d expected %zd\n", 537 i, pProbe->offObjHdr, (intptr_t)pVtgHdr - (intptr_t)pProbe); 305 538 return VERR_SUPDRV_VTG_BAD_PROBE; 306 if (pVtgHdr->paProbes[i].offArgList & 3)307 return VERR_SUPDRV_VTG_BAD_PROBE;308 if (pVtgHdr->paProbes[i].idxEnabled != i) /* The lists are parallel. */309 return VERR_SUPDRV_VTG_BAD_PROBE;310 if (pVtgHdr->paProbes[i].idxProvider >= cProviders)311 return VERR_SUPDRV_VTG_BAD_PROBE;312 if ( i - pVtgHdr->paProviders[pVtgHdr->paProbes[i].idxProvider].iFirstProbe313 >= pVtgHdr->paProviders[pVtgHdr->paProbes[i].idxProvider].cProbes)314 return VERR_SUPDRV_VTG_BAD_PROBE;315 if (pVtgHdr->paProbes[i].u32User)316 return VERR_SUPDRV_VTG_BAD_PROBE;317 if (pVtgHdr->paProbes[i].u32User2)318 return VERR_SUPDRV_VTG_BAD_PROBE;319 if ( pVtgHdr->paProbes[i].offObjHdr320 != (intptr_t)pVtgHdr - (intptr_t)&pVtgHdr->paProbes[i])321 {322 SUPR0Printf("supdrvVtgValidate: VERR_SUPDRV_TRACER_BAD_ARG_FLAGS - iProbe=%u offObjHdr=%d expected %zd\n",323 i, pVtgHdr->paProbes[i].offObjHdr, (intptr_t)pVtgHdr - (intptr_t)&pVtgHdr->paProbes[i]);324 return VERR_SUPDRV_VTG_BAD_PROBE;325 539 } 326 540 327 541 /* The referenced argument list. */ 328 pArgList = (PVTGDESCARGLIST)((uintptr_t)pVtgHdr->paArgLists + pVtgHdr->paProbes[i].offArgList);329 542 if (pArgList->cArgs > 16) 330 543 { … … 383 596 384 597 /* 385 * Check that pafProbeEnabled is all zero. 386 */ 387 i = pVtgHdr->cbProbeEnabled; 388 while (i-- > 0) 389 if (pVtgHdr->pafProbeEnabled[0]) 390 return VERR_SUPDRV_VTG_BAD_PROBE_ENABLED; 598 * Check that pacProbeEnabled is all zeros. 599 */ 600 { 601 uint32_t const *pcProbeEnabled = (uint32_t const *)((uintptr_t)pVtgHdr + pVtgHdr->offProbeEnabled); 602 i = pVtgHdr->cbProbeEnabled / sizeof(uint32_t); 603 while (i-- > 0) 604 MY_CHECK_RET(pcProbeEnabled[0] == 0, VERR_SUPDRV_VTG_BAD_PROBE_ENABLED); 605 } 391 606 392 607 /* 393 608 * Probe locations. 394 609 */ 395 i = pVtgHdr->paProbLocsEnd - pVtgHdr->paProbLocs; 396 while (i-- > 0) 397 { 398 if (pVtgHdr->paProbLocs[i].uLine >= _1G) 399 return VERR_SUPDRV_VTG_BAD_PROBE_LOC; 400 if (pVtgHdr->paProbLocs[i].fEnabled) 401 return VERR_SUPDRV_VTG_BAD_PROBE_LOC; 402 if (pVtgHdr->paProbLocs[i].idProbe != UINT32_MAX) 403 return VERR_SUPDRV_VTG_BAD_PROBE_LOC; 404 MY_WITHIN_IMAGE(pVtgHdr->paProbLocs[i].pszFunction, VERR_SUPDRV_VTG_BAD_PROBE_LOC); 405 offTmp = (uintptr_t)pVtgHdr->paProbLocs[i].pbProbe - (uintptr_t)pVtgHdr->paProbes; 406 if (offTmp >= pVtgHdr->cbProbes) 407 return VERR_SUPDRV_VTG_BAD_PROBE_LOC; 408 if (offTmp / sizeof(VTGDESCPROBE) * sizeof(VTGDESCPROBE) != offTmp) 409 return VERR_SUPDRV_VTG_BAD_PROBE_LOC; 610 { 611 PCVTGPROBELOC paProbeLocs = (PCVTGPROBELOC)((intptr_t)pVtgHdr + pVtgHdr->offProbeLocs); 612 i = pVtgHdr->cbProbeLocs / sizeof(VTGPROBELOC); 613 while (i-- > 0) 614 { 615 MY_CHECK_RET(paProbeLocs[i].uLine < _1G, VERR_SUPDRV_VTG_BAD_PROBE_LOC); 616 MY_CHECK_RET(paProbeLocs[i].fEnabled == false, VERR_SUPDRV_VTG_BAD_PROBE_LOC); 617 MY_CHECK_RET(paProbeLocs[i].idProbe == 0, VERR_SUPDRV_VTG_BAD_PROBE_LOC); 618 MY_WITHIN_IMAGE(paProbeLocs[i].pszFunction, VERR_SUPDRV_VTG_BAD_PROBE_LOC); 619 offTmp = (uintptr_t)paProbeLocs[i].pbProbe - (uintptr_t)pVtgHdr->offProbes - (uintptr_t)pVtgHdr; 620 MY_CHECK_RET(offTmp < pVtgHdr->cbProbes, VERR_SUPDRV_VTG_BAD_PROBE_LOC); 621 MY_CHECK_RET(offTmp / sizeof(VTGDESCPROBE) * sizeof(VTGDESCPROBE) == offTmp, VERR_SUPDRV_VTG_BAD_PROBE_LOC); 622 } 410 623 } 411 624 412 625 return VINF_SUCCESS; 626 } 627 413 628 #undef MY_VALIDATE_STR 414 #undef MY_VALIDATE_ PTR629 #undef MY_VALIDATE_ATTR 415 630 #undef MY_WITHIN_IMAGE 416 }417 631 418 632 … … 427 641 { 428 642 Assert(offStrTab < pVtgHdr->cbStrTab); 429 return &pVtgHdr->pachStrTab[offStrTab];643 return (char *)pVtgHdr + pVtgHdr->offStrTab + offStrTab; 430 644 } 431 645 … … 439 653 { 440 654 LOG_TRACER(("Freeing tracepoint provider '%s' / %p\n", pProv->szName, pProv->Core.TracerData.DTrace.idProvider)); 441 pProv->fRegistered = false; 442 pProv->fZombie = true; 443 pProv->Core.pDesc = NULL; 444 pProv->Core.pHdr = NULL; 655 pProv->fRegistered = false; 656 pProv->fZombie = true; 657 pProv->Core.pDesc = NULL; 658 pProv->Core.pHdr = NULL; 659 pProv->Core.paProbeLocsRO = NULL; 660 pProv->Core.pvProbeLocsEn = NULL; 661 pProv->Core.pacProbeEnabled = NULL; 662 pProv->Core.paR0ProbeLocs = NULL; 663 pProv->Core.paR0Probes = NULL; 445 664 RT_ZERO(pProv->Core.TracerData); 446 665 RTMemFree(pProv); … … 449 668 450 669 /** 451 * Deregisters a provider.670 * Unlinks and deregisters a provider. 452 671 * 453 672 * If the provider is still busy, it will be put in the zombie list. … … 461 680 { 462 681 int rc; 682 683 RTListNodeRemove(&pProv->ListEntry); 684 if (pProv->pSession) 685 { 686 RTListNodeRemove(&pProv->SessionListEntry); 687 RTListInit(&pProv->SessionListEntry); 688 pProv->pSession->cTpProviders--; 689 } 690 463 691 if (!pProv->fRegistered || !pDevExt->pTracerOps) 464 692 rc = VINF_SUCCESS; … … 471 699 } 472 700 473 pProv->fZombie = true; 701 pProv->fZombie = true; 702 pProv->pImage = NULL; 703 pProv->pSession = NULL; 704 pProv->pUmod = NULL; 705 pProv->Core.pDesc = NULL; 706 pProv->Core.pHdr = NULL; 707 pProv->Core.paProbeLocsRO = NULL; 708 pProv->Core.pvProbeLocsEn = NULL; 709 pProv->Core.pacProbeEnabled = NULL; 710 pProv->Core.paR0ProbeLocs = NULL; 711 474 712 RTListAppend(&pDevExt->TracerProviderZombieList, &pProv->ListEntry); 475 713 LOG_TRACER(("Invalidated provider '%s' / %p and put it on the zombie list (rc=%Rrc)\n", … … 521 759 RTListForEachSafe(&pDevExt->TracerProviderList, pProv, pProvNext, SUPDRVTPPROVIDER, ListEntry) 522 760 { 523 RTListNodeRemove(&pProv->ListEntry);524 761 supdrvTracerDeregisterVtgObj(pDevExt, pProv); 525 762 } … … 589 826 * @param pszName The driver name. 590 827 * @param pVtgHdr The VTG object header. 591 * @param pVtgObj The size of the VTG object.592 828 * @param pImage The image if applicable. 593 829 * @param pSession The session if applicable. 830 * @param pUmod The associated user tracepoint module if 831 * applicable. 594 832 * @param pszModName The module name. 595 833 */ 596 static int supdrvTracerRegisterVtgObj(PSUPDRVDEVEXT pDevExt, PVTGOBJHDR pVtgHdr, size_t cbVtgObj,PSUPDRVLDRIMAGE pImage,597 PSUPDRVSESSION pSession, const char *pszModName)834 static int supdrvTracerRegisterVtgObj(PSUPDRVDEVEXT pDevExt, PVTGOBJHDR pVtgHdr, PSUPDRVLDRIMAGE pImage, 835 PSUPDRVSESSION pSession, PSUPDRVTRACERUMOD pUmod, const char *pszModName) 598 836 { 599 837 int rc; 600 838 uintptr_t i; 601 839 PSUPDRVTPPROVIDER pProv; 840 size_t cchModName; 602 841 603 842 /* … … 609 848 AssertPtrNullReturn(pSession, VERR_INVALID_POINTER); 610 849 AssertPtrReturn(pszModName, VERR_INVALID_POINTER); 850 cchModName = strlen(pszModName); 611 851 612 852 if (pImage) 613 rc = supdrvVtgValidate(pVtgHdr, cbVtgObj, (const uint8_t *)pImage->pvImage, pImage->cbImageBits); 853 rc = supdrvVtgValidate(pVtgHdr, (uintptr_t)pVtgHdr, 854 (const uint8_t *)pImage->pvImage, pImage->cbImageBits, 855 false /*fUmod*/); 614 856 else 615 rc = supdrvVtgValidate(pVtgHdr, cbVtgObj, NULL, 0);857 rc = supdrvVtgValidate(pVtgHdr, (uintptr_t)pVtgHdr, NULL, 0, pUmod != NULL); 616 858 if (RT_FAILURE(rc)) 617 859 return rc; 618 860 861 /* 862 * Check that there aren't any obvious duplicates. 863 * (Yes, this isn't race free, but it's good enough for now.) 864 */ 619 865 rc = RTSemFastMutexRequest(pDevExt->mtxTracer); 620 866 if (RT_FAILURE(rc)) 621 867 return rc; 622 RTListForEach(&pDevExt->TracerProviderList, pProv, SUPDRVTPPROVIDER, ListEntry) 623 { 624 if (pProv->Core.pHdr == pVtgHdr) 625 { 626 rc = VERR_SUPDRV_VTG_ALREADY_REGISTERED; 627 break; 628 } 629 if ( pProv->pSession == pSession 630 && pProv->pImage == pImage) 631 { 632 rc = VERR_SUPDRV_VTG_ONLY_ONCE_PER_SESSION; 633 break; 868 if (pImage || pSession->R0Process == NIL_RTPROCESS) 869 { 870 RTListForEach(&pDevExt->TracerProviderList, pProv, SUPDRVTPPROVIDER, ListEntry) 871 { 872 if (pProv->Core.pHdr == pVtgHdr) 873 { 874 rc = VERR_SUPDRV_VTG_ALREADY_REGISTERED; 875 break; 876 } 877 878 if ( pProv->pSession == pSession 879 && pProv->pImage == pImage) 880 { 881 rc = VERR_SUPDRV_VTG_ONLY_ONCE_PER_SESSION; 882 break; 883 } 884 } 885 } 886 else 887 { 888 RTListForEach(&pSession->TpProviders, pProv, SUPDRVTPPROVIDER, SessionListEntry) 889 { 890 if (pProv->Core.pHdr == pVtgHdr) 891 { 892 rc = VERR_SUPDRV_VTG_ALREADY_REGISTERED; 893 break; 894 } 634 895 } 635 896 } … … 644 905 while (i-- > 0) 645 906 { 646 PVTGDESCPROVIDER pDesc = &pVtgHdr->paProviders[i];907 PVTGDESCPROVIDER pDesc = (PVTGDESCPROVIDER)((uintptr_t)pVtgHdr + pVtgHdr->offProviders) + i; 647 908 const char *pszName = supdrvVtgGetString(pVtgHdr, pDesc->offName); 648 size_t const cchName = strlen(pszName); 649 pProv = (PSUPDRVTPPROVIDER)RTMemAllocZ(RT_OFFSETOF(SUPDRVTPPROVIDER, szName[cchName + 1])); 909 size_t const cchName = strlen(pszName) + (pUmod ? 16 : 0); 910 911 pProv = (PSUPDRVTPPROVIDER)RTMemAllocZ(RT_OFFSETOF(SUPDRVTPPROVIDER, szName[cchName + 1 + cchModName + 1])); 650 912 if (pProv) 651 913 { 652 pProv->Core.pDesc = pDesc; 653 pProv->Core.pHdr = pVtgHdr; 654 pProv->Core.pszName = &pProv->szName[0]; 655 pProv->Core.pszModName = pszModName; 656 pProv->pImage = pImage; 657 pProv->pSession = pSession; 658 pProv->fZombie = false; 659 pProv->fRegistered = true; 660 memcpy(&pProv->szName[0], pszName, cchName + 1); 661 914 pProv->Core.pszName = &pProv->szName[0]; 915 pProv->Core.pszModName = &pProv->szName[cchName + 1]; 916 pProv->Core.pDesc = pDesc; 917 pProv->Core.pHdr = pVtgHdr; 918 pProv->Core.paProbeLocsRO = (PCVTGPROBELOC )((uintptr_t)pVtgHdr + pVtgHdr->offProbeLocs); 919 if (!pUmod) 920 { 921 pProv->Core.pvProbeLocsEn = (void *)((uintptr_t)pVtgHdr + pVtgHdr->offProbeLocs); 922 pProv->Core.pacProbeEnabled = (uint32_t *)((uintptr_t)pVtgHdr + pVtgHdr->offProbeEnabled); 923 pProv->Core.paR0ProbeLocs = NULL; 924 pProv->Core.paR0Probes = NULL; 925 pProv->Core.cbProbeLocsEn = sizeof(VTGPROBELOC); 926 pProv->Core.cBits = ARCH_BITS; 927 pProv->Core.fUmod = false; 928 } 929 else 930 { 931 pProv->Core.pvProbeLocsEn = pUmod->pvProbeLocs; 932 pProv->Core.pacProbeEnabled = pUmod->pacProbeEnabled; 933 pProv->Core.paR0ProbeLocs = &pUmod->aProbeLocs[0]; 934 pProv->Core.paR0Probes = (PSUPDRVPROBEINFO)&pUmod->aProbeLocs[pUmod->cProbeLocs]; 935 pProv->Core.cbProbeLocsEn = pUmod->cbProbeLoc; 936 pProv->Core.cBits = pUmod->cBits; 937 pProv->Core.fUmod = true; 938 } 939 pProv->pImage = pImage; 940 pProv->pSession = pSession; 941 pProv->pUmod = pUmod; 942 pProv->fZombie = false; 943 pProv->fRegistered = true; 944 945 if (!pUmod) 946 memcpy(pProv->szName, pszName, cchName + 1); 947 else 948 RTStrPrintf(pProv->szName, cchName + 1, "%s%u", pszName, (uint32_t)pSession->Process); 949 memcpy((void *)pProv->Core.pszModName, pszModName, cchModName + 1); 950 951 /* 952 * Do the actual registration and list manipulations while holding 953 * down the lock. 954 */ 662 955 rc = RTSemFastMutexRequest(pDevExt->mtxTracer); 663 956 if (RT_SUCCESS(rc)) … … 674 967 { 675 968 RTListAppend(&pDevExt->TracerProviderList, &pProv->ListEntry); 969 if (pSession) 970 { 971 RTListAppend(&pSession->TpProviders, &pProv->SessionListEntry); 972 pSession->cTpProviders++; 973 } 974 else 975 RTListInit(&pProv->SessionListEntry); 676 976 RTSemFastMutexRelease(pDevExt->mtxTracer); 677 977 LOG_TRACER(("Registered tracepoint provider '%s' in '%s' -> %p\n", … … 683 983 LOG_TRACER(("Failed to register tracepoint provider '%s' in '%s' -> %Rrc\n", 684 984 pProv->szName, pszModName, rc)); 685 RTMemFree(pProv);686 985 } 687 986 } … … 690 989 rc = VERR_NO_MEMORY; 691 990 991 /* 992 * In case of failure, we have to undo any providers we already 993 * managed to register. 994 */ 692 995 if (RT_FAILURE(rc)) 693 996 { 694 997 PSUPDRVTPPROVIDER pProvNext; 695 supdrvTracerFreeProvider(pProv); 998 999 if (pProv) 1000 supdrvTracerFreeProvider(pProv); 696 1001 697 1002 RTSemFastMutexRequest(pDevExt->mtxTracer); 698 RTListForEachReverseSafe(&pDevExt->TracerProviderList, pProv, pProvNext, SUPDRVTPPROVIDER, ListEntry)699 { 700 if (pProv->Core.pHdr == pVtgHdr)1003 if (pImage) 1004 { 1005 RTListForEachReverseSafe(&pDevExt->TracerProviderList, pProv, pProvNext, SUPDRVTPPROVIDER, ListEntry) 701 1006 { 702 RTListNodeRemove(&pProv->ListEntry); 703 supdrvTracerDeregisterVtgObj(pDevExt, pProv); 1007 if (pProv->Core.pHdr == pVtgHdr) 1008 supdrvTracerDeregisterVtgObj(pDevExt, pProv); 1009 } 1010 } 1011 else 1012 { 1013 RTListForEachSafe(&pSession->TpProviders, pProv, pProvNext, SUPDRVTPPROVIDER, SessionListEntry) 1014 { 1015 if (pProv->Core.pHdr == pVtgHdr) 1016 supdrvTracerDeregisterVtgObj(pDevExt, pProv); 704 1017 } 705 1018 } … … 731 1044 LOG_TRACER(("SUPR0TracerRegisterDrv: pSession=%p pVtgHdr=%p pszName=%s\n", pSession, pVtgHdr, pszName)); 732 1045 733 rc = supdrvTracerRegisterVtgObj(pSession->pDevExt, pVtgHdr, _1M, NULL /*pImage*/, pSession, pszName);1046 rc = supdrvTracerRegisterVtgObj(pSession->pDevExt, pVtgHdr, NULL /*pImage*/, pSession, NULL /*pUmod*/, pszName); 734 1047 735 1048 /* … … 762 1075 */ 763 1076 RTSemFastMutexRequest(pDevExt->mtxTracer); 764 RTListForEachSafe(&pDevExt->TracerProviderList, pProv, pProvNext, SUPDRVTPPROVIDER, ListEntry) 765 { 766 if (pProv->pSession == pSession) 767 { 768 RTListNodeRemove(&pProv->ListEntry); 769 supdrvTracerDeregisterVtgObj(pDevExt, pProv); 770 } 1077 RTListForEachSafe(&pSession->TpProviders, pProv, pProvNext, SUPDRVTPPROVIDER, SessionListEntry) 1078 { 1079 supdrvTracerDeregisterVtgObj(pDevExt, pProv); 771 1080 } 772 1081 RTSemFastMutexRelease(pDevExt->mtxTracer); … … 793 1102 PSUPDRVLDRIMAGE pImage = (PSUPDRVLDRIMAGE)hMod; 794 1103 PSUPDRVDEVEXT pDevExt; 795 uintptr_t cbVtgObj;796 1104 int rc; 797 1105 … … 809 1117 AssertReturn(pDevExt->pLdrInitImage == pImage, VERR_WRONG_ORDER); 810 1118 AssertReturn(pDevExt->hLdrInitThread == RTThreadNativeSelf(), VERR_WRONG_ORDER); 811 812 /* 813 * Calculate the max VTG object size and hand it over to the common code. 814 */ 815 cbVtgObj = (uintptr_t)pVtgHdr - (uintptr_t)pImage->pvImage; 816 AssertMsgReturn(cbVtgObj /*off*/ < pImage->cbImageBits, 817 ("pVtgHdr=%p offVtgObj=%p cbImageBits=%p\n", pVtgHdr, cbVtgObj, pImage->cbImageBits), 818 VERR_INVALID_PARAMETER); 819 cbVtgObj = pImage->cbImageBits - cbVtgObj; 820 821 rc = supdrvTracerRegisterVtgObj(pDevExt, pVtgHdr, cbVtgObj, pImage, NULL, pImage->szName); 1119 AssertReturn((uintptr_t)pVtgHdr - (uintptr_t)pImage->pvImage < pImage->cbImageBits, VERR_INVALID_PARAMETER); 1120 1121 /* 1122 * Do the job. 1123 */ 1124 rc = supdrvTracerRegisterVtgObj(pDevExt, pVtgHdr, pImage, NULL /*pSession*/, NULL /*pUmod*/, pImage->szName); 822 1125 LOG_TRACER(("SUPR0TracerRegisterModule: rc=%d\n", rc)); 823 1126 … … 1021 1324 else 1022 1325 LOG_TRACER(("supdrvTracerCommonDeregisterImpl: Waiting on %u opens\n", pDevExt->cTracerOpens)); 1326 } 1327 1328 /* Tracer calls. */ 1329 if (pDevExt->cTracerCallers) 1330 { 1331 cZombies++; 1332 if (!(i & 0xf)) 1333 SUPR0Printf("supdrvTracerCommonDeregisterImpl: Waiting on %u callers\n", pDevExt->cTracerCallers); 1334 else 1335 LOG_TRACER(("supdrvTracerCommonDeregisterImpl: Waiting on %u callers\n", pDevExt->cTracerCallers)); 1023 1336 } 1024 1337 … … 1179 1492 { 1180 1493 if (pProv->pImage == pImage) 1181 {1182 RTListNodeRemove(&pProv->ListEntry);1183 1494 supdrvTracerDeregisterVtgObj(pDevExt, pProv); 1184 }1185 1495 } 1186 1496 … … 1204 1514 { 1205 1515 /* 1206 * If ring-0 session, make sure it has deregistered VTG objects and the tracer. 1207 */ 1208 if (pSession->R0Process == NIL_RTR0PROCESS) 1209 { 1210 SUPDRVTPPROVIDER *pProvNext; 1211 SUPDRVTPPROVIDER *pProv; 1212 1213 RTSemFastMutexRequest(pDevExt->mtxTracer); 1214 RTListForEachSafe(&pDevExt->TracerProviderList, pProv, pProvNext, SUPDRVTPPROVIDER, ListEntry) 1215 { 1216 if (pProv->pSession == pSession) 1217 { 1218 RTListNodeRemove(&pProv->ListEntry); 1219 supdrvTracerDeregisterVtgObj(pDevExt, pProv); 1220 } 1221 } 1222 RTSemFastMutexRelease(pDevExt->mtxTracer); 1223 1224 (void)SUPR0TracerDeregisterImpl(NULL, pSession); 1225 } 1516 * Deregister all providers. 1517 */ 1518 SUPDRVTPPROVIDER *pProvNext; 1519 SUPDRVTPPROVIDER *pProv; 1520 RTSemFastMutexRequest(pDevExt->mtxTracer); 1521 RTListForEachSafe(&pSession->TpProviders, pProv, pProvNext, SUPDRVTPPROVIDER, SessionListEntry) 1522 { 1523 supdrvTracerDeregisterVtgObj(pDevExt, pProv); 1524 } 1525 RTSemFastMutexRelease(pDevExt->mtxTracer); 1226 1526 1227 1527 /* … … 1230 1530 if (pSession->uTracerData) 1231 1531 supdrvIOCtl_TracerClose(pDevExt, pSession); 1232 } 1233 1234 1235 int VBOXCALL supdrvIOCtl_TracerUmodRegister(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, RTR3PTR pVtgHdr, const char *pszModName, uint32_t fFlags) 1236 { 1237 return VERR_NOT_IMPLEMENTED; 1238 } 1239 1240 int VBOXCALL supdrvIOCtl_TracerUmodDeregister(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, RTR3PTR pVtgHdr) 1241 { 1242 return VERR_NOT_IMPLEMENTED; 1243 } 1244 1245 void VBOXCALL supdrvIOCtl_TracerUmodProbeFire(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, PCSUPDRVTRACERUSRCTX pCtx) 1246 { 1247 1532 1533 /* 1534 * Deregister any tracer implementation. 1535 */ 1536 if (pSession->R0Process == NIL_RTR0PROCESS) 1537 (void)SUPR0TracerDeregisterImpl(NULL, pSession); 1538 1539 if (pSession->R0Process != NIL_RTR0PROCESS) 1540 { 1541 /* 1542 * Free any lingering user modules. We don't bother holding the lock 1543 * here as there shouldn't be anyone messing with the session at this 1544 * point. 1545 */ 1546 PSUPDRVTRACERUMOD pUmodNext; 1547 PSUPDRVTRACERUMOD pUmod; 1548 RTListForEachSafe(&pSession->TpUmods, pUmod, pUmodNext, SUPDRVTRACERUMOD, ListEntry) 1549 { 1550 RTR0MemObjFree(pUmod->hMemObjMap, false /*fFreeMappings*/); 1551 RTR0MemObjFree(pUmod->hMemObjLock, false /*fFreeMappings*/); 1552 supdrvVtgReleaseObjectCopy(pDevExt, pUmod->pVtgCopy); 1553 RTMemFree(pUmod); 1554 } 1555 } 1556 } 1557 1558 1559 static void supdrvVtgReleaseObjectCopy(PSUPDRVDEVEXT pDevExt, PSUPDRVVTGCOPY pThis) 1560 { 1561 uint32_t cRefs = ASMAtomicDecU32(&pThis->cRefs); 1562 if (!cRefs) 1563 { 1564 RTSemFastMutexRequest(pDevExt->mtxTracer); 1565 pThis->u32Magic = ~SUDPRVVTGCOPY_MAGIC; 1566 RTListNodeRemove(&pThis->ListEntry); 1567 RTSemFastMutexRelease(pDevExt->mtxTracer); 1568 1569 RTMemFree(pThis); 1570 } 1571 } 1572 1573 1574 /** 1575 * Finds a matching VTG object copy, caller owns the lock already. 1576 * 1577 * @returns Copy with reference. NULL if not found. 1578 * @param pHashList The hash list to search. 1579 * @param pHdr The VTG header (valid). 1580 * @param cbStrTab The string table size. 1581 * @param fFlags The user module flags. 1582 */ 1583 static PSUPDRVVTGCOPY supdrvVtgFindObjectCopyLocked(PRTLISTANCHOR pHashList, PCVTGOBJHDR pHdr, uint32_t cbStrTab, uint32_t fFlags) 1584 { 1585 PSUPDRVVTGCOPY pCur; 1586 1587 fFlags &= SUP_TRACER_UMOD_FLAGS_TYPE_MASK; 1588 RTListForEach(pHashList, pCur, SUPDRVVTGCOPY, ListEntry) 1589 { 1590 #define HDR_EQUALS(member) pCur->Hdr.member == pHdr->member 1591 if ( HDR_EQUALS(Uuid.au32[0]) 1592 && HDR_EQUALS(Uuid.au32[1]) 1593 && HDR_EQUALS(Uuid.au32[2]) 1594 && HDR_EQUALS(Uuid.au32[3]) 1595 && HDR_EQUALS(cbObj) 1596 && HDR_EQUALS(cBits) 1597 && pCur->cbStrTab == cbStrTab 1598 && pCur->fFlags == fFlags 1599 ) 1600 { 1601 if (RT_LIKELY( HDR_EQUALS(offStrTab) 1602 && HDR_EQUALS(cbStrTab) 1603 && HDR_EQUALS(offArgLists) 1604 && HDR_EQUALS(cbArgLists) 1605 && HDR_EQUALS(offProbes) 1606 && HDR_EQUALS(cbProbes) 1607 && HDR_EQUALS(offProviders) 1608 && HDR_EQUALS(cbProviders) 1609 && HDR_EQUALS(offProbeEnabled) 1610 && HDR_EQUALS(cbProbeEnabled) 1611 && HDR_EQUALS(offProbeLocs) 1612 && HDR_EQUALS(cbProbeLocs) 1613 ) 1614 ) 1615 { 1616 Assert(pCur->cRefs > 0); 1617 Assert(pCur->cRefs < _1M); 1618 pCur->cRefs++; 1619 return pCur; 1620 } 1621 } 1622 #undef HDR_EQUALS 1623 } 1624 1625 return NULL; 1626 } 1627 1628 1629 /** 1630 * Finds a matching VTG object copy. 1631 * 1632 * @returns Copy with reference. NULL if not found. 1633 * @param pDevExt The device extension. 1634 * @param pHdr The VTG header (valid). 1635 * @param cbStrTab The string table size. 1636 * @param fFlags The user module flags. 1637 */ 1638 static PSUPDRVVTGCOPY supdrvVtgFindObjectCopy(PSUPDRVDEVEXT pDevExt, PCVTGOBJHDR pHdr, uint32_t cbStrTab, uint32_t fFlags) 1639 { 1640 PRTLISTANCHOR pHashList = &pDevExt->aTrackerUmodHash[pHdr->Uuid.au8[3] % RT_ELEMENTS(pDevExt->aTrackerUmodHash)]; 1641 PSUPDRVVTGCOPY pRet; 1642 1643 int rc = RTSemFastMutexRequest(pDevExt->mtxTracer); 1644 AssertRCReturn(rc, NULL); 1645 1646 pRet = supdrvVtgFindObjectCopyLocked(pHashList, pHdr, cbStrTab, fFlags); 1647 1648 RTSemFastMutexRelease(pDevExt->mtxTracer); 1649 return pRet; 1650 } 1651 1652 1653 /** 1654 * Makes a shared copy of the VTG object. 1655 * 1656 * @returns VBox status code. 1657 * @param pDevExt The device extension. 1658 * @param pVtgHdr The VTG header (valid). 1659 * @param R3PtrVtgHdr The ring-3 VTG header address. 1660 * @param uVtgHdrAddr The address of the VTG header in the context 1661 * where it is actually used. 1662 * @param R3PtrStrTab The ring-3 address of the probe location string 1663 * table. The probe location array have offsets 1664 * into this instead of funciton name pointers. 1665 * @param cbStrTab The size of the probe location string table. 1666 * @param fFlags The user module flags. 1667 * @param pUmod The structure we've allocated to track the 1668 * module. This have a valid kernel mapping of the 1669 * probe location array. Upon successful return, 1670 * the pVtgCopy member will hold the address of our 1671 * copy (with a referenced of course). 1672 */ 1673 static int supdrvVtgCreateObjectCopy(PSUPDRVDEVEXT pDevExt, PCVTGOBJHDR pVtgHdr, RTR3PTR R3PtrVtgHdr, RTUINTPTR uVtgHdrAddr, 1674 RTR3PTR R3PtrStrTab, uint32_t cbStrTab, uint32_t fFlags, PSUPDRVTRACERUMOD pUmod) 1675 { 1676 /* 1677 * Calculate the space required, allocate and copy in the data. 1678 */ 1679 int rc; 1680 size_t const cProbeLocs = pVtgHdr->cbProbeLocs / (pVtgHdr->cBits == 32 ? sizeof(VTGPROBELOC32) : sizeof(VTGPROBELOC64)); 1681 size_t const cbProbeLocs = cProbeLocs * sizeof(VTGPROBELOC); 1682 size_t const offProbeLocs = RT_ALIGN(pVtgHdr->cbObj, 8); 1683 size_t const cb = offProbeLocs + cbProbeLocs + cbStrTab + 1; 1684 PSUPDRVVTGCOPY pThis = (PSUPDRVVTGCOPY)RTMemAlloc(RT_OFFSETOF(SUPDRVVTGCOPY, Hdr) + cb); 1685 if (!pThis) 1686 return VERR_NO_MEMORY; 1687 1688 pThis->u32Magic = SUDPRVVTGCOPY_MAGIC; 1689 pThis->cRefs = 1; 1690 pThis->cbStrTab = cbStrTab; 1691 pThis->fFlags = fFlags & SUP_TRACER_UMOD_FLAGS_TYPE_MASK; 1692 RTListInit(&pThis->ListEntry); 1693 1694 rc = RTR0MemUserCopyFrom(&pThis->Hdr, R3PtrVtgHdr, pVtgHdr->cbObj); 1695 if (RT_SUCCESS(rc)) 1696 { 1697 char *pchStrTab = (char *)&pThis->Hdr + offProbeLocs + cbProbeLocs; 1698 rc = RTR0MemUserCopyFrom(pchStrTab, R3PtrStrTab, cbStrTab); 1699 if (RT_SUCCESS(rc)) 1700 { 1701 PVTGPROBELOC paDst = (PVTGPROBELOC)((char *)&pThis->Hdr + offProbeLocs); 1702 uint32_t i; 1703 1704 /* 1705 * Some paranoia: Overwrite the header with the copy we've already 1706 * validated and zero terminate the string table. 1707 */ 1708 pThis->Hdr = *pVtgHdr; 1709 pchStrTab[cbStrTab] = '\0'; 1710 1711 /* 1712 * Set the probe location array related header members since we're 1713 * making our own copy in a different location. 1714 */ 1715 pThis->Hdr.uProbeLocs.u64 = (uintptr_t)paDst; 1716 pThis->Hdr.uProbeLocsEnd.u64 = (uintptr_t)paDst + cbProbeLocs; 1717 pThis->Hdr.offProbeLocs = offProbeLocs; 1718 pThis->Hdr.cbProbeLocs = cbProbeLocs; 1719 pThis->Hdr.cBits = ARCH_BITS; 1720 1721 /* 1722 * Copy, convert and fix up the the probe location table. 1723 */ 1724 if (pVtgHdr->cBits == 32) 1725 { 1726 uintptr_t const offDelta = (uintptr_t)&pThis->Hdr - uVtgHdrAddr; 1727 PCVTGPROBELOC32 paSrc = (PCVTGPROBELOC32)pUmod->pvProbeLocs; 1728 1729 for (i = 0; i < cProbeLocs; i++) 1730 { 1731 paDst[i].uLine = paSrc[i].uLine; 1732 paDst[i].fEnabled = paSrc[i].fEnabled; 1733 paDst[i].idProbe = paSrc[i].idProbe; 1734 if (paSrc[i].pszFunction > cbStrTab) 1735 { 1736 rc = VERR_SUPDRV_TRACER_UMOD_STRTAB_OFF_BAD; 1737 break; 1738 } 1739 paDst[i].pszFunction = pchStrTab + paSrc[i].pszFunction; 1740 paDst[i].pbProbe = (uint8_t *)(paSrc[i].pbProbe + offDelta); 1741 } 1742 } 1743 else 1744 { 1745 uint64_t const offDelta = (uintptr_t)&pThis->Hdr - uVtgHdrAddr; 1746 PCVTGPROBELOC64 paSrc = (PCVTGPROBELOC64)pUmod->pvProbeLocs; 1747 1748 for (i = 0; i < cProbeLocs; i++) 1749 { 1750 paDst[i].uLine = paSrc[i].uLine; 1751 paDst[i].fEnabled = paSrc[i].fEnabled; 1752 paDst[i].idProbe = paSrc[i].idProbe; 1753 if (paSrc[i].pszFunction > cbStrTab) 1754 { 1755 rc = VERR_SUPDRV_TRACER_UMOD_STRTAB_OFF_BAD; 1756 break; 1757 } 1758 paDst[i].pszFunction = pchStrTab + (uintptr_t)paSrc[i].pszFunction; 1759 paDst[i].pbProbe = (uint8_t *)(uintptr_t)(paSrc[i].pbProbe + offDelta); 1760 } 1761 } 1762 1763 /* 1764 * Validate it 1765 * 1766 * Note! fUmod is false as this is a kernel copy with all native 1767 * structures. 1768 */ 1769 if (RT_SUCCESS(rc)) 1770 rc = supdrvVtgValidate(&pThis->Hdr, (uintptr_t)&pThis->Hdr, (uint8_t *)&pThis->Hdr, cb, false /*fUmod*/); 1771 if (RT_SUCCESS(rc)) 1772 { 1773 /* 1774 * Add it to the hash list, making sure nobody raced us. 1775 */ 1776 PRTLISTANCHOR pHashList = &pDevExt->aTrackerUmodHash[ pVtgHdr->Uuid.au8[3] 1777 % RT_ELEMENTS(pDevExt->aTrackerUmodHash)]; 1778 1779 rc = RTSemFastMutexRequest(pDevExt->mtxTracer); 1780 if (RT_SUCCESS(rc)) 1781 { 1782 pUmod->pVtgCopy = supdrvVtgFindObjectCopyLocked(pHashList, pVtgHdr, cbStrTab, fFlags); 1783 if (!pUmod->pVtgCopy) 1784 { 1785 pUmod->pVtgCopy = pThis; 1786 RTListAppend(pHashList, &pThis->ListEntry); 1787 RTSemFastMutexRelease(pDevExt->mtxTracer); 1788 return rc; 1789 } 1790 1791 /* 1792 * Someone raced us, free our copy and return the existing 1793 * one instead. 1794 */ 1795 RTSemFastMutexRelease(pDevExt->mtxTracer); 1796 } 1797 } 1798 } 1799 } 1800 RTMemFree(pThis); 1801 return rc; 1802 } 1803 1804 1805 /** 1806 * Undoes what supdrvTracerUmodSetProbeIds did. 1807 * 1808 * @param pDevExt The device extension. 1809 * @param pSession The current session. 1810 * @param pUmod The user tracepoint module. 1811 */ 1812 static void supdrvTracerUmodClearProbeIds(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, PSUPDRVTRACERUMOD pUmod) 1813 { 1814 uint32_t i; 1815 1816 AssertReturnVoid(pUmod->iLookupTable < RT_ELEMENTS(pSession->apTpLookupTable)); 1817 AssertReturnVoid(pSession->apTpLookupTable[pUmod->iLookupTable] == pUmod); 1818 1819 /* 1820 * Clear the probe IDs and disable the probes. 1821 */ 1822 i = pUmod->cProbeLocs; 1823 if (pUmod->cBits == 32) 1824 { 1825 PVTGPROBELOC32 paProbeLocs = (PVTGPROBELOC32)pUmod->pvProbeLocs; 1826 while (i-- > 0) 1827 paProbeLocs[i].idProbe = 0; 1828 } 1829 else 1830 { 1831 PVTGPROBELOC64 paProbeLocs = (PVTGPROBELOC64)pUmod->pvProbeLocs; 1832 while (i-- > 0) 1833 paProbeLocs[i].idProbe = 0; 1834 } 1835 1836 /* 1837 * Free the lookup table entry. We'll have to wait for the table to go 1838 * idle to make sure there are no current users of pUmod. 1839 */ 1840 RTSemFastMutexRequest(pDevExt->mtxTracer); 1841 if (pSession->apTpLookupTable[pUmod->iLookupTable] == pUmod) 1842 { 1843 if (pSession->cTpProbesFiring > 0) 1844 { 1845 uint32_t i = 0; 1846 while (pSession->cTpProbesFiring > 0) 1847 { 1848 RTSemFastMutexRelease(pDevExt->mtxTracer); 1849 i++; 1850 if (!(i & 0xff)) 1851 SUPR0Printf("supdrvTracerUmodClearProbeIds: waiting for lookup table to go idle (i=%u)\n", i); 1852 RTThreadSleep(10); 1853 RTSemFastMutexRequest(pDevExt->mtxTracer); 1854 } 1855 } 1856 ASMAtomicWriteNullPtr(&pSession->apTpLookupTable[pUmod->iLookupTable]); 1857 } 1858 RTSemFastMutexRelease(pDevExt->mtxTracer); 1859 } 1860 1861 1862 /** 1863 * Allocates a lookup table entry for the Umod and sets the 1864 * VTGPROBELOC::idProbe fields in user mode. 1865 * 1866 * @returns VINF_SUCCESS or VERR_SUPDRV_TRACER_TOO_MANY_PROVIDERS. 1867 * @param pDevExt The device extension. 1868 * @param pSession The current session. 1869 * @param pUmod The user tracepoint module. 1870 */ 1871 static int supdrvTracerUmodSetProbeIds(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, PSUPDRVTRACERUMOD pUmod) 1872 { 1873 uint32_t iBase; 1874 uint32_t i; 1875 1876 /* 1877 * Allocate a lookup table entry. 1878 */ 1879 RTSemFastMutexRequest(pDevExt->mtxTracer); 1880 for (i = 0; i < RT_ELEMENTS(pSession->apTpLookupTable); i++) 1881 { 1882 if (!pSession->apTpLookupTable[i]) 1883 { 1884 pSession->apTpLookupTable[i] = pUmod; 1885 pUmod->iLookupTable = i; 1886 break; 1887 } 1888 } 1889 RTSemFastMutexRelease(pDevExt->mtxTracer); 1890 if (i >= RT_ELEMENTS(pSession->apTpLookupTable)) 1891 return VERR_SUPDRV_TRACER_TOO_MANY_PROVIDERS; 1892 1893 /* 1894 * Set probe IDs of the usermode probe location to indicate our lookup 1895 * table entry as well as the probe location array entry. 1896 */ 1897 iBase = (uint32_t)pUmod->iLookupTable << 24; 1898 i = pUmod->cProbeLocs; 1899 if (pUmod->cBits == 32) 1900 { 1901 PVTGPROBELOC32 paProbeLocs = (PVTGPROBELOC32)pUmod->pvProbeLocs; 1902 while (i-- > 0) 1903 paProbeLocs[i].idProbe = iBase | i; 1904 } 1905 else 1906 { 1907 PVTGPROBELOC64 paProbeLocs = (PVTGPROBELOC64)pUmod->pvProbeLocs; 1908 while (i-- > 0) 1909 paProbeLocs[i].idProbe = iBase | i; 1910 } 1911 1912 return VINF_SUCCESS; 1913 } 1914 1915 1916 int VBOXCALL supdrvIOCtl_TracerUmodRegister(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, 1917 RTR3PTR R3PtrVtgHdr, RTUINTPTR uVtgHdrAddr, 1918 RTR3PTR R3PtrStrTab, uint32_t cbStrTab, 1919 const char *pszModName, uint32_t fFlags) 1920 { 1921 VTGOBJHDR Hdr; 1922 PSUPDRVTRACERUMOD pUmod; 1923 RTR3PTR R3PtrLock; 1924 size_t cbLock; 1925 uint32_t cProbeLocs; 1926 int rc; 1927 1928 /* 1929 * Validate input. 1930 */ 1931 if (pSession->R0Process == NIL_RTR0PROCESS) 1932 return VERR_INVALID_CONTEXT; 1933 if ( fFlags != SUP_TRACER_UMOD_FLAGS_EXE 1934 && fFlags != SUP_TRACER_UMOD_FLAGS_SHARED) 1935 return VERR_INVALID_PARAMETER; 1936 1937 if (pSession->cTpProviders >= RT_ELEMENTS(pSession->apTpLookupTable)) 1938 return VERR_SUPDRV_TRACER_TOO_MANY_PROVIDERS; 1939 1940 if ( cbStrTab < 2 1941 || cbStrTab > _1M) 1942 return VERR_SUPDRV_TRACER_UMOD_STRTAB_TOO_BIG; 1943 1944 /* 1945 * Read the VTG header into a temporary buffer and perform some simple 1946 * validations to make sure we aren't wasting our time here. 1947 */ 1948 rc = RTR0MemUserCopyFrom(&Hdr, R3PtrVtgHdr, sizeof(Hdr)); 1949 if (RT_FAILURE(rc)) 1950 return rc; 1951 rc = supdrvVtgValidateHdr(&Hdr, uVtgHdrAddr, NULL, 0, true /*fUmod*/); 1952 if (RT_FAILURE(rc)) 1953 return rc; 1954 if (Hdr.cbProviders / sizeof(VTGDESCPROVIDER) > 2) 1955 return VERR_SUPDRV_TRACER_TOO_MANY_PROVIDERS; 1956 1957 /* 1958 * Check how much needs to be locked down and how many probe locations 1959 * there are. 1960 */ 1961 if ( Hdr.offProbeLocs <= 0 1962 || Hdr.offProbeEnabled > (uint32_t)Hdr.offProbeLocs 1963 || (uint32_t)Hdr.offProbeLocs - Hdr.offProbeEnabled - Hdr.cbProbeEnabled > 128) 1964 return VERR_SUPDRV_TRACER_UMOD_NOT_ADJACENT; 1965 R3PtrLock = R3PtrVtgHdr + Hdr.offProbeEnabled; 1966 cbLock = Hdr.offProbeLocs + Hdr.cbProbeLocs - Hdr.offProbeEnabled + (R3PtrLock & PAGE_OFFSET_MASK); 1967 R3PtrLock &= ~(RTR3PTR)PAGE_OFFSET_MASK; 1968 if (cbLock > _64K) 1969 return VERR_SUPDRV_TRACER_UMOD_TOO_MANY_PROBES; 1970 1971 cProbeLocs = Hdr.cbProbeLocs / (Hdr.cBits == 32 ? sizeof(VTGPROBELOC32) : sizeof(VTGPROBELOC64)); 1972 1973 /* 1974 * Allocate the tracker data we keep in the session. 1975 */ 1976 pUmod = (PSUPDRVTRACERUMOD)RTMemAllocZ( RT_OFFSETOF(SUPDRVTRACERUMOD, aProbeLocs[cProbeLocs]) 1977 + (Hdr.cbProbeEnabled / sizeof(uint32_t) * sizeof(SUPDRVPROBEINFO)) ); 1978 if (!pUmod) 1979 return VERR_NO_MEMORY; 1980 pUmod->u32Magic = SUPDRVTRACERUMOD_MAGIC; 1981 RTListInit(&pUmod->ListEntry); 1982 pUmod->R3PtrVtgHdr = R3PtrVtgHdr; 1983 pUmod->pVtgCopy = NULL; 1984 pUmod->hMemObjLock = NIL_RTR0MEMOBJ; 1985 pUmod->hMemObjMap = NIL_RTR0MEMOBJ; 1986 pUmod->R3PtrProbeLocs = (RTR3INTPTR)R3PtrVtgHdr + Hdr.offProbeLocs; 1987 pUmod->iLookupTable = UINT8_MAX; 1988 pUmod->cBits = Hdr.cBits; 1989 pUmod->cbProbeLoc = Hdr.cBits == 32 ? sizeof(VTGPROBELOC32) : sizeof(VTGPROBELOC64); 1990 pUmod->cProbeLocs = cProbeLocs; 1991 1992 /* 1993 * Lock down and map the user-mode structures. 1994 */ 1995 rc = RTR0MemObjLockUser(&pUmod->hMemObjLock, R3PtrLock, cbLock, RTMEM_PROT_READ | RTMEM_PROT_WRITE, NIL_RTR0PROCESS); 1996 if (RT_SUCCESS(rc)) 1997 { 1998 rc = RTR0MemObjMapKernel(&pUmod->hMemObjMap, pUmod->hMemObjLock, (void *)-1, 0, RTMEM_PROT_READ | RTMEM_PROT_WRITE); 1999 if (RT_SUCCESS(rc)) 2000 { 2001 pUmod->pacProbeEnabled = (uint32_t *)( (uintptr_t)RTR0MemObjAddress(pUmod->hMemObjMap) 2002 + ((uintptr_t)(R3PtrVtgHdr + Hdr.offProbeEnabled) & PAGE_OFFSET_MASK)); 2003 pUmod->pvProbeLocs = (uint8_t *)pUmod->pacProbeEnabled + Hdr.offProbeLocs - Hdr.offProbeEnabled; 2004 2005 /* 2006 * Does some other process use the same module already? If so, 2007 * share the VTG data with it. Otherwise, make a ring-0 copy it. 2008 */ 2009 pUmod->pVtgCopy = supdrvVtgFindObjectCopy(pDevExt, &Hdr, cbStrTab, fFlags); 2010 if (!pUmod->pVtgCopy) 2011 rc = supdrvVtgCreateObjectCopy(pDevExt, &Hdr, R3PtrVtgHdr, uVtgHdrAddr, R3PtrStrTab, cbStrTab, fFlags, pUmod); 2012 if (RT_SUCCESS(rc)) 2013 { 2014 AssertPtr(pUmod->pVtgCopy); 2015 2016 /* 2017 * Grabe a place in apTpLookupTable and set the probe IDs 2018 * accordingly. 2019 */ 2020 rc = supdrvTracerUmodSetProbeIds(pDevExt, pSession, pUmod); 2021 if (RT_SUCCESS(rc)) 2022 { 2023 /* 2024 * Register the providers. 2025 */ 2026 rc = supdrvTracerRegisterVtgObj(pDevExt, &pUmod->pVtgCopy->Hdr, 2027 NULL /*pImage*/, pSession, pUmod, pszModName); 2028 if (RT_SUCCESS(rc)) 2029 { 2030 RTSemFastMutexRequest(pDevExt->mtxTracer); 2031 RTListAppend(&pSession->TpUmods, &pUmod->ListEntry); 2032 RTSemFastMutexRelease(pDevExt->mtxTracer); 2033 2034 return VINF_SUCCESS; 2035 } 2036 2037 /* bail out. */ 2038 supdrvTracerUmodClearProbeIds(pDevExt, pSession, pUmod); 2039 } 2040 supdrvVtgReleaseObjectCopy(pDevExt, pUmod->pVtgCopy); 2041 } 2042 RTR0MemObjFree(pUmod->hMemObjMap, false /*fFreeMappings*/); 2043 } 2044 RTR0MemObjFree(pUmod->hMemObjLock, false /*fFreeMappings*/); 2045 } 2046 pUmod->u32Magic = ~SUPDRVTRACERUMOD_MAGIC; 2047 RTMemFree(pUmod); 2048 return rc; 2049 } 2050 2051 2052 int VBOXCALL supdrvIOCtl_TracerUmodDeregister(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, RTR3PTR R3PtrVtgHdr) 2053 { 2054 PSUPDRVTRACERUMOD pUmod = NULL; 2055 uint32_t i; 2056 int rc; 2057 2058 /* 2059 * Validate the request. 2060 */ 2061 RTSemFastMutexRequest(pDevExt->mtxTracer); 2062 for (i = 0; i < RT_ELEMENTS(pSession->apTpLookupTable); i++) 2063 { 2064 pUmod = pSession->apTpLookupTable[i]; 2065 if ( pUmod 2066 && pUmod->u32Magic == SUPDRVTRACERUMOD_MAGIC 2067 && pUmod->R3PtrVtgHdr == R3PtrVtgHdr) 2068 break; 2069 } 2070 RTSemFastMutexRelease(pDevExt->mtxTracer); 2071 if (pUmod) 2072 { 2073 SUPDRVTPPROVIDER *pProvNext; 2074 SUPDRVTPPROVIDER *pProv; 2075 2076 /* 2077 * Remove ourselves from the lookup table and clean up the ring-3 bits 2078 * we've dirtied. We do this first to make sure no probes are firing 2079 * when we're destroying the providers in the next step. 2080 */ 2081 supdrvTracerUmodClearProbeIds(pDevExt, pSession, pUmod); 2082 2083 /* 2084 * Deregister providers related to the VTG object. 2085 */ 2086 RTSemFastMutexRequest(pDevExt->mtxTracer); 2087 RTListForEachSafe(&pSession->TpProviders, pProv, pProvNext, SUPDRVTPPROVIDER, SessionListEntry) 2088 { 2089 if (pProv->pUmod == pUmod) 2090 supdrvTracerDeregisterVtgObj(pDevExt, pProv); 2091 } 2092 RTSemFastMutexRelease(pDevExt->mtxTracer); 2093 2094 /* 2095 * Destroy the Umod object. 2096 */ 2097 pUmod->u32Magic = ~SUPDRVTRACERUMOD_MAGIC; 2098 supdrvVtgReleaseObjectCopy(pDevExt, pUmod->pVtgCopy); 2099 RTR0MemObjFree(pUmod->hMemObjMap, false /*fFreeMappings*/); 2100 RTR0MemObjFree(pUmod->hMemObjLock, false /*fFreeMappings*/); 2101 RTMemFree(pUmod); 2102 } 2103 else 2104 rc = VERR_NOT_FOUND; 2105 return rc; 2106 } 2107 2108 2109 /** 2110 * Implementation of supdrvIOCtl_TracerUmodProbeFire and 2111 * SUPR0TracerUmodProbeFire. 2112 * 2113 * @param pDevExt The device extension. 2114 * @param pSession The calling session. 2115 * @param pCtx The context record. 2116 */ 2117 static void supdrvTracerUmodProbeFire(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, PSUPDRVTRACERUSRCTX pCtx) 2118 { 2119 /* 2120 * We cannot trust user mode to hand us the right bits nor not calling us 2121 * when disabled. So, we have to check for our selves. 2122 */ 2123 PSUPDRVTRACERUMOD pUmod; 2124 uint32_t const iLookupTable = pCtx->idProbe >> 24; 2125 uint32_t const iProbeLoc = pCtx->idProbe & UINT32_C(0x00ffffff); 2126 2127 if (RT_UNLIKELY( !pDevExt->pTracerOps 2128 || pDevExt->fTracerUnloading)) 2129 return; 2130 if (RT_UNLIKELY(iLookupTable >= RT_ELEMENTS(pSession->apTpLookupTable))) 2131 return; 2132 if (RT_UNLIKELY( pCtx->cBits != 32 2133 && pCtx->cBits != 64)) 2134 return; 2135 2136 ASMAtomicIncU32(&pSession->cTpProviders); 2137 2138 pUmod = pSession->apTpLookupTable[iLookupTable]; 2139 if (RT_LIKELY(pUmod)) 2140 { 2141 if (RT_LIKELY( pUmod->u32Magic == SUPDRVTRACERUMOD_MAGIC 2142 && iProbeLoc < pUmod->cProbeLocs 2143 && pCtx->cBits == pUmod->cBits)) 2144 { 2145 RTR3PTR R3PtrProbeLoc = pUmod->R3PtrProbeLocs + iProbeLoc * pUmod->cbProbeLoc; 2146 if (RT_LIKELY( (pCtx->cBits == 32 ? (RTR3PTR)pCtx->u.X86.uVtgProbeLoc : pCtx->u.Amd64.uVtgProbeLoc) 2147 == R3PtrProbeLoc)) 2148 { 2149 if (RT_LIKELY(pUmod->aProbeLocs[iProbeLoc].fEnabled)) 2150 { 2151 ASMAtomicIncU32(&pDevExt->cTracerCallers); 2152 if (RT_LIKELY( pDevExt->pTracerOps 2153 && !pDevExt->fTracerUnloading)) 2154 { 2155 pCtx->idProbe = pUmod->aProbeLocs[iProbeLoc].idProbe; 2156 pDevExt->pTracerOps->pfnProbeFireUser(pDevExt->pTracerOps, pSession, pCtx); 2157 } 2158 ASMAtomicDecU32(&pDevExt->cTracerCallers); 2159 } 2160 } 2161 } 2162 } 2163 2164 ASMAtomicDecU32(&pSession->cTpProviders); 2165 } 2166 2167 2168 SUPR0DECL(void) SUPR0TracerUmodProbeFire(PSUPDRVSESSION pSession, PSUPDRVTRACERUSRCTX pCtx) 2169 { 2170 AssertReturnVoid(SUP_IS_SESSION_VALID(pSession)); 2171 AssertPtrReturnVoid(pCtx); 2172 2173 supdrvTracerUmodProbeFire(pSession->pDevExt, pSession, pCtx); 2174 } 2175 2176 2177 void VBOXCALL supdrvIOCtl_TracerUmodProbeFire(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, PSUPDRVTRACERUSRCTX pCtx) 2178 { 2179 supdrvTracerUmodProbeFire(pDevExt, pSession, pCtx); 1248 2180 } 1249 2181 … … 1434 2366 if (RT_SUCCESS(rc)) 1435 2367 { 2368 uint32_t i; 2369 1436 2370 pDevExt->TracerHlp.uVersion = SUPDRVTRACERHLP_VERSION; 1437 2371 /** @todo */ … … 1439 2373 RTListInit(&pDevExt->TracerProviderList); 1440 2374 RTListInit(&pDevExt->TracerProviderZombieList); 2375 for (i = 0; i < RT_ELEMENTS(pDevExt->aTrackerUmodHash); i++) 2376 RTListInit(&pDevExt->aTrackerUmodHash[i]); 1441 2377 1442 2378 #ifdef VBOX_WITH_NATIVE_DTRACE … … 1450 2386 */ 1451 2387 #ifdef VBOX_WITH_DTRACE_R0DRV 1452 rc = supdrvTracerRegisterVtgObj(pDevExt, &g_VTGObjHeader, _1M, NULL /*pImage*/, NULL /*pSession*/, "vboxdrv");2388 rc = supdrvTracerRegisterVtgObj(pDevExt, &g_VTGObjHeader, NULL /*pImage*/, NULL /*pSession*/, NULL /*pUmod*/, "vboxdrv"); 1453 2389 if (RT_SUCCESS(rc)) 1454 2390 return rc; -
trunk/src/VBox/HostDrivers/Support/SUPLib.cpp
r40981 r41117 51 51 #include <VBox/param.h> 52 52 #include <VBox/log.h> 53 #include <VBox/VBoxTpG.h> 53 54 54 55 #include <iprt/assert.h> … … 2389 2390 2390 2391 2391 SUPDECL(void) SUPTracerFireProbe(struct VTGPROBELOC *pVtgProbeLoc, uintptr_t uArg0, uintptr_t uArg1, uintptr_t uArg2, 2392 uintptr_t uArg3, uintptr_t uArg4) 2393 { 2394 /* C and stubbed for now. */ 2395 } 2396 2397 2398 SUPR3DECL(int) SUPR3TracerRegisterModule(uintptr_t hModNative, const char *pszModule, struct VTGOBJHDR *pVtgHdr, uint32_t fFlags) 2392 typedef struct SUPDRVTRACERSTRTAB 2393 { 2394 /** Pointer to the string table. */ 2395 char *pchStrTab; 2396 /** The actual string table size. */ 2397 uint32_t cbStrTab; 2398 /** The original string pointers. */ 2399 RTUINTPTR apszOrgFunctions[1]; 2400 } SUPDRVTRACERSTRTAB, *PSUPDRVTRACERSTRTAB; 2401 2402 2403 /** 2404 * Destroys a string table, restoring the original pszFunction member valus. 2405 * 2406 * @param pThis The string table structure. 2407 * @param paProbLocs The probe location array. 2408 * @param cProbLocs The number of probe locations. 2409 */ 2410 static void supr3TracerDestroyStrTab(PSUPDRVTRACERSTRTAB pThis, PVTGPROBELOC32 paProbeLocs32, PVTGPROBELOC64 paProbeLocs64, 2411 uint32_t cProbeLocs, bool f32Bit) 2412 { 2413 /* Restore. */ 2414 size_t i = cProbeLocs; 2415 if (f32Bit) 2416 while (i--) 2417 paProbeLocs32[i].pszFunction = (uint32_t)pThis->apszOrgFunctions[i]; 2418 else 2419 while (i--) 2420 paProbeLocs64[i].pszFunction = pThis->apszOrgFunctions[i]; 2421 2422 /* Free. */ 2423 RTMemFree(pThis->pchStrTab); 2424 RTMemFree(pThis); 2425 } 2426 2427 2428 /** 2429 * Creates a string table for the pszFunction members in the probe location 2430 * array. 2431 * 2432 * This will save and replace the pszFunction members with offsets. 2433 * 2434 * @returns Pointer to a string table structure. NULL on failure. 2435 * @param paProbLocs The probe location array. 2436 * @param cProbLocs The number of elements in the array. 2437 * @param cBits 2438 */ 2439 static PSUPDRVTRACERSTRTAB supr3TracerCreateStrTab(PVTGPROBELOC32 paProbeLocs32, 2440 PVTGPROBELOC64 paProbeLocs64, 2441 uint32_t cProbeLocs, 2442 RTUINTPTR offDelta, 2443 bool f32Bit) 2444 { 2445 if (cProbeLocs > _128K) 2446 return NULL; 2447 2448 /* 2449 * Allocate the string table structures. 2450 */ 2451 size_t cbThis = RT_OFFSETOF(SUPDRVTRACERSTRTAB, apszOrgFunctions[cProbeLocs]); 2452 PSUPDRVTRACERSTRTAB pThis = (PSUPDRVTRACERSTRTAB)RTMemAlloc(cbThis); 2453 if (!pThis) 2454 return NULL; 2455 2456 uint32_t const cHashBits = cProbeLocs * 2 - 1; 2457 uint32_t *pbmHash = (uint32_t *)RTMemAllocZ(RT_ALIGN_32(cHashBits, 64) / 8 ); 2458 if (!pbmHash) 2459 { 2460 RTMemFree(pThis); 2461 return NULL; 2462 } 2463 2464 /* 2465 * Calc the max string table size and save the orignal pointers so we can 2466 * replace them later. 2467 */ 2468 size_t cbMax = 1; 2469 for (uint32_t i = 0; i < cProbeLocs; i++) 2470 { 2471 pThis->apszOrgFunctions[i] = f32Bit ? paProbeLocs32[i].pszFunction : paProbeLocs64[i].pszFunction; 2472 const char *pszFunction = (const char *)(uintptr_t)(pThis->apszOrgFunctions[i] + offDelta); 2473 size_t cch = strlen(pszFunction); 2474 if (cch > _1K) 2475 { 2476 cbMax = 0; 2477 break; 2478 } 2479 cbMax += cch + 1; 2480 } 2481 2482 /* Alloc space for it. */ 2483 if (cbMax > 0) 2484 pThis->pchStrTab = (char *)RTMemAlloc(cbMax); 2485 else 2486 pThis->pchStrTab = NULL; 2487 if (!pThis->pchStrTab) 2488 { 2489 RTMemFree(pbmHash); 2490 RTMemFree(pThis); 2491 return NULL; 2492 } 2493 2494 /* 2495 * Create the string table. 2496 */ 2497 uint32_t off = 0; 2498 uint32_t offPrev = 0; 2499 2500 for (uint32_t i = 0; i < cProbeLocs; i++) 2501 { 2502 const char * const psz = (const char *)(uintptr_t)(pThis->apszOrgFunctions[i] + offDelta); 2503 size_t const cch = strlen(psz); 2504 uint32_t const iHashBit = RTStrHash1(psz) % cHashBits; 2505 if (ASMBitTestAndSet(pbmHash, iHashBit)) 2506 { 2507 /* Often it's the most recent string. */ 2508 if ( off - offPrev < cch + 1 2509 || memcmp(&pThis->pchStrTab[offPrev], psz, cch + 1)) 2510 { 2511 /* It wasn't, search the entire string table. (lazy bird) */ 2512 offPrev = 0; 2513 while (offPrev < off) 2514 { 2515 size_t cchCur = strlen(&pThis->pchStrTab[offPrev]); 2516 if ( cchCur == cch 2517 && !memcmp(&pThis->pchStrTab[offPrev], psz, cch + 1)) 2518 break; 2519 offPrev += (uint32_t)cchCur + 1; 2520 } 2521 } 2522 } 2523 else 2524 offPrev = off; 2525 2526 /* Add the string to the table. */ 2527 if (offPrev >= off) 2528 { 2529 memcpy(&pThis->pchStrTab[off], psz, cch + 1); 2530 offPrev = off; 2531 off += (uint32_t)cch + 1; 2532 } 2533 2534 /* Update the entry */ 2535 if (f32Bit) 2536 paProbeLocs32[i].pszFunction = offPrev; 2537 else 2538 paProbeLocs64[i].pszFunction = offPrev; 2539 } 2540 2541 pThis->cbStrTab = off; 2542 RTMemFree(pbmHash); 2543 return pThis; 2544 } 2545 2546 2547 2548 SUPR3DECL(int) SUPR3TracerRegisterModule(uintptr_t hModNative, const char *pszModule, struct VTGOBJHDR *pVtgHdr, 2549 RTUINTPTR uVtgHdrAddr, uint32_t fFlags) 2399 2550 { 2400 2551 /* Validate input. */ 2401 2552 NOREF(hModNative); 2402 2553 AssertPtrReturn(pVtgHdr, VERR_INVALID_POINTER); 2554 AssertReturn(!memcmp(pVtgHdr->szMagic, VTGOBJHDR_MAGIC, sizeof(pVtgHdr->szMagic)), VERR_SUPDRV_VTG_MAGIC); 2403 2555 AssertPtrReturn(pszModule, VERR_INVALID_POINTER); 2404 2556 size_t cchModule = strlen(pszModule); … … 2407 2559 AssertReturn(fFlags == SUP_TRACER_UMOD_FLAGS_EXE || fFlags == SUP_TRACER_UMOD_FLAGS_SHARED, VERR_INVALID_PARAMETER); 2408 2560 2409 /* fake */ 2561 /* 2562 * Set the probe location array offset and size members. If the size is 2563 * zero, don't bother ring-0 with it. 2564 */ 2565 if (!pVtgHdr->offProbeLocs) 2566 { 2567 uint64_t u64Tmp = pVtgHdr->uProbeLocsEnd.u64 - pVtgHdr->uProbeLocs.u64; 2568 if (u64Tmp >= UINT32_MAX) 2569 return VERR_SUPDRV_VTG_BAD_HDR_TOO_MUCH; 2570 pVtgHdr->cbProbeLocs = (uint32_t)u64Tmp; 2571 2572 u64Tmp = pVtgHdr->uProbeLocs.u64 - (uintptr_t)pVtgHdr; 2573 if ((int64_t)u64Tmp != (int32_t)u64Tmp) 2574 return VERR_SUPDRV_VTG_BAD_HDR_PTR; 2575 pVtgHdr->offProbeLocs = (int32_t)u64Tmp; 2576 } 2577 2578 if ( !pVtgHdr->cbProbeLocs 2579 || !pVtgHdr->cbProbes) 2580 return VINF_SUCCESS; 2581 2582 /* 2583 * Fake out. 2584 */ 2410 2585 if (RT_UNLIKELY(g_u32FakeMode)) 2411 2586 return VINF_SUCCESS; 2587 2588 /* 2589 * Create a string table for the function names in the location array. 2590 * It's somewhat easier to do that here than from ring-0. 2591 */ 2592 size_t const cProbeLocs = pVtgHdr->cbProbeLocs 2593 / (pVtgHdr->cBits == 32 ? sizeof(VTGPROBELOC32) : sizeof(VTGPROBELOC64)); 2594 PVTGPROBELOC paProbeLocs = (PVTGPROBELOC)((uintptr_t)pVtgHdr + pVtgHdr->offProbeLocs); 2595 PSUPDRVTRACERSTRTAB pStrTab = supr3TracerCreateStrTab((PVTGPROBELOC32)paProbeLocs, 2596 (PVTGPROBELOC64)paProbeLocs, 2597 cProbeLocs, (uintptr_t)pVtgHdr - uVtgHdrAddr, 2598 pVtgHdr->cBits == 32); 2599 if (!pStrTab) 2600 return VERR_NO_MEMORY; 2601 2412 2602 2413 2603 /* … … 2421 2611 Req.Hdr.fFlags = SUPREQHDR_FLAGS_DEFAULT; 2422 2612 Req.Hdr.rc = VERR_INTERNAL_ERROR; 2423 Req.u.In.pVtgHdr = pVtgHdr; 2613 Req.u.In.uVtgHdrAddr = uVtgHdrAddr; 2614 Req.u.In.R3PtrVtgHdr = pVtgHdr; 2615 Req.u.In.R3PtrStrTab = pStrTab->pchStrTab; 2616 Req.u.In.cbStrTab = pStrTab->cbStrTab; 2424 2617 Req.u.In.fFlags = fFlags; 2425 2618 … … 2451 2644 if (RT_SUCCESS(rc)) 2452 2645 rc = Req.Hdr.rc; 2646 2647 supr3TracerDestroyStrTab(pStrTab, (PVTGPROBELOC32)paProbeLocs, (PVTGPROBELOC64)paProbeLocs, 2648 cProbeLocs, pVtgHdr->cBits == 32); 2453 2649 return rc; 2454 2650 } … … 2459 2655 /* Validate input. */ 2460 2656 AssertPtrReturn(pVtgHdr, VERR_INVALID_POINTER); 2461 2462 /* fake */ 2657 AssertReturn(!memcmp(pVtgHdr->szMagic, VTGOBJHDR_MAGIC, sizeof(pVtgHdr->szMagic)), VERR_SUPDRV_VTG_MAGIC); 2658 2659 /* 2660 * Don't bother if the object is empty. 2661 */ 2662 if ( !pVtgHdr->cbProbeLocs 2663 || !pVtgHdr->cbProbes) 2664 return VINF_SUCCESS; 2665 2666 /* 2667 * Fake out. 2668 */ 2463 2669 if (RT_UNLIKELY(g_u32FakeMode)) 2464 2670 return VINF_SUCCESS; … … 2482 2688 } 2483 2689 2690 2691 DECLASM(void) suplibTracerFireProbe(PVTGPROBELOC pProbeLoc, PSUPTRACERUMODFIREPROBE pReq) 2692 { 2693 pReq->Hdr.u32Cookie = g_u32Cookie; 2694 pReq->Hdr.u32SessionCookie = g_u32SessionCookie; 2695 Assert(pReq->Hdr.cbIn == SUP_IOCTL_TRACER_UMOD_FIRE_PROBE_SIZE_IN); 2696 Assert(pReq->Hdr.cbOut == SUP_IOCTL_TRACER_UMOD_FIRE_PROBE_SIZE_OUT); 2697 pReq->Hdr.fFlags = SUPREQHDR_FLAGS_DEFAULT; 2698 pReq->Hdr.rc = VINF_SUCCESS; 2699 2700 suplibOsIOCtl(&g_supLibData, SUP_IOCTL_TRACER_UMOD_FIRE_PROBE, pReq, SUP_IOCTL_TRACER_UMOD_FIRE_PROBE_SIZE); 2701 } 2702
Note:
See TracChangeset
for help on using the changeset viewer.