SUPDrvTracer.cpp revision 19660e509403dbd7f409c4f7662a93830f93bde6
17ef1920962b3df57bf6d2704ced1586396d96f0vboxsync/* $Id$ */
17ef1920962b3df57bf6d2704ced1586396d96f0vboxsync/** @file
17ef1920962b3df57bf6d2704ced1586396d96f0vboxsync * VBoxDrv - The VirtualBox Support Driver - Tracer Interface.
17ef1920962b3df57bf6d2704ced1586396d96f0vboxsync */
17ef1920962b3df57bf6d2704ced1586396d96f0vboxsync
17ef1920962b3df57bf6d2704ced1586396d96f0vboxsync/*
17ef1920962b3df57bf6d2704ced1586396d96f0vboxsync * Copyright (C) 2012 Oracle Corporation
17ef1920962b3df57bf6d2704ced1586396d96f0vboxsync *
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 *
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 *
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
17ef1920962b3df57bf6d2704ced1586396d96f0vboxsync
17ef1920962b3df57bf6d2704ced1586396d96f0vboxsync/*******************************************************************************
17ef1920962b3df57bf6d2704ced1586396d96f0vboxsync* Header Files *
17ef1920962b3df57bf6d2704ced1586396d96f0vboxsync*******************************************************************************/
17ef1920962b3df57bf6d2704ced1586396d96f0vboxsync#define LOG_GROUP LOG_GROUP_SUP_DRV
17ef1920962b3df57bf6d2704ced1586396d96f0vboxsync#define SUPDRV_AGNOSTIC
17ef1920962b3df57bf6d2704ced1586396d96f0vboxsync#include "SUPDrvInternal.h"
17ef1920962b3df57bf6d2704ced1586396d96f0vboxsync
17ef1920962b3df57bf6d2704ced1586396d96f0vboxsync#include <VBox/err.h>
fe14fe6d46ce87a9b25cbdacb3a20b1f87bf34c7vboxsync#include <VBox/log.h>
fe14fe6d46ce87a9b25cbdacb3a20b1f87bf34c7vboxsync#include <VBox/VBoxTpG.h>
fe14fe6d46ce87a9b25cbdacb3a20b1f87bf34c7vboxsync
fe14fe6d46ce87a9b25cbdacb3a20b1f87bf34c7vboxsync#include <iprt/assert.h>
17ef1920962b3df57bf6d2704ced1586396d96f0vboxsync#include <iprt/ctype.h>
17ef1920962b3df57bf6d2704ced1586396d96f0vboxsync#include <iprt/list.h>
17ef1920962b3df57bf6d2704ced1586396d96f0vboxsync#include <iprt/mem.h>
17ef1920962b3df57bf6d2704ced1586396d96f0vboxsync#include <iprt/semaphore.h>
17ef1920962b3df57bf6d2704ced1586396d96f0vboxsync#include <iprt/thread.h>
17ef1920962b3df57bf6d2704ced1586396d96f0vboxsync
17ef1920962b3df57bf6d2704ced1586396d96f0vboxsync
17ef1920962b3df57bf6d2704ced1586396d96f0vboxsync/*******************************************************************************
17ef1920962b3df57bf6d2704ced1586396d96f0vboxsync* Structures and Typedefs *
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync*******************************************************************************/
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync/**
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync * Data for a tracepoint provider.
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync */
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsynctypedef struct SUPDRVTPPROVIDER
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync{
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync /** The entry in the provider list for this image. */
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync RTLISTNODE ListEntry;
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync /** The core structure. */
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync SUPDRVVDTPROVIDERCORE Core;
fe14fe6d46ce87a9b25cbdacb3a20b1f87bf34c7vboxsync
fe14fe6d46ce87a9b25cbdacb3a20b1f87bf34c7vboxsync /** Pointer to the image this provider resides in. NULL if it's a
fe14fe6d46ce87a9b25cbdacb3a20b1f87bf34c7vboxsync * driver. */
fe14fe6d46ce87a9b25cbdacb3a20b1f87bf34c7vboxsync PSUPDRVLDRIMAGE pImage;
fe14fe6d46ce87a9b25cbdacb3a20b1f87bf34c7vboxsync /** The session this provider is associated with if registered via
fe14fe6d46ce87a9b25cbdacb3a20b1f87bf34c7vboxsync * SUPR0VtgRegisterDrv. NULL if pImage is set. */
fe14fe6d46ce87a9b25cbdacb3a20b1f87bf34c7vboxsync PSUPDRVSESSION pSession;
fe14fe6d46ce87a9b25cbdacb3a20b1f87bf34c7vboxsync
fe14fe6d46ce87a9b25cbdacb3a20b1f87bf34c7vboxsync /** Set when the module is unloaded or the driver deregisters its probes. */
fe14fe6d46ce87a9b25cbdacb3a20b1f87bf34c7vboxsync bool fZombie;
fe14fe6d46ce87a9b25cbdacb3a20b1f87bf34c7vboxsync /** Set if the provider has been successfully registered with the
fe14fe6d46ce87a9b25cbdacb3a20b1f87bf34c7vboxsync * tracer. */
8867771015571c5542d39e393d7fe6304421a928vboxsync bool fRegistered;
8867771015571c5542d39e393d7fe6304421a928vboxsync /** The provider name (for logging purposes). */
fe14fe6d46ce87a9b25cbdacb3a20b1f87bf34c7vboxsync char szName[1];
fe14fe6d46ce87a9b25cbdacb3a20b1f87bf34c7vboxsync} SUPDRVTPPROVIDER;
fe14fe6d46ce87a9b25cbdacb3a20b1f87bf34c7vboxsync/** Pointer to the data for a tracepoint provider. */
fe14fe6d46ce87a9b25cbdacb3a20b1f87bf34c7vboxsynctypedef SUPDRVTPPROVIDER *PSUPDRVTPPROVIDER;
fe14fe6d46ce87a9b25cbdacb3a20b1f87bf34c7vboxsync
fe14fe6d46ce87a9b25cbdacb3a20b1f87bf34c7vboxsync
fe14fe6d46ce87a9b25cbdacb3a20b1f87bf34c7vboxsync/*******************************************************************************
fe14fe6d46ce87a9b25cbdacb3a20b1f87bf34c7vboxsync* Defined Constants And Macros *
fe14fe6d46ce87a9b25cbdacb3a20b1f87bf34c7vboxsync*******************************************************************************/
fe14fe6d46ce87a9b25cbdacb3a20b1f87bf34c7vboxsync#if 0
fe14fe6d46ce87a9b25cbdacb3a20b1f87bf34c7vboxsync# define LOG_TRACER(a_Args) SUPR0Printf a_Args
fe14fe6d46ce87a9b25cbdacb3a20b1f87bf34c7vboxsync#else
fe14fe6d46ce87a9b25cbdacb3a20b1f87bf34c7vboxsync# define LOG_TRACER(a_Args) do { } while (0)
fe14fe6d46ce87a9b25cbdacb3a20b1f87bf34c7vboxsync#endif
fe14fe6d46ce87a9b25cbdacb3a20b1f87bf34c7vboxsync
fe14fe6d46ce87a9b25cbdacb3a20b1f87bf34c7vboxsync
fe14fe6d46ce87a9b25cbdacb3a20b1f87bf34c7vboxsync/*******************************************************************************
fe14fe6d46ce87a9b25cbdacb3a20b1f87bf34c7vboxsync* Global Variables *
8867771015571c5542d39e393d7fe6304421a928vboxsync*******************************************************************************/
8867771015571c5542d39e393d7fe6304421a928vboxsync/** The address of the current probe fire routine for kernel mode. */
8867771015571c5542d39e393d7fe6304421a928vboxsyncPFNRT g_pfnSupdrvProbeFireKernel = supdrvTracerProbeFireStub;
8867771015571c5542d39e393d7fe6304421a928vboxsync
8867771015571c5542d39e393d7fe6304421a928vboxsync
8867771015571c5542d39e393d7fe6304421a928vboxsync
8867771015571c5542d39e393d7fe6304421a928vboxsync/**
fe14fe6d46ce87a9b25cbdacb3a20b1f87bf34c7vboxsync * Validates a VTG string against length and characterset limitations.
8867771015571c5542d39e393d7fe6304421a928vboxsync *
8867771015571c5542d39e393d7fe6304421a928vboxsync * @returns VINF_SUCCESS, VERR_SUPDRV_VTG_BAD_STRING or
fe14fe6d46ce87a9b25cbdacb3a20b1f87bf34c7vboxsync * VERR_SUPDRV_VTG_STRING_TOO_LONG.
8867771015571c5542d39e393d7fe6304421a928vboxsync * @param psz The string.
8867771015571c5542d39e393d7fe6304421a928vboxsync */
8867771015571c5542d39e393d7fe6304421a928vboxsyncstatic int supdrvVtgValidateString(const char *psz)
fe14fe6d46ce87a9b25cbdacb3a20b1f87bf34c7vboxsync{
fe14fe6d46ce87a9b25cbdacb3a20b1f87bf34c7vboxsync size_t off = 0;
fe14fe6d46ce87a9b25cbdacb3a20b1f87bf34c7vboxsync while (off < _4K)
fe14fe6d46ce87a9b25cbdacb3a20b1f87bf34c7vboxsync {
fe14fe6d46ce87a9b25cbdacb3a20b1f87bf34c7vboxsync char const ch = psz[off++];
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync if (!ch)
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync return VINF_SUCCESS;
8867771015571c5542d39e393d7fe6304421a928vboxsync if ( !RTLocCIsAlNum(ch)
8867771015571c5542d39e393d7fe6304421a928vboxsync && ch != ' '
fe14fe6d46ce87a9b25cbdacb3a20b1f87bf34c7vboxsync && ch != '_'
fe14fe6d46ce87a9b25cbdacb3a20b1f87bf34c7vboxsync && ch != '-'
fe14fe6d46ce87a9b25cbdacb3a20b1f87bf34c7vboxsync && ch != '('
fe14fe6d46ce87a9b25cbdacb3a20b1f87bf34c7vboxsync && ch != ')'
fe14fe6d46ce87a9b25cbdacb3a20b1f87bf34c7vboxsync && ch != ','
fe14fe6d46ce87a9b25cbdacb3a20b1f87bf34c7vboxsync && ch != '*'
fe14fe6d46ce87a9b25cbdacb3a20b1f87bf34c7vboxsync && ch != '&'
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync )
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync {
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync /*RTAssertMsg2("off=%u '%s'\n", off, psz);*/
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync return VERR_SUPDRV_VTG_BAD_STRING;
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync }
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync }
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync return VERR_SUPDRV_VTG_STRING_TOO_LONG;
8867771015571c5542d39e393d7fe6304421a928vboxsync}
8867771015571c5542d39e393d7fe6304421a928vboxsync
8867771015571c5542d39e393d7fe6304421a928vboxsync
8867771015571c5542d39e393d7fe6304421a928vboxsync/**
8867771015571c5542d39e393d7fe6304421a928vboxsync * Validates the VTG data.
8867771015571c5542d39e393d7fe6304421a928vboxsync *
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.
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync */
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsyncstatic int supdrvVtgValidate(PVTGOBJHDR pVtgHdr, size_t cbVtgObj, const uint8_t *pbImage, size_t cbImage)
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync{
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync uintptr_t cbTmp;
8867771015571c5542d39e393d7fe6304421a928vboxsync uintptr_t offTmp;
8867771015571c5542d39e393d7fe6304421a928vboxsync uintptr_t i;
8867771015571c5542d39e393d7fe6304421a928vboxsync int rc;
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync uint32_t cProviders;
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync
fe14fe6d46ce87a9b25cbdacb3a20b1f87bf34c7vboxsync if (!pbImage || !cbImage)
fe14fe6d46ce87a9b25cbdacb3a20b1f87bf34c7vboxsync {
fe14fe6d46ce87a9b25cbdacb3a20b1f87bf34c7vboxsync pbImage = NULL;
fe14fe6d46ce87a9b25cbdacb3a20b1f87bf34c7vboxsync cbImage = 0;
fe14fe6d46ce87a9b25cbdacb3a20b1f87bf34c7vboxsync }
fe14fe6d46ce87a9b25cbdacb3a20b1f87bf34c7vboxsync
fe14fe6d46ce87a9b25cbdacb3a20b1f87bf34c7vboxsync#define MY_VALIDATE_PTR(p, cb, cMin, cMax, cbUnit, rcBase) \
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync do { \
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync if ( (cb) >= cbVtgObj \
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync || (uintptr_t)(p) - (uintptr_t)pVtgHdr > cbVtgObj - (cb) ) \
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync return rcBase ## _PTR; \
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync if ((cb) < (cMin) * (cbUnit)) \
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync return rcBase ## _TOO_FEW; \
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync if ((cb) >= (cMax) * (cbUnit)) \
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync return rcBase ## _TOO_MUCH; \
fe14fe6d46ce87a9b25cbdacb3a20b1f87bf34c7vboxsync if ((cb) / (cbUnit) * (cbUnit) != (cb)) \
fe14fe6d46ce87a9b25cbdacb3a20b1f87bf34c7vboxsync return rcBase ## _NOT_MULTIPLE; \
8867771015571c5542d39e393d7fe6304421a928vboxsync } while (0)
8867771015571c5542d39e393d7fe6304421a928vboxsync#define MY_WITHIN_IMAGE(p, rc) \
8867771015571c5542d39e393d7fe6304421a928vboxsync do { \
8867771015571c5542d39e393d7fe6304421a928vboxsync if (pbImage) \
fe14fe6d46ce87a9b25cbdacb3a20b1f87bf34c7vboxsync { \
fe14fe6d46ce87a9b25cbdacb3a20b1f87bf34c7vboxsync if ((uintptr_t)(p) - (uintptr_t)pbImage > cbImage) \
fe14fe6d46ce87a9b25cbdacb3a20b1f87bf34c7vboxsync return (rc); \
8867771015571c5542d39e393d7fe6304421a928vboxsync } \
8867771015571c5542d39e393d7fe6304421a928vboxsync else if (!RT_VALID_PTR(p)) \
8867771015571c5542d39e393d7fe6304421a928vboxsync return (rc); \
8867771015571c5542d39e393d7fe6304421a928vboxsync } while (0)
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync#define MY_VALIDATE_STR(offStrTab) \
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync do { \
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync if ((offStrTab) >= pVtgHdr->cbStrTab) \
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync return VERR_SUPDRV_VTG_STRTAB_OFF; \
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync rc = supdrvVtgValidateString(pVtgHdr->pachStrTab + (offStrTab)); \
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync if (rc != VINF_SUCCESS) \
fe14fe6d46ce87a9b25cbdacb3a20b1f87bf34c7vboxsync return rc; \
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync } while (0)
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync#define MY_VALIDATE_ATTR(Attr) \
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync do { \
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync if ((Attr).u8Code <= (uint8_t)kVTGStability_Invalid || (Attr).u8Code >= (uint8_t)kVTGStability_End) \
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync return VERR_SUPDRV_VTG_BAD_ATTR; \
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync if ((Attr).u8Data <= (uint8_t)kVTGStability_Invalid || (Attr).u8Data >= (uint8_t)kVTGStability_End) \
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync return VERR_SUPDRV_VTG_BAD_ATTR; \
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync if ((Attr).u8DataDep <= (uint8_t)kVTGClass_Invalid || (Attr).u8DataDep >= (uint8_t)kVTGClass_End) \
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync return VERR_SUPDRV_VTG_BAD_ATTR; \
fe14fe6d46ce87a9b25cbdacb3a20b1f87bf34c7vboxsync } while (0)
fe14fe6d46ce87a9b25cbdacb3a20b1f87bf34c7vboxsync
8867771015571c5542d39e393d7fe6304421a928vboxsync /*
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync * The header.
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync */
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync if (memcmp(pVtgHdr->szMagic, VTGOBJHDR_MAGIC, sizeof(pVtgHdr->szMagic)))
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync return VERR_SUPDRV_VTG_MAGIC;
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync if (pVtgHdr->cBits != ARCH_BITS)
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync return VERR_SUPDRV_VTG_BITS;
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync if (pVtgHdr->u32Reserved0)
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync return VERR_SUPDRV_VTG_BAD_HDR;
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync
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
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 return VERR_SUPDRV_VTG_BAD_HDR_PTR;
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync cbTmp = (uintptr_t)pVtgHdr->paProbLocsEnd - (uintptr_t)pVtgHdr->paProbLocs;
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync if (cbTmp < sizeof(VTGPROBELOC))
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync return VERR_SUPDRV_VTG_BAD_HDR_TOO_FEW;
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync if (cbTmp >= _128K * sizeof(VTGPROBELOC))
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync return VERR_SUPDRV_VTG_BAD_HDR_TOO_MUCH;
8867771015571c5542d39e393d7fe6304421a928vboxsync if (cbTmp / sizeof(VTGPROBELOC) * sizeof(VTGPROBELOC) != cbTmp)
8867771015571c5542d39e393d7fe6304421a928vboxsync return VERR_SUPDRV_VTG_BAD_HDR_NOT_MULTIPLE;
8867771015571c5542d39e393d7fe6304421a928vboxsync
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync if (pVtgHdr->cbProbes / sizeof(VTGDESCPROBE) != pVtgHdr->cbProbeEnabled)
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync return VERR_SUPDRV_VTG_BAD_HDR;
8867771015571c5542d39e393d7fe6304421a928vboxsync
8867771015571c5542d39e393d7fe6304421a928vboxsync /*
8867771015571c5542d39e393d7fe6304421a928vboxsync * Validate the providers.
8867771015571c5542d39e393d7fe6304421a928vboxsync */
8867771015571c5542d39e393d7fe6304421a928vboxsync cProviders = i = pVtgHdr->cbProviders / sizeof(VTGDESCPROVIDER);
8867771015571c5542d39e393d7fe6304421a928vboxsync while (i-- > 0)
8867771015571c5542d39e393d7fe6304421a928vboxsync {
8867771015571c5542d39e393d7fe6304421a928vboxsync MY_VALIDATE_STR(pVtgHdr->paProviders[i].offName);
8867771015571c5542d39e393d7fe6304421a928vboxsync if (pVtgHdr->paProviders[i].iFirstProbe >= pVtgHdr->cbProbeEnabled)
8867771015571c5542d39e393d7fe6304421a928vboxsync return VERR_SUPDRV_VTG_BAD_PROVIDER;
8867771015571c5542d39e393d7fe6304421a928vboxsync if (pVtgHdr->paProviders[i].iFirstProbe + pVtgHdr->paProviders[i].cProbes > pVtgHdr->cbProbeEnabled)
8867771015571c5542d39e393d7fe6304421a928vboxsync return VERR_SUPDRV_VTG_BAD_PROVIDER;
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 if (pVtgHdr->paProviders[i].bReserved)
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync return VERR_SUPDRV_VTG_BAD_PROVIDER;
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync }
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync /*
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync * Validate probes.
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync */
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync i = pVtgHdr->cbProbes / sizeof(VTGDESCPROBE);
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync while (i-- > 0)
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync {
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync PVTGDESCARGLIST pArgList;
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync unsigned iArg;
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync MY_VALIDATE_STR(pVtgHdr->paProbes[i].offName);
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync if (pVtgHdr->paProbes[i].offArgList >= pVtgHdr->cbArgLists)
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync return VERR_SUPDRV_VTG_BAD_PROBE;
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync if (pVtgHdr->paProbes[i].offArgList & 3)
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync return VERR_SUPDRV_VTG_BAD_PROBE;
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync if (pVtgHdr->paProbes[i].idxEnabled != i) /* The lists are parallel. */
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync return VERR_SUPDRV_VTG_BAD_PROBE;
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync if (pVtgHdr->paProbes[i].idxProvider >= cProviders)
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync return VERR_SUPDRV_VTG_BAD_PROBE;
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync if ( i - pVtgHdr->paProviders[pVtgHdr->paProbes[i].idxProvider].iFirstProbe
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync >= pVtgHdr->paProviders[pVtgHdr->paProbes[i].idxProvider].cProbes)
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync return VERR_SUPDRV_VTG_BAD_PROBE;
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync if (pVtgHdr->paProbes[i].u32User)
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync return VERR_SUPDRV_VTG_BAD_PROBE;
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync /* The referenced argument list. */
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync pArgList = (PVTGDESCARGLIST)((uintptr_t)pVtgHdr->paArgLists + pVtgHdr->paProbes[i].offArgList);
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync if (pArgList->cArgs > 16)
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync return VERR_SUPDRV_VTG_BAD_ARGLIST;
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync if ( pArgList->abReserved[0]
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync || pArgList->abReserved[1]
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync || pArgList->abReserved[2])
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync return VERR_SUPDRV_VTG_BAD_ARGLIST;
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync iArg = pArgList->cArgs;
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync while (iArg-- > 0)
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync {
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync MY_VALIDATE_STR(pArgList->aArgs[iArg].offType);
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync MY_VALIDATE_STR(pArgList->aArgs[iArg].offName);
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync }
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync }
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync /*
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync * Check that pafProbeEnabled is all zero.
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync */
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync i = pVtgHdr->cbProbeEnabled;
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync while (i-- > 0)
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync if (pVtgHdr->pafProbeEnabled[0])
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync return VERR_SUPDRV_VTG_BAD_PROBE_ENABLED;
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync /*
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync * Probe locations.
8867771015571c5542d39e393d7fe6304421a928vboxsync */
8867771015571c5542d39e393d7fe6304421a928vboxsync i = pVtgHdr->paProbLocsEnd - pVtgHdr->paProbLocs;
8867771015571c5542d39e393d7fe6304421a928vboxsync while (i-- > 0)
8867771015571c5542d39e393d7fe6304421a928vboxsync {
8867771015571c5542d39e393d7fe6304421a928vboxsync if (pVtgHdr->paProbLocs[i].uLine >= _1G)
8867771015571c5542d39e393d7fe6304421a928vboxsync return VERR_SUPDRV_VTG_BAD_PROBE_LOC;
8867771015571c5542d39e393d7fe6304421a928vboxsync if (pVtgHdr->paProbLocs[i].fEnabled)
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync return VERR_SUPDRV_VTG_BAD_PROBE_LOC;
8867771015571c5542d39e393d7fe6304421a928vboxsync if (pVtgHdr->paProbLocs[i].idProbe != UINT32_MAX)
8867771015571c5542d39e393d7fe6304421a928vboxsync return VERR_SUPDRV_VTG_BAD_PROBE_LOC;
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;
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync if (offTmp >= pVtgHdr->cbProbes)
8867771015571c5542d39e393d7fe6304421a928vboxsync return VERR_SUPDRV_VTG_BAD_PROBE_LOC;
8867771015571c5542d39e393d7fe6304421a928vboxsync if (offTmp / sizeof(VTGDESCPROBE) * sizeof(VTGDESCPROBE) != offTmp)
8867771015571c5542d39e393d7fe6304421a928vboxsync return VERR_SUPDRV_VTG_BAD_PROBE_LOC;
8867771015571c5542d39e393d7fe6304421a928vboxsync }
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync return VINF_SUCCESS;
8867771015571c5542d39e393d7fe6304421a928vboxsync#undef MY_VALIDATE_STR
8867771015571c5542d39e393d7fe6304421a928vboxsync#undef MY_VALIDATE_PTR
8867771015571c5542d39e393d7fe6304421a928vboxsync#undef MY_WITHIN_IMAGE
8867771015571c5542d39e393d7fe6304421a928vboxsync}
8867771015571c5542d39e393d7fe6304421a928vboxsync
8867771015571c5542d39e393d7fe6304421a928vboxsync
8867771015571c5542d39e393d7fe6304421a928vboxsync/**
8867771015571c5542d39e393d7fe6304421a928vboxsync * Gets a string from the string table.
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync *
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync * @returns Pointer to the string.
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync * @param pVtgHdr The VTG object header.
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync * @param offStrTab The string table offset.
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync */
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsyncstatic const char *supdrvVtgGetString(PVTGOBJHDR pVtgHdr, uint32_t offStrTab)
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync{
8867771015571c5542d39e393d7fe6304421a928vboxsync Assert(offStrTab < pVtgHdr->cbStrTab);
8867771015571c5542d39e393d7fe6304421a928vboxsync return &pVtgHdr->pachStrTab[offStrTab];
8867771015571c5542d39e393d7fe6304421a928vboxsync}
8867771015571c5542d39e393d7fe6304421a928vboxsync
8867771015571c5542d39e393d7fe6304421a928vboxsync
8867771015571c5542d39e393d7fe6304421a928vboxsync/**
8867771015571c5542d39e393d7fe6304421a928vboxsync * Frees the provider structure and associated resources.
8867771015571c5542d39e393d7fe6304421a928vboxsync *
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync * @param pProv The provider to free.
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync */
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsyncstatic void supdrvTracerFreeProvider(PSUPDRVTPPROVIDER pProv)
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync{
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync LOG_TRACER(("Freeing DTrace provider '%s' / %p\n", pProv->szName, pProv->Core.TracerData.DTrace.idProvider));
8867771015571c5542d39e393d7fe6304421a928vboxsync pProv->fRegistered = false;
8867771015571c5542d39e393d7fe6304421a928vboxsync pProv->fZombie = true;
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync pProv->Core.pDesc = NULL;
8867771015571c5542d39e393d7fe6304421a928vboxsync pProv->Core.pHdr = NULL;
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync RT_ZERO(pProv->Core.TracerData);
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync RTMemFree(pProv);
8867771015571c5542d39e393d7fe6304421a928vboxsync}
8867771015571c5542d39e393d7fe6304421a928vboxsync
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync/**
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync * Deregisters a provider.
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync *
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync * If the provider is still busy, it will be put in the zombie list.
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync *
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync * @param pDevExt The device extension.
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync * @param pProv The provider.
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync *
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync * @remarks The caller owns mtxTracer.
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync */
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsyncstatic void supdrvTracerDeregisterVtgObj(PSUPDRVDEVEXT pDevExt, PSUPDRVTPPROVIDER pProv)
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync{
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync int rc;
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync if (!pProv->fRegistered || !pDevExt->pTracerOps)
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync rc = VINF_SUCCESS;
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync else
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync rc = pDevExt->pTracerOps->pfnProviderDeregister(pDevExt->pTracerOps, &pProv->Core);
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync if (RT_SUCCESS(rc))
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync {
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync supdrvTracerFreeProvider(pProv);
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync return;
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync }
8867771015571c5542d39e393d7fe6304421a928vboxsync
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync pProv->fZombie = true;
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}
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync/**
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync * Processes the zombie list.
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync *
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync * @param pDevExt The device extension.
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync */
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsyncstatic void supdrvTracerProcessZombies(PSUPDRVDEVEXT pDevExt)
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync{
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync PSUPDRVTPPROVIDER pProv, pProvNext;
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync
8867771015571c5542d39e393d7fe6304421a928vboxsync RTSemFastMutexRequest(pDevExt->mtxTracer);
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync RTListForEachSafe(&pDevExt->TracerProviderZombieList, pProv, pProvNext, SUPDRVTPPROVIDER, ListEntry)
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync {
8867771015571c5542d39e393d7fe6304421a928vboxsync int rc = pDevExt->pTracerOps->pfnProviderDeregisterZombie(pDevExt->pTracerOps, &pProv->Core);
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync if (RT_SUCCESS(rc))
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync {
8867771015571c5542d39e393d7fe6304421a928vboxsync RTListNodeRemove(&pProv->ListEntry);
8867771015571c5542d39e393d7fe6304421a928vboxsync supdrvTracerFreeProvider(pProv);
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync }
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync }
8867771015571c5542d39e393d7fe6304421a928vboxsync RTSemFastMutexRelease(pDevExt->mtxTracer);
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync}
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync
8867771015571c5542d39e393d7fe6304421a928vboxsync
8867771015571c5542d39e393d7fe6304421a928vboxsync/**
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync * Unregisters all providers, including zombies, waiting for busy providers to
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync * go idle and unregister smoothly.
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync *
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync * This may block.
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync *
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync * @param pDevExt The device extension.
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync */
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsyncstatic void supdrvTracerRemoveAllProviders(PSUPDRVDEVEXT pDevExt)
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync{
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync uint32_t i;
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync PSUPDRVTPPROVIDER pProv;
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync PSUPDRVTPPROVIDER pProvNext;
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync /*
8867771015571c5542d39e393d7fe6304421a928vboxsync * Unregister all probes (there should only be one).
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync */
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync RTSemFastMutexRequest(pDevExt->mtxTracer);
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync RTListForEachSafe(&pDevExt->TracerProviderList, pProv, pProvNext, SUPDRVTPPROVIDER, ListEntry)
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync {
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync RTListNodeRemove(&pProv->ListEntry);
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync supdrvTracerDeregisterVtgObj(pDevExt, pProv);
8867771015571c5542d39e393d7fe6304421a928vboxsync }
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync RTSemFastMutexRelease(pDevExt->mtxTracer);
8867771015571c5542d39e393d7fe6304421a928vboxsync
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync /*
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync * Try unregister zombies now, sleep on busy ones.
8867771015571c5542d39e393d7fe6304421a928vboxsync */
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync for (i = 0; ; i++)
8867771015571c5542d39e393d7fe6304421a928vboxsync {
8867771015571c5542d39e393d7fe6304421a928vboxsync bool fEmpty;
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync RTSemFastMutexRequest(pDevExt->mtxTracer);
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync RTListForEachSafe(&pDevExt->TracerProviderZombieList, pProv, pProvNext, SUPDRVTPPROVIDER, ListEntry)
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync {
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync int rc;
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync LOG_TRACER(("supdrvTracerRemoveAllProviders: Attemting to unregister '%s' / %p...\n",
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync pProv->szName, pProv->Core.TracerData.DTrace.idProvider));
c999f225d03074008a0c21cdd5d3594da476e243vboxsync
c999f225d03074008a0c21cdd5d3594da476e243vboxsync if (pDevExt->pTracerOps)
c999f225d03074008a0c21cdd5d3594da476e243vboxsync rc = pDevExt->pTracerOps->pfnProviderDeregisterZombie(pDevExt->pTracerOps, &pProv->Core);
c999f225d03074008a0c21cdd5d3594da476e243vboxsync else
c999f225d03074008a0c21cdd5d3594da476e243vboxsync rc = VINF_SUCCESS;
c999f225d03074008a0c21cdd5d3594da476e243vboxsync if (!rc)
c999f225d03074008a0c21cdd5d3594da476e243vboxsync {
c999f225d03074008a0c21cdd5d3594da476e243vboxsync RTListNodeRemove(&pProv->ListEntry);
c999f225d03074008a0c21cdd5d3594da476e243vboxsync supdrvTracerFreeProvider(pProv);
c999f225d03074008a0c21cdd5d3594da476e243vboxsync }
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 else
c999f225d03074008a0c21cdd5d3594da476e243vboxsync LOG_TRACER(("supdrvTracerRemoveAllProviders: Failed to unregister provider '%s' / %p - rc=%d\n",
c999f225d03074008a0c21cdd5d3594da476e243vboxsync pProv->szName, pProv->Core.TracerData.DTrace.idProvider, rc));
c999f225d03074008a0c21cdd5d3594da476e243vboxsync }
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync
c999f225d03074008a0c21cdd5d3594da476e243vboxsync fEmpty = RTListIsEmpty(&pDevExt->TracerProviderZombieList);
c999f225d03074008a0c21cdd5d3594da476e243vboxsync RTSemFastMutexRelease(pDevExt->mtxTracer);
c999f225d03074008a0c21cdd5d3594da476e243vboxsync if (fEmpty)
c999f225d03074008a0c21cdd5d3594da476e243vboxsync break;
c999f225d03074008a0c21cdd5d3594da476e243vboxsync
c999f225d03074008a0c21cdd5d3594da476e243vboxsync /* Delay...*/
c999f225d03074008a0c21cdd5d3594da476e243vboxsync RTThreadSleep(1000);
c999f225d03074008a0c21cdd5d3594da476e243vboxsync }
c999f225d03074008a0c21cdd5d3594da476e243vboxsync}
c999f225d03074008a0c21cdd5d3594da476e243vboxsync
8867771015571c5542d39e393d7fe6304421a928vboxsync
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync/**
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync * Registers the VTG tracepoint providers of a driver.
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync *
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.
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync */
8867771015571c5542d39e393d7fe6304421a928vboxsyncstatic int supdrvTracerRegisterVtgObj(PSUPDRVDEVEXT pDevExt, PVTGOBJHDR pVtgHdr, size_t cbVtgObj, PSUPDRVLDRIMAGE pImage,
8867771015571c5542d39e393d7fe6304421a928vboxsync PSUPDRVSESSION pSession, const char *pszModName)
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync{
8867771015571c5542d39e393d7fe6304421a928vboxsync int rc;
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync unsigned i;
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync PSUPDRVTPPROVIDER pProv;
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync /*
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync * Validate input.
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync */
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync AssertPtrReturn(pDevExt, VERR_INVALID_POINTER);
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync AssertPtrReturn(pVtgHdr, VERR_INVALID_POINTER);
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync AssertPtrNullReturn(pImage, VERR_INVALID_POINTER);
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync AssertPtrNullReturn(pSession, VERR_INVALID_POINTER);
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync AssertPtrReturn(pszModName, VERR_INVALID_POINTER);
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync if (pImage)
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync rc = supdrvVtgValidate(pVtgHdr, cbVtgObj, (const uint8_t *)pImage->pvImage, pImage->cbImageBits);
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync else
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync rc = supdrvVtgValidate(pVtgHdr, cbVtgObj, NULL, 0);
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync if (RT_FAILURE(rc))
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync return rc;
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync rc = RTSemFastMutexRequest(pDevExt->mtxTracer);
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync if (RT_FAILURE(rc))
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync return rc;
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync RTListForEach(&pDevExt->TracerProviderList, pProv, SUPDRVTPPROVIDER, ListEntry)
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync {
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync if (pProv->Core.pHdr == pVtgHdr)
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync {
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync rc = VERR_SUPDRV_VTG_ALREADY_REGISTERED;
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync break;
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync }
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync if ( pProv->pSession == pSession
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync && pProv->pImage == pImage)
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync {
8867771015571c5542d39e393d7fe6304421a928vboxsync rc = VERR_SUPDRV_VTG_ONLY_ONCE_PER_SESSION;
8867771015571c5542d39e393d7fe6304421a928vboxsync break;
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync }
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync }
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync RTSemFastMutexRelease(pDevExt->mtxTracer);
8867771015571c5542d39e393d7fe6304421a928vboxsync if (RT_FAILURE(rc))
8867771015571c5542d39e393d7fe6304421a928vboxsync return rc;
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync /*
8867771015571c5542d39e393d7fe6304421a928vboxsync * Register the providers.
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync */
8867771015571c5542d39e393d7fe6304421a928vboxsync i = pVtgHdr->cbProviders / sizeof(VTGDESCPROVIDER);
8867771015571c5542d39e393d7fe6304421a928vboxsync while (i-- > 0)
8867771015571c5542d39e393d7fe6304421a928vboxsync {
8867771015571c5542d39e393d7fe6304421a928vboxsync PVTGDESCPROVIDER pDesc = &pVtgHdr->paProviders[i];
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync const char *pszName = supdrvVtgGetString(pVtgHdr, pDesc->offName);
8867771015571c5542d39e393d7fe6304421a928vboxsync size_t const cchName = strlen(pszName);
8867771015571c5542d39e393d7fe6304421a928vboxsync pProv = (PSUPDRVTPPROVIDER)RTMemAllocZ(RT_OFFSETOF(SUPDRVTPPROVIDER, szName[cchName + 1]));
8867771015571c5542d39e393d7fe6304421a928vboxsync if (pProv)
8867771015571c5542d39e393d7fe6304421a928vboxsync {
8867771015571c5542d39e393d7fe6304421a928vboxsync pProv->Core.pDesc = pDesc;
8867771015571c5542d39e393d7fe6304421a928vboxsync pProv->Core.pHdr = pVtgHdr;
8867771015571c5542d39e393d7fe6304421a928vboxsync pProv->Core.pszName = &pProv->szName[0];
8867771015571c5542d39e393d7fe6304421a928vboxsync pProv->Core.pszModName = pszModName;
8867771015571c5542d39e393d7fe6304421a928vboxsync pProv->pImage = pImage;
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync pProv->pSession = pSession;
8867771015571c5542d39e393d7fe6304421a928vboxsync pProv->fZombie = false;
8867771015571c5542d39e393d7fe6304421a928vboxsync pProv->fRegistered = true;
8867771015571c5542d39e393d7fe6304421a928vboxsync memcpy(&pProv->szName[0], pszName, cchName + 1);
8867771015571c5542d39e393d7fe6304421a928vboxsync
8867771015571c5542d39e393d7fe6304421a928vboxsync rc = RTSemFastMutexRequest(pDevExt->mtxTracer);
8867771015571c5542d39e393d7fe6304421a928vboxsync if (RT_SUCCESS(rc))
8867771015571c5542d39e393d7fe6304421a928vboxsync {
8867771015571c5542d39e393d7fe6304421a928vboxsync if (pDevExt->pTracerOps)
8867771015571c5542d39e393d7fe6304421a928vboxsync rc = pDevExt->pTracerOps->pfnProviderRegister(pDevExt->pTracerOps, &pProv->Core);
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync else
8867771015571c5542d39e393d7fe6304421a928vboxsync {
8867771015571c5542d39e393d7fe6304421a928vboxsync pProv->fRegistered = false;
8867771015571c5542d39e393d7fe6304421a928vboxsync rc = VINF_SUCCESS;
8867771015571c5542d39e393d7fe6304421a928vboxsync }
8867771015571c5542d39e393d7fe6304421a928vboxsync if (RT_SUCCESS(rc))
8867771015571c5542d39e393d7fe6304421a928vboxsync {
8867771015571c5542d39e393d7fe6304421a928vboxsync RTListAppend(&pDevExt->TracerProviderList, &pProv->ListEntry);
8867771015571c5542d39e393d7fe6304421a928vboxsync RTSemFastMutexRelease(pDevExt->mtxTracer);
8867771015571c5542d39e393d7fe6304421a928vboxsync LOG_TRACER(("Registered DTrace provider '%s' in '%s' -> %p\n",
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync pProv->szName, pszModName, pProv->Core.TracerData.DTrace.idProvider));
8867771015571c5542d39e393d7fe6304421a928vboxsync }
8867771015571c5542d39e393d7fe6304421a928vboxsync else
8867771015571c5542d39e393d7fe6304421a928vboxsync {
8867771015571c5542d39e393d7fe6304421a928vboxsync RTSemFastMutexRelease(pDevExt->mtxTracer);
8867771015571c5542d39e393d7fe6304421a928vboxsync RTMemFree(pProv);
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync }
8867771015571c5542d39e393d7fe6304421a928vboxsync }
8867771015571c5542d39e393d7fe6304421a928vboxsync }
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync else
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync rc = VERR_NO_MEMORY;
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync if (RT_FAILURE(rc))
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync {
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync PSUPDRVTPPROVIDER pProvNext;
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync supdrvTracerFreeProvider(pProv);
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync RTSemFastMutexRequest(pDevExt->mtxTracer);
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync RTListForEachReverseSafe(&pDevExt->TracerProviderList, pProv, pProvNext, SUPDRVTPPROVIDER, ListEntry)
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync {
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync if (pProv->Core.pHdr == pVtgHdr)
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync {
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync RTListNodeRemove(&pProv->ListEntry);
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync supdrvTracerDeregisterVtgObj(pDevExt, pProv);
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync }
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync }
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync RTSemFastMutexRelease(pDevExt->mtxTracer);
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync return rc;
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync }
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync }
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync return VINF_SUCCESS;
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync}
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync/**
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync * Registers the VTG tracepoint providers of a driver.
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync *
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.
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync */
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsyncSUPR0DECL(int) SUPR0TracerRegisterDrv(PSUPDRVSESSION pSession, PVTGOBJHDR pVtgHdr, const char *pszName)
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync{
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync int rc;
c999f225d03074008a0c21cdd5d3594da476e243vboxsync
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync AssertReturn(SUP_IS_SESSION_VALID(pSession), VERR_INVALID_PARAMETER);
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync AssertPtrReturn(pszName, VERR_INVALID_POINTER);
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync AssertPtrReturn(pVtgHdr, VERR_INVALID_POINTER);
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync AssertReturn(pSession->R0Process == NIL_RTR0PROCESS, VERR_INVALID_PARAMETER);
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync rc = supdrvTracerRegisterVtgObj(pSession->pDevExt, pVtgHdr, _1M, NULL /*pImage*/, pSession, pszName);
159b42c2e42dbee770ce06fcf174697a9ae96e06vboxsync
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync /*
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync * Try unregister zombies while we have a chance.
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync */
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync supdrvTracerProcessZombies(pSession->pDevExt);
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync return rc;
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync}
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync/**
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync * Deregister the VTG tracepoint providers of a driver.
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync *
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync * @param pSession The support driver session handle.
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync * @param pVtgHdr The VTG header.
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync */
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsyncSUPR0DECL(void) SUPR0TracerDeregisterDrv(PSUPDRVSESSION pSession)
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync{
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync PSUPDRVTPPROVIDER pProv, pProvNext;
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync PSUPDRVDEVEXT pDevExt;
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync AssertReturnVoid(SUP_IS_SESSION_VALID(pSession));
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync AssertReturnVoid(pSession->R0Process == NIL_RTR0PROCESS);
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync pDevExt = pSession->pDevExt;
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync /*
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync * Search for providers belonging to this driver session.
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync */
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync RTSemFastMutexRequest(pDevExt->mtxTracer);
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync RTListForEachSafe(&pDevExt->TracerProviderList, pProv, pProvNext, SUPDRVTPPROVIDER, ListEntry)
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync {
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync if (pProv->pSession == pSession)
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync {
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync RTListNodeRemove(&pProv->ListEntry);
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync supdrvTracerDeregisterVtgObj(pDevExt, pProv);
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync }
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync }
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync RTSemFastMutexRelease(pDevExt->mtxTracer);
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync /*
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync * Try unregister zombies while we have a chance.
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync */
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync supdrvTracerProcessZombies(pDevExt);
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync}
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync/**
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync * Registers the VTG tracepoint providers of a module loaded by
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync * the support driver.
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync *
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync * This should be called from the ModuleInit code.
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync *
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync * @returns VBox status code.
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync * @param hMod The module handle.
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync * @param pVtgHdr The VTG header.
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync */
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsyncSUPR0DECL(int) SUPR0TracerRegisterModule(void *hMod, PVTGOBJHDR pVtgHdr)
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync{
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync PSUPDRVLDRIMAGE pImage = (PSUPDRVLDRIMAGE)hMod;
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync PSUPDRVDEVEXT pDevExt;
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync uintptr_t cbVtgObj;
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync int rc;
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync /*
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync * Validate input and context.
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync */
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync AssertPtrReturn(pImage, VERR_INVALID_HANDLE);
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync AssertPtrReturn(pVtgHdr, VERR_INVALID_POINTER);
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync AssertPtrReturn(pImage, VERR_INVALID_POINTER);
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync pDevExt = pImage->pDevExt;
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync AssertPtrReturn(pDevExt, VERR_INVALID_POINTER);
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync AssertReturn(pDevExt->pLdrInitImage == pImage, VERR_WRONG_ORDER);
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync AssertReturn(pDevExt->hLdrInitThread == RTThreadNativeSelf(), VERR_WRONG_ORDER);
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync /*
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync * Calculate the max VTG object size and hand it over to the common code.
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync */
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 VERR_INVALID_PARAMETER);
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync cbVtgObj = pImage->cbImageBits - cbVtgObj;
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync rc = supdrvTracerRegisterVtgObj(pDevExt, pVtgHdr, cbVtgObj, pImage, NULL, pImage->szName);
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync /*
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync * Try unregister zombies while we have a chance.
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync */
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync supdrvTracerProcessZombies(pDevExt);
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync return rc;
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync}
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync/**
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync * Registers the tracer implementation.
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync *
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync * This should be called from the ModuleInit code or from a ring-0 session.
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync *
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.
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync */
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsyncSUPR0DECL(int) SUPR0TracerRegisterImpl(void *hMod, PSUPDRVSESSION pSession, PCSUPDRVTRACERREG pReg, PCSUPDRVTRACERHLP *ppHlp)
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync{
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync PSUPDRVLDRIMAGE pImage = (PSUPDRVLDRIMAGE)hMod;
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync PSUPDRVDEVEXT pDevExt;
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync int rc;
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync /*
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync * Validate input and context.
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync */
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync AssertPtrReturn(ppHlp, VERR_INVALID_POINTER);
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync *ppHlp = NULL;
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync AssertPtrReturn(pReg, VERR_INVALID_HANDLE);
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync if (pImage)
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync {
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync AssertPtrReturn(pImage, VERR_INVALID_POINTER);
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync AssertReturn(pSession == NULL, VERR_INVALID_PARAMETER);
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync pDevExt = pImage->pDevExt;
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync AssertPtrReturn(pDevExt, VERR_INVALID_POINTER);
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync AssertReturn(pDevExt->pLdrInitImage == pImage, VERR_WRONG_ORDER);
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync AssertReturn(pDevExt->hLdrInitThread == RTThreadNativeSelf(), VERR_WRONG_ORDER);
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync }
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync else
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync {
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync AssertReturn(SUP_IS_SESSION_VALID(pSession), VERR_INVALID_PARAMETER);
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync AssertReturn(pSession->R0Process == NIL_RTR0PROCESS, VERR_INVALID_PARAMETER);
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync pDevExt = pSession->pDevExt;
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync AssertPtrReturn(pDevExt, VERR_INVALID_POINTER);
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync }
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync
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
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync /*
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync * Do the job.
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync */
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync rc = RTSemFastMutexRequest(pDevExt->mtxTracer);
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync if (RT_SUCCESS(rc))
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync {
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync if (!pDevExt->pTracerOps)
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync {
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync pDevExt->pTracerOps = pReg;
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync pDevExt->pTracerSession = pSession;
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync pDevExt->pTracerImage = pImage;
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync *ppHlp = &pDevExt->TracerHlp;
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync rc = VINF_SUCCESS;
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync }
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync else
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync rc = VERR_SUPDRV_TRACER_ALREADY_REGISTERED;
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync RTSemFastMutexRelease(pDevExt->mtxTracer);
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync }
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync return rc;
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync}
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync/**
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync * Common tracer implementation deregistration code.
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync *
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync * The caller sets fTracerUnloading prior to calling this function.
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync *
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync * @param pDevExt The device extension structure.
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync */
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsyncstatic void supdrvTracerCommonDeregisterImpl(PSUPDRVDEVEXT pDevExt)
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync{
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync supdrvTracerRemoveAllProviders(pDevExt);
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync RTSemFastMutexRequest(pDevExt->mtxTracer);
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync pDevExt->pTracerImage = NULL;
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync pDevExt->pTracerSession = NULL;
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync pDevExt->pTracerOps = NULL;
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync pDevExt->fTracerUnloading = false;
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync RTSemFastMutexRelease(pDevExt->mtxTracer);
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync}
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync/**
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync * Deregister a tracer implementation.
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync *
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync * This should be called from the ModuleTerm code or from a ring-0 session.
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync *
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync * @returns VBox status code.
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync * @param hMod The module handle.
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync * @param pSession Ring-0 session handle.
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync */
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsyncSUPR0DECL(int) SUPR0TracerDeregisterImpl(void *hMod, PSUPDRVSESSION pSession)
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync{
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync PSUPDRVLDRIMAGE pImage = (PSUPDRVLDRIMAGE)hMod;
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync PSUPDRVDEVEXT pDevExt;
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync int rc;
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync /*
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync * Validate input and context.
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync */
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync if (pImage)
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync {
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync AssertPtrReturn(pImage, VERR_INVALID_POINTER);
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync AssertReturn(pSession == NULL, VERR_INVALID_PARAMETER);
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync pDevExt = pImage->pDevExt;
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync }
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync else
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync {
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync AssertReturn(SUP_IS_SESSION_VALID(pSession), VERR_INVALID_PARAMETER);
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync AssertReturn(pSession->R0Process == NIL_RTR0PROCESS, VERR_INVALID_PARAMETER);
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync pDevExt = pSession->pDevExt;
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync }
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync AssertPtrReturn(pDevExt, VERR_INVALID_POINTER);
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync /*
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync * Do the job.
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync */
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync rc = RTSemFastMutexRequest(pDevExt->mtxTracer);
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync if (RT_SUCCESS(rc))
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync {
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync if ( pImage
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync ? pDevExt->pTracerImage == pImage
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync : pDevExt->pTracerSession == pSession)
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync {
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync pDevExt->fTracerUnloading = true;
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync RTSemFastMutexRelease(pDevExt->mtxTracer);
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync supdrvTracerCommonDeregisterImpl(pDevExt);
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync }
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync else
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync {
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync rc = VERR_SUPDRV_TRACER_NOT_REGISTERED;
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync RTSemFastMutexRelease(pDevExt->mtxTracer);
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync }
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync }
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync return rc;
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync}
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync/*
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync * The probe function is a bit more fun since we need tail jump optimizating.
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync *
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 */
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync#if defined(__GNUC__) && (defined(RT_OS_FREEBSD) || defined(RT_OS_LINUX))
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync__asm__ __volatile__("\
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync .section .text \n\
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync \n\
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync .p2align 2,,3 \n\
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync .global SUPR0TracerFireProbe \n\
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsyncSUPR0TracerFireProbe: \n\
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync");
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync# if defined(RT_ARCH_AMD64)
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync__asm__ __volatile__(" \
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync movq g_pfnSupdrvProbeFireKernel(%rip), %rax \n\
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync jmp *%rax \n\
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync");
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync# elif defined(RT_ARCH_X86)
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync__asm__ __volatile__("\
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync movl g_pfnSupdrvProbeFireKernel, %eax \n\
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync jmp *%eax \n\
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync");
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync# else
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync# error "Which arch is this?"
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync#endif
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync__asm__ __volatile__("\
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync \n\
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync .type supdrvTracerProbeFireStub,@function \n\
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync .global supdrvTracerProbeFireStub \n\
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsyncsupdrvTracerProbeFireStub: \n\
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync ret \n\
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync \n\
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync .previous \n\
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync");
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync#endif
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync
c999f225d03074008a0c21cdd5d3594da476e243vboxsync/**
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync * Module unloading hook, called after execution in the module have ceased.
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync *
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync * @param pDevExt The device extension structure.
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync * @param pImage The image being unloaded.
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync */
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsyncvoid VBOXCALL supdrvTracerModuleUnloading(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage)
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync{
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync PSUPDRVTPPROVIDER pProv, pProvNext;
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync AssertPtrReturnVoid(pImage); /* paranoia */
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync RTSemFastMutexRequest(pDevExt->mtxTracer);
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync /*
c1b4529a269091edd0274bd98d35b75663fd66c0vboxsync * If it is the tracer image, we have to unload all the providers.
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync */
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync if (pDevExt->pTracerImage == pImage)
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync {
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync pDevExt->fTracerUnloading = true;
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync RTSemFastMutexRelease(pDevExt->mtxTracer);
4c464a0800535c29782d7ab5bcd7820bc7115cd7vboxsync supdrvTracerCommonDeregisterImpl(pDevExt);
c999f225d03074008a0c21cdd5d3594da476e243vboxsync }
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync else
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync {
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync /*
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync * Unregister all providers belonging to this image.
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync */
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync RTListForEachSafe(&pDevExt->TracerProviderList, pProv, pProvNext, SUPDRVTPPROVIDER, ListEntry)
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync {
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync if (pProv->pImage == pImage)
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync {
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync RTListNodeRemove(&pProv->ListEntry);
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync supdrvTracerDeregisterVtgObj(pDevExt, pProv);
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync }
c999f225d03074008a0c21cdd5d3594da476e243vboxsync }
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync RTSemFastMutexRelease(pDevExt->mtxTracer);
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync
8867771015571c5542d39e393d7fe6304421a928vboxsync /*
8867771015571c5542d39e393d7fe6304421a928vboxsync * Try unregister zombies while we have a chance.
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync */
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync supdrvTracerProcessZombies(pDevExt);
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync }
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync}
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync/**
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync * Called when a session is being cleaned up.
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync *
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync * @param pDevExt The device extension structure.
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync * @param pSession The session that is being torn down.
8867771015571c5542d39e393d7fe6304421a928vboxsync */
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsyncvoid VBOXCALL supdrvTracerCleanupSession(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession)
8867771015571c5542d39e393d7fe6304421a928vboxsync{
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync /*
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync * If ring-0 session, make sure it has deregistered VTG objects and the tracer.
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync */
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync if (pSession->R0Process == NIL_RTR0PROCESS)
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync {
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync SUPDRVTPPROVIDER *pProvNext;
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync SUPDRVTPPROVIDER *pProv;
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync
8867771015571c5542d39e393d7fe6304421a928vboxsync RTSemFastMutexRequest(pDevExt->mtxTracer);
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync RTListForEachSafe(&pDevExt->TracerProviderList, pProv, pProvNext, SUPDRVTPPROVIDER, ListEntry)
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync {
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync if (pProv->pSession == pSession)
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync {
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync RTListNodeRemove(&pProv->ListEntry);
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync supdrvTracerDeregisterVtgObj(pDevExt, pProv);
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync }
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync }
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync RTSemFastMutexRelease(pDevExt->mtxTracer);
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync (void)SUPR0TracerDeregisterImpl(NULL, pSession);
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync }
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync /*
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync * Clean up instance data the trace may have associated with the session.
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync */
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync if (pSession->uTracerData)
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync {
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync RTSemFastMutexRequest(pDevExt->mtxTracer);
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync if ( pSession->uTracerData
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync && pDevExt->pTracerOps)
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync pDevExt->pTracerOps->pfnTracerClose(pDevExt->pTracerOps, pSession, pSession->uTracerData);
8867771015571c5542d39e393d7fe6304421a928vboxsync pSession->uTracerData = 0;
8867771015571c5542d39e393d7fe6304421a928vboxsync RTSemFastMutexRelease(pDevExt->mtxTracer);
9de47c4ec7b0fc9a384e4b815153de399da7b8devboxsync }
8867771015571c5542d39e393d7fe6304421a928vboxsync}
/**
* Early module initialization hook.
*
* @returns VBox status code.
* @param pDevExt The device extension structure.
*/
int VBOXCALL supdrvTracerInit(PSUPDRVDEVEXT pDevExt)
{
/*
* Register a provider for this module.
*/
int rc = RTSemFastMutexCreate(&pDevExt->mtxTracer);
if (RT_SUCCESS(rc))
{
pDevExt->TracerHlp.uVersion = SUPDRVTRACERHLP_VERSION;
/** @todo */
pDevExt->TracerHlp.uEndVersion = SUPDRVTRACERHLP_VERSION;
RTListInit(&pDevExt->TracerProviderList);
RTListInit(&pDevExt->TracerProviderZombieList);
#ifdef VBOX_WITH_DTRACE_R0DRV
rc = supdrvTracerRegisterVtgObj(pDevExt, &g_VTGObjHeader, _1M, NULL /*pImage*/, NULL /*pSession*/, "vboxdrv");
if (RT_SUCCESS(rc))
#endif
return rc;
RTSemFastMutexDestroy(pDevExt->mtxTracer);
}
pDevExt->mtxTracer = NIL_RTSEMFASTMUTEX;
return rc;
}
/**
* Late module termination hook.
*
* @returns VBox status code.
* @param pDevExt The device extension structure.
*/
void VBOXCALL supdrvTracerTerm(PSUPDRVDEVEXT pDevExt)
{
LOG_TRACER(("supdrvTracerTerm\n"));
supdrvTracerRemoveAllProviders(pDevExt);
RTSemFastMutexDestroy(pDevExt->mtxTracer);
pDevExt->mtxTracer = NIL_RTSEMFASTMUTEX;
LOG_TRACER(("supdrvTracerTerm: Done\n"));
}