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