VirtualBox

source: vbox/trunk/src/VBox/HostDrivers/Support/SUPDrvTracer.cpp

Last change on this file was 103727, checked in by vboxsync, 2 months ago

Linux: SUPDrvTracer.cpp: Annotate indirect jumps to instruct objtool that such jump is vouched safe for retpoline build (fix scm build), bugref:10617

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 91.4 KB
RevLine 
[40518]1/* $Id: SUPDrvTracer.cpp 103727 2024-03-07 11:10:23Z vboxsync $ */
2/** @file
[40777]3 * VBoxDrv - The VirtualBox Support Driver - Tracer Interface.
[40518]4 */
5
6/*
[98103]7 * Copyright (C) 2012-2023 Oracle and/or its affiliates.
[40518]8 *
[96407]9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
[40518]11 *
[96407]12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
[40518]25 * The contents of this file may alternatively be used under the terms
26 * of the Common Development and Distribution License Version 1.0
[96407]27 * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
28 * in the VirtualBox distribution, in which case the provisions of the
[40518]29 * CDDL are applicable instead of those of the GPL.
30 *
31 * You may elect to license modified versions of this file under the
32 * terms and conditions of either the GPL or the CDDL or both.
[96407]33 *
34 * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
[40518]35 */
36
37
[57358]38/*********************************************************************************************************************************
39* Header Files *
40*********************************************************************************************************************************/
[40518]41#define LOG_GROUP LOG_GROUP_SUP_DRV
[40756]42#define SUPDRV_AGNOSTIC
[40518]43#include "SUPDrvInternal.h"
44
45#include <VBox/err.h>
[40605]46#include <VBox/log.h>
[40600]47#include <VBox/VBoxTpG.h>
[40602]48
[40518]49#include <iprt/assert.h>
[40602]50#include <iprt/ctype.h>
51#include <iprt/list.h>
52#include <iprt/mem.h>
53#include <iprt/semaphore.h>
[40636]54#include <iprt/thread.h>
[41117]55#include <iprt/param.h>
56#include <iprt/uuid.h>
[40518]57
[103726]58#if defined(RT_OS_LINUX)
59# if RTLNX_VER_MIN(4,15,10)
60# include <asm/nospec-branch.h>
61# endif /* < 4.15.10 */
62# if RTLNX_VER_MIN(5,17,0)
63# include <asm/linkage.h>
64# endif /* < 5.17.0 */
65#endif /* !RT_OS_LINUX */
[40518]66
[103727]67
[57358]68/*********************************************************************************************************************************
69* Structures and Typedefs *
70*********************************************************************************************************************************/
[41117]71/** Pointer to a user tracer module registration record. */
72typedef struct SUPDRVTRACERUMOD *PSUPDRVTRACERUMOD;
73
[40600]74/**
[40756]75 * Data for a tracepoint provider.
[40600]76 */
[40756]77typedef struct SUPDRVTPPROVIDER
[40600]78{
79 /** The entry in the provider list for this image. */
[40756]80 RTLISTNODE ListEntry;
[41117]81 /** The entry in the per session provider list for this image. */
82 RTLISTNODE SessionListEntry;
[40518]83
[40756]84 /** The core structure. */
85 SUPDRVVDTPROVIDERCORE Core;
[40600]86
87 /** Pointer to the image this provider resides in. NULL if it's a
88 * driver. */
[40756]89 PSUPDRVLDRIMAGE pImage;
[40600]90 /** The session this provider is associated with if registered via
[40602]91 * SUPR0VtgRegisterDrv. NULL if pImage is set. */
[40756]92 PSUPDRVSESSION pSession;
[41117]93 /** The user tracepoint module associated with this provider. NULL if
94 * pImage is set. */
95 PSUPDRVTRACERUMOD pUmod;
[40602]96
[40812]97 /** Used to indicate that we've called pfnProviderDeregistered already and it
98 * failed because the provider was busy. Next time we must try
99 * pfnProviderDeregisterZombie.
100 *
101 * @remarks This does not necessiarly mean the provider is in the zombie
102 * list. See supdrvTracerCommonDeregisterImpl. */
[40756]103 bool fZombie;
104 /** Set if the provider has been successfully registered with the
105 * tracer. */
106 bool fRegistered;
[40704]107 /** The provider name (for logging purposes). */
[103684]108 RT_FLEXIBLE_ARRAY_EXTENSION
109 char szName[RT_FLEXIBLE_ARRAY];
[40756]110} SUPDRVTPPROVIDER;
111/** Pointer to the data for a tracepoint provider. */
112typedef SUPDRVTPPROVIDER *PSUPDRVTPPROVIDER;
[40600]113
114
[41117]115/**
116 * User tracer module VTG data copy.
117 */
118typedef struct SUPDRVVTGCOPY
119{
120 /** Magic (SUDPRVVTGCOPY_MAGIC). */
121 uint32_t u32Magic;
122 /** Refernece counter (we expect to share a lot of these). */
123 uint32_t cRefs;
124 /** The size of the */
125 uint32_t cbStrTab;
126 /** Image type flags. */
127 uint32_t fFlags;
128 /** Hash list entry (SUPDRVDEVEXT::aTrackerUmodHash). */
129 RTLISTNODE ListEntry;
130 /** The VTG object header.
131 * The rest of the data follows immediately afterwards. First the object,
132 * then the probe locations and finally the probe location string table. All
133 * pointers are fixed up to point within this data. */
134 VTGOBJHDR Hdr;
135} SUPDRVVTGCOPY;
136/** Pointer to a VTG object copy. */
137typedef SUPDRVVTGCOPY *PSUPDRVVTGCOPY;
138/** Magic value for SUPDRVVTGCOPY. */
139#define SUDPRVVTGCOPY_MAGIC UINT32_C(0x00080386)
140
141
142/**
143 * User tracer module registration record.
144 */
145typedef struct SUPDRVTRACERUMOD
146{
147 /** Magic (SUPDRVTRACERUMOD_MAGIC). */
148 uint32_t u32Magic;
149 /** List entry. This is anchored in SUPDRVSESSION::UmodList. */
150 RTLISTNODE ListEntry;
151 /** The address of the ring-3 VTG header. */
152 RTR3PTR R3PtrVtgHdr;
153 /** Pointer to the ring-0 copy of the VTG data. */
154 PSUPDRVVTGCOPY pVtgCopy;
155 /** The memory object that locks down the user memory. */
156 RTR0MEMOBJ hMemObjLock;
157 /** The memory object that maps the locked memory into kernel space. */
158 RTR0MEMOBJ hMemObjMap;
159 /** Pointer to the probe enabled-count array within the mapping. */
160 uint32_t *pacProbeEnabled;
161 /** Pointer to the probe location array within the mapping. */
162 void *pvProbeLocs;
163 /** The address of the ring-3 probe locations. */
164 RTR3PTR R3PtrProbeLocs;
165 /** The lookup table index. */
166 uint8_t iLookupTable;
167 /** The module bit count. */
168 uint8_t cBits;
169 /** The size of a probe location record. */
170 uint8_t cbProbeLoc;
171 /** The number of probe locations. */
172 uint32_t cProbeLocs;
173 /** Ring-0 probe location info. */
[103684]174 RT_FLEXIBLE_ARRAY_EXTENSION
175 SUPDRVPROBELOC aProbeLocs[RT_FLEXIBLE_ARRAY];
[41117]176} SUPDRVTRACERUMOD;
177/** Magic value for SUPDRVVTGCOPY. */
178#define SUPDRVTRACERUMOD_MAGIC UINT32_C(0x00080486)
179
180
[57358]181/*********************************************************************************************************************************
182* Defined Constants And Macros *
183*********************************************************************************************************************************/
[40867]184/** Simple SUPR0Printf-style logging. */
[40812]185#ifdef DEBUG_bird
[40756]186# define LOG_TRACER(a_Args) SUPR0Printf a_Args
[40704]187#else
[40756]188# define LOG_TRACER(a_Args) do { } while (0)
[40704]189#endif
190
[40518]191
[57358]192/*********************************************************************************************************************************
193* Global Variables *
194*********************************************************************************************************************************/
[40777]195/** The address of the current probe fire routine for kernel mode. */
[40781]196PFNRT g_pfnSupdrvProbeFireKernel = supdrvTracerProbeFireStub;
[40518]197
198
[57358]199/*********************************************************************************************************************************
200* Internal Functions *
201*********************************************************************************************************************************/
[41117]202static void supdrvVtgReleaseObjectCopy(PSUPDRVDEVEXT pDevExt, PSUPDRVVTGCOPY pThis);
[40763]203
[41117]204
205
[40763]206/**
207 * Validates a VTG string against length and characterset limitations.
208 *
209 * @returns VINF_SUCCESS, VERR_SUPDRV_VTG_BAD_STRING or
210 * VERR_SUPDRV_VTG_STRING_TOO_LONG.
211 * @param psz The string.
212 */
[40601]213static int supdrvVtgValidateString(const char *psz)
214{
215 size_t off = 0;
216 while (off < _4K)
217 {
218 char const ch = psz[off++];
219 if (!ch)
220 return VINF_SUCCESS;
[40602]221 if ( !RTLocCIsAlNum(ch)
[40601]222 && ch != ' '
[40612]223 && ch != '_'
224 && ch != '-'
[40601]225 && ch != '('
226 && ch != ')'
227 && ch != ','
228 && ch != '*'
[40602]229 && ch != '&'
[40601]230 )
[40612]231 {
232 /*RTAssertMsg2("off=%u '%s'\n", off, psz);*/
[40601]233 return VERR_SUPDRV_VTG_BAD_STRING;
[40612]234 }
[40601]235 }
236 return VERR_SUPDRV_VTG_STRING_TOO_LONG;
237}
238
[40763]239
[41117]240/** Used by the validation code below. */
241#define MY_CHECK_RET(a_Expr, a_rc) \
242 MY_CHECK_MSG_RET(a_Expr, ("%s: Validation failed on line " RT_XSTR(__LINE__) ": " #a_Expr "\n", __FUNCTION__), a_rc)
243
244/** Used by the validation code below. */
245#define MY_CHECK_MSG_RET(a_Expr, a_PrintfArgs, a_rc) \
246 do { if (RT_UNLIKELY(!(a_Expr))) { SUPR0Printf a_PrintfArgs; return (a_rc); } } while (0)
247
248/** Used by the validation code below. */
249#define MY_WITHIN_IMAGE(p, rc) \
250 do { \
251 if (pbImage) \
252 { \
253 if ((uintptr_t)(p) - (uintptr_t)pbImage > cbImage) \
254 { \
255 SUPR0Printf("supdrvVtgValidate: " #rc " - p=%p pbImage=%p cbImage=%#zxline=%u %s\n", \
256 p, pbImage, cbImage, #p); \
257 return (rc); \
258 } \
259 } \
260 else if (!RT_VALID_PTR(p)) \
261 return (rc); \
262 } while (0)
263
264
[40602]265/**
[41117]266 * Validates the VTG object header.
[40602]267 *
[40600]268 * @returns VBox status code.
[41117]269 * @param pVtgHdr The header.
270 * @param uVtgHdrAddr The address where the header is actually
271 * loaded.
272 * @param pbImage The image base, if available.
273 * @param cbImage The image size, if available.
274 * @param fUmod Whether this is a user module.
[40600]275 */
[41117]276static int supdrvVtgValidateHdr(PVTGOBJHDR pVtgHdr, RTUINTPTR uVtgHdrAddr, const uint8_t *pbImage, size_t cbImage, bool fUmod)
[40600]277{
[41117]278 struct VTGAREAS
[40601]279 {
[41117]280 uint32_t off;
281 uint32_t cb;
282 } const *paAreas;
283 unsigned cAreas;
284 unsigned i;
285 uint32_t cbVtgObj;
286 uint32_t off;
[40601]287
[41117]288#define MY_VALIDATE_SIZE(cb, cMin, cMax, cbUnit, rcBase) \
[40600]289 do { \
290 if ((cb) < (cMin) * (cbUnit)) \
[40851]291 { \
[41117]292 SUPR0Printf("supdrvVtgValidateHdr: " #rcBase "_TOO_FEW - cb=%#zx cMin=%#zx cbUnit=%#zx line=%u %s\n", \
293 (size_t)(cb), (size_t)(cMin), (size_t)cbUnit, __LINE__, #cb); \
[40602]294 return rcBase ## _TOO_FEW; \
[40851]295 } \
[40600]296 if ((cb) >= (cMax) * (cbUnit)) \
[40851]297 { \
[41117]298 SUPR0Printf("supdrvVtgValidateHdr: " #rcBase "_TOO_MUCH - cb=%#zx cMax=%#zx cbUnit=%#zx line=%u %s\n", \
299 (size_t)(cb), (size_t)(cMax), (size_t)cbUnit, __LINE__, #cb); \
[40602]300 return rcBase ## _TOO_MUCH; \
[40851]301 } \
[40600]302 if ((cb) / (cbUnit) * (cbUnit) != (cb)) \
[40851]303 { \
[41117]304 SUPR0Printf("supdrvVtgValidateHdr: " #rcBase "_NOT_MULTIPLE - cb=%#zx cbUnit=%#zx line=%u %s\n", \
305 (size_t)(cb), (size_t)cbUnit, __LINE__, #cb); \
[40602]306 return rcBase ## _NOT_MULTIPLE; \
[40851]307 } \
[40600]308 } while (0)
[41117]309
310#define MY_VALIDATE_OFF(off, cb, cMin, cMax, cbUnit, cbAlign, rcBase) \
[40601]311 do { \
[41117]312 if ( (cb) >= cbVtgObj \
313 || off > cbVtgObj - (cb) ) \
[40601]314 { \
[41117]315 SUPR0Printf("supdrvVtgValidateHdr: " #rcBase "_OFF - off=%#x cb=%#x pVtgHdr=%p cbVtgHdr=%#zx line=%u %s\n", \
316 (off), (cb), pVtgHdr, cbVtgObj, __LINE__, #off); \
317 return rcBase ## _OFF; \
[40601]318 } \
[41117]319 if (RT_ALIGN(off, cbAlign) != (off)) \
320 { \
321 SUPR0Printf("supdrvVtgValidateHdr: " #rcBase "_OFF - off=%#x align=%#zx line=%u %s\n", \
322 (off), (size_t)(cbAlign), __LINE__, #off); \
323 return rcBase ## _OFF; \
324 } \
325 MY_VALIDATE_SIZE(cb, cMin, cMax, cbUnit, rcBase); \
[40601]326 } while (0)
[40600]327
[40601]328 /*
[41117]329 * Make sure both pbImage and cbImage are NULL/0 if one if of them is.
[40601]330 */
[41117]331 if (!pbImage || !cbImage)
332 {
333 pbImage = NULL;
334 cbImage = 0;
335 cbVtgObj = pVtgHdr->cbObj;
336 }
337 else
338 {
339 MY_WITHIN_IMAGE(pVtgHdr, VERR_SUPDRV_VTG_BAD_HDR_PTR);
340 cbVtgObj = pVtgHdr->cbObj;
341 MY_WITHIN_IMAGE((uint8_t *)pVtgHdr + cbVtgObj - 1, VERR_SUPDRV_VTG_BAD_HDR_PTR);
342 }
343
344 if (cbVtgObj > _1M)
345 {
346 SUPR0Printf("supdrvVtgValidateHdr: VERR_SUPDRV_TRACER_TOO_LARGE - cbVtgObj=%#x\n", cbVtgObj);
347 return VERR_SUPDRV_TRACER_TOO_LARGE;
348 }
349
350 /*
351 * Set the probe location array offset and size members.
352 */
353 if (!pVtgHdr->offProbeLocs)
354 {
355 uint64_t u64Tmp = pVtgHdr->uProbeLocsEnd.u64 - pVtgHdr->uProbeLocs.u64;
356 if (u64Tmp >= UINT32_MAX)
[41147]357 {
[41311]358 SUPR0Printf("supdrvVtgValidateHdr: VERR_SUPDRV_VTG_BAD_HDR_TOO_MUCH - u64Tmp=%#llx ProbeLocs=%#llx ProbeLocsEnd=%#llx\n",
[41147]359 u64Tmp, pVtgHdr->uProbeLocs.u64, pVtgHdr->uProbeLocsEnd.u64);
[41117]360 return VERR_SUPDRV_VTG_BAD_HDR_TOO_MUCH;
[41147]361 }
[49143]362 /*SUPR0Printf("supdrvVtgValidateHdr: cbProbeLocs %#x -> %#x\n", pVtgHdr->cbProbeLocs, (uint32_t)u64Tmp);*/
[41117]363 pVtgHdr->cbProbeLocs = (uint32_t)u64Tmp;
364
365 u64Tmp = pVtgHdr->uProbeLocs.u64 - uVtgHdrAddr;
[41311]366#ifdef RT_OS_DARWIN
367 /* The loader and/or ld64-97.17 seems not to generate fixups for our
368 __VTGObj section. Detect this by comparing them with the
[47518]369 u64VtgObjSectionStart member and assume max image size of 4MB.
370 Seems to be worked around by the __VTGPrLc.End and __VTGPrLc.Begin
371 padding fudge, meaning that the linker misplaced the relocations. */
[41311]372 if ( (int64_t)u64Tmp != (int32_t)u64Tmp
373 && pVtgHdr->u64VtgObjSectionStart != uVtgHdrAddr
374 && pVtgHdr->u64VtgObjSectionStart < _4M
375 && pVtgHdr->uProbeLocsEnd.u64 < _4M
376 && !fUmod)
377 {
378 uint64_t offDelta = uVtgHdrAddr - pVtgHdr->u64VtgObjSectionStart;
[49143]379 /*SUPR0Printf("supdrvVtgValidateHdr: offDelta=%#llx\n", offDelta);*/
[41311]380 pVtgHdr->uProbeLocs.u64 += offDelta;
381 pVtgHdr->uProbeLocsEnd.u64 += offDelta;
382 u64Tmp += offDelta;
383 }
384#endif
[41117]385 if ((int64_t)u64Tmp != (int32_t)u64Tmp)
[41147]386 {
[41311]387 SUPR0Printf("supdrvVtgValidateHdr: VERR_SUPDRV_VTG_BAD_HDR_PTR - u64Tmp=%#llx uProbeLocs=%#llx uVtgHdrAddr=%RTptr\n",
[41147]388 u64Tmp, pVtgHdr->uProbeLocs.u64, uVtgHdrAddr);
[41117]389 return VERR_SUPDRV_VTG_BAD_HDR_PTR;
[41147]390 }
[49143]391 /*SUPR0Printf("supdrvVtgValidateHdr: offProbeLocs %#x -> %#x\n", pVtgHdr->offProbeLocs, (int32_t)u64Tmp);*/
[41117]392 pVtgHdr->offProbeLocs = (int32_t)u64Tmp;
393 }
394
395 /*
396 * The non-area description fields.
397 */
[40612]398 if (memcmp(pVtgHdr->szMagic, VTGOBJHDR_MAGIC, sizeof(pVtgHdr->szMagic)))
[49143]399 {
400 SUPR0Printf("supdrvVtgValidateHdr: %p: %.16Rhxs\n", pVtgHdr, pVtgHdr->szMagic);
[40601]401 return VERR_SUPDRV_VTG_MAGIC;
[49143]402 }
[41117]403 if ( pVtgHdr->cBits != ARCH_BITS
404 && ( !fUmod
405 || ( pVtgHdr->cBits != 32
406 && pVtgHdr->cBits != 64)) )
[40601]407 return VERR_SUPDRV_VTG_BITS;
[41311]408 MY_CHECK_RET(pVtgHdr->au32Reserved1[0] == 0, VERR_SUPDRV_VTG_BAD_HDR_MISC);
409 MY_CHECK_RET(pVtgHdr->au32Reserved1[1] == 0, VERR_SUPDRV_VTG_BAD_HDR_MISC);
410 MY_CHECK_RET(!RTUuidIsNull(&pVtgHdr->Uuid), VERR_SUPDRV_VTG_BAD_HDR_MISC);
[40600]411
[41117]412 /*
413 * Check the individual area descriptors.
414 */
415 MY_VALIDATE_OFF(pVtgHdr->offStrTab, pVtgHdr->cbStrTab, 4, _1M, sizeof(char), sizeof(uint8_t), VERR_SUPDRV_VTG_BAD_HDR);
416 MY_VALIDATE_OFF(pVtgHdr->offArgLists, pVtgHdr->cbArgLists, 1, _32K, sizeof(uint32_t), sizeof(uint32_t), VERR_SUPDRV_VTG_BAD_HDR);
417 MY_VALIDATE_OFF(pVtgHdr->offProbes, pVtgHdr->cbProbes, 1, _32K, sizeof(VTGDESCPROBE), sizeof(uint32_t), VERR_SUPDRV_VTG_BAD_HDR);
418 MY_VALIDATE_OFF(pVtgHdr->offProviders, pVtgHdr->cbProviders, 1, 16, sizeof(VTGDESCPROVIDER), sizeof(uint32_t), VERR_SUPDRV_VTG_BAD_HDR);
419 MY_VALIDATE_OFF(pVtgHdr->offProbeEnabled, pVtgHdr->cbProbeEnabled, 1, _32K, sizeof(uint32_t), sizeof(uint32_t), VERR_SUPDRV_VTG_BAD_HDR);
420 if (!fUmod)
421 {
422 MY_WITHIN_IMAGE(pVtgHdr->uProbeLocs.p, VERR_SUPDRV_VTG_BAD_HDR_PTR);
423 MY_WITHIN_IMAGE(pVtgHdr->uProbeLocsEnd.p, VERR_SUPDRV_VTG_BAD_HDR_PTR);
424 MY_VALIDATE_SIZE( pVtgHdr->cbProbeLocs, 1, _128K, sizeof(VTGPROBELOC), VERR_SUPDRV_VTG_BAD_HDR);
425 }
426 else
427 {
428 if (pVtgHdr->cBits == 32)
429 MY_VALIDATE_SIZE( pVtgHdr->cbProbeLocs, 1, _8K, sizeof(VTGPROBELOC32), VERR_SUPDRV_VTG_BAD_HDR);
430 else
431 MY_VALIDATE_SIZE( pVtgHdr->cbProbeLocs, 1, _8K, sizeof(VTGPROBELOC64), VERR_SUPDRV_VTG_BAD_HDR);
432 /* Will check later that offProbeLocs are following closely on the
433 enable count array, so no need to validate the offset here. */
434 }
[40612]435
[41117]436 /*
437 * Some additional consistency checks.
438 */
439 if ( pVtgHdr->uProbeLocsEnd.u64 - pVtgHdr->uProbeLocs.u64 != pVtgHdr->cbProbeLocs
440 || (int64_t)(pVtgHdr->uProbeLocs.u64 - uVtgHdrAddr) != pVtgHdr->offProbeLocs)
[40851]441 {
[41117]442 SUPR0Printf("supdrvVtgValidateHdr: VERR_SUPDRV_VTG_BAD_HDR_MISC - uProbeLocs=%#llx uProbeLocsEnd=%#llx offProbeLocs=%#llx cbProbeLocs=%#x uVtgHdrAddr=%RTptr\n",
443 pVtgHdr->uProbeLocs.u64, pVtgHdr->uProbeLocsEnd.u64, pVtgHdr->offProbeLocs, pVtgHdr->cbProbeLocs, uVtgHdrAddr);
444 return VERR_SUPDRV_VTG_BAD_HDR_MISC;
[40851]445 }
[41117]446
447 if (pVtgHdr->cbProbes / sizeof(VTGDESCPROBE) != pVtgHdr->cbProbeEnabled / sizeof(uint32_t))
[40851]448 {
[41117]449 SUPR0Printf("supdrvVtgValidateHdr: VERR_SUPDRV_VTG_BAD_HDR_MISC - cbProbeEnabled=%#zx cbProbes=%#zx\n",
450 pVtgHdr->cbProbeEnabled, pVtgHdr->cbProbes);
451 return VERR_SUPDRV_VTG_BAD_HDR_MISC;
[40851]452 }
[41117]453
454 /*
455 * Check that there are no overlapping areas. This is a little bit ugly...
456 */
457 paAreas = (struct VTGAREAS const *)&pVtgHdr->offStrTab;
458 cAreas = pVtgHdr->offProbeLocs >= 0 ? 6 : 5;
459 off = sizeof(VTGOBJHDR);
460 for (i = 0; i < cAreas; i++)
[40851]461 {
[41117]462 if (paAreas[i].off < off)
463 {
464 SUPR0Printf("supdrvVtgValidateHdr: VERR_SUPDRV_VTG_BAD_HDR_MISC - overlapping areas %d and %d\n", i, i-1);
465 return VERR_SUPDRV_VTG_BAD_HDR_MISC;
466 }
467 off = paAreas[i].off + paAreas[i].cb;
[40851]468 }
[41117]469 if ( pVtgHdr->offProbeLocs > 0
470 && (uint32_t)-pVtgHdr->offProbeLocs < pVtgHdr->cbProbeLocs)
[40851]471 {
[41117]472 SUPR0Printf("supdrvVtgValidateHdr: VERR_SUPDRV_VTG_BAD_HDR_MISC - probe locations overlaps the header\n");
473 return VERR_SUPDRV_VTG_BAD_HDR_MISC;
[40851]474 }
[40601]475
[41117]476 /*
477 * Check that the object size is correct.
478 */
479 if (pVtgHdr->cbObj != pVtgHdr->offProbeEnabled + pVtgHdr->cbProbeEnabled)
[40851]480 {
[41117]481 SUPR0Printf("supdrvVtgValidateHdr: VERR_SUPDRV_VTG_BAD_HDR_MISC - bad header size %#x, expected %#x\n",
482 pVtgHdr->cbObj, pVtgHdr->offProbeEnabled + pVtgHdr->cbProbeEnabled);
483 return VERR_SUPDRV_VTG_BAD_HDR_MISC;
[40851]484 }
[40601]485
[41117]486
487 return VINF_SUCCESS;
488#undef MY_VALIDATE_OFF
489#undef MY_VALIDATE_SIZE
490}
491
492
493/**
494 * Validates the VTG data.
495 *
496 * @returns VBox status code.
497 * @param pVtgHdr The VTG object header of the data to validate.
498 * @param uVtgHdrAddr The address where the header is actually
499 * loaded.
500 * @param pbImage The image base. For validating the probe
501 * locations.
502 * @param cbImage The image size to go with @a pbImage.
503 * @param fUmod Whether this is a user module.
504 */
505static int supdrvVtgValidate(PVTGOBJHDR pVtgHdr, RTUINTPTR uVtgHdrAddr, const uint8_t *pbImage, size_t cbImage, bool fUmod)
506{
507 uintptr_t offTmp;
508 uintptr_t i;
509 uintptr_t cProviders;
510 int rc;
511
512 if (!pbImage || !cbImage)
513 {
514 pbImage = NULL;
515 cbImage = 0;
516 }
517
518#define MY_VALIDATE_STR(a_offStrTab) \
519 do { \
520 if ((a_offStrTab) >= pVtgHdr->cbStrTab) \
521 return VERR_SUPDRV_VTG_STRTAB_OFF; \
522 rc = supdrvVtgValidateString((char *)pVtgHdr + pVtgHdr->offStrTab + (a_offStrTab)); \
523 if (rc != VINF_SUCCESS) \
524 return rc; \
525 } while (0)
526#define MY_VALIDATE_ATTR(Attr) \
527 do { \
528 if ((Attr).u8Code <= (uint8_t)kVTGStability_Invalid || (Attr).u8Code >= (uint8_t)kVTGStability_End) \
529 return VERR_SUPDRV_VTG_BAD_ATTR; \
530 if ((Attr).u8Data <= (uint8_t)kVTGStability_Invalid || (Attr).u8Data >= (uint8_t)kVTGStability_End) \
531 return VERR_SUPDRV_VTG_BAD_ATTR; \
532 if ((Attr).u8DataDep <= (uint8_t)kVTGClass_Invalid || (Attr).u8DataDep >= (uint8_t)kVTGClass_End) \
533 return VERR_SUPDRV_VTG_BAD_ATTR; \
534 } while (0)
535
[40601]536 /*
[41117]537 * The header.
538 */
539 rc = supdrvVtgValidateHdr(pVtgHdr, uVtgHdrAddr, pbImage, cbImage, fUmod);
540 if (RT_FAILURE(rc))
541 return rc;
542
543 /*
[40601]544 * Validate the providers.
545 */
[40602]546 cProviders = i = pVtgHdr->cbProviders / sizeof(VTGDESCPROVIDER);
[40601]547 while (i-- > 0)
[40600]548 {
[41117]549 PCVTGDESCPROVIDER pProvider = (PCVTGDESCPROVIDER)((uintptr_t)pVtgHdr + pVtgHdr->offProviders) + i;
550
551 MY_VALIDATE_STR(pProvider->offName);
552 MY_CHECK_RET(pProvider->iFirstProbe < pVtgHdr->cbProbeEnabled / sizeof(uint32_t), VERR_SUPDRV_VTG_BAD_PROVIDER);
553 MY_CHECK_RET((uint32_t)pProvider->iFirstProbe + pProvider->cProbes <= pVtgHdr->cbProbeEnabled / sizeof(uint32_t),
554 VERR_SUPDRV_VTG_BAD_PROVIDER);
555 MY_VALIDATE_ATTR(pProvider->AttrSelf);
556 MY_VALIDATE_ATTR(pProvider->AttrModules);
557 MY_VALIDATE_ATTR(pProvider->AttrFunctions);
558 MY_VALIDATE_ATTR(pProvider->AttrNames);
559 MY_VALIDATE_ATTR(pProvider->AttrArguments);
560 MY_CHECK_RET(pProvider->bReserved == 0, VERR_SUPDRV_VTG_BAD_PROVIDER);
[58920]561 MY_CHECK_RET(pProvider->cProbesEnabled == 0, VERR_SUPDRV_VTG_BAD_PROVIDER);
[58976]562 MY_CHECK_RET(pProvider->uSettingsSerialNo == 0, VERR_SUPDRV_VTG_BAD_PROVIDER);
[40600]563 }
564
565 /*
[40601]566 * Validate probes.
[40600]567 */
[40601]568 i = pVtgHdr->cbProbes / sizeof(VTGDESCPROBE);
569 while (i-- > 0)
570 {
[41117]571 PCVTGDESCPROBE pProbe = (PCVTGDESCPROBE)( (uintptr_t)pVtgHdr + pVtgHdr->offProbes) + i;
572 PCVTGDESCPROVIDER pProvider = (PCVTGDESCPROVIDER)((uintptr_t)pVtgHdr + pVtgHdr->offProviders) + pProbe->idxProvider;
573 PCVTGDESCARGLIST pArgList = (PCVTGDESCARGLIST)( (uintptr_t)pVtgHdr + pVtgHdr->offArgLists + pProbe->offArgList );
574 unsigned iArg;
575 bool fHaveLargeArgs;
[40602]576
[41117]577
578 MY_VALIDATE_STR(pProbe->offName);
579 MY_CHECK_RET(pProbe->offArgList < pVtgHdr->cbArgLists, VERR_SUPDRV_VTG_BAD_PROBE);
580 MY_CHECK_RET((pProbe->offArgList & 3) == 0, VERR_SUPDRV_VTG_BAD_PROBE);
581 MY_CHECK_RET(pProbe->idxEnabled == i, VERR_SUPDRV_VTG_BAD_PROBE); /* The lists are parallel. */
582 MY_CHECK_RET(pProbe->idxProvider < cProviders, VERR_SUPDRV_VTG_BAD_PROBE);
583 MY_CHECK_RET(i - pProvider->iFirstProbe < pProvider->cProbes, VERR_SUPDRV_VTG_BAD_PROBE);
584 if (pProbe->offObjHdr != (intptr_t)pVtgHdr - (intptr_t)pProbe)
[40892]585 {
[41338]586 SUPR0Printf("supdrvVtgValidate: VERR_SUPDRV_VTG_BAD_PROBE - iProbe=%u offObjHdr=%d expected %zd\n",
[41117]587 i, pProbe->offObjHdr, (intptr_t)pVtgHdr - (intptr_t)pProbe);
[40892]588 return VERR_SUPDRV_VTG_BAD_PROBE;
589 }
[40602]590
591 /* The referenced argument list. */
592 if (pArgList->cArgs > 16)
[40886]593 {
[41338]594 SUPR0Printf("supdrvVtgValidate: VERR_SUPDRV_VTG_BAD_ARGLIST - iProbe=%u cArgs=%u\n", i, pArgList->cArgs);
[40602]595 return VERR_SUPDRV_VTG_BAD_ARGLIST;
[40886]596 }
[40878]597 if (pArgList->fHaveLargeArgs >= 2)
[40886]598 {
[41338]599 SUPR0Printf("supdrvVtgValidate: VERR_SUPDRV_VTG_BAD_ARGLIST - iProbe=%u fHaveLargeArgs=%d\n", i, pArgList->fHaveLargeArgs);
[40878]600 return VERR_SUPDRV_VTG_BAD_ARGLIST;
[40886]601 }
[40602]602 if ( pArgList->abReserved[0]
[40878]603 || pArgList->abReserved[1])
[40886]604 {
[41338]605 SUPR0Printf("supdrvVtgValidate: VERR_SUPDRV_VTG_BAD_ARGLIST - reserved MBZ iProbe=%u\n", i);
[40602]606 return VERR_SUPDRV_VTG_BAD_ARGLIST;
[40886]607 }
[40878]608 fHaveLargeArgs = false;
[40602]609 iArg = pArgList->cArgs;
610 while (iArg-- > 0)
611 {
[40886]612 uint32_t const fType = pArgList->aArgs[iArg].fType;
613 if (fType & ~VTG_TYPE_VALID_MASK)
614 {
615 SUPR0Printf("supdrvVtgValidate: VERR_SUPDRV_TRACER_BAD_ARG_FLAGS - fType=%#x iArg=%u iProbe=%u (#0)\n", fType, iArg, i);
616 return VERR_SUPDRV_TRACER_BAD_ARG_FLAGS;
617 }
618
[40878]619 switch (pArgList->aArgs[iArg].fType & VTG_TYPE_SIZE_MASK)
620 {
621 case 0:
[40880]622 if (pArgList->aArgs[iArg].fType & VTG_TYPE_FIXED_SIZED)
[40886]623 {
624 SUPR0Printf("supdrvVtgValidate: VERR_SUPDRV_TRACER_BAD_ARG_FLAGS - fType=%#x iArg=%u iProbe=%u (#1)\n", fType, iArg, i);
625 return VERR_SUPDRV_TRACER_BAD_ARG_FLAGS;
626 }
[40878]627 break;
628 case 1: case 2: case 4: case 8:
629 break;
630 default:
[40886]631 SUPR0Printf("supdrvVtgValidate: VERR_SUPDRV_TRACER_BAD_ARG_FLAGS - fType=%#x iArg=%u iProbe=%u (#2)\n", fType, iArg, i);
632 return VERR_SUPDRV_TRACER_BAD_ARG_FLAGS;
[40878]633 }
[40886]634 if (VTG_TYPE_IS_LARGE(pArgList->aArgs[iArg].fType))
[40878]635 fHaveLargeArgs = true;
[40886]636
637 MY_VALIDATE_STR(pArgList->aArgs[iArg].offType);
[40602]638 }
[40878]639 if ((uint8_t)fHaveLargeArgs != pArgList->fHaveLargeArgs)
[40881]640 {
[40886]641 SUPR0Printf("supdrvVtgValidate: VERR_SUPDRV_TRACER_BAD_ARG_FLAGS - iProbe=%u fHaveLargeArgs=%d expected %d\n",
642 i, pArgList->fHaveLargeArgs, fHaveLargeArgs);
[40878]643 return VERR_SUPDRV_VTG_BAD_PROBE;
[40881]644 }
[40601]645 }
[40600]646
[40602]647 /*
[41117]648 * Check that pacProbeEnabled is all zeros.
[40602]649 */
[41117]650 {
651 uint32_t const *pcProbeEnabled = (uint32_t const *)((uintptr_t)pVtgHdr + pVtgHdr->offProbeEnabled);
652 i = pVtgHdr->cbProbeEnabled / sizeof(uint32_t);
653 while (i-- > 0)
654 MY_CHECK_RET(pcProbeEnabled[0] == 0, VERR_SUPDRV_VTG_BAD_PROBE_ENABLED);
655 }
[40602]656
657 /*
658 * Probe locations.
659 */
660 {
[41311]661 PVTGPROBELOC paProbeLocs = (PVTGPROBELOC)((intptr_t)pVtgHdr + pVtgHdr->offProbeLocs);
[41117]662 i = pVtgHdr->cbProbeLocs / sizeof(VTGPROBELOC);
663 while (i-- > 0)
664 {
665 MY_CHECK_RET(paProbeLocs[i].uLine < _1G, VERR_SUPDRV_VTG_BAD_PROBE_LOC);
666 MY_CHECK_RET(paProbeLocs[i].fEnabled == false, VERR_SUPDRV_VTG_BAD_PROBE_LOC);
667 MY_CHECK_RET(paProbeLocs[i].idProbe == 0, VERR_SUPDRV_VTG_BAD_PROBE_LOC);
[41130]668 offTmp = (uintptr_t)paProbeLocs[i].pProbe - (uintptr_t)pVtgHdr->offProbes - (uintptr_t)pVtgHdr;
[41311]669#ifdef RT_OS_DARWIN /* See header validation code. */
670 if ( offTmp >= pVtgHdr->cbProbes
671 && pVtgHdr->u64VtgObjSectionStart != uVtgHdrAddr
672 && pVtgHdr->u64VtgObjSectionStart < _4M
673 && (uintptr_t)paProbeLocs[i].pProbe < _4M
674 && !fUmod )
675 {
676 uint64_t offDelta = uVtgHdrAddr - pVtgHdr->u64VtgObjSectionStart;
[44247]677
[41311]678 paProbeLocs[i].pProbe = (PVTGDESCPROBE)((uintptr_t)paProbeLocs[i].pProbe + offDelta);
[44247]679 if ((uintptr_t)paProbeLocs[i].pszFunction < _4M)
680 paProbeLocs[i].pszFunction = (const char *)((uintptr_t)paProbeLocs[i].pszFunction + offDelta);
681
[41311]682 offTmp += offDelta;
683 }
684#endif
[41117]685 MY_CHECK_RET(offTmp < pVtgHdr->cbProbes, VERR_SUPDRV_VTG_BAD_PROBE_LOC);
686 MY_CHECK_RET(offTmp / sizeof(VTGDESCPROBE) * sizeof(VTGDESCPROBE) == offTmp, VERR_SUPDRV_VTG_BAD_PROBE_LOC);
[44247]687 MY_WITHIN_IMAGE(paProbeLocs[i].pszFunction, VERR_SUPDRV_VTG_BAD_PROBE_LOC);
[41117]688 }
[40602]689 }
690
[40600]691 return VINF_SUCCESS;
[41117]692}
693
[40601]694#undef MY_VALIDATE_STR
[41117]695#undef MY_VALIDATE_ATTR
[40601]696#undef MY_WITHIN_IMAGE
[40600]697
698
[40518]699/**
[40602]700 * Gets a string from the string table.
701 *
702 * @returns Pointer to the string.
703 * @param pVtgHdr The VTG object header.
704 * @param offStrTab The string table offset.
705 */
706static const char *supdrvVtgGetString(PVTGOBJHDR pVtgHdr, uint32_t offStrTab)
707{
708 Assert(offStrTab < pVtgHdr->cbStrTab);
[41117]709 return (char *)pVtgHdr + pVtgHdr->offStrTab + offStrTab;
[40602]710}
711
712
713/**
[40756]714 * Frees the provider structure and associated resources.
715 *
[40675]716 * @param pProv The provider to free.
717 */
[40756]718static void supdrvTracerFreeProvider(PSUPDRVTPPROVIDER pProv)
[40675]719{
[40813]720 LOG_TRACER(("Freeing tracepoint provider '%s' / %p\n", pProv->szName, pProv->Core.TracerData.DTrace.idProvider));
[41117]721 pProv->fRegistered = false;
722 pProv->fZombie = true;
723 pProv->Core.pDesc = NULL;
724 pProv->Core.pHdr = NULL;
725 pProv->Core.paProbeLocsRO = NULL;
726 pProv->Core.pvProbeLocsEn = NULL;
727 pProv->Core.pacProbeEnabled = NULL;
728 pProv->Core.paR0ProbeLocs = NULL;
729 pProv->Core.paR0Probes = NULL;
[40756]730 RT_ZERO(pProv->Core.TracerData);
[40675]731 RTMemFree(pProv);
732}
733
734
735/**
[41117]736 * Unlinks and deregisters a provider.
[40756]737 *
[40704]738 * If the provider is still busy, it will be put in the zombie list.
[40756]739 *
[40704]740 * @param pDevExt The device extension.
[40756]741 * @param pProv The provider.
742 *
743 * @remarks The caller owns mtxTracer.
[40704]744 */
[40756]745static void supdrvTracerDeregisterVtgObj(PSUPDRVDEVEXT pDevExt, PSUPDRVTPPROVIDER pProv)
[40704]746{
747 int rc;
[41117]748
749 RTListNodeRemove(&pProv->ListEntry);
750 if (pProv->pSession)
751 {
752 RTListNodeRemove(&pProv->SessionListEntry);
753 RTListInit(&pProv->SessionListEntry);
754 pProv->pSession->cTpProviders--;
755 }
756
[40756]757 if (!pProv->fRegistered || !pDevExt->pTracerOps)
758 rc = VINF_SUCCESS;
759 else
[40777]760 rc = pDevExt->pTracerOps->pfnProviderDeregister(pDevExt->pTracerOps, &pProv->Core);
[40756]761 if (RT_SUCCESS(rc))
[40704]762 {
[40756]763 supdrvTracerFreeProvider(pProv);
[40704]764 return;
765 }
766
[41117]767 pProv->fZombie = true;
768 pProv->pImage = NULL;
769 pProv->pSession = NULL;
770 pProv->pUmod = NULL;
771 pProv->Core.pDesc = NULL;
772 pProv->Core.pHdr = NULL;
773 pProv->Core.paProbeLocsRO = NULL;
774 pProv->Core.pvProbeLocsEn = NULL;
775 pProv->Core.pacProbeEnabled = NULL;
776 pProv->Core.paR0ProbeLocs = NULL;
777
[40756]778 RTListAppend(&pDevExt->TracerProviderZombieList, &pProv->ListEntry);
779 LOG_TRACER(("Invalidated provider '%s' / %p and put it on the zombie list (rc=%Rrc)\n",
780 pProv->szName, pProv->Core.TracerData.DTrace.idProvider, rc));
[40704]781}
782
783
784/**
[40756]785 * Processes the zombie list.
786 *
[40704]787 * @param pDevExt The device extension.
788 */
[40756]789static void supdrvTracerProcessZombies(PSUPDRVDEVEXT pDevExt)
[40704]790{
[40756]791 PSUPDRVTPPROVIDER pProv, pProvNext;
[40704]792
[40756]793 RTSemFastMutexRequest(pDevExt->mtxTracer);
794 RTListForEachSafe(&pDevExt->TracerProviderZombieList, pProv, pProvNext, SUPDRVTPPROVIDER, ListEntry)
[40704]795 {
[40777]796 int rc = pDevExt->pTracerOps->pfnProviderDeregisterZombie(pDevExt->pTracerOps, &pProv->Core);
[40756]797 if (RT_SUCCESS(rc))
[40704]798 {
799 RTListNodeRemove(&pProv->ListEntry);
[40756]800 supdrvTracerFreeProvider(pProv);
[40704]801 }
802 }
[40756]803 RTSemFastMutexRelease(pDevExt->mtxTracer);
[40704]804}
805
806
807/**
[40756]808 * Unregisters all providers, including zombies, waiting for busy providers to
809 * go idle and unregister smoothly.
810 *
811 * This may block.
812 *
813 * @param pDevExt The device extension.
814 */
815static void supdrvTracerRemoveAllProviders(PSUPDRVDEVEXT pDevExt)
816{
817 uint32_t i;
818 PSUPDRVTPPROVIDER pProv;
819 PSUPDRVTPPROVIDER pProvNext;
820
821 /*
822 * Unregister all probes (there should only be one).
823 */
824 RTSemFastMutexRequest(pDevExt->mtxTracer);
825 RTListForEachSafe(&pDevExt->TracerProviderList, pProv, pProvNext, SUPDRVTPPROVIDER, ListEntry)
826 {
827 supdrvTracerDeregisterVtgObj(pDevExt, pProv);
828 }
829 RTSemFastMutexRelease(pDevExt->mtxTracer);
830
831 /*
[40819]832 * Try unregister zombies now, sleep on busy ones and tracer opens.
[40756]833 */
834 for (i = 0; ; i++)
835 {
836 bool fEmpty;
837
838 RTSemFastMutexRequest(pDevExt->mtxTracer);
[40819]839
840 /* Zombies */
[40756]841 RTListForEachSafe(&pDevExt->TracerProviderZombieList, pProv, pProvNext, SUPDRVTPPROVIDER, ListEntry)
842 {
843 int rc;
844 LOG_TRACER(("supdrvTracerRemoveAllProviders: Attemting to unregister '%s' / %p...\n",
845 pProv->szName, pProv->Core.TracerData.DTrace.idProvider));
846
847 if (pDevExt->pTracerOps)
[40777]848 rc = pDevExt->pTracerOps->pfnProviderDeregisterZombie(pDevExt->pTracerOps, &pProv->Core);
[40756]849 else
850 rc = VINF_SUCCESS;
851 if (!rc)
852 {
853 RTListNodeRemove(&pProv->ListEntry);
854 supdrvTracerFreeProvider(pProv);
855 }
856 else if (!(i & 0xf))
857 SUPR0Printf("supdrvTracerRemoveAllProviders: Waiting on busy provider '%s' / %p (rc=%d)\n",
858 pProv->szName, pProv->Core.TracerData.DTrace.idProvider, rc);
859 else
860 LOG_TRACER(("supdrvTracerRemoveAllProviders: Failed to unregister provider '%s' / %p - rc=%d\n",
861 pProv->szName, pProv->Core.TracerData.DTrace.idProvider, rc));
862 }
863
864 fEmpty = RTListIsEmpty(&pDevExt->TracerProviderZombieList);
[40819]865
866 /* Tracer opens. */
867 if ( pDevExt->cTracerOpens
868 && pDevExt->pTracerOps)
869 {
870 fEmpty = false;
871 if (!(i & 0xf))
872 SUPR0Printf("supdrvTracerRemoveAllProviders: Waiting on %u opens\n", pDevExt->cTracerOpens);
873 else
874 LOG_TRACER(("supdrvTracerRemoveAllProviders: Waiting on %u opens\n", pDevExt->cTracerOpens));
875 }
876
[40756]877 RTSemFastMutexRelease(pDevExt->mtxTracer);
[40819]878
[40756]879 if (fEmpty)
880 break;
881
882 /* Delay...*/
883 RTThreadSleep(1000);
884 }
885}
886
887
888/**
[40600]889 * Registers the VTG tracepoint providers of a driver.
[40602]890 *
891 * @returns VBox status code.
[58340]892 * @param pDevExt The device instance data.
[40602]893 * @param pVtgHdr The VTG object header.
894 * @param pImage The image if applicable.
895 * @param pSession The session if applicable.
[41117]896 * @param pUmod The associated user tracepoint module if
897 * applicable.
[40602]898 * @param pszModName The module name.
[40600]899 */
[41117]900static int supdrvTracerRegisterVtgObj(PSUPDRVDEVEXT pDevExt, PVTGOBJHDR pVtgHdr, PSUPDRVLDRIMAGE pImage,
901 PSUPDRVSESSION pSession, PSUPDRVTRACERUMOD pUmod, const char *pszModName)
[40600]902{
[40602]903 int rc;
[40819]904 uintptr_t i;
[40756]905 PSUPDRVTPPROVIDER pProv;
[41117]906 size_t cchModName;
[40602]907
[40600]908 /*
909 * Validate input.
910 */
911 AssertPtrReturn(pDevExt, VERR_INVALID_POINTER);
912 AssertPtrReturn(pVtgHdr, VERR_INVALID_POINTER);
913 AssertPtrNullReturn(pImage, VERR_INVALID_POINTER);
914 AssertPtrNullReturn(pSession, VERR_INVALID_POINTER);
915 AssertPtrReturn(pszModName, VERR_INVALID_POINTER);
[41117]916 cchModName = strlen(pszModName);
[40600]917
[40602]918 if (pImage)
[41117]919 rc = supdrvVtgValidate(pVtgHdr, (uintptr_t)pVtgHdr,
920 (const uint8_t *)pImage->pvImage, pImage->cbImageBits,
921 false /*fUmod*/);
[40602]922 else
[41117]923 rc = supdrvVtgValidate(pVtgHdr, (uintptr_t)pVtgHdr, NULL, 0, pUmod != NULL);
[40602]924 if (RT_FAILURE(rc))
925 return rc;
[40600]926
[41117]927 /*
928 * Check that there aren't any obvious duplicates.
929 * (Yes, this isn't race free, but it's good enough for now.)
930 */
[40756]931 rc = RTSemFastMutexRequest(pDevExt->mtxTracer);
[40704]932 if (RT_FAILURE(rc))
933 return rc;
[41133]934 if (pImage || !pSession || pSession->R0Process == NIL_RTPROCESS)
[40602]935 {
[41117]936 RTListForEach(&pDevExt->TracerProviderList, pProv, SUPDRVTPPROVIDER, ListEntry)
[40602]937 {
[41117]938 if (pProv->Core.pHdr == pVtgHdr)
939 {
940 rc = VERR_SUPDRV_VTG_ALREADY_REGISTERED;
941 break;
942 }
943
944 if ( pProv->pSession == pSession
945 && pProv->pImage == pImage)
946 {
947 rc = VERR_SUPDRV_VTG_ONLY_ONCE_PER_SESSION;
948 break;
949 }
[40602]950 }
[41117]951 }
952 else
953 {
954 RTListForEach(&pSession->TpProviders, pProv, SUPDRVTPPROVIDER, SessionListEntry)
[40704]955 {
[41117]956 if (pProv->Core.pHdr == pVtgHdr)
957 {
958 rc = VERR_SUPDRV_VTG_ALREADY_REGISTERED;
959 break;
960 }
[40704]961 }
[40602]962 }
[40756]963 RTSemFastMutexRelease(pDevExt->mtxTracer);
[40704]964 if (RT_FAILURE(rc))
965 return rc;
[40600]966
967 /*
[40602]968 * Register the providers.
[40600]969 */
[40602]970 i = pVtgHdr->cbProviders / sizeof(VTGDESCPROVIDER);
971 while (i-- > 0)
972 {
[41117]973 PVTGDESCPROVIDER pDesc = (PVTGDESCPROVIDER)((uintptr_t)pVtgHdr + pVtgHdr->offProviders) + i;
[40704]974 const char *pszName = supdrvVtgGetString(pVtgHdr, pDesc->offName);
[41117]975 size_t const cchName = strlen(pszName) + (pUmod ? 16 : 0);
976
[73097]977 pProv = (PSUPDRVTPPROVIDER)RTMemAllocZ(RT_UOFFSETOF_DYN(SUPDRVTPPROVIDER, szName[cchName + 1 + cchModName + 1]));
[40602]978 if (pProv)
979 {
[41117]980 pProv->Core.pszName = &pProv->szName[0];
981 pProv->Core.pszModName = &pProv->szName[cchName + 1];
982 pProv->Core.pDesc = pDesc;
983 pProv->Core.pHdr = pVtgHdr;
984 pProv->Core.paProbeLocsRO = (PCVTGPROBELOC )((uintptr_t)pVtgHdr + pVtgHdr->offProbeLocs);
985 if (!pUmod)
986 {
987 pProv->Core.pvProbeLocsEn = (void *)((uintptr_t)pVtgHdr + pVtgHdr->offProbeLocs);
988 pProv->Core.pacProbeEnabled = (uint32_t *)((uintptr_t)pVtgHdr + pVtgHdr->offProbeEnabled);
989 pProv->Core.paR0ProbeLocs = NULL;
990 pProv->Core.paR0Probes = NULL;
991 pProv->Core.cbProbeLocsEn = sizeof(VTGPROBELOC);
992 pProv->Core.cBits = ARCH_BITS;
993 pProv->Core.fUmod = false;
994 }
995 else
996 {
997 pProv->Core.pvProbeLocsEn = pUmod->pvProbeLocs;
998 pProv->Core.pacProbeEnabled = pUmod->pacProbeEnabled;
999 pProv->Core.paR0ProbeLocs = &pUmod->aProbeLocs[0];
1000 pProv->Core.paR0Probes = (PSUPDRVPROBEINFO)&pUmod->aProbeLocs[pUmod->cProbeLocs];
1001 pProv->Core.cbProbeLocsEn = pUmod->cbProbeLoc;
1002 pProv->Core.cBits = pUmod->cBits;
1003 pProv->Core.fUmod = true;
1004 }
1005 pProv->pImage = pImage;
1006 pProv->pSession = pSession;
1007 pProv->pUmod = pUmod;
1008 pProv->fZombie = false;
1009 pProv->fRegistered = true;
[40600]1010
[41117]1011 if (!pUmod)
[101358]1012 RT_BCOPY_UNFORTIFIED(pProv->szName, pszName, cchName + 1);
[41117]1013 else
1014 RTStrPrintf(pProv->szName, cchName + 1, "%s%u", pszName, (uint32_t)pSession->Process);
[101358]1015 RT_BCOPY_UNFORTIFIED((void *)pProv->Core.pszModName, pszModName, cchModName + 1);
[41117]1016
1017 /*
1018 * Do the actual registration and list manipulations while holding
1019 * down the lock.
1020 */
[40756]1021 rc = RTSemFastMutexRequest(pDevExt->mtxTracer);
1022 if (RT_SUCCESS(rc))
[40602]1023 {
[40812]1024 if ( pDevExt->pTracerOps
1025 && !pDevExt->fTracerUnloading)
[40777]1026 rc = pDevExt->pTracerOps->pfnProviderRegister(pDevExt->pTracerOps, &pProv->Core);
[40756]1027 else
1028 {
1029 pProv->fRegistered = false;
1030 rc = VINF_SUCCESS;
1031 }
[40602]1032 if (RT_SUCCESS(rc))
1033 {
[40756]1034 RTListAppend(&pDevExt->TracerProviderList, &pProv->ListEntry);
[41117]1035 if (pSession)
1036 {
1037 RTListAppend(&pSession->TpProviders, &pProv->SessionListEntry);
1038 pSession->cTpProviders++;
1039 }
1040 else
1041 RTListInit(&pProv->SessionListEntry);
[40756]1042 RTSemFastMutexRelease(pDevExt->mtxTracer);
[40813]1043 LOG_TRACER(("Registered tracepoint provider '%s' in '%s' -> %p\n",
[40756]1044 pProv->szName, pszModName, pProv->Core.TracerData.DTrace.idProvider));
[40602]1045 }
1046 else
[40756]1047 {
1048 RTSemFastMutexRelease(pDevExt->mtxTracer);
[40851]1049 LOG_TRACER(("Failed to register tracepoint provider '%s' in '%s' -> %Rrc\n",
1050 pProv->szName, pszModName, rc));
[40756]1051 }
[40602]1052 }
1053 }
1054 else
1055 rc = VERR_NO_MEMORY;
1056
[41117]1057 /*
1058 * In case of failure, we have to undo any providers we already
1059 * managed to register.
1060 */
[40602]1061 if (RT_FAILURE(rc))
1062 {
[40756]1063 PSUPDRVTPPROVIDER pProvNext;
[40602]1064
[41117]1065 if (pProv)
1066 supdrvTracerFreeProvider(pProv);
1067
[40756]1068 RTSemFastMutexRequest(pDevExt->mtxTracer);
[41117]1069 if (pImage)
[40602]1070 {
[41117]1071 RTListForEachReverseSafe(&pDevExt->TracerProviderList, pProv, pProvNext, SUPDRVTPPROVIDER, ListEntry)
[40602]1072 {
[41117]1073 if (pProv->Core.pHdr == pVtgHdr)
1074 supdrvTracerDeregisterVtgObj(pDevExt, pProv);
[40602]1075 }
1076 }
[41117]1077 else
1078 {
1079 RTListForEachSafe(&pSession->TpProviders, pProv, pProvNext, SUPDRVTPPROVIDER, SessionListEntry)
1080 {
1081 if (pProv->Core.pHdr == pVtgHdr)
1082 supdrvTracerDeregisterVtgObj(pDevExt, pProv);
1083 }
1084 }
[40756]1085 RTSemFastMutexRelease(pDevExt->mtxTracer);
[40602]1086 return rc;
1087 }
1088 }
1089
1090 return VINF_SUCCESS;
[40600]1091}
1092
1093
1094/**
1095 * Registers the VTG tracepoint providers of a driver.
[40602]1096 *
1097 * @returns VBox status code.
1098 * @param pSession The support driver session handle.
[40600]1099 * @param pVtgHdr The VTG header.
1100 * @param pszName The driver name.
1101 */
[40763]1102SUPR0DECL(int) SUPR0TracerRegisterDrv(PSUPDRVSESSION pSession, PVTGOBJHDR pVtgHdr, const char *pszName)
[40600]1103{
[40675]1104 int rc;
1105
[40607]1106 AssertReturn(SUP_IS_SESSION_VALID(pSession), VERR_INVALID_PARAMETER);
[40600]1107 AssertPtrReturn(pszName, VERR_INVALID_POINTER);
1108 AssertPtrReturn(pVtgHdr, VERR_INVALID_POINTER);
[40675]1109 AssertReturn(pSession->R0Process == NIL_RTR0PROCESS, VERR_INVALID_PARAMETER);
[40851]1110 LOG_TRACER(("SUPR0TracerRegisterDrv: pSession=%p pVtgHdr=%p pszName=%s\n", pSession, pVtgHdr, pszName));
[40600]1111
[41117]1112 rc = supdrvTracerRegisterVtgObj(pSession->pDevExt, pVtgHdr, NULL /*pImage*/, pSession, NULL /*pUmod*/, pszName);
[40675]1113
1114 /*
1115 * Try unregister zombies while we have a chance.
1116 */
[40756]1117 supdrvTracerProcessZombies(pSession->pDevExt);
[40675]1118
1119 return rc;
[40600]1120}
[87700]1121SUPR0_EXPORT_SYMBOL(SUPR0TracerRegisterDrv);
[40600]1122
1123
1124/**
1125 * Deregister the VTG tracepoint providers of a driver.
[40602]1126 *
1127 * @param pSession The support driver session handle.
[40600]1128 */
[40763]1129SUPR0DECL(void) SUPR0TracerDeregisterDrv(PSUPDRVSESSION pSession)
[40600]1130{
[40756]1131 PSUPDRVTPPROVIDER pProv, pProvNext;
[40602]1132 PSUPDRVDEVEXT pDevExt;
1133 AssertReturnVoid(SUP_IS_SESSION_VALID(pSession));
[40675]1134 AssertReturnVoid(pSession->R0Process == NIL_RTR0PROCESS);
[40851]1135 LOG_TRACER(("SUPR0TracerDeregisterDrv: pSession=%p\n", pSession));
[40602]1136
1137 pDevExt = pSession->pDevExt;
[40675]1138
1139 /*
1140 * Search for providers belonging to this driver session.
1141 */
[40756]1142 RTSemFastMutexRequest(pDevExt->mtxTracer);
[41117]1143 RTListForEachSafe(&pSession->TpProviders, pProv, pProvNext, SUPDRVTPPROVIDER, SessionListEntry)
[40602]1144 {
[41117]1145 supdrvTracerDeregisterVtgObj(pDevExt, pProv);
[40602]1146 }
[40756]1147 RTSemFastMutexRelease(pDevExt->mtxTracer);
[40675]1148
1149 /*
1150 * Try unregister zombies while we have a chance.
1151 */
[40756]1152 supdrvTracerProcessZombies(pDevExt);
[40600]1153}
[87700]1154SUPR0_EXPORT_SYMBOL(SUPR0TracerDeregisterDrv);
[40600]1155
1156
[40636]1157/**
[40756]1158 * Registers the VTG tracepoint providers of a module loaded by
1159 * the support driver.
1160 *
[40636]1161 * This should be called from the ModuleInit code.
1162 *
1163 * @returns VBox status code.
1164 * @param hMod The module handle.
1165 * @param pVtgHdr The VTG header.
1166 */
[40763]1167SUPR0DECL(int) SUPR0TracerRegisterModule(void *hMod, PVTGOBJHDR pVtgHdr)
[40636]1168{
1169 PSUPDRVLDRIMAGE pImage = (PSUPDRVLDRIMAGE)hMod;
1170 PSUPDRVDEVEXT pDevExt;
[40675]1171 int rc;
[40600]1172
[40812]1173 LOG_TRACER(("SUPR0TracerRegisterModule: %p\n", pVtgHdr));
1174
[40756]1175 /*
[40636]1176 * Validate input and context.
1177 */
1178 AssertPtrReturn(pImage, VERR_INVALID_HANDLE);
1179 AssertPtrReturn(pVtgHdr, VERR_INVALID_POINTER);
1180
[40756]1181 AssertPtrReturn(pImage, VERR_INVALID_POINTER);
[40636]1182 pDevExt = pImage->pDevExt;
1183 AssertPtrReturn(pDevExt, VERR_INVALID_POINTER);
1184 AssertReturn(pDevExt->pLdrInitImage == pImage, VERR_WRONG_ORDER);
1185 AssertReturn(pDevExt->hLdrInitThread == RTThreadNativeSelf(), VERR_WRONG_ORDER);
[41117]1186 AssertReturn((uintptr_t)pVtgHdr - (uintptr_t)pImage->pvImage < pImage->cbImageBits, VERR_INVALID_PARAMETER);
[40636]1187
1188 /*
[41117]1189 * Do the job.
[40636]1190 */
[41117]1191 rc = supdrvTracerRegisterVtgObj(pDevExt, pVtgHdr, pImage, NULL /*pSession*/, NULL /*pUmod*/, pImage->szName);
[40812]1192 LOG_TRACER(("SUPR0TracerRegisterModule: rc=%d\n", rc));
[40675]1193
1194 /*
1195 * Try unregister zombies while we have a chance.
1196 */
[40756]1197 supdrvTracerProcessZombies(pDevExt);
[40675]1198
1199 return rc;
[40636]1200}
[87700]1201SUPR0_EXPORT_SYMBOL(SUPR0TracerRegisterModule);
[40636]1202
1203
[40600]1204/**
[40763]1205 * Registers the tracer implementation.
[40636]1206 *
[40756]1207 * This should be called from the ModuleInit code or from a ring-0 session.
1208 *
1209 * @returns VBox status code.
1210 * @param hMod The module handle.
1211 * @param pSession Ring-0 session handle.
1212 * @param pReg Pointer to the tracer registration structure.
1213 * @param ppHlp Where to return the tracer helper method table.
[40636]1214 */
[40763]1215SUPR0DECL(int) SUPR0TracerRegisterImpl(void *hMod, PSUPDRVSESSION pSession, PCSUPDRVTRACERREG pReg, PCSUPDRVTRACERHLP *ppHlp)
[40636]1216{
[40812]1217 PSUPDRVLDRIMAGE pImage = (PSUPDRVLDRIMAGE)hMod;
1218 PSUPDRVDEVEXT pDevExt;
1219 PSUPDRVTPPROVIDER pProv;
1220 int rc;
[42011]1221 int rc2;
[40636]1222
1223 /*
[40756]1224 * Validate input and context.
[40636]1225 */
[40756]1226 AssertPtrReturn(ppHlp, VERR_INVALID_POINTER);
1227 *ppHlp = NULL;
1228 AssertPtrReturn(pReg, VERR_INVALID_HANDLE);
1229
1230 if (pImage)
[40636]1231 {
[40756]1232 AssertPtrReturn(pImage, VERR_INVALID_POINTER);
1233 AssertReturn(pSession == NULL, VERR_INVALID_PARAMETER);
1234 pDevExt = pImage->pDevExt;
1235 AssertPtrReturn(pDevExt, VERR_INVALID_POINTER);
1236 AssertReturn(pDevExt->pLdrInitImage == pImage, VERR_WRONG_ORDER);
1237 AssertReturn(pDevExt->hLdrInitThread == RTThreadNativeSelf(), VERR_WRONG_ORDER);
[40636]1238 }
[40756]1239 else
1240 {
1241 AssertReturn(SUP_IS_SESSION_VALID(pSession), VERR_INVALID_PARAMETER);
1242 AssertReturn(pSession->R0Process == NIL_RTR0PROCESS, VERR_INVALID_PARAMETER);
1243 pDevExt = pSession->pDevExt;
1244 AssertPtrReturn(pDevExt, VERR_INVALID_POINTER);
1245 }
[40675]1246
[40812]1247 AssertReturn(pReg->u32Magic == SUPDRVTRACERREG_MAGIC, VERR_INVALID_MAGIC);
1248 AssertReturn(pReg->u32Version == SUPDRVTRACERREG_VERSION, VERR_VERSION_MISMATCH);
1249 AssertReturn(pReg->uEndMagic == SUPDRVTRACERREG_MAGIC, VERR_VERSION_MISMATCH);
[40777]1250 AssertPtrReturn(pReg->pfnProbeFireKernel, VERR_INVALID_POINTER);
1251 AssertPtrReturn(pReg->pfnProbeFireUser, VERR_INVALID_POINTER);
1252 AssertPtrReturn(pReg->pfnTracerOpen, VERR_INVALID_POINTER);
1253 AssertPtrReturn(pReg->pfnTracerIoCtl, VERR_INVALID_POINTER);
1254 AssertPtrReturn(pReg->pfnTracerClose, VERR_INVALID_POINTER);
1255 AssertPtrReturn(pReg->pfnProviderRegister, VERR_INVALID_POINTER);
1256 AssertPtrReturn(pReg->pfnProviderDeregister, VERR_INVALID_POINTER);
1257 AssertPtrReturn(pReg->pfnProviderDeregisterZombie, VERR_INVALID_POINTER);
[40636]1258
[40518]1259 /*
[40756]1260 * Do the job.
[40518]1261 */
[40756]1262 rc = RTSemFastMutexRequest(pDevExt->mtxTracer);
[40602]1263 if (RT_SUCCESS(rc))
1264 {
[40756]1265 if (!pDevExt->pTracerOps)
1266 {
[40812]1267 LOG_TRACER(("SUPR0TracerRegisterImpl: pReg=%p\n", pReg));
[40756]1268 pDevExt->pTracerOps = pReg;
1269 pDevExt->pTracerSession = pSession;
1270 pDevExt->pTracerImage = pImage;
1271
[40831]1272 g_pfnSupdrvProbeFireKernel = (PFNRT)pDevExt->pTracerOps->pfnProbeFireKernel;
1273
[40756]1274 *ppHlp = &pDevExt->TracerHlp;
1275 rc = VINF_SUCCESS;
[40812]1276
1277 /*
1278 * Iterate the already loaded modules and register their providers.
1279 */
1280 RTListForEach(&pDevExt->TracerProviderList, pProv, SUPDRVTPPROVIDER, ListEntry)
1281 {
1282 Assert(!pProv->fRegistered);
1283 pProv->fRegistered = true;
[42011]1284 rc2 = pDevExt->pTracerOps->pfnProviderRegister(pDevExt->pTracerOps, &pProv->Core);
[40812]1285 if (RT_FAILURE(rc2))
1286 {
1287 pProv->fRegistered = false;
1288 SUPR0Printf("SUPR0TracerRegisterImpl: Failed to register provider %s::%s - rc=%d\n",
1289 pProv->Core.pszModName, pProv->szName, rc2);
1290 }
1291 }
[40756]1292 }
1293 else
1294 rc = VERR_SUPDRV_TRACER_ALREADY_REGISTERED;
1295 RTSemFastMutexRelease(pDevExt->mtxTracer);
[40602]1296 }
[40756]1297
[40602]1298 return rc;
[40756]1299
[40518]1300}
[87700]1301SUPR0_EXPORT_SYMBOL(SUPR0TracerRegisterImpl);
[40518]1302
1303
1304/**
[40777]1305 * Common tracer implementation deregistration code.
[40600]1306 *
[40777]1307 * The caller sets fTracerUnloading prior to calling this function.
1308 *
1309 * @param pDevExt The device extension structure.
1310 */
1311static void supdrvTracerCommonDeregisterImpl(PSUPDRVDEVEXT pDevExt)
1312{
[40812]1313 uint32_t i;
1314 PSUPDRVTPPROVIDER pProv;
1315 PSUPDRVTPPROVIDER pProvNext;
[40777]1316
1317 RTSemFastMutexRequest(pDevExt->mtxTracer);
[40812]1318
1319 /*
[40831]1320 * Reinstall the stub probe-fire function.
1321 */
1322 g_pfnSupdrvProbeFireKernel = supdrvTracerProbeFireStub;
1323
1324 /*
[40812]1325 * Disassociate the tracer implementation from all providers.
1326 * We will have to wait on busy providers.
1327 */
1328 for (i = 0; ; i++)
1329 {
1330 uint32_t cZombies = 0;
1331
1332 /* Live providers. */
1333 RTListForEachSafe(&pDevExt->TracerProviderList, pProv, pProvNext, SUPDRVTPPROVIDER, ListEntry)
1334 {
1335 int rc;
[40819]1336 LOG_TRACER(("supdrvTracerCommonDeregisterImpl: Attemting to unregister '%s' / %p...\n",
[40812]1337 pProv->szName, pProv->Core.TracerData.DTrace.idProvider));
1338
1339 if (!pProv->fRegistered)
1340 continue;
1341 if (!pProv->fZombie)
1342 {
1343 rc = pDevExt->pTracerOps->pfnProviderDeregister(pDevExt->pTracerOps, &pProv->Core);
1344 if (RT_FAILURE(rc))
1345 pProv->fZombie = true;
1346 }
1347 else
1348 rc = pDevExt->pTracerOps->pfnProviderDeregisterZombie(pDevExt->pTracerOps, &pProv->Core);
1349 if (RT_SUCCESS(rc))
1350 pProv->fZombie = pProv->fRegistered = false;
1351 else
1352 {
1353 cZombies++;
1354 if (!(i & 0xf))
1355 SUPR0Printf("supdrvTracerCommonDeregisterImpl: Waiting on busy provider '%s' / %p (rc=%d)\n",
1356 pProv->szName, pProv->Core.TracerData.DTrace.idProvider, rc);
1357 else
1358 LOG_TRACER(("supdrvTracerCommonDeregisterImpl: Failed to unregister provider '%s' / %p - rc=%d\n",
1359 pProv->szName, pProv->Core.TracerData.DTrace.idProvider, rc));
1360 }
1361 }
1362
1363 /* Zombies providers. */
1364 RTListForEachSafe(&pDevExt->TracerProviderZombieList, pProv, pProvNext, SUPDRVTPPROVIDER, ListEntry)
1365 {
1366 int rc;
[40819]1367 LOG_TRACER(("supdrvTracerCommonDeregisterImpl: Attemting to unregister '%s' / %p (zombie)...\n",
[40812]1368 pProv->szName, pProv->Core.TracerData.DTrace.idProvider));
1369
1370 rc = pDevExt->pTracerOps->pfnProviderDeregisterZombie(pDevExt->pTracerOps, &pProv->Core);
1371 if (RT_SUCCESS(rc))
1372 {
1373 RTListNodeRemove(&pProv->ListEntry);
1374 supdrvTracerFreeProvider(pProv);
1375 }
1376 else
1377 {
1378 cZombies++;
1379 if (!(i & 0xf))
[40819]1380 SUPR0Printf("supdrvTracerCommonDeregisterImpl: Waiting on busy provider '%s' / %p (rc=%d)\n",
[40812]1381 pProv->szName, pProv->Core.TracerData.DTrace.idProvider, rc);
1382 else
[40819]1383 LOG_TRACER(("supdrvTracerCommonDeregisterImpl: Failed to unregister provider '%s' / %p - rc=%d\n",
[40812]1384 pProv->szName, pProv->Core.TracerData.DTrace.idProvider, rc));
1385 }
1386 }
1387
[40819]1388 /* Tracer opens. */
1389 if (pDevExt->cTracerOpens)
1390 {
1391 cZombies++;
1392 if (!(i & 0xf))
1393 SUPR0Printf("supdrvTracerCommonDeregisterImpl: Waiting on %u opens\n", pDevExt->cTracerOpens);
1394 else
1395 LOG_TRACER(("supdrvTracerCommonDeregisterImpl: Waiting on %u opens\n", pDevExt->cTracerOpens));
1396 }
1397
[41117]1398 /* Tracer calls. */
1399 if (pDevExt->cTracerCallers)
1400 {
1401 cZombies++;
1402 if (!(i & 0xf))
1403 SUPR0Printf("supdrvTracerCommonDeregisterImpl: Waiting on %u callers\n", pDevExt->cTracerCallers);
1404 else
1405 LOG_TRACER(("supdrvTracerCommonDeregisterImpl: Waiting on %u callers\n", pDevExt->cTracerCallers));
1406 }
1407
[40819]1408 /* Done? */
[40812]1409 if (cZombies == 0)
1410 break;
1411
1412 /* Delay...*/
1413 RTSemFastMutexRelease(pDevExt->mtxTracer);
1414 RTThreadSleep(1000);
1415 RTSemFastMutexRequest(pDevExt->mtxTracer);
1416 }
1417
1418 /*
1419 * Deregister the tracer implementation.
1420 */
[40777]1421 pDevExt->pTracerImage = NULL;
1422 pDevExt->pTracerSession = NULL;
1423 pDevExt->pTracerOps = NULL;
1424 pDevExt->fTracerUnloading = false;
[40812]1425
[40777]1426 RTSemFastMutexRelease(pDevExt->mtxTracer);
1427}
1428
1429
1430/**
1431 * Deregister a tracer implementation.
1432 *
1433 * This should be called from the ModuleTerm code or from a ring-0 session.
1434 *
[40518]1435 * @returns VBox status code.
[40777]1436 * @param hMod The module handle.
[40756]1437 * @param pSession Ring-0 session handle.
[40518]1438 */
[40777]1439SUPR0DECL(int) SUPR0TracerDeregisterImpl(void *hMod, PSUPDRVSESSION pSession)
[40518]1440{
[40777]1441 PSUPDRVLDRIMAGE pImage = (PSUPDRVLDRIMAGE)hMod;
[40756]1442 PSUPDRVDEVEXT pDevExt;
1443 int rc;
[40602]1444
[40518]1445 /*
[40756]1446 * Validate input and context.
[40518]1447 */
[40777]1448 if (pImage)
1449 {
1450 AssertPtrReturn(pImage, VERR_INVALID_POINTER);
1451 AssertReturn(pSession == NULL, VERR_INVALID_PARAMETER);
1452 pDevExt = pImage->pDevExt;
1453 }
1454 else
1455 {
1456 AssertReturn(SUP_IS_SESSION_VALID(pSession), VERR_INVALID_PARAMETER);
1457 AssertReturn(pSession->R0Process == NIL_RTR0PROCESS, VERR_INVALID_PARAMETER);
1458 pDevExt = pSession->pDevExt;
1459 }
[40756]1460 AssertPtrReturn(pDevExt, VERR_INVALID_POINTER);
[40518]1461
[40675]1462 /*
[40756]1463 * Do the job.
[40675]1464 */
[40756]1465 rc = RTSemFastMutexRequest(pDevExt->mtxTracer);
1466 if (RT_SUCCESS(rc))
[40675]1467 {
[40777]1468 if ( pImage
1469 ? pDevExt->pTracerImage == pImage
1470 : pDevExt->pTracerSession == pSession)
[40675]1471 {
[40812]1472 LOG_TRACER(("SUPR0TracerDeregisterImpl: Unloading ...\n"));
[40756]1473 pDevExt->fTracerUnloading = true;
1474 RTSemFastMutexRelease(pDevExt->mtxTracer);
[40777]1475 supdrvTracerCommonDeregisterImpl(pDevExt);
[40812]1476 LOG_TRACER(("SUPR0TracerDeregisterImpl: ... done.\n"));
[40756]1477 }
1478 else
[40777]1479 {
[40756]1480 rc = VERR_SUPDRV_TRACER_NOT_REGISTERED;
[40777]1481 RTSemFastMutexRelease(pDevExt->mtxTracer);
1482 }
[40602]1483 }
[40675]1484
[40756]1485 return rc;
[40518]1486}
[87700]1487SUPR0_EXPORT_SYMBOL(SUPR0TracerDeregisterImpl);
[40518]1488
1489
[40777]1490/*
1491 * The probe function is a bit more fun since we need tail jump optimizating.
1492 *
1493 * Since we cannot ship yasm sources for linux and freebsd, owing to the cursed
1494 * rebuilding of the kernel module from scratch at install time, we have to
1495 * deploy some ugly gcc inline assembly here.
1496 */
1497#if defined(__GNUC__) && (defined(RT_OS_FREEBSD) || defined(RT_OS_LINUX))
[40798]1498__asm__("\
[40784]1499 .section .text \n\
[40783]1500 \n\
[85606]1501 .p2align 4 \n\
[40784]1502 .global SUPR0TracerFireProbe \n\
[85606]1503 .type SUPR0TracerFireProbe, @function \n\
[40783]1504SUPR0TracerFireProbe: \n\
[40777]1505");
1506# if defined(RT_ARCH_AMD64)
[85606]1507__asm__("\
1508 movq g_pfnSupdrvProbeFireKernel(%rip), %rax \n\
[103723]1509 "
[103726]1510# if defined(RT_OS_LINUX)
1511# if RTLNX_VER_MIN(4,15,10)
[103723]1512 ANNOTATE_RETPOLINE_SAFE
[103726]1513# endif
[103723]1514# endif
1515 " \n\
[48952]1516 jmp *%rax \n\
[40784]1517");
[40777]1518# elif defined(RT_ARCH_X86)
[40798]1519__asm__("\
[85606]1520 movl g_pfnSupdrvProbeFireKernel, %eax \n\
[103723]1521 "
[103726]1522# if defined(RT_OS_LINUX)
1523# if RTLNX_VER_MIN(4,15,10)
[103723]1524 ANNOTATE_RETPOLINE_SAFE
[103726]1525# endif
[103723]1526# endif
1527 " \n\
[48952]1528 jmp *%eax \n\
[40777]1529");
1530# else
1531# error "Which arch is this?"
[40867]1532# endif
[40798]1533__asm__("\
[85606]1534 .size SUPR0TracerFireProbe, . - SUPR0TracerFireProbe \n\
[40783]1535 \n\
[40784]1536 .type supdrvTracerProbeFireStub,@function \n\
1537 .global supdrvTracerProbeFireStub \n\
[40783]1538supdrvTracerProbeFireStub: \n\
[103723]1539 "
[103726]1540# if defined(RT_OS_LINUX)
[103723]1541# if RTLNX_VER_MIN(5,17,0)
1542 ASM_RET "\n\
1543 "
[103726]1544# else /* < 5.17.0 */
[103723]1545 "ret \n\
1546 "
[103726]1547# endif /* < 5.17.0 */
1548# else /* !RT_OS_LINUX */
1549 "ret \n\
1550 "
1551# endif /* !RT_OS_LINUX */
[103723]1552 ".size supdrvTracerProbeFireStub, . - supdrvTracerProbeFireStub \n\
[40783]1553 \n\
[40784]1554 .previous \n\
[40777]1555");
[40819]1556# if 0 /* Slickedit on windows highlighting fix */
1557 )
1558# endif
[40777]1559#endif
[87700]1560SUPR0_EXPORT_SYMBOL(SUPR0TracerFireProbe);
[40777]1561
1562
[40518]1563/**
[40756]1564 * Module unloading hook, called after execution in the module have ceased.
1565 *
1566 * @param pDevExt The device extension structure.
1567 * @param pImage The image being unloaded.
[40518]1568 */
[40756]1569void VBOXCALL supdrvTracerModuleUnloading(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage)
[40518]1570{
[40756]1571 PSUPDRVTPPROVIDER pProv, pProvNext;
1572 AssertPtrReturnVoid(pImage); /* paranoia */
[40602]1573
[40756]1574 RTSemFastMutexRequest(pDevExt->mtxTracer);
[40602]1575
[40756]1576 /*
1577 * If it is the tracer image, we have to unload all the providers.
1578 */
1579 if (pDevExt->pTracerImage == pImage)
1580 {
[40812]1581 LOG_TRACER(("supdrvTracerModuleUnloading: Unloading tracer ...\n"));
[40756]1582 pDevExt->fTracerUnloading = true;
1583 RTSemFastMutexRelease(pDevExt->mtxTracer);
[40777]1584 supdrvTracerCommonDeregisterImpl(pDevExt);
[40812]1585 LOG_TRACER(("supdrvTracerModuleUnloading: ... done.\n"));
[40756]1586 }
1587 else
[40675]1588 {
[40756]1589 /*
1590 * Unregister all providers belonging to this image.
1591 */
1592 RTListForEachSafe(&pDevExt->TracerProviderList, pProv, pProvNext, SUPDRVTPPROVIDER, ListEntry)
[40675]1593 {
[40756]1594 if (pProv->pImage == pImage)
1595 supdrvTracerDeregisterVtgObj(pDevExt, pProv);
[40675]1596 }
[40602]1597
[40756]1598 RTSemFastMutexRelease(pDevExt->mtxTracer);
[40518]1599
[40756]1600 /*
1601 * Try unregister zombies while we have a chance.
1602 */
1603 supdrvTracerProcessZombies(pDevExt);
[40602]1604 }
[40518]1605}
1606
1607
1608/**
[40759]1609 * Called when a session is being cleaned up.
1610 *
1611 * @param pDevExt The device extension structure.
1612 * @param pSession The session that is being torn down.
1613 */
1614void VBOXCALL supdrvTracerCleanupSession(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession)
1615{
1616 /*
[41117]1617 * Deregister all providers.
[40759]1618 */
[41117]1619 SUPDRVTPPROVIDER *pProvNext;
1620 SUPDRVTPPROVIDER *pProv;
1621 RTSemFastMutexRequest(pDevExt->mtxTracer);
1622 RTListForEachSafe(&pSession->TpProviders, pProv, pProvNext, SUPDRVTPPROVIDER, SessionListEntry)
1623 {
1624 supdrvTracerDeregisterVtgObj(pDevExt, pProv);
1625 }
1626 RTSemFastMutexRelease(pDevExt->mtxTracer);
1627
1628 /*
1629 * Clean up instance data the trace may have associated with the session.
1630 */
1631 if (pSession->uTracerData)
1632 supdrvIOCtl_TracerClose(pDevExt, pSession);
1633
1634 /*
1635 * Deregister any tracer implementation.
1636 */
[40759]1637 if (pSession->R0Process == NIL_RTR0PROCESS)
[41117]1638 (void)SUPR0TracerDeregisterImpl(NULL, pSession);
1639
1640 if (pSession->R0Process != NIL_RTR0PROCESS)
[40759]1641 {
[41117]1642 /*
1643 * Free any lingering user modules. We don't bother holding the lock
1644 * here as there shouldn't be anyone messing with the session at this
1645 * point.
1646 */
1647 PSUPDRVTRACERUMOD pUmodNext;
1648 PSUPDRVTRACERUMOD pUmod;
1649 RTListForEachSafe(&pSession->TpUmods, pUmod, pUmodNext, SUPDRVTRACERUMOD, ListEntry)
1650 {
1651 RTR0MemObjFree(pUmod->hMemObjMap, false /*fFreeMappings*/);
1652 RTR0MemObjFree(pUmod->hMemObjLock, false /*fFreeMappings*/);
1653 supdrvVtgReleaseObjectCopy(pDevExt, pUmod->pVtgCopy);
1654 RTMemFree(pUmod);
1655 }
1656 }
1657}
[40759]1658
[41117]1659
1660static void supdrvVtgReleaseObjectCopy(PSUPDRVDEVEXT pDevExt, PSUPDRVVTGCOPY pThis)
1661{
1662 uint32_t cRefs = ASMAtomicDecU32(&pThis->cRefs);
1663 if (!cRefs)
1664 {
[40759]1665 RTSemFastMutexRequest(pDevExt->mtxTracer);
[41117]1666 pThis->u32Magic = ~SUDPRVVTGCOPY_MAGIC;
1667 RTListNodeRemove(&pThis->ListEntry);
1668 RTSemFastMutexRelease(pDevExt->mtxTracer);
1669
1670 RTMemFree(pThis);
1671 }
1672}
1673
1674
1675/**
1676 * Finds a matching VTG object copy, caller owns the lock already.
1677 *
1678 * @returns Copy with reference. NULL if not found.
1679 * @param pHashList The hash list to search.
1680 * @param pHdr The VTG header (valid).
1681 * @param cbStrTab The string table size.
1682 * @param fFlags The user module flags.
1683 */
1684static PSUPDRVVTGCOPY supdrvVtgFindObjectCopyLocked(PRTLISTANCHOR pHashList, PCVTGOBJHDR pHdr, uint32_t cbStrTab, uint32_t fFlags)
1685{
1686 PSUPDRVVTGCOPY pCur;
1687
1688 fFlags &= SUP_TRACER_UMOD_FLAGS_TYPE_MASK;
1689 RTListForEach(pHashList, pCur, SUPDRVVTGCOPY, ListEntry)
1690 {
1691#define HDR_EQUALS(member) pCur->Hdr.member == pHdr->member
1692 if ( HDR_EQUALS(Uuid.au32[0])
1693 && HDR_EQUALS(Uuid.au32[1])
1694 && HDR_EQUALS(Uuid.au32[2])
1695 && HDR_EQUALS(Uuid.au32[3])
1696 && HDR_EQUALS(cbObj)
1697 && HDR_EQUALS(cBits)
1698 && pCur->cbStrTab == cbStrTab
1699 && pCur->fFlags == fFlags
1700 )
[40759]1701 {
[41117]1702 if (RT_LIKELY( HDR_EQUALS(offStrTab)
1703 && HDR_EQUALS(cbStrTab)
1704 && HDR_EQUALS(offArgLists)
1705 && HDR_EQUALS(cbArgLists)
1706 && HDR_EQUALS(offProbes)
1707 && HDR_EQUALS(cbProbes)
1708 && HDR_EQUALS(offProviders)
1709 && HDR_EQUALS(cbProviders)
1710 && HDR_EQUALS(offProbeEnabled)
1711 && HDR_EQUALS(cbProbeEnabled)
1712 && HDR_EQUALS(offProbeLocs)
1713 && HDR_EQUALS(cbProbeLocs)
1714 )
1715 )
[40759]1716 {
[41117]1717 Assert(pCur->cRefs > 0);
1718 Assert(pCur->cRefs < _1M);
1719 pCur->cRefs++;
1720 return pCur;
[40759]1721 }
1722 }
[41117]1723#undef HDR_EQUALS
1724 }
[40759]1725
[41117]1726 return NULL;
1727}
1728
1729
1730/**
1731 * Finds a matching VTG object copy.
1732 *
1733 * @returns Copy with reference. NULL if not found.
1734 * @param pDevExt The device extension.
1735 * @param pHdr The VTG header (valid).
1736 * @param cbStrTab The string table size.
1737 * @param fFlags The user module flags.
1738 */
1739static PSUPDRVVTGCOPY supdrvVtgFindObjectCopy(PSUPDRVDEVEXT pDevExt, PCVTGOBJHDR pHdr, uint32_t cbStrTab, uint32_t fFlags)
1740{
1741 PRTLISTANCHOR pHashList = &pDevExt->aTrackerUmodHash[pHdr->Uuid.au8[3] % RT_ELEMENTS(pDevExt->aTrackerUmodHash)];
1742 PSUPDRVVTGCOPY pRet;
1743
1744 int rc = RTSemFastMutexRequest(pDevExt->mtxTracer);
1745 AssertRCReturn(rc, NULL);
1746
1747 pRet = supdrvVtgFindObjectCopyLocked(pHashList, pHdr, cbStrTab, fFlags);
1748
1749 RTSemFastMutexRelease(pDevExt->mtxTracer);
1750 return pRet;
1751}
1752
1753
1754/**
1755 * Makes a shared copy of the VTG object.
1756 *
1757 * @returns VBox status code.
1758 * @param pDevExt The device extension.
1759 * @param pVtgHdr The VTG header (valid).
1760 * @param R3PtrVtgHdr The ring-3 VTG header address.
1761 * @param uVtgHdrAddr The address of the VTG header in the context
1762 * where it is actually used.
1763 * @param R3PtrStrTab The ring-3 address of the probe location string
1764 * table. The probe location array have offsets
1765 * into this instead of funciton name pointers.
1766 * @param cbStrTab The size of the probe location string table.
1767 * @param fFlags The user module flags.
1768 * @param pUmod The structure we've allocated to track the
1769 * module. This have a valid kernel mapping of the
1770 * probe location array. Upon successful return,
1771 * the pVtgCopy member will hold the address of our
1772 * copy (with a referenced of course).
1773 */
1774static int supdrvVtgCreateObjectCopy(PSUPDRVDEVEXT pDevExt, PCVTGOBJHDR pVtgHdr, RTR3PTR R3PtrVtgHdr, RTUINTPTR uVtgHdrAddr,
1775 RTR3PTR R3PtrStrTab, uint32_t cbStrTab, uint32_t fFlags, PSUPDRVTRACERUMOD pUmod)
1776{
1777 /*
1778 * Calculate the space required, allocate and copy in the data.
1779 */
1780 int rc;
[62665]1781 uint32_t const cProbeLocs = pVtgHdr->cbProbeLocs / (pVtgHdr->cBits == 32 ? sizeof(VTGPROBELOC32) : sizeof(VTGPROBELOC64));
1782 uint32_t const cbProbeLocs = cProbeLocs * sizeof(VTGPROBELOC);
1783 uint32_t const offProbeLocs = RT_ALIGN(pVtgHdr->cbObj, 8);
[41117]1784 size_t const cb = offProbeLocs + cbProbeLocs + cbStrTab + 1;
[73097]1785 PSUPDRVVTGCOPY pThis = (PSUPDRVVTGCOPY)RTMemAlloc(RT_UOFFSETOF(SUPDRVVTGCOPY, Hdr) + cb);
[41117]1786 if (!pThis)
1787 return VERR_NO_MEMORY;
1788
1789 pThis->u32Magic = SUDPRVVTGCOPY_MAGIC;
1790 pThis->cRefs = 1;
1791 pThis->cbStrTab = cbStrTab;
1792 pThis->fFlags = fFlags & SUP_TRACER_UMOD_FLAGS_TYPE_MASK;
1793 RTListInit(&pThis->ListEntry);
1794
1795 rc = RTR0MemUserCopyFrom(&pThis->Hdr, R3PtrVtgHdr, pVtgHdr->cbObj);
1796 if (RT_SUCCESS(rc))
1797 {
1798 char *pchStrTab = (char *)&pThis->Hdr + offProbeLocs + cbProbeLocs;
1799 rc = RTR0MemUserCopyFrom(pchStrTab, R3PtrStrTab, cbStrTab);
1800 if (RT_SUCCESS(rc))
1801 {
1802 PVTGPROBELOC paDst = (PVTGPROBELOC)((char *)&pThis->Hdr + offProbeLocs);
1803 uint32_t i;
1804
1805 /*
1806 * Some paranoia: Overwrite the header with the copy we've already
1807 * validated and zero terminate the string table.
1808 */
1809 pThis->Hdr = *pVtgHdr;
1810 pchStrTab[cbStrTab] = '\0';
1811
1812 /*
1813 * Set the probe location array related header members since we're
1814 * making our own copy in a different location.
1815 */
1816 pThis->Hdr.uProbeLocs.u64 = (uintptr_t)paDst;
1817 pThis->Hdr.uProbeLocsEnd.u64 = (uintptr_t)paDst + cbProbeLocs;
1818 pThis->Hdr.offProbeLocs = offProbeLocs;
1819 pThis->Hdr.cbProbeLocs = cbProbeLocs;
1820 pThis->Hdr.cBits = ARCH_BITS;
1821
1822 /*
[41783]1823 * Copy, convert and fix up the probe location table.
[41117]1824 */
1825 if (pVtgHdr->cBits == 32)
1826 {
1827 uintptr_t const offDelta = (uintptr_t)&pThis->Hdr - uVtgHdrAddr;
1828 PCVTGPROBELOC32 paSrc = (PCVTGPROBELOC32)pUmod->pvProbeLocs;
1829
1830 for (i = 0; i < cProbeLocs; i++)
1831 {
1832 paDst[i].uLine = paSrc[i].uLine;
1833 paDst[i].fEnabled = paSrc[i].fEnabled;
1834 paDst[i].idProbe = paSrc[i].idProbe;
1835 if (paSrc[i].pszFunction > cbStrTab)
1836 {
1837 rc = VERR_SUPDRV_TRACER_UMOD_STRTAB_OFF_BAD;
1838 break;
1839 }
1840 paDst[i].pszFunction = pchStrTab + paSrc[i].pszFunction;
[41130]1841 paDst[i].pProbe = (PVTGDESCPROBE)(uintptr_t)(paSrc[i].pProbe + offDelta);
[41117]1842 }
1843 }
1844 else
1845 {
1846 uint64_t const offDelta = (uintptr_t)&pThis->Hdr - uVtgHdrAddr;
1847 PCVTGPROBELOC64 paSrc = (PCVTGPROBELOC64)pUmod->pvProbeLocs;
1848
1849 for (i = 0; i < cProbeLocs; i++)
1850 {
1851 paDst[i].uLine = paSrc[i].uLine;
1852 paDst[i].fEnabled = paSrc[i].fEnabled;
1853 paDst[i].idProbe = paSrc[i].idProbe;
1854 if (paSrc[i].pszFunction > cbStrTab)
1855 {
1856 rc = VERR_SUPDRV_TRACER_UMOD_STRTAB_OFF_BAD;
1857 break;
1858 }
1859 paDst[i].pszFunction = pchStrTab + (uintptr_t)paSrc[i].pszFunction;
[41130]1860 paDst[i].pProbe = (PVTGDESCPROBE)(uintptr_t)(paSrc[i].pProbe + offDelta);
[41117]1861 }
1862 }
1863
1864 /*
1865 * Validate it
1866 *
1867 * Note! fUmod is false as this is a kernel copy with all native
1868 * structures.
1869 */
1870 if (RT_SUCCESS(rc))
1871 rc = supdrvVtgValidate(&pThis->Hdr, (uintptr_t)&pThis->Hdr, (uint8_t *)&pThis->Hdr, cb, false /*fUmod*/);
1872 if (RT_SUCCESS(rc))
1873 {
1874 /*
1875 * Add it to the hash list, making sure nobody raced us.
1876 */
1877 PRTLISTANCHOR pHashList = &pDevExt->aTrackerUmodHash[ pVtgHdr->Uuid.au8[3]
1878 % RT_ELEMENTS(pDevExt->aTrackerUmodHash)];
1879
1880 rc = RTSemFastMutexRequest(pDevExt->mtxTracer);
1881 if (RT_SUCCESS(rc))
1882 {
1883 pUmod->pVtgCopy = supdrvVtgFindObjectCopyLocked(pHashList, pVtgHdr, cbStrTab, fFlags);
1884 if (!pUmod->pVtgCopy)
1885 {
1886 pUmod->pVtgCopy = pThis;
1887 RTListAppend(pHashList, &pThis->ListEntry);
1888 RTSemFastMutexRelease(pDevExt->mtxTracer);
1889 return rc;
1890 }
1891
1892 /*
1893 * Someone raced us, free our copy and return the existing
1894 * one instead.
1895 */
1896 RTSemFastMutexRelease(pDevExt->mtxTracer);
1897 }
1898 }
1899 }
[40759]1900 }
[41117]1901 RTMemFree(pThis);
1902 return rc;
1903}
[40759]1904
[41117]1905
1906/**
1907 * Undoes what supdrvTracerUmodSetProbeIds did.
1908 *
1909 * @param pDevExt The device extension.
1910 * @param pSession The current session.
1911 * @param pUmod The user tracepoint module.
1912 */
1913static void supdrvTracerUmodClearProbeIds(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, PSUPDRVTRACERUMOD pUmod)
1914{
1915 uint32_t i;
1916
1917 AssertReturnVoid(pUmod->iLookupTable < RT_ELEMENTS(pSession->apTpLookupTable));
1918 AssertReturnVoid(pSession->apTpLookupTable[pUmod->iLookupTable] == pUmod);
1919
[40759]1920 /*
[41117]1921 * Clear the probe IDs and disable the probes.
[40759]1922 */
[41117]1923 i = pUmod->cProbeLocs;
1924 if (pUmod->cBits == 32)
1925 {
1926 PVTGPROBELOC32 paProbeLocs = (PVTGPROBELOC32)pUmod->pvProbeLocs;
1927 while (i-- > 0)
1928 paProbeLocs[i].idProbe = 0;
1929 }
1930 else
1931 {
1932 PVTGPROBELOC64 paProbeLocs = (PVTGPROBELOC64)pUmod->pvProbeLocs;
1933 while (i-- > 0)
1934 paProbeLocs[i].idProbe = 0;
1935 }
1936
1937 /*
1938 * Free the lookup table entry. We'll have to wait for the table to go
1939 * idle to make sure there are no current users of pUmod.
1940 */
1941 RTSemFastMutexRequest(pDevExt->mtxTracer);
1942 if (pSession->apTpLookupTable[pUmod->iLookupTable] == pUmod)
1943 {
1944 if (pSession->cTpProbesFiring > 0)
1945 {
[41135]1946 i = 0;
[41117]1947 while (pSession->cTpProbesFiring > 0)
1948 {
1949 RTSemFastMutexRelease(pDevExt->mtxTracer);
1950 i++;
1951 if (!(i & 0xff))
1952 SUPR0Printf("supdrvTracerUmodClearProbeIds: waiting for lookup table to go idle (i=%u)\n", i);
1953 RTThreadSleep(10);
1954 RTSemFastMutexRequest(pDevExt->mtxTracer);
1955 }
1956 }
1957 ASMAtomicWriteNullPtr(&pSession->apTpLookupTable[pUmod->iLookupTable]);
1958 }
1959 RTSemFastMutexRelease(pDevExt->mtxTracer);
[40759]1960}
1961
1962
[41117]1963/**
1964 * Allocates a lookup table entry for the Umod and sets the
1965 * VTGPROBELOC::idProbe fields in user mode.
1966 *
1967 * @returns VINF_SUCCESS or VERR_SUPDRV_TRACER_TOO_MANY_PROVIDERS.
1968 * @param pDevExt The device extension.
1969 * @param pSession The current session.
1970 * @param pUmod The user tracepoint module.
1971 */
1972static int supdrvTracerUmodSetProbeIds(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, PSUPDRVTRACERUMOD pUmod)
[40981]1973{
[41117]1974 uint32_t iBase;
1975 uint32_t i;
1976
1977 /*
1978 * Allocate a lookup table entry.
1979 */
1980 RTSemFastMutexRequest(pDevExt->mtxTracer);
1981 for (i = 0; i < RT_ELEMENTS(pSession->apTpLookupTable); i++)
1982 {
1983 if (!pSession->apTpLookupTable[i])
1984 {
1985 pSession->apTpLookupTable[i] = pUmod;
1986 pUmod->iLookupTable = i;
1987 break;
1988 }
1989 }
1990 RTSemFastMutexRelease(pDevExt->mtxTracer);
1991 if (i >= RT_ELEMENTS(pSession->apTpLookupTable))
1992 return VERR_SUPDRV_TRACER_TOO_MANY_PROVIDERS;
1993
1994 /*
1995 * Set probe IDs of the usermode probe location to indicate our lookup
1996 * table entry as well as the probe location array entry.
1997 */
1998 iBase = (uint32_t)pUmod->iLookupTable << 24;
1999 i = pUmod->cProbeLocs;
2000 if (pUmod->cBits == 32)
2001 {
2002 PVTGPROBELOC32 paProbeLocs = (PVTGPROBELOC32)pUmod->pvProbeLocs;
2003 while (i-- > 0)
2004 paProbeLocs[i].idProbe = iBase | i;
2005 }
2006 else
2007 {
2008 PVTGPROBELOC64 paProbeLocs = (PVTGPROBELOC64)pUmod->pvProbeLocs;
2009 while (i-- > 0)
2010 paProbeLocs[i].idProbe = iBase | i;
2011 }
2012
2013 return VINF_SUCCESS;
[40981]2014}
2015
[41117]2016
2017int VBOXCALL supdrvIOCtl_TracerUmodRegister(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession,
2018 RTR3PTR R3PtrVtgHdr, RTUINTPTR uVtgHdrAddr,
2019 RTR3PTR R3PtrStrTab, uint32_t cbStrTab,
2020 const char *pszModName, uint32_t fFlags)
[40981]2021{
[41117]2022 VTGOBJHDR Hdr;
2023 PSUPDRVTRACERUMOD pUmod;
2024 RTR3PTR R3PtrLock;
2025 size_t cbLock;
2026 uint32_t cProbeLocs;
2027 int rc;
2028
2029 /*
2030 * Validate input.
2031 */
2032 if (pSession->R0Process == NIL_RTR0PROCESS)
2033 return VERR_INVALID_CONTEXT;
2034 if ( fFlags != SUP_TRACER_UMOD_FLAGS_EXE
2035 && fFlags != SUP_TRACER_UMOD_FLAGS_SHARED)
2036 return VERR_INVALID_PARAMETER;
2037
2038 if (pSession->cTpProviders >= RT_ELEMENTS(pSession->apTpLookupTable))
2039 return VERR_SUPDRV_TRACER_TOO_MANY_PROVIDERS;
2040
2041 if ( cbStrTab < 2
2042 || cbStrTab > _1M)
2043 return VERR_SUPDRV_TRACER_UMOD_STRTAB_TOO_BIG;
2044
2045 /*
2046 * Read the VTG header into a temporary buffer and perform some simple
2047 * validations to make sure we aren't wasting our time here.
2048 */
2049 rc = RTR0MemUserCopyFrom(&Hdr, R3PtrVtgHdr, sizeof(Hdr));
2050 if (RT_FAILURE(rc))
2051 return rc;
2052 rc = supdrvVtgValidateHdr(&Hdr, uVtgHdrAddr, NULL, 0, true /*fUmod*/);
2053 if (RT_FAILURE(rc))
2054 return rc;
2055 if (Hdr.cbProviders / sizeof(VTGDESCPROVIDER) > 2)
2056 return VERR_SUPDRV_TRACER_TOO_MANY_PROVIDERS;
2057
2058 /*
2059 * Check how much needs to be locked down and how many probe locations
2060 * there are.
2061 */
2062 if ( Hdr.offProbeLocs <= 0
2063 || Hdr.offProbeEnabled > (uint32_t)Hdr.offProbeLocs
2064 || (uint32_t)Hdr.offProbeLocs - Hdr.offProbeEnabled - Hdr.cbProbeEnabled > 128)
2065 return VERR_SUPDRV_TRACER_UMOD_NOT_ADJACENT;
2066 R3PtrLock = R3PtrVtgHdr + Hdr.offProbeEnabled;
2067 cbLock = Hdr.offProbeLocs + Hdr.cbProbeLocs - Hdr.offProbeEnabled + (R3PtrLock & PAGE_OFFSET_MASK);
2068 R3PtrLock &= ~(RTR3PTR)PAGE_OFFSET_MASK;
2069 if (cbLock > _64K)
2070 return VERR_SUPDRV_TRACER_UMOD_TOO_MANY_PROBES;
2071
2072 cProbeLocs = Hdr.cbProbeLocs / (Hdr.cBits == 32 ? sizeof(VTGPROBELOC32) : sizeof(VTGPROBELOC64));
2073
2074 /*
2075 * Allocate the tracker data we keep in the session.
2076 */
[73097]2077 pUmod = (PSUPDRVTRACERUMOD)RTMemAllocZ( RT_UOFFSETOF_DYN(SUPDRVTRACERUMOD, aProbeLocs[cProbeLocs])
[41117]2078 + (Hdr.cbProbeEnabled / sizeof(uint32_t) * sizeof(SUPDRVPROBEINFO)) );
2079 if (!pUmod)
2080 return VERR_NO_MEMORY;
2081 pUmod->u32Magic = SUPDRVTRACERUMOD_MAGIC;
2082 RTListInit(&pUmod->ListEntry);
2083 pUmod->R3PtrVtgHdr = R3PtrVtgHdr;
2084 pUmod->pVtgCopy = NULL;
2085 pUmod->hMemObjLock = NIL_RTR0MEMOBJ;
2086 pUmod->hMemObjMap = NIL_RTR0MEMOBJ;
2087 pUmod->R3PtrProbeLocs = (RTR3INTPTR)R3PtrVtgHdr + Hdr.offProbeLocs;
2088 pUmod->iLookupTable = UINT8_MAX;
2089 pUmod->cBits = Hdr.cBits;
2090 pUmod->cbProbeLoc = Hdr.cBits == 32 ? sizeof(VTGPROBELOC32) : sizeof(VTGPROBELOC64);
2091 pUmod->cProbeLocs = cProbeLocs;
2092
2093 /*
2094 * Lock down and map the user-mode structures.
2095 */
2096 rc = RTR0MemObjLockUser(&pUmod->hMemObjLock, R3PtrLock, cbLock, RTMEM_PROT_READ | RTMEM_PROT_WRITE, NIL_RTR0PROCESS);
2097 if (RT_SUCCESS(rc))
2098 {
2099 rc = RTR0MemObjMapKernel(&pUmod->hMemObjMap, pUmod->hMemObjLock, (void *)-1, 0, RTMEM_PROT_READ | RTMEM_PROT_WRITE);
2100 if (RT_SUCCESS(rc))
2101 {
2102 pUmod->pacProbeEnabled = (uint32_t *)( (uintptr_t)RTR0MemObjAddress(pUmod->hMemObjMap)
2103 + ((uintptr_t)(R3PtrVtgHdr + Hdr.offProbeEnabled) & PAGE_OFFSET_MASK));
2104 pUmod->pvProbeLocs = (uint8_t *)pUmod->pacProbeEnabled + Hdr.offProbeLocs - Hdr.offProbeEnabled;
2105
2106 /*
2107 * Does some other process use the same module already? If so,
2108 * share the VTG data with it. Otherwise, make a ring-0 copy it.
2109 */
2110 pUmod->pVtgCopy = supdrvVtgFindObjectCopy(pDevExt, &Hdr, cbStrTab, fFlags);
2111 if (!pUmod->pVtgCopy)
2112 rc = supdrvVtgCreateObjectCopy(pDevExt, &Hdr, R3PtrVtgHdr, uVtgHdrAddr, R3PtrStrTab, cbStrTab, fFlags, pUmod);
2113 if (RT_SUCCESS(rc))
2114 {
2115 AssertPtr(pUmod->pVtgCopy);
2116
2117 /*
2118 * Grabe a place in apTpLookupTable and set the probe IDs
2119 * accordingly.
2120 */
2121 rc = supdrvTracerUmodSetProbeIds(pDevExt, pSession, pUmod);
2122 if (RT_SUCCESS(rc))
2123 {
2124 /*
2125 * Register the providers.
2126 */
2127 rc = supdrvTracerRegisterVtgObj(pDevExt, &pUmod->pVtgCopy->Hdr,
2128 NULL /*pImage*/, pSession, pUmod, pszModName);
2129 if (RT_SUCCESS(rc))
2130 {
2131 RTSemFastMutexRequest(pDevExt->mtxTracer);
2132 RTListAppend(&pSession->TpUmods, &pUmod->ListEntry);
2133 RTSemFastMutexRelease(pDevExt->mtxTracer);
2134
2135 return VINF_SUCCESS;
2136 }
2137
2138 /* bail out. */
2139 supdrvTracerUmodClearProbeIds(pDevExt, pSession, pUmod);
2140 }
2141 supdrvVtgReleaseObjectCopy(pDevExt, pUmod->pVtgCopy);
2142 }
2143 RTR0MemObjFree(pUmod->hMemObjMap, false /*fFreeMappings*/);
2144 }
2145 RTR0MemObjFree(pUmod->hMemObjLock, false /*fFreeMappings*/);
2146 }
2147 pUmod->u32Magic = ~SUPDRVTRACERUMOD_MAGIC;
2148 RTMemFree(pUmod);
2149 return rc;
[40981]2150}
2151
[41117]2152
2153int VBOXCALL supdrvIOCtl_TracerUmodDeregister(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, RTR3PTR R3PtrVtgHdr)
[40981]2154{
[41117]2155 PSUPDRVTRACERUMOD pUmod = NULL;
2156 uint32_t i;
2157 int rc;
[40981]2158
[41117]2159 /*
2160 * Validate the request.
2161 */
2162 RTSemFastMutexRequest(pDevExt->mtxTracer);
2163 for (i = 0; i < RT_ELEMENTS(pSession->apTpLookupTable); i++)
2164 {
2165 pUmod = pSession->apTpLookupTable[i];
2166 if ( pUmod
2167 && pUmod->u32Magic == SUPDRVTRACERUMOD_MAGIC
2168 && pUmod->R3PtrVtgHdr == R3PtrVtgHdr)
2169 break;
2170 }
2171 RTSemFastMutexRelease(pDevExt->mtxTracer);
2172 if (pUmod)
2173 {
2174 SUPDRVTPPROVIDER *pProvNext;
2175 SUPDRVTPPROVIDER *pProv;
2176
2177 /*
2178 * Remove ourselves from the lookup table and clean up the ring-3 bits
2179 * we've dirtied. We do this first to make sure no probes are firing
2180 * when we're destroying the providers in the next step.
2181 */
2182 supdrvTracerUmodClearProbeIds(pDevExt, pSession, pUmod);
2183
2184 /*
2185 * Deregister providers related to the VTG object.
2186 */
2187 RTSemFastMutexRequest(pDevExt->mtxTracer);
2188 RTListForEachSafe(&pSession->TpProviders, pProv, pProvNext, SUPDRVTPPROVIDER, SessionListEntry)
2189 {
2190 if (pProv->pUmod == pUmod)
2191 supdrvTracerDeregisterVtgObj(pDevExt, pProv);
2192 }
2193 RTSemFastMutexRelease(pDevExt->mtxTracer);
2194
2195 /*
2196 * Destroy the Umod object.
2197 */
2198 pUmod->u32Magic = ~SUPDRVTRACERUMOD_MAGIC;
2199 supdrvVtgReleaseObjectCopy(pDevExt, pUmod->pVtgCopy);
2200 RTR0MemObjFree(pUmod->hMemObjMap, false /*fFreeMappings*/);
2201 RTR0MemObjFree(pUmod->hMemObjLock, false /*fFreeMappings*/);
2202 RTMemFree(pUmod);
[44370]2203 rc = VINF_SUCCESS;
[41117]2204 }
2205 else
2206 rc = VERR_NOT_FOUND;
2207 return rc;
[40981]2208}
2209
2210
[40759]2211/**
[41117]2212 * Implementation of supdrvIOCtl_TracerUmodProbeFire and
2213 * SUPR0TracerUmodProbeFire.
2214 *
2215 * @param pDevExt The device extension.
2216 * @param pSession The calling session.
2217 * @param pCtx The context record.
2218 */
2219static void supdrvTracerUmodProbeFire(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, PSUPDRVTRACERUSRCTX pCtx)
2220{
2221 /*
2222 * We cannot trust user mode to hand us the right bits nor not calling us
2223 * when disabled. So, we have to check for our selves.
2224 */
2225 PSUPDRVTRACERUMOD pUmod;
2226 uint32_t const iLookupTable = pCtx->idProbe >> 24;
2227 uint32_t const iProbeLoc = pCtx->idProbe & UINT32_C(0x00ffffff);
2228
2229 if (RT_UNLIKELY( !pDevExt->pTracerOps
2230 || pDevExt->fTracerUnloading))
2231 return;
2232 if (RT_UNLIKELY(iLookupTable >= RT_ELEMENTS(pSession->apTpLookupTable)))
2233 return;
2234 if (RT_UNLIKELY( pCtx->cBits != 32
2235 && pCtx->cBits != 64))
2236 return;
2237
2238 ASMAtomicIncU32(&pSession->cTpProviders);
2239
2240 pUmod = pSession->apTpLookupTable[iLookupTable];
2241 if (RT_LIKELY(pUmod))
2242 {
2243 if (RT_LIKELY( pUmod->u32Magic == SUPDRVTRACERUMOD_MAGIC
2244 && iProbeLoc < pUmod->cProbeLocs
2245 && pCtx->cBits == pUmod->cBits))
2246 {
[41156]2247#if 0 /* This won't work for RC modules. */
[41117]2248 RTR3PTR R3PtrProbeLoc = pUmod->R3PtrProbeLocs + iProbeLoc * pUmod->cbProbeLoc;
2249 if (RT_LIKELY( (pCtx->cBits == 32 ? (RTR3PTR)pCtx->u.X86.uVtgProbeLoc : pCtx->u.Amd64.uVtgProbeLoc)
2250 == R3PtrProbeLoc))
[41156]2251#endif
[41117]2252 {
2253 if (RT_LIKELY(pUmod->aProbeLocs[iProbeLoc].fEnabled))
2254 {
[41130]2255 PSUPDRVVTGCOPY pVtgCopy;
[41117]2256 ASMAtomicIncU32(&pDevExt->cTracerCallers);
[41130]2257 pVtgCopy = pUmod->pVtgCopy;
[41117]2258 if (RT_LIKELY( pDevExt->pTracerOps
[41130]2259 && !pDevExt->fTracerUnloading
2260 && pVtgCopy))
[41117]2261 {
[41130]2262 PCVTGPROBELOC pProbeLocRO;
2263 pProbeLocRO = (PCVTGPROBELOC)((uintptr_t)&pVtgCopy->Hdr + pVtgCopy->Hdr.offProbeLocs) + iProbeLoc;
2264
[41117]2265 pCtx->idProbe = pUmod->aProbeLocs[iProbeLoc].idProbe;
[41130]2266 pDevExt->pTracerOps->pfnProbeFireUser(pDevExt->pTracerOps, pSession, pCtx, &pVtgCopy->Hdr, pProbeLocRO);
[41117]2267 }
2268 ASMAtomicDecU32(&pDevExt->cTracerCallers);
2269 }
2270 }
2271 }
2272 }
2273
2274 ASMAtomicDecU32(&pSession->cTpProviders);
2275}
2276
2277
2278SUPR0DECL(void) SUPR0TracerUmodProbeFire(PSUPDRVSESSION pSession, PSUPDRVTRACERUSRCTX pCtx)
2279{
2280 AssertReturnVoid(SUP_IS_SESSION_VALID(pSession));
2281 AssertPtrReturnVoid(pCtx);
2282
2283 supdrvTracerUmodProbeFire(pSession->pDevExt, pSession, pCtx);
2284}
[87700]2285SUPR0_EXPORT_SYMBOL(SUPR0TracerUmodProbeFire);
[41117]2286
2287
2288void VBOXCALL supdrvIOCtl_TracerUmodProbeFire(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, PSUPDRVTRACERUSRCTX pCtx)
2289{
2290 supdrvTracerUmodProbeFire(pDevExt, pSession, pCtx);
2291}
2292
2293
2294/**
[40819]2295 * Open the tracer.
2296 *
2297 * @returns VBox status code
2298 * @param pDevExt The device extension structure.
2299 * @param pSession The current session.
2300 * @param uCookie The tracer cookie.
2301 * @param uArg The tracer open argument.
2302 */
2303int VBOXCALL supdrvIOCtl_TracerOpen(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, uint32_t uCookie, uintptr_t uArg)
2304{
2305 RTNATIVETHREAD hNativeSelf = RTThreadNativeSelf();
2306 int rc;
2307
2308 RTSemFastMutexRequest(pDevExt->mtxTracer);
2309
2310 if (!pSession->uTracerData)
2311 {
2312 if (pDevExt->pTracerOps)
2313 {
2314 if (pDevExt->pTracerSession != pSession)
2315 {
2316 if (!pDevExt->fTracerUnloading)
2317 {
2318 if (pSession->hTracerCaller == NIL_RTNATIVETHREAD)
2319 {
2320 pDevExt->cTracerOpens++;
2321 pSession->uTracerData = ~(uintptr_t)0;
2322 pSession->hTracerCaller = hNativeSelf;
2323 RTSemFastMutexRelease(pDevExt->mtxTracer);
2324
2325 rc = pDevExt->pTracerOps->pfnTracerOpen(pDevExt->pTracerOps, pSession, uCookie, uArg, &pSession->uTracerData);
2326
2327 RTSemFastMutexRequest(pDevExt->mtxTracer);
2328 if (RT_FAILURE(rc))
2329 {
2330 pDevExt->cTracerOpens--;
2331 pSession->uTracerData = 0;
2332 }
2333 pSession->hTracerCaller = NIL_RTNATIVETHREAD;
2334 }
2335 else
2336 rc = VERR_SUPDRV_TRACER_SESSION_BUSY;
2337 }
2338 else
2339 rc = VERR_SUPDRV_TRACER_UNLOADING;
2340 }
2341 else
2342 rc = VERR_SUPDRV_TRACER_CANNOT_OPEN_SELF;
2343 }
2344 else
2345 rc = VERR_SUPDRV_TRACER_NOT_PRESENT;
2346 }
2347 else
2348 rc = VERR_SUPDRV_TRACER_ALREADY_OPENED;
2349
2350 RTSemFastMutexRelease(pDevExt->mtxTracer);
2351 return rc;
2352}
2353
2354
2355/**
2356 * Closes the tracer.
2357 *
2358 * @returns VBox status code.
2359 * @param pDevExt The device extension structure.
2360 * @param pSession The current session.
2361 */
2362int VBOXCALL supdrvIOCtl_TracerClose(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession)
2363{
2364 RTNATIVETHREAD hNativeSelf = RTThreadNativeSelf();
2365 int rc;
2366
2367 RTSemFastMutexRequest(pDevExt->mtxTracer);
2368
2369 if (pSession->uTracerData)
2370 {
2371 Assert(pDevExt->cTracerOpens > 0);
2372
2373 if (pDevExt->pTracerOps)
2374 {
2375 if (pSession->hTracerCaller == NIL_RTNATIVETHREAD)
2376 {
2377 uintptr_t uTracerData = pSession->uTracerData;
2378 pSession->uTracerData = 0;
2379 pSession->hTracerCaller = hNativeSelf;
2380 RTSemFastMutexRelease(pDevExt->mtxTracer);
2381
2382 pDevExt->pTracerOps->pfnTracerClose(pDevExt->pTracerOps, pSession, uTracerData);
2383 rc = VINF_SUCCESS;
2384
2385 RTSemFastMutexRequest(pDevExt->mtxTracer);
2386 pSession->hTracerCaller = NIL_RTNATIVETHREAD;
2387 Assert(pDevExt->cTracerOpens > 0);
2388 pDevExt->cTracerOpens--;
2389 }
2390 else
2391 rc = VERR_SUPDRV_TRACER_SESSION_BUSY;
2392 }
2393 else
2394 {
2395 rc = VERR_SUPDRV_TRACER_NOT_PRESENT;
2396 pSession->uTracerData = 0;
2397 Assert(pDevExt->cTracerOpens > 0);
2398 pDevExt->cTracerOpens--;
2399 }
2400 }
2401 else
2402 rc = VERR_SUPDRV_TRACER_NOT_OPENED;
2403
2404 RTSemFastMutexRelease(pDevExt->mtxTracer);
2405 return rc;
2406}
2407
2408
2409/**
2410 * Performs a tracer I/O control request.
2411 *
2412 * @returns VBox status code.
2413 * @param pDevExt The device extension structure.
2414 * @param pSession The current session.
2415 * @param uCmd The tracer command.
2416 * @param uArg The tracer argument.
2417 * @param piRetVal Where to store the tracer specific return value.
2418 */
2419int VBOXCALL supdrvIOCtl_TracerIOCtl(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, uintptr_t uCmd, uintptr_t uArg, int32_t *piRetVal)
2420{
2421 RTNATIVETHREAD hNativeSelf = RTThreadNativeSelf();
2422 int rc;
2423
[40823]2424 *piRetVal = 0;
[40819]2425 RTSemFastMutexRequest(pDevExt->mtxTracer);
2426
2427 if (pSession->uTracerData)
2428 {
2429 Assert(pDevExt->cTracerOpens > 0);
2430 if (pDevExt->pTracerOps)
2431 {
2432 if (!pDevExt->fTracerUnloading)
2433 {
2434 if (pSession->hTracerCaller == NIL_RTNATIVETHREAD)
2435 {
2436 uintptr_t uTracerData = pSession->uTracerData;
2437 pDevExt->cTracerOpens++;
2438 pSession->hTracerCaller = hNativeSelf;
2439 RTSemFastMutexRelease(pDevExt->mtxTracer);
2440
2441 rc = pDevExt->pTracerOps->pfnTracerIoCtl(pDevExt->pTracerOps, pSession, uTracerData, uCmd, uArg, piRetVal);
2442
2443 RTSemFastMutexRequest(pDevExt->mtxTracer);
2444 pSession->hTracerCaller = NIL_RTNATIVETHREAD;
2445 Assert(pDevExt->cTracerOpens > 0);
2446 pDevExt->cTracerOpens--;
2447 }
2448 else
2449 rc = VERR_SUPDRV_TRACER_SESSION_BUSY;
2450 }
2451 else
2452 rc = VERR_SUPDRV_TRACER_UNLOADING;
2453 }
2454 else
2455 rc = VERR_SUPDRV_TRACER_NOT_PRESENT;
2456 }
2457 else
2458 rc = VERR_SUPDRV_TRACER_NOT_OPENED;
2459
2460 RTSemFastMutexRelease(pDevExt->mtxTracer);
2461 return rc;
2462}
2463
2464
2465/**
[40756]2466 * Early module initialization hook.
2467 *
2468 * @returns VBox status code.
2469 * @param pDevExt The device extension structure.
[40518]2470 */
[40756]2471int VBOXCALL supdrvTracerInit(PSUPDRVDEVEXT pDevExt)
[40518]2472{
[40756]2473 /*
[40851]2474 * Initialize the tracer.
[40756]2475 */
2476 int rc = RTSemFastMutexCreate(&pDevExt->mtxTracer);
2477 if (RT_SUCCESS(rc))
[40602]2478 {
[41117]2479 uint32_t i;
2480
[40756]2481 pDevExt->TracerHlp.uVersion = SUPDRVTRACERHLP_VERSION;
2482 /** @todo */
2483 pDevExt->TracerHlp.uEndVersion = SUPDRVTRACERHLP_VERSION;
2484 RTListInit(&pDevExt->TracerProviderList);
2485 RTListInit(&pDevExt->TracerProviderZombieList);
[41117]2486 for (i = 0; i < RT_ELEMENTS(pDevExt->aTrackerUmodHash); i++)
2487 RTListInit(&pDevExt->aTrackerUmodHash[i]);
[40759]2488
[40975]2489#ifdef VBOX_WITH_NATIVE_DTRACE
[40851]2490 pDevExt->pTracerOps = supdrvDTraceInit();
[40867]2491 if (pDevExt->pTracerOps)
2492 g_pfnSupdrvProbeFireKernel = (PFNRT)pDevExt->pTracerOps->pfnProbeFireKernel;
[40851]2493#endif
2494
[40867]2495 /*
[40851]2496 * Register the provider for this module, if compiled in.
2497 */
[40777]2498#ifdef VBOX_WITH_DTRACE_R0DRV
[41117]2499 rc = supdrvTracerRegisterVtgObj(pDevExt, &g_VTGObjHeader, NULL /*pImage*/, NULL /*pSession*/, NULL /*pUmod*/, "vboxdrv");
[40756]2500 if (RT_SUCCESS(rc))
2501 return rc;
[40851]2502 SUPR0Printf("supdrvTracerInit: supdrvTracerRegisterVtgObj failed with rc=%d\n", rc);
[40756]2503 RTSemFastMutexDestroy(pDevExt->mtxTracer);
[40851]2504#else
2505
2506 return VINF_SUCCESS;
2507#endif
[40602]2508 }
[40756]2509 pDevExt->mtxTracer = NIL_RTSEMFASTMUTEX;
2510 return rc;
[40518]2511}
2512
2513
2514/**
[40756]2515 * Late module termination hook.
2516 *
2517 * @param pDevExt The device extension structure.
[40518]2518 */
[40756]2519void VBOXCALL supdrvTracerTerm(PSUPDRVDEVEXT pDevExt)
[40518]2520{
[40756]2521 LOG_TRACER(("supdrvTracerTerm\n"));
[40518]2522
[40756]2523 supdrvTracerRemoveAllProviders(pDevExt);
[85766]2524#ifdef VBOX_WITH_NATIVE_DTRACE
2525 supdrvDTraceFini();
2526#endif
[40756]2527 RTSemFastMutexDestroy(pDevExt->mtxTracer);
2528 pDevExt->mtxTracer = NIL_RTSEMFASTMUTEX;
2529 LOG_TRACER(("supdrvTracerTerm: Done\n"));
[40518]2530}
2531
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use