SUPDrvTracer.cpp revision 6947da10583ff63a965e6c07156ce7126a7bad22
9ad572a3ac0fd3845a9abecfbf41e8db9b3a5cf0vboxsync/* $Id$ */
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync/** @file
adf2bcd2e5d07d5a11553b88e147c1f4b2249bffvboxsync * VBoxDrv - The VirtualBox Support Driver - Tracer Interface.
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync */
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync/*
c58f1213e628a545081c70e26c6b67a841cff880vboxsync * Copyright (C) 2012 Oracle Corporation
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync *
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync * available from http://www.virtualbox.org. This file is free software;
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync * you can redistribute it and/or modify it under the terms of the GNU
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync * General Public License (GPL) as published by the Free Software
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync *
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync * The contents of this file may alternatively be used under the terms
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync * of the Common Development and Distribution License Version 1.0
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync * VirtualBox OSE distribution, in which case the provisions of the
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync * CDDL are applicable instead of those of the GPL.
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync *
70bb61ea2f96e80150e807529ce5df435607706bvboxsync * You may elect to license modified versions of this file under the
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync * terms and conditions of either the GPL or the CDDL or both.
23179f1443b03947d85eccc81cbc6b5153a4abf3vboxsync */
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync/*******************************************************************************
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync* Header Files *
edefdc20eedaf9ef5b1293e56ba9b8cca7b5c740vboxsync*******************************************************************************/
edefdc20eedaf9ef5b1293e56ba9b8cca7b5c740vboxsync#define LOG_GROUP LOG_GROUP_SUP_DRV
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync#define SUPDRV_AGNOSTIC
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync#include "SUPDrvInternal.h"
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync#include <VBox/err.h>
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync#include <VBox/log.h>
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync#include <VBox/VBoxTpG.h>
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync#include <iprt/assert.h>
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync#include <iprt/ctype.h>
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync#include <iprt/list.h>
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync#include <iprt/mem.h>
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync#include <iprt/semaphore.h>
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync#include <iprt/thread.h>
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync/*******************************************************************************
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync* Structures and Typedefs *
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync*******************************************************************************/
1147e980f6ab0b7ff1d08c13ad1c03eea30d102dvboxsync/**
e59069cf1c98c1c2e90a18ec76fbc2e9907fb917vboxsync * Data for a tracepoint provider.
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync */
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsynctypedef struct SUPDRVTPPROVIDER
b304856b23107864c9c594a80cebca6006623f31vboxsync{
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync /** The entry in the provider list for this image. */
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync RTLISTNODE ListEntry;
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync /** The core structure. */
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync SUPDRVVDTPROVIDERCORE Core;
8fdb854581fe3cb394d84835dc09b02e6e18d4edvboxsync
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync /** Pointer to the image this provider resides in. NULL if it's a
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync * driver. */
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync PSUPDRVLDRIMAGE pImage;
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync /** The session this provider is associated with if registered via
c33fc49611f2444dade533488bf431e29eb88bcdvboxsync * SUPR0VtgRegisterDrv. NULL if pImage is set. */
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync PSUPDRVSESSION pSession;
1bf151411167b02ebdc6d6a18de8b97030341e1fvboxsync
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync /** Used to indicate that we've called pfnProviderDeregistered already and it
6e12ccc60ac657fb87e27b7a2b26e0a63bebe024vboxsync * failed because the provider was busy. Next time we must try
6e12ccc60ac657fb87e27b7a2b26e0a63bebe024vboxsync * pfnProviderDeregisterZombie.
6e12ccc60ac657fb87e27b7a2b26e0a63bebe024vboxsync *
db0ecde8f28fdb4525bc6d94056166c70b02ebb8vboxsync * @remarks This does not necessiarly mean the provider is in the zombie
db0ecde8f28fdb4525bc6d94056166c70b02ebb8vboxsync * list. See supdrvTracerCommonDeregisterImpl. */
db0ecde8f28fdb4525bc6d94056166c70b02ebb8vboxsync bool fZombie;
8b36957d815c23b479eb35d93ac76c66392e9402vboxsync /** Set if the provider has been successfully registered with the
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync * tracer. */
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync bool fRegistered;
9353e321b583ed6f2b42414257a5212885575b5cvboxsync /** The provider name (for logging purposes). */
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync char szName[1];
9353e321b583ed6f2b42414257a5212885575b5cvboxsync} SUPDRVTPPROVIDER;
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync/** Pointer to the data for a tracepoint provider. */
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsynctypedef SUPDRVTPPROVIDER *PSUPDRVTPPROVIDER;
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync/*******************************************************************************
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync* Defined Constants And Macros *
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync*******************************************************************************/
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync/** Simple SUPR0Printf-style logging. */
2a5e5a032e6f23f8937718e4ee4d6979188bdd19vboxsync#ifdef DEBUG_bird
2a5e5a032e6f23f8937718e4ee4d6979188bdd19vboxsync# define LOG_TRACER(a_Args) SUPR0Printf a_Args
2a5e5a032e6f23f8937718e4ee4d6979188bdd19vboxsync#else
2a5e5a032e6f23f8937718e4ee4d6979188bdd19vboxsync# define LOG_TRACER(a_Args) do { } while (0)
2a5e5a032e6f23f8937718e4ee4d6979188bdd19vboxsync#endif
2a5e5a032e6f23f8937718e4ee4d6979188bdd19vboxsync
2a5e5a032e6f23f8937718e4ee4d6979188bdd19vboxsync
2a5e5a032e6f23f8937718e4ee4d6979188bdd19vboxsync/*******************************************************************************
2a5e5a032e6f23f8937718e4ee4d6979188bdd19vboxsync* Global Variables *
2a5e5a032e6f23f8937718e4ee4d6979188bdd19vboxsync*******************************************************************************/
2a5e5a032e6f23f8937718e4ee4d6979188bdd19vboxsync/** The address of the current probe fire routine for kernel mode. */
2a5e5a032e6f23f8937718e4ee4d6979188bdd19vboxsyncPFNRT g_pfnSupdrvProbeFireKernel = supdrvTracerProbeFireStub;
2a5e5a032e6f23f8937718e4ee4d6979188bdd19vboxsync
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsync/**
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync * Validates a VTG string against length and characterset limitations.
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync *
f62342e2cc901a67e27fa69c0e712ee35e9c4c68vboxsync * @returns VINF_SUCCESS, VERR_SUPDRV_VTG_BAD_STRING or
b604fbf16eda38d14b4999c245f032bfaa5aa85avboxsync * VERR_SUPDRV_VTG_STRING_TOO_LONG.
13d1fd6f43e9a245a4f2b4fc6845bdaa5d0f4134vboxsync * @param psz The string.
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync */
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsyncstatic int supdrvVtgValidateString(const char *psz)
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync{
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync size_t off = 0;
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync while (off < _4K)
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync {
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsync char const ch = psz[off++];
cebc93936b5bb4d867e1c086dd1b206db33c31dcvboxsync if (!ch)
cebc93936b5bb4d867e1c086dd1b206db33c31dcvboxsync return VINF_SUCCESS;
cebc93936b5bb4d867e1c086dd1b206db33c31dcvboxsync if ( !RTLocCIsAlNum(ch)
62a515eec8de1b7804ec6997c0f2013fef5c5a6bvboxsync && ch != ' '
cebc93936b5bb4d867e1c086dd1b206db33c31dcvboxsync && ch != '_'
cebc93936b5bb4d867e1c086dd1b206db33c31dcvboxsync && ch != '-'
cebc93936b5bb4d867e1c086dd1b206db33c31dcvboxsync && ch != '('
cebc93936b5bb4d867e1c086dd1b206db33c31dcvboxsync && ch != ')'
cebc93936b5bb4d867e1c086dd1b206db33c31dcvboxsync && ch != ','
cebc93936b5bb4d867e1c086dd1b206db33c31dcvboxsync && ch != '*'
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync && ch != '&'
19cb1f8699e352d590c4946caee33863a5157241vboxsync )
19cb1f8699e352d590c4946caee33863a5157241vboxsync {
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync /*RTAssertMsg2("off=%u '%s'\n", off, psz);*/
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync return VERR_SUPDRV_VTG_BAD_STRING;
67ee25dd0b63a61dc35a35d0aade75ca6cd06350vboxsync }
67ee25dd0b63a61dc35a35d0aade75ca6cd06350vboxsync }
67ee25dd0b63a61dc35a35d0aade75ca6cd06350vboxsync return VERR_SUPDRV_VTG_STRING_TOO_LONG;
67ee25dd0b63a61dc35a35d0aade75ca6cd06350vboxsync}
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync/**
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync * Validates the VTG data.
2a171646d32f8a15e9820d6fb3bf3f9b9990ca3fvboxsync *
3933885bc0c2c93436d858a14564c6179ec72872vboxsync * @returns VBox status code.
3933885bc0c2c93436d858a14564c6179ec72872vboxsync * @param pVtgHdr The VTG object header of the data to validate.
3933885bc0c2c93436d858a14564c6179ec72872vboxsync * @param cbVtgObj The size of the VTG object.
3933885bc0c2c93436d858a14564c6179ec72872vboxsync * @param pbImage The image base. For validating the probe
3933885bc0c2c93436d858a14564c6179ec72872vboxsync * locations.
3933885bc0c2c93436d858a14564c6179ec72872vboxsync * @param cbImage The image size to go with @a pbImage.
3933885bc0c2c93436d858a14564c6179ec72872vboxsync */
3933885bc0c2c93436d858a14564c6179ec72872vboxsyncstatic int supdrvVtgValidate(PVTGOBJHDR pVtgHdr, size_t cbVtgObj, const uint8_t *pbImage, size_t cbImage)
cc74f15083bf80fbc96723a89faa06c15d0dead8vboxsync{
a72b5355eb89aafe6bfcc8912cf02645d7cccceavboxsync uintptr_t cbTmp;
a72b5355eb89aafe6bfcc8912cf02645d7cccceavboxsync uintptr_t offTmp;
3933885bc0c2c93436d858a14564c6179ec72872vboxsync uintptr_t i;
6e25221ce8ef8e656d1e15eb7ec5cf8ae758ceb2vboxsync uintptr_t cProviders;
3933885bc0c2c93436d858a14564c6179ec72872vboxsync int rc;
3933885bc0c2c93436d858a14564c6179ec72872vboxsync
3933885bc0c2c93436d858a14564c6179ec72872vboxsync if (!pbImage || !cbImage)
3933885bc0c2c93436d858a14564c6179ec72872vboxsync {
9ca017ceee656f9d33f2cb6652e401b5f17fcfb7vboxsync pbImage = NULL;
3933885bc0c2c93436d858a14564c6179ec72872vboxsync cbImage = 0;
e2760cdc84c692bc46cfaf5018d313db2f122acavboxsync }
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync#define MY_VALIDATE_PTR(p, cb, cMin, cMax, cbUnit, rcBase) \
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync do { \
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync if ( (cb) >= cbVtgObj \
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync || (uintptr_t)(p) - (uintptr_t)pVtgHdr > cbVtgObj - (cb) ) \
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync { \
ad9e5a61fea617d40d07390ff1737277d6aef869vboxsync SUPR0Printf("supdrvVtgValidate: " #rcBase "_TOO_PTR - p=%p cb=%#zx pVtgHdr=%p cbVtgHdr=%#zu line=%u %s\n", \
23d9dbdaf1b83107abf9882246a4a46933f733efvboxsync p, (size_t)(cb), pVtgHdr, cbVtgObj, __LINE__, #p); \
a9315925c69e4c3bb342bb317ca5b6d29e1ee467vboxsync return rcBase ## _PTR; \
a9315925c69e4c3bb342bb317ca5b6d29e1ee467vboxsync } \
a9315925c69e4c3bb342bb317ca5b6d29e1ee467vboxsync if ((cb) < (cMin) * (cbUnit)) \
dbabc9de5bf52ce5eb77cf82b038e9a6166c5a04vboxsync { \
4090390866c02d5d0ad061151cdb298b9a173e86vboxsync SUPR0Printf("supdrvVtgValidate: " #rcBase "_TOO_FEW - cb=%#zx cMin=%#zx cbUnit=%#zx line=%u %s\n", \
4090390866c02d5d0ad061151cdb298b9a173e86vboxsync (size_t)(cb), (size_t)(cMin), (size_t)cbUnit, __LINE__, #p); \
40dce69ff1c2949a489337922f30f1021d62d864vboxsync return rcBase ## _TOO_FEW; \
40dce69ff1c2949a489337922f30f1021d62d864vboxsync } \
40dce69ff1c2949a489337922f30f1021d62d864vboxsync if ((cb) >= (cMax) * (cbUnit)) \
40dce69ff1c2949a489337922f30f1021d62d864vboxsync { \
40dce69ff1c2949a489337922f30f1021d62d864vboxsync SUPR0Printf("supdrvVtgValidate: " #rcBase "_TOO_MUCH - cb=%#zx cMax=%#zx cbUnit=%#zx line=%u %s\n", \
657b2c9f6d33f08001e5fa6f6e0572dcf0391013vboxsync (size_t)(cb), (size_t)(cMax), (size_t)cbUnit, __LINE__, #p); \
7a29aa5ce149ccd344a2929d2815b8e212690b92vboxsync return rcBase ## _TOO_MUCH; \
45a01ef53b009e9f56ce427bd8688da02ad32389vboxsync } \
45a01ef53b009e9f56ce427bd8688da02ad32389vboxsync if ((cb) / (cbUnit) * (cbUnit) != (cb)) \
45a01ef53b009e9f56ce427bd8688da02ad32389vboxsync { \
a1b4fb3917412d2632d358ff8989f1ec971f2d5bvboxsync SUPR0Printf("supdrvVtgValidate: " #rcBase "_NOT_MULTIPLE - cb=%#zx cbUnit=%#zx line=%u %s\n", \
a1b4fb3917412d2632d358ff8989f1ec971f2d5bvboxsync (size_t)(cb), (size_t)cbUnit, __LINE__, #p); \
a1b4fb3917412d2632d358ff8989f1ec971f2d5bvboxsync return rcBase ## _NOT_MULTIPLE; \
7708252d252a55417a6a817041e4356797e34255vboxsync } \
5a41049c24bcf93e3dc63c76bee23db645867e0cvboxsync } while (0)
62ab017295981c81484e5a5f93ff8b5f85f7defbvboxsync#define MY_WITHIN_IMAGE(p, rc) \
62ab017295981c81484e5a5f93ff8b5f85f7defbvboxsync do { \
7708252d252a55417a6a817041e4356797e34255vboxsync if (pbImage) \
7708252d252a55417a6a817041e4356797e34255vboxsync { \
a1b4fb3917412d2632d358ff8989f1ec971f2d5bvboxsync if ((uintptr_t)(p) - (uintptr_t)pbImage > cbImage) \
3f00104a87d8a725dfa0348b69cbdac901062a4avboxsync { \
3f00104a87d8a725dfa0348b69cbdac901062a4avboxsync SUPR0Printf("supdrvVtgValidate: " #rc " - p=%p pbImage=%p cbImage=%#zxline=%u %s\n", \
48890ac9b4b339e0341e826b5c26ce6408729987vboxsync p, pbImage, cbImage, #p); \
3f00104a87d8a725dfa0348b69cbdac901062a4avboxsync return (rc); \
3f00104a87d8a725dfa0348b69cbdac901062a4avboxsync } \
f2dbf051efd73ff79892d4cec2b466139f962a40vboxsync } \
5d57bcb78f1f3f918bd3daf709b551b8c2d30485vboxsync else if (!RT_VALID_PTR(p)) \
cccc6ee5f7156cfcdf13acca545cf65124d9ed44vboxsync return (rc); \
3f00104a87d8a725dfa0348b69cbdac901062a4avboxsync } while (0)
904810c4c6668233349b025cc58013cb7c11c701vboxsync#define MY_VALIDATE_STR(offStrTab) \
904810c4c6668233349b025cc58013cb7c11c701vboxsync do { \
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync if ((offStrTab) >= pVtgHdr->cbStrTab) \
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync return VERR_SUPDRV_VTG_STRTAB_OFF; \
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync rc = supdrvVtgValidateString(pVtgHdr->pachStrTab + (offStrTab)); \
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync if (rc != VINF_SUCCESS) \
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync return rc; \
1147e980f6ab0b7ff1d08c13ad1c03eea30d102dvboxsync } while (0)
e59069cf1c98c1c2e90a18ec76fbc2e9907fb917vboxsync#define MY_VALIDATE_ATTR(Attr) \
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync do { \
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync if ((Attr).u8Code <= (uint8_t)kVTGStability_Invalid || (Attr).u8Code >= (uint8_t)kVTGStability_End) \
b304856b23107864c9c594a80cebca6006623f31vboxsync return VERR_SUPDRV_VTG_BAD_ATTR; \
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync if ((Attr).u8Data <= (uint8_t)kVTGStability_Invalid || (Attr).u8Data >= (uint8_t)kVTGStability_End) \
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync return VERR_SUPDRV_VTG_BAD_ATTR; \
261b44f7fa60a1d4bb4102142d3aa44188908484vboxsync if ((Attr).u8DataDep <= (uint8_t)kVTGClass_Invalid || (Attr).u8DataDep >= (uint8_t)kVTGClass_End) \
261b44f7fa60a1d4bb4102142d3aa44188908484vboxsync return VERR_SUPDRV_VTG_BAD_ATTR; \
261b44f7fa60a1d4bb4102142d3aa44188908484vboxsync } while (0)
8fdb854581fe3cb394d84835dc09b02e6e18d4edvboxsync
261b44f7fa60a1d4bb4102142d3aa44188908484vboxsync /*
261b44f7fa60a1d4bb4102142d3aa44188908484vboxsync * The header.
261b44f7fa60a1d4bb4102142d3aa44188908484vboxsync */
261b44f7fa60a1d4bb4102142d3aa44188908484vboxsync if (memcmp(pVtgHdr->szMagic, VTGOBJHDR_MAGIC, sizeof(pVtgHdr->szMagic)))
c33fc49611f2444dade533488bf431e29eb88bcdvboxsync return VERR_SUPDRV_VTG_MAGIC;
261b44f7fa60a1d4bb4102142d3aa44188908484vboxsync if (pVtgHdr->cBits != ARCH_BITS)
1bf151411167b02ebdc6d6a18de8b97030341e1fvboxsync return VERR_SUPDRV_VTG_BITS;
db0ecde8f28fdb4525bc6d94056166c70b02ebb8vboxsync if (pVtgHdr->u32Reserved0)
db0ecde8f28fdb4525bc6d94056166c70b02ebb8vboxsync return VERR_SUPDRV_VTG_BAD_HDR;
db0ecde8f28fdb4525bc6d94056166c70b02ebb8vboxsync
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync MY_VALIDATE_PTR(pVtgHdr->paProviders, pVtgHdr->cbProviders, 1, 16, sizeof(VTGDESCPROVIDER), VERR_SUPDRV_VTG_BAD_HDR);
6e12ccc60ac657fb87e27b7a2b26e0a63bebe024vboxsync MY_VALIDATE_PTR(pVtgHdr->paProbes, pVtgHdr->cbProbes, 1, _32K, sizeof(VTGDESCPROBE), VERR_SUPDRV_VTG_BAD_HDR);
6e12ccc60ac657fb87e27b7a2b26e0a63bebe024vboxsync MY_VALIDATE_PTR(pVtgHdr->pafProbeEnabled, pVtgHdr->cbProbeEnabled, 1, _32K, sizeof(bool), VERR_SUPDRV_VTG_BAD_HDR);
6e12ccc60ac657fb87e27b7a2b26e0a63bebe024vboxsync MY_VALIDATE_PTR(pVtgHdr->pachStrTab, pVtgHdr->cbStrTab, 4, _1M, sizeof(char), VERR_SUPDRV_VTG_BAD_HDR);
657b2c9f6d33f08001e5fa6f6e0572dcf0391013vboxsync MY_VALIDATE_PTR(pVtgHdr->paArgLists, pVtgHdr->cbArgLists, 1, _32K, sizeof(uint32_t), VERR_SUPDRV_VTG_BAD_HDR);
e2760cdc84c692bc46cfaf5018d313db2f122acavboxsync
8b36957d815c23b479eb35d93ac76c66392e9402vboxsync MY_WITHIN_IMAGE(pVtgHdr->paProbLocs, VERR_SUPDRV_VTG_BAD_HDR_PTR);
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync MY_WITHIN_IMAGE(pVtgHdr->paProbLocsEnd, VERR_SUPDRV_VTG_BAD_HDR_PTR);
261b44f7fa60a1d4bb4102142d3aa44188908484vboxsync if ((uintptr_t)pVtgHdr->paProbLocs > (uintptr_t)pVtgHdr->paProbLocsEnd)
9353e321b583ed6f2b42414257a5212885575b5cvboxsync {
261b44f7fa60a1d4bb4102142d3aa44188908484vboxsync SUPR0Printf("supdrvVtgValidate: VERR_SUPDRV_VTG_BAD_HDR_PTR - paProbeLocs=%p > paProbLocsEnd=%p\n",
9353e321b583ed6f2b42414257a5212885575b5cvboxsync pVtgHdr->paProbLocs, pVtgHdr->paProbLocsEnd);
261b44f7fa60a1d4bb4102142d3aa44188908484vboxsync return VERR_SUPDRV_VTG_BAD_HDR_PTR;
261b44f7fa60a1d4bb4102142d3aa44188908484vboxsync }
fc5f879e9508f333e20b37c63db9189a33059308vboxsync cbTmp = (uintptr_t)pVtgHdr->paProbLocsEnd - (uintptr_t)pVtgHdr->paProbLocs;
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync if (cbTmp < sizeof(VTGPROBELOC))
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync {
1c6ec9a3a329da6f61978a372e509cd233f0d9f9vboxsync SUPR0Printf("supdrvVtgValidate: VERR_SUPDRV_VTG_BAD_HDR_TOO_FEW - cbTmp=%#zx paProbeLocs=%p paProbLocsEnd=%p\n",
261b44f7fa60a1d4bb4102142d3aa44188908484vboxsync cbTmp, pVtgHdr->paProbLocs, pVtgHdr->paProbLocsEnd);
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync return VERR_SUPDRV_VTG_BAD_HDR_TOO_FEW;
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync }
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync if (cbTmp >= _128K * sizeof(VTGPROBELOC))
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync {
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync SUPR0Printf("supdrvVtgValidate: VERR_SUPDRV_VTG_BAD_HDR_TOO_MUCH - cbTmp=%#zx paProbeLocs=%p paProbLocsEnd=%p\n",
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync cbTmp, pVtgHdr->paProbLocs, pVtgHdr->paProbLocsEnd);
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync return VERR_SUPDRV_VTG_BAD_HDR_TOO_MUCH;
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync }
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync if (cbTmp / sizeof(VTGPROBELOC) * sizeof(VTGPROBELOC) != cbTmp)
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync {
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync SUPR0Printf("supdrvVtgValidate: VERR_SUPDRV_VTG_BAD_HDR_NOT_MULTIPLE - cbTmp=%#zx cbUnit=%#zx paProbeLocs=%p paProbLocsEnd=%p\n",
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync cbTmp, sizeof(VTGPROBELOC), pVtgHdr->paProbLocs, pVtgHdr->paProbLocsEnd);
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync return VERR_SUPDRV_VTG_BAD_HDR_NOT_MULTIPLE;
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync }
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync
261b44f7fa60a1d4bb4102142d3aa44188908484vboxsync if (pVtgHdr->cbProbes / sizeof(VTGDESCPROBE) != pVtgHdr->cbProbeEnabled)
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsync {
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync SUPR0Printf("supdrvVtgValidate: VERR_SUPDRV_VTG_BAD_HDR - cbProbeEnabled=%#zx cbProbes=%#zx\n",
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync pVtgHdr->cbProbeEnabled, pVtgHdr->cbProbes);
f62342e2cc901a67e27fa69c0e712ee35e9c4c68vboxsync return VERR_SUPDRV_VTG_BAD_HDR;
b604fbf16eda38d14b4999c245f032bfaa5aa85avboxsync }
13d1fd6f43e9a245a4f2b4fc6845bdaa5d0f4134vboxsync
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync /*
261b44f7fa60a1d4bb4102142d3aa44188908484vboxsync * Validate the providers.
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync */
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync cProviders = i = pVtgHdr->cbProviders / sizeof(VTGDESCPROVIDER);
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync while (i-- > 0)
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync {
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsync MY_VALIDATE_STR(pVtgHdr->paProviders[i].offName);
cebc93936b5bb4d867e1c086dd1b206db33c31dcvboxsync if (pVtgHdr->paProviders[i].iFirstProbe >= pVtgHdr->cbProbeEnabled)
95cb8e789c1eed6f2bb3195d0b996feee11d548evboxsync return VERR_SUPDRV_VTG_BAD_PROVIDER;
cebc93936b5bb4d867e1c086dd1b206db33c31dcvboxsync if (pVtgHdr->paProviders[i].iFirstProbe + pVtgHdr->paProviders[i].cProbes > pVtgHdr->cbProbeEnabled)
62a515eec8de1b7804ec6997c0f2013fef5c5a6bvboxsync return VERR_SUPDRV_VTG_BAD_PROVIDER;
cebc93936b5bb4d867e1c086dd1b206db33c31dcvboxsync MY_VALIDATE_ATTR(pVtgHdr->paProviders[i].AttrSelf);
cebc93936b5bb4d867e1c086dd1b206db33c31dcvboxsync MY_VALIDATE_ATTR(pVtgHdr->paProviders[i].AttrModules);
cebc93936b5bb4d867e1c086dd1b206db33c31dcvboxsync MY_VALIDATE_ATTR(pVtgHdr->paProviders[i].AttrFunctions);
cebc93936b5bb4d867e1c086dd1b206db33c31dcvboxsync MY_VALIDATE_ATTR(pVtgHdr->paProviders[i].AttrNames);
cebc93936b5bb4d867e1c086dd1b206db33c31dcvboxsync MY_VALIDATE_ATTR(pVtgHdr->paProviders[i].AttrArguments);
cebc93936b5bb4d867e1c086dd1b206db33c31dcvboxsync if (pVtgHdr->paProviders[i].bReserved)
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync return VERR_SUPDRV_VTG_BAD_PROVIDER;
19cb1f8699e352d590c4946caee33863a5157241vboxsync }
19cb1f8699e352d590c4946caee33863a5157241vboxsync
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync /*
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync * Validate probes.
67ee25dd0b63a61dc35a35d0aade75ca6cd06350vboxsync */
67ee25dd0b63a61dc35a35d0aade75ca6cd06350vboxsync i = pVtgHdr->cbProbes / sizeof(VTGDESCPROBE);
67ee25dd0b63a61dc35a35d0aade75ca6cd06350vboxsync while (i-- > 0)
67ee25dd0b63a61dc35a35d0aade75ca6cd06350vboxsync {
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync PVTGDESCARGLIST pArgList;
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync unsigned iArg;
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync bool fHaveLargeArgs;
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync
2a171646d32f8a15e9820d6fb3bf3f9b9990ca3fvboxsync MY_VALIDATE_STR(pVtgHdr->paProbes[i].offName);
3933885bc0c2c93436d858a14564c6179ec72872vboxsync if (pVtgHdr->paProbes[i].offArgList >= pVtgHdr->cbArgLists)
3933885bc0c2c93436d858a14564c6179ec72872vboxsync return VERR_SUPDRV_VTG_BAD_PROBE;
3933885bc0c2c93436d858a14564c6179ec72872vboxsync if (pVtgHdr->paProbes[i].offArgList & 3)
3933885bc0c2c93436d858a14564c6179ec72872vboxsync return VERR_SUPDRV_VTG_BAD_PROBE;
3933885bc0c2c93436d858a14564c6179ec72872vboxsync if (pVtgHdr->paProbes[i].idxEnabled != i) /* The lists are parallel. */
3933885bc0c2c93436d858a14564c6179ec72872vboxsync return VERR_SUPDRV_VTG_BAD_PROBE;
060f7ec6ae5c99df18341ef2e1f3e91f4b0c89f1vboxsync if (pVtgHdr->paProbes[i].idxProvider >= cProviders)
3933885bc0c2c93436d858a14564c6179ec72872vboxsync return VERR_SUPDRV_VTG_BAD_PROBE;
cc74f15083bf80fbc96723a89faa06c15d0dead8vboxsync if ( i - pVtgHdr->paProviders[pVtgHdr->paProbes[i].idxProvider].iFirstProbe
a72b5355eb89aafe6bfcc8912cf02645d7cccceavboxsync >= pVtgHdr->paProviders[pVtgHdr->paProbes[i].idxProvider].cProbes)
a72b5355eb89aafe6bfcc8912cf02645d7cccceavboxsync return VERR_SUPDRV_VTG_BAD_PROBE;
3933885bc0c2c93436d858a14564c6179ec72872vboxsync if (pVtgHdr->paProbes[i].u32User)
6e25221ce8ef8e656d1e15eb7ec5cf8ae758ceb2vboxsync return VERR_SUPDRV_VTG_BAD_PROBE;
3933885bc0c2c93436d858a14564c6179ec72872vboxsync
3933885bc0c2c93436d858a14564c6179ec72872vboxsync /* The referenced argument list. */
3933885bc0c2c93436d858a14564c6179ec72872vboxsync pArgList = (PVTGDESCARGLIST)((uintptr_t)pVtgHdr->paArgLists + pVtgHdr->paProbes[i].offArgList);
060f7ec6ae5c99df18341ef2e1f3e91f4b0c89f1vboxsync if (pArgList->cArgs > 16)
9ca017ceee656f9d33f2cb6652e401b5f17fcfb7vboxsync return VERR_SUPDRV_VTG_BAD_ARGLIST;
3933885bc0c2c93436d858a14564c6179ec72872vboxsync if (pArgList->fHaveLargeArgs >= 2)
261b44f7fa60a1d4bb4102142d3aa44188908484vboxsync return VERR_SUPDRV_VTG_BAD_ARGLIST;
261b44f7fa60a1d4bb4102142d3aa44188908484vboxsync if ( pArgList->abReserved[0]
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync || pArgList->abReserved[1])
f106b549ead77cab51ff1e2c116060aaabb90d5evboxsync return VERR_SUPDRV_VTG_BAD_ARGLIST;
f106b549ead77cab51ff1e2c116060aaabb90d5evboxsync fHaveLargeArgs = false;
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync iArg = pArgList->cArgs;
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync while (iArg-- > 0)
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync {
23d9dbdaf1b83107abf9882246a4a46933f733efvboxsync rc = VINF_SUCCESS;
a9315925c69e4c3bb342bb317ca5b6d29e1ee467vboxsync MY_VALIDATE_STR(pArgList->aArgs[iArg].offType);
a9315925c69e4c3bb342bb317ca5b6d29e1ee467vboxsync switch (pArgList->aArgs[iArg].fType & VTG_TYPE_SIZE_MASK)
a9315925c69e4c3bb342bb317ca5b6d29e1ee467vboxsync {
ad9e5a61fea617d40d07390ff1737277d6aef869vboxsync case 0:
dbabc9de5bf52ce5eb77cf82b038e9a6166c5a04vboxsync if (pArgList->aArgs[iArg].fType & VTG_TYPE_FIXED_SIZED)
4090390866c02d5d0ad061151cdb298b9a173e86vboxsync rc = VERR_SUPDRV_TRACER_BAD_ARG_FLAGS;
4090390866c02d5d0ad061151cdb298b9a173e86vboxsync break;
40dce69ff1c2949a489337922f30f1021d62d864vboxsync case 1: case 2: case 4: case 8:
40dce69ff1c2949a489337922f30f1021d62d864vboxsync break;
40dce69ff1c2949a489337922f30f1021d62d864vboxsync default:
40dce69ff1c2949a489337922f30f1021d62d864vboxsync rc = VERR_SUPDRV_TRACER_BAD_ARG_FLAGS;
40dce69ff1c2949a489337922f30f1021d62d864vboxsync }
7a29aa5ce149ccd344a2929d2815b8e212690b92vboxsync if (RT_FAILURE(rc))
3f00104a87d8a725dfa0348b69cbdac901062a4avboxsync {
f57758f0bcf995d350d64a7c059ac93573144c05vboxsync SUPR0Printf("supdrvVtgValidate: VERR_SUPDRV_TRACER_BAD_ARG_FLAGS - fType=%#x iArg=%u iProbe=%u\n",
48890ac9b4b339e0341e826b5c26ce6408729987vboxsync pArgList->aArgs[iArg].fType, iArg, i);
f57758f0bcf995d350d64a7c059ac93573144c05vboxsync return rc;
3f00104a87d8a725dfa0348b69cbdac901062a4avboxsync }
3f00104a87d8a725dfa0348b69cbdac901062a4avboxsync if (VTG_TYPE_IS_LARGE(pArgList->aArgs[iArg].fType) && iArg >= 5)
5d57bcb78f1f3f918bd3daf709b551b8c2d30485vboxsync fHaveLargeArgs = true;
cccc6ee5f7156cfcdf13acca545cf65124d9ed44vboxsync }
3f00104a87d8a725dfa0348b69cbdac901062a4avboxsync if ((uint8_t)fHaveLargeArgs != pArgList->fHaveLargeArgs)
45a01ef53b009e9f56ce427bd8688da02ad32389vboxsync {
45a01ef53b009e9f56ce427bd8688da02ad32389vboxsync SUPR0Printf("supdrvVtgValidate: VERR_SUPDRV_TRACER_BAD_ARG_FLAGS - fType=%#x iProbe=%u fHaveLargeArgs=%d expected %d\n",
45a01ef53b009e9f56ce427bd8688da02ad32389vboxsync pArgList->aArgs[iArg].fType, i, pArgList->fHaveLargeArgs, fHaveLargeArgs);
a1b4fb3917412d2632d358ff8989f1ec971f2d5bvboxsync return VERR_SUPDRV_VTG_BAD_PROBE;
505ddd00252720bfb5569fcb17bfda53dc141e3bvboxsync }
505ddd00252720bfb5569fcb17bfda53dc141e3bvboxsync }
a1b4fb3917412d2632d358ff8989f1ec971f2d5bvboxsync
5a41049c24bcf93e3dc63c76bee23db645867e0cvboxsync /*
62ab017295981c81484e5a5f93ff8b5f85f7defbvboxsync * Check that pafProbeEnabled is all zero.
62ab017295981c81484e5a5f93ff8b5f85f7defbvboxsync */
7708252d252a55417a6a817041e4356797e34255vboxsync i = pVtgHdr->cbProbeEnabled;
7708252d252a55417a6a817041e4356797e34255vboxsync while (i-- > 0)
7708252d252a55417a6a817041e4356797e34255vboxsync if (pVtgHdr->pafProbeEnabled[0])
904810c4c6668233349b025cc58013cb7c11c701vboxsync return VERR_SUPDRV_VTG_BAD_PROBE_ENABLED;
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync /*
3933885bc0c2c93436d858a14564c6179ec72872vboxsync * Probe locations.
3933885bc0c2c93436d858a14564c6179ec72872vboxsync */
3933885bc0c2c93436d858a14564c6179ec72872vboxsync i = pVtgHdr->paProbLocsEnd - pVtgHdr->paProbLocs;
3933885bc0c2c93436d858a14564c6179ec72872vboxsync while (i-- > 0)
3933885bc0c2c93436d858a14564c6179ec72872vboxsync {
a1b4fb3917412d2632d358ff8989f1ec971f2d5bvboxsync if (pVtgHdr->paProbLocs[i].uLine >= _1G)
a1b4fb3917412d2632d358ff8989f1ec971f2d5bvboxsync return VERR_SUPDRV_VTG_BAD_PROBE_LOC;
a1b4fb3917412d2632d358ff8989f1ec971f2d5bvboxsync if (pVtgHdr->paProbLocs[i].fEnabled)
a1b4fb3917412d2632d358ff8989f1ec971f2d5bvboxsync return VERR_SUPDRV_VTG_BAD_PROBE_LOC;
a1b4fb3917412d2632d358ff8989f1ec971f2d5bvboxsync if (pVtgHdr->paProbLocs[i].idProbe != UINT32_MAX)
a1b4fb3917412d2632d358ff8989f1ec971f2d5bvboxsync return VERR_SUPDRV_VTG_BAD_PROBE_LOC;
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsync MY_WITHIN_IMAGE(pVtgHdr->paProbLocs[i].pszFunction, VERR_SUPDRV_VTG_BAD_PROBE_LOC);
a1b4fb3917412d2632d358ff8989f1ec971f2d5bvboxsync offTmp = (uintptr_t)pVtgHdr->paProbLocs[i].pbProbe - (uintptr_t)pVtgHdr->paProbes;
a1b4fb3917412d2632d358ff8989f1ec971f2d5bvboxsync if (offTmp >= pVtgHdr->cbProbes)
a1b4fb3917412d2632d358ff8989f1ec971f2d5bvboxsync return VERR_SUPDRV_VTG_BAD_PROBE_LOC;
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsync if (offTmp / sizeof(VTGDESCPROBE) * sizeof(VTGDESCPROBE) != offTmp)
a1b4fb3917412d2632d358ff8989f1ec971f2d5bvboxsync return VERR_SUPDRV_VTG_BAD_PROBE_LOC;
a1b4fb3917412d2632d358ff8989f1ec971f2d5bvboxsync }
a1b4fb3917412d2632d358ff8989f1ec971f2d5bvboxsync
a1b4fb3917412d2632d358ff8989f1ec971f2d5bvboxsync return VINF_SUCCESS;
a1b4fb3917412d2632d358ff8989f1ec971f2d5bvboxsync#undef MY_VALIDATE_STR
a1b4fb3917412d2632d358ff8989f1ec971f2d5bvboxsync#undef MY_VALIDATE_PTR
a1b4fb3917412d2632d358ff8989f1ec971f2d5bvboxsync#undef MY_WITHIN_IMAGE
a1b4fb3917412d2632d358ff8989f1ec971f2d5bvboxsync}
a1b4fb3917412d2632d358ff8989f1ec971f2d5bvboxsync
a1b4fb3917412d2632d358ff8989f1ec971f2d5bvboxsync
3933885bc0c2c93436d858a14564c6179ec72872vboxsync/**
1147e980f6ab0b7ff1d08c13ad1c03eea30d102dvboxsync * Gets a string from the string table.
1147e980f6ab0b7ff1d08c13ad1c03eea30d102dvboxsync *
1147e980f6ab0b7ff1d08c13ad1c03eea30d102dvboxsync * @returns Pointer to the string.
1147e980f6ab0b7ff1d08c13ad1c03eea30d102dvboxsync * @param pVtgHdr The VTG object header.
1147e980f6ab0b7ff1d08c13ad1c03eea30d102dvboxsync * @param offStrTab The string table offset.
1147e980f6ab0b7ff1d08c13ad1c03eea30d102dvboxsync */
1147e980f6ab0b7ff1d08c13ad1c03eea30d102dvboxsyncstatic const char *supdrvVtgGetString(PVTGOBJHDR pVtgHdr, uint32_t offStrTab)
1147e980f6ab0b7ff1d08c13ad1c03eea30d102dvboxsync{
1147e980f6ab0b7ff1d08c13ad1c03eea30d102dvboxsync Assert(offStrTab < pVtgHdr->cbStrTab);
1147e980f6ab0b7ff1d08c13ad1c03eea30d102dvboxsync return &pVtgHdr->pachStrTab[offStrTab];
1147e980f6ab0b7ff1d08c13ad1c03eea30d102dvboxsync}
1147e980f6ab0b7ff1d08c13ad1c03eea30d102dvboxsync
1147e980f6ab0b7ff1d08c13ad1c03eea30d102dvboxsync
1147e980f6ab0b7ff1d08c13ad1c03eea30d102dvboxsync/**
1147e980f6ab0b7ff1d08c13ad1c03eea30d102dvboxsync * Frees the provider structure and associated resources.
1147e980f6ab0b7ff1d08c13ad1c03eea30d102dvboxsync *
1147e980f6ab0b7ff1d08c13ad1c03eea30d102dvboxsync * @param pProv The provider to free.
1147e980f6ab0b7ff1d08c13ad1c03eea30d102dvboxsync */
48890ac9b4b339e0341e826b5c26ce6408729987vboxsyncstatic void supdrvTracerFreeProvider(PSUPDRVTPPROVIDER pProv)
48890ac9b4b339e0341e826b5c26ce6408729987vboxsync{
48890ac9b4b339e0341e826b5c26ce6408729987vboxsync LOG_TRACER(("Freeing tracepoint provider '%s' / %p\n", pProv->szName, pProv->Core.TracerData.DTrace.idProvider));
48890ac9b4b339e0341e826b5c26ce6408729987vboxsync pProv->fRegistered = false;
48890ac9b4b339e0341e826b5c26ce6408729987vboxsync pProv->fZombie = true;
48890ac9b4b339e0341e826b5c26ce6408729987vboxsync pProv->Core.pDesc = NULL;
48890ac9b4b339e0341e826b5c26ce6408729987vboxsync pProv->Core.pHdr = NULL;
48890ac9b4b339e0341e826b5c26ce6408729987vboxsync RT_ZERO(pProv->Core.TracerData);
48890ac9b4b339e0341e826b5c26ce6408729987vboxsync RTMemFree(pProv);
48890ac9b4b339e0341e826b5c26ce6408729987vboxsync}
48890ac9b4b339e0341e826b5c26ce6408729987vboxsync
48890ac9b4b339e0341e826b5c26ce6408729987vboxsync
48890ac9b4b339e0341e826b5c26ce6408729987vboxsync/**
48890ac9b4b339e0341e826b5c26ce6408729987vboxsync * Deregisters a provider.
48890ac9b4b339e0341e826b5c26ce6408729987vboxsync *
48890ac9b4b339e0341e826b5c26ce6408729987vboxsync * If the provider is still busy, it will be put in the zombie list.
48890ac9b4b339e0341e826b5c26ce6408729987vboxsync *
48890ac9b4b339e0341e826b5c26ce6408729987vboxsync * @param pDevExt The device extension.
48890ac9b4b339e0341e826b5c26ce6408729987vboxsync * @param pProv The provider.
48890ac9b4b339e0341e826b5c26ce6408729987vboxsync *
48890ac9b4b339e0341e826b5c26ce6408729987vboxsync * @remarks The caller owns mtxTracer.
48890ac9b4b339e0341e826b5c26ce6408729987vboxsync */
48890ac9b4b339e0341e826b5c26ce6408729987vboxsyncstatic void supdrvTracerDeregisterVtgObj(PSUPDRVDEVEXT pDevExt, PSUPDRVTPPROVIDER pProv)
48890ac9b4b339e0341e826b5c26ce6408729987vboxsync{
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync int rc;
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync if (!pProv->fRegistered || !pDevExt->pTracerOps)
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync rc = VINF_SUCCESS;
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync else
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync rc = pDevExt->pTracerOps->pfnProviderDeregister(pDevExt->pTracerOps, &pProv->Core);
2823fbb1428e982169f04923472d7c94e7ed8385vboxsync if (RT_SUCCESS(rc))
2823fbb1428e982169f04923472d7c94e7ed8385vboxsync {
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync supdrvTracerFreeProvider(pProv);
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync return;
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync }
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync pProv->fZombie = true;
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync RTListAppend(&pDevExt->TracerProviderZombieList, &pProv->ListEntry);
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync LOG_TRACER(("Invalidated provider '%s' / %p and put it on the zombie list (rc=%Rrc)\n",
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync pProv->szName, pProv->Core.TracerData.DTrace.idProvider, rc));
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync}
508452243fd3328f7b9e0405d39fb9dc004e31b8vboxsync
508452243fd3328f7b9e0405d39fb9dc004e31b8vboxsync
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync/**
89aedeb1d8af54aba6ae46dbbd256281315c1be6vboxsync * Processes the zombie list.
89aedeb1d8af54aba6ae46dbbd256281315c1be6vboxsync *
89aedeb1d8af54aba6ae46dbbd256281315c1be6vboxsync * @param pDevExt The device extension.
89aedeb1d8af54aba6ae46dbbd256281315c1be6vboxsync */
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsyncstatic void supdrvTracerProcessZombies(PSUPDRVDEVEXT pDevExt)
f409459bdd4c15cdb8d7fb6c6d54338cce9ac814vboxsync{
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync PSUPDRVTPPROVIDER pProv, pProvNext;
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync
f4e792b5d6ee04e9d93499b747cce21510c3cdb3vboxsync RTSemFastMutexRequest(pDevExt->mtxTracer);
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync RTListForEachSafe(&pDevExt->TracerProviderZombieList, pProv, pProvNext, SUPDRVTPPROVIDER, ListEntry)
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync {
1dc37bff2fb26897f5892d8330fe2bc0c9859aecvboxsync int rc = pDevExt->pTracerOps->pfnProviderDeregisterZombie(pDevExt->pTracerOps, &pProv->Core);
fb1975a6972d89de9e515bed0248db93f04ec9d8vboxsync if (RT_SUCCESS(rc))
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync {
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync RTListNodeRemove(&pProv->ListEntry);
2823fbb1428e982169f04923472d7c94e7ed8385vboxsync supdrvTracerFreeProvider(pProv);
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync }
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync }
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync RTSemFastMutexRelease(pDevExt->mtxTracer);
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync}
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync
1207f59aa62006952dbb0bf7700decf34d8caeb2vboxsync
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync/**
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync * Unregisters all providers, including zombies, waiting for busy providers to
1147e980f6ab0b7ff1d08c13ad1c03eea30d102dvboxsync * go idle and unregister smoothly.
1147e980f6ab0b7ff1d08c13ad1c03eea30d102dvboxsync *
1147e980f6ab0b7ff1d08c13ad1c03eea30d102dvboxsync * This may block.
1147e980f6ab0b7ff1d08c13ad1c03eea30d102dvboxsync *
1147e980f6ab0b7ff1d08c13ad1c03eea30d102dvboxsync * @param pDevExt The device extension.
1147e980f6ab0b7ff1d08c13ad1c03eea30d102dvboxsync */
1147e980f6ab0b7ff1d08c13ad1c03eea30d102dvboxsyncstatic void supdrvTracerRemoveAllProviders(PSUPDRVDEVEXT pDevExt)
e59069cf1c98c1c2e90a18ec76fbc2e9907fb917vboxsync{
e59069cf1c98c1c2e90a18ec76fbc2e9907fb917vboxsync uint32_t i;
e59069cf1c98c1c2e90a18ec76fbc2e9907fb917vboxsync PSUPDRVTPPROVIDER pProv;
e59069cf1c98c1c2e90a18ec76fbc2e9907fb917vboxsync PSUPDRVTPPROVIDER pProvNext;
e59069cf1c98c1c2e90a18ec76fbc2e9907fb917vboxsync
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync /*
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync * Unregister all probes (there should only be one).
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync */
1207f59aa62006952dbb0bf7700decf34d8caeb2vboxsync RTSemFastMutexRequest(pDevExt->mtxTracer);
1207f59aa62006952dbb0bf7700decf34d8caeb2vboxsync RTListForEachSafe(&pDevExt->TracerProviderList, pProv, pProvNext, SUPDRVTPPROVIDER, ListEntry)
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync {
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync RTListNodeRemove(&pProv->ListEntry);
1207f59aa62006952dbb0bf7700decf34d8caeb2vboxsync supdrvTracerDeregisterVtgObj(pDevExt, pProv);
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync }
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync RTSemFastMutexRelease(pDevExt->mtxTracer);
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync
e48239695d41f806ff02d8a60b97dc20d4822d7avboxsync /*
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync * Try unregister zombies now, sleep on busy ones and tracer opens.
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync */
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync for (i = 0; ; i++)
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync {
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync bool fEmpty;
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync RTSemFastMutexRequest(pDevExt->mtxTracer);
6efcf94383d6e48c764c6518cf1b4069ad34e210vboxsync
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync /* Zombies */
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync RTListForEachSafe(&pDevExt->TracerProviderZombieList, pProv, pProvNext, SUPDRVTPPROVIDER, ListEntry)
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync {
b304856b23107864c9c594a80cebca6006623f31vboxsync int rc;
b304856b23107864c9c594a80cebca6006623f31vboxsync LOG_TRACER(("supdrvTracerRemoveAllProviders: Attemting to unregister '%s' / %p...\n",
b304856b23107864c9c594a80cebca6006623f31vboxsync pProv->szName, pProv->Core.TracerData.DTrace.idProvider));
b304856b23107864c9c594a80cebca6006623f31vboxsync
b304856b23107864c9c594a80cebca6006623f31vboxsync if (pDevExt->pTracerOps)
b304856b23107864c9c594a80cebca6006623f31vboxsync rc = pDevExt->pTracerOps->pfnProviderDeregisterZombie(pDevExt->pTracerOps, &pProv->Core);
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync else
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync rc = VINF_SUCCESS;
6efcf94383d6e48c764c6518cf1b4069ad34e210vboxsync if (!rc)
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync {
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync RTListNodeRemove(&pProv->ListEntry);
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync supdrvTracerFreeProvider(pProv);
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync }
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync else if (!(i & 0xf))
8b36957d815c23b479eb35d93ac76c66392e9402vboxsync SUPR0Printf("supdrvTracerRemoveAllProviders: Waiting on busy provider '%s' / %p (rc=%d)\n",
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync pProv->szName, pProv->Core.TracerData.DTrace.idProvider, rc);
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync else
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync LOG_TRACER(("supdrvTracerRemoveAllProviders: Failed to unregister provider '%s' / %p - rc=%d\n",
8b36957d815c23b479eb35d93ac76c66392e9402vboxsync pProv->szName, pProv->Core.TracerData.DTrace.idProvider, rc));
3a0bc95d0adf57baefd303e94b8f1b7b31a8f080vboxsync }
3a0bc95d0adf57baefd303e94b8f1b7b31a8f080vboxsync
3a0bc95d0adf57baefd303e94b8f1b7b31a8f080vboxsync fEmpty = RTListIsEmpty(&pDevExt->TracerProviderZombieList);
8b36957d815c23b479eb35d93ac76c66392e9402vboxsync
21ddd8aa21b8d7ad25b18ab341ede34c1cb4a125vboxsync /* Tracer opens. */
21ddd8aa21b8d7ad25b18ab341ede34c1cb4a125vboxsync if ( pDevExt->cTracerOpens
21ddd8aa21b8d7ad25b18ab341ede34c1cb4a125vboxsync && pDevExt->pTracerOps)
8b36957d815c23b479eb35d93ac76c66392e9402vboxsync {
21ddd8aa21b8d7ad25b18ab341ede34c1cb4a125vboxsync fEmpty = false;
21ddd8aa21b8d7ad25b18ab341ede34c1cb4a125vboxsync if (!(i & 0xf))
21ddd8aa21b8d7ad25b18ab341ede34c1cb4a125vboxsync SUPR0Printf("supdrvTracerRemoveAllProviders: Waiting on %u opens\n", pDevExt->cTracerOpens);
8b36957d815c23b479eb35d93ac76c66392e9402vboxsync else
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync LOG_TRACER(("supdrvTracerRemoveAllProviders: Waiting on %u opens\n", pDevExt->cTracerOpens));
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync }
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync RTSemFastMutexRelease(pDevExt->mtxTracer);
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync if (fEmpty)
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync break;
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync /* Delay...*/
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync RTThreadSleep(1000);
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync }
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync}
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync
261b44f7fa60a1d4bb4102142d3aa44188908484vboxsync
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync/**
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync * Registers the VTG tracepoint providers of a driver.
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync *
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync * @returns VBox status code.
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync * @param pszName The driver name.
261b44f7fa60a1d4bb4102142d3aa44188908484vboxsync * @param pVtgHdr The VTG object header.
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync * @param pVtgObj The size of the VTG object.
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync * @param pImage The image if applicable.
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync * @param pSession The session if applicable.
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync * @param pszModName The module name.
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync */
f31ac84c1c57e23801423b5bd184fadabe6456f3vboxsyncstatic int supdrvTracerRegisterVtgObj(PSUPDRVDEVEXT pDevExt, PVTGOBJHDR pVtgHdr, size_t cbVtgObj, PSUPDRVLDRIMAGE pImage,
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync PSUPDRVSESSION pSession, const char *pszModName)
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync{
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync int rc;
8fdb854581fe3cb394d84835dc09b02e6e18d4edvboxsync uintptr_t i;
8fdb854581fe3cb394d84835dc09b02e6e18d4edvboxsync PSUPDRVTPPROVIDER pProv;
8fdb854581fe3cb394d84835dc09b02e6e18d4edvboxsync
8fdb854581fe3cb394d84835dc09b02e6e18d4edvboxsync /*
8fdb854581fe3cb394d84835dc09b02e6e18d4edvboxsync * Validate input.
8fdb854581fe3cb394d84835dc09b02e6e18d4edvboxsync */
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync AssertPtrReturn(pDevExt, VERR_INVALID_POINTER);
36929067a9d3cba77fd78f1e8fa042ed3a8ae2d6vboxsync AssertPtrReturn(pVtgHdr, VERR_INVALID_POINTER);
f31ac84c1c57e23801423b5bd184fadabe6456f3vboxsync AssertPtrNullReturn(pImage, VERR_INVALID_POINTER);
36929067a9d3cba77fd78f1e8fa042ed3a8ae2d6vboxsync AssertPtrNullReturn(pSession, VERR_INVALID_POINTER);
36929067a9d3cba77fd78f1e8fa042ed3a8ae2d6vboxsync AssertPtrReturn(pszModName, VERR_INVALID_POINTER);
36929067a9d3cba77fd78f1e8fa042ed3a8ae2d6vboxsync
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync if (pImage)
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync rc = supdrvVtgValidate(pVtgHdr, cbVtgObj, (const uint8_t *)pImage->pvImage, pImage->cbImageBits);
261b44f7fa60a1d4bb4102142d3aa44188908484vboxsync else
ab2292e9c32bd271ec91123ef38699a0284b72cbvboxsync rc = supdrvVtgValidate(pVtgHdr, cbVtgObj, NULL, 0);
ab2292e9c32bd271ec91123ef38699a0284b72cbvboxsync if (RT_FAILURE(rc))
ab2292e9c32bd271ec91123ef38699a0284b72cbvboxsync return rc;
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync
ab2292e9c32bd271ec91123ef38699a0284b72cbvboxsync rc = RTSemFastMutexRequest(pDevExt->mtxTracer);
261b44f7fa60a1d4bb4102142d3aa44188908484vboxsync if (RT_FAILURE(rc))
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync return rc;
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync RTListForEach(&pDevExt->TracerProviderList, pProv, SUPDRVTPPROVIDER, ListEntry)
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync {
db0ecde8f28fdb4525bc6d94056166c70b02ebb8vboxsync if (pProv->Core.pHdr == pVtgHdr)
121568d0a1e932e6f6acd49376827a0e593815favboxsync {
121568d0a1e932e6f6acd49376827a0e593815favboxsync rc = VERR_SUPDRV_VTG_ALREADY_REGISTERED;
121568d0a1e932e6f6acd49376827a0e593815favboxsync break;
121568d0a1e932e6f6acd49376827a0e593815favboxsync }
121568d0a1e932e6f6acd49376827a0e593815favboxsync if ( pProv->pSession == pSession
121568d0a1e932e6f6acd49376827a0e593815favboxsync && pProv->pImage == pImage)
121568d0a1e932e6f6acd49376827a0e593815favboxsync {
121568d0a1e932e6f6acd49376827a0e593815favboxsync rc = VERR_SUPDRV_VTG_ONLY_ONCE_PER_SESSION;
121568d0a1e932e6f6acd49376827a0e593815favboxsync break;
121568d0a1e932e6f6acd49376827a0e593815favboxsync }
121568d0a1e932e6f6acd49376827a0e593815favboxsync }
121568d0a1e932e6f6acd49376827a0e593815favboxsync RTSemFastMutexRelease(pDevExt->mtxTracer);
121568d0a1e932e6f6acd49376827a0e593815favboxsync if (RT_FAILURE(rc))
f31ac84c1c57e23801423b5bd184fadabe6456f3vboxsync return rc;
121568d0a1e932e6f6acd49376827a0e593815favboxsync
121568d0a1e932e6f6acd49376827a0e593815favboxsync /*
121568d0a1e932e6f6acd49376827a0e593815favboxsync * Register the providers.
db0ecde8f28fdb4525bc6d94056166c70b02ebb8vboxsync */
db0ecde8f28fdb4525bc6d94056166c70b02ebb8vboxsync i = pVtgHdr->cbProviders / sizeof(VTGDESCPROVIDER);
f31ac84c1c57e23801423b5bd184fadabe6456f3vboxsync while (i-- > 0)
db0ecde8f28fdb4525bc6d94056166c70b02ebb8vboxsync {
db0ecde8f28fdb4525bc6d94056166c70b02ebb8vboxsync PVTGDESCPROVIDER pDesc = &pVtgHdr->paProviders[i];
db0ecde8f28fdb4525bc6d94056166c70b02ebb8vboxsync const char *pszName = supdrvVtgGetString(pVtgHdr, pDesc->offName);
db0ecde8f28fdb4525bc6d94056166c70b02ebb8vboxsync size_t const cchName = strlen(pszName);
db0ecde8f28fdb4525bc6d94056166c70b02ebb8vboxsync pProv = (PSUPDRVTPPROVIDER)RTMemAllocZ(RT_OFFSETOF(SUPDRVTPPROVIDER, szName[cchName + 1]));
f31ac84c1c57e23801423b5bd184fadabe6456f3vboxsync if (pProv)
db0ecde8f28fdb4525bc6d94056166c70b02ebb8vboxsync {
db0ecde8f28fdb4525bc6d94056166c70b02ebb8vboxsync pProv->Core.pDesc = pDesc;
db0ecde8f28fdb4525bc6d94056166c70b02ebb8vboxsync pProv->Core.pHdr = pVtgHdr;
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync pProv->Core.pszName = &pProv->szName[0];
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync pProv->Core.pszModName = pszModName;
261b44f7fa60a1d4bb4102142d3aa44188908484vboxsync pProv->pImage = pImage;
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync pProv->pSession = pSession;
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync pProv->fZombie = false;
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync pProv->fRegistered = true;
c33fc49611f2444dade533488bf431e29eb88bcdvboxsync memcpy(&pProv->szName[0], pszName, cchName + 1);
c33fc49611f2444dade533488bf431e29eb88bcdvboxsync
c33fc49611f2444dade533488bf431e29eb88bcdvboxsync rc = RTSemFastMutexRequest(pDevExt->mtxTracer);
c33fc49611f2444dade533488bf431e29eb88bcdvboxsync if (RT_SUCCESS(rc))
c33fc49611f2444dade533488bf431e29eb88bcdvboxsync {
c33fc49611f2444dade533488bf431e29eb88bcdvboxsync if ( pDevExt->pTracerOps
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync && !pDevExt->fTracerUnloading)
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync rc = pDevExt->pTracerOps->pfnProviderRegister(pDevExt->pTracerOps, &pProv->Core);
261b44f7fa60a1d4bb4102142d3aa44188908484vboxsync else
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync {
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync pProv->fRegistered = false;
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync rc = VINF_SUCCESS;
1bf151411167b02ebdc6d6a18de8b97030341e1fvboxsync }
1bf151411167b02ebdc6d6a18de8b97030341e1fvboxsync if (RT_SUCCESS(rc))
1bf151411167b02ebdc6d6a18de8b97030341e1fvboxsync {
1bf151411167b02ebdc6d6a18de8b97030341e1fvboxsync RTListAppend(&pDevExt->TracerProviderList, &pProv->ListEntry);
1bf151411167b02ebdc6d6a18de8b97030341e1fvboxsync RTSemFastMutexRelease(pDevExt->mtxTracer);
8fdb854581fe3cb394d84835dc09b02e6e18d4edvboxsync LOG_TRACER(("Registered tracepoint provider '%s' in '%s' -> %p\n",
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync pProv->szName, pszModName, pProv->Core.TracerData.DTrace.idProvider));
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync }
6efcf94383d6e48c764c6518cf1b4069ad34e210vboxsync else
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync {
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync RTSemFastMutexRelease(pDevExt->mtxTracer);
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync LOG_TRACER(("Failed to register tracepoint provider '%s' in '%s' -> %Rrc\n",
e2760cdc84c692bc46cfaf5018d313db2f122acavboxsync pProv->szName, pszModName, rc));
e2760cdc84c692bc46cfaf5018d313db2f122acavboxsync RTMemFree(pProv);
e2760cdc84c692bc46cfaf5018d313db2f122acavboxsync }
e2760cdc84c692bc46cfaf5018d313db2f122acavboxsync }
e2760cdc84c692bc46cfaf5018d313db2f122acavboxsync }
e2760cdc84c692bc46cfaf5018d313db2f122acavboxsync else
6e12ccc60ac657fb87e27b7a2b26e0a63bebe024vboxsync rc = VERR_NO_MEMORY;
6e12ccc60ac657fb87e27b7a2b26e0a63bebe024vboxsync
6e12ccc60ac657fb87e27b7a2b26e0a63bebe024vboxsync if (RT_FAILURE(rc))
6e12ccc60ac657fb87e27b7a2b26e0a63bebe024vboxsync {
6e12ccc60ac657fb87e27b7a2b26e0a63bebe024vboxsync PSUPDRVTPPROVIDER pProvNext;
6e12ccc60ac657fb87e27b7a2b26e0a63bebe024vboxsync supdrvTracerFreeProvider(pProv);
6e12ccc60ac657fb87e27b7a2b26e0a63bebe024vboxsync
6e12ccc60ac657fb87e27b7a2b26e0a63bebe024vboxsync RTSemFastMutexRequest(pDevExt->mtxTracer);
6e12ccc60ac657fb87e27b7a2b26e0a63bebe024vboxsync RTListForEachReverseSafe(&pDevExt->TracerProviderList, pProv, pProvNext, SUPDRVTPPROVIDER, ListEntry)
6e12ccc60ac657fb87e27b7a2b26e0a63bebe024vboxsync {
6e12ccc60ac657fb87e27b7a2b26e0a63bebe024vboxsync if (pProv->Core.pHdr == pVtgHdr)
6e12ccc60ac657fb87e27b7a2b26e0a63bebe024vboxsync {
6e12ccc60ac657fb87e27b7a2b26e0a63bebe024vboxsync RTListNodeRemove(&pProv->ListEntry);
6e12ccc60ac657fb87e27b7a2b26e0a63bebe024vboxsync supdrvTracerDeregisterVtgObj(pDevExt, pProv);
6e12ccc60ac657fb87e27b7a2b26e0a63bebe024vboxsync }
6e12ccc60ac657fb87e27b7a2b26e0a63bebe024vboxsync }
6e12ccc60ac657fb87e27b7a2b26e0a63bebe024vboxsync RTSemFastMutexRelease(pDevExt->mtxTracer);
6e12ccc60ac657fb87e27b7a2b26e0a63bebe024vboxsync return rc;
657b2c9f6d33f08001e5fa6f6e0572dcf0391013vboxsync }
657b2c9f6d33f08001e5fa6f6e0572dcf0391013vboxsync }
657b2c9f6d33f08001e5fa6f6e0572dcf0391013vboxsync
d6f9950e2cf4ba7fd217c083400d9812ff745374vboxsync return VINF_SUCCESS;
657b2c9f6d33f08001e5fa6f6e0572dcf0391013vboxsync}
657b2c9f6d33f08001e5fa6f6e0572dcf0391013vboxsync
8b36957d815c23b479eb35d93ac76c66392e9402vboxsync
8b36957d815c23b479eb35d93ac76c66392e9402vboxsync/**
8b36957d815c23b479eb35d93ac76c66392e9402vboxsync * Registers the VTG tracepoint providers of a driver.
8b36957d815c23b479eb35d93ac76c66392e9402vboxsync *
8b36957d815c23b479eb35d93ac76c66392e9402vboxsync * @returns VBox status code.
8b36957d815c23b479eb35d93ac76c66392e9402vboxsync * @param pSession The support driver session handle.
8b36957d815c23b479eb35d93ac76c66392e9402vboxsync * @param pVtgHdr The VTG header.
8b36957d815c23b479eb35d93ac76c66392e9402vboxsync * @param pszName The driver name.
8b36957d815c23b479eb35d93ac76c66392e9402vboxsync */
8b36957d815c23b479eb35d93ac76c66392e9402vboxsyncSUPR0DECL(int) SUPR0TracerRegisterDrv(PSUPDRVSESSION pSession, PVTGOBJHDR pVtgHdr, const char *pszName)
8b36957d815c23b479eb35d93ac76c66392e9402vboxsync{
8b36957d815c23b479eb35d93ac76c66392e9402vboxsync int rc;
8b36957d815c23b479eb35d93ac76c66392e9402vboxsync
8b36957d815c23b479eb35d93ac76c66392e9402vboxsync AssertReturn(SUP_IS_SESSION_VALID(pSession), VERR_INVALID_PARAMETER);
8b36957d815c23b479eb35d93ac76c66392e9402vboxsync AssertPtrReturn(pszName, VERR_INVALID_POINTER);
8b36957d815c23b479eb35d93ac76c66392e9402vboxsync AssertPtrReturn(pVtgHdr, VERR_INVALID_POINTER);
8b36957d815c23b479eb35d93ac76c66392e9402vboxsync AssertReturn(pSession->R0Process == NIL_RTR0PROCESS, VERR_INVALID_PARAMETER);
8b36957d815c23b479eb35d93ac76c66392e9402vboxsync LOG_TRACER(("SUPR0TracerRegisterDrv: pSession=%p pVtgHdr=%p pszName=%s\n", pSession, pVtgHdr, pszName));
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync
49e54e2ffe0c10864d06e9d1ebe24a8eb1327a6bvboxsync rc = supdrvTracerRegisterVtgObj(pSession->pDevExt, pVtgHdr, _1M, NULL /*pImage*/, pSession, pszName);
6efcf94383d6e48c764c6518cf1b4069ad34e210vboxsync
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync /*
49e54e2ffe0c10864d06e9d1ebe24a8eb1327a6bvboxsync * Try unregister zombies while we have a chance.
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync */
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync supdrvTracerProcessZombies(pSession->pDevExt);
49e54e2ffe0c10864d06e9d1ebe24a8eb1327a6bvboxsync
261b44f7fa60a1d4bb4102142d3aa44188908484vboxsync return rc;
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync}
49e54e2ffe0c10864d06e9d1ebe24a8eb1327a6bvboxsync
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync/**
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync * Deregister the VTG tracepoint providers of a driver.
49e54e2ffe0c10864d06e9d1ebe24a8eb1327a6bvboxsync *
261b44f7fa60a1d4bb4102142d3aa44188908484vboxsync * @param pSession The support driver session handle.
49e54e2ffe0c10864d06e9d1ebe24a8eb1327a6bvboxsync * @param pVtgHdr The VTG header.
49e54e2ffe0c10864d06e9d1ebe24a8eb1327a6bvboxsync */
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsyncSUPR0DECL(void) SUPR0TracerDeregisterDrv(PSUPDRVSESSION pSession)
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync{
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync PSUPDRVTPPROVIDER pProv, pProvNext;
91f8453d16b48876deddaba298c211071d0ca3a5vboxsync PSUPDRVDEVEXT pDevExt;
261b44f7fa60a1d4bb4102142d3aa44188908484vboxsync AssertReturnVoid(SUP_IS_SESSION_VALID(pSession));
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync AssertReturnVoid(pSession->R0Process == NIL_RTR0PROCESS);
91f8453d16b48876deddaba298c211071d0ca3a5vboxsync LOG_TRACER(("SUPR0TracerDeregisterDrv: pSession=%p\n", pSession));
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync pDevExt = pSession->pDevExt;
91f8453d16b48876deddaba298c211071d0ca3a5vboxsync
261b44f7fa60a1d4bb4102142d3aa44188908484vboxsync /*
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync * Search for providers belonging to this driver session.
91f8453d16b48876deddaba298c211071d0ca3a5vboxsync */
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync RTSemFastMutexRequest(pDevExt->mtxTracer);
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync RTListForEachSafe(&pDevExt->TracerProviderList, pProv, pProvNext, SUPDRVTPPROVIDER, ListEntry)
91f8453d16b48876deddaba298c211071d0ca3a5vboxsync {
fc5f879e9508f333e20b37c63db9189a33059308vboxsync if (pProv->pSession == pSession)
91f8453d16b48876deddaba298c211071d0ca3a5vboxsync {
91f8453d16b48876deddaba298c211071d0ca3a5vboxsync RTListNodeRemove(&pProv->ListEntry);
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync supdrvTracerDeregisterVtgObj(pDevExt, pProv);
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync }
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync }
1207f59aa62006952dbb0bf7700decf34d8caeb2vboxsync RTSemFastMutexRelease(pDevExt->mtxTracer);
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync /*
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync * Try unregister zombies while we have a chance.
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync */
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync supdrvTracerProcessZombies(pDevExt);
8b36957d815c23b479eb35d93ac76c66392e9402vboxsync}
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync/**
8b36957d815c23b479eb35d93ac76c66392e9402vboxsync * Registers the VTG tracepoint providers of a module loaded by
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync * the support driver.
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync *
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync * This should be called from the ModuleInit code.
8b36957d815c23b479eb35d93ac76c66392e9402vboxsync *
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync * @returns VBox status code.
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync * @param hMod The module handle.
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync * @param pVtgHdr The VTG header.
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync */
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsyncSUPR0DECL(int) SUPR0TracerRegisterModule(void *hMod, PVTGOBJHDR pVtgHdr)
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync{
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync PSUPDRVLDRIMAGE pImage = (PSUPDRVLDRIMAGE)hMod;
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync PSUPDRVDEVEXT pDevExt;
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync uintptr_t cbVtgObj;
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync int rc;
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync LOG_TRACER(("SUPR0TracerRegisterModule: %p\n", pVtgHdr));
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync
1c6ec9a3a329da6f61978a372e509cd233f0d9f9vboxsync /*
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync * Validate input and context.
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync */
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync AssertPtrReturn(pImage, VERR_INVALID_HANDLE);
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync AssertPtrReturn(pVtgHdr, VERR_INVALID_POINTER);
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync
261b44f7fa60a1d4bb4102142d3aa44188908484vboxsync AssertPtrReturn(pImage, VERR_INVALID_POINTER);
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync pDevExt = pImage->pDevExt;
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync AssertPtrReturn(pDevExt, VERR_INVALID_POINTER);
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync AssertReturn(pDevExt->pLdrInitImage == pImage, VERR_WRONG_ORDER);
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync AssertReturn(pDevExt->hLdrInitThread == RTThreadNativeSelf(), VERR_WRONG_ORDER);
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync
8b36957d815c23b479eb35d93ac76c66392e9402vboxsync /*
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync * Calculate the max VTG object size and hand it over to the common code.
1dc37bff2fb26897f5892d8330fe2bc0c9859aecvboxsync */
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync cbVtgObj = (uintptr_t)pVtgHdr - (uintptr_t)pImage->pvImage;
8b36957d815c23b479eb35d93ac76c66392e9402vboxsync AssertMsgReturn(cbVtgObj /*off*/ < pImage->cbImageBits,
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync ("pVtgHdr=%p offVtgObj=%p cbImageBits=%p\n", pVtgHdr, cbVtgObj, pImage->cbImageBits),
1dc37bff2fb26897f5892d8330fe2bc0c9859aecvboxsync VERR_INVALID_PARAMETER);
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync cbVtgObj = pImage->cbImageBits - cbVtgObj;
8b36957d815c23b479eb35d93ac76c66392e9402vboxsync
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync rc = supdrvTracerRegisterVtgObj(pDevExt, pVtgHdr, cbVtgObj, pImage, NULL, pImage->szName);
1dc37bff2fb26897f5892d8330fe2bc0c9859aecvboxsync LOG_TRACER(("SUPR0TracerRegisterModule: rc=%d\n", rc));
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync
8b36957d815c23b479eb35d93ac76c66392e9402vboxsync /*
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync * Try unregister zombies while we have a chance.
1dc37bff2fb26897f5892d8330fe2bc0c9859aecvboxsync */
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync supdrvTracerProcessZombies(pDevExt);
8b36957d815c23b479eb35d93ac76c66392e9402vboxsync
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync return rc;
1dc37bff2fb26897f5892d8330fe2bc0c9859aecvboxsync}
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync
2823fbb1428e982169f04923472d7c94e7ed8385vboxsync/**
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync * Registers the tracer implementation.
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync *
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync * This should be called from the ModuleInit code or from a ring-0 session.
2a5e5a032e6f23f8937718e4ee4d6979188bdd19vboxsync *
2a5e5a032e6f23f8937718e4ee4d6979188bdd19vboxsync * @returns VBox status code.
4a0e2f51aaf27c0bca61ff0f1adb91106264f0dbvboxsync * @param hMod The module handle.
4a0e2f51aaf27c0bca61ff0f1adb91106264f0dbvboxsync * @param pSession Ring-0 session handle.
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync * @param pReg Pointer to the tracer registration structure.
7922c4cd397713a387c9e854e74c31a0d5065365vboxsync * @param ppHlp Where to return the tracer helper method table.
4a0e2f51aaf27c0bca61ff0f1adb91106264f0dbvboxsync */
4a0e2f51aaf27c0bca61ff0f1adb91106264f0dbvboxsyncSUPR0DECL(int) SUPR0TracerRegisterImpl(void *hMod, PSUPDRVSESSION pSession, PCSUPDRVTRACERREG pReg, PCSUPDRVTRACERHLP *ppHlp)
4a0e2f51aaf27c0bca61ff0f1adb91106264f0dbvboxsync{
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync PSUPDRVLDRIMAGE pImage = (PSUPDRVLDRIMAGE)hMod;
4a0e2f51aaf27c0bca61ff0f1adb91106264f0dbvboxsync PSUPDRVDEVEXT pDevExt;
4a0e2f51aaf27c0bca61ff0f1adb91106264f0dbvboxsync PSUPDRVTPPROVIDER pProv;
4a0e2f51aaf27c0bca61ff0f1adb91106264f0dbvboxsync int rc;
4a0e2f51aaf27c0bca61ff0f1adb91106264f0dbvboxsync
4a0e2f51aaf27c0bca61ff0f1adb91106264f0dbvboxsync /*
4a0e2f51aaf27c0bca61ff0f1adb91106264f0dbvboxsync * Validate input and context.
4a0e2f51aaf27c0bca61ff0f1adb91106264f0dbvboxsync */
4a0e2f51aaf27c0bca61ff0f1adb91106264f0dbvboxsync AssertPtrReturn(ppHlp, VERR_INVALID_POINTER);
4a0e2f51aaf27c0bca61ff0f1adb91106264f0dbvboxsync *ppHlp = NULL;
4a0e2f51aaf27c0bca61ff0f1adb91106264f0dbvboxsync AssertPtrReturn(pReg, VERR_INVALID_HANDLE);
4a0e2f51aaf27c0bca61ff0f1adb91106264f0dbvboxsync
4a0e2f51aaf27c0bca61ff0f1adb91106264f0dbvboxsync if (pImage)
4a0e2f51aaf27c0bca61ff0f1adb91106264f0dbvboxsync {
4a0e2f51aaf27c0bca61ff0f1adb91106264f0dbvboxsync AssertPtrReturn(pImage, VERR_INVALID_POINTER);
4a0e2f51aaf27c0bca61ff0f1adb91106264f0dbvboxsync AssertReturn(pSession == NULL, VERR_INVALID_PARAMETER);
4a0e2f51aaf27c0bca61ff0f1adb91106264f0dbvboxsync pDevExt = pImage->pDevExt;
4a0e2f51aaf27c0bca61ff0f1adb91106264f0dbvboxsync AssertPtrReturn(pDevExt, VERR_INVALID_POINTER);
4a0e2f51aaf27c0bca61ff0f1adb91106264f0dbvboxsync AssertReturn(pDevExt->pLdrInitImage == pImage, VERR_WRONG_ORDER);
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync AssertReturn(pDevExt->hLdrInitThread == RTThreadNativeSelf(), VERR_WRONG_ORDER);
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync }
8b36957d815c23b479eb35d93ac76c66392e9402vboxsync else
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync {
1207f59aa62006952dbb0bf7700decf34d8caeb2vboxsync AssertReturn(SUP_IS_SESSION_VALID(pSession), VERR_INVALID_PARAMETER);
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync AssertReturn(pSession->R0Process == NIL_RTR0PROCESS, VERR_INVALID_PARAMETER);
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync pDevExt = pSession->pDevExt;
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync AssertPtrReturn(pDevExt, VERR_INVALID_POINTER);
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync }
a9f530691071e3496b072915b0c5ceabd4e05ea5vboxsync
a9f530691071e3496b072915b0c5ceabd4e05ea5vboxsync AssertReturn(pReg->u32Magic == SUPDRVTRACERREG_MAGIC, VERR_INVALID_MAGIC);
a9f530691071e3496b072915b0c5ceabd4e05ea5vboxsync AssertReturn(pReg->u32Version == SUPDRVTRACERREG_VERSION, VERR_VERSION_MISMATCH);
a9f530691071e3496b072915b0c5ceabd4e05ea5vboxsync AssertReturn(pReg->uEndMagic == SUPDRVTRACERREG_MAGIC, VERR_VERSION_MISMATCH);
67e7d53d62514401efcd0e7a34f5faf772a3fe04vboxsync AssertPtrReturn(pReg->pfnProbeFireKernel, VERR_INVALID_POINTER);
b7a8ce033b32a429def2feb142bc1bdd1b5dffa2vboxsync AssertPtrReturn(pReg->pfnProbeFireUser, VERR_INVALID_POINTER);
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync AssertPtrReturn(pReg->pfnTracerOpen, VERR_INVALID_POINTER);
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync AssertPtrReturn(pReg->pfnTracerIoCtl, VERR_INVALID_POINTER);
1207f59aa62006952dbb0bf7700decf34d8caeb2vboxsync AssertPtrReturn(pReg->pfnTracerClose, VERR_INVALID_POINTER);
1207f59aa62006952dbb0bf7700decf34d8caeb2vboxsync AssertPtrReturn(pReg->pfnProviderRegister, VERR_INVALID_POINTER);
1207f59aa62006952dbb0bf7700decf34d8caeb2vboxsync AssertPtrReturn(pReg->pfnProviderDeregister, VERR_INVALID_POINTER);
1207f59aa62006952dbb0bf7700decf34d8caeb2vboxsync AssertPtrReturn(pReg->pfnProviderDeregisterZombie, VERR_INVALID_POINTER);
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync /*
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync * Do the job.
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync */
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync rc = RTSemFastMutexRequest(pDevExt->mtxTracer);
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync if (RT_SUCCESS(rc))
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync {
2a5e5a032e6f23f8937718e4ee4d6979188bdd19vboxsync if (!pDevExt->pTracerOps)
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync {
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync LOG_TRACER(("SUPR0TracerRegisterImpl: pReg=%p\n", pReg));
1207f59aa62006952dbb0bf7700decf34d8caeb2vboxsync pDevExt->pTracerOps = pReg;
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync pDevExt->pTracerSession = pSession;
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync pDevExt->pTracerImage = pImage;
2823fbb1428e982169f04923472d7c94e7ed8385vboxsync
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync g_pfnSupdrvProbeFireKernel = (PFNRT)pDevExt->pTracerOps->pfnProbeFireKernel;
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync *ppHlp = &pDevExt->TracerHlp;
2823fbb1428e982169f04923472d7c94e7ed8385vboxsync rc = VINF_SUCCESS;
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync /*
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync * Iterate the already loaded modules and register their providers.
2823fbb1428e982169f04923472d7c94e7ed8385vboxsync */
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync RTListForEach(&pDevExt->TracerProviderList, pProv, SUPDRVTPPROVIDER, ListEntry)
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync {
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync Assert(!pProv->fRegistered);
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync pProv->fRegistered = true;
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync int rc2 = pDevExt->pTracerOps->pfnProviderRegister(pDevExt->pTracerOps, &pProv->Core);
2823fbb1428e982169f04923472d7c94e7ed8385vboxsync if (RT_FAILURE(rc2))
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync {
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync pProv->fRegistered = false;
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync SUPR0Printf("SUPR0TracerRegisterImpl: Failed to register provider %s::%s - rc=%d\n",
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync pProv->Core.pszModName, pProv->szName, rc2);
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync }
2a5e5a032e6f23f8937718e4ee4d6979188bdd19vboxsync }
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync }
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync else
1207f59aa62006952dbb0bf7700decf34d8caeb2vboxsync rc = VERR_SUPDRV_TRACER_ALREADY_REGISTERED;
1207f59aa62006952dbb0bf7700decf34d8caeb2vboxsync RTSemFastMutexRelease(pDevExt->mtxTracer);
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync }
2823fbb1428e982169f04923472d7c94e7ed8385vboxsync
2823fbb1428e982169f04923472d7c94e7ed8385vboxsync return rc;
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync}
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync
2a5e5a032e6f23f8937718e4ee4d6979188bdd19vboxsync
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync/**
8b36957d815c23b479eb35d93ac76c66392e9402vboxsync * Common tracer implementation deregistration code.
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync *
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync * The caller sets fTracerUnloading prior to calling this function.
1207f59aa62006952dbb0bf7700decf34d8caeb2vboxsync *
1207f59aa62006952dbb0bf7700decf34d8caeb2vboxsync * @param pDevExt The device extension structure.
1207f59aa62006952dbb0bf7700decf34d8caeb2vboxsync */
1dc37bff2fb26897f5892d8330fe2bc0c9859aecvboxsyncstatic void supdrvTracerCommonDeregisterImpl(PSUPDRVDEVEXT pDevExt)
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync{
8b36957d815c23b479eb35d93ac76c66392e9402vboxsync uint32_t i;
1207f59aa62006952dbb0bf7700decf34d8caeb2vboxsync PSUPDRVTPPROVIDER pProv;
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync PSUPDRVTPPROVIDER pProvNext;
2823fbb1428e982169f04923472d7c94e7ed8385vboxsync
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync RTSemFastMutexRequest(pDevExt->mtxTracer);
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync /*
2a5e5a032e6f23f8937718e4ee4d6979188bdd19vboxsync * Reinstall the stub probe-fire function.
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync */
8b36957d815c23b479eb35d93ac76c66392e9402vboxsync g_pfnSupdrvProbeFireKernel = supdrvTracerProbeFireStub;
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync
1207f59aa62006952dbb0bf7700decf34d8caeb2vboxsync /*
1207f59aa62006952dbb0bf7700decf34d8caeb2vboxsync * Disassociate the tracer implementation from all providers.
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync * We will have to wait on busy providers.
1207f59aa62006952dbb0bf7700decf34d8caeb2vboxsync */
1207f59aa62006952dbb0bf7700decf34d8caeb2vboxsync for (i = 0; ; i++)
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync {
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync uint32_t cZombies = 0;
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync /* Live providers. */
a9f530691071e3496b072915b0c5ceabd4e05ea5vboxsync RTListForEachSafe(&pDevExt->TracerProviderList, pProv, pProvNext, SUPDRVTPPROVIDER, ListEntry)
a9f530691071e3496b072915b0c5ceabd4e05ea5vboxsync {
a9f530691071e3496b072915b0c5ceabd4e05ea5vboxsync int rc;
a9f530691071e3496b072915b0c5ceabd4e05ea5vboxsync LOG_TRACER(("supdrvTracerCommonDeregisterImpl: Attemting to unregister '%s' / %p...\n",
67e7d53d62514401efcd0e7a34f5faf772a3fe04vboxsync pProv->szName, pProv->Core.TracerData.DTrace.idProvider));
b7a8ce033b32a429def2feb142bc1bdd1b5dffa2vboxsync
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync if (!pProv->fRegistered)
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync continue;
1207f59aa62006952dbb0bf7700decf34d8caeb2vboxsync if (!pProv->fZombie)
1207f59aa62006952dbb0bf7700decf34d8caeb2vboxsync {
1207f59aa62006952dbb0bf7700decf34d8caeb2vboxsync rc = pDevExt->pTracerOps->pfnProviderDeregister(pDevExt->pTracerOps, &pProv->Core);
1207f59aa62006952dbb0bf7700decf34d8caeb2vboxsync if (RT_FAILURE(rc))
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync pProv->fZombie = true;
1dc37bff2fb26897f5892d8330fe2bc0c9859aecvboxsync }
1207f59aa62006952dbb0bf7700decf34d8caeb2vboxsync else
1207f59aa62006952dbb0bf7700decf34d8caeb2vboxsync rc = pDevExt->pTracerOps->pfnProviderDeregisterZombie(pDevExt->pTracerOps, &pProv->Core);
1207f59aa62006952dbb0bf7700decf34d8caeb2vboxsync if (RT_SUCCESS(rc))
1207f59aa62006952dbb0bf7700decf34d8caeb2vboxsync pProv->fZombie = pProv->fRegistered = false;
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync else
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync {
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync cZombies++;
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync if (!(i & 0xf))
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync SUPR0Printf("supdrvTracerCommonDeregisterImpl: Waiting on busy provider '%s' / %p (rc=%d)\n",
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync pProv->szName, pProv->Core.TracerData.DTrace.idProvider, rc);
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync else
2a5e5a032e6f23f8937718e4ee4d6979188bdd19vboxsync LOG_TRACER(("supdrvTracerCommonDeregisterImpl: Failed to unregister provider '%s' / %p - rc=%d\n",
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync pProv->szName, pProv->Core.TracerData.DTrace.idProvider, rc));
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync }
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync }
2823fbb1428e982169f04923472d7c94e7ed8385vboxsync
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync /* Zombies providers. */
1207f59aa62006952dbb0bf7700decf34d8caeb2vboxsync RTListForEachSafe(&pDevExt->TracerProviderZombieList, pProv, pProvNext, SUPDRVTPPROVIDER, ListEntry)
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync {
1207f59aa62006952dbb0bf7700decf34d8caeb2vboxsync int rc;
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync LOG_TRACER(("supdrvTracerCommonDeregisterImpl: Attemting to unregister '%s' / %p (zombie)...\n",
1dc37bff2fb26897f5892d8330fe2bc0c9859aecvboxsync pProv->szName, pProv->Core.TracerData.DTrace.idProvider));
1207f59aa62006952dbb0bf7700decf34d8caeb2vboxsync
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync rc = pDevExt->pTracerOps->pfnProviderDeregisterZombie(pDevExt->pTracerOps, &pProv->Core);
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync if (RT_SUCCESS(rc))
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync {
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync RTListNodeRemove(&pProv->ListEntry);
1dc37bff2fb26897f5892d8330fe2bc0c9859aecvboxsync supdrvTracerFreeProvider(pProv);
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync }
2823fbb1428e982169f04923472d7c94e7ed8385vboxsync else
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync {
1207f59aa62006952dbb0bf7700decf34d8caeb2vboxsync cZombies++;
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync if (!(i & 0xf))
1207f59aa62006952dbb0bf7700decf34d8caeb2vboxsync SUPR0Printf("supdrvTracerCommonDeregisterImpl: Waiting on busy provider '%s' / %p (rc=%d)\n",
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync pProv->szName, pProv->Core.TracerData.DTrace.idProvider, rc);
1dc37bff2fb26897f5892d8330fe2bc0c9859aecvboxsync else
1207f59aa62006952dbb0bf7700decf34d8caeb2vboxsync LOG_TRACER(("supdrvTracerCommonDeregisterImpl: Failed to unregister provider '%s' / %p - rc=%d\n",
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync pProv->szName, pProv->Core.TracerData.DTrace.idProvider, rc));
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync }
e214bb78026c1d64078b34ca9504d3f5abbc52efvboxsync }
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync
1dc37bff2fb26897f5892d8330fe2bc0c9859aecvboxsync /* Tracer opens. */
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync if (pDevExt->cTracerOpens)
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync {
2823fbb1428e982169f04923472d7c94e7ed8385vboxsync cZombies++;
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync if (!(i & 0xf))
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync SUPR0Printf("supdrvTracerCommonDeregisterImpl: Waiting on %u opens\n", pDevExt->cTracerOpens);
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync else
2a5e5a032e6f23f8937718e4ee4d6979188bdd19vboxsync LOG_TRACER(("supdrvTracerCommonDeregisterImpl: Waiting on %u opens\n", pDevExt->cTracerOpens));
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync }
8b36957d815c23b479eb35d93ac76c66392e9402vboxsync
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync /* Done? */
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync if (cZombies == 0)
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync break;
1207f59aa62006952dbb0bf7700decf34d8caeb2vboxsync
1207f59aa62006952dbb0bf7700decf34d8caeb2vboxsync /* Delay...*/
1207f59aa62006952dbb0bf7700decf34d8caeb2vboxsync RTSemFastMutexRelease(pDevExt->mtxTracer);
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync RTThreadSleep(1000);
1dc37bff2fb26897f5892d8330fe2bc0c9859aecvboxsync RTSemFastMutexRequest(pDevExt->mtxTracer);
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync }
8b36957d815c23b479eb35d93ac76c66392e9402vboxsync
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync /*
1207f59aa62006952dbb0bf7700decf34d8caeb2vboxsync * Deregister the tracer implementation.
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync */
1207f59aa62006952dbb0bf7700decf34d8caeb2vboxsync pDevExt->pTracerImage = NULL;
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync pDevExt->pTracerSession = NULL;
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync pDevExt->pTracerOps = NULL;
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync pDevExt->fTracerUnloading = false;
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync
2a5e5a032e6f23f8937718e4ee4d6979188bdd19vboxsync RTSemFastMutexRelease(pDevExt->mtxTracer);
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync}
1207f59aa62006952dbb0bf7700decf34d8caeb2vboxsync
1207f59aa62006952dbb0bf7700decf34d8caeb2vboxsync
8b36957d815c23b479eb35d93ac76c66392e9402vboxsync/**
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync * Deregister a tracer implementation.
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync *
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync * This should be called from the ModuleTerm code or from a ring-0 session.
2a5e5a032e6f23f8937718e4ee4d6979188bdd19vboxsync *
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync * @returns VBox status code.
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync * @param hMod The module handle.
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync * @param pSession Ring-0 session handle.
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync */
8b36957d815c23b479eb35d93ac76c66392e9402vboxsyncSUPR0DECL(int) SUPR0TracerDeregisterImpl(void *hMod, PSUPDRVSESSION pSession)
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync{
fc148a6b23d25a87561beaffe0ba06c3ba93bf5avboxsync PSUPDRVLDRIMAGE pImage = (PSUPDRVLDRIMAGE)hMod;
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync PSUPDRVDEVEXT pDevExt;
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync int rc;
8b36957d815c23b479eb35d93ac76c66392e9402vboxsync
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync /*
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync * Validate input and context.
1dc37bff2fb26897f5892d8330fe2bc0c9859aecvboxsync */
1207f59aa62006952dbb0bf7700decf34d8caeb2vboxsync if (pImage)
1207f59aa62006952dbb0bf7700decf34d8caeb2vboxsync {
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync AssertPtrReturn(pImage, VERR_INVALID_POINTER);
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync AssertReturn(pSession == NULL, VERR_INVALID_PARAMETER);
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync pDevExt = pImage->pDevExt;
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync }
2823fbb1428e982169f04923472d7c94e7ed8385vboxsync else
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync {
2823fbb1428e982169f04923472d7c94e7ed8385vboxsync AssertReturn(SUP_IS_SESSION_VALID(pSession), VERR_INVALID_PARAMETER);
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync AssertReturn(pSession->R0Process == NIL_RTR0PROCESS, VERR_INVALID_PARAMETER);
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync pDevExt = pSession->pDevExt;
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync }
1207f59aa62006952dbb0bf7700decf34d8caeb2vboxsync AssertPtrReturn(pDevExt, VERR_INVALID_POINTER);
1207f59aa62006952dbb0bf7700decf34d8caeb2vboxsync
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync /*
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync * Do the job.
2823fbb1428e982169f04923472d7c94e7ed8385vboxsync */
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync rc = RTSemFastMutexRequest(pDevExt->mtxTracer);
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync if (RT_SUCCESS(rc))
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync {
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync if ( pImage
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync ? pDevExt->pTracerImage == pImage
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync : pDevExt->pTracerSession == pSession)
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync {
a9f530691071e3496b072915b0c5ceabd4e05ea5vboxsync LOG_TRACER(("SUPR0TracerDeregisterImpl: Unloading ...\n"));
a9f530691071e3496b072915b0c5ceabd4e05ea5vboxsync pDevExt->fTracerUnloading = true;
a9f530691071e3496b072915b0c5ceabd4e05ea5vboxsync RTSemFastMutexRelease(pDevExt->mtxTracer);
a9f530691071e3496b072915b0c5ceabd4e05ea5vboxsync supdrvTracerCommonDeregisterImpl(pDevExt);
b7a8ce033b32a429def2feb142bc1bdd1b5dffa2vboxsync LOG_TRACER(("SUPR0TracerDeregisterImpl: ... done.\n"));
b7a8ce033b32a429def2feb142bc1bdd1b5dffa2vboxsync }
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync else
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync {
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync rc = VERR_SUPDRV_TRACER_NOT_REGISTERED;
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync RTSemFastMutexRelease(pDevExt->mtxTracer);
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync }
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync }
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync
1207f59aa62006952dbb0bf7700decf34d8caeb2vboxsync return rc;
d107911787df36a78788a841b73d24da896d02f6vboxsync}
d107911787df36a78788a841b73d24da896d02f6vboxsync
1207f59aa62006952dbb0bf7700decf34d8caeb2vboxsync
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync/*
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync * The probe function is a bit more fun since we need tail jump optimizating.
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync *
2a5e5a032e6f23f8937718e4ee4d6979188bdd19vboxsync * Since we cannot ship yasm sources for linux and freebsd, owing to the cursed
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync * rebuilding of the kernel module from scratch at install time, we have to
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync * deploy some ugly gcc inline assembly here.
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync */
1207f59aa62006952dbb0bf7700decf34d8caeb2vboxsync#if defined(__GNUC__) && (defined(RT_OS_FREEBSD) || defined(RT_OS_LINUX))
1207f59aa62006952dbb0bf7700decf34d8caeb2vboxsync__asm__("\
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync .section .text \n\
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync \n\
8b36957d815c23b479eb35d93ac76c66392e9402vboxsync .p2align 2,,3 \n\
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync .global SUPR0TracerFireProbe \n\
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsyncSUPR0TracerFireProbe: \n\
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync");
1207f59aa62006952dbb0bf7700decf34d8caeb2vboxsync# if defined(RT_ARCH_AMD64)
1207f59aa62006952dbb0bf7700decf34d8caeb2vboxsync__asm__(" \
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync movq g_pfnSupdrvProbeFireKernel(%rip), %rax \n\
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync jmp *%rax \n\
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync");
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync# elif defined(RT_ARCH_X86)
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync__asm__("\
1871985cb4854e5bfb2ead8174ee28dbfce74df5vboxsync movl g_pfnSupdrvProbeFireKernel, %eax \n\
1871985cb4854e5bfb2ead8174ee28dbfce74df5vboxsync jmp *%eax \n\
1871985cb4854e5bfb2ead8174ee28dbfce74df5vboxsync");
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync# else
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync# error "Which arch is this?"
8b36957d815c23b479eb35d93ac76c66392e9402vboxsync# endif
8b36957d815c23b479eb35d93ac76c66392e9402vboxsync__asm__("\
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync \n\
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync .type supdrvTracerProbeFireStub,@function \n\
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync .global supdrvTracerProbeFireStub \n\
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsyncsupdrvTracerProbeFireStub: \n\
8b36957d815c23b479eb35d93ac76c66392e9402vboxsync ret \n\
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync \n\
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync .previous \n\
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync");
1207f59aa62006952dbb0bf7700decf34d8caeb2vboxsync# if 0 /* Slickedit on windows highlighting fix */
1207f59aa62006952dbb0bf7700decf34d8caeb2vboxsync )
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync# endif
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync#endif
2823fbb1428e982169f04923472d7c94e7ed8385vboxsync
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync/**
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync * Module unloading hook, called after execution in the module have ceased.
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync *
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync * @param pDevExt The device extension structure.
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync * @param pImage The image being unloaded.
a9f530691071e3496b072915b0c5ceabd4e05ea5vboxsync */
a9f530691071e3496b072915b0c5ceabd4e05ea5vboxsyncvoid VBOXCALL supdrvTracerModuleUnloading(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage)
a9f530691071e3496b072915b0c5ceabd4e05ea5vboxsync{
a9f530691071e3496b072915b0c5ceabd4e05ea5vboxsync PSUPDRVTPPROVIDER pProv, pProvNext;
b7a8ce033b32a429def2feb142bc1bdd1b5dffa2vboxsync AssertPtrReturnVoid(pImage); /* paranoia */
b7a8ce033b32a429def2feb142bc1bdd1b5dffa2vboxsync
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync RTSemFastMutexRequest(pDevExt->mtxTracer);
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync /*
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync * If it is the tracer image, we have to unload all the providers.
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync */
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync if (pDevExt->pTracerImage == pImage)
1207f59aa62006952dbb0bf7700decf34d8caeb2vboxsync {
d107911787df36a78788a841b73d24da896d02f6vboxsync LOG_TRACER(("supdrvTracerModuleUnloading: Unloading tracer ...\n"));
d107911787df36a78788a841b73d24da896d02f6vboxsync pDevExt->fTracerUnloading = true;
1207f59aa62006952dbb0bf7700decf34d8caeb2vboxsync RTSemFastMutexRelease(pDevExt->mtxTracer);
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync supdrvTracerCommonDeregisterImpl(pDevExt);
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync LOG_TRACER(("supdrvTracerModuleUnloading: ... done.\n"));
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync }
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync else
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync {
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync /*
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync * Unregister all providers belonging to this image.
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync */
1dc37bff2fb26897f5892d8330fe2bc0c9859aecvboxsync RTListForEachSafe(&pDevExt->TracerProviderList, pProv, pProvNext, SUPDRVTPPROVIDER, ListEntry)
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync {
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync if (pProv->pImage == pImage)
1207f59aa62006952dbb0bf7700decf34d8caeb2vboxsync {
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync RTListNodeRemove(&pProv->ListEntry);
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync supdrvTracerDeregisterVtgObj(pDevExt, pProv);
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync }
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync }
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync RTSemFastMutexRelease(pDevExt->mtxTracer);
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync
1dc37bff2fb26897f5892d8330fe2bc0c9859aecvboxsync /*
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync * Try unregister zombies while we have a chance.
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync */
261b44f7fa60a1d4bb4102142d3aa44188908484vboxsync supdrvTracerProcessZombies(pDevExt);
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync }
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync}
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsync
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsync/**
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsync * Called when a session is being cleaned up.
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsync *
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsync * @param pDevExt The device extension structure.
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsync * @param pSession The session that is being torn down.
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsync */
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsyncvoid VBOXCALL supdrvTracerCleanupSession(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession)
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsync{
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsync /*
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsync * If ring-0 session, make sure it has deregistered VTG objects and the tracer.
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsync */
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsync if (pSession->R0Process == NIL_RTR0PROCESS)
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsync {
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsync SUPDRVTPPROVIDER *pProvNext;
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsync SUPDRVTPPROVIDER *pProv;
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsync
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsync RTSemFastMutexRequest(pDevExt->mtxTracer);
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsync RTListForEachSafe(&pDevExt->TracerProviderList, pProv, pProvNext, SUPDRVTPPROVIDER, ListEntry)
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsync {
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsync if (pProv->pSession == pSession)
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsync {
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsync RTListNodeRemove(&pProv->ListEntry);
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsync supdrvTracerDeregisterVtgObj(pDevExt, pProv);
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsync }
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsync }
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsync RTSemFastMutexRelease(pDevExt->mtxTracer);
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsync
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsync (void)SUPR0TracerDeregisterImpl(NULL, pSession);
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsync }
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsync
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsync /*
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsync * Clean up instance data the trace may have associated with the session.
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsync */
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsync if (pSession->uTracerData)
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsync supdrvIOCtl_TracerClose(pDevExt, pSession);
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsync}
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync/**
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync * Open the tracer.
1dc37bff2fb26897f5892d8330fe2bc0c9859aecvboxsync *
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync * @returns VBox status code
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync * @param pDevExt The device extension structure.
8b36957d815c23b479eb35d93ac76c66392e9402vboxsync * @param pSession The current session.
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync * @param uCookie The tracer cookie.
1dc37bff2fb26897f5892d8330fe2bc0c9859aecvboxsync * @param uArg The tracer open argument.
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync */
8b36957d815c23b479eb35d93ac76c66392e9402vboxsyncint VBOXCALL supdrvIOCtl_TracerOpen(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, uint32_t uCookie, uintptr_t uArg)
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync{
1dc37bff2fb26897f5892d8330fe2bc0c9859aecvboxsync RTNATIVETHREAD hNativeSelf = RTThreadNativeSelf();
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync int rc;
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync
8b36957d815c23b479eb35d93ac76c66392e9402vboxsync RTSemFastMutexRequest(pDevExt->mtxTracer);
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync
1dc37bff2fb26897f5892d8330fe2bc0c9859aecvboxsync if (!pSession->uTracerData)
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync {
8b36957d815c23b479eb35d93ac76c66392e9402vboxsync if (pDevExt->pTracerOps)
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync {
1dc37bff2fb26897f5892d8330fe2bc0c9859aecvboxsync if (pDevExt->pTracerSession != pSession)
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync {
8b36957d815c23b479eb35d93ac76c66392e9402vboxsync if (!pDevExt->fTracerUnloading)
5704a317c3b6bdf4b59f6a6ebe45d443296b1995vboxsync {
1dc37bff2fb26897f5892d8330fe2bc0c9859aecvboxsync if (pSession->hTracerCaller == NIL_RTNATIVETHREAD)
5704a317c3b6bdf4b59f6a6ebe45d443296b1995vboxsync {
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync pDevExt->cTracerOpens++;
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync pSession->uTracerData = ~(uintptr_t)0;
8b36957d815c23b479eb35d93ac76c66392e9402vboxsync pSession->hTracerCaller = hNativeSelf;
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync RTSemFastMutexRelease(pDevExt->mtxTracer);
1dc37bff2fb26897f5892d8330fe2bc0c9859aecvboxsync
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync rc = pDevExt->pTracerOps->pfnTracerOpen(pDevExt->pTracerOps, pSession, uCookie, uArg, &pSession->uTracerData);
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync RTSemFastMutexRequest(pDevExt->mtxTracer);
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync if (RT_FAILURE(rc))
6c1f3eb64096421b9ba7272f297bac6ff3d29fe7vboxsync {
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync pDevExt->cTracerOpens--;
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync pSession->uTracerData = 0;
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync }
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync pSession->hTracerCaller = NIL_RTNATIVETHREAD;
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync }
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync else
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync rc = VERR_SUPDRV_TRACER_SESSION_BUSY;
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync }
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync else
1dc37bff2fb26897f5892d8330fe2bc0c9859aecvboxsync rc = VERR_SUPDRV_TRACER_UNLOADING;
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync }
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync else
1dc37bff2fb26897f5892d8330fe2bc0c9859aecvboxsync rc = VERR_SUPDRV_TRACER_CANNOT_OPEN_SELF;
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync }
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync else
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync rc = VERR_SUPDRV_TRACER_NOT_PRESENT;
f62342e2cc901a67e27fa69c0e712ee35e9c4c68vboxsync }
f62342e2cc901a67e27fa69c0e712ee35e9c4c68vboxsync else
f62342e2cc901a67e27fa69c0e712ee35e9c4c68vboxsync rc = VERR_SUPDRV_TRACER_ALREADY_OPENED;
f8df398d066204e2bf0ba209ea3554fc113fb484vboxsync
f62342e2cc901a67e27fa69c0e712ee35e9c4c68vboxsync RTSemFastMutexRelease(pDevExt->mtxTracer);
f62342e2cc901a67e27fa69c0e712ee35e9c4c68vboxsync return rc;
f62342e2cc901a67e27fa69c0e712ee35e9c4c68vboxsync}
f62342e2cc901a67e27fa69c0e712ee35e9c4c68vboxsync
f62342e2cc901a67e27fa69c0e712ee35e9c4c68vboxsync
f62342e2cc901a67e27fa69c0e712ee35e9c4c68vboxsync/**
f62342e2cc901a67e27fa69c0e712ee35e9c4c68vboxsync * Closes the tracer.
f62342e2cc901a67e27fa69c0e712ee35e9c4c68vboxsync *
f62342e2cc901a67e27fa69c0e712ee35e9c4c68vboxsync * @returns VBox status code.
f62342e2cc901a67e27fa69c0e712ee35e9c4c68vboxsync * @param pDevExt The device extension structure.
f62342e2cc901a67e27fa69c0e712ee35e9c4c68vboxsync * @param pSession The current session.
f62342e2cc901a67e27fa69c0e712ee35e9c4c68vboxsync */
f62342e2cc901a67e27fa69c0e712ee35e9c4c68vboxsyncint VBOXCALL supdrvIOCtl_TracerClose(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession)
f62342e2cc901a67e27fa69c0e712ee35e9c4c68vboxsync{
f62342e2cc901a67e27fa69c0e712ee35e9c4c68vboxsync RTNATIVETHREAD hNativeSelf = RTThreadNativeSelf();
f62342e2cc901a67e27fa69c0e712ee35e9c4c68vboxsync int rc;
f62342e2cc901a67e27fa69c0e712ee35e9c4c68vboxsync
f62342e2cc901a67e27fa69c0e712ee35e9c4c68vboxsync RTSemFastMutexRequest(pDevExt->mtxTracer);
f62342e2cc901a67e27fa69c0e712ee35e9c4c68vboxsync
b604fbf16eda38d14b4999c245f032bfaa5aa85avboxsync if (pSession->uTracerData)
b604fbf16eda38d14b4999c245f032bfaa5aa85avboxsync {
b604fbf16eda38d14b4999c245f032bfaa5aa85avboxsync Assert(pDevExt->cTracerOpens > 0);
8b36957d815c23b479eb35d93ac76c66392e9402vboxsync
b604fbf16eda38d14b4999c245f032bfaa5aa85avboxsync if (pDevExt->pTracerOps)
8b36957d815c23b479eb35d93ac76c66392e9402vboxsync {
8b36957d815c23b479eb35d93ac76c66392e9402vboxsync if (pSession->hTracerCaller == NIL_RTNATIVETHREAD)
b604fbf16eda38d14b4999c245f032bfaa5aa85avboxsync {
8b36957d815c23b479eb35d93ac76c66392e9402vboxsync uintptr_t uTracerData = pSession->uTracerData;
b604fbf16eda38d14b4999c245f032bfaa5aa85avboxsync pSession->uTracerData = 0;
b604fbf16eda38d14b4999c245f032bfaa5aa85avboxsync pSession->hTracerCaller = hNativeSelf;
b604fbf16eda38d14b4999c245f032bfaa5aa85avboxsync RTSemFastMutexRelease(pDevExt->mtxTracer);
b604fbf16eda38d14b4999c245f032bfaa5aa85avboxsync
b604fbf16eda38d14b4999c245f032bfaa5aa85avboxsync pDevExt->pTracerOps->pfnTracerClose(pDevExt->pTracerOps, pSession, uTracerData);
b604fbf16eda38d14b4999c245f032bfaa5aa85avboxsync rc = VINF_SUCCESS;
b604fbf16eda38d14b4999c245f032bfaa5aa85avboxsync
b604fbf16eda38d14b4999c245f032bfaa5aa85avboxsync RTSemFastMutexRequest(pDevExt->mtxTracer);
b604fbf16eda38d14b4999c245f032bfaa5aa85avboxsync pSession->hTracerCaller = NIL_RTNATIVETHREAD;
b604fbf16eda38d14b4999c245f032bfaa5aa85avboxsync Assert(pDevExt->cTracerOpens > 0);
b604fbf16eda38d14b4999c245f032bfaa5aa85avboxsync pDevExt->cTracerOpens--;
b604fbf16eda38d14b4999c245f032bfaa5aa85avboxsync }
b604fbf16eda38d14b4999c245f032bfaa5aa85avboxsync else
b604fbf16eda38d14b4999c245f032bfaa5aa85avboxsync rc = VERR_SUPDRV_TRACER_SESSION_BUSY;
b604fbf16eda38d14b4999c245f032bfaa5aa85avboxsync }
b604fbf16eda38d14b4999c245f032bfaa5aa85avboxsync else
13d1fd6f43e9a245a4f2b4fc6845bdaa5d0f4134vboxsync {
13d1fd6f43e9a245a4f2b4fc6845bdaa5d0f4134vboxsync rc = VERR_SUPDRV_TRACER_NOT_PRESENT;
13d1fd6f43e9a245a4f2b4fc6845bdaa5d0f4134vboxsync pSession->uTracerData = 0;
13d1fd6f43e9a245a4f2b4fc6845bdaa5d0f4134vboxsync Assert(pDevExt->cTracerOpens > 0);
13d1fd6f43e9a245a4f2b4fc6845bdaa5d0f4134vboxsync pDevExt->cTracerOpens--;
13d1fd6f43e9a245a4f2b4fc6845bdaa5d0f4134vboxsync }
13d1fd6f43e9a245a4f2b4fc6845bdaa5d0f4134vboxsync }
13d1fd6f43e9a245a4f2b4fc6845bdaa5d0f4134vboxsync else
13d1fd6f43e9a245a4f2b4fc6845bdaa5d0f4134vboxsync rc = VERR_SUPDRV_TRACER_NOT_OPENED;
13d1fd6f43e9a245a4f2b4fc6845bdaa5d0f4134vboxsync
13d1fd6f43e9a245a4f2b4fc6845bdaa5d0f4134vboxsync RTSemFastMutexRelease(pDevExt->mtxTracer);
13d1fd6f43e9a245a4f2b4fc6845bdaa5d0f4134vboxsync return rc;
13d1fd6f43e9a245a4f2b4fc6845bdaa5d0f4134vboxsync}
13d1fd6f43e9a245a4f2b4fc6845bdaa5d0f4134vboxsync
13d1fd6f43e9a245a4f2b4fc6845bdaa5d0f4134vboxsync
13d1fd6f43e9a245a4f2b4fc6845bdaa5d0f4134vboxsync/**
13d1fd6f43e9a245a4f2b4fc6845bdaa5d0f4134vboxsync * Performs a tracer I/O control request.
13d1fd6f43e9a245a4f2b4fc6845bdaa5d0f4134vboxsync *
13d1fd6f43e9a245a4f2b4fc6845bdaa5d0f4134vboxsync * @returns VBox status code.
13d1fd6f43e9a245a4f2b4fc6845bdaa5d0f4134vboxsync * @param pDevExt The device extension structure.
13d1fd6f43e9a245a4f2b4fc6845bdaa5d0f4134vboxsync * @param pSession The current session.
13d1fd6f43e9a245a4f2b4fc6845bdaa5d0f4134vboxsync * @param uCmd The tracer command.
13d1fd6f43e9a245a4f2b4fc6845bdaa5d0f4134vboxsync * @param uArg The tracer argument.
13d1fd6f43e9a245a4f2b4fc6845bdaa5d0f4134vboxsync * @param piRetVal Where to store the tracer specific return value.
13d1fd6f43e9a245a4f2b4fc6845bdaa5d0f4134vboxsync */
13d1fd6f43e9a245a4f2b4fc6845bdaa5d0f4134vboxsyncint VBOXCALL supdrvIOCtl_TracerIOCtl(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, uintptr_t uCmd, uintptr_t uArg, int32_t *piRetVal)
13d1fd6f43e9a245a4f2b4fc6845bdaa5d0f4134vboxsync{
13d1fd6f43e9a245a4f2b4fc6845bdaa5d0f4134vboxsync RTNATIVETHREAD hNativeSelf = RTThreadNativeSelf();
13d1fd6f43e9a245a4f2b4fc6845bdaa5d0f4134vboxsync int rc;
13d1fd6f43e9a245a4f2b4fc6845bdaa5d0f4134vboxsync
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync *piRetVal = 0;
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync RTSemFastMutexRequest(pDevExt->mtxTracer);
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync if (pSession->uTracerData)
1dc37bff2fb26897f5892d8330fe2bc0c9859aecvboxsync {
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync Assert(pDevExt->cTracerOpens > 0);
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync if (pDevExt->pTracerOps)
8b36957d815c23b479eb35d93ac76c66392e9402vboxsync {
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync if (!pDevExt->fTracerUnloading)
1dc37bff2fb26897f5892d8330fe2bc0c9859aecvboxsync {
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync if (pSession->hTracerCaller == NIL_RTNATIVETHREAD)
8b36957d815c23b479eb35d93ac76c66392e9402vboxsync {
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync uintptr_t uTracerData = pSession->uTracerData;
1dc37bff2fb26897f5892d8330fe2bc0c9859aecvboxsync pDevExt->cTracerOpens++;
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsync pSession->hTracerCaller = hNativeSelf;
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync RTSemFastMutexRelease(pDevExt->mtxTracer);
8b36957d815c23b479eb35d93ac76c66392e9402vboxsync
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync rc = pDevExt->pTracerOps->pfnTracerIoCtl(pDevExt->pTracerOps, pSession, uTracerData, uCmd, uArg, piRetVal);
1dc37bff2fb26897f5892d8330fe2bc0c9859aecvboxsync
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsync RTSemFastMutexRequest(pDevExt->mtxTracer);
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync pSession->hTracerCaller = NIL_RTNATIVETHREAD;
8b36957d815c23b479eb35d93ac76c66392e9402vboxsync Assert(pDevExt->cTracerOpens > 0);
8b36957d815c23b479eb35d93ac76c66392e9402vboxsync pDevExt->cTracerOpens--;
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync }
1dc37bff2fb26897f5892d8330fe2bc0c9859aecvboxsync else
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsync rc = VERR_SUPDRV_TRACER_SESSION_BUSY;
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync }
8b36957d815c23b479eb35d93ac76c66392e9402vboxsync else
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync rc = VERR_SUPDRV_TRACER_UNLOADING;
1dc37bff2fb26897f5892d8330fe2bc0c9859aecvboxsync }
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsync else
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync rc = VERR_SUPDRV_TRACER_NOT_PRESENT;
8b36957d815c23b479eb35d93ac76c66392e9402vboxsync }
14650dbf3041b8fcb092b55cf673bd6f392390c2vboxsync else
04c6e2bf4c47aa33be5ee50ac468b1b86b7125b4vboxsync rc = VERR_SUPDRV_TRACER_NOT_OPENED;
1dc37bff2fb26897f5892d8330fe2bc0c9859aecvboxsync
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsync RTSemFastMutexRelease(pDevExt->mtxTracer);
14650dbf3041b8fcb092b55cf673bd6f392390c2vboxsync return rc;
8b36957d815c23b479eb35d93ac76c66392e9402vboxsync}
8c58249d7f93d82395aa6c8b31526443892bc375vboxsync
8c58249d7f93d82395aa6c8b31526443892bc375vboxsync
8c58249d7f93d82395aa6c8b31526443892bc375vboxsync/**
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsync * Early module initialization hook.
8c58249d7f93d82395aa6c8b31526443892bc375vboxsync *
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync * @returns VBox status code.
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync * @param pDevExt The device extension structure.
6c1f3eb64096421b9ba7272f297bac6ff3d29fe7vboxsync */
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsyncint VBOXCALL supdrvTracerInit(PSUPDRVDEVEXT pDevExt)
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync{
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync /*
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync * Initialize the tracer.
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync */
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync int rc = RTSemFastMutexCreate(&pDevExt->mtxTracer);
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync if (RT_SUCCESS(rc))
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync {
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync pDevExt->TracerHlp.uVersion = SUPDRVTRACERHLP_VERSION;
1dc37bff2fb26897f5892d8330fe2bc0c9859aecvboxsync /** @todo */
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync pDevExt->TracerHlp.uEndVersion = SUPDRVTRACERHLP_VERSION;
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync RTListInit(&pDevExt->TracerProviderList);
261b44f7fa60a1d4bb4102142d3aa44188908484vboxsync RTListInit(&pDevExt->TracerProviderZombieList);
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync#ifdef VBOX_WITH_NATIVE_DTRACE_R0DRV
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync pDevExt->pTracerOps = supdrvDTraceInit();
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync if (pDevExt->pTracerOps)
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync g_pfnSupdrvProbeFireKernel = (PFNRT)pDevExt->pTracerOps->pfnProbeFireKernel;
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync#endif
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync
1dc37bff2fb26897f5892d8330fe2bc0c9859aecvboxsync /*
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync * Register the provider for this module, if compiled in.
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync */
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync#ifdef VBOX_WITH_DTRACE_R0DRV
8b36957d815c23b479eb35d93ac76c66392e9402vboxsync rc = supdrvTracerRegisterVtgObj(pDevExt, &g_VTGObjHeader, _1M, NULL /*pImage*/, NULL /*pSession*/, "vboxdrv");
9bb98d54790a98dad0ad6d9bdc5d319b6fdf0bffvboxsync if (RT_SUCCESS(rc))
56349fc0a23f96f82208016f8f59f8377bb284b1vboxsync return rc;
9bb98d54790a98dad0ad6d9bdc5d319b6fdf0bffvboxsync SUPR0Printf("supdrvTracerInit: supdrvTracerRegisterVtgObj failed with rc=%d\n", rc);
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync RTSemFastMutexDestroy(pDevExt->mtxTracer);
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync#else
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsync
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync return VINF_SUCCESS;
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync#endif
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync }
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync pDevExt->mtxTracer = NIL_RTSEMFASTMUTEX;
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsync return rc;
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync}
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync
1dc37bff2fb26897f5892d8330fe2bc0c9859aecvboxsync/**
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync * Late module termination hook.
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync *
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync * @returns VBox status code.
8b36957d815c23b479eb35d93ac76c66392e9402vboxsync * @param pDevExt The device extension structure.
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync */
56349fc0a23f96f82208016f8f59f8377bb284b1vboxsyncvoid VBOXCALL supdrvTracerTerm(PSUPDRVDEVEXT pDevExt)
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync{
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync LOG_TRACER(("supdrvTracerTerm\n"));
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsync supdrvTracerRemoveAllProviders(pDevExt);
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync RTSemFastMutexDestroy(pDevExt->mtxTracer);
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync pDevExt->mtxTracer = NIL_RTSEMFASTMUTEX;
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync LOG_TRACER(("supdrvTracerTerm: Done\n"));
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsync}
8c58249d7f93d82395aa6c8b31526443892bc375vboxsync
8c58249d7f93d82395aa6c8b31526443892bc375vboxsync