VirtualBox

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

Last change on this file since 103726 was 103726, 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 (build fix), ​bugref:10617.

Make changes specific to Linux only.

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

© 2023 Oracle
ContactPrivacy policyTerms of Use