Changeset 40756 in vbox for trunk/src/VBox/HostDrivers/Support/SUPDrv-tracer.cpp
- Timestamp:
- Apr 3, 2012 2:47:33 PM (13 years ago)
- File:
-
- 1 copied
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/HostDrivers/Support/SUPDrv-tracer.cpp
r40753 r40756 1 1 /* $Id$ */ 2 2 /** @file 3 * VBoxDrv - The VirtualBox Support Driver - DTrace Provider.3 * VBoxDrv - The VirtualBox Support Driver - Generic Tracer Interface. 4 4 */ 5 5 … … 30 30 *******************************************************************************/ 31 31 #define LOG_GROUP LOG_GROUP_SUP_DRV 32 #define SUPDRV_AGNOSTIC 32 33 #include "SUPDrvInternal.h" 33 34 … … 43 44 #include <iprt/thread.h> 44 45 45 #ifdef RT_OS_DARWIN /** @todo figure this! */46 # include "/Developer/SDKs/MacOSX10.6.sdk/usr/include/sys/dtrace.h"47 #else48 # include <sys/dtrace.h>49 #endif50 51 46 52 47 /******************************************************************************* … … 54 49 *******************************************************************************/ 55 50 /** 56 * Data for a provider.57 */ 58 typedef struct SUPDRV DTPROVIDER51 * Data for a tracepoint provider. 52 */ 53 typedef struct SUPDRVTPPROVIDER 59 54 { 60 55 /** The entry in the provider list for this image. */ 61 RTLISTNODE ListEntry; 62 63 /** The provider descriptor. */ 64 PVTGDESCPROVIDER pDesc; 65 /** The VTG header. */ 66 PVTGOBJHDR pHdr; 56 RTLISTNODE ListEntry; 57 58 /** The core structure. */ 59 SUPDRVVDTPROVIDERCORE Core; 67 60 68 61 /** Pointer to the image this provider resides in. NULL if it's a 69 62 * driver. */ 70 PSUPDRVLDRIMAGE pImage;63 PSUPDRVLDRIMAGE pImage; 71 64 /** The session this provider is associated with if registered via 72 65 * SUPR0VtgRegisterDrv. NULL if pImage is set. */ 73 PSUPDRVSESSION pSession;66 PSUPDRVSESSION pSession; 74 67 /** The module name. */ 75 const char *pszModName; 76 77 /** Dtrace provider attributes. */ 78 dtrace_pattr_t DtAttrs; 79 /** The ID of this provider. */ 80 dtrace_provider_id_t idDtProv; 81 /** The number of probes we've provided to DTrace. */ 82 uint32_t cProvidedProbes; 68 const char *pszModName; 69 83 70 /** Set when the module is unloaded or the driver deregisters its probes. */ 84 bool fZombie; 71 bool fZombie; 72 /** Set if the provider has been successfully registered with the 73 * tracer. */ 74 bool fRegistered; 85 75 /** The provider name (for logging purposes). */ 86 char szName[1]; 87 } SUPDRVDTPROVIDER; 88 /** Pointer to the data for a provider. */ 89 typedef SUPDRVDTPROVIDER *PSUPDRVDTPROVIDER; 90 91 /* Seems there is some return code difference here. Keep the return code and 92 case it to whatever the host desires. */ 93 #ifdef RT_OS_DARWIN 94 typedef void FNPOPS_ENABLE(void *, dtrace_id_t, void *); 95 #else 96 typedef int FNPOPS_ENABLE(void *, dtrace_id_t, void *); 97 #endif 76 char szName[1]; 77 } SUPDRVTPPROVIDER; 78 /** Pointer to the data for a tracepoint provider. */ 79 typedef SUPDRVTPPROVIDER *PSUPDRVTPPROVIDER; 98 80 99 81 … … 102 84 *******************************************************************************/ 103 85 #if 0 104 # define LOG_ DTRACE(a_Args) SUPR0Printf a_Args86 # define LOG_TRACER(a_Args) SUPR0Printf a_Args 105 87 #else 106 # define LOG_ DTRACE(a_Args) do { } while (0)88 # define LOG_TRACER(a_Args) do { } while (0) 107 89 #endif 108 109 /*******************************************************************************110 * Internal Functions *111 *******************************************************************************/112 static void supdrvDTracePOps_Provide(void *pvProv, const dtrace_probedesc_t *pDtProbeDesc);113 static int supdrvDTracePOps_Enable(void *pvProv, dtrace_id_t idProbe, void *pvProbe);114 static void supdrvDTracePOps_Disable(void *pvProv, dtrace_id_t idProbe, void *pvProbe);115 static void supdrvDTracePOps_GetArgDesc(void *pvProv, dtrace_id_t idProbe, void *pvProbe,116 dtrace_argdesc_t *pArgDesc);117 #ifdef RT_OS_SOLARIS118 static uint64_t supdrvDTracePOps_GetArgVal(void *pvProv, dtrace_id_t idProbe, void *pvProbe,119 int iArg, int cFrames);120 #endif121 static void supdrvDTracePOps_Destroy(void *pvProv, dtrace_id_t idProbe, void *pvProbe);122 123 90 124 91 … … 126 93 * Global Variables * 127 94 *******************************************************************************/ 128 /**129 * DTrace provider method table.130 */131 static const dtrace_pops_t g_SupDrvDTraceProvOps =132 {133 /* .dtps_provide = */ supdrvDTracePOps_Provide,134 /* .dtps_provide_module = */ NULL,135 /* .dtps_enable = */ (FNPOPS_ENABLE *)supdrvDTracePOps_Enable,136 /* .dtps_disable = */ supdrvDTracePOps_Disable,137 /* .dtps_suspend = */ NULL,138 /* .dtps_resume = */ NULL,139 /* .dtps_getargdesc = */ supdrvDTracePOps_GetArgDesc,140 #ifdef RT_OS_SOLARIS141 /* .dtps_getargval = */ supdrvDTracePOps_GetArgVal,142 #else143 /* .dtps_getargval = */ NULL/*supdrvDTracePOps_GetArgVal*/,144 #endif145 /* .dtps_usermode = */ NULL,146 /* .dtps_destroy = */ supdrvDTracePOps_Destroy147 };148 95 149 96 … … 366 313 367 314 /** 368 * Converts an attribute from VTG description speak to DTrace.369 *370 * @param pDtAttr The DTrace attribute (dst).371 * @param pVtgAttr The VTG attribute descriptor (src).372 */373 static void supdrvVtgConvAttr(dtrace_attribute_t *pDtAttr, PCVTGDESCATTR pVtgAttr)374 {375 pDtAttr->dtat_name = pVtgAttr->u8Code - 1;376 pDtAttr->dtat_data = pVtgAttr->u8Data - 1;377 pDtAttr->dtat_class = pVtgAttr->u8DataDep - 1;378 }379 380 /**381 315 * Gets a string from the string table. 382 316 * … … 393 327 394 328 /** 395 * Frees the provider structure and associated resources. 396 * 329 * Frees the provider structure and associated resources. 330 * 397 331 * @param pProv The provider to free. 398 332 */ 399 static void supdrvVtgFreeProvider(PSUPDRVDTPROVIDER pProv) 400 { 401 LOG_DTRACE(("Freeing DTrace provider '%s' / %p\n", pProv->szName, pProv->idDtProv)); 333 static void supdrvTracerFreeProvider(PSUPDRVTPPROVIDER pProv) 334 { 335 LOG_TRACER(("Freeing DTrace provider '%s' / %p\n", pProv->szName, pProv->Core.TracerData.DTrace.idProvider)); 336 pProv->fRegistered = false; 337 pProv->fZombie = true; 338 pProv->Core.pDesc = NULL; 339 pProv->Core.pHdr = NULL; 340 RT_ZERO(pProv->Core.TracerData); 341 RTMemFree(pProv); 342 } 343 344 345 /** 346 * Deregisters a provider. 347 * 348 * If the provider is still busy, it will be put in the zombie list. 349 * 350 * @param pDevExt The device extension. 351 * @param pProv The provider. 352 * 353 * @remarks The caller owns mtxTracer. 354 */ 355 static void supdrvTracerDeregisterVtgObj(PSUPDRVDEVEXT pDevExt, PSUPDRVTPPROVIDER pProv) 356 { 357 int rc; 358 if (!pProv->fRegistered || !pDevExt->pTracerOps) 359 rc = VINF_SUCCESS; 360 else 361 rc = pDevExt->pTracerOps->pfnDeregisterProvider(pDevExt->pTracerOps, &pProv->Core); 362 if (RT_SUCCESS(rc)) 363 { 364 supdrvTracerFreeProvider(pProv); 365 return; 366 } 367 402 368 pProv->fZombie = true; 403 pProv->pDesc = NULL; 404 pProv->pHdr = NULL; 405 RTMemFree(pProv); 406 } 407 408 409 /** 410 * Deregisters a provider. 411 * 412 * If the provider is still busy, it will be put in the zombie list. 413 * 369 RTListAppend(&pDevExt->TracerProviderZombieList, &pProv->ListEntry); 370 LOG_TRACER(("Invalidated provider '%s' / %p and put it on the zombie list (rc=%Rrc)\n", 371 pProv->szName, pProv->Core.TracerData.DTrace.idProvider, rc)); 372 } 373 374 375 /** 376 * Processes the zombie list. 377 * 414 378 * @param pDevExt The device extension. 415 * @param pProv The provider.416 * 417 * @remarks The caller owns mtxDTrace. 418 */419 static void supdrvVtgDeregister(PSUPDRVDEVEXT pDevExt, PSUPDRVDTPROVIDER pProv) 420 { 421 int rc;422 423 dtrace_invalidate(pProv->idDtProv);424 rc = dtrace_unregister(pProv->idDtProv);425 if (!rc)426 {427 supdrvVtgFreeProvider(pProv);428 return;429 } 430 431 pProv->fZombie = true; 432 RTListAppend(&pDevExt->DtProviderZombieList, &pProv->ListEntry); 433 LOG_DTRACE(("Invalidate DTrace provider '%s' / %p and put it on the zombie list\n", pProv->szName, pProv->idDtProv)); 434 } 435 436 437 /**438 * Processes the zombie list.439 * 379 */ 380 static void supdrvTracerProcessZombies(PSUPDRVDEVEXT pDevExt) 381 { 382 PSUPDRVTPPROVIDER pProv, pProvNext; 383 384 RTSemFastMutexRequest(pDevExt->mtxTracer); 385 RTListForEachSafe(&pDevExt->TracerProviderZombieList, pProv, pProvNext, SUPDRVTPPROVIDER, ListEntry) 386 { 387 int rc = pDevExt->pTracerOps->pfnDeregisterZombieProvider(pDevExt->pTracerOps, &pProv->Core); 388 if (RT_SUCCESS(rc)) 389 { 390 RTListNodeRemove(&pProv->ListEntry); 391 supdrvTracerFreeProvider(pProv); 392 } 393 } 394 RTSemFastMutexRelease(pDevExt->mtxTracer); 395 } 396 397 398 /** 399 * Unregisters all providers, including zombies, waiting for busy providers to 400 * go idle and unregister smoothly. 401 * 402 * This may block. 403 * 440 404 * @param pDevExt The device extension. 441 405 */ 442 static void supdrvVtgProcessZombies(PSUPDRVDEVEXT pDevExt) 443 { 444 PSUPDRVDTPROVIDER pProv, pProvNext; 445 446 RTSemFastMutexRequest(pDevExt->mtxDTrace); 447 RTListForEachSafe(&pDevExt->DtProviderZombieList, pProv, pProvNext, SUPDRVDTPROVIDER, ListEntry) 448 { 449 int rc = dtrace_unregister(pProv->idDtProv); 450 if (!rc) 451 { 452 RTListNodeRemove(&pProv->ListEntry); 453 supdrvVtgFreeProvider(pProv); 454 } 455 } 456 RTSemFastMutexRelease(pDevExt->mtxDTrace); 406 static void supdrvTracerRemoveAllProviders(PSUPDRVDEVEXT pDevExt) 407 { 408 uint32_t i; 409 PSUPDRVTPPROVIDER pProv; 410 PSUPDRVTPPROVIDER pProvNext; 411 412 /* 413 * Unregister all probes (there should only be one). 414 */ 415 RTSemFastMutexRequest(pDevExt->mtxTracer); 416 RTListForEachSafe(&pDevExt->TracerProviderList, pProv, pProvNext, SUPDRVTPPROVIDER, ListEntry) 417 { 418 RTListNodeRemove(&pProv->ListEntry); 419 supdrvTracerDeregisterVtgObj(pDevExt, pProv); 420 } 421 RTSemFastMutexRelease(pDevExt->mtxTracer); 422 423 /* 424 * Try unregister zombies now, sleep on busy ones. 425 */ 426 for (i = 0; ; i++) 427 { 428 bool fEmpty; 429 430 RTSemFastMutexRequest(pDevExt->mtxTracer); 431 RTListForEachSafe(&pDevExt->TracerProviderZombieList, pProv, pProvNext, SUPDRVTPPROVIDER, ListEntry) 432 { 433 int rc; 434 LOG_TRACER(("supdrvTracerRemoveAllProviders: Attemting to unregister '%s' / %p...\n", 435 pProv->szName, pProv->Core.TracerData.DTrace.idProvider)); 436 437 if (pDevExt->pTracerOps) 438 rc = pDevExt->pTracerOps->pfnDeregisterZombieProvider(pDevExt->pTracerOps, &pProv->Core); 439 else 440 rc = VINF_SUCCESS; 441 if (!rc) 442 { 443 RTListNodeRemove(&pProv->ListEntry); 444 supdrvTracerFreeProvider(pProv); 445 } 446 else if (!(i & 0xf)) 447 SUPR0Printf("supdrvTracerRemoveAllProviders: Waiting on busy provider '%s' / %p (rc=%d)\n", 448 pProv->szName, pProv->Core.TracerData.DTrace.idProvider, rc); 449 else 450 LOG_TRACER(("supdrvTracerRemoveAllProviders: Failed to unregister provider '%s' / %p - rc=%d\n", 451 pProv->szName, pProv->Core.TracerData.DTrace.idProvider, rc)); 452 } 453 454 fEmpty = RTListIsEmpty(&pDevExt->TracerProviderZombieList); 455 RTSemFastMutexRelease(pDevExt->mtxTracer); 456 if (fEmpty) 457 break; 458 459 /* Delay...*/ 460 RTThreadSleep(1000); 461 } 457 462 } 458 463 … … 469 474 * @param pszModName The module name. 470 475 */ 471 static int supdrv VtgRegister(PSUPDRVDEVEXT pDevExt, PVTGOBJHDR pVtgHdr, size_t cbVtgObj, PSUPDRVLDRIMAGE pImage,472 PSUPDRVSESSION pSession, const char *pszModName)476 static int supdrvTracerRegisterVtgObj(PSUPDRVDEVEXT pDevExt, PVTGOBJHDR pVtgHdr, size_t cbVtgObj, PSUPDRVLDRIMAGE pImage, 477 PSUPDRVSESSION pSession, const char *pszModName) 473 478 { 474 479 int rc; 475 480 unsigned i; 476 PSUPDRV DTPROVIDER pProv;481 PSUPDRVTPPROVIDER pProv; 477 482 478 483 /* … … 492 497 return rc; 493 498 494 rc = RTSemFastMutexRequest(pDevExt->mtx DTrace);499 rc = RTSemFastMutexRequest(pDevExt->mtxTracer); 495 500 if (RT_FAILURE(rc)) 496 501 return rc; 497 RTListForEach(&pDevExt-> DtProviderList, pProv, SUPDRVDTPROVIDER, ListEntry)498 { 499 if (pProv-> pHdr == pVtgHdr)502 RTListForEach(&pDevExt->TracerProviderList, pProv, SUPDRVTPPROVIDER, ListEntry) 503 { 504 if (pProv->Core.pHdr == pVtgHdr) 500 505 { 501 506 rc = VERR_SUPDRV_VTG_ALREADY_REGISTERED; 502 507 break; 503 508 } 504 if ( pProv->pSession == pSession 509 if ( pProv->pSession == pSession 505 510 && pProv->pImage == pImage) 506 511 { … … 509 514 } 510 515 } 511 RTSemFastMutexRelease(pDevExt->mtx DTrace);516 RTSemFastMutexRelease(pDevExt->mtxTracer); 512 517 if (RT_FAILURE(rc)) 513 518 return rc; … … 522 527 const char *pszName = supdrvVtgGetString(pVtgHdr, pDesc->offName); 523 528 size_t const cchName = strlen(pszName); 524 pProv = (PSUPDRV DTPROVIDER)RTMemAllocZ(RT_OFFSETOF(SUPDRVDTPROVIDER, szName[cchName + 1]));529 pProv = (PSUPDRVTPPROVIDER)RTMemAllocZ(RT_OFFSETOF(SUPDRVTPPROVIDER, szName[cchName + 1])); 525 530 if (pProv) 526 531 { 527 pProv->pDesc = pDesc; 528 pProv->pHdr = pVtgHdr; 532 pProv->Core.pDesc = pDesc; 533 pProv->Core.pHdr = pVtgHdr; 534 pProv->Core.pszName = &pProv->szName[0]; 529 535 pProv->pImage = pImage; 530 536 pProv->pSession = pSession; 531 537 pProv->pszModName = pszModName; 532 pProv->idDtProv = 0;533 pProv->cProvidedProbes = 0;534 538 pProv->fZombie = false; 535 memcpy(pProv->szName, pszName, cchName + 1); 536 supdrvVtgConvAttr(&pProv->DtAttrs.dtpa_provider, &pDesc->AttrSelf); 537 supdrvVtgConvAttr(&pProv->DtAttrs.dtpa_mod, &pDesc->AttrModules); 538 supdrvVtgConvAttr(&pProv->DtAttrs.dtpa_func, &pDesc->AttrFunctions); 539 supdrvVtgConvAttr(&pProv->DtAttrs.dtpa_name, &pDesc->AttrNames); 540 supdrvVtgConvAttr(&pProv->DtAttrs.dtpa_args, &pDesc->AttrArguments); 541 542 rc = dtrace_register(pProv->szName, 543 &pProv->DtAttrs, 544 DTRACE_PRIV_KERNEL, 545 NULL /* cred */, 546 &g_SupDrvDTraceProvOps, 547 pProv, 548 &pProv->idDtProv); 549 if (!rc) 539 pProv->fRegistered = true; 540 memcpy(&pProv->szName[0], pszName, cchName + 1); 541 542 rc = RTSemFastMutexRequest(pDevExt->mtxTracer); 543 if (RT_SUCCESS(rc)) 550 544 { 551 rc = RTSemFastMutexRequest(pDevExt->mtxDTrace); 545 if (pDevExt->pTracerOps) 546 rc = pDevExt->pTracerOps->pfnRegisterProvider(pDevExt->pTracerOps, &pProv->Core); 547 else 548 { 549 pProv->fRegistered = false; 550 rc = VINF_SUCCESS; 551 } 552 552 if (RT_SUCCESS(rc)) 553 553 { 554 RTListAppend(&pDevExt->DtProviderList, &pProv->ListEntry); 555 RTSemFastMutexRelease(pDevExt->mtxDTrace); 556 LOG_DTRACE(("Registered DTrace provider '%s' in '%s' -> %p\n", pProv->szName, pszModName, pProv->idDtProv)); 554 RTListAppend(&pDevExt->TracerProviderList, &pProv->ListEntry); 555 RTSemFastMutexRelease(pDevExt->mtxTracer); 556 LOG_TRACER(("Registered DTrace provider '%s' in '%s' -> %p\n", 557 pProv->szName, pszModName, pProv->Core.TracerData.DTrace.idProvider)); 557 558 } 558 559 else 559 dtrace_unregister(pProv->idDtProv); 560 { 561 RTSemFastMutexRelease(pDevExt->mtxTracer); 562 RTMemFree(pProv); 563 } 560 564 } 561 else562 rc = RTErrConvertFromErrno(rc);563 565 } 564 566 else … … 567 569 if (RT_FAILURE(rc)) 568 570 { 569 PSUPDRV DTPROVIDER pProvNext;570 supdrv VtgFreeProvider(pProv);571 572 RTSemFastMutexRequest(pDevExt->mtx DTrace);573 RTListForEachReverseSafe(&pDevExt-> DtProviderList, pProv, pProvNext, SUPDRVDTPROVIDER, ListEntry)571 PSUPDRVTPPROVIDER pProvNext; 572 supdrvTracerFreeProvider(pProv); 573 574 RTSemFastMutexRequest(pDevExt->mtxTracer); 575 RTListForEachReverseSafe(&pDevExt->TracerProviderList, pProv, pProvNext, SUPDRVTPPROVIDER, ListEntry) 574 576 { 575 if (pProv-> pHdr == pVtgHdr)577 if (pProv->Core.pHdr == pVtgHdr) 576 578 { 577 579 RTListNodeRemove(&pProv->ListEntry); 578 supdrv VtgDeregister(pDevExt, pProv);580 supdrvTracerDeregisterVtgObj(pDevExt, pProv); 579 581 } 580 582 } 581 RTSemFastMutexRelease(pDevExt->mtx DTrace);583 RTSemFastMutexRelease(pDevExt->mtxTracer); 582 584 return rc; 583 585 } … … 605 607 AssertReturn(pSession->R0Process == NIL_RTR0PROCESS, VERR_INVALID_PARAMETER); 606 608 607 rc = supdrv VtgRegister(pSession->pDevExt, pVtgHdr, _1M, NULL /*pImage*/, pSession, pszName);609 rc = supdrvTracerRegisterVtgObj(pSession->pDevExt, pVtgHdr, _1M, NULL /*pImage*/, pSession, pszName); 608 610 609 611 /* 610 612 * Try unregister zombies while we have a chance. 611 613 */ 612 supdrv VtgProcessZombies(pSession->pDevExt);614 supdrvTracerProcessZombies(pSession->pDevExt); 613 615 614 616 return rc; … … 624 626 SUPR0DECL(void) SUPR0VtgDeregisterDrv(PSUPDRVSESSION pSession) 625 627 { 626 PSUPDRV DTPROVIDER pProv, pProvNext;628 PSUPDRVTPPROVIDER pProv, pProvNext; 627 629 PSUPDRVDEVEXT pDevExt; 628 630 AssertReturnVoid(SUP_IS_SESSION_VALID(pSession)); … … 634 636 * Search for providers belonging to this driver session. 635 637 */ 636 RTSemFastMutexRequest(pDevExt->mtx DTrace);637 RTListForEachSafe(&pDevExt-> DtProviderList, pProv, pProvNext, SUPDRVDTPROVIDER, ListEntry)638 RTSemFastMutexRequest(pDevExt->mtxTracer); 639 RTListForEachSafe(&pDevExt->TracerProviderList, pProv, pProvNext, SUPDRVTPPROVIDER, ListEntry) 638 640 { 639 641 if (pProv->pSession == pSession) 640 642 { 641 643 RTListNodeRemove(&pProv->ListEntry); 642 supdrv VtgDeregister(pDevExt, pProv);643 } 644 } 645 RTSemFastMutexRelease(pDevExt->mtx DTrace);644 supdrvTracerDeregisterVtgObj(pDevExt, pProv); 645 } 646 } 647 RTSemFastMutexRelease(pDevExt->mtxTracer); 646 648 647 649 /* 648 650 * Try unregister zombies while we have a chance. 649 651 */ 650 supdrv VtgProcessZombies(pDevExt);651 } 652 653 654 /** 655 * Registers the VTG tracepoint providers of a module loaded by 656 * the support driver. 657 * 652 supdrvTracerProcessZombies(pDevExt); 653 } 654 655 656 /** 657 * Registers the VTG tracepoint providers of a module loaded by 658 * the support driver. 659 * 658 660 * This should be called from the ModuleInit code. 659 661 * … … 669 671 int rc; 670 672 671 /* 673 /* 672 674 * Validate input and context. 673 675 */ … … 675 677 AssertPtrReturn(pVtgHdr, VERR_INVALID_POINTER); 676 678 679 AssertPtrReturn(pImage, VERR_INVALID_POINTER); 677 680 pDevExt = pImage->pDevExt; 678 681 AssertPtrReturn(pDevExt, VERR_INVALID_POINTER); … … 684 687 */ 685 688 cbVtgObj = (uintptr_t)pVtgHdr - (uintptr_t)pImage->pvImage; 686 AssertMsgReturn(cbVtgObj /*off*/ < pImage->cbImageBits, 689 AssertMsgReturn(cbVtgObj /*off*/ < pImage->cbImageBits, 687 690 ("pVtgHdr=%p offVtgObj=%p cbImageBits=%p\n", pVtgHdr, cbVtgObj, pImage->cbImageBits), 688 691 VERR_INVALID_PARAMETER); 689 692 cbVtgObj = pImage->cbImageBits - cbVtgObj; 690 693 691 rc = supdrv VtgRegister(pDevExt, pVtgHdr, cbVtgObj, pImage, NULL, pImage->szName);694 rc = supdrvTracerRegisterVtgObj(pDevExt, pVtgHdr, cbVtgObj, pImage, NULL, pImage->szName); 692 695 693 696 /* 694 697 * Try unregister zombies while we have a chance. 695 698 */ 696 supdrv VtgProcessZombies(pDevExt);699 supdrvTracerProcessZombies(pDevExt); 697 700 698 701 return rc; … … 701 704 702 705 /** 703 * Module unloading hook, called after execution in the module have ceased. 704 * 705 * @param pDevExt The device extension structure. 706 * @param pImage The image being unloaded. 707 */ 708 void VBOXCALL supdrvVtgModuleUnloading(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage) 709 { 710 PSUPDRVDTPROVIDER pProv, pProvNext; 711 712 /* 713 * Unregister all providers belonging to this image. 714 */ 715 RTSemFastMutexRequest(pDevExt->mtxDTrace); 716 RTListForEachSafe(&pDevExt->DtProviderList, pProv, pProvNext, SUPDRVDTPROVIDER, ListEntry) 717 { 718 if (pProv->pImage == pImage) 719 { 720 RTListNodeRemove(&pProv->ListEntry); 721 supdrvVtgDeregister(pDevExt, pProv); 722 } 723 } 724 RTSemFastMutexRelease(pDevExt->mtxDTrace); 725 726 /* 727 * Try unregister zombies while we have a chance. 728 */ 729 supdrvVtgProcessZombies(pDevExt); 706 * Registers the tracer. 707 * 708 * This should be called from the ModuleInit code or from a ring-0 session. 709 * 710 * @returns VBox status code. 711 * @param hMod The module handle. 712 * @param pSession Ring-0 session handle. 713 * @param pReg Pointer to the tracer registration structure. 714 * @param ppHlp Where to return the tracer helper method table. 715 */ 716 SUPR0DECL(int) SUPR0TracerRegister(void *hMod, PSUPDRVSESSION pSession, PCSUPDRVTRACERREG pReg, PCSUPDRVTRACERHLP *ppHlp) 717 { 718 PSUPDRVLDRIMAGE pImage = (PSUPDRVLDRIMAGE)hMod; 719 PSUPDRVDEVEXT pDevExt; 720 int rc; 721 722 /* 723 * Validate input and context. 724 */ 725 AssertPtrReturn(ppHlp, VERR_INVALID_POINTER); 726 *ppHlp = NULL; 727 AssertPtrReturn(pReg, VERR_INVALID_HANDLE); 728 729 if (pImage) 730 { 731 AssertPtrReturn(pImage, VERR_INVALID_POINTER); 732 AssertReturn(pSession == NULL, VERR_INVALID_PARAMETER); 733 pDevExt = pImage->pDevExt; 734 AssertPtrReturn(pDevExt, VERR_INVALID_POINTER); 735 AssertReturn(pDevExt->pLdrInitImage == pImage, VERR_WRONG_ORDER); 736 AssertReturn(pDevExt->hLdrInitThread == RTThreadNativeSelf(), VERR_WRONG_ORDER); 737 } 738 else 739 { 740 AssertReturn(SUP_IS_SESSION_VALID(pSession), VERR_INVALID_PARAMETER); 741 AssertReturn(pSession->R0Process == NIL_RTR0PROCESS, VERR_INVALID_PARAMETER); 742 pDevExt = pSession->pDevExt; 743 AssertPtrReturn(pDevExt, VERR_INVALID_POINTER); 744 } 745 746 AssertPtrReturn(pReg->pfnRegisterProvider, VERR_INVALID_POINTER); 747 AssertPtrReturn(pReg->pfnDeregisterProvider, VERR_INVALID_POINTER); 748 AssertPtrReturn(pReg->pfnDeregisterZombieProvider, VERR_INVALID_POINTER); 749 750 /* 751 * Do the job. 752 */ 753 rc = RTSemFastMutexRequest(pDevExt->mtxTracer); 754 if (RT_SUCCESS(rc)) 755 { 756 if (!pDevExt->pTracerOps) 757 { 758 pDevExt->pTracerOps = pReg; 759 pDevExt->pTracerSession = pSession; 760 pDevExt->pTracerImage = pImage; 761 762 *ppHlp = &pDevExt->TracerHlp; 763 rc = VINF_SUCCESS; 764 } 765 else 766 rc = VERR_SUPDRV_TRACER_ALREADY_REGISTERED; 767 RTSemFastMutexRelease(pDevExt->mtxTracer); 768 } 769 770 return rc; 771 772 } 773 774 775 /** 776 * Deregister a tracer associated with a ring-0 session. 777 * 778 * @returns VBox status code. 779 * @param pSession Ring-0 session handle. 780 */ 781 SUPR0DECL(int) SUPR0TracerDeregister(PSUPDRVSESSION pSession) 782 { 783 PSUPDRVDEVEXT pDevExt; 784 int rc; 785 786 /* 787 * Validate input and context. 788 */ 789 AssertReturn(SUP_IS_SESSION_VALID(pSession), VERR_INVALID_PARAMETER); 790 AssertReturn(pSession->R0Process == NIL_RTR0PROCESS, VERR_INVALID_PARAMETER); 791 pDevExt = pSession->pDevExt; 792 AssertPtrReturn(pDevExt, VERR_INVALID_POINTER); 793 794 /* 795 * Do the job. 796 */ 797 rc = RTSemFastMutexRequest(pDevExt->mtxTracer); 798 if (RT_SUCCESS(rc)) 799 { 800 if (pDevExt->pTracerSession == pSession) 801 { 802 pDevExt->fTracerUnloading = true; 803 RTSemFastMutexRelease(pDevExt->mtxTracer); 804 805 supdrvTracerRemoveAllProviders(pDevExt); 806 807 RTSemFastMutexRequest(pDevExt->mtxTracer); 808 pDevExt->pTracerImage = NULL; 809 pDevExt->pTracerSession = NULL; 810 pDevExt->pTracerOps = NULL; 811 pDevExt->fTracerUnloading = false; 812 } 813 else 814 rc = VERR_SUPDRV_TRACER_NOT_REGISTERED; 815 RTSemFastMutexRelease(pDevExt->mtxTracer); 816 } 817 818 return rc; 819 } 820 821 822 /** 823 * Module unloading hook, called after execution in the module have ceased. 824 * 825 * @param pDevExt The device extension structure. 826 * @param pImage The image being unloaded. 827 */ 828 void VBOXCALL supdrvTracerModuleUnloading(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage) 829 { 830 PSUPDRVTPPROVIDER pProv, pProvNext; 831 AssertPtrReturnVoid(pImage); /* paranoia */ 832 833 RTSemFastMutexRequest(pDevExt->mtxTracer); 834 835 /* 836 * If it is the tracer image, we have to unload all the providers. 837 */ 838 if (pDevExt->pTracerImage == pImage) 839 { 840 pDevExt->fTracerUnloading = true; 841 RTSemFastMutexRelease(pDevExt->mtxTracer); 842 843 supdrvTracerRemoveAllProviders(pDevExt); 844 845 RTSemFastMutexRequest(pDevExt->mtxTracer); 846 pDevExt->pTracerImage = NULL; 847 pDevExt->pTracerSession = NULL; 848 pDevExt->pTracerOps = NULL; 849 pDevExt->fTracerUnloading = false; 850 RTSemFastMutexRelease(pDevExt->mtxTracer); 851 } 852 else 853 { 854 /* 855 * Unregister all providers belonging to this image. 856 */ 857 RTListForEachSafe(&pDevExt->TracerProviderList, pProv, pProvNext, SUPDRVTPPROVIDER, ListEntry) 858 { 859 if (pProv->pImage == pImage) 860 { 861 RTListNodeRemove(&pProv->ListEntry); 862 supdrvTracerDeregisterVtgObj(pDevExt, pProv); 863 } 864 } 865 866 RTSemFastMutexRelease(pDevExt->mtxTracer); 867 868 /* 869 * Try unregister zombies while we have a chance. 870 */ 871 supdrvTracerProcessZombies(pDevExt); 872 } 730 873 } 731 874 … … 735 878 * 736 879 * @returns VBox status code. 737 * @param pDevExt The device extension structure. 738 * @param pVtgFireProbe Pointer to the SUPR0VtgFireProbe entry. 739 */ 740 int VBOXCALL supdrvVtgInit(PSUPDRVDEVEXT pDevExt, PSUPFUNC pVtgFireProbe) 741 { 742 Assert(!strcmp(pVtgFireProbe->szName, "SUPR0VtgFireProbe")); 743 880 * @param pDevExt The device extension structure. 881 */ 882 int VBOXCALL supdrvTracerInit(PSUPDRVDEVEXT pDevExt) 883 { 744 884 /* 745 885 * Register a provider for this module. 746 886 */ 747 int rc = RTSemFastMutexCreate(&pDevExt->mtx DTrace);887 int rc = RTSemFastMutexCreate(&pDevExt->mtxTracer); 748 888 if (RT_SUCCESS(rc)) 749 889 { 750 #ifdef RT_OS_SOLARIS 751 pVtgFireProbe->pfn = (void *)(uintptr_t)dtrace_probe; 752 #endif 753 RTListInit(&pDevExt->DtProviderList); 754 RTListInit(&pDevExt->DtProviderZombieList); 755 rc = supdrvVtgRegister(pDevExt, &g_VTGObjHeader, _1M, NULL /*pImage*/, NULL /*pSession*/, "vboxdrv"); 890 pDevExt->TracerHlp.uVersion = SUPDRVTRACERHLP_VERSION; 891 /** @todo */ 892 pDevExt->TracerHlp.uEndVersion = SUPDRVTRACERHLP_VERSION; 893 894 RTListInit(&pDevExt->TracerProviderList); 895 RTListInit(&pDevExt->TracerProviderZombieList); 896 rc = supdrvTracerRegisterVtgObj(pDevExt, &g_VTGObjHeader, _1M, NULL /*pImage*/, NULL /*pSession*/, "vboxdrv"); 756 897 if (RT_SUCCESS(rc)) 757 898 return rc; 758 RTSemFastMutexDestroy(pDevExt->mtx DTrace);759 } 760 pDevExt->mtx DTrace= NIL_RTSEMFASTMUTEX;899 RTSemFastMutexDestroy(pDevExt->mtxTracer); 900 } 901 pDevExt->mtxTracer = NIL_RTSEMFASTMUTEX; 761 902 return rc; 762 903 } … … 769 910 * @param pDevExt The device extension structure. 770 911 */ 771 void VBOXCALL supdrvVtgTerm(PSUPDRVDEVEXT pDevExt) 772 { 773 PSUPDRVDTPROVIDER pProv, pProvNext; 774 uint32_t i; 775 LOG_DTRACE(("supdrvVtgTerm\n")); 776 777 /* 778 * Unregister all probes (there should only be one). 779 */ 780 RTSemFastMutexRequest(pDevExt->mtxDTrace); 781 RTListForEachSafe(&pDevExt->DtProviderList, pProv, pProvNext, SUPDRVDTPROVIDER, ListEntry) 782 { 783 RTListNodeRemove(&pProv->ListEntry); 784 supdrvVtgDeregister(pDevExt, pProv); 785 } 786 RTSemFastMutexRelease(pDevExt->mtxDTrace); 787 788 /* 789 * Try unregister zombies now, sleep on busy ones. 790 */ 791 for (i = 0; ; i++) 792 { 793 bool fEmpty; 794 795 RTSemFastMutexRequest(pDevExt->mtxDTrace); 796 RTListForEachSafe(&pDevExt->DtProviderZombieList, pProv, pProvNext, SUPDRVDTPROVIDER, ListEntry) 797 { 798 int rc; 799 LOG_DTRACE(("supdrvVtgTerm: Attemting to unregister '%s' / %p...\n", pProv->szName, pProv->idDtProv)); 800 rc = dtrace_unregister(pProv->idDtProv); 801 if (!rc) 802 { 803 RTListNodeRemove(&pProv->ListEntry); 804 supdrvVtgFreeProvider(pProv); 805 } 806 else if (!(i & 0xf)) 807 SUPR0Printf("supdrvVtgTerm: Waiting on busy provider '%s' / %p (rc=%d)\n", pProv->szName, pProv->idDtProv, rc); 808 else 809 LOG_DTRACE(("supdrvVtgTerm: Failed to unregister provider '%s' / %p - rc=%d\n", pProv->szName, pProv->idDtProv, rc)); 810 } 811 812 fEmpty = RTListIsEmpty(&pDevExt->DtProviderZombieList); 813 RTSemFastMutexRelease(pDevExt->mtxDTrace); 814 if (fEmpty) 815 break; 816 817 /* Delay...*/ 818 RTThreadSleep(1000); 819 } 820 821 RTSemFastMutexDestroy(pDevExt->mtxDTrace); 822 pDevExt->mtxDTrace = NIL_RTSEMFASTMUTEX; 823 LOG_DTRACE(("supdrvVtgTerm: Done\n")); 824 } 825 826 827 /** 828 * @callback_method_impl{dtrace_pops_t,dtps_provide} 829 */ 830 static void supdrvDTracePOps_Provide(void *pvProv, const dtrace_probedesc_t *pDtProbeDesc) 831 { 832 PSUPDRVDTPROVIDER pProv = (PSUPDRVDTPROVIDER)pvProv; 833 uint16_t idxProv; 834 PVTGPROBELOC pProbeLoc; 835 PVTGPROBELOC pProbeLocEnd; 836 char *pszFnNmBuf; 837 size_t const cbFnNmBuf = _4K + _1K; 838 839 if (pDtProbeDesc) 840 return; /* We don't generate probes, so never mind these requests. */ 841 842 if (pProv->fZombie) 843 return; 844 845 if (pProv->cProvidedProbes >= pProv->pDesc->cProbes) 846 return; 847 848 /* Need a buffer for extracting the function names and mangling them in 849 case of collision. */ 850 pszFnNmBuf = (char *)RTMemAlloc(cbFnNmBuf); 851 if (!pszFnNmBuf) 852 return; 853 854 /* 855 * Itereate the probe location list and register all probes related to 856 * this provider. 857 */ 858 idxProv = (uint16_t)(&pProv->pHdr->paProviders[0] - pProv->pDesc); 859 pProbeLoc = pProv->pHdr->paProbLocs; 860 pProbeLocEnd = pProv->pHdr->paProbLocsEnd; 861 while ((uintptr_t)pProbeLoc < (uintptr_t)pProbeLocEnd) 862 { 863 PVTGDESCPROBE pProbeDesc = (PVTGDESCPROBE)pProbeLoc->pbProbe; 864 if ( pProbeDesc->idxProvider == idxProv 865 && pProbeLoc->idProbe == UINT32_MAX) 866 { 867 /* The function name normally needs to be stripped since we're 868 using C++ compilers for most of the code. ASSUMES nobody are 869 brave/stupid enough to use function pointer returns without 870 typedef'ing properly them. */ 871 const char *pszPrbName = supdrvVtgGetString(pProv->pHdr, pProbeDesc->offName); 872 const char *pszFunc = pProbeLoc->pszFunction; 873 const char *psz = strchr(pProbeLoc->pszFunction, '('); 874 size_t cch; 875 if (psz) 876 { 877 /* skip blanks preceeding the parameter parenthesis. */ 878 while ( (uintptr_t)psz > (uintptr_t)pProbeLoc->pszFunction 879 && RT_C_IS_BLANK(psz[-1])) 880 psz--; 881 882 /* Find the start of the function name. */ 883 pszFunc = psz - 1; 884 while ((uintptr_t)pszFunc > (uintptr_t)pProbeLoc->pszFunction) 885 { 886 char ch = pszFunc[-1]; 887 if (!RT_C_IS_ALNUM(ch) && ch != '_' && ch != ':') 888 break; 889 pszFunc--; 890 } 891 cch = psz - pszFunc; 892 } 893 else 894 cch = strlen(pszFunc); 895 RTStrCopyEx(pszFnNmBuf, cbFnNmBuf, pszFunc, cch); 896 897 /* Look up the probe, if we have one in the same function, mangle 898 the function name a little to avoid having to deal with having 899 multiple location entries with the same probe ID. (lazy bird) */ 900 Assert(pProbeLoc->idProbe == UINT32_MAX); 901 if (dtrace_probe_lookup(pProv->idDtProv, pProv->pszModName, pszFnNmBuf, pszPrbName) != DTRACE_IDNONE) 902 { 903 RTStrPrintf(pszFnNmBuf+cch, cbFnNmBuf - cch, "-%u", pProbeLoc->uLine); 904 if (dtrace_probe_lookup(pProv->idDtProv, pProv->pszModName, pszFnNmBuf, pszPrbName) != DTRACE_IDNONE) 905 { 906 unsigned iOrd = 2; 907 while (iOrd < 128) 908 { 909 RTStrPrintf(pszFnNmBuf+cch, cbFnNmBuf - cch, "-%u-%u", pProbeLoc->uLine, iOrd); 910 if (dtrace_probe_lookup(pProv->idDtProv, pProv->pszModName, pszFnNmBuf, pszPrbName) == DTRACE_IDNONE) 911 break; 912 iOrd++; 913 } 914 if (iOrd >= 128) 915 { 916 LogRel(("VBoxDrv: More than 128 duplicate probe location instances in file %s at line %u, function %s [%s], probe %s\n", 917 pProbeLoc->pszFile, pProbeLoc->uLine, pProbeLoc->pszFunction, pszFnNmBuf, pszPrbName)); 918 continue; 919 } 920 } 921 } 922 923 /* Create the probe. */ 924 AssertCompile(sizeof(pProbeLoc->idProbe) == sizeof(dtrace_id_t)); 925 pProbeLoc->idProbe = dtrace_probe_create(pProv->idDtProv, pProv->pszModName, pszFnNmBuf, pszPrbName, 926 0 /*aframes*/, pProbeLoc); 927 pProv->cProvidedProbes++; 928 } 929 930 pProbeLoc++; 931 } 932 933 RTMemFree(pszFnNmBuf); 934 } 935 936 937 /** 938 * @callback_method_impl{dtrace_pops_t,dtps_enable} 939 */ 940 static int supdrvDTracePOps_Enable(void *pvProv, dtrace_id_t idProbe, void *pvProbe) 941 { 942 PSUPDRVDTPROVIDER pProv = (PSUPDRVDTPROVIDER)pvProv; 943 if (!pProv->fZombie) 944 { 945 PVTGPROBELOC pProbeLoc = (PVTGPROBELOC)pvProbe; 946 PVTGDESCPROBE pProbeDesc = (PVTGDESCPROBE)pProbeLoc->pbProbe; 947 948 if (!pProbeLoc->fEnabled) 949 { 950 pProbeLoc->fEnabled = 1; 951 if (ASMAtomicIncU32(&pProbeDesc->u32User) == 1) 952 pProv->pHdr->pafProbeEnabled[pProbeDesc->idxEnabled] = 1; 953 } 954 } 955 956 return 0; 957 } 958 959 960 /** 961 * @callback_method_impl{dtrace_pops_t,dtps_disable} 962 */ 963 static void supdrvDTracePOps_Disable(void *pvProv, dtrace_id_t idProbe, void *pvProbe) 964 { 965 PSUPDRVDTPROVIDER pProv = (PSUPDRVDTPROVIDER)pvProv; 966 if (!pProv->fZombie) 967 { 968 PVTGPROBELOC pProbeLoc = (PVTGPROBELOC)pvProbe; 969 PVTGDESCPROBE pProbeDesc = (PVTGDESCPROBE)pProbeLoc->pbProbe; 970 971 if (pProbeLoc->fEnabled) 972 { 973 pProbeLoc->fEnabled = 0; 974 if (ASMAtomicDecU32(&pProbeDesc->u32User) == 0) 975 pProv->pHdr->pafProbeEnabled[pProbeDesc->idxEnabled] = 1; 976 } 977 } 978 } 979 980 981 /** 982 * @callback_method_impl{dtrace_pops_t,dtps_getargdesc} 983 */ 984 static void supdrvDTracePOps_GetArgDesc(void *pvProv, dtrace_id_t idProbe, void *pvProbe, 985 dtrace_argdesc_t *pArgDesc) 986 { 987 PSUPDRVDTPROVIDER pProv = (PSUPDRVDTPROVIDER)pvProv; 988 unsigned uArg = pArgDesc->dtargd_ndx; 989 990 if (!pProv->fZombie) 991 { 992 PVTGPROBELOC pProbeLoc = (PVTGPROBELOC)pvProbe; 993 PVTGDESCPROBE pProbeDesc = (PVTGDESCPROBE)pProbeLoc->pbProbe; 994 PVTGDESCARGLIST pArgList = (PVTGDESCARGLIST)((uintptr_t)pProv->pHdr->paArgLists + pProbeDesc->offArgList); 995 996 Assert(pProbeDesc->offArgList < pProv->pHdr->cbArgLists); 997 if (pArgList->cArgs > uArg) 998 { 999 const char *pszType = supdrvVtgGetString(pProv->pHdr, pArgList->aArgs[uArg].offType); 1000 size_t cchType = strlen(pszType); 1001 if (cchType < sizeof(pArgDesc->dtargd_native)) 1002 { 1003 memcpy(pArgDesc->dtargd_native, pszType, cchType + 1); 1004 /** @todo mapping */ 1005 return; 1006 } 1007 } 1008 } 1009 1010 pArgDesc->dtargd_ndx = DTRACE_ARGNONE; 1011 } 1012 1013 1014 #ifdef RT_OS_SOLARIS 1015 1016 # ifdef __cplusplus 1017 extern "C" 1018 #endif 1019 uint64_t dtrace_getarg(int iArg, int cFrames); 1020 1021 /** 1022 * @callback_method_impl{dtrace_pops_t,dtps_getargval} 1023 */ 1024 static uint64_t supdrvDTracePOps_GetArgVal(void *pvProv, dtrace_id_t idProbe, void *pvProbe, 1025 int iArg, int cFrames) 1026 { 1027 /* dtrace_getarg on AMD64 has a different opinion about how to use the 1028 cFrames argument than dtrace_caller() and/or dtrace_getpcstack(), at 1029 least when the probe is fired by dtrace_probe() the way we do. 1030 1031 Setting aframes to 1 when calling dtrace_probe_create gives me the right 1032 arguments, but the wrong 'caller'. Since I cannot do anything about 1033 'caller', the only solution is this hack. 1034 1035 Not sure why the Solaris guys hasn't seen this issue before, but maybe 1036 there isn't anyone using the default argument getter path for ring-0 1037 dtrace_probe() calls, SDT surely isn't. 1038 1039 WARNING! This code is subject to dtrace_getarg interface unstability! */ 1040 /** @todo File a solaris bug on dtrace_probe() + dtrace_getarg(). */ 1041 return dtrace_getarg(iArg, cFrames + 1); 1042 } 1043 1044 #endif /* RT_OS_SOLARIS */ 1045 1046 1047 /** 1048 * @callback_method_impl{dtrace_pops_t,dtps_destroy} 1049 */ 1050 static void supdrvDTracePOps_Destroy(void *pvProv, dtrace_id_t idProbe, void *pvProbe) 1051 { 1052 PSUPDRVDTPROVIDER pProv = (PSUPDRVDTPROVIDER)pvProv; 1053 if (!pProv->fZombie) 1054 { 1055 PVTGPROBELOC pProbeLoc = (PVTGPROBELOC)pvProbe; 1056 Assert(!pProbeLoc->fEnabled); 1057 Assert(pProbeLoc->idProbe == idProbe); NOREF(idProbe); 1058 pProbeLoc->idProbe = UINT32_MAX; 1059 } 1060 pProv->cProvidedProbes--; 1061 } 1062 912 void VBOXCALL supdrvTracerTerm(PSUPDRVDEVEXT pDevExt) 913 { 914 LOG_TRACER(("supdrvTracerTerm\n")); 915 916 supdrvTracerRemoveAllProviders(pDevExt); 917 918 RTSemFastMutexDestroy(pDevExt->mtxTracer); 919 pDevExt->mtxTracer = NIL_RTSEMFASTMUTEX; 920 LOG_TRACER(("supdrvTracerTerm: Done\n")); 921 } 922
Note:
See TracChangeset
for help on using the changeset viewer.