SUPDrvTracer.cpp revision 19660e509403dbd7f409c4f7662a93830f93bde6
17ef1920962b3df57bf6d2704ced1586396d96f0vboxsync * VBoxDrv - The VirtualBox Support Driver - Tracer Interface.
17ef1920962b3df57bf6d2704ced1586396d96f0vboxsync * Copyright (C) 2012 Oracle Corporation
17ef1920962b3df57bf6d2704ced1586396d96f0vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
17ef1920962b3df57bf6d2704ced1586396d96f0vboxsync * available from http://www.virtualbox.org. This file is free software;
17ef1920962b3df57bf6d2704ced1586396d96f0vboxsync * you can redistribute it and/or modify it under the terms of the GNU
17ef1920962b3df57bf6d2704ced1586396d96f0vboxsync * General Public License (GPL) as published by the Free Software
17ef1920962b3df57bf6d2704ced1586396d96f0vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
17ef1920962b3df57bf6d2704ced1586396d96f0vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
17ef1920962b3df57bf6d2704ced1586396d96f0vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
17ef1920962b3df57bf6d2704ced1586396d96f0vboxsync * The contents of this file may alternatively be used under the terms
17ef1920962b3df57bf6d2704ced1586396d96f0vboxsync * of the Common Development and Distribution License Version 1.0
17ef1920962b3df57bf6d2704ced1586396d96f0vboxsync * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
17ef1920962b3df57bf6d2704ced1586396d96f0vboxsync * VirtualBox OSE distribution, in which case the provisions of the
17ef1920962b3df57bf6d2704ced1586396d96f0vboxsync * CDDL are applicable instead of those of the GPL.
17ef1920962b3df57bf6d2704ced1586396d96f0vboxsync * You may elect to license modified versions of this file under the
17ef1920962b3df57bf6d2704ced1586396d96f0vboxsync * terms and conditions of either the GPL or the CDDL or both.
17ef1920962b3df57bf6d2704ced1586396d96f0vboxsync/*******************************************************************************
17ef1920962b3df57bf6d2704ced1586396d96f0vboxsync* Header Files *
17ef1920962b3df57bf6d2704ced1586396d96f0vboxsync*******************************************************************************/
17ef1920962b3df57bf6d2704ced1586396d96f0vboxsync/*******************************************************************************
17ef1920962b3df57bf6d2704ced1586396d96f0vboxsync* Structures and Typedefs *
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync*******************************************************************************/
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync * Data for a tracepoint provider.
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync /** The entry in the provider list for this image. */
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync /** The core structure. */
fe14fe6d46ce87a9b25cbdacb3a20b1f87bf34c7vboxsync /** Pointer to the image this provider resides in. NULL if it's a
fe14fe6d46ce87a9b25cbdacb3a20b1f87bf34c7vboxsync * driver. */
fe14fe6d46ce87a9b25cbdacb3a20b1f87bf34c7vboxsync /** The session this provider is associated with if registered via
fe14fe6d46ce87a9b25cbdacb3a20b1f87bf34c7vboxsync * SUPR0VtgRegisterDrv. NULL if pImage is set. */
fe14fe6d46ce87a9b25cbdacb3a20b1f87bf34c7vboxsync /** Set when the module is unloaded or the driver deregisters its probes. */
fe14fe6d46ce87a9b25cbdacb3a20b1f87bf34c7vboxsync /** Set if the provider has been successfully registered with the
fe14fe6d46ce87a9b25cbdacb3a20b1f87bf34c7vboxsync * tracer. */
8867771015571c5542d39e393d7fe6304421a928vboxsync /** The provider name (for logging purposes). */
fe14fe6d46ce87a9b25cbdacb3a20b1f87bf34c7vboxsync/** Pointer to the data for a tracepoint provider. */
fe14fe6d46ce87a9b25cbdacb3a20b1f87bf34c7vboxsync/*******************************************************************************
fe14fe6d46ce87a9b25cbdacb3a20b1f87bf34c7vboxsync* Defined Constants And Macros *
fe14fe6d46ce87a9b25cbdacb3a20b1f87bf34c7vboxsync*******************************************************************************/
fe14fe6d46ce87a9b25cbdacb3a20b1f87bf34c7vboxsync/*******************************************************************************
fe14fe6d46ce87a9b25cbdacb3a20b1f87bf34c7vboxsync* Global Variables *
8867771015571c5542d39e393d7fe6304421a928vboxsync*******************************************************************************/
8867771015571c5542d39e393d7fe6304421a928vboxsync/** The address of the current probe fire routine for kernel mode. */
8867771015571c5542d39e393d7fe6304421a928vboxsyncPFNRT g_pfnSupdrvProbeFireKernel = supdrvTracerProbeFireStub;
fe14fe6d46ce87a9b25cbdacb3a20b1f87bf34c7vboxsync * Validates a VTG string against length and characterset limitations.
8867771015571c5542d39e393d7fe6304421a928vboxsync * @returns VINF_SUCCESS, VERR_SUPDRV_VTG_BAD_STRING or
fe14fe6d46ce87a9b25cbdacb3a20b1f87bf34c7vboxsync * VERR_SUPDRV_VTG_STRING_TOO_LONG.
8867771015571c5542d39e393d7fe6304421a928vboxsync * @param psz The string.
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync /*RTAssertMsg2("off=%u '%s'\n", off, psz);*/
8867771015571c5542d39e393d7fe6304421a928vboxsync * Validates the VTG data.
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync * @returns VBox status code.
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync * @param pVtgHdr The VTG object header of the data to validate.
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync * @param cbVtgObj The size of the VTG object.
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync * @param pbImage The image base. For validating the probe
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync * locations.
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync * @param cbImage The image size to go with @a pbImage.
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsyncstatic int supdrvVtgValidate(PVTGOBJHDR pVtgHdr, size_t cbVtgObj, const uint8_t *pbImage, size_t cbImage)
fe14fe6d46ce87a9b25cbdacb3a20b1f87bf34c7vboxsync#define MY_VALIDATE_PTR(p, cb, cMin, cMax, cbUnit, rcBase) \
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync || (uintptr_t)(p) - (uintptr_t)pVtgHdr > cbVtgObj - (cb) ) \
8867771015571c5542d39e393d7fe6304421a928vboxsync } while (0)
fe14fe6d46ce87a9b25cbdacb3a20b1f87bf34c7vboxsync if ((uintptr_t)(p) - (uintptr_t)pbImage > cbImage) \
fe14fe6d46ce87a9b25cbdacb3a20b1f87bf34c7vboxsync return (rc); \
8867771015571c5542d39e393d7fe6304421a928vboxsync else if (!RT_VALID_PTR(p)) \
8867771015571c5542d39e393d7fe6304421a928vboxsync return (rc); \
8867771015571c5542d39e393d7fe6304421a928vboxsync } while (0)
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync rc = supdrvVtgValidateString(pVtgHdr->pachStrTab + (offStrTab)); \
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync } while (0)
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync if ((Attr).u8Code <= (uint8_t)kVTGStability_Invalid || (Attr).u8Code >= (uint8_t)kVTGStability_End) \
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync if ((Attr).u8Data <= (uint8_t)kVTGStability_Invalid || (Attr).u8Data >= (uint8_t)kVTGStability_End) \
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync if ((Attr).u8DataDep <= (uint8_t)kVTGClass_Invalid || (Attr).u8DataDep >= (uint8_t)kVTGClass_End) \
fe14fe6d46ce87a9b25cbdacb3a20b1f87bf34c7vboxsync } while (0)
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync * The header.
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync if (memcmp(pVtgHdr->szMagic, VTGOBJHDR_MAGIC, sizeof(pVtgHdr->szMagic)))
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync MY_VALIDATE_PTR(pVtgHdr->paProviders, pVtgHdr->cbProviders, 1, 16, sizeof(VTGDESCPROVIDER), VERR_SUPDRV_VTG_BAD_HDR);
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync MY_VALIDATE_PTR(pVtgHdr->paProbes, pVtgHdr->cbProbes, 1, _32K, sizeof(VTGDESCPROBE), VERR_SUPDRV_VTG_BAD_HDR);
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync MY_VALIDATE_PTR(pVtgHdr->pafProbeEnabled, pVtgHdr->cbProbeEnabled, 1, _32K, sizeof(bool), VERR_SUPDRV_VTG_BAD_HDR);
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync MY_VALIDATE_PTR(pVtgHdr->pachStrTab, pVtgHdr->cbStrTab, 4, _1M, sizeof(char), VERR_SUPDRV_VTG_BAD_HDR);
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync MY_VALIDATE_PTR(pVtgHdr->paArgLists, pVtgHdr->cbArgLists, 1, _32K, sizeof(uint32_t), VERR_SUPDRV_VTG_BAD_HDR);
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync MY_WITHIN_IMAGE(pVtgHdr->paProbLocs, VERR_SUPDRV_VTG_BAD_HDR_PTR);
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync MY_WITHIN_IMAGE(pVtgHdr->paProbLocsEnd, VERR_SUPDRV_VTG_BAD_HDR_PTR);
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync if ((uintptr_t)pVtgHdr->paProbLocs > (uintptr_t)pVtgHdr->paProbLocsEnd)
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync cbTmp = (uintptr_t)pVtgHdr->paProbLocsEnd - (uintptr_t)pVtgHdr->paProbLocs;
8867771015571c5542d39e393d7fe6304421a928vboxsync if (cbTmp / sizeof(VTGPROBELOC) * sizeof(VTGPROBELOC) != cbTmp)
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync if (pVtgHdr->cbProbes / sizeof(VTGDESCPROBE) != pVtgHdr->cbProbeEnabled)
8867771015571c5542d39e393d7fe6304421a928vboxsync * Validate the providers.
8867771015571c5542d39e393d7fe6304421a928vboxsync cProviders = i = pVtgHdr->cbProviders / sizeof(VTGDESCPROVIDER);
8867771015571c5542d39e393d7fe6304421a928vboxsync while (i-- > 0)
8867771015571c5542d39e393d7fe6304421a928vboxsync if (pVtgHdr->paProviders[i].iFirstProbe >= pVtgHdr->cbProbeEnabled)
8867771015571c5542d39e393d7fe6304421a928vboxsync if (pVtgHdr->paProviders[i].iFirstProbe + pVtgHdr->paProviders[i].cProbes > pVtgHdr->cbProbeEnabled)
8867771015571c5542d39e393d7fe6304421a928vboxsync MY_VALIDATE_ATTR(pVtgHdr->paProviders[i].AttrSelf);
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync MY_VALIDATE_ATTR(pVtgHdr->paProviders[i].AttrModules);
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync MY_VALIDATE_ATTR(pVtgHdr->paProviders[i].AttrFunctions);
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync MY_VALIDATE_ATTR(pVtgHdr->paProviders[i].AttrNames);
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync MY_VALIDATE_ATTR(pVtgHdr->paProviders[i].AttrArguments);
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync * Validate probes.
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync while (i-- > 0)
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync if (pVtgHdr->paProbes[i].offArgList >= pVtgHdr->cbArgLists)
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync if (pVtgHdr->paProbes[i].idxEnabled != i) /* The lists are parallel. */
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync if (pVtgHdr->paProbes[i].idxProvider >= cProviders)
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync if ( i - pVtgHdr->paProviders[pVtgHdr->paProbes[i].idxProvider].iFirstProbe
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync >= pVtgHdr->paProviders[pVtgHdr->paProbes[i].idxProvider].cProbes)
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync /* The referenced argument list. */
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync pArgList = (PVTGDESCARGLIST)((uintptr_t)pVtgHdr->paArgLists + pVtgHdr->paProbes[i].offArgList);
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync while (iArg-- > 0)
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync * Check that pafProbeEnabled is all zero.
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync while (i-- > 0)
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync * Probe locations.
8867771015571c5542d39e393d7fe6304421a928vboxsync while (i-- > 0)
8867771015571c5542d39e393d7fe6304421a928vboxsync MY_WITHIN_IMAGE(pVtgHdr->paProbLocs[i].pszFunction, VERR_SUPDRV_VTG_BAD_PROBE_LOC);
8867771015571c5542d39e393d7fe6304421a928vboxsync MY_WITHIN_IMAGE(pVtgHdr->paProbLocs[i].pszFile, VERR_SUPDRV_VTG_BAD_PROBE_LOC);
8867771015571c5542d39e393d7fe6304421a928vboxsync offTmp = (uintptr_t)pVtgHdr->paProbLocs[i].pbProbe - (uintptr_t)pVtgHdr->paProbes;
8867771015571c5542d39e393d7fe6304421a928vboxsync if (offTmp / sizeof(VTGDESCPROBE) * sizeof(VTGDESCPROBE) != offTmp)
8867771015571c5542d39e393d7fe6304421a928vboxsync * Gets a string from the string table.
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync * @returns Pointer to the string.
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync * @param pVtgHdr The VTG object header.
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync * @param offStrTab The string table offset.
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsyncstatic const char *supdrvVtgGetString(PVTGOBJHDR pVtgHdr, uint32_t offStrTab)
8867771015571c5542d39e393d7fe6304421a928vboxsync * Frees the provider structure and associated resources.
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync * @param pProv The provider to free.
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsyncstatic void supdrvTracerFreeProvider(PSUPDRVTPPROVIDER pProv)
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync LOG_TRACER(("Freeing DTrace provider '%s' / %p\n", pProv->szName, pProv->Core.TracerData.DTrace.idProvider));
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync * Deregisters a provider.
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync * If the provider is still busy, it will be put in the zombie list.
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync * @param pDevExt The device extension.
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync * @param pProv The provider.
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync * @remarks The caller owns mtxTracer.
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsyncstatic void supdrvTracerDeregisterVtgObj(PSUPDRVDEVEXT pDevExt, PSUPDRVTPPROVIDER pProv)
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync rc = pDevExt->pTracerOps->pfnProviderDeregister(pDevExt->pTracerOps, &pProv->Core);
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync RTListAppend(&pDevExt->TracerProviderZombieList, &pProv->ListEntry);
8867771015571c5542d39e393d7fe6304421a928vboxsync LOG_TRACER(("Invalidated provider '%s' / %p and put it on the zombie list (rc=%Rrc)\n",
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync pProv->szName, pProv->Core.TracerData.DTrace.idProvider, rc));
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync * Processes the zombie list.
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync * @param pDevExt The device extension.
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsyncstatic void supdrvTracerProcessZombies(PSUPDRVDEVEXT pDevExt)
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync RTListForEachSafe(&pDevExt->TracerProviderZombieList, pProv, pProvNext, SUPDRVTPPROVIDER, ListEntry)
8867771015571c5542d39e393d7fe6304421a928vboxsync int rc = pDevExt->pTracerOps->pfnProviderDeregisterZombie(pDevExt->pTracerOps, &pProv->Core);
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync * Unregisters all providers, including zombies, waiting for busy providers to
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync * go idle and unregister smoothly.
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync * This may block.
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync * @param pDevExt The device extension.
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsyncstatic void supdrvTracerRemoveAllProviders(PSUPDRVDEVEXT pDevExt)
8867771015571c5542d39e393d7fe6304421a928vboxsync * Unregister all probes (there should only be one).
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync RTListForEachSafe(&pDevExt->TracerProviderList, pProv, pProvNext, SUPDRVTPPROVIDER, ListEntry)
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync * Try unregister zombies now, sleep on busy ones.
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync for (i = 0; ; i++)
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync RTListForEachSafe(&pDevExt->TracerProviderZombieList, pProv, pProvNext, SUPDRVTPPROVIDER, ListEntry)
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync LOG_TRACER(("supdrvTracerRemoveAllProviders: Attemting to unregister '%s' / %p...\n",
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync pProv->szName, pProv->Core.TracerData.DTrace.idProvider));
c999f225d03074008a0c21cdd5d3594da476e243vboxsync rc = pDevExt->pTracerOps->pfnProviderDeregisterZombie(pDevExt->pTracerOps, &pProv->Core);
c999f225d03074008a0c21cdd5d3594da476e243vboxsync else if (!(i & 0xf))
c999f225d03074008a0c21cdd5d3594da476e243vboxsync SUPR0Printf("supdrvTracerRemoveAllProviders: Waiting on busy provider '%s' / %p (rc=%d)\n",
c999f225d03074008a0c21cdd5d3594da476e243vboxsync pProv->szName, pProv->Core.TracerData.DTrace.idProvider, rc);
c999f225d03074008a0c21cdd5d3594da476e243vboxsync LOG_TRACER(("supdrvTracerRemoveAllProviders: Failed to unregister provider '%s' / %p - rc=%d\n",
c999f225d03074008a0c21cdd5d3594da476e243vboxsync pProv->szName, pProv->Core.TracerData.DTrace.idProvider, rc));
c999f225d03074008a0c21cdd5d3594da476e243vboxsync fEmpty = RTListIsEmpty(&pDevExt->TracerProviderZombieList);
c999f225d03074008a0c21cdd5d3594da476e243vboxsync /* Delay...*/
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync * Registers the VTG tracepoint providers of a driver.
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync * @returns VBox status code.
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync * @param pszName The driver name.
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync * @param pVtgHdr The VTG object header.
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync * @param pVtgObj The size of the VTG object.
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync * @param pImage The image if applicable.
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync * @param pSession The session if applicable.
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync * @param pszModName The module name.
8867771015571c5542d39e393d7fe6304421a928vboxsyncstatic int supdrvTracerRegisterVtgObj(PSUPDRVDEVEXT pDevExt, PVTGOBJHDR pVtgHdr, size_t cbVtgObj, PSUPDRVLDRIMAGE pImage,
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync unsigned i;
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync * Validate input.
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync AssertPtrNullReturn(pSession, VERR_INVALID_POINTER);
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync rc = supdrvVtgValidate(pVtgHdr, cbVtgObj, (const uint8_t *)pImage->pvImage, pImage->cbImageBits);
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync rc = supdrvVtgValidate(pVtgHdr, cbVtgObj, NULL, 0);
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync RTListForEach(&pDevExt->TracerProviderList, pProv, SUPDRVTPPROVIDER, ListEntry)
8867771015571c5542d39e393d7fe6304421a928vboxsync * Register the providers.
8867771015571c5542d39e393d7fe6304421a928vboxsync i = pVtgHdr->cbProviders / sizeof(VTGDESCPROVIDER);
8867771015571c5542d39e393d7fe6304421a928vboxsync while (i-- > 0)
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync const char *pszName = supdrvVtgGetString(pVtgHdr, pDesc->offName);
8867771015571c5542d39e393d7fe6304421a928vboxsync pProv = (PSUPDRVTPPROVIDER)RTMemAllocZ(RT_OFFSETOF(SUPDRVTPPROVIDER, szName[cchName + 1]));
8867771015571c5542d39e393d7fe6304421a928vboxsync rc = pDevExt->pTracerOps->pfnProviderRegister(pDevExt->pTracerOps, &pProv->Core);
8867771015571c5542d39e393d7fe6304421a928vboxsync RTListAppend(&pDevExt->TracerProviderList, &pProv->ListEntry);
8867771015571c5542d39e393d7fe6304421a928vboxsync LOG_TRACER(("Registered DTrace provider '%s' in '%s' -> %p\n",
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync pProv->szName, pszModName, pProv->Core.TracerData.DTrace.idProvider));
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync RTListForEachReverseSafe(&pDevExt->TracerProviderList, pProv, pProvNext, SUPDRVTPPROVIDER, ListEntry)
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync * Registers the VTG tracepoint providers of a driver.
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync * @returns VBox status code.
c999f225d03074008a0c21cdd5d3594da476e243vboxsync * @param pSession The support driver session handle.
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync * @param pVtgHdr The VTG header.
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync * @param pszName The driver name.
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsyncSUPR0DECL(int) SUPR0TracerRegisterDrv(PSUPDRVSESSION pSession, PVTGOBJHDR pVtgHdr, const char *pszName)
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync AssertReturn(SUP_IS_SESSION_VALID(pSession), VERR_INVALID_PARAMETER);
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync AssertReturn(pSession->R0Process == NIL_RTR0PROCESS, VERR_INVALID_PARAMETER);
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync rc = supdrvTracerRegisterVtgObj(pSession->pDevExt, pVtgHdr, _1M, NULL /*pImage*/, pSession, pszName);
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync * Try unregister zombies while we have a chance.
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync * Deregister the VTG tracepoint providers of a driver.
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync * @param pSession The support driver session handle.
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync * @param pVtgHdr The VTG header.
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsyncSUPR0DECL(void) SUPR0TracerDeregisterDrv(PSUPDRVSESSION pSession)
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync AssertReturnVoid(pSession->R0Process == NIL_RTR0PROCESS);
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync * Search for providers belonging to this driver session.
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync RTListForEachSafe(&pDevExt->TracerProviderList, pProv, pProvNext, SUPDRVTPPROVIDER, ListEntry)
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync * Try unregister zombies while we have a chance.
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync * Registers the VTG tracepoint providers of a module loaded by
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync * the support driver.
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync * This should be called from the ModuleInit code.
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync * @returns VBox status code.
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync * @param hMod The module handle.
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync * @param pVtgHdr The VTG header.
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsyncSUPR0DECL(int) SUPR0TracerRegisterModule(void *hMod, PVTGOBJHDR pVtgHdr)
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync * Validate input and context.
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync AssertReturn(pDevExt->pLdrInitImage == pImage, VERR_WRONG_ORDER);
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync AssertReturn(pDevExt->hLdrInitThread == RTThreadNativeSelf(), VERR_WRONG_ORDER);
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync * Calculate the max VTG object size and hand it over to the common code.
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync cbVtgObj = (uintptr_t)pVtgHdr - (uintptr_t)pImage->pvImage;
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync AssertMsgReturn(cbVtgObj /*off*/ < pImage->cbImageBits,
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync ("pVtgHdr=%p offVtgObj=%p cbImageBits=%p\n", pVtgHdr, cbVtgObj, pImage->cbImageBits),
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync rc = supdrvTracerRegisterVtgObj(pDevExt, pVtgHdr, cbVtgObj, pImage, NULL, pImage->szName);
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync * Try unregister zombies while we have a chance.
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync * Registers the tracer implementation.
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync * This should be called from the ModuleInit code or from a ring-0 session.
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync * @returns VBox status code.
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync * @param hMod The module handle.
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync * @param pSession Ring-0 session handle.
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync * @param pReg Pointer to the tracer registration structure.
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync * @param ppHlp Where to return the tracer helper method table.
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsyncSUPR0DECL(int) SUPR0TracerRegisterImpl(void *hMod, PSUPDRVSESSION pSession, PCSUPDRVTRACERREG pReg, PCSUPDRVTRACERHLP *ppHlp)
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync * Validate input and context.
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync AssertReturn(pSession == NULL, VERR_INVALID_PARAMETER);
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync AssertReturn(pDevExt->pLdrInitImage == pImage, VERR_WRONG_ORDER);
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync AssertReturn(pDevExt->hLdrInitThread == RTThreadNativeSelf(), VERR_WRONG_ORDER);
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync AssertReturn(SUP_IS_SESSION_VALID(pSession), VERR_INVALID_PARAMETER);
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync AssertReturn(pSession->R0Process == NIL_RTR0PROCESS, VERR_INVALID_PARAMETER);
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync AssertPtrReturn(pReg->pfnProbeFireKernel, VERR_INVALID_POINTER);
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync AssertPtrReturn(pReg->pfnProbeFireUser, VERR_INVALID_POINTER);
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync AssertPtrReturn(pReg->pfnTracerOpen, VERR_INVALID_POINTER);
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync AssertPtrReturn(pReg->pfnTracerIoCtl, VERR_INVALID_POINTER);
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync AssertPtrReturn(pReg->pfnTracerClose, VERR_INVALID_POINTER);
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync AssertPtrReturn(pReg->pfnProviderRegister, VERR_INVALID_POINTER);
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync AssertPtrReturn(pReg->pfnProviderDeregister, VERR_INVALID_POINTER);
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync AssertPtrReturn(pReg->pfnProviderDeregisterZombie, VERR_INVALID_POINTER);
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync * Do the job.
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync * Common tracer implementation deregistration code.
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync * The caller sets fTracerUnloading prior to calling this function.
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync * @param pDevExt The device extension structure.
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsyncstatic void supdrvTracerCommonDeregisterImpl(PSUPDRVDEVEXT pDevExt)
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync * Deregister a tracer implementation.
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync * This should be called from the ModuleTerm code or from a ring-0 session.
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync * @returns VBox status code.
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync * @param hMod The module handle.
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync * @param pSession Ring-0 session handle.
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsyncSUPR0DECL(int) SUPR0TracerDeregisterImpl(void *hMod, PSUPDRVSESSION pSession)
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync * Validate input and context.
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync AssertReturn(pSession == NULL, VERR_INVALID_PARAMETER);
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync AssertReturn(SUP_IS_SESSION_VALID(pSession), VERR_INVALID_PARAMETER);
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync AssertReturn(pSession->R0Process == NIL_RTR0PROCESS, VERR_INVALID_PARAMETER);
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync * Do the job.
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync * The probe function is a bit more fun since we need tail jump optimizating.
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync * Since we cannot ship yasm sources for linux and freebsd, owing to the cursed
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync * rebuilding of the kernel module from scratch at install time, we have to
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync * deploy some ugly gcc inline assembly here.
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync#if defined(__GNUC__) && (defined(RT_OS_FREEBSD) || defined(RT_OS_LINUX))
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync .section .text \n\
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync .p2align 2,,3 \n\
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync .global SUPR0TracerFireProbe \n\
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsyncSUPR0TracerFireProbe: \n\
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync movq g_pfnSupdrvProbeFireKernel(%rip), %rax \n\
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync jmp *%rax \n\
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync movl g_pfnSupdrvProbeFireKernel, %eax \n\
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync jmp *%eax \n\
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync .type supdrvTracerProbeFireStub,@function \n\
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync .global supdrvTracerProbeFireStub \n\
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsyncsupdrvTracerProbeFireStub: \n\
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync .previous \n\
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync * Module unloading hook, called after execution in the module have ceased.
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync * @param pDevExt The device extension structure.
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync * @param pImage The image being unloaded.
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsyncvoid VBOXCALL supdrvTracerModuleUnloading(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage)
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync * If it is the tracer image, we have to unload all the providers.
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync * Unregister all providers belonging to this image.
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync RTListForEachSafe(&pDevExt->TracerProviderList, pProv, pProvNext, SUPDRVTPPROVIDER, ListEntry)
8867771015571c5542d39e393d7fe6304421a928vboxsync * Try unregister zombies while we have a chance.
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync * Called when a session is being cleaned up.
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync * @param pDevExt The device extension structure.
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync * @param pSession The session that is being torn down.
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsyncvoid VBOXCALL supdrvTracerCleanupSession(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession)
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync * If ring-0 session, make sure it has deregistered VTG objects and the tracer.
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync RTListForEachSafe(&pDevExt->TracerProviderList, pProv, pProvNext, SUPDRVTPPROVIDER, ListEntry)
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync * Clean up instance data the trace may have associated with the session.
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync pDevExt->pTracerOps->pfnTracerClose(pDevExt->pTracerOps, pSession, pSession->uTracerData);
#ifdef VBOX_WITH_DTRACE_R0DRV
rc = supdrvTracerRegisterVtgObj(pDevExt, &g_VTGObjHeader, _1M, NULL /*pImage*/, NULL /*pSession*/, "vboxdrv");
return rc;
return rc;