VirtualBox

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

Last change on this file since 103723 was 103723, checked in by vboxsync, 3 months ago

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

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

© 2023 Oracle
ContactPrivacy policyTerms of Use