VirtualBox

source: vbox/trunk/src/VBox/HostDrivers/Support/SUPDrv-dtrace.cpp@ 40602

Last change on this file since 40602 was 40602, checked in by vboxsync, 13 years ago

SUPDrv-dtrace.cpp: More code.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 28.7 KB
Line 
1/* $Id: SUPDrv-dtrace.cpp 40602 2012-03-24 13:38:46Z vboxsync $ */
2/** @file
3 * VBoxDrv - The VirtualBox Support Driver - DTrace Provider.
4 */
5
6/*
7 * Copyright (C) 2012 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * The contents of this file may alternatively be used under the terms
18 * of the Common Development and Distribution License Version 1.0
19 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
20 * VirtualBox OSE distribution, in which case the provisions of the
21 * CDDL are applicable instead of those of the GPL.
22 *
23 * You may elect to license modified versions of this file under the
24 * terms and conditions of either the GPL or the CDDL or both.
25 */
26
27
28/*******************************************************************************
29* Header Files *
30*******************************************************************************/
31#define LOG_GROUP LOG_GROUP_SUP_DRV
32#include "SUPDrvInternal.h"
33
34#include <VBox/err.h>
35#include <VBox/VBoxTpG.h>
36
37#include <iprt/assert.h>
38#include <iprt/ctype.h>
39#include <iprt/list.h>
40#include <iprt/mem.h>
41#include <iprt/semaphore.h>
42
43#ifdef RT_OS_DARWIN /** @todo figure this! */
44# include "/Developer/SDKs/MacOSX10.6.sdk/usr/include/sys/dtrace.h"
45#else
46# include <sys/dtrace.h>
47#endif
48
49
50/*******************************************************************************
51* Structures and Typedefs *
52*******************************************************************************/
53/**
54 * Data for a provider.
55 */
56typedef struct SUPDRVDTPROVIDER
57{
58 /** The entry in the provider list for this image. */
59 RTLISTNODE ListEntry;
60
61 /** The provider descriptor. */
62 PVTGDESCPROVIDER pDesc;
63 /** The VTG header. */
64 PVTGOBJHDR pHdr;
65
66 /** Pointer to the image this provider resides in. NULL if it's a
67 * driver. */
68 PSUPDRVLDRIMAGE pImage;
69 /** The session this provider is associated with if registered via
70 * SUPR0VtgRegisterDrv. NULL if pImage is set. */
71 PSUPDRVSESSION pSession;
72 /** The module name. */
73 const char *pszModName;
74
75 /** Dtrace provider attributes. */
76 dtrace_pattr_t DtAttrs;
77 /** The ID of this provider. */
78 dtrace_provider_id_t idDtProv;
79} SUPDRVDTPROVIDER;
80/** Pointer to the data for a provider. */
81typedef SUPDRVDTPROVIDER *PSUPDRVDTPROVIDER;
82
83/* Seems there is some return code difference here. Keep the return code and
84 case it to whatever the host desires. */
85#ifdef RT_OS_DARWIN
86typedef void FNPOPS_ENABLE(void *, dtrace_id_t, void *);
87#else
88typedef int FNPOPS_ENABLE(void *, dtrace_id_t, void *);
89#endif
90
91
92/*******************************************************************************
93* Internal Functions *
94*******************************************************************************/
95static void supdrvDTracePOps_Provide(void *pvProv, const dtrace_probedesc_t *pDtProbeDesc);
96static int supdrvDTracePOps_Enable(void *pvProv, dtrace_id_t idProbe, void *pvProbe);
97static void supdrvDTracePOps_Disable(void *pvProv, dtrace_id_t idProbe, void *pvProbe);
98static void supdrvDTracePOps_GetArgDesc(void *pvProv, dtrace_id_t idProbe, void *pvProbe,
99 dtrace_argdesc_t *pArgDesc);
100/*static uint64_t supdrvDTracePOps_GetArgVal(void *pvProv, dtrace_id_t idProbe, void *pvProbe,
101 int iArg, int cFrames);*/
102static void supdrvDTracePOps_Destroy(void *pvProv, dtrace_id_t idProbe, void *pvProbe);
103
104
105
106/*******************************************************************************
107* Global Variables *
108*******************************************************************************/
109/** The default provider attributes. */
110static dtrace_pattr_t g_DefProvAttrs =
111{ /* .dtat_name, .dtat_data, .dtat_class */
112 /* .dtpa_provider = */ { DTRACE_STABILITY_UNSTABLE, DTRACE_STABILITY_UNSTABLE, DTRACE_CLASS_ISA },
113 /* .dtpa_mod = */ { DTRACE_STABILITY_UNSTABLE, DTRACE_STABILITY_UNSTABLE, DTRACE_CLASS_ISA },
114 /* .dtpa_func = */ { DTRACE_STABILITY_UNSTABLE, DTRACE_STABILITY_UNSTABLE, DTRACE_CLASS_ISA },
115 /* .dtpa_name = */ { DTRACE_STABILITY_UNSTABLE, DTRACE_STABILITY_UNSTABLE, DTRACE_CLASS_ISA },
116 /* .dtpa_args = */ { DTRACE_STABILITY_UNSTABLE, DTRACE_STABILITY_UNSTABLE, DTRACE_CLASS_ISA },
117};
118
119/**
120 * DTrace provider method table.
121 */
122static const dtrace_pops_t g_SupDrvDTraceProvOps =
123{
124 /* .dtps_provide = */ supdrvDTracePOps_Provide,
125 /* .dtps_provide_module = */ NULL,
126 /* .dtps_enable = */ (FNPOPS_ENABLE *)supdrvDTracePOps_Enable,
127 /* .dtps_disable = */ supdrvDTracePOps_Disable,
128 /* .dtps_suspend = */ NULL,
129 /* .dtps_resume = */ NULL,
130 /* .dtps_getargdesc = */ supdrvDTracePOps_GetArgDesc,
131 /* .dtps_getargval = */ NULL/*supdrvDTracePOps_GetArgVal*/,
132 /* .dtps_usermode = */ NULL,
133 /* .dtps_destroy = */ supdrvDTracePOps_Destroy
134};
135
136
137#define VERR_SUPDRV_VTG_MAGIC (-3704)
138#define VERR_SUPDRV_VTG_BITS (-3705)
139//#define VERR_SUPDRV_VTG_RESERVED (-3705)
140#define VERR_SUPDRV_VTG_BAD_HDR (-3706)
141#define VERR_SUPDRV_VTG_BAD_HDR_PTR (-3706)
142#define VERR_SUPDRV_VTG_BAD_HDR_TOO_FEW (-3707)
143#define VERR_SUPDRV_VTG_BAD_HDR_TOO_MUCH (-3708)
144#define VERR_SUPDRV_VTG_BAD_HDR_NOT_MULTIPLE (-3709)
145#define VERR_SUPDRV_VTG_STRTAB_OFF (-3709)
146#define VERR_SUPDRV_VTG_BAD_STRING (-1111)
147#define VERR_SUPDRV_VTG_STRING_TOO_LONG (-1111)
148#define VERR_SUPDRV_VTG_BAD_ATTR (-1111)
149#define VERR_SUPDRV_VTG_BAD_PROVIDER (-1111)
150#define VERR_SUPDRV_VTG_BAD_PROBE (-1111)
151#define VERR_SUPDRV_VTG_BAD_ARGLIST (-3709)
152#define VERR_SUPDRV_VTG_BAD_PROBE_ENABLED (-1111)
153#define VERR_SUPDRV_VTG_BAD_PROBE_LOC (-3709)
154#define VERR_SUPDRV_VTG_ALREADY_REGISTERED (-1111)
155#define VERR_SUPDRV_VTG_ONLY_ONCE_PER_SESSION (-1111)
156
157
158static int supdrvVtgValidateString(const char *psz)
159{
160 size_t off = 0;
161 while (off < _4K)
162 {
163 char const ch = psz[off++];
164 if (!ch)
165 return VINF_SUCCESS;
166 if ( !RTLocCIsAlNum(ch)
167 && ch != ' '
168 && ch != '('
169 && ch != ')'
170 && ch != ','
171 && ch != '*'
172 && ch != '&'
173 )
174 return VERR_SUPDRV_VTG_BAD_STRING;
175 }
176 return VERR_SUPDRV_VTG_STRING_TOO_LONG;
177}
178
179/**
180 * Validates the VTG data.
181 *
182 * @returns VBox status code.
183 * @param pVtgHdr The VTG object header of the data to validate.
184 * @param cbVtgObj The size of the VTG object.
185 * @param pbImage The image base. For validating the probe
186 * locations.
187 * @param cbImage The image size to go with @a pbImage.
188 */
189static int supdrvVtgValidate(PVTGOBJHDR pVtgHdr, size_t cbVtgObj, const uint8_t *pbImage, size_t cbImage)
190{
191 uintptr_t cbTmp;
192 uintptr_t offTmp;
193 uintptr_t i;
194 int rc;
195 uint32_t cProviders;
196
197 if (!pbImage || !cbImage)
198 {
199 pbImage = NULL;
200 cbImage = 0;
201 }
202
203#define MY_VALIDATE_PTR(p, cb, cMin, cMax, cbUnit, rcBase) \
204 do { \
205 if ( (cb) >= cbVtgObj \
206 || (uintptr_t)(p) - (uintptr_t)pVtgHdr < cbVtgObj - (cb) ) \
207 return rcBase ## _PTR; \
208 if ((cb) < (cMin) * (cbUnit)) \
209 return rcBase ## _TOO_FEW; \
210 if ((cb) >= (cMax) * (cbUnit)) \
211 return rcBase ## _TOO_MUCH; \
212 if ((cb) / (cbUnit) * (cbUnit) != (cb)) \
213 return rcBase ## _NOT_MULTIPLE; \
214 } while (0)
215#define MY_WITHIN_IMAGE(p, rc) \
216 do { \
217 if (pbImage) \
218 { \
219 if ((uintptr_t)(p) - (uintptr_t)pbImage > cbImage) \
220 return (rc); \
221 } \
222 else if (!RT_VALID_PTR(p)) \
223 return (rc); \
224 } while (0)
225#define MY_VALIDATE_STR(offStrTab) \
226 do { \
227 if ((offStrTab) >= pVtgHdr->cbStrTab) \
228 return VERR_SUPDRV_VTG_STRTAB_OFF; \
229 rc = supdrvVtgValidateString(pVtgHdr->pachStrTab + (offStrTab)); \
230 if (rc != VINF_SUCCESS) \
231 return rc; \
232 } while (0)
233#define MY_VALIDATE_ATTR(Attr) \
234 do { \
235 if ((Attr).u8Code <= (uint8_t)kVTGStability_Invalid || (Attr).u8Code >= (uint8_t)kVTGStability_End) \
236 return VERR_SUPDRV_VTG_BAD_ATTR; \
237 if ((Attr).u8Data <= (uint8_t)kVTGStability_Invalid || (Attr).u8Data >= (uint8_t)kVTGStability_End) \
238 return VERR_SUPDRV_VTG_BAD_ATTR; \
239 if ((Attr).u8DataDep <= (uint8_t)kVTGClass_Invalid || (Attr).u8DataDep >= (uint8_t)kVTGClass_End) \
240 return VERR_SUPDRV_VTG_BAD_ATTR; \
241 } while (0)
242
243 /*
244 * The header.
245 */
246 if (!memcmp(pVtgHdr->szMagic, VTGOBJHDR_MAGIC, sizeof(pVtgHdr->szMagic)))
247 return VERR_SUPDRV_VTG_MAGIC;
248 if (pVtgHdr->cBits != ARCH_BITS)
249 return VERR_SUPDRV_VTG_BITS;
250 if (pVtgHdr->u32Reserved0)
251 return VERR_SUPDRV_VTG_BAD_HDR;
252
253 MY_VALIDATE_PTR(pVtgHdr->paProviders, pVtgHdr->cbProviders, 1, 16, sizeof(VTGDESCPROVIDER), VERR_SUPDRV_VTG_BAD_HDR);
254 MY_VALIDATE_PTR(pVtgHdr->paProbes, pVtgHdr->cbProbes, 1, _32K, sizeof(VTGDESCPROBE), VERR_SUPDRV_VTG_BAD_HDR);
255 MY_VALIDATE_PTR(pVtgHdr->pafProbeEnabled, pVtgHdr->cbProbeEnabled, 1, _32K, sizeof(bool), VERR_SUPDRV_VTG_BAD_HDR);
256 MY_VALIDATE_PTR(pVtgHdr->pachStrTab, pVtgHdr->cbStrTab, 4, _1M, sizeof(char), VERR_SUPDRV_VTG_BAD_HDR);
257 MY_VALIDATE_PTR(pVtgHdr->paArgLists, pVtgHdr->cbArgLists, 1, _32K, sizeof(uint32_t), VERR_SUPDRV_VTG_BAD_HDR);
258 MY_WITHIN_IMAGE(pVtgHdr->paProbLocs, VERR_SUPDRV_VTG_BAD_HDR_PTR);
259 MY_WITHIN_IMAGE(pVtgHdr->paProbLocsEnd, VERR_SUPDRV_VTG_BAD_HDR_PTR);
260 if ((uintptr_t)pVtgHdr->paProbLocs > (uintptr_t)pVtgHdr->paProbLocsEnd)
261 return VERR_SUPDRV_VTG_BAD_HDR_PTR;
262 cbTmp = (uintptr_t)pVtgHdr->paProbLocsEnd - (uintptr_t)pVtgHdr->paProbLocs;
263 MY_VALIDATE_PTR(pVtgHdr->paProbLocs, cbTmp, 1, _128K, sizeof(VTGPROBELOC), VERR_SUPDRV_VTG_BAD_HDR);
264 if (cbTmp < sizeof(VTGPROBELOC))
265 return VERR_SUPDRV_VTG_BAD_HDR_TOO_FEW;
266
267 if (pVtgHdr->cbProbes / sizeof(VTGDESCPROBE) != pVtgHdr->cbProbeEnabled)
268 return VERR_SUPDRV_VTG_BAD_HDR;
269
270 /*
271 * Validate the providers.
272 */
273 cProviders = i = pVtgHdr->cbProviders / sizeof(VTGDESCPROVIDER);
274 while (i-- > 0)
275 {
276 MY_VALIDATE_STR(pVtgHdr->paProviders[i].offName);
277 if (pVtgHdr->paProviders[i].iFirstProbe >= pVtgHdr->cbProbeEnabled)
278 return VERR_SUPDRV_VTG_BAD_PROVIDER;
279 if (pVtgHdr->paProviders[i].iFirstProbe + pVtgHdr->paProviders[i].cProbes > pVtgHdr->cbProbeEnabled)
280 return VERR_SUPDRV_VTG_BAD_PROVIDER;
281 MY_VALIDATE_ATTR(pVtgHdr->paProviders[i].AttrSelf);
282 MY_VALIDATE_ATTR(pVtgHdr->paProviders[i].AttrModules);
283 MY_VALIDATE_ATTR(pVtgHdr->paProviders[i].AttrFunctions);
284 MY_VALIDATE_ATTR(pVtgHdr->paProviders[i].AttrNames);
285 MY_VALIDATE_ATTR(pVtgHdr->paProviders[i].AttrArguments);
286 if (pVtgHdr->paProviders[i].bReserved)
287 return VERR_SUPDRV_VTG_BAD_PROVIDER;
288 }
289
290 /*
291 * Validate probes.
292 */
293 i = pVtgHdr->cbProbes / sizeof(VTGDESCPROBE);
294 while (i-- > 0)
295 {
296 PVTGDESCARGLIST pArgList;
297 unsigned iArg;
298
299 MY_VALIDATE_STR(pVtgHdr->paProbes[i].offName);
300 if (pVtgHdr->paProbes[i].offArgList >= pVtgHdr->cbArgLists)
301 return VERR_SUPDRV_VTG_BAD_PROBE;
302 if (pVtgHdr->paProbes[i].offArgList & 3)
303 return VERR_SUPDRV_VTG_BAD_PROBE;
304 if (pVtgHdr->paProbes[i].idxEnabled != i) /* The lists are parallel. */
305 return VERR_SUPDRV_VTG_BAD_PROBE;
306 if (pVtgHdr->paProbes[i].idxProvider >= cProviders)
307 return VERR_SUPDRV_VTG_BAD_PROBE;
308 if ( i - pVtgHdr->paProviders[pVtgHdr->paProbes[i].idxProvider].iFirstProbe
309 < pVtgHdr->paProviders[pVtgHdr->paProbes[i].idxProvider].cProbes)
310 return VERR_SUPDRV_VTG_BAD_PROBE;
311 if (pVtgHdr->paProbes[i].u32User)
312 return VERR_SUPDRV_VTG_BAD_PROBE;
313
314 /* The referenced argument list. */
315 pArgList = (PVTGDESCARGLIST)((uintptr_t)pVtgHdr->paArgLists + pVtgHdr->paProbes[i].offArgList);
316 if (pArgList->cArgs > 16)
317 return VERR_SUPDRV_VTG_BAD_ARGLIST;
318 if ( pArgList->abReserved[0]
319 || pArgList->abReserved[1]
320 || pArgList->abReserved[2])
321 return VERR_SUPDRV_VTG_BAD_ARGLIST;
322 iArg = pArgList->cArgs;
323 while (iArg-- > 0)
324 {
325 MY_VALIDATE_STR(pArgList->aArgs[iArg].offType);
326 MY_VALIDATE_STR(pArgList->aArgs[iArg].offName);
327 }
328 }
329
330 /*
331 * Check that pafProbeEnabled is all zero.
332 */
333 i = pVtgHdr->cbProbeEnabled;
334 while (i-- > 0)
335 if (pVtgHdr->pafProbeEnabled[0])
336 return VERR_SUPDRV_VTG_BAD_PROBE_ENABLED;
337
338 /*
339 * Probe locations.
340 */
341 i = pVtgHdr->paProbLocsEnd - pVtgHdr->paProbLocs;
342 while (i-- > 0)
343 {
344 if (pVtgHdr->paProbLocs[i].uLine >= _1G)
345 return VERR_SUPDRV_VTG_BAD_PROBE_LOC;
346 if (pVtgHdr->paProbLocs[i].fEnabled)
347 return VERR_SUPDRV_VTG_BAD_PROBE_LOC;
348 if (pVtgHdr->paProbLocs[i].idProbe != UINT32_MAX)
349 return VERR_SUPDRV_VTG_BAD_PROBE_LOC;
350 MY_WITHIN_IMAGE(pVtgHdr->paProbLocs[i].pszFunction, VERR_SUPDRV_VTG_BAD_PROBE_LOC);
351 MY_WITHIN_IMAGE(pVtgHdr->paProbLocs[i].pszFile, VERR_SUPDRV_VTG_BAD_PROBE_LOC);
352 offTmp = (uintptr_t)pVtgHdr->paProbLocs[i].pbProbe - (uintptr_t)pVtgHdr->paProbes;
353 if (offTmp >= pVtgHdr->cbProbes)
354 return VERR_SUPDRV_VTG_BAD_PROBE_LOC;
355 if (offTmp / sizeof(VTGDESCPROBE) * sizeof(VTGDESCPROBE) != offTmp)
356 return VERR_SUPDRV_VTG_BAD_PROBE_LOC;
357 }
358
359 return VINF_SUCCESS;
360#undef MY_VALIDATE_STR
361#undef MY_VALIDATE_PTR
362#undef MY_WITHIN_IMAGE
363}
364
365
366/**
367 * Converts an attribute from VTG description speak to DTrace.
368 *
369 * @param pDtAttr The DTrace attribute (dst).
370 * @param pVtgAttr The VTG attribute descriptor (src).
371 */
372static void supdrvVtgConvAttr(dtrace_attribute_t *pDtAttr, PCVTGDESCATTR pVtgAttr)
373{
374 pDtAttr->dtat_name = pVtgAttr->u8Code - 1;
375 pDtAttr->dtat_data = pVtgAttr->u8Data - 1;
376 pDtAttr->dtat_class = pVtgAttr->u8DataDep - 1;
377}
378
379/**
380 * Gets a string from the string table.
381 *
382 * @returns Pointer to the string.
383 * @param pVtgHdr The VTG object header.
384 * @param offStrTab The string table offset.
385 */
386static const char *supdrvVtgGetString(PVTGOBJHDR pVtgHdr, uint32_t offStrTab)
387{
388 Assert(offStrTab < pVtgHdr->cbStrTab);
389 return &pVtgHdr->pachStrTab[offStrTab];
390}
391
392
393/**
394 * Registers the VTG tracepoint providers of a driver.
395 *
396 * @returns VBox status code.
397 * @param pszName The driver name.
398 * @param pVtgHdr The VTG object header.
399 * @param pVtgObj The size of the VTG object.
400 * @param pImage The image if applicable.
401 * @param pSession The session if applicable.
402 * @param pszModName The module name.
403 */
404static int supdrvVtgRegister(PSUPDRVDEVEXT pDevExt, PVTGOBJHDR pVtgHdr, size_t cbVtgObj, PSUPDRVLDRIMAGE pImage, PSUPDRVSESSION pSession,
405 const char *pszModName)
406{
407 int rc;
408 unsigned i;
409 PSUPDRVDTPROVIDER pProv;
410
411 /*
412 * Validate input.
413 */
414 AssertPtrReturn(pDevExt, VERR_INVALID_POINTER);
415 AssertPtrReturn(pVtgHdr, VERR_INVALID_POINTER);
416 AssertPtrNullReturn(pImage, VERR_INVALID_POINTER);
417 AssertPtrNullReturn(pSession, VERR_INVALID_POINTER);
418 AssertPtrReturn(pszModName, VERR_INVALID_POINTER);
419
420 if (pImage)
421 rc = supdrvVtgValidate(pVtgHdr, cbVtgObj, (const uint8_t *)pImage->pvImage, pImage->cbImageBits);
422 else
423 rc = supdrvVtgValidate(pVtgHdr, cbVtgObj, NULL, 0);
424 if (RT_FAILURE(rc))
425 return rc;
426
427 rc = RTSemFastMutexRequest(pDevExt->mtxDTrace);
428 if (RT_SUCCESS(rc))
429 {
430 RTListForEach(&pDevExt->DtProviderList, pProv, SUPDRVDTPROVIDER, ListEntry)
431 {
432 if (pProv->pHdr == pVtgHdr)
433 {
434 RTSemFastMutexRelease(pDevExt->mtxDTrace);
435 return VERR_SUPDRV_VTG_ALREADY_REGISTERED;
436 }
437 if (pProv->pSession == pSession && !pProv->pImage)
438 {
439 RTSemFastMutexRelease(pDevExt->mtxDTrace);
440 return VERR_SUPDRV_VTG_ONLY_ONCE_PER_SESSION;
441 }
442 }
443 RTSemFastMutexRelease(pDevExt->mtxDTrace);
444 }
445
446 /*
447 * Register the providers.
448 */
449 i = pVtgHdr->cbProviders / sizeof(VTGDESCPROVIDER);
450 while (i-- > 0)
451 {
452 PVTGDESCPROVIDER pDesc = &pVtgHdr->paProviders[i];
453 pProv = (PSUPDRVDTPROVIDER)RTMemAllocZ(sizeof(*pProv));
454 if (pProv)
455 {
456 pProv->pDesc = pDesc;
457 pProv->pHdr = pVtgHdr;
458 pProv->pImage = pImage;
459 pProv->pSession = pSession;
460 pProv->pszModName = pszModName;
461 pProv->idDtProv = 0;
462 supdrvVtgConvAttr(&pProv->DtAttrs.dtpa_provider, &pDesc->AttrSelf);
463 supdrvVtgConvAttr(&pProv->DtAttrs.dtpa_mod, &pDesc->AttrModules);
464 supdrvVtgConvAttr(&pProv->DtAttrs.dtpa_func, &pDesc->AttrFunctions);
465 supdrvVtgConvAttr(&pProv->DtAttrs.dtpa_name, &pDesc->AttrNames);
466 supdrvVtgConvAttr(&pProv->DtAttrs.dtpa_args, &pDesc->AttrArguments);
467
468 rc = dtrace_register(supdrvVtgGetString(pVtgHdr, pDesc->offName),
469 &pProv->DtAttrs,
470 DTRACE_PRIV_KERNEL,
471 NULL /* cred */,
472 &g_SupDrvDTraceProvOps,
473 pProv,
474 &pProv->idDtProv);
475 if (!rc)
476 {
477 rc = RTSemFastMutexRequest(pDevExt->mtxDTrace);
478 if (RT_SUCCESS(rc))
479 {
480 RTListAppend(&pDevExt->DtProviderList, &pProv->ListEntry);
481 RTSemFastMutexRelease(pDevExt->mtxDTrace);
482 }
483 else
484 dtrace_unregister(pProv->idDtProv);
485 }
486 else
487 rc = RTErrConvertFromErrno(rc);
488 }
489 else
490 rc = VERR_NO_MEMORY;
491
492 if (RT_FAILURE(rc))
493 {
494 PSUPDRVDTPROVIDER pProvNext;
495 RTMemFree(pProv);
496
497 RTSemFastMutexRequest(pDevExt->mtxDTrace);
498 RTListForEachReverseSafe(&pDevExt->DtProviderList, pProv, pProvNext, SUPDRVDTPROVIDER, ListEntry)
499 {
500 if (pProv->pHdr == pVtgHdr)
501 {
502 RTListNodeRemove(&pProv->ListEntry);
503 RTSemFastMutexRelease(pDevExt->mtxDTrace);
504
505 dtrace_unregister(pProv->idDtProv);
506 RTMemFree(pProv);
507
508 RTSemFastMutexRequest(pDevExt->mtxDTrace);
509 }
510 }
511 RTSemFastMutexRelease(pDevExt->mtxDTrace);
512 return rc;
513 }
514 }
515
516 return VINF_SUCCESS;
517}
518
519
520
521/**
522 * Registers the VTG tracepoint providers of a driver.
523 *
524 * @returns VBox status code.
525 * @param pSession The support driver session handle.
526 * @param pVtgHdr The VTG header.
527 * @param pszName The driver name.
528 */
529SUPR0DECL(int) SUPR0VtgRegisterDrv(PSUPDRVSESSION pSession, PVTGOBJHDR pVtgHdr, const char *pszName)
530{
531 AssertReturn(SUP_IS_SESSION_VALID(pSession), NULL);
532 AssertPtrReturn(pszName, VERR_INVALID_POINTER);
533 AssertPtrReturn(pVtgHdr, VERR_INVALID_POINTER);
534
535 return supdrvVtgRegister(pSession->pDevExt, pVtgHdr, _1M, NULL /*pImage*/, pSession, pszName);
536}
537
538
539
540/**
541 * Deregister the VTG tracepoint providers of a driver.
542 *
543 * @param pSession The support driver session handle.
544 * @param pVtgHdr The VTG header.
545 */
546SUPR0DECL(void) SUPR0VtgDeregisterDrv(PSUPDRVSESSION pSession)
547{
548 PSUPDRVDTPROVIDER pProv, pProvNext;
549 PSUPDRVDEVEXT pDevExt;
550 AssertReturnVoid(SUP_IS_SESSION_VALID(pSession));
551
552 pDevExt = pSession->pDevExt;
553 RTSemFastMutexRequest(pDevExt->mtxDTrace);
554 RTListForEachSafe(&pDevExt->DtProviderList, pProv, pProvNext, SUPDRVDTPROVIDER, ListEntry)
555 {
556 if (pProv->pSession == pSession)
557 {
558 RTListNodeRemove(&pProv->ListEntry);
559 RTSemFastMutexRelease(pDevExt->mtxDTrace);
560
561 dtrace_unregister(pProv->idDtProv);
562 RTMemFree(pProv);
563
564 RTSemFastMutexRequest(pDevExt->mtxDTrace);
565 }
566 }
567 RTSemFastMutexRelease(pDevExt->mtxDTrace);
568}
569
570
571
572/**
573 * Early module initialization hook.
574 *
575 * @returns VBox status code.
576 * @param pDevExt The device extension structure.
577 */
578int supdrvDTraceInit(PSUPDRVDEVEXT pDevExt)
579{
580 /*
581 * Register a provider for this module.
582 */
583 int rc = RTSemFastMutexCreate(&pDevExt->mtxDTrace);
584 if (RT_SUCCESS(rc))
585 {
586 RTListInit(&pDevExt->DtProviderList);
587 rc = supdrvVtgRegister(pDevExt, &g_VTGObjHeader, _1M, NULL /*pImage*/, NULL /*pSession*/, "vboxdrv");
588 if (RT_SUCCESS(rc))
589 return rc;
590 RTSemFastMutexDestroy(pDevExt->mtxDTrace);
591 }
592 pDevExt->mtxDTrace = NIL_RTSEMFASTMUTEX;
593 return rc;
594}
595
596
597/**
598 * Late module termination hook.
599 *
600 * @returns VBox status code.
601 * @param pDevExt The device extension structure.
602 */
603int supdrvDTraceTerm(PSUPDRVDEVEXT pDevExt)
604{
605 PSUPDRVDTPROVIDER pProv, pProvNext;
606
607 /*
608 * Unregister all probes (there should only be one).
609 */
610 RTSemFastMutexRequest(pDevExt->mtxDTrace);
611 RTListForEachSafe(&pDevExt->DtProviderList, pProv, pProvNext, SUPDRVDTPROVIDER, ListEntry)
612 {
613 RTListNodeRemove(&pProv->ListEntry);
614 RTSemFastMutexRelease(pDevExt->mtxDTrace);
615
616 dtrace_unregister(pProv->idDtProv);
617 RTMemFree(pProv);
618
619 RTSemFastMutexRequest(pDevExt->mtxDTrace);
620 }
621 RTSemFastMutexRelease(pDevExt->mtxDTrace);
622 RTSemFastMutexDestroy(pDevExt->mtxDTrace);
623 pDevExt->mtxDTrace = NIL_RTSEMFASTMUTEX;
624 return VINF_SUCCESS;
625}
626
627
628/**
629 * Module loading hook, called before calling into the module.
630 *
631 * @returns VBox status code.
632 * @param pDevExt The device extension structure.
633 */
634int supdrvDTraceModuleLoading(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage)
635{
636 /*
637 * Check for DTrace probes in the module, register a new provider for them
638 * if found.
639 */
640
641 return VINF_SUCCESS;
642}
643
644
645/**
646 * Module unloading hook, called after execution in the module
647 * have ceased.
648 *
649 * @returns VBox status code.
650 * @param pDevExt The device extension structure.
651 */
652int supdrvDTraceModuleUnloading(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage)
653{
654 /*
655 * Undo what we did in supdrvDTraceModuleLoading.
656 */
657 return VINF_SUCCESS;
658}
659
660
661
662
663
664/**
665 * @callback_method_impl{dtrace_pops_t,dtps_provide}
666 */
667static void supdrvDTracePOps_Provide(void *pvProv, const dtrace_probedesc_t *pDtProbeDesc)
668{
669 PSUPDRVDTPROVIDER pProv = (PSUPDRVDTPROVIDER)pvProv;
670 uint16_t const idxProv = (uint16_t)(&pProv->pHdr->paProviders[0] - pProv->pDesc);
671 PVTGPROBELOC pProbeLoc;
672 PVTGPROBELOC pProbeLocEnd;
673 char *pszFnNmBuf;
674 size_t const cbFnNmBuf = _4K + _1K;
675
676 if (pDtProbeDesc)
677 return; /* We don't generate probes, so never mind these requests. */
678
679 /* Need a buffer for extracting the function names and mangling them in
680 case of collision. */
681 pszFnNmBuf = (char *)RTMemAlloc(_4K + _1K);
682 if (!pszFnNmBuf)
683 return;
684
685 /*
686 * Itereate the probe location list and register all probes related to
687 * this provider.
688 */
689 pProbeLoc = pProv->pHdr->paProbLocs;
690 pProbeLocEnd = pProv->pHdr->paProbLocsEnd;
691 while ((uintptr_t)pProbeLoc < (uintptr_t)pProbeLocEnd)
692 {
693 PVTGDESCPROBE pProbeDesc = (PVTGDESCPROBE)pProbeLoc->pbProbe;
694 if (pProbeDesc->idxProvider == idxProv)
695 {
696 /* The function name normally needs to be stripped since we're
697 using C++ compilers for most of the code. ASSUMES nobody are
698 brave/stupid enough to use function pointer returns without
699 typedef'ing properly them. */
700 const char *pszName = supdrvVtgGetString(pProv->pHdr, pProbeDesc->offName);
701 const char *pszFunc = pProbeLoc->pszFunction;
702 const char *psz = strchr(pProbeLoc->pszFunction, '(');
703 size_t cch;
704 if (psz)
705 {
706 pszFunc = psz - 1; /* ASSUMES not space... FIXME */
707 while ((uintptr_t)pszFunc > (uintptr_t)pProbeLoc->pszFunction)
708 {
709 char ch = pszFunc[-1];
710 if (!RT_C_IS_ALNUM(ch) && ch != '_' && ch != ':')
711 break;
712 pszFunc--;
713 }
714 cch = psz - pszFunc;
715 }
716 else
717 cch = strlen(pszFunc);
718 RTStrCopyEx(pszFnNmBuf, cbFnNmBuf, pszFunc, cch);
719
720 /* Look up the probe, if we have one in the same function, mangle
721 the function name a little to avoid having to deal with having
722 multiple location entries with the same probe ID. (lazy bird) */
723
724 //dtrace_probe_lookup()
725 //dtrace_probe_create()
726
727 Assert(pProbeLoc->idProbe == UINT32_MAX);
728 }
729
730 pProbeLoc++;
731 }
732
733 RTMemFree(pszFnNmBuf);
734}
735
736
737/**
738 * @callback_method_impl{dtrace_pops_t,dtps_enable}
739 */
740static int supdrvDTracePOps_Enable(void *pvProv, dtrace_id_t idProbe, void *pvProbe)
741{
742 PVTGPROBELOC pProbeLoc = (PVTGPROBELOC)pvProbe;
743 PVTGDESCPROBE pProbeDesc = (PVTGDESCPROBE)pProbeLoc->pbProbe;
744
745 if (!pProbeLoc->fEnabled)
746 {
747 pProbeLoc->fEnabled = 1;
748 if (ASMAtomicIncU32(&pProbeDesc->u32User) == 1)
749 pProbeLoc->fEnabled = 1;
750 }
751
752 NOREF(pvProv);
753 return 0;
754}
755
756
757/**
758 * @callback_method_impl{dtrace_pops_t,dtps_disable}
759 */
760static void supdrvDTracePOps_Disable(void *pvProv, dtrace_id_t idProbe, void *pvProbe)
761{
762 PVTGPROBELOC pProbeLoc = (PVTGPROBELOC)pvProbe;
763 PVTGDESCPROBE pProbeDesc = (PVTGDESCPROBE)pProbeLoc->pbProbe;
764
765 if (pProbeLoc->fEnabled)
766 {
767 pProbeLoc->fEnabled = 0;
768 if (ASMAtomicDecU32(&pProbeDesc->u32User) == 0)
769 pProbeLoc->fEnabled = 0;
770 }
771
772 NOREF(pvProv);
773}
774
775
776/**
777 * @callback_method_impl{dtrace_pops_t,dtps_getargdesc}
778 */
779static void supdrvDTracePOps_GetArgDesc(void *pvProv, dtrace_id_t idProbe, void *pvProbe,
780 dtrace_argdesc_t *pArgDesc)
781{
782 PSUPDRVDTPROVIDER pProv = (PSUPDRVDTPROVIDER)pvProv;
783 PVTGPROBELOC pProbeLoc = (PVTGPROBELOC)pvProbe;
784 PVTGDESCPROBE pProbeDesc = (PVTGDESCPROBE)pProbeLoc->pbProbe;
785 PVTGDESCARGLIST pArgList = (PVTGDESCARGLIST)((uintptr_t)pProv->pHdr->paArgLists + pProbeDesc->offArgList);
786
787 Assert(pProbeDesc->offArgList < pProv->pHdr->cbArgLists);
788 if (pArgList->cArgs > pArgDesc->dtargd_ndx)
789 {
790 const char *pszType = supdrvVtgGetString(pProv->pHdr, pArgList->aArgs[pArgDesc->dtargd_ndx].offType);
791 size_t cchType = strlen(pszType);
792 if (cchType < sizeof(pArgDesc->dtargd_native))
793 memcpy(pArgDesc->dtargd_native, pszType, cchType + 1);
794 else
795 pArgDesc->dtargd_ndx = DTRACE_ARGNONE;
796 }
797 else
798 pArgDesc->dtargd_ndx = DTRACE_ARGNONE;
799}
800
801
802#if 0
803/**
804 * @callback_method_impl{dtrace_pops_t,dtps_getargval}
805 */
806static uint64_t supdrvDTracePOps_GetArgVal(void *pvProv, dtrace_id_t idProbe, void *pvProbe,
807 int iArg, int cFrames)
808{
809 return 0xbeef;
810}
811#endif
812
813
814/**
815 * @callback_method_impl{dtrace_pops_t,dtps_destroy}
816 */
817static void supdrvDTracePOps_Destroy(void *pvProv, dtrace_id_t idProbe, void *pvProbe)
818{
819 PVTGPROBELOC pProbeLoc = (PVTGPROBELOC)pvProbe;
820
821 Assert(!pProbeLoc->fEnabled);
822 Assert(pProbeLoc->idProbe == idProbe); NOREF(idProbe);
823 pProbeLoc->idProbe = UINT32_MAX;
824
825 NOREF(pvProv);
826}
827
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette