SUPDrv-dtrace.cpp revision e250515922582e0410c9bcb6d24b0f17bef083a0
42576743851c3c956ad7e867e74df1084c30d434vboxsync * VBoxDrv - The VirtualBox Support Driver - DTrace Provider.
42576743851c3c956ad7e867e74df1084c30d434vboxsync * Copyright (C) 2012 Oracle Corporation
42576743851c3c956ad7e867e74df1084c30d434vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
42576743851c3c956ad7e867e74df1084c30d434vboxsync * available from http://www.virtualbox.org. This file is free software;
42576743851c3c956ad7e867e74df1084c30d434vboxsync * you can redistribute it and/or modify it under the terms of the GNU
42576743851c3c956ad7e867e74df1084c30d434vboxsync * General Public License (GPL) as published by the Free Software
42576743851c3c956ad7e867e74df1084c30d434vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
42576743851c3c956ad7e867e74df1084c30d434vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
42576743851c3c956ad7e867e74df1084c30d434vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
42576743851c3c956ad7e867e74df1084c30d434vboxsync * The contents of this file may alternatively be used under the terms
42576743851c3c956ad7e867e74df1084c30d434vboxsync * of the Common Development and Distribution License Version 1.0
42576743851c3c956ad7e867e74df1084c30d434vboxsync * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
42576743851c3c956ad7e867e74df1084c30d434vboxsync * VirtualBox OSE distribution, in which case the provisions of the
42576743851c3c956ad7e867e74df1084c30d434vboxsync * CDDL are applicable instead of those of the GPL.
42576743851c3c956ad7e867e74df1084c30d434vboxsync * You may elect to license modified versions of this file under the
42576743851c3c956ad7e867e74df1084c30d434vboxsync * terms and conditions of either the GPL or the CDDL or both.
42576743851c3c956ad7e867e74df1084c30d434vboxsync/*******************************************************************************
42576743851c3c956ad7e867e74df1084c30d434vboxsync* Header Files *
42576743851c3c956ad7e867e74df1084c30d434vboxsync*******************************************************************************/
02f73b88a6e96b7f1b8ab0bbb98cfb798b566fbdvboxsync/*******************************************************************************
02f73b88a6e96b7f1b8ab0bbb98cfb798b566fbdvboxsync* Structures and Typedefs *
02f73b88a6e96b7f1b8ab0bbb98cfb798b566fbdvboxsync*******************************************************************************/
cdcfac625bb49f1d4b67aaf8fb8b1cdb69fe49c2vboxsync/* Seems there is some return code difference here. Keep the return code and
cdcfac625bb49f1d4b67aaf8fb8b1cdb69fe49c2vboxsync case it to whatever the host desires. */
cdcfac625bb49f1d4b67aaf8fb8b1cdb69fe49c2vboxsynctypedef void FNPOPS_ENABLE(void *, dtrace_id_t, void *);
cdcfac625bb49f1d4b67aaf8fb8b1cdb69fe49c2vboxsynctypedef int FNPOPS_ENABLE(void *, dtrace_id_t, void *);
1379dfd407ada5fab15655776896f13b61a951fdvboxsync * Stack data planted before calling dtrace_probe so that we can easily find the
1379dfd407ada5fab15655776896f13b61a951fdvboxsync * stack argument later.
1379dfd407ada5fab15655776896f13b61a951fdvboxsync /** Eyecatcher no. 1 (SUPDRVDT_STACK_DATA_MAGIC2). */
1379dfd407ada5fab15655776896f13b61a951fdvboxsync /** Eyecatcher no. 2 (SUPDRVDT_STACK_DATA_MAGIC2). */
1379dfd407ada5fab15655776896f13b61a951fdvboxsync /** Pointer to the stack arguments of a probe function call. */
1379dfd407ada5fab15655776896f13b61a951fdvboxsync /** Pointer to this structure.
1379dfd407ada5fab15655776896f13b61a951fdvboxsync * This is the final bit of integrity checking. */
1379dfd407ada5fab15655776896f13b61a951fdvboxsync/** Pointer to the on-stack thread specific data. */
e89bf42607ac3c1b6c60fabbf6067a38adb1284bvboxsync/*******************************************************************************
e89bf42607ac3c1b6c60fabbf6067a38adb1284bvboxsync* Defined Constants And Macros *
e89bf42607ac3c1b6c60fabbf6067a38adb1284bvboxsync*******************************************************************************/
1379dfd407ada5fab15655776896f13b61a951fdvboxsync/** The first magic value. */
1379dfd407ada5fab15655776896f13b61a951fdvboxsync#define SUPDRVDT_STACK_DATA_MAGIC1 RT_MAKE_U32_FROM_U8('S', 'U', 'P', 'D')
1379dfd407ada5fab15655776896f13b61a951fdvboxsync/** The second magic value. */
1379dfd407ada5fab15655776896f13b61a951fdvboxsync#define SUPDRVDT_STACK_DATA_MAGIC2 RT_MAKE_U32_FROM_U8('D', 'T', 'r', 'c')
1379dfd407ada5fab15655776896f13b61a951fdvboxsync/** The alignment of the stack data.
1379dfd407ada5fab15655776896f13b61a951fdvboxsync * The data doesn't require more than sizeof(uintptr_t) alignment, but the
1379dfd407ada5fab15655776896f13b61a951fdvboxsync * greater alignment the quicker lookup. */
1379dfd407ada5fab15655776896f13b61a951fdvboxsync/** Plants the stack data. */
1379dfd407ada5fab15655776896f13b61a951fdvboxsync uint8_t abBlob[sizeof(SUPDRVDTSTACKDATA) + SUPDRVDT_STACK_DATA_ALIGN - 1]; \
1379dfd407ada5fab15655776896f13b61a951fdvboxsync PSUPDRVDTSTACKDATA pStackData = (PSUPDRVDTSTACKDATA)( (uintptr_t)&abBlob[SUPDRVDT_STACK_DATA_ALIGN - 1] \
1379dfd407ada5fab15655776896f13b61a951fdvboxsync pStackData->u32Magic1 = SUPDRVDT_STACK_DATA_MAGIC1; \
1379dfd407ada5fab15655776896f13b61a951fdvboxsync pStackData->u32Magic2 = SUPDRVDT_STACK_DATA_MAGIC2; \
1379dfd407ada5fab15655776896f13b61a951fdvboxsync/** Passifies the stack data and frees up resource held within it. */
1379dfd407ada5fab15655776896f13b61a951fdvboxsync } while (0)
cb70b5cc08e3b666361766188f99cc86ed1626fbvboxsync/** Simple SUPR0Printf-style logging. */
cb70b5cc08e3b666361766188f99cc86ed1626fbvboxsync#if 0 /*def DEBUG_bird*/
e89bf42607ac3c1b6c60fabbf6067a38adb1284bvboxsync# define LOG_DTRACE(a) do { } while (0)
42576743851c3c956ad7e867e74df1084c30d434vboxsync/*******************************************************************************
42576743851c3c956ad7e867e74df1084c30d434vboxsync* Global Variables *
42576743851c3c956ad7e867e74df1084c30d434vboxsync*******************************************************************************/
1379dfd407ada5fab15655776896f13b61a951fdvboxsync/** @name DTrace kernel interface used on Darwin
82e3a4017d20f44c30ff909e6b825ff78139cbbbvboxsyncstatic void (* g_pfnDTraceProbeFire)(dtrace_id_t, uint64_t, uint64_t, uint64_t, uint64_t, uint64_t);
82e3a4017d20f44c30ff909e6b825ff78139cbbbvboxsyncstatic dtrace_id_t (* g_pfnDTraceProbeCreate)(dtrace_provider_id_t, const char *, const char *, const char *, int, void *);
82e3a4017d20f44c30ff909e6b825ff78139cbbbvboxsyncstatic dtrace_id_t (* g_pfnDTraceProbeLookup)(dtrace_provider_id_t, const char *, const char *, const char *);
82e3a4017d20f44c30ff909e6b825ff78139cbbbvboxsyncstatic int (* g_pfnDTraceProviderRegister)(const char *, const dtrace_pattr_t *, uint32_t, /*cred_t*/ void *,
82e3a4017d20f44c30ff909e6b825ff78139cbbbvboxsync const dtrace_pops_t *, void *, dtrace_provider_id_t *);
82e3a4017d20f44c30ff909e6b825ff78139cbbbvboxsyncstatic void (* g_pfnDTraceProviderInvalidate)(dtrace_provider_id_t);
82e3a4017d20f44c30ff909e6b825ff78139cbbbvboxsyncstatic int (* g_pfnDTraceProviderUnregister)(dtrace_provider_id_t);
82e3a4017d20f44c30ff909e6b825ff78139cbbbvboxsync#define dtrace_invalidate g_pfnDTraceProviderInvalidate
82e3a4017d20f44c30ff909e6b825ff78139cbbbvboxsync#define dtrace_unregister g_pfnDTraceProviderUnregister
1379dfd407ada5fab15655776896f13b61a951fdvboxsync * Helpers for handling VTG structures.
1379dfd407ada5fab15655776896f13b61a951fdvboxsync * Helpers for handling VTG structures.
1379dfd407ada5fab15655776896f13b61a951fdvboxsync * Helpers for handling VTG structures.
cdcfac625bb49f1d4b67aaf8fb8b1cdb69fe49c2vboxsync * Converts an attribute from VTG description speak to DTrace.
cdcfac625bb49f1d4b67aaf8fb8b1cdb69fe49c2vboxsync * @param pDtAttr The DTrace attribute (dst).
cdcfac625bb49f1d4b67aaf8fb8b1cdb69fe49c2vboxsync * @param pVtgAttr The VTG attribute descriptor (src).
1379dfd407ada5fab15655776896f13b61a951fdvboxsyncstatic void vboxDtVtgConvAttr(dtrace_attribute_t *pDtAttr, PCVTGDESCATTR pVtgAttr)
cdcfac625bb49f1d4b67aaf8fb8b1cdb69fe49c2vboxsync * Gets a string from the string table.
cdcfac625bb49f1d4b67aaf8fb8b1cdb69fe49c2vboxsync * @returns Pointer to the string.
cdcfac625bb49f1d4b67aaf8fb8b1cdb69fe49c2vboxsync * @param pVtgHdr The VTG object header.
cdcfac625bb49f1d4b67aaf8fb8b1cdb69fe49c2vboxsync * @param offStrTab The string table offset.
1379dfd407ada5fab15655776896f13b61a951fdvboxsyncstatic const char *vboxDtVtgGetString(PVTGOBJHDR pVtgHdr, uint32_t offStrTab)
1379dfd407ada5fab15655776896f13b61a951fdvboxsync * DTrace Provider Interface.
1379dfd407ada5fab15655776896f13b61a951fdvboxsync * DTrace Provider Interface.
1379dfd407ada5fab15655776896f13b61a951fdvboxsync * DTrace Provider Interface.
cdcfac625bb49f1d4b67aaf8fb8b1cdb69fe49c2vboxsync * @callback_method_impl{dtrace_pops_t,dtps_provide}
1379dfd407ada5fab15655776896f13b61a951fdvboxsyncstatic void supdrvDtPOps_Provide(void *pvProv, const dtrace_probedesc_t *pDtProbeDesc)
1379dfd407ada5fab15655776896f13b61a951fdvboxsync PSUPDRVVDTPROVIDERCORE pProv = (PSUPDRVVDTPROVIDERCORE)pvProv;
e89bf42607ac3c1b6c60fabbf6067a38adb1284bvboxsync LOG_DTRACE(("supdrvDtPOps_Provide: %p / %p pDtProbeDesc=%p\n", pProv, pProv->TracerData.DTrace.idProvider, pDtProbeDesc));
1379dfd407ada5fab15655776896f13b61a951fdvboxsync PVTGPROBELOC pProbeLocEnd = pProv->pHdr->paProbLocsEnd;
1379dfd407ada5fab15655776896f13b61a951fdvboxsync dtrace_provider_id_t idProvider = pProv->TracerData.DTrace.idProvider;
cdcfac625bb49f1d4b67aaf8fb8b1cdb69fe49c2vboxsync return; /* We don't generate probes, so never mind these requests. */
1379dfd407ada5fab15655776896f13b61a951fdvboxsync if (pProv->TracerData.DTrace.cProvidedProbes >= pProbeLocEnd - pProbeLoc)
cdcfac625bb49f1d4b67aaf8fb8b1cdb69fe49c2vboxsync /* Need a buffer for extracting the function names and mangling them in
cdcfac625bb49f1d4b67aaf8fb8b1cdb69fe49c2vboxsync case of collision. */
cdcfac625bb49f1d4b67aaf8fb8b1cdb69fe49c2vboxsync * Itereate the probe location list and register all probes related to
cdcfac625bb49f1d4b67aaf8fb8b1cdb69fe49c2vboxsync * this provider.
b32be08cd134577ca98e517c019c867c416ec0f2vboxsync idxProv = (uint16_t)(&pProv->pHdr->paProviders[0] - pProv->pDesc);
cdcfac625bb49f1d4b67aaf8fb8b1cdb69fe49c2vboxsync while ((uintptr_t)pProbeLoc < (uintptr_t)pProbeLocEnd)
cdcfac625bb49f1d4b67aaf8fb8b1cdb69fe49c2vboxsync PVTGDESCPROBE pProbeDesc = (PVTGDESCPROBE)pProbeLoc->pbProbe;
cdcfac625bb49f1d4b67aaf8fb8b1cdb69fe49c2vboxsync /* The function name normally needs to be stripped since we're
cdcfac625bb49f1d4b67aaf8fb8b1cdb69fe49c2vboxsync using C++ compilers for most of the code. ASSUMES nobody are
cdcfac625bb49f1d4b67aaf8fb8b1cdb69fe49c2vboxsync brave/stupid enough to use function pointer returns without
cdcfac625bb49f1d4b67aaf8fb8b1cdb69fe49c2vboxsync typedef'ing properly them. */
1379dfd407ada5fab15655776896f13b61a951fdvboxsync const char *pszPrbName = vboxDtVtgGetString(pProv->pHdr, pProbeDesc->offName);
6998b7cea7c904f33047cd17b05bea760a5839a9vboxsync const char *psz = strchr(pProbeLoc->pszFunction, '(');
6998b7cea7c904f33047cd17b05bea760a5839a9vboxsync /* skip blanks preceeding the parameter parenthesis. */
6998b7cea7c904f33047cd17b05bea760a5839a9vboxsync while ( (uintptr_t)psz > (uintptr_t)pProbeLoc->pszFunction
6998b7cea7c904f33047cd17b05bea760a5839a9vboxsync /* Find the start of the function name. */
cdcfac625bb49f1d4b67aaf8fb8b1cdb69fe49c2vboxsync while ((uintptr_t)pszFunc > (uintptr_t)pProbeLoc->pszFunction)
cdcfac625bb49f1d4b67aaf8fb8b1cdb69fe49c2vboxsync /* Look up the probe, if we have one in the same function, mangle
cdcfac625bb49f1d4b67aaf8fb8b1cdb69fe49c2vboxsync the function name a little to avoid having to deal with having
cdcfac625bb49f1d4b67aaf8fb8b1cdb69fe49c2vboxsync multiple location entries with the same probe ID. (lazy bird) */
1379dfd407ada5fab15655776896f13b61a951fdvboxsync if (dtrace_probe_lookup(idProvider, pProv->pszModName, pszFnNmBuf, pszPrbName) != DTRACE_IDNONE)
6998b7cea7c904f33047cd17b05bea760a5839a9vboxsync RTStrPrintf(pszFnNmBuf+cch, cbFnNmBuf - cch, "-%u", pProbeLoc->uLine);
1379dfd407ada5fab15655776896f13b61a951fdvboxsync if (dtrace_probe_lookup(idProvider, pProv->pszModName, pszFnNmBuf, pszPrbName) != DTRACE_IDNONE)
6998b7cea7c904f33047cd17b05bea760a5839a9vboxsync RTStrPrintf(pszFnNmBuf+cch, cbFnNmBuf - cch, "-%u-%u", pProbeLoc->uLine, iOrd);
1379dfd407ada5fab15655776896f13b61a951fdvboxsync if (dtrace_probe_lookup(idProvider, pProv->pszModName, pszFnNmBuf, pszPrbName) == DTRACE_IDNONE)
1379dfd407ada5fab15655776896f13b61a951fdvboxsync LogRel(("VBoxDrv: More than 128 duplicate probe location instances %s at line %u in function %s [%s], probe %s\n",
1379dfd407ada5fab15655776896f13b61a951fdvboxsync pProbeLoc->uLine, pProbeLoc->pszFunction, pszFnNmBuf, pszPrbName));
6998b7cea7c904f33047cd17b05bea760a5839a9vboxsync /* Create the probe. */
6998b7cea7c904f33047cd17b05bea760a5839a9vboxsync AssertCompile(sizeof(pProbeLoc->idProbe) == sizeof(dtrace_id_t));
1379dfd407ada5fab15655776896f13b61a951fdvboxsync pProbeLoc->idProbe = dtrace_probe_create(idProvider, pProv->pszModName, pszFnNmBuf, pszPrbName,
42576743851c3c956ad7e867e74df1084c30d434vboxsync * @callback_method_impl{dtrace_pops_t,dtps_enable}
1379dfd407ada5fab15655776896f13b61a951fdvboxsyncstatic int supdrvDtPOps_Enable(void *pvProv, dtrace_id_t idProbe, void *pvProbe)
1379dfd407ada5fab15655776896f13b61a951fdvboxsync PSUPDRVVDTPROVIDERCORE pProv = (PSUPDRVVDTPROVIDERCORE)pvProv;
e89bf42607ac3c1b6c60fabbf6067a38adb1284bvboxsync LOG_DTRACE(("supdrvDtPOps_Enable: %p / %p - %#x / %p\n", pProv, pProv->TracerData.DTrace.idProvider, idProbe, pvProbe));
e89bf42607ac3c1b6c60fabbf6067a38adb1284bvboxsync AssertPtrReturn(pProv->TracerData.DTrace.idProvider, EINVAL);
b32be08cd134577ca98e517c019c867c416ec0f2vboxsync PVTGDESCPROBE pProbeDesc = (PVTGDESCPROBE)pProbeLoc->pbProbe;
b32be08cd134577ca98e517c019c867c416ec0f2vboxsync pProv->pHdr->pafProbeEnabled[pProbeDesc->idxEnabled] = 1;
42576743851c3c956ad7e867e74df1084c30d434vboxsync * @callback_method_impl{dtrace_pops_t,dtps_disable}
1379dfd407ada5fab15655776896f13b61a951fdvboxsyncstatic void supdrvDtPOps_Disable(void *pvProv, dtrace_id_t idProbe, void *pvProbe)
1379dfd407ada5fab15655776896f13b61a951fdvboxsync PSUPDRVVDTPROVIDERCORE pProv = (PSUPDRVVDTPROVIDERCORE)pvProv;
e89bf42607ac3c1b6c60fabbf6067a38adb1284bvboxsync LOG_DTRACE(("supdrvDtPOps_Disable: %p / %p - %#x / %p\n", pProv, pProv->TracerData.DTrace.idProvider, idProbe, pvProbe));
e89bf42607ac3c1b6c60fabbf6067a38adb1284bvboxsync AssertPtrReturnVoid(pProv->TracerData.DTrace.idProvider);
b32be08cd134577ca98e517c019c867c416ec0f2vboxsync PVTGDESCPROBE pProbeDesc = (PVTGDESCPROBE)pProbeLoc->pbProbe;
cb70b5cc08e3b666361766188f99cc86ed1626fbvboxsync pProv->pHdr->pafProbeEnabled[pProbeDesc->idxEnabled] = 0;
42576743851c3c956ad7e867e74df1084c30d434vboxsync * @callback_method_impl{dtrace_pops_t,dtps_getargdesc}
1379dfd407ada5fab15655776896f13b61a951fdvboxsyncstatic void supdrvDtPOps_GetArgDesc(void *pvProv, dtrace_id_t idProbe, void *pvProbe,
1379dfd407ada5fab15655776896f13b61a951fdvboxsync PSUPDRVVDTPROVIDERCORE pProv = (PSUPDRVVDTPROVIDERCORE)pvProv;
e89bf42607ac3c1b6c60fabbf6067a38adb1284bvboxsync LOG_DTRACE(("supdrvDtPOps_GetArgDesc: %p / %p - %#x / %p uArg=%d\n", pProv, pProv->TracerData.DTrace.idProvider, idProbe, pvProbe, uArg));
e89bf42607ac3c1b6c60fabbf6067a38adb1284bvboxsync AssertPtrReturnVoid(pProv->TracerData.DTrace.idProvider);
b32be08cd134577ca98e517c019c867c416ec0f2vboxsync PVTGDESCPROBE pProbeDesc = (PVTGDESCPROBE)pProbeLoc->pbProbe;
b32be08cd134577ca98e517c019c867c416ec0f2vboxsync PVTGDESCARGLIST pArgList = (PVTGDESCARGLIST)((uintptr_t)pProv->pHdr->paArgLists + pProbeDesc->offArgList);
b32be08cd134577ca98e517c019c867c416ec0f2vboxsync Assert(pProbeDesc->offArgList < pProv->pHdr->cbArgLists);
1379dfd407ada5fab15655776896f13b61a951fdvboxsync const char *pszType = vboxDtVtgGetString(pProv->pHdr, pArgList->aArgs[uArg].offType);
b32be08cd134577ca98e517c019c867c416ec0f2vboxsync memcpy(pArgDesc->dtargd_native, pszType, cchType + 1);
e250515922582e0410c9bcb6d24b0f17bef083a0vboxsync /** @todo mapping? */
e89bf42607ac3c1b6c60fabbf6067a38adb1284bvboxsync LOG_DTRACE(("supdrvDtPOps_GetArgVal: returns dtargd_native = %s\n", pArgDesc->dtargd_native));
82e3a4017d20f44c30ff909e6b825ff78139cbbbvboxsync * @callback_method_impl{dtrace_pops_t,dtps_getargval}
82e3a4017d20f44c30ff909e6b825ff78139cbbbvboxsync * We just cook our own stuff here, using a stack marker for finding the
82e3a4017d20f44c30ff909e6b825ff78139cbbbvboxsync * required information. That's more reliable than subjecting oneself to the
82e3a4017d20f44c30ff909e6b825ff78139cbbbvboxsync * solaris bugs and 32-bit apple peculiarities.
1379dfd407ada5fab15655776896f13b61a951fdvboxsync * @remarks Solaris Bug
82e3a4017d20f44c30ff909e6b825ff78139cbbbvboxsync * dtrace_getarg on AMD64 has a different opinion about how to use the cFrames
82e3a4017d20f44c30ff909e6b825ff78139cbbbvboxsync * argument than dtrace_caller() and/or dtrace_getpcstack(), at least when the
82e3a4017d20f44c30ff909e6b825ff78139cbbbvboxsync * probe is fired by dtrace_probe() the way we do.
1379dfd407ada5fab15655776896f13b61a951fdvboxsync * Setting aframes to 1 when calling dtrace_probe_create gives me the right
1379dfd407ada5fab15655776896f13b61a951fdvboxsync * arguments, but the wrong 'caller'. Since I cannot do anything about
1379dfd407ada5fab15655776896f13b61a951fdvboxsync * 'caller', the only solution is this hack.
1379dfd407ada5fab15655776896f13b61a951fdvboxsync * Not sure why the Solaris guys hasn't seen this issue before, but maybe there
82e3a4017d20f44c30ff909e6b825ff78139cbbbvboxsync * isn't anyone using the default argument getter path for ring-0 dtrace_probe()
82e3a4017d20f44c30ff909e6b825ff78139cbbbvboxsync * calls, SDT surely isn't.
1379dfd407ada5fab15655776896f13b61a951fdvboxsync * @todo File a solaris bug on dtrace_probe() + dtrace_getarg().
82e3a4017d20f44c30ff909e6b825ff78139cbbbvboxsync * @remarks 32-bit XNU (Apple)
82e3a4017d20f44c30ff909e6b825ff78139cbbbvboxsync * The dtrace_probe arguments are 64-bit unsigned integers instead of uintptr_t,
82e3a4017d20f44c30ff909e6b825ff78139cbbbvboxsync * so we need to make an extra call.
1379dfd407ada5fab15655776896f13b61a951fdvboxsyncstatic uint64_t supdrvDtPOps_GetArgVal(void *pvProv, dtrace_id_t idProbe, void *pvProbe,
e89bf42607ac3c1b6c60fabbf6067a38adb1284bvboxsync PSUPDRVVDTPROVIDERCORE pProv = (PSUPDRVVDTPROVIDERCORE)pvProv;
e89bf42607ac3c1b6c60fabbf6067a38adb1284bvboxsync LOG_DTRACE(("supdrvDtPOps_GetArgVal: %p / %p - %#x / %p iArg=%d cFrames=%u\n", pProv, pProv->TracerData.DTrace.idProvider, idProbe, pvProbe, iArg, cFrames));
e89bf42607ac3c1b6c60fabbf6067a38adb1284bvboxsync AssertReturn(!pProv->TracerData.DTrace.fZombie, UINT64_MAX);
e89bf42607ac3c1b6c60fabbf6067a38adb1284bvboxsync AssertPtrReturn(pProv->TracerData.DTrace.idProvider, UINT64_MAX);
e250515922582e0410c9bcb6d24b0f17bef083a0vboxsync PVTGDESCPROBE pProbe = (PVTGDESCPROBE)pProbeLoc->pbProbe
e250515922582e0410c9bcb6d24b0f17bef083a0vboxsync PVTGDESCARGLIST pArgList = (PVTGDESCPROBE)((uintptr_t)pProv->pHdr->paArgLists + pProbe->offArgList);
1379dfd407ada5fab15655776896f13b61a951fdvboxsync /* Locate the caller of probe_dtrace, . */
1379dfd407ada5fab15655776896f13b61a951fdvboxsync int volatile iDummy = 1; /* use this to get the stack address. */
1379dfd407ada5fab15655776896f13b61a951fdvboxsync PSUPDRVDTSTACKDATA pData = (PSUPDRVDTSTACKDATA)( ((uintptr_t)&iDummy + SUPDRVDT_STACK_DATA_ALIGN - 1)
1379dfd407ada5fab15655776896f13b61a951fdvboxsync if ( pData->u32Magic1 == SUPDRVDT_STACK_DATA_MAGIC1
1379dfd407ada5fab15655776896f13b61a951fdvboxsync pData = (PSUPDRVDTSTACKDATA)((uintptr_t)pData + SUPDRVDT_STACK_DATA_ALIGN);
1379dfd407ada5fab15655776896f13b61a951fdvboxsync /* Get the stack data. */
e250515922582e0410c9bcb6d24b0f17bef083a0vboxsync /* wonder if this will work... */
e250515922582e0410c9bcb6d24b0f17bef083a0vboxsync if ( (pArgList->aArgs[i].fType & VTG_TYPE_FIXED_SIZED)
e250515922582e0410c9bcb6d24b0f17bef083a0vboxsync && (pArgList->aArgs[i].fType & VTG_TYPE_SIZE_MASK) == 8)
e250515922582e0410c9bcb6d24b0f17bef083a0vboxsync if ( (pArgList->aArgs[iArg].fType & VTG_TYPE_FIXED_SIZED)
e250515922582e0410c9bcb6d24b0f17bef083a0vboxsync && (pArgList->aArgs[iArg].fType & VTG_TYPE_SIZE_MASK) == 8
e250515922582e0410c9bcb6d24b0f17bef083a0vboxsync u64Ret |= (uint64_t)pData->pauStackArgs[iArg - 5 + off + 1] << 32;
e250515922582e0410c9bcb6d24b0f17bef083a0vboxsync LOG_DTRACE(("supdrvDtPOps_GetArgVal: returns %#llx\n", u64Ret));
42576743851c3c956ad7e867e74df1084c30d434vboxsync * @callback_method_impl{dtrace_pops_t,dtps_destroy}
1379dfd407ada5fab15655776896f13b61a951fdvboxsyncstatic void supdrvDtPOps_Destroy(void *pvProv, dtrace_id_t idProbe, void *pvProbe)
1379dfd407ada5fab15655776896f13b61a951fdvboxsync PSUPDRVVDTPROVIDERCORE pProv = (PSUPDRVVDTPROVIDERCORE)pvProv;
e89bf42607ac3c1b6c60fabbf6067a38adb1284bvboxsync LOG_DTRACE(("supdrvDtPOps_Destroy: %p / %p - %#x / %p\n", pProv, pProv->TracerData.DTrace.idProvider, idProbe, pvProbe));
e89bf42607ac3c1b6c60fabbf6067a38adb1284bvboxsync AssertReturnVoid(pProv->TracerData.DTrace.cProvidedProbes > 0);
e89bf42607ac3c1b6c60fabbf6067a38adb1284bvboxsync AssertPtrReturnVoid(pProv->TracerData.DTrace.idProvider);
1379dfd407ada5fab15655776896f13b61a951fdvboxsync * DTrace provider method table.
1379dfd407ada5fab15655776896f13b61a951fdvboxsync /* .dtps_enable = */ (FNPOPS_ENABLE *)supdrvDtPOps_Enable,
1379dfd407ada5fab15655776896f13b61a951fdvboxsync * Support Driver Tracer Interface.
1379dfd407ada5fab15655776896f13b61a951fdvboxsync * Support Driver Tracer Interface.
1379dfd407ada5fab15655776896f13b61a951fdvboxsync * Support Driver Tracer Interface.
1379dfd407ada5fab15655776896f13b61a951fdvboxsync * interface_method_impl{SUPDRVTRACERREG,pfnProbeFireUser}
1379dfd407ada5fab15655776896f13b61a951fdvboxsyncstatic DECLCALLBACK(void) supdrvDtTOps_ProbeFireKernel(struct VTGPROBELOC *pVtgProbeLoc, uintptr_t uArg0, uintptr_t uArg1, uintptr_t uArg2,
e89bf42607ac3c1b6c60fabbf6067a38adb1284bvboxsync LOG_DTRACE(("supdrvDtTOps_ProbeFireKernel: %p / %p\n", pVtgProbeLoc, pVtgProbeLoc->idProbe));
1379dfd407ada5fab15655776896f13b61a951fdvboxsync dtrace_probe(pVtgProbeLoc->idProbe, uArg0, uArg1, uArg2, uArg3, uArg4);
e89bf42607ac3c1b6c60fabbf6067a38adb1284bvboxsync LOG_DTRACE(("supdrvDtTOps_ProbeFireKernel: returns\n"));
1379dfd407ada5fab15655776896f13b61a951fdvboxsync * interface_method_impl{SUPDRVTRACERREG,pfnProbeFireUser}
1379dfd407ada5fab15655776896f13b61a951fdvboxsyncstatic DECLCALLBACK(void) supdrvDtTOps_ProbeFireUser(PCSUPDRVTRACERREG pThis, PSUPDRVSESSION pSession, PCSUPDRVTRACERUSRCTX pCtx)
1379dfd407ada5fab15655776896f13b61a951fdvboxsync * interface_method_impl{SUPDRVTRACERREG,pfnTracerOpen}
82e3a4017d20f44c30ff909e6b825ff78139cbbbvboxsyncstatic DECLCALLBACK(int) supdrvDtTOps_TracerOpen(PCSUPDRVTRACERREG pThis, PSUPDRVSESSION pSession, uint32_t uCookie,
1379dfd407ada5fab15655776896f13b61a951fdvboxsync NOREF(pThis); NOREF(pSession); NOREF(uCookie); NOREF(uArg);
1379dfd407ada5fab15655776896f13b61a951fdvboxsync * interface_method_impl{SUPDRVTRACERREG,pfnTracerClose}
1379dfd407ada5fab15655776896f13b61a951fdvboxsyncstatic DECLCALLBACK(int) supdrvDtTOps_TracerIoCtl(PCSUPDRVTRACERREG pThis, PSUPDRVSESSION pSession, uintptr_t uSessionData,
1379dfd407ada5fab15655776896f13b61a951fdvboxsync NOREF(pThis); NOREF(pSession); NOREF(uSessionData);
1379dfd407ada5fab15655776896f13b61a951fdvboxsync * interface_method_impl{SUPDRVTRACERREG,pfnTracerClose}
1379dfd407ada5fab15655776896f13b61a951fdvboxsyncstatic DECLCALLBACK(void) supdrvDtTOps_TracerClose(PCSUPDRVTRACERREG pThis, PSUPDRVSESSION pSession, uintptr_t uSessionData)
1379dfd407ada5fab15655776896f13b61a951fdvboxsync NOREF(pThis); NOREF(pSession); NOREF(uSessionData);
1379dfd407ada5fab15655776896f13b61a951fdvboxsync * interface_method_impl{SUPDRVTRACERREG,pfnProviderRegister}
1379dfd407ada5fab15655776896f13b61a951fdvboxsyncstatic DECLCALLBACK(int) supdrvDtTOps_ProviderRegister(PCSUPDRVTRACERREG pThis, PSUPDRVVDTPROVIDERCORE pCore)
e89bf42607ac3c1b6c60fabbf6067a38adb1284bvboxsync LOG_DTRACE(("supdrvDtTOps_ProviderRegister: %p %s/%s\n", pThis, pCore->pszModName, pCore->pszName));
1379dfd407ada5fab15655776896f13b61a951fdvboxsync AssertReturn(pCore->TracerData.DTrace.idProvider == UINT32_MAX || pCore->TracerData.DTrace.idProvider == 0,
1379dfd407ada5fab15655776896f13b61a951fdvboxsync vboxDtVtgConvAttr(&DtAttrs.dtpa_provider, &pDesc->AttrSelf);
1379dfd407ada5fab15655776896f13b61a951fdvboxsync vboxDtVtgConvAttr(&DtAttrs.dtpa_mod, &pDesc->AttrModules);
1379dfd407ada5fab15655776896f13b61a951fdvboxsync vboxDtVtgConvAttr(&DtAttrs.dtpa_func, &pDesc->AttrFunctions);
1379dfd407ada5fab15655776896f13b61a951fdvboxsync vboxDtVtgConvAttr(&DtAttrs.dtpa_name, &pDesc->AttrNames);
1379dfd407ada5fab15655776896f13b61a951fdvboxsync vboxDtVtgConvAttr(&DtAttrs.dtpa_args, &pDesc->AttrArguments);
e89bf42607ac3c1b6c60fabbf6067a38adb1284bvboxsync /* Note! DTrace may call us back before dtrace_register returns, so we
e89bf42607ac3c1b6c60fabbf6067a38adb1284bvboxsync have to point it to pCore->TracerData.DTrace.idProvider. */
e89bf42607ac3c1b6c60fabbf6067a38adb1284bvboxsync LOG_DTRACE(("supdrvDtTOps_ProviderRegister: idProvider=%p\n", pCore->TracerData.DTrace.idProvider));
e89bf42607ac3c1b6c60fabbf6067a38adb1284bvboxsync Assert(pCore->TracerData.DTrace.idProvider != UINT32_MAX && pCore->TracerData.DTrace.idProvider != 0);
e89bf42607ac3c1b6c60fabbf6067a38adb1284bvboxsync LOG_DTRACE(("supdrvDtTOps_ProviderRegister: returns %Rrc\n", rc));
1379dfd407ada5fab15655776896f13b61a951fdvboxsync * interface_method_impl{SUPDRVTRACERREG,pfnProviderDeregister}
1379dfd407ada5fab15655776896f13b61a951fdvboxsyncstatic DECLCALLBACK(int) supdrvDtTOps_ProviderDeregister(PCSUPDRVTRACERREG pThis, PSUPDRVVDTPROVIDERCORE pCore)
1379dfd407ada5fab15655776896f13b61a951fdvboxsync uintptr_t idProvider = pCore->TracerData.DTrace.idProvider;
e89bf42607ac3c1b6c60fabbf6067a38adb1284bvboxsync LOG_DTRACE(("supdrvDtTOps_ProviderDeregister: %p / %p\n", pThis, idProvider));
e89bf42607ac3c1b6c60fabbf6067a38adb1284bvboxsync AssertPtrReturn(idProvider, VERR_INTERNAL_ERROR_3);
1379dfd407ada5fab15655776896f13b61a951fdvboxsync AssertReturn(idProvider != UINT32_MAX && idProvider != 0, VERR_INTERNAL_ERROR_4);
e89bf42607ac3c1b6c60fabbf6067a38adb1284bvboxsync LOG_DTRACE(("supdrvDtTOps_ProviderDeregister: returns %Rrc\n", rc));
1379dfd407ada5fab15655776896f13b61a951fdvboxsync * interface_method_impl{SUPDRVTRACERREG,pfnProviderDeregisterZombie}
1379dfd407ada5fab15655776896f13b61a951fdvboxsyncstatic DECLCALLBACK(int) supdrvDtTOps_ProviderDeregisterZombie(PCSUPDRVTRACERREG pThis, PSUPDRVVDTPROVIDERCORE pCore)
1379dfd407ada5fab15655776896f13b61a951fdvboxsync uintptr_t idProvider = pCore->TracerData.DTrace.idProvider;
e89bf42607ac3c1b6c60fabbf6067a38adb1284bvboxsync LOG_DTRACE(("supdrvDtTOps_ProviderDeregisterZombie: %p / %p\n", pThis, idProvider));
e89bf42607ac3c1b6c60fabbf6067a38adb1284bvboxsync AssertPtrReturn(idProvider, VERR_INTERNAL_ERROR_3);
1379dfd407ada5fab15655776896f13b61a951fdvboxsync AssertReturn(idProvider != UINT32_MAX && idProvider != 0, VERR_INTERNAL_ERROR_4);
e89bf42607ac3c1b6c60fabbf6067a38adb1284bvboxsync LOG_DTRACE(("supdrvDtTOps_ProviderDeregisterZombie: returns %Rrc\n", rc));
1379dfd407ada5fab15655776896f13b61a951fdvboxsync * The tracer registration record of the VBox DTrace implementation
1379dfd407ada5fab15655776896f13b61a951fdvboxsync * Module initialization code.
1379dfd407ada5fab15655776896f13b61a951fdvboxsync * @param hMod Opque module handle.
1379dfd407ada5fab15655776896f13b61a951fdvboxsyncconst SUPDRVTRACERREG * VBOXCALL supdrvDTraceInit(void)
1379dfd407ada5fab15655776896f13b61a951fdvboxsync * Resolve the kernel symbols we need.
1379dfd407ada5fab15655776896f13b61a951fdvboxsync SUPR0Printf("supdrvDTraceInit: RTR0DbgKrnlInfoOpen failed with rc=%d.\n", rc);
1379dfd407ada5fab15655776896f13b61a951fdvboxsync static const struct
1379dfd407ada5fab15655776896f13b61a951fdvboxsync const char *pszName;
1379dfd407ada5fab15655776896f13b61a951fdvboxsync { "dtrace_probe_create", (PFNRT*)&dtrace_probe_create },
1379dfd407ada5fab15655776896f13b61a951fdvboxsync { "dtrace_probe_lookup", (PFNRT*)&dtrace_probe_lookup },
1379dfd407ada5fab15655776896f13b61a951fdvboxsync { "dtrace_invalidate", (PFNRT*)&dtrace_invalidate },
1379dfd407ada5fab15655776896f13b61a951fdvboxsync { "dtrace_unregister", (PFNRT*)&dtrace_unregister },
1379dfd407ada5fab15655776896f13b61a951fdvboxsync for (unsigned i = 0; i < RT_ELEMENTS(s_aDTraceFunctions); i++)
82e3a4017d20f44c30ff909e6b825ff78139cbbbvboxsync rc = RTR0DbgKrnlInfoQuerySymbol(hKrnlInfo, NULL, s_aDTraceFunctions[i].pszName,
1379dfd407ada5fab15655776896f13b61a951fdvboxsync SUPR0Printf("supdrvDTraceInit: Failed to resolved '%s' (rc=%Rrc, i=%u).\n", s_aDTraceFunctions[i].pszName, rc, i);
1379dfd407ada5fab15655776896f13b61a951fdvboxsync# error "VBOX_WITH_NATIVE_DTRACE_R0DRV is not defined as it should"