VirtualBox

Ignore:
Timestamp:
May 2, 2012 2:22:29 PM (13 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
77725
Message:

SUP,VBoxTpG,++: Initial implementation of generic user module tracepoints. (disabled)

Location:
trunk/src/VBox/HostDrivers/Support
Files:
1 added
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/HostDrivers/Support/Makefile.kmk

    r41092 r41117  
    8787        SUPLib.cpp \
    8888        SUPLibSem.cpp \
     89        SUPLibTracerA.asm \
    8990        SUPR3HardenedIPRT.cpp \
    9091        SUPR3HardenedVerify.cpp \
  • trunk/src/VBox/HostDrivers/Support/SUPDrv.c

    r41068 r41117  
    697697                /*pSession->uTracerData       = 0;*/
    698698                pSession->hTracerCaller     = NIL_RTNATIVETHREAD;
     699                RTListInit(&pSession->TpProviders);
     700                /*pSession->cTpProviders      = 0;*/
     701                /*pSession->cTpProbesFiring   = 0;*/
     702                RTListInit(&pSession->TpUmods);
     703                /*RT_ZERO(pSession->apTpLookupTable);*/
    699704
    700705                VBOXDRV_SESSION_CREATE(pSession, fUser);
     
    17941799            PSUPTRACERUMODREG pReq = (PSUPTRACERUMODREG)pReqHdr;
    17951800            REQ_CHECK_SIZES(SUP_IOCTL_TRACER_UMOD_REG);
     1801            if (!RTStrEnd(pReq->u.In.szName, sizeof(pReq->u.In.szName)))
     1802                return VERR_INVALID_PARAMETER;
    17961803
    17971804            /* execute */
    1798             pReqHdr->rc = supdrvIOCtl_TracerUmodRegister(pDevExt, pSession, pReq->u.In.pVtgHdr, pReq->u.In.szName, pReq->u.In.fFlags);
     1805            pReqHdr->rc = supdrvIOCtl_TracerUmodRegister(pDevExt, pSession,
     1806                                                         pReq->u.In.R3PtrVtgHdr, pReq->u.In.uVtgHdrAddr,
     1807                                                         pReq->u.In.R3PtrStrTab, pReq->u.In.cbStrTab,
     1808                                                         pReq->u.In.szName, pReq->u.In.fFlags);
    17991809            return 0;
    18001810        }
     
    18081818            /* execute */
    18091819            pReqHdr->rc = supdrvIOCtl_TracerUmodDeregister(pDevExt, pSession, pReq->u.In.pVtgHdr);
     1820            return 0;
     1821        }
     1822
     1823        case SUP_CTL_CODE_NO_SIZE(SUP_IOCTL_TRACER_UMOD_FIRE_PROBE):
     1824        {
     1825            /* validate */
     1826            PSUPTRACERUMODFIREPROBE pReq = (PSUPTRACERUMODFIREPROBE)pReqHdr;
     1827            REQ_CHECK_SIZES(SUP_IOCTL_TRACER_UMOD_FIRE_PROBE);
     1828
     1829            supdrvIOCtl_TracerUmodProbeFire(pDevExt, pSession, &pReq->u.In);
     1830            pReqHdr->rc = VINF_SUCCESS;
    18101831            return 0;
    18111832        }
  • trunk/src/VBox/HostDrivers/Support/SUPDrvIOC.h

    r40982 r41117  
    3232 */
    3333#include <iprt/types.h>
     34#include <VBox/sup.h>
    3435
    3536/*
     
    193194 *          - Remove RTSpinlockReleaseNoInts.
    194195 */
    195 #define SUPDRV_IOC_VERSION                              0x001a0001
     196#define SUPDRV_IOC_VERSION                              0x001a0002
    196197
    197198/** SUP_IOCTL_COOKIE. */
     
    12661267        struct
    12671268        {
    1268             /** Pointer to the VTG header. */
    1269             RTR3PTR         pVtgHdr;
     1269            /** The address at which the VTG header actually resides.
     1270             * This will differ from R3PtrVtgHdr for raw-mode context
     1271             * modules. */
     1272            RTUINTPTR       uVtgHdrAddr;
     1273            /** The ring-3 pointer of the VTG header. */
     1274            RTR3PTR         R3PtrVtgHdr;
     1275            /** The ring-3 pointer of the probe location string table. */
     1276            RTR3PTR         R3PtrStrTab;
     1277            /** The size of the string table. */
     1278            uint32_t        cbStrTab;
    12701279            /** Future flags, MBZ.  */
    12711280            uint32_t        fFlags;
     
    13031312
    13041313
     1314/** @name SUP_IOCTL_TRACER_UMOD_FIRE_PROBE
     1315 * Fire a probe in a user tracepoint module.
     1316 *
     1317 * @{
     1318 */
     1319#define SUP_IOCTL_TRACER_UMOD_FIRE_PROBE            SUP_CTL_CODE_SIZE(33, SUP_IOCTL_TRACER_UMOD_FIRE_PROBE_SIZE)
     1320#define SUP_IOCTL_TRACER_UMOD_FIRE_PROBE_SIZE       sizeof(SUPTRACERUMODFIREPROBE)
     1321#define SUP_IOCTL_TRACER_UMOD_FIRE_PROBE_SIZE_IN    sizeof(SUPTRACERUMODFIREPROBE)
     1322#define SUP_IOCTL_TRACER_UMOD_FIRE_PROBE_SIZE_OUT   sizeof(SUPREQHDR)
     1323typedef struct SUPTRACERUMODFIREPROBE
     1324{
     1325    /** The header. */
     1326    SUPREQHDR               Hdr;
     1327    union
     1328    {
     1329        SUPDRVTRACERUSRCTX  In;
     1330    } u;
     1331} SUPTRACERUMODFIREPROBE, *PSUPTRACERUMODFIREPROBE;
     1332/** @} */
     1333
     1334
    13051335#pragma pack()                          /* paranoia */
    13061336
  • trunk/src/VBox/HostDrivers/Support/SUPDrvInternal.h

    r41067 r41117  
    440440    /** The thread currently actively talking to the tracer. (One at the time!) */
    441441    RTNATIVETHREAD                  hTracerCaller;
     442    /** List of tracepoint providers associated with the session
     443     * (SUPDRVTPPROVIDER). */
     444    RTLISTANCHOR                    TpProviders;
     445    /** The number of providers in TpProviders. */
     446    uint32_t                        cTpProviders;
     447    /** The number of threads active in supdrvIOCtl_TracerUmodProbeFire or
     448     *  SUPR0TracerUmodProbeFire. */
     449    uint32_t volatile               cTpProbesFiring;
     450    /** User tracepoint modules (PSUPDRVTRACKERUMOD). */
     451    RTLISTANCHOR                    TpUmods;
     452    /** The user tracepoint module lookup table. */
     453    struct SUPDRVTRACERUMOD        *apTpLookupTable[32];
    442454#ifndef SUPDRV_AGNOSTIC
    443455# if defined(RT_OS_DARWIN)
     
    559571    /** The number of session having opened the tracer currently. */
    560572    uint32_t                        cTracerOpens;
     573    /** The number of threads currently calling into the tracer. */
     574    uint32_t volatile               cTracerCallers;
    561575    /** Set if the tracer is being unloaded. */
    562576    bool                            fTracerUnloading;
     577    /** Hash table for user tracer modules (SUPDRVVTGCOPY). */
     578    RTLISTANCHOR                    aTrackerUmodHash[128];
    563579
    564580    /*
     
    665681void VBOXCALL   supdrvTracerModuleUnloading(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage);
    666682void VBOXCALL   supdrvTracerCleanupSession(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession);
     683int  VBOXCALL   supdrvIOCtl_TracerUmodRegister(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession,
     684                                               RTR3PTR R3PtrVtgHdr, RTUINTPTR uVtgHdrAddr,
     685                                               RTR3PTR R3PtrStrTab, uint32_t cbStrTab,
     686                                               const char *pszModName, uint32_t fFlags);
     687int  VBOXCALL   supdrvIOCtl_TracerUmodDeregister(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, RTR3PTR R3PtrVtgHdr);
     688void  VBOXCALL  supdrvIOCtl_TracerUmodProbeFire(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, PSUPDRVTRACERUSRCTX pCtx);
    667689int  VBOXCALL   supdrvIOCtl_TracerOpen(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, uint32_t uCookie, uintptr_t uArg);
    668690int  VBOXCALL   supdrvIOCtl_TracerClose(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession);
     
    671693DECLASM(void)   supdrvTracerProbeFireStub(void);
    672694
    673 int  VBOXCALL   supdrvIOCtl_TracerUmodRegister(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, RTR3PTR pVtgHdr, const char *pszModName, uint32_t fFlags);
    674 int  VBOXCALL   supdrvIOCtl_TracerUmodDeregister(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, RTR3PTR pVtgHdr);
    675 void  VBOXCALL  supdrvIOCtl_TracerUmodProbeFire(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, PCSUPDRVTRACERUSRCTX pCtx);
    676 
    677695#ifdef VBOX_WITH_NATIVE_DTRACE
    678696const SUPDRVTRACERREG * VBOXCALL supdrvDTraceInit(void);
  • trunk/src/VBox/HostDrivers/Support/SUPDrvTracer.cpp

    r40981 r41117  
    4343#include <iprt/semaphore.h>
    4444#include <iprt/thread.h>
     45#include <iprt/param.h>
     46#include <iprt/uuid.h>
    4547
    4648
     
    4850*   Structures and Typedefs                                                    *
    4951*******************************************************************************/
     52/** Pointer to a user tracer module registration record. */
     53typedef struct SUPDRVTRACERUMOD *PSUPDRVTRACERUMOD;
     54
    5055/**
    5156 * Data for a tracepoint provider.
     
    5560    /** The entry in the provider list for this image. */
    5661    RTLISTNODE              ListEntry;
     62    /** The entry in the per session provider list for this image. */
     63    RTLISTNODE              SessionListEntry;
    5764
    5865    /** The core structure. */
     
    6572     * SUPR0VtgRegisterDrv.  NULL if pImage is set. */
    6673    PSUPDRVSESSION          pSession;
     74    /** The user tracepoint module associated with this provider.  NULL if
     75     *  pImage is set. */
     76    PSUPDRVTRACERUMOD       pUmod;
    6777
    6878    /** Used to indicate that we've called pfnProviderDeregistered already and it
     
    8393
    8494
     95/**
     96 * User tracer module VTG data copy.
     97 */
     98typedef struct SUPDRVVTGCOPY
     99{
     100    /** Magic (SUDPRVVTGCOPY_MAGIC).  */
     101    uint32_t    u32Magic;
     102    /** Refernece counter (we expect to share a lot of these). */
     103    uint32_t    cRefs;
     104    /** The size of the  */
     105    uint32_t    cbStrTab;
     106    /** Image type flags. */
     107    uint32_t    fFlags;
     108    /** Hash list entry (SUPDRVDEVEXT::aTrackerUmodHash).  */
     109    RTLISTNODE  ListEntry;
     110    /** The VTG object header.
     111     * The rest of the data follows immediately afterwards.  First the object,
     112     * then the probe locations and finally the probe location string table. All
     113     * pointers are fixed up to point within this data. */
     114    VTGOBJHDR   Hdr;
     115} SUPDRVVTGCOPY;
     116/** Pointer to a VTG object copy. */
     117typedef SUPDRVVTGCOPY *PSUPDRVVTGCOPY;
     118/** Magic value for SUPDRVVTGCOPY. */
     119#define SUDPRVVTGCOPY_MAGIC UINT32_C(0x00080386)
     120
     121
     122/**
     123 * User tracer module registration record.
     124 */
     125typedef struct SUPDRVTRACERUMOD
     126{
     127    /** Magic (SUPDRVTRACERUMOD_MAGIC).  */
     128    uint32_t                u32Magic;
     129    /** List entry.  This is anchored in SUPDRVSESSION::UmodList. */
     130    RTLISTNODE              ListEntry;
     131    /** The address of the ring-3 VTG header. */
     132    RTR3PTR                 R3PtrVtgHdr;
     133    /** Pointer to the ring-0 copy of the VTG data. */
     134    PSUPDRVVTGCOPY          pVtgCopy;
     135    /** The memory object that locks down the user memory. */
     136    RTR0MEMOBJ              hMemObjLock;
     137    /** The memory object that maps the locked memory into kernel space. */
     138    RTR0MEMOBJ              hMemObjMap;
     139    /** Pointer to the probe enabled-count array within the mapping. */
     140    uint32_t               *pacProbeEnabled;
     141    /** Pointer to the probe location array within the mapping. */
     142    void                   *pvProbeLocs;
     143    /** The address of the ring-3 probe locations. */
     144    RTR3PTR                 R3PtrProbeLocs;
     145    /** The lookup table index. */
     146    uint8_t                 iLookupTable;
     147    /** The module bit count. */
     148    uint8_t                 cBits;
     149    /** The size of a probe location record. */
     150    uint8_t                 cbProbeLoc;
     151    /** The number of probe locations. */
     152    uint32_t                cProbeLocs;
     153    /** Ring-0 probe location info. */
     154    SUPDRVPROBELOC          aProbeLocs[1];
     155} SUPDRVTRACERUMOD;
     156/** Magic value for SUPDRVVTGCOPY. */
     157#define SUPDRVTRACERUMOD_MAGIC UINT32_C(0x00080486)
     158
     159
    85160/*******************************************************************************
    86161*   Defined Constants And Macros                                               *
     
    99174/** The address of the current probe fire routine for kernel mode. */
    100175PFNRT       g_pfnSupdrvProbeFireKernel = supdrvTracerProbeFireStub;
     176
     177
     178/*******************************************************************************
     179*   Internal Functions                                                         *
     180*******************************************************************************/
     181static void supdrvVtgReleaseObjectCopy(PSUPDRVDEVEXT pDevExt, PSUPDRVVTGCOPY pThis);
    101182
    102183
     
    136217
    137218
    138 /**
    139  * Validates the VTG data.
    140  *
    141  * @returns VBox status code.
    142  * @param   pVtgHdr             The VTG object header of the data to validate.
    143  * @param   cbVtgObj            The size of the VTG object.
    144  * @param   pbImage             The image base. For validating the probe
    145  *                              locations.
    146  * @param   cbImage             The image size to go with @a pbImage.
    147  */
    148 static int supdrvVtgValidate(PVTGOBJHDR pVtgHdr, size_t cbVtgObj, const uint8_t *pbImage, size_t cbImage)
    149 {
    150     uintptr_t   cbTmp;
    151     uintptr_t   offTmp;
    152     uintptr_t   i;
    153     uintptr_t   cProviders;
    154     int         rc;
    155 
    156     if (!pbImage || !cbImage)
    157     {
    158         pbImage = NULL;
    159         cbImage = 0;
    160     }
    161 
    162 #define MY_VALIDATE_PTR(p, cb, cMin, cMax, cbUnit, rcBase) \
    163     do { \
    164         if (   (cb) >= cbVtgObj \
    165             || (uintptr_t)(p) - (uintptr_t)pVtgHdr > cbVtgObj - (cb) ) \
    166         { \
    167             SUPR0Printf("supdrvVtgValidate: " #rcBase "_TOO_PTR - p=%p cb=%#zx pVtgHdr=%p cbVtgHdr=%#zu line=%u %s\n", \
    168                         p, (size_t)(cb), pVtgHdr, cbVtgObj, __LINE__, #p); \
    169             return rcBase ## _PTR; \
    170         } \
    171         if ((cb) <  (cMin) * (cbUnit)) \
    172         { \
    173             SUPR0Printf("supdrvVtgValidate: " #rcBase "_TOO_FEW - cb=%#zx cMin=%#zx cbUnit=%#zx line=%u %s\n", \
    174                         (size_t)(cb), (size_t)(cMin), (size_t)cbUnit, __LINE__, #p); \
    175             return rcBase ## _TOO_FEW; \
    176         } \
    177         if ((cb) >= (cMax) * (cbUnit)) \
    178         { \
    179             SUPR0Printf("supdrvVtgValidate: " #rcBase "_TOO_MUCH - cb=%#zx cMax=%#zx cbUnit=%#zx line=%u %s\n", \
    180                         (size_t)(cb), (size_t)(cMax), (size_t)cbUnit, __LINE__, #p); \
    181             return rcBase ## _TOO_MUCH; \
    182         } \
    183         if ((cb) / (cbUnit) * (cbUnit) != (cb)) \
    184         { \
    185             SUPR0Printf("supdrvVtgValidate: " #rcBase "_NOT_MULTIPLE - cb=%#zx cbUnit=%#zx line=%u %s\n", \
    186                         (size_t)(cb), (size_t)cbUnit, __LINE__, #p); \
    187             return rcBase ## _NOT_MULTIPLE; \
    188         } \
    189     } while (0)
     219/** Used by the validation code below. */
     220#define MY_CHECK_RET(a_Expr, a_rc) \
     221    MY_CHECK_MSG_RET(a_Expr, ("%s: Validation failed on line " RT_XSTR(__LINE__) ": " #a_Expr "\n", __FUNCTION__), a_rc)
     222
     223/** Used by the validation code below. */
     224#define MY_CHECK_MSG_RET(a_Expr, a_PrintfArgs, a_rc) \
     225    do { if (RT_UNLIKELY(!(a_Expr))) { SUPR0Printf a_PrintfArgs; return (a_rc); } } while (0)
     226
     227/** Used by the validation code below. */
    190228#define MY_WITHIN_IMAGE(p, rc) \
    191229    do { \
     
    202240            return (rc); \
    203241    } while (0)
    204 #define MY_VALIDATE_STR(offStrTab) \
     242
     243
     244/**
     245 * Validates the VTG object header.
     246 *
     247 * @returns VBox status code.
     248 * @param   pVtgHdr             The header.
     249 * @param   uVtgHdrAddr         The address where the header is actually
     250 *                              loaded.
     251 * @param   cbVtgObj            The alleged size of the header.
     252 * @param   pbImage             The image base, if available.
     253 * @param   cbImage             The image size, if available.
     254 * @param   fUmod               Whether this is a user module.
     255 */
     256static int supdrvVtgValidateHdr(PVTGOBJHDR pVtgHdr, RTUINTPTR uVtgHdrAddr, const uint8_t *pbImage, size_t cbImage, bool fUmod)
     257{
     258    struct VTGAREAS
     259    {
     260        uint32_t off;
     261        uint32_t cb;
     262    } const        *paAreas;
     263    unsigned        cAreas;
     264    unsigned        i;
     265    uint32_t        cbVtgObj;
     266    uint32_t        off;
     267
     268#define MY_VALIDATE_SIZE(cb, cMin, cMax, cbUnit, rcBase) \
    205269    do { \
    206         if ((offStrTab) >= pVtgHdr->cbStrTab) \
     270        if ((cb) <  (cMin) * (cbUnit)) \
     271        { \
     272            SUPR0Printf("supdrvVtgValidateHdr: " #rcBase "_TOO_FEW - cb=%#zx cMin=%#zx cbUnit=%#zx line=%u %s\n", \
     273                        (size_t)(cb), (size_t)(cMin), (size_t)cbUnit, __LINE__, #cb); \
     274            return rcBase ## _TOO_FEW; \
     275        } \
     276        if ((cb) >= (cMax) * (cbUnit)) \
     277        { \
     278            SUPR0Printf("supdrvVtgValidateHdr: " #rcBase "_TOO_MUCH - cb=%#zx cMax=%#zx cbUnit=%#zx line=%u %s\n", \
     279                        (size_t)(cb), (size_t)(cMax), (size_t)cbUnit, __LINE__, #cb); \
     280            return rcBase ## _TOO_MUCH; \
     281        } \
     282        if ((cb) / (cbUnit) * (cbUnit) != (cb)) \
     283        { \
     284            SUPR0Printf("supdrvVtgValidateHdr: " #rcBase "_NOT_MULTIPLE - cb=%#zx cbUnit=%#zx line=%u %s\n", \
     285                        (size_t)(cb), (size_t)cbUnit, __LINE__, #cb); \
     286            return rcBase ## _NOT_MULTIPLE; \
     287        } \
     288    } while (0)
     289
     290#define MY_VALIDATE_OFF(off, cb, cMin, cMax, cbUnit, cbAlign, rcBase) \
     291    do { \
     292        if (   (cb) >= cbVtgObj \
     293            || off > cbVtgObj - (cb) ) \
     294        { \
     295            SUPR0Printf("supdrvVtgValidateHdr: " #rcBase "_OFF - off=%#x cb=%#x pVtgHdr=%p cbVtgHdr=%#zx line=%u %s\n", \
     296                        (off), (cb), pVtgHdr, cbVtgObj, __LINE__, #off); \
     297            return rcBase ## _OFF; \
     298        } \
     299        if (RT_ALIGN(off, cbAlign) != (off)) \
     300        { \
     301            SUPR0Printf("supdrvVtgValidateHdr: " #rcBase "_OFF - off=%#x align=%#zx line=%u %s\n", \
     302                        (off), (size_t)(cbAlign), __LINE__, #off); \
     303            return rcBase ## _OFF; \
     304        } \
     305        MY_VALIDATE_SIZE(cb, cMin, cMax, cbUnit, rcBase); \
     306    } while (0)
     307
     308    /*
     309     * Make sure both pbImage and cbImage are NULL/0 if one if of them is.
     310     */
     311    if (!pbImage || !cbImage)
     312    {
     313        pbImage = NULL;
     314        cbImage = 0;
     315        cbVtgObj = pVtgHdr->cbObj;
     316    }
     317    else
     318    {
     319        MY_WITHIN_IMAGE(pVtgHdr, VERR_SUPDRV_VTG_BAD_HDR_PTR);
     320        cbVtgObj = pVtgHdr->cbObj;
     321        MY_WITHIN_IMAGE((uint8_t *)pVtgHdr + cbVtgObj - 1, VERR_SUPDRV_VTG_BAD_HDR_PTR);
     322    }
     323
     324    if (cbVtgObj > _1M)
     325    {
     326        SUPR0Printf("supdrvVtgValidateHdr: VERR_SUPDRV_TRACER_TOO_LARGE - cbVtgObj=%#x\n", cbVtgObj);
     327        return VERR_SUPDRV_TRACER_TOO_LARGE;
     328    }
     329
     330    /*
     331     * Set the probe location array offset and size members.
     332     */
     333    if (!pVtgHdr->offProbeLocs)
     334    {
     335        uint64_t u64Tmp = pVtgHdr->uProbeLocsEnd.u64 - pVtgHdr->uProbeLocs.u64;
     336        if (u64Tmp >= UINT32_MAX)
     337            return VERR_SUPDRV_VTG_BAD_HDR_TOO_MUCH;
     338        pVtgHdr->cbProbeLocs  = (uint32_t)u64Tmp;
     339
     340        u64Tmp = pVtgHdr->uProbeLocs.u64 - uVtgHdrAddr;
     341        if ((int64_t)u64Tmp != (int32_t)u64Tmp)
     342            return VERR_SUPDRV_VTG_BAD_HDR_PTR;
     343        pVtgHdr->offProbeLocs = (int32_t)u64Tmp;
     344    }
     345
     346    /*
     347     * The non-area description fields.
     348     */
     349    if (memcmp(pVtgHdr->szMagic, VTGOBJHDR_MAGIC, sizeof(pVtgHdr->szMagic)))
     350        return VERR_SUPDRV_VTG_MAGIC;
     351    if (   pVtgHdr->cBits != ARCH_BITS
     352        && (   !fUmod
     353            || (   pVtgHdr->cBits != 32
     354                && pVtgHdr->cBits != 64)) )
     355        return VERR_SUPDRV_VTG_BITS;
     356    if (   pVtgHdr->au32Reserved1[0]
     357        || pVtgHdr->au32Reserved1[1]
     358        || pVtgHdr->au32Reserved1[2]
     359        || pVtgHdr->au32Reserved1[3])
     360        return VERR_SUPDRV_VTG_BAD_HDR_MISC;
     361    if (RTUuidIsNull(&pVtgHdr->Uuid))
     362        return VERR_SUPDRV_VTG_BAD_HDR_MISC;
     363
     364    /*
     365     * Check the individual area descriptors.
     366     */
     367    MY_VALIDATE_OFF(pVtgHdr->offStrTab,          pVtgHdr->cbStrTab,       4,   _1M, sizeof(char),            sizeof(uint8_t),  VERR_SUPDRV_VTG_BAD_HDR);
     368    MY_VALIDATE_OFF(pVtgHdr->offArgLists,        pVtgHdr->cbArgLists,     1,  _32K, sizeof(uint32_t),        sizeof(uint32_t), VERR_SUPDRV_VTG_BAD_HDR);
     369    MY_VALIDATE_OFF(pVtgHdr->offProbes,          pVtgHdr->cbProbes,       1,  _32K, sizeof(VTGDESCPROBE),    sizeof(uint32_t), VERR_SUPDRV_VTG_BAD_HDR);
     370    MY_VALIDATE_OFF(pVtgHdr->offProviders,       pVtgHdr->cbProviders,    1,    16, sizeof(VTGDESCPROVIDER), sizeof(uint32_t), VERR_SUPDRV_VTG_BAD_HDR);
     371    MY_VALIDATE_OFF(pVtgHdr->offProbeEnabled,    pVtgHdr->cbProbeEnabled, 1,  _32K, sizeof(uint32_t),        sizeof(uint32_t), VERR_SUPDRV_VTG_BAD_HDR);
     372    if (!fUmod)
     373    {
     374        MY_WITHIN_IMAGE(pVtgHdr->uProbeLocs.p,    VERR_SUPDRV_VTG_BAD_HDR_PTR);
     375        MY_WITHIN_IMAGE(pVtgHdr->uProbeLocsEnd.p, VERR_SUPDRV_VTG_BAD_HDR_PTR);
     376        MY_VALIDATE_SIZE(                        pVtgHdr->cbProbeLocs,    1, _128K, sizeof(VTGPROBELOC),     VERR_SUPDRV_VTG_BAD_HDR);
     377    }
     378    else
     379    {
     380        if (pVtgHdr->cBits == 32)
     381            MY_VALIDATE_SIZE(                   pVtgHdr->cbProbeLocs,    1, _8K,   sizeof(VTGPROBELOC32),    VERR_SUPDRV_VTG_BAD_HDR);
     382        else
     383            MY_VALIDATE_SIZE(                   pVtgHdr->cbProbeLocs,    1, _8K,   sizeof(VTGPROBELOC64),    VERR_SUPDRV_VTG_BAD_HDR);
     384        /* Will check later that offProbeLocs are following closely on the
     385           enable count array, so no need to validate the offset here. */
     386    }
     387
     388    /*
     389     * Some additional consistency checks.
     390     */
     391    if (   pVtgHdr->uProbeLocsEnd.u64 - pVtgHdr->uProbeLocs.u64 != pVtgHdr->cbProbeLocs
     392        || (int64_t)(pVtgHdr->uProbeLocs.u64 - uVtgHdrAddr)     != pVtgHdr->offProbeLocs)
     393    {
     394        SUPR0Printf("supdrvVtgValidateHdr: VERR_SUPDRV_VTG_BAD_HDR_MISC - uProbeLocs=%#llx uProbeLocsEnd=%#llx offProbeLocs=%#llx cbProbeLocs=%#x uVtgHdrAddr=%RTptr\n",
     395                    pVtgHdr->uProbeLocs.u64, pVtgHdr->uProbeLocsEnd.u64, pVtgHdr->offProbeLocs, pVtgHdr->cbProbeLocs, uVtgHdrAddr);
     396        return VERR_SUPDRV_VTG_BAD_HDR_MISC;
     397    }
     398
     399    if (pVtgHdr->cbProbes / sizeof(VTGDESCPROBE) != pVtgHdr->cbProbeEnabled / sizeof(uint32_t))
     400    {
     401        SUPR0Printf("supdrvVtgValidateHdr: VERR_SUPDRV_VTG_BAD_HDR_MISC - cbProbeEnabled=%#zx cbProbes=%#zx\n",
     402                    pVtgHdr->cbProbeEnabled, pVtgHdr->cbProbes);
     403        return VERR_SUPDRV_VTG_BAD_HDR_MISC;
     404    }
     405
     406    /*
     407     * Check that there are no overlapping areas.  This is a little bit ugly...
     408     */
     409    paAreas = (struct VTGAREAS const *)&pVtgHdr->offStrTab;
     410    cAreas  = pVtgHdr->offProbeLocs >= 0 ? 6 : 5;
     411    off     = sizeof(VTGOBJHDR);
     412    for (i = 0; i < cAreas; i++)
     413    {
     414        if (paAreas[i].off < off)
     415        {
     416            SUPR0Printf("supdrvVtgValidateHdr: VERR_SUPDRV_VTG_BAD_HDR_MISC - overlapping areas %d and %d\n", i, i-1);
     417            return VERR_SUPDRV_VTG_BAD_HDR_MISC;
     418        }
     419        off = paAreas[i].off + paAreas[i].cb;
     420    }
     421    if (   pVtgHdr->offProbeLocs > 0
     422        && (uint32_t)-pVtgHdr->offProbeLocs < pVtgHdr->cbProbeLocs)
     423    {
     424        SUPR0Printf("supdrvVtgValidateHdr: VERR_SUPDRV_VTG_BAD_HDR_MISC - probe locations overlaps the header\n");
     425        return VERR_SUPDRV_VTG_BAD_HDR_MISC;
     426    }
     427
     428    /*
     429     * Check that the object size is correct.
     430     */
     431    if (pVtgHdr->cbObj != pVtgHdr->offProbeEnabled + pVtgHdr->cbProbeEnabled)
     432    {
     433        SUPR0Printf("supdrvVtgValidateHdr: VERR_SUPDRV_VTG_BAD_HDR_MISC - bad header size %#x, expected %#x\n",
     434                    pVtgHdr->cbObj, pVtgHdr->offProbeEnabled + pVtgHdr->cbProbeEnabled);
     435        return VERR_SUPDRV_VTG_BAD_HDR_MISC;
     436    }
     437
     438
     439    return VINF_SUCCESS;
     440#undef MY_VALIDATE_OFF
     441#undef MY_VALIDATE_SIZE
     442}
     443
     444
     445/**
     446 * Validates the VTG data.
     447 *
     448 * @returns VBox status code.
     449 * @param   pVtgHdr             The VTG object header of the data to validate.
     450 * @param   uVtgHdrAddr         The address where the header is actually
     451 *                              loaded.
     452 * @param   pbImage             The image base. For validating the probe
     453 *                              locations.
     454 * @param   cbImage             The image size to go with @a pbImage.
     455 * @param   fUmod               Whether this is a user module.
     456 */
     457static int supdrvVtgValidate(PVTGOBJHDR pVtgHdr, RTUINTPTR uVtgHdrAddr, const uint8_t *pbImage, size_t cbImage, bool fUmod)
     458{
     459    uintptr_t   offTmp;
     460    uintptr_t   i;
     461    uintptr_t   cProviders;
     462    int         rc;
     463
     464    if (!pbImage || !cbImage)
     465    {
     466        pbImage = NULL;
     467        cbImage = 0;
     468    }
     469
     470#define MY_VALIDATE_STR(a_offStrTab) \
     471    do { \
     472        if ((a_offStrTab) >= pVtgHdr->cbStrTab) \
    207473            return VERR_SUPDRV_VTG_STRTAB_OFF; \
    208         rc = supdrvVtgValidateString(pVtgHdr->pachStrTab + (offStrTab)); \
     474        rc = supdrvVtgValidateString((char *)pVtgHdr + pVtgHdr->offStrTab + (a_offStrTab)); \
    209475        if (rc != VINF_SUCCESS) \
    210476            return rc; \
     
    223489     * The header.
    224490     */
    225     if (memcmp(pVtgHdr->szMagic, VTGOBJHDR_MAGIC, sizeof(pVtgHdr->szMagic)))
    226         return VERR_SUPDRV_VTG_MAGIC;
    227     if (pVtgHdr->cBits != ARCH_BITS)
    228         return VERR_SUPDRV_VTG_BITS;
    229     if (pVtgHdr->u32Reserved0)
    230         return VERR_SUPDRV_VTG_BAD_HDR;
    231 
    232     MY_VALIDATE_PTR(pVtgHdr->paProviders,       pVtgHdr->cbProviders,    1,    16, sizeof(VTGDESCPROVIDER), VERR_SUPDRV_VTG_BAD_HDR);
    233     MY_VALIDATE_PTR(pVtgHdr->paProbes,          pVtgHdr->cbProbes,       1,  _32K, sizeof(VTGDESCPROBE),    VERR_SUPDRV_VTG_BAD_HDR);
    234     MY_VALIDATE_PTR(pVtgHdr->pafProbeEnabled,   pVtgHdr->cbProbeEnabled, 1,  _32K, sizeof(bool),            VERR_SUPDRV_VTG_BAD_HDR);
    235     MY_VALIDATE_PTR(pVtgHdr->pachStrTab,        pVtgHdr->cbStrTab,       4,   _1M, sizeof(char),            VERR_SUPDRV_VTG_BAD_HDR);
    236     MY_VALIDATE_PTR(pVtgHdr->paArgLists,        pVtgHdr->cbArgLists,     1,  _32K, sizeof(uint32_t),        VERR_SUPDRV_VTG_BAD_HDR);
    237 
    238     MY_WITHIN_IMAGE(pVtgHdr->paProbLocs,    VERR_SUPDRV_VTG_BAD_HDR_PTR);
    239     MY_WITHIN_IMAGE(pVtgHdr->paProbLocsEnd, VERR_SUPDRV_VTG_BAD_HDR_PTR);
    240     if ((uintptr_t)pVtgHdr->paProbLocs > (uintptr_t)pVtgHdr->paProbLocsEnd)
    241     {
    242         SUPR0Printf("supdrvVtgValidate: VERR_SUPDRV_VTG_BAD_HDR_PTR - paProbeLocs=%p > paProbLocsEnd=%p\n",
    243                     pVtgHdr->paProbLocs, pVtgHdr->paProbLocsEnd);
    244         return VERR_SUPDRV_VTG_BAD_HDR_PTR;
    245     }
    246     cbTmp = (uintptr_t)pVtgHdr->paProbLocsEnd - (uintptr_t)pVtgHdr->paProbLocs;
    247     if (cbTmp < sizeof(VTGPROBELOC))
    248     {
    249         SUPR0Printf("supdrvVtgValidate: VERR_SUPDRV_VTG_BAD_HDR_TOO_FEW - cbTmp=%#zx paProbeLocs=%p paProbLocsEnd=%p\n",
    250                     cbTmp, pVtgHdr->paProbLocs, pVtgHdr->paProbLocsEnd);
    251         return VERR_SUPDRV_VTG_BAD_HDR_TOO_FEW;
    252     }
    253     if (cbTmp >= _128K * sizeof(VTGPROBELOC))
    254     {
    255         SUPR0Printf("supdrvVtgValidate: VERR_SUPDRV_VTG_BAD_HDR_TOO_MUCH - cbTmp=%#zx paProbeLocs=%p paProbLocsEnd=%p\n",
    256                     cbTmp, pVtgHdr->paProbLocs, pVtgHdr->paProbLocsEnd);
    257         return VERR_SUPDRV_VTG_BAD_HDR_TOO_MUCH;
    258     }
    259     if (cbTmp / sizeof(VTGPROBELOC) * sizeof(VTGPROBELOC) != cbTmp)
    260     {
    261         SUPR0Printf("supdrvVtgValidate: VERR_SUPDRV_VTG_BAD_HDR_NOT_MULTIPLE - cbTmp=%#zx cbUnit=%#zx paProbeLocs=%p paProbLocsEnd=%p\n",
    262                     cbTmp, sizeof(VTGPROBELOC), pVtgHdr->paProbLocs, pVtgHdr->paProbLocsEnd);
    263         return VERR_SUPDRV_VTG_BAD_HDR_NOT_MULTIPLE;
    264     }
    265 
    266     if (pVtgHdr->cbProbes / sizeof(VTGDESCPROBE) != pVtgHdr->cbProbeEnabled)
    267     {
    268         SUPR0Printf("supdrvVtgValidate: VERR_SUPDRV_VTG_BAD_HDR - cbProbeEnabled=%#zx cbProbes=%#zx\n",
    269                     pVtgHdr->cbProbeEnabled, pVtgHdr->cbProbes);
    270         return VERR_SUPDRV_VTG_BAD_HDR;
    271     }
     491    rc = supdrvVtgValidateHdr(pVtgHdr, uVtgHdrAddr, pbImage, cbImage, fUmod);
     492    if (RT_FAILURE(rc))
     493        return rc;
    272494
    273495    /*
     
    277499    while (i-- > 0)
    278500    {
    279         MY_VALIDATE_STR(pVtgHdr->paProviders[i].offName);
    280         if (pVtgHdr->paProviders[i].iFirstProbe >= pVtgHdr->cbProbeEnabled)
    281             return VERR_SUPDRV_VTG_BAD_PROVIDER;
    282         if (pVtgHdr->paProviders[i].iFirstProbe + pVtgHdr->paProviders[i].cProbes > pVtgHdr->cbProbeEnabled)
    283             return VERR_SUPDRV_VTG_BAD_PROVIDER;
    284         MY_VALIDATE_ATTR(pVtgHdr->paProviders[i].AttrSelf);
    285         MY_VALIDATE_ATTR(pVtgHdr->paProviders[i].AttrModules);
    286         MY_VALIDATE_ATTR(pVtgHdr->paProviders[i].AttrFunctions);
    287         MY_VALIDATE_ATTR(pVtgHdr->paProviders[i].AttrNames);
    288         MY_VALIDATE_ATTR(pVtgHdr->paProviders[i].AttrArguments);
    289         if (pVtgHdr->paProviders[i].bReserved)
    290             return VERR_SUPDRV_VTG_BAD_PROVIDER;
     501        PCVTGDESCPROVIDER pProvider = (PCVTGDESCPROVIDER)((uintptr_t)pVtgHdr + pVtgHdr->offProviders) + i;
     502
     503        MY_VALIDATE_STR(pProvider->offName);
     504        MY_CHECK_RET(pProvider->iFirstProbe < pVtgHdr->cbProbeEnabled / sizeof(uint32_t), VERR_SUPDRV_VTG_BAD_PROVIDER);
     505        MY_CHECK_RET((uint32_t)pProvider->iFirstProbe + pProvider->cProbes <= pVtgHdr->cbProbeEnabled / sizeof(uint32_t),
     506                     VERR_SUPDRV_VTG_BAD_PROVIDER);
     507        MY_VALIDATE_ATTR(pProvider->AttrSelf);
     508        MY_VALIDATE_ATTR(pProvider->AttrModules);
     509        MY_VALIDATE_ATTR(pProvider->AttrFunctions);
     510        MY_VALIDATE_ATTR(pProvider->AttrNames);
     511        MY_VALIDATE_ATTR(pProvider->AttrArguments);
     512        MY_CHECK_RET(pProvider->bReserved == 0, VERR_SUPDRV_VTG_BAD_PROVIDER);
    291513    }
    292514
     
    297519    while (i-- > 0)
    298520    {
    299         PVTGDESCARGLIST pArgList;
    300         unsigned        iArg;
    301         bool            fHaveLargeArgs;
    302 
    303         MY_VALIDATE_STR(pVtgHdr->paProbes[i].offName);
    304         if (pVtgHdr->paProbes[i].offArgList >= pVtgHdr->cbArgLists)
     521        PCVTGDESCPROBE      pProbe    = (PCVTGDESCPROBE)(   (uintptr_t)pVtgHdr + pVtgHdr->offProbes)    + i;
     522        PCVTGDESCPROVIDER   pProvider = (PCVTGDESCPROVIDER)((uintptr_t)pVtgHdr + pVtgHdr->offProviders) + pProbe->idxProvider;
     523        PCVTGDESCARGLIST    pArgList  = (PCVTGDESCARGLIST)( (uintptr_t)pVtgHdr + pVtgHdr->offArgLists + pProbe->offArgList );
     524        unsigned            iArg;
     525        bool                fHaveLargeArgs;
     526
     527
     528        MY_VALIDATE_STR(pProbe->offName);
     529        MY_CHECK_RET(pProbe->offArgList < pVtgHdr->cbArgLists, VERR_SUPDRV_VTG_BAD_PROBE);
     530        MY_CHECK_RET((pProbe->offArgList & 3) == 0, VERR_SUPDRV_VTG_BAD_PROBE);
     531        MY_CHECK_RET(pProbe->idxEnabled == i, VERR_SUPDRV_VTG_BAD_PROBE); /* The lists are parallel. */
     532        MY_CHECK_RET(pProbe->idxProvider < cProviders, VERR_SUPDRV_VTG_BAD_PROBE);
     533        MY_CHECK_RET(i - pProvider->iFirstProbe < pProvider->cProbes, VERR_SUPDRV_VTG_BAD_PROBE);
     534        if (pProbe->offObjHdr != (intptr_t)pVtgHdr - (intptr_t)pProbe)
     535        {
     536            SUPR0Printf("supdrvVtgValidate: VERR_SUPDRV_TRACER_BAD_ARG_FLAGS - iProbe=%u offObjHdr=%d expected %zd\n",
     537                        i, pProbe->offObjHdr, (intptr_t)pVtgHdr - (intptr_t)pProbe);
    305538            return VERR_SUPDRV_VTG_BAD_PROBE;
    306         if (pVtgHdr->paProbes[i].offArgList & 3)
    307             return VERR_SUPDRV_VTG_BAD_PROBE;
    308         if (pVtgHdr->paProbes[i].idxEnabled != i) /* The lists are parallel. */
    309             return VERR_SUPDRV_VTG_BAD_PROBE;
    310         if (pVtgHdr->paProbes[i].idxProvider >= cProviders)
    311             return VERR_SUPDRV_VTG_BAD_PROBE;
    312         if (  i - pVtgHdr->paProviders[pVtgHdr->paProbes[i].idxProvider].iFirstProbe
    313             >= pVtgHdr->paProviders[pVtgHdr->paProbes[i].idxProvider].cProbes)
    314             return VERR_SUPDRV_VTG_BAD_PROBE;
    315         if (pVtgHdr->paProbes[i].u32User)
    316             return VERR_SUPDRV_VTG_BAD_PROBE;
    317         if (pVtgHdr->paProbes[i].u32User2)
    318             return VERR_SUPDRV_VTG_BAD_PROBE;
    319         if (   pVtgHdr->paProbes[i].offObjHdr
    320             != (intptr_t)pVtgHdr - (intptr_t)&pVtgHdr->paProbes[i])
    321         {
    322             SUPR0Printf("supdrvVtgValidate: VERR_SUPDRV_TRACER_BAD_ARG_FLAGS - iProbe=%u offObjHdr=%d expected %zd\n",
    323                         i, pVtgHdr->paProbes[i].offObjHdr, (intptr_t)pVtgHdr - (intptr_t)&pVtgHdr->paProbes[i]);
    324             return VERR_SUPDRV_VTG_BAD_PROBE;
    325539        }
    326540
    327541        /* The referenced argument list. */
    328         pArgList = (PVTGDESCARGLIST)((uintptr_t)pVtgHdr->paArgLists + pVtgHdr->paProbes[i].offArgList);
    329542        if (pArgList->cArgs > 16)
    330543        {
     
    383596
    384597    /*
    385      * Check that pafProbeEnabled is all zero.
    386      */
    387     i = pVtgHdr->cbProbeEnabled;
    388     while (i-- > 0)
    389         if (pVtgHdr->pafProbeEnabled[0])
    390             return VERR_SUPDRV_VTG_BAD_PROBE_ENABLED;
     598     * Check that pacProbeEnabled is all zeros.
     599     */
     600    {
     601        uint32_t const *pcProbeEnabled = (uint32_t const *)((uintptr_t)pVtgHdr + pVtgHdr->offProbeEnabled);
     602        i = pVtgHdr->cbProbeEnabled / sizeof(uint32_t);
     603        while (i-- > 0)
     604            MY_CHECK_RET(pcProbeEnabled[0] == 0, VERR_SUPDRV_VTG_BAD_PROBE_ENABLED);
     605    }
    391606
    392607    /*
    393608     * Probe locations.
    394609     */
    395     i = pVtgHdr->paProbLocsEnd - pVtgHdr->paProbLocs;
    396     while (i-- > 0)
    397     {
    398         if (pVtgHdr->paProbLocs[i].uLine >= _1G)
    399             return VERR_SUPDRV_VTG_BAD_PROBE_LOC;
    400         if (pVtgHdr->paProbLocs[i].fEnabled)
    401             return VERR_SUPDRV_VTG_BAD_PROBE_LOC;
    402         if (pVtgHdr->paProbLocs[i].idProbe != UINT32_MAX)
    403             return VERR_SUPDRV_VTG_BAD_PROBE_LOC;
    404         MY_WITHIN_IMAGE(pVtgHdr->paProbLocs[i].pszFunction, VERR_SUPDRV_VTG_BAD_PROBE_LOC);
    405         offTmp = (uintptr_t)pVtgHdr->paProbLocs[i].pbProbe - (uintptr_t)pVtgHdr->paProbes;
    406         if (offTmp >= pVtgHdr->cbProbes)
    407             return VERR_SUPDRV_VTG_BAD_PROBE_LOC;
    408         if (offTmp / sizeof(VTGDESCPROBE) * sizeof(VTGDESCPROBE) != offTmp)
    409             return VERR_SUPDRV_VTG_BAD_PROBE_LOC;
     610    {
     611        PCVTGPROBELOC paProbeLocs = (PCVTGPROBELOC)((intptr_t)pVtgHdr + pVtgHdr->offProbeLocs);
     612        i = pVtgHdr->cbProbeLocs / sizeof(VTGPROBELOC);
     613        while (i-- > 0)
     614        {
     615            MY_CHECK_RET(paProbeLocs[i].uLine < _1G, VERR_SUPDRV_VTG_BAD_PROBE_LOC);
     616            MY_CHECK_RET(paProbeLocs[i].fEnabled == false, VERR_SUPDRV_VTG_BAD_PROBE_LOC);
     617            MY_CHECK_RET(paProbeLocs[i].idProbe == 0, VERR_SUPDRV_VTG_BAD_PROBE_LOC);
     618            MY_WITHIN_IMAGE(paProbeLocs[i].pszFunction, VERR_SUPDRV_VTG_BAD_PROBE_LOC);
     619            offTmp = (uintptr_t)paProbeLocs[i].pbProbe - (uintptr_t)pVtgHdr->offProbes - (uintptr_t)pVtgHdr;
     620            MY_CHECK_RET(offTmp < pVtgHdr->cbProbes, VERR_SUPDRV_VTG_BAD_PROBE_LOC);
     621            MY_CHECK_RET(offTmp / sizeof(VTGDESCPROBE) * sizeof(VTGDESCPROBE) == offTmp, VERR_SUPDRV_VTG_BAD_PROBE_LOC);
     622        }
    410623    }
    411624
    412625    return VINF_SUCCESS;
     626}
     627
    413628#undef MY_VALIDATE_STR
    414 #undef MY_VALIDATE_PTR
     629#undef MY_VALIDATE_ATTR
    415630#undef MY_WITHIN_IMAGE
    416 }
    417631
    418632
     
    427641{
    428642    Assert(offStrTab < pVtgHdr->cbStrTab);
    429     return &pVtgHdr->pachStrTab[offStrTab];
     643    return (char *)pVtgHdr + pVtgHdr->offStrTab + offStrTab;
    430644}
    431645
     
    439653{
    440654    LOG_TRACER(("Freeing tracepoint provider '%s' / %p\n", pProv->szName, pProv->Core.TracerData.DTrace.idProvider));
    441     pProv->fRegistered = false;
    442     pProv->fZombie     = true;
    443     pProv->Core.pDesc  = NULL;
    444     pProv->Core.pHdr   = NULL;
     655    pProv->fRegistered          = false;
     656    pProv->fZombie              = true;
     657    pProv->Core.pDesc           = NULL;
     658    pProv->Core.pHdr            = NULL;
     659    pProv->Core.paProbeLocsRO   = NULL;
     660    pProv->Core.pvProbeLocsEn   = NULL;
     661    pProv->Core.pacProbeEnabled = NULL;
     662    pProv->Core.paR0ProbeLocs   = NULL;
     663    pProv->Core.paR0Probes      = NULL;
    445664    RT_ZERO(pProv->Core.TracerData);
    446665    RTMemFree(pProv);
     
    449668
    450669/**
    451  * Deregisters a provider.
     670 * Unlinks and deregisters a provider.
    452671 *
    453672 * If the provider is still busy, it will be put in the zombie list.
     
    461680{
    462681    int rc;
     682
     683    RTListNodeRemove(&pProv->ListEntry);
     684    if (pProv->pSession)
     685    {
     686        RTListNodeRemove(&pProv->SessionListEntry);
     687        RTListInit(&pProv->SessionListEntry);
     688        pProv->pSession->cTpProviders--;
     689    }
     690
    463691    if (!pProv->fRegistered || !pDevExt->pTracerOps)
    464692        rc = VINF_SUCCESS;
     
    471699    }
    472700
    473     pProv->fZombie = true;
     701    pProv->fZombie              = true;
     702    pProv->pImage               = NULL;
     703    pProv->pSession             = NULL;
     704    pProv->pUmod                = NULL;
     705    pProv->Core.pDesc           = NULL;
     706    pProv->Core.pHdr            = NULL;
     707    pProv->Core.paProbeLocsRO   = NULL;
     708    pProv->Core.pvProbeLocsEn   = NULL;
     709    pProv->Core.pacProbeEnabled = NULL;
     710    pProv->Core.paR0ProbeLocs   = NULL;
     711
    474712    RTListAppend(&pDevExt->TracerProviderZombieList, &pProv->ListEntry);
    475713    LOG_TRACER(("Invalidated provider '%s' / %p and put it on the zombie list (rc=%Rrc)\n",
     
    521759    RTListForEachSafe(&pDevExt->TracerProviderList, pProv, pProvNext, SUPDRVTPPROVIDER, ListEntry)
    522760    {
    523         RTListNodeRemove(&pProv->ListEntry);
    524761        supdrvTracerDeregisterVtgObj(pDevExt, pProv);
    525762    }
     
    589826 * @param   pszName             The driver name.
    590827 * @param   pVtgHdr             The VTG object header.
    591  * @param   pVtgObj             The size of the VTG object.
    592828 * @param   pImage              The image if applicable.
    593829 * @param   pSession            The session if applicable.
     830 * @param   pUmod               The associated user tracepoint module if
     831 *                              applicable.
    594832 * @param   pszModName          The module name.
    595833 */
    596 static int supdrvTracerRegisterVtgObj(PSUPDRVDEVEXT pDevExt, PVTGOBJHDR pVtgHdr, size_t cbVtgObj, PSUPDRVLDRIMAGE pImage,
    597                                       PSUPDRVSESSION pSession, const char *pszModName)
     834static int supdrvTracerRegisterVtgObj(PSUPDRVDEVEXT pDevExt, PVTGOBJHDR pVtgHdr, PSUPDRVLDRIMAGE pImage,
     835                                      PSUPDRVSESSION pSession, PSUPDRVTRACERUMOD pUmod, const char *pszModName)
    598836{
    599837    int                 rc;
    600838    uintptr_t           i;
    601839    PSUPDRVTPPROVIDER   pProv;
     840    size_t              cchModName;
    602841
    603842    /*
     
    609848    AssertPtrNullReturn(pSession, VERR_INVALID_POINTER);
    610849    AssertPtrReturn(pszModName, VERR_INVALID_POINTER);
     850    cchModName = strlen(pszModName);
    611851
    612852    if (pImage)
    613         rc = supdrvVtgValidate(pVtgHdr, cbVtgObj, (const uint8_t *)pImage->pvImage, pImage->cbImageBits);
     853        rc = supdrvVtgValidate(pVtgHdr, (uintptr_t)pVtgHdr,
     854                               (const uint8_t *)pImage->pvImage, pImage->cbImageBits,
     855                               false /*fUmod*/);
    614856    else
    615         rc = supdrvVtgValidate(pVtgHdr, cbVtgObj, NULL, 0);
     857        rc = supdrvVtgValidate(pVtgHdr, (uintptr_t)pVtgHdr, NULL, 0, pUmod != NULL);
    616858    if (RT_FAILURE(rc))
    617859        return rc;
    618860
     861    /*
     862     * Check that there aren't any obvious duplicates.
     863     * (Yes, this isn't race free, but it's good enough for now.)
     864     */
    619865    rc = RTSemFastMutexRequest(pDevExt->mtxTracer);
    620866    if (RT_FAILURE(rc))
    621867        return rc;
    622     RTListForEach(&pDevExt->TracerProviderList, pProv, SUPDRVTPPROVIDER, ListEntry)
    623     {
    624         if (pProv->Core.pHdr == pVtgHdr)
    625         {
    626             rc = VERR_SUPDRV_VTG_ALREADY_REGISTERED;
    627             break;
    628         }
    629         if (   pProv->pSession == pSession
    630             && pProv->pImage   == pImage)
    631         {
    632             rc = VERR_SUPDRV_VTG_ONLY_ONCE_PER_SESSION;
    633             break;
     868    if (pImage || pSession->R0Process == NIL_RTPROCESS)
     869    {
     870        RTListForEach(&pDevExt->TracerProviderList, pProv, SUPDRVTPPROVIDER, ListEntry)
     871        {
     872            if (pProv->Core.pHdr == pVtgHdr)
     873            {
     874                rc = VERR_SUPDRV_VTG_ALREADY_REGISTERED;
     875                break;
     876            }
     877
     878            if (   pProv->pSession == pSession
     879                && pProv->pImage   == pImage)
     880            {
     881                rc = VERR_SUPDRV_VTG_ONLY_ONCE_PER_SESSION;
     882                break;
     883            }
     884        }
     885    }
     886    else
     887    {
     888        RTListForEach(&pSession->TpProviders, pProv, SUPDRVTPPROVIDER, SessionListEntry)
     889        {
     890            if (pProv->Core.pHdr == pVtgHdr)
     891            {
     892                rc = VERR_SUPDRV_VTG_ALREADY_REGISTERED;
     893                break;
     894            }
    634895        }
    635896    }
     
    644905    while (i-- > 0)
    645906    {
    646         PVTGDESCPROVIDER pDesc   = &pVtgHdr->paProviders[i];
     907        PVTGDESCPROVIDER pDesc   = (PVTGDESCPROVIDER)((uintptr_t)pVtgHdr + pVtgHdr->offProviders) + i;
    647908        const char      *pszName = supdrvVtgGetString(pVtgHdr, pDesc->offName);
    648         size_t const     cchName = strlen(pszName);
    649         pProv = (PSUPDRVTPPROVIDER)RTMemAllocZ(RT_OFFSETOF(SUPDRVTPPROVIDER, szName[cchName + 1]));
     909        size_t const     cchName = strlen(pszName) + (pUmod ? 16 : 0);
     910
     911        pProv = (PSUPDRVTPPROVIDER)RTMemAllocZ(RT_OFFSETOF(SUPDRVTPPROVIDER, szName[cchName + 1 + cchModName + 1]));
    650912        if (pProv)
    651913        {
    652             pProv->Core.pDesc       = pDesc;
    653             pProv->Core.pHdr        = pVtgHdr;
    654             pProv->Core.pszName     = &pProv->szName[0];
    655             pProv->Core.pszModName  = pszModName;
    656             pProv->pImage           = pImage;
    657             pProv->pSession         = pSession;
    658             pProv->fZombie          = false;
    659             pProv->fRegistered      = true;
    660             memcpy(&pProv->szName[0], pszName, cchName + 1);
    661 
     914            pProv->Core.pszName         = &pProv->szName[0];
     915            pProv->Core.pszModName      = &pProv->szName[cchName + 1];
     916            pProv->Core.pDesc           = pDesc;
     917            pProv->Core.pHdr            = pVtgHdr;
     918            pProv->Core.paProbeLocsRO   = (PCVTGPROBELOC )((uintptr_t)pVtgHdr + pVtgHdr->offProbeLocs);
     919            if (!pUmod)
     920            {
     921                pProv->Core.pvProbeLocsEn   = (void     *)((uintptr_t)pVtgHdr + pVtgHdr->offProbeLocs);
     922                pProv->Core.pacProbeEnabled = (uint32_t *)((uintptr_t)pVtgHdr + pVtgHdr->offProbeEnabled);
     923                pProv->Core.paR0ProbeLocs   = NULL;
     924                pProv->Core.paR0Probes      = NULL;
     925                pProv->Core.cbProbeLocsEn   = sizeof(VTGPROBELOC);
     926                pProv->Core.cBits           = ARCH_BITS;
     927                pProv->Core.fUmod           = false;
     928            }
     929            else
     930            {
     931                pProv->Core.pvProbeLocsEn   = pUmod->pvProbeLocs;
     932                pProv->Core.pacProbeEnabled = pUmod->pacProbeEnabled;
     933                pProv->Core.paR0ProbeLocs   = &pUmod->aProbeLocs[0];
     934                pProv->Core.paR0Probes      = (PSUPDRVPROBEINFO)&pUmod->aProbeLocs[pUmod->cProbeLocs];
     935                pProv->Core.cbProbeLocsEn   = pUmod->cbProbeLoc;
     936                pProv->Core.cBits           = pUmod->cBits;
     937                pProv->Core.fUmod           = true;
     938            }
     939            pProv->pImage               = pImage;
     940            pProv->pSession             = pSession;
     941            pProv->pUmod                = pUmod;
     942            pProv->fZombie              = false;
     943            pProv->fRegistered          = true;
     944
     945            if (!pUmod)
     946                memcpy(pProv->szName, pszName, cchName + 1);
     947            else
     948                RTStrPrintf(pProv->szName, cchName + 1, "%s%u", pszName, (uint32_t)pSession->Process);
     949            memcpy((void *)pProv->Core.pszModName, pszModName, cchModName + 1);
     950
     951            /*
     952             * Do the actual registration and list manipulations while holding
     953             * down the lock.
     954             */
    662955            rc = RTSemFastMutexRequest(pDevExt->mtxTracer);
    663956            if (RT_SUCCESS(rc))
     
    674967                {
    675968                    RTListAppend(&pDevExt->TracerProviderList, &pProv->ListEntry);
     969                    if (pSession)
     970                    {
     971                        RTListAppend(&pSession->TpProviders, &pProv->SessionListEntry);
     972                        pSession->cTpProviders++;
     973                    }
     974                    else
     975                        RTListInit(&pProv->SessionListEntry);
    676976                    RTSemFastMutexRelease(pDevExt->mtxTracer);
    677977                    LOG_TRACER(("Registered tracepoint provider '%s' in '%s' -> %p\n",
     
    683983                    LOG_TRACER(("Failed to register tracepoint provider '%s' in '%s' -> %Rrc\n",
    684984                                pProv->szName, pszModName, rc));
    685                     RTMemFree(pProv);
    686985                }
    687986            }
     
    690989            rc = VERR_NO_MEMORY;
    691990
     991        /*
     992         * In case of failure, we have to undo any providers we already
     993         * managed to register.
     994         */
    692995        if (RT_FAILURE(rc))
    693996        {
    694997            PSUPDRVTPPROVIDER   pProvNext;
    695             supdrvTracerFreeProvider(pProv);
     998
     999            if (pProv)
     1000                supdrvTracerFreeProvider(pProv);
    6961001
    6971002            RTSemFastMutexRequest(pDevExt->mtxTracer);
    698             RTListForEachReverseSafe(&pDevExt->TracerProviderList, pProv, pProvNext, SUPDRVTPPROVIDER, ListEntry)
    699             {
    700                 if (pProv->Core.pHdr == pVtgHdr)
     1003            if (pImage)
     1004            {
     1005                RTListForEachReverseSafe(&pDevExt->TracerProviderList, pProv, pProvNext, SUPDRVTPPROVIDER, ListEntry)
    7011006                {
    702                     RTListNodeRemove(&pProv->ListEntry);
    703                     supdrvTracerDeregisterVtgObj(pDevExt, pProv);
     1007                    if (pProv->Core.pHdr == pVtgHdr)
     1008                        supdrvTracerDeregisterVtgObj(pDevExt, pProv);
     1009                }
     1010            }
     1011            else
     1012            {
     1013                RTListForEachSafe(&pSession->TpProviders, pProv, pProvNext, SUPDRVTPPROVIDER, SessionListEntry)
     1014                {
     1015                    if (pProv->Core.pHdr == pVtgHdr)
     1016                        supdrvTracerDeregisterVtgObj(pDevExt, pProv);
    7041017                }
    7051018            }
     
    7311044    LOG_TRACER(("SUPR0TracerRegisterDrv: pSession=%p pVtgHdr=%p pszName=%s\n", pSession, pVtgHdr, pszName));
    7321045
    733     rc = supdrvTracerRegisterVtgObj(pSession->pDevExt, pVtgHdr, _1M, NULL /*pImage*/, pSession, pszName);
     1046    rc = supdrvTracerRegisterVtgObj(pSession->pDevExt, pVtgHdr, NULL /*pImage*/, pSession, NULL /*pUmod*/, pszName);
    7341047
    7351048    /*
     
    7621075     */
    7631076    RTSemFastMutexRequest(pDevExt->mtxTracer);
    764     RTListForEachSafe(&pDevExt->TracerProviderList, pProv, pProvNext, SUPDRVTPPROVIDER, ListEntry)
    765     {
    766         if (pProv->pSession == pSession)
    767         {
    768             RTListNodeRemove(&pProv->ListEntry);
    769             supdrvTracerDeregisterVtgObj(pDevExt, pProv);
    770         }
     1077    RTListForEachSafe(&pSession->TpProviders, pProv, pProvNext, SUPDRVTPPROVIDER, SessionListEntry)
     1078    {
     1079        supdrvTracerDeregisterVtgObj(pDevExt, pProv);
    7711080    }
    7721081    RTSemFastMutexRelease(pDevExt->mtxTracer);
     
    7931102    PSUPDRVLDRIMAGE pImage = (PSUPDRVLDRIMAGE)hMod;
    7941103    PSUPDRVDEVEXT   pDevExt;
    795     uintptr_t       cbVtgObj;
    7961104    int             rc;
    7971105
     
    8091117    AssertReturn(pDevExt->pLdrInitImage  == pImage, VERR_WRONG_ORDER);
    8101118    AssertReturn(pDevExt->hLdrInitThread == RTThreadNativeSelf(), VERR_WRONG_ORDER);
    811 
    812     /*
    813      * Calculate the max VTG object size and hand it over to the common code.
    814      */
    815     cbVtgObj = (uintptr_t)pVtgHdr - (uintptr_t)pImage->pvImage;
    816     AssertMsgReturn(cbVtgObj /*off*/ < pImage->cbImageBits,
    817                     ("pVtgHdr=%p offVtgObj=%p cbImageBits=%p\n", pVtgHdr, cbVtgObj, pImage->cbImageBits),
    818                     VERR_INVALID_PARAMETER);
    819     cbVtgObj = pImage->cbImageBits - cbVtgObj;
    820 
    821     rc = supdrvTracerRegisterVtgObj(pDevExt, pVtgHdr, cbVtgObj, pImage, NULL, pImage->szName);
     1119    AssertReturn((uintptr_t)pVtgHdr - (uintptr_t)pImage->pvImage < pImage->cbImageBits, VERR_INVALID_PARAMETER);
     1120
     1121    /*
     1122     * Do the job.
     1123     */
     1124    rc = supdrvTracerRegisterVtgObj(pDevExt, pVtgHdr, pImage, NULL /*pSession*/, NULL /*pUmod*/, pImage->szName);
    8221125    LOG_TRACER(("SUPR0TracerRegisterModule: rc=%d\n", rc));
    8231126
     
    10211324            else
    10221325                LOG_TRACER(("supdrvTracerCommonDeregisterImpl: Waiting on %u opens\n", pDevExt->cTracerOpens));
     1326        }
     1327
     1328        /* Tracer calls. */
     1329        if (pDevExt->cTracerCallers)
     1330        {
     1331            cZombies++;
     1332            if (!(i & 0xf))
     1333                SUPR0Printf("supdrvTracerCommonDeregisterImpl: Waiting on %u callers\n", pDevExt->cTracerCallers);
     1334            else
     1335                LOG_TRACER(("supdrvTracerCommonDeregisterImpl: Waiting on %u callers\n", pDevExt->cTracerCallers));
    10231336        }
    10241337
     
    11791492        {
    11801493            if (pProv->pImage == pImage)
    1181             {
    1182                 RTListNodeRemove(&pProv->ListEntry);
    11831494                supdrvTracerDeregisterVtgObj(pDevExt, pProv);
    1184             }
    11851495        }
    11861496
     
    12041514{
    12051515    /*
    1206      * If ring-0 session, make sure it has deregistered VTG objects and the tracer.
    1207      */
    1208     if (pSession->R0Process == NIL_RTR0PROCESS)
    1209     {
    1210         SUPDRVTPPROVIDER *pProvNext;
    1211         SUPDRVTPPROVIDER *pProv;
    1212 
    1213         RTSemFastMutexRequest(pDevExt->mtxTracer);
    1214         RTListForEachSafe(&pDevExt->TracerProviderList, pProv, pProvNext, SUPDRVTPPROVIDER, ListEntry)
    1215         {
    1216             if (pProv->pSession == pSession)
    1217             {
    1218                 RTListNodeRemove(&pProv->ListEntry);
    1219                 supdrvTracerDeregisterVtgObj(pDevExt, pProv);
    1220             }
    1221         }
    1222         RTSemFastMutexRelease(pDevExt->mtxTracer);
    1223 
    1224         (void)SUPR0TracerDeregisterImpl(NULL, pSession);
    1225     }
     1516     * Deregister all providers.
     1517     */
     1518    SUPDRVTPPROVIDER   *pProvNext;
     1519    SUPDRVTPPROVIDER   *pProv;
     1520    RTSemFastMutexRequest(pDevExt->mtxTracer);
     1521    RTListForEachSafe(&pSession->TpProviders, pProv, pProvNext, SUPDRVTPPROVIDER, SessionListEntry)
     1522    {
     1523        supdrvTracerDeregisterVtgObj(pDevExt, pProv);
     1524    }
     1525    RTSemFastMutexRelease(pDevExt->mtxTracer);
    12261526
    12271527    /*
     
    12301530    if (pSession->uTracerData)
    12311531        supdrvIOCtl_TracerClose(pDevExt, pSession);
    1232 }
    1233 
    1234 
    1235 int  VBOXCALL   supdrvIOCtl_TracerUmodRegister(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, RTR3PTR pVtgHdr, const char *pszModName, uint32_t fFlags)
    1236 {
    1237     return VERR_NOT_IMPLEMENTED;
    1238 }
    1239 
    1240 int  VBOXCALL   supdrvIOCtl_TracerUmodDeregister(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, RTR3PTR pVtgHdr)
    1241 {
    1242     return VERR_NOT_IMPLEMENTED;
    1243 }
    1244 
    1245 void  VBOXCALL  supdrvIOCtl_TracerUmodProbeFire(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, PCSUPDRVTRACERUSRCTX pCtx)
    1246 {
    1247 
     1532
     1533    /*
     1534     * Deregister any tracer implementation.
     1535     */
     1536    if (pSession->R0Process == NIL_RTR0PROCESS)
     1537        (void)SUPR0TracerDeregisterImpl(NULL, pSession);
     1538
     1539    if (pSession->R0Process != NIL_RTR0PROCESS)
     1540    {
     1541        /*
     1542         * Free any lingering user modules.  We don't bother holding the lock
     1543         * here as there shouldn't be anyone messing with the session at this
     1544         * point.
     1545         */
     1546        PSUPDRVTRACERUMOD pUmodNext;
     1547        PSUPDRVTRACERUMOD pUmod;
     1548        RTListForEachSafe(&pSession->TpUmods, pUmod, pUmodNext, SUPDRVTRACERUMOD, ListEntry)
     1549        {
     1550            RTR0MemObjFree(pUmod->hMemObjMap, false /*fFreeMappings*/);
     1551            RTR0MemObjFree(pUmod->hMemObjLock, false /*fFreeMappings*/);
     1552            supdrvVtgReleaseObjectCopy(pDevExt, pUmod->pVtgCopy);
     1553            RTMemFree(pUmod);
     1554        }
     1555    }
     1556}
     1557
     1558
     1559static void supdrvVtgReleaseObjectCopy(PSUPDRVDEVEXT pDevExt, PSUPDRVVTGCOPY pThis)
     1560{
     1561    uint32_t cRefs = ASMAtomicDecU32(&pThis->cRefs);
     1562    if (!cRefs)
     1563    {
     1564        RTSemFastMutexRequest(pDevExt->mtxTracer);
     1565        pThis->u32Magic = ~SUDPRVVTGCOPY_MAGIC;
     1566        RTListNodeRemove(&pThis->ListEntry);
     1567        RTSemFastMutexRelease(pDevExt->mtxTracer);
     1568
     1569        RTMemFree(pThis);
     1570    }
     1571}
     1572
     1573
     1574/**
     1575 * Finds a matching VTG object copy, caller owns the lock already.
     1576 *
     1577 * @returns Copy with reference. NULL if not found.
     1578 * @param   pHashList           The hash list to search.
     1579 * @param   pHdr                The VTG header (valid).
     1580 * @param   cbStrTab            The string table size.
     1581 * @param   fFlags              The user module flags.
     1582 */
     1583static PSUPDRVVTGCOPY supdrvVtgFindObjectCopyLocked(PRTLISTANCHOR pHashList, PCVTGOBJHDR pHdr, uint32_t cbStrTab, uint32_t fFlags)
     1584{
     1585    PSUPDRVVTGCOPY  pCur;
     1586
     1587    fFlags &= SUP_TRACER_UMOD_FLAGS_TYPE_MASK;
     1588    RTListForEach(pHashList, pCur, SUPDRVVTGCOPY, ListEntry)
     1589    {
     1590#define HDR_EQUALS(member) pCur->Hdr.member == pHdr->member
     1591        if (   HDR_EQUALS(Uuid.au32[0])
     1592            && HDR_EQUALS(Uuid.au32[1])
     1593            && HDR_EQUALS(Uuid.au32[2])
     1594            && HDR_EQUALS(Uuid.au32[3])
     1595            && HDR_EQUALS(cbObj)
     1596            && HDR_EQUALS(cBits)
     1597            && pCur->cbStrTab == cbStrTab
     1598            && pCur->fFlags == fFlags
     1599           )
     1600        {
     1601            if (RT_LIKELY(   HDR_EQUALS(offStrTab)
     1602                          && HDR_EQUALS(cbStrTab)
     1603                          && HDR_EQUALS(offArgLists)
     1604                          && HDR_EQUALS(cbArgLists)
     1605                          && HDR_EQUALS(offProbes)
     1606                          && HDR_EQUALS(cbProbes)
     1607                          && HDR_EQUALS(offProviders)
     1608                          && HDR_EQUALS(cbProviders)
     1609                          && HDR_EQUALS(offProbeEnabled)
     1610                          && HDR_EQUALS(cbProbeEnabled)
     1611                          && HDR_EQUALS(offProbeLocs)
     1612                          && HDR_EQUALS(cbProbeLocs)
     1613                         )
     1614                )
     1615            {
     1616                Assert(pCur->cRefs > 0);
     1617                Assert(pCur->cRefs < _1M);
     1618                pCur->cRefs++;
     1619                return pCur;
     1620            }
     1621        }
     1622#undef HDR_EQUALS
     1623    }
     1624
     1625    return NULL;
     1626}
     1627
     1628
     1629/**
     1630 * Finds a matching VTG object copy.
     1631 *
     1632 * @returns Copy with reference. NULL if not found.
     1633 * @param   pDevExt             The device extension.
     1634 * @param   pHdr                The VTG header (valid).
     1635 * @param   cbStrTab            The string table size.
     1636 * @param   fFlags              The user module flags.
     1637 */
     1638static PSUPDRVVTGCOPY supdrvVtgFindObjectCopy(PSUPDRVDEVEXT pDevExt, PCVTGOBJHDR pHdr, uint32_t cbStrTab, uint32_t fFlags)
     1639{
     1640    PRTLISTANCHOR   pHashList = &pDevExt->aTrackerUmodHash[pHdr->Uuid.au8[3] % RT_ELEMENTS(pDevExt->aTrackerUmodHash)];
     1641    PSUPDRVVTGCOPY pRet;
     1642
     1643    int rc = RTSemFastMutexRequest(pDevExt->mtxTracer);
     1644    AssertRCReturn(rc, NULL);
     1645
     1646    pRet = supdrvVtgFindObjectCopyLocked(pHashList, pHdr, cbStrTab, fFlags);
     1647
     1648    RTSemFastMutexRelease(pDevExt->mtxTracer);
     1649    return pRet;
     1650}
     1651
     1652
     1653/**
     1654 * Makes a shared copy of the VTG object.
     1655 *
     1656 * @returns VBox status code.
     1657 * @param   pDevExt             The device extension.
     1658 * @param   pVtgHdr             The VTG header (valid).
     1659 * @param   R3PtrVtgHdr         The ring-3 VTG header address.
     1660 * @param   uVtgHdrAddr         The address of the VTG header in the context
     1661 *                              where it is actually used.
     1662 * @param   R3PtrStrTab         The ring-3 address of the probe location string
     1663 *                              table.  The probe location array have offsets
     1664 *                              into this instead of funciton name pointers.
     1665 * @param   cbStrTab            The size of the probe location string table.
     1666 * @param   fFlags              The user module flags.
     1667 * @param   pUmod               The structure we've allocated to track the
     1668 *                              module.  This have a valid kernel mapping of the
     1669 *                              probe location array.  Upon successful return,
     1670 *                              the pVtgCopy member will hold the address of our
     1671 *                              copy (with a referenced of course).
     1672 */
     1673static int supdrvVtgCreateObjectCopy(PSUPDRVDEVEXT pDevExt, PCVTGOBJHDR pVtgHdr, RTR3PTR R3PtrVtgHdr, RTUINTPTR uVtgHdrAddr,
     1674                                     RTR3PTR R3PtrStrTab, uint32_t cbStrTab, uint32_t fFlags, PSUPDRVTRACERUMOD pUmod)
     1675{
     1676    /*
     1677     * Calculate the space required, allocate and copy in the data.
     1678     */
     1679    int             rc;
     1680    size_t const    cProbeLocs   = pVtgHdr->cbProbeLocs / (pVtgHdr->cBits == 32 ? sizeof(VTGPROBELOC32) : sizeof(VTGPROBELOC64));
     1681    size_t const    cbProbeLocs  = cProbeLocs * sizeof(VTGPROBELOC);
     1682    size_t const    offProbeLocs = RT_ALIGN(pVtgHdr->cbObj, 8);
     1683    size_t const    cb           = offProbeLocs + cbProbeLocs + cbStrTab + 1;
     1684    PSUPDRVVTGCOPY  pThis = (PSUPDRVVTGCOPY)RTMemAlloc(RT_OFFSETOF(SUPDRVVTGCOPY, Hdr) + cb);
     1685    if (!pThis)
     1686        return VERR_NO_MEMORY;
     1687
     1688    pThis->u32Magic = SUDPRVVTGCOPY_MAGIC;
     1689    pThis->cRefs    = 1;
     1690    pThis->cbStrTab = cbStrTab;
     1691    pThis->fFlags   = fFlags & SUP_TRACER_UMOD_FLAGS_TYPE_MASK;
     1692    RTListInit(&pThis->ListEntry);
     1693
     1694    rc = RTR0MemUserCopyFrom(&pThis->Hdr, R3PtrVtgHdr, pVtgHdr->cbObj);
     1695    if (RT_SUCCESS(rc))
     1696    {
     1697        char  *pchStrTab = (char *)&pThis->Hdr + offProbeLocs + cbProbeLocs;
     1698        rc = RTR0MemUserCopyFrom(pchStrTab, R3PtrStrTab, cbStrTab);
     1699        if (RT_SUCCESS(rc))
     1700        {
     1701            PVTGPROBELOC    paDst = (PVTGPROBELOC)((char *)&pThis->Hdr + offProbeLocs);
     1702            uint32_t        i;
     1703
     1704            /*
     1705             * Some paranoia: Overwrite the header with the copy we've already
     1706             * validated and zero terminate the string table.
     1707             */
     1708            pThis->Hdr = *pVtgHdr;
     1709            pchStrTab[cbStrTab] = '\0';
     1710
     1711            /*
     1712             * Set the probe location array related header members since we're
     1713             * making our own copy in a different location.
     1714             */
     1715            pThis->Hdr.uProbeLocs.u64     = (uintptr_t)paDst;
     1716            pThis->Hdr.uProbeLocsEnd.u64  = (uintptr_t)paDst + cbProbeLocs;
     1717            pThis->Hdr.offProbeLocs       = offProbeLocs;
     1718            pThis->Hdr.cbProbeLocs        = cbProbeLocs;
     1719            pThis->Hdr.cBits              = ARCH_BITS;
     1720
     1721            /*
     1722             * Copy, convert and fix up the the probe location table.
     1723             */
     1724            if (pVtgHdr->cBits == 32)
     1725            {
     1726                uintptr_t const offDelta = (uintptr_t)&pThis->Hdr - uVtgHdrAddr;
     1727                PCVTGPROBELOC32 paSrc    = (PCVTGPROBELOC32)pUmod->pvProbeLocs;
     1728
     1729                for (i = 0; i < cProbeLocs; i++)
     1730                {
     1731                    paDst[i].uLine    = paSrc[i].uLine;
     1732                    paDst[i].fEnabled = paSrc[i].fEnabled;
     1733                    paDst[i].idProbe  = paSrc[i].idProbe;
     1734                    if (paSrc[i].pszFunction > cbStrTab)
     1735                    {
     1736                        rc = VERR_SUPDRV_TRACER_UMOD_STRTAB_OFF_BAD;
     1737                        break;
     1738                    }
     1739                    paDst[i].pszFunction = pchStrTab + paSrc[i].pszFunction;
     1740                    paDst[i].pbProbe     = (uint8_t *)(paSrc[i].pbProbe + offDelta);
     1741                }
     1742            }
     1743            else
     1744            {
     1745                uint64_t const  offDelta = (uintptr_t)&pThis->Hdr - uVtgHdrAddr;
     1746                PCVTGPROBELOC64 paSrc    = (PCVTGPROBELOC64)pUmod->pvProbeLocs;
     1747
     1748                for (i = 0; i < cProbeLocs; i++)
     1749                {
     1750                    paDst[i].uLine    = paSrc[i].uLine;
     1751                    paDst[i].fEnabled = paSrc[i].fEnabled;
     1752                    paDst[i].idProbe  = paSrc[i].idProbe;
     1753                    if (paSrc[i].pszFunction > cbStrTab)
     1754                    {
     1755                        rc = VERR_SUPDRV_TRACER_UMOD_STRTAB_OFF_BAD;
     1756                        break;
     1757                    }
     1758                    paDst[i].pszFunction = pchStrTab + (uintptr_t)paSrc[i].pszFunction;
     1759                    paDst[i].pbProbe     = (uint8_t *)(uintptr_t)(paSrc[i].pbProbe + offDelta);
     1760                }
     1761            }
     1762
     1763            /*
     1764             * Validate it
     1765             *
     1766             * Note! fUmod is false as this is a kernel copy with all native
     1767             *       structures.
     1768             */
     1769            if (RT_SUCCESS(rc))
     1770                rc = supdrvVtgValidate(&pThis->Hdr, (uintptr_t)&pThis->Hdr, (uint8_t *)&pThis->Hdr, cb, false /*fUmod*/);
     1771            if (RT_SUCCESS(rc))
     1772            {
     1773                /*
     1774                 * Add it to the hash list, making sure nobody raced us.
     1775                 */
     1776                PRTLISTANCHOR pHashList = &pDevExt->aTrackerUmodHash[  pVtgHdr->Uuid.au8[3]
     1777                                                                     % RT_ELEMENTS(pDevExt->aTrackerUmodHash)];
     1778
     1779                rc = RTSemFastMutexRequest(pDevExt->mtxTracer);
     1780                if (RT_SUCCESS(rc))
     1781                {
     1782                    pUmod->pVtgCopy = supdrvVtgFindObjectCopyLocked(pHashList, pVtgHdr, cbStrTab, fFlags);
     1783                    if (!pUmod->pVtgCopy)
     1784                    {
     1785                        pUmod->pVtgCopy = pThis;
     1786                        RTListAppend(pHashList, &pThis->ListEntry);
     1787                        RTSemFastMutexRelease(pDevExt->mtxTracer);
     1788                        return rc;
     1789                    }
     1790
     1791                    /*
     1792                     * Someone raced us, free our copy and return the existing
     1793                     * one instead.
     1794                     */
     1795                    RTSemFastMutexRelease(pDevExt->mtxTracer);
     1796                }
     1797            }
     1798        }
     1799    }
     1800    RTMemFree(pThis);
     1801    return rc;
     1802}
     1803
     1804
     1805/**
     1806 * Undoes what supdrvTracerUmodSetProbeIds did.
     1807 *
     1808 * @param   pDevExt             The device extension.
     1809 * @param   pSession            The current session.
     1810 * @param   pUmod               The user tracepoint module.
     1811 */
     1812static void supdrvTracerUmodClearProbeIds(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, PSUPDRVTRACERUMOD pUmod)
     1813{
     1814    uint32_t i;
     1815
     1816    AssertReturnVoid(pUmod->iLookupTable < RT_ELEMENTS(pSession->apTpLookupTable));
     1817    AssertReturnVoid(pSession->apTpLookupTable[pUmod->iLookupTable] == pUmod);
     1818
     1819    /*
     1820     * Clear the probe IDs and disable the probes.
     1821     */
     1822    i = pUmod->cProbeLocs;
     1823    if (pUmod->cBits == 32)
     1824    {
     1825        PVTGPROBELOC32 paProbeLocs = (PVTGPROBELOC32)pUmod->pvProbeLocs;
     1826        while (i-- > 0)
     1827            paProbeLocs[i].idProbe = 0;
     1828    }
     1829    else
     1830    {
     1831        PVTGPROBELOC64 paProbeLocs = (PVTGPROBELOC64)pUmod->pvProbeLocs;
     1832        while (i-- > 0)
     1833            paProbeLocs[i].idProbe = 0;
     1834    }
     1835
     1836    /*
     1837     * Free the lookup table entry.  We'll have to wait for the table to go
     1838     * idle to make sure there are no current users of pUmod.
     1839     */
     1840    RTSemFastMutexRequest(pDevExt->mtxTracer);
     1841    if (pSession->apTpLookupTable[pUmod->iLookupTable] == pUmod)
     1842    {
     1843        if (pSession->cTpProbesFiring > 0)
     1844        {
     1845            uint32_t i = 0;
     1846            while (pSession->cTpProbesFiring > 0)
     1847            {
     1848                RTSemFastMutexRelease(pDevExt->mtxTracer);
     1849                i++;
     1850                if (!(i & 0xff))
     1851                    SUPR0Printf("supdrvTracerUmodClearProbeIds: waiting for lookup table to go idle (i=%u)\n", i);
     1852                RTThreadSleep(10);
     1853                RTSemFastMutexRequest(pDevExt->mtxTracer);
     1854            }
     1855        }
     1856        ASMAtomicWriteNullPtr(&pSession->apTpLookupTable[pUmod->iLookupTable]);
     1857    }
     1858    RTSemFastMutexRelease(pDevExt->mtxTracer);
     1859}
     1860
     1861
     1862/**
     1863 * Allocates a lookup table entry for the Umod and sets the
     1864 * VTGPROBELOC::idProbe fields in user mode.
     1865 *
     1866 * @returns VINF_SUCCESS or VERR_SUPDRV_TRACER_TOO_MANY_PROVIDERS.
     1867 * @param   pDevExt             The device extension.
     1868 * @param   pSession            The current session.
     1869 * @param   pUmod               The user tracepoint module.
     1870 */
     1871static int supdrvTracerUmodSetProbeIds(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, PSUPDRVTRACERUMOD pUmod)
     1872{
     1873    uint32_t iBase;
     1874    uint32_t i;
     1875
     1876    /*
     1877     * Allocate a lookup table entry.
     1878     */
     1879    RTSemFastMutexRequest(pDevExt->mtxTracer);
     1880    for (i = 0; i < RT_ELEMENTS(pSession->apTpLookupTable); i++)
     1881    {
     1882        if (!pSession->apTpLookupTable[i])
     1883        {
     1884            pSession->apTpLookupTable[i] = pUmod;
     1885            pUmod->iLookupTable = i;
     1886            break;
     1887        }
     1888    }
     1889    RTSemFastMutexRelease(pDevExt->mtxTracer);
     1890    if (i >= RT_ELEMENTS(pSession->apTpLookupTable))
     1891        return VERR_SUPDRV_TRACER_TOO_MANY_PROVIDERS;
     1892
     1893    /*
     1894     * Set probe IDs of the usermode probe location to indicate our lookup
     1895     * table entry as well as the probe location array entry.
     1896     */
     1897    iBase = (uint32_t)pUmod->iLookupTable << 24;
     1898    i = pUmod->cProbeLocs;
     1899    if (pUmod->cBits == 32)
     1900    {
     1901        PVTGPROBELOC32 paProbeLocs = (PVTGPROBELOC32)pUmod->pvProbeLocs;
     1902        while (i-- > 0)
     1903            paProbeLocs[i].idProbe = iBase | i;
     1904    }
     1905    else
     1906    {
     1907        PVTGPROBELOC64 paProbeLocs = (PVTGPROBELOC64)pUmod->pvProbeLocs;
     1908        while (i-- > 0)
     1909            paProbeLocs[i].idProbe = iBase | i;
     1910    }
     1911
     1912    return VINF_SUCCESS;
     1913}
     1914
     1915
     1916int  VBOXCALL   supdrvIOCtl_TracerUmodRegister(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession,
     1917                                               RTR3PTR R3PtrVtgHdr, RTUINTPTR uVtgHdrAddr,
     1918                                               RTR3PTR R3PtrStrTab, uint32_t cbStrTab,
     1919                                               const char *pszModName, uint32_t fFlags)
     1920{
     1921    VTGOBJHDR           Hdr;
     1922    PSUPDRVTRACERUMOD   pUmod;
     1923    RTR3PTR             R3PtrLock;
     1924    size_t              cbLock;
     1925    uint32_t            cProbeLocs;
     1926    int                 rc;
     1927
     1928    /*
     1929     * Validate input.
     1930     */
     1931    if (pSession->R0Process == NIL_RTR0PROCESS)
     1932        return VERR_INVALID_CONTEXT;
     1933    if (   fFlags != SUP_TRACER_UMOD_FLAGS_EXE
     1934        && fFlags != SUP_TRACER_UMOD_FLAGS_SHARED)
     1935        return VERR_INVALID_PARAMETER;
     1936
     1937    if (pSession->cTpProviders >= RT_ELEMENTS(pSession->apTpLookupTable))
     1938        return VERR_SUPDRV_TRACER_TOO_MANY_PROVIDERS;
     1939
     1940    if (   cbStrTab < 2
     1941        || cbStrTab > _1M)
     1942        return VERR_SUPDRV_TRACER_UMOD_STRTAB_TOO_BIG;
     1943
     1944    /*
     1945     * Read the VTG header into a temporary buffer and perform some simple
     1946     * validations to make sure we aren't wasting our time here.
     1947     */
     1948    rc = RTR0MemUserCopyFrom(&Hdr, R3PtrVtgHdr, sizeof(Hdr));
     1949    if (RT_FAILURE(rc))
     1950        return rc;
     1951    rc = supdrvVtgValidateHdr(&Hdr, uVtgHdrAddr, NULL, 0, true /*fUmod*/);
     1952    if (RT_FAILURE(rc))
     1953        return rc;
     1954    if (Hdr.cbProviders / sizeof(VTGDESCPROVIDER) > 2)
     1955        return VERR_SUPDRV_TRACER_TOO_MANY_PROVIDERS;
     1956
     1957    /*
     1958     * Check how much needs to be locked down and how many probe locations
     1959     * there are.
     1960     */
     1961    if (   Hdr.offProbeLocs <= 0
     1962        || Hdr.offProbeEnabled > (uint32_t)Hdr.offProbeLocs
     1963        || (uint32_t)Hdr.offProbeLocs - Hdr.offProbeEnabled - Hdr.cbProbeEnabled > 128)
     1964        return VERR_SUPDRV_TRACER_UMOD_NOT_ADJACENT;
     1965    R3PtrLock  = R3PtrVtgHdr + Hdr.offProbeEnabled;
     1966    cbLock     = Hdr.offProbeLocs + Hdr.cbProbeLocs - Hdr.offProbeEnabled + (R3PtrLock & PAGE_OFFSET_MASK);
     1967    R3PtrLock &= ~(RTR3PTR)PAGE_OFFSET_MASK;
     1968    if (cbLock > _64K)
     1969        return VERR_SUPDRV_TRACER_UMOD_TOO_MANY_PROBES;
     1970
     1971    cProbeLocs = Hdr.cbProbeLocs / (Hdr.cBits == 32 ? sizeof(VTGPROBELOC32) : sizeof(VTGPROBELOC64));
     1972
     1973    /*
     1974     * Allocate the tracker data we keep in the session.
     1975     */
     1976    pUmod = (PSUPDRVTRACERUMOD)RTMemAllocZ(  RT_OFFSETOF(SUPDRVTRACERUMOD, aProbeLocs[cProbeLocs])
     1977                                           + (Hdr.cbProbeEnabled / sizeof(uint32_t) * sizeof(SUPDRVPROBEINFO)) );
     1978    if (!pUmod)
     1979        return VERR_NO_MEMORY;
     1980    pUmod->u32Magic         = SUPDRVTRACERUMOD_MAGIC;
     1981    RTListInit(&pUmod->ListEntry);
     1982    pUmod->R3PtrVtgHdr      = R3PtrVtgHdr;
     1983    pUmod->pVtgCopy         = NULL;
     1984    pUmod->hMemObjLock      = NIL_RTR0MEMOBJ;
     1985    pUmod->hMemObjMap       = NIL_RTR0MEMOBJ;
     1986    pUmod->R3PtrProbeLocs   = (RTR3INTPTR)R3PtrVtgHdr + Hdr.offProbeLocs;
     1987    pUmod->iLookupTable     = UINT8_MAX;
     1988    pUmod->cBits            = Hdr.cBits;
     1989    pUmod->cbProbeLoc       = Hdr.cBits == 32 ? sizeof(VTGPROBELOC32) : sizeof(VTGPROBELOC64);
     1990    pUmod->cProbeLocs       = cProbeLocs;
     1991
     1992    /*
     1993     * Lock down and map the user-mode structures.
     1994     */
     1995    rc = RTR0MemObjLockUser(&pUmod->hMemObjLock, R3PtrLock, cbLock, RTMEM_PROT_READ | RTMEM_PROT_WRITE, NIL_RTR0PROCESS);
     1996    if (RT_SUCCESS(rc))
     1997    {
     1998        rc = RTR0MemObjMapKernel(&pUmod->hMemObjMap, pUmod->hMemObjLock, (void *)-1, 0, RTMEM_PROT_READ | RTMEM_PROT_WRITE);
     1999        if (RT_SUCCESS(rc))
     2000        {
     2001            pUmod->pacProbeEnabled  = (uint32_t *)(  (uintptr_t)RTR0MemObjAddress(pUmod->hMemObjMap)
     2002                                                   + ((uintptr_t)(R3PtrVtgHdr + Hdr.offProbeEnabled) & PAGE_OFFSET_MASK));
     2003            pUmod->pvProbeLocs      = (uint8_t *)pUmod->pacProbeEnabled + Hdr.offProbeLocs - Hdr.offProbeEnabled;
     2004
     2005            /*
     2006             * Does some other process use the same module already?  If so,
     2007             * share the VTG data with it.  Otherwise, make a ring-0 copy it.
     2008             */
     2009            pUmod->pVtgCopy = supdrvVtgFindObjectCopy(pDevExt, &Hdr, cbStrTab, fFlags);
     2010            if (!pUmod->pVtgCopy)
     2011                rc = supdrvVtgCreateObjectCopy(pDevExt, &Hdr, R3PtrVtgHdr, uVtgHdrAddr, R3PtrStrTab, cbStrTab, fFlags, pUmod);
     2012            if (RT_SUCCESS(rc))
     2013            {
     2014                AssertPtr(pUmod->pVtgCopy);
     2015
     2016                /*
     2017                 * Grabe a place in apTpLookupTable and set the probe IDs
     2018                 * accordingly.
     2019                 */
     2020                rc = supdrvTracerUmodSetProbeIds(pDevExt, pSession, pUmod);
     2021                if (RT_SUCCESS(rc))
     2022                {
     2023                    /*
     2024                     * Register the providers.
     2025                     */
     2026                    rc = supdrvTracerRegisterVtgObj(pDevExt, &pUmod->pVtgCopy->Hdr,
     2027                                                    NULL /*pImage*/, pSession, pUmod, pszModName);
     2028                    if (RT_SUCCESS(rc))
     2029                    {
     2030                        RTSemFastMutexRequest(pDevExt->mtxTracer);
     2031                        RTListAppend(&pSession->TpUmods, &pUmod->ListEntry);
     2032                        RTSemFastMutexRelease(pDevExt->mtxTracer);
     2033
     2034                        return VINF_SUCCESS;
     2035                    }
     2036
     2037                    /* bail out. */
     2038                    supdrvTracerUmodClearProbeIds(pDevExt, pSession, pUmod);
     2039                }
     2040                supdrvVtgReleaseObjectCopy(pDevExt, pUmod->pVtgCopy);
     2041            }
     2042            RTR0MemObjFree(pUmod->hMemObjMap, false /*fFreeMappings*/);
     2043        }
     2044        RTR0MemObjFree(pUmod->hMemObjLock, false /*fFreeMappings*/);
     2045    }
     2046    pUmod->u32Magic = ~SUPDRVTRACERUMOD_MAGIC;
     2047    RTMemFree(pUmod);
     2048    return rc;
     2049}
     2050
     2051
     2052int  VBOXCALL   supdrvIOCtl_TracerUmodDeregister(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, RTR3PTR R3PtrVtgHdr)
     2053{
     2054    PSUPDRVTRACERUMOD   pUmod = NULL;
     2055    uint32_t            i;
     2056    int                 rc;
     2057
     2058    /*
     2059     * Validate the request.
     2060     */
     2061    RTSemFastMutexRequest(pDevExt->mtxTracer);
     2062    for (i = 0; i < RT_ELEMENTS(pSession->apTpLookupTable); i++)
     2063    {
     2064        pUmod = pSession->apTpLookupTable[i];
     2065        if (   pUmod
     2066            && pUmod->u32Magic    == SUPDRVTRACERUMOD_MAGIC
     2067            && pUmod->R3PtrVtgHdr == R3PtrVtgHdr)
     2068            break;
     2069    }
     2070    RTSemFastMutexRelease(pDevExt->mtxTracer);
     2071    if (pUmod)
     2072    {
     2073        SUPDRVTPPROVIDER   *pProvNext;
     2074        SUPDRVTPPROVIDER   *pProv;
     2075
     2076        /*
     2077         * Remove ourselves from the lookup table and clean up the ring-3 bits
     2078         * we've dirtied.  We do this first to make sure no probes are firing
     2079         * when we're destroying the providers in the next step.
     2080         */
     2081        supdrvTracerUmodClearProbeIds(pDevExt, pSession, pUmod);
     2082
     2083        /*
     2084         * Deregister providers related to the VTG object.
     2085         */
     2086        RTSemFastMutexRequest(pDevExt->mtxTracer);
     2087        RTListForEachSafe(&pSession->TpProviders, pProv, pProvNext, SUPDRVTPPROVIDER, SessionListEntry)
     2088        {
     2089            if (pProv->pUmod == pUmod)
     2090                supdrvTracerDeregisterVtgObj(pDevExt, pProv);
     2091        }
     2092        RTSemFastMutexRelease(pDevExt->mtxTracer);
     2093
     2094        /*
     2095         * Destroy the Umod object.
     2096         */
     2097        pUmod->u32Magic = ~SUPDRVTRACERUMOD_MAGIC;
     2098        supdrvVtgReleaseObjectCopy(pDevExt, pUmod->pVtgCopy);
     2099        RTR0MemObjFree(pUmod->hMemObjMap, false /*fFreeMappings*/);
     2100        RTR0MemObjFree(pUmod->hMemObjLock, false /*fFreeMappings*/);
     2101        RTMemFree(pUmod);
     2102    }
     2103    else
     2104        rc = VERR_NOT_FOUND;
     2105    return rc;
     2106}
     2107
     2108
     2109/**
     2110 * Implementation of supdrvIOCtl_TracerUmodProbeFire and
     2111 * SUPR0TracerUmodProbeFire.
     2112 *
     2113 * @param   pDevExt             The device extension.
     2114 * @param   pSession            The calling session.
     2115 * @param   pCtx                The context record.
     2116 */
     2117static void supdrvTracerUmodProbeFire(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, PSUPDRVTRACERUSRCTX pCtx)
     2118{
     2119    /*
     2120     * We cannot trust user mode to hand us the right bits nor not calling us
     2121     * when disabled.  So, we have to check for our selves.
     2122     */
     2123    PSUPDRVTRACERUMOD   pUmod;
     2124    uint32_t const      iLookupTable = pCtx->idProbe >> 24;
     2125    uint32_t const      iProbeLoc    = pCtx->idProbe & UINT32_C(0x00ffffff);
     2126
     2127    if (RT_UNLIKELY(   !pDevExt->pTracerOps
     2128                    || pDevExt->fTracerUnloading))
     2129        return;
     2130    if (RT_UNLIKELY(iLookupTable >= RT_ELEMENTS(pSession->apTpLookupTable)))
     2131        return;
     2132    if (RT_UNLIKELY(   pCtx->cBits != 32
     2133                    && pCtx->cBits != 64))
     2134        return;
     2135
     2136    ASMAtomicIncU32(&pSession->cTpProviders);
     2137
     2138    pUmod = pSession->apTpLookupTable[iLookupTable];
     2139    if (RT_LIKELY(pUmod))
     2140    {
     2141        if (RT_LIKELY(   pUmod->u32Magic == SUPDRVTRACERUMOD_MAGIC
     2142                      && iProbeLoc < pUmod->cProbeLocs
     2143                      && pCtx->cBits == pUmod->cBits))
     2144        {
     2145            RTR3PTR R3PtrProbeLoc = pUmod->R3PtrProbeLocs + iProbeLoc * pUmod->cbProbeLoc;
     2146            if (RT_LIKELY(   (pCtx->cBits == 32 ? (RTR3PTR)pCtx->u.X86.uVtgProbeLoc : pCtx->u.Amd64.uVtgProbeLoc)
     2147                          == R3PtrProbeLoc))
     2148            {
     2149                if (RT_LIKELY(pUmod->aProbeLocs[iProbeLoc].fEnabled))
     2150                {
     2151                    ASMAtomicIncU32(&pDevExt->cTracerCallers);
     2152                    if (RT_LIKELY(   pDevExt->pTracerOps
     2153                                  && !pDevExt->fTracerUnloading))
     2154                    {
     2155                        pCtx->idProbe = pUmod->aProbeLocs[iProbeLoc].idProbe;
     2156                        pDevExt->pTracerOps->pfnProbeFireUser(pDevExt->pTracerOps, pSession, pCtx);
     2157                    }
     2158                    ASMAtomicDecU32(&pDevExt->cTracerCallers);
     2159                }
     2160            }
     2161        }
     2162    }
     2163
     2164    ASMAtomicDecU32(&pSession->cTpProviders);
     2165}
     2166
     2167
     2168SUPR0DECL(void) SUPR0TracerUmodProbeFire(PSUPDRVSESSION pSession, PSUPDRVTRACERUSRCTX pCtx)
     2169{
     2170    AssertReturnVoid(SUP_IS_SESSION_VALID(pSession));
     2171    AssertPtrReturnVoid(pCtx);
     2172
     2173    supdrvTracerUmodProbeFire(pSession->pDevExt, pSession, pCtx);
     2174}
     2175
     2176
     2177void  VBOXCALL  supdrvIOCtl_TracerUmodProbeFire(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, PSUPDRVTRACERUSRCTX pCtx)
     2178{
     2179    supdrvTracerUmodProbeFire(pDevExt, pSession, pCtx);
    12482180}
    12492181
     
    14342366    if (RT_SUCCESS(rc))
    14352367    {
     2368        uint32_t i;
     2369
    14362370        pDevExt->TracerHlp.uVersion    = SUPDRVTRACERHLP_VERSION;
    14372371        /** @todo  */
     
    14392373        RTListInit(&pDevExt->TracerProviderList);
    14402374        RTListInit(&pDevExt->TracerProviderZombieList);
     2375        for (i = 0; i < RT_ELEMENTS(pDevExt->aTrackerUmodHash); i++)
     2376            RTListInit(&pDevExt->aTrackerUmodHash[i]);
    14412377
    14422378#ifdef VBOX_WITH_NATIVE_DTRACE
     
    14502386         */
    14512387#ifdef VBOX_WITH_DTRACE_R0DRV
    1452         rc = supdrvTracerRegisterVtgObj(pDevExt, &g_VTGObjHeader, _1M, NULL /*pImage*/, NULL /*pSession*/, "vboxdrv");
     2388        rc = supdrvTracerRegisterVtgObj(pDevExt, &g_VTGObjHeader, NULL /*pImage*/, NULL /*pSession*/, NULL /*pUmod*/, "vboxdrv");
    14532389        if (RT_SUCCESS(rc))
    14542390            return rc;
  • trunk/src/VBox/HostDrivers/Support/SUPLib.cpp

    r40981 r41117  
    5151#include <VBox/param.h>
    5252#include <VBox/log.h>
     53#include <VBox/VBoxTpG.h>
    5354
    5455#include <iprt/assert.h>
     
    23892390
    23902391
    2391 SUPDECL(void) SUPTracerFireProbe(struct VTGPROBELOC *pVtgProbeLoc, uintptr_t uArg0, uintptr_t uArg1, uintptr_t uArg2,
    2392                                  uintptr_t uArg3, uintptr_t uArg4)
    2393 {
    2394     /* C and stubbed for now. */
    2395 }
    2396 
    2397 
    2398 SUPR3DECL(int) SUPR3TracerRegisterModule(uintptr_t hModNative, const char *pszModule, struct VTGOBJHDR *pVtgHdr, uint32_t fFlags)
     2392typedef struct SUPDRVTRACERSTRTAB
     2393{
     2394    /** Pointer to the string table. */
     2395    char       *pchStrTab;
     2396    /** The actual string table size. */
     2397    uint32_t    cbStrTab;
     2398    /** The original string pointers. */
     2399    RTUINTPTR   apszOrgFunctions[1];
     2400} SUPDRVTRACERSTRTAB, *PSUPDRVTRACERSTRTAB;
     2401
     2402
     2403/**
     2404 * Destroys a string table, restoring the original pszFunction member valus.
     2405 *
     2406 * @param   pThis               The string table structure.
     2407 * @param   paProbLocs          The probe location array.
     2408 * @param   cProbLocs           The number of probe locations.
     2409 */
     2410static void supr3TracerDestroyStrTab(PSUPDRVTRACERSTRTAB pThis, PVTGPROBELOC32 paProbeLocs32, PVTGPROBELOC64 paProbeLocs64,
     2411                                     uint32_t cProbeLocs, bool f32Bit)
     2412{
     2413    /* Restore. */
     2414    size_t i = cProbeLocs;
     2415    if (f32Bit)
     2416        while (i--)
     2417            paProbeLocs32[i].pszFunction = (uint32_t)pThis->apszOrgFunctions[i];
     2418    else
     2419        while (i--)
     2420            paProbeLocs64[i].pszFunction = pThis->apszOrgFunctions[i];
     2421
     2422    /* Free. */
     2423    RTMemFree(pThis->pchStrTab);
     2424    RTMemFree(pThis);
     2425}
     2426
     2427
     2428/**
     2429 * Creates a string table for the pszFunction members in the probe location
     2430 * array.
     2431 *
     2432 * This will save and replace the pszFunction members with offsets.
     2433 *
     2434 * @returns Pointer to a string table structure.  NULL on failure.
     2435 * @param   paProbLocs          The probe location array.
     2436 * @param   cProbLocs           The number of elements in the array.
     2437 * @param   cBits
     2438 */
     2439static PSUPDRVTRACERSTRTAB supr3TracerCreateStrTab(PVTGPROBELOC32 paProbeLocs32,
     2440                                                   PVTGPROBELOC64 paProbeLocs64,
     2441                                                   uint32_t cProbeLocs,
     2442                                                   RTUINTPTR offDelta,
     2443                                                   bool f32Bit)
     2444{
     2445    if (cProbeLocs > _128K)
     2446        return NULL;
     2447
     2448    /*
     2449     * Allocate the string table structures.
     2450     */
     2451    size_t              cbThis    = RT_OFFSETOF(SUPDRVTRACERSTRTAB, apszOrgFunctions[cProbeLocs]);
     2452    PSUPDRVTRACERSTRTAB pThis     = (PSUPDRVTRACERSTRTAB)RTMemAlloc(cbThis);
     2453    if (!pThis)
     2454        return NULL;
     2455
     2456    uint32_t const      cHashBits = cProbeLocs * 2 - 1;
     2457    uint32_t           *pbmHash   = (uint32_t *)RTMemAllocZ(RT_ALIGN_32(cHashBits, 64) / 8 );
     2458    if (!pbmHash)
     2459    {
     2460        RTMemFree(pThis);
     2461        return NULL;
     2462    }
     2463
     2464    /*
     2465     * Calc the max string table size and save the orignal pointers so we can
     2466     * replace them later.
     2467     */
     2468    size_t cbMax = 1;
     2469    for (uint32_t i = 0; i < cProbeLocs; i++)
     2470    {
     2471        pThis->apszOrgFunctions[i] = f32Bit ? paProbeLocs32[i].pszFunction : paProbeLocs64[i].pszFunction;
     2472        const char *pszFunction = (const char *)(uintptr_t)(pThis->apszOrgFunctions[i] + offDelta);
     2473        size_t cch = strlen(pszFunction);
     2474        if (cch > _1K)
     2475        {
     2476            cbMax = 0;
     2477            break;
     2478        }
     2479        cbMax += cch + 1;
     2480    }
     2481
     2482    /* Alloc space for it. */
     2483    if (cbMax > 0)
     2484        pThis->pchStrTab = (char *)RTMemAlloc(cbMax);
     2485    else
     2486        pThis->pchStrTab = NULL;
     2487    if (!pThis->pchStrTab)
     2488    {
     2489        RTMemFree(pbmHash);
     2490        RTMemFree(pThis);
     2491        return NULL;
     2492    }
     2493
     2494    /*
     2495     * Create the string table.
     2496     */
     2497    uint32_t off = 0;
     2498    uint32_t offPrev = 0;
     2499
     2500    for (uint32_t i = 0; i < cProbeLocs; i++)
     2501    {
     2502        const char * const psz      = (const char *)(uintptr_t)(pThis->apszOrgFunctions[i] + offDelta);
     2503        size_t       const cch      = strlen(psz);
     2504        uint32_t     const iHashBit = RTStrHash1(psz) % cHashBits;
     2505        if (ASMBitTestAndSet(pbmHash, iHashBit))
     2506        {
     2507            /* Often it's the most recent string. */
     2508            if (   off - offPrev < cch + 1
     2509                || memcmp(&pThis->pchStrTab[offPrev], psz, cch + 1))
     2510            {
     2511                /* It wasn't, search the entire string table. (lazy bird) */
     2512                offPrev = 0;
     2513                while (offPrev < off)
     2514                {
     2515                    size_t cchCur = strlen(&pThis->pchStrTab[offPrev]);
     2516                    if (   cchCur == cch
     2517                        && !memcmp(&pThis->pchStrTab[offPrev], psz, cch + 1))
     2518                        break;
     2519                    offPrev += (uint32_t)cchCur + 1;
     2520                }
     2521            }
     2522        }
     2523        else
     2524            offPrev = off;
     2525
     2526        /* Add the string to the table. */
     2527        if (offPrev >= off)
     2528        {
     2529            memcpy(&pThis->pchStrTab[off], psz, cch + 1);
     2530            offPrev = off;
     2531            off += (uint32_t)cch + 1;
     2532        }
     2533
     2534        /* Update the entry */
     2535        if (f32Bit)
     2536            paProbeLocs32[i].pszFunction = offPrev;
     2537        else
     2538            paProbeLocs64[i].pszFunction = offPrev;
     2539    }
     2540
     2541    pThis->cbStrTab = off;
     2542    RTMemFree(pbmHash);
     2543    return pThis;
     2544}
     2545
     2546
     2547
     2548SUPR3DECL(int) SUPR3TracerRegisterModule(uintptr_t hModNative, const char *pszModule, struct VTGOBJHDR *pVtgHdr,
     2549                                         RTUINTPTR uVtgHdrAddr, uint32_t fFlags)
    23992550{
    24002551    /* Validate input. */
    24012552    NOREF(hModNative);
    24022553    AssertPtrReturn(pVtgHdr, VERR_INVALID_POINTER);
     2554    AssertReturn(!memcmp(pVtgHdr->szMagic, VTGOBJHDR_MAGIC, sizeof(pVtgHdr->szMagic)), VERR_SUPDRV_VTG_MAGIC);
    24032555    AssertPtrReturn(pszModule, VERR_INVALID_POINTER);
    24042556    size_t cchModule = strlen(pszModule);
     
    24072559    AssertReturn(fFlags == SUP_TRACER_UMOD_FLAGS_EXE || fFlags == SUP_TRACER_UMOD_FLAGS_SHARED, VERR_INVALID_PARAMETER);
    24082560
    2409     /* fake */
     2561    /*
     2562     * Set the probe location array offset and size members. If the size is
     2563     * zero, don't bother ring-0 with it.
     2564     */
     2565    if (!pVtgHdr->offProbeLocs)
     2566    {
     2567        uint64_t u64Tmp = pVtgHdr->uProbeLocsEnd.u64 - pVtgHdr->uProbeLocs.u64;
     2568        if (u64Tmp >= UINT32_MAX)
     2569            return VERR_SUPDRV_VTG_BAD_HDR_TOO_MUCH;
     2570        pVtgHdr->cbProbeLocs  = (uint32_t)u64Tmp;
     2571
     2572        u64Tmp = pVtgHdr->uProbeLocs.u64 - (uintptr_t)pVtgHdr;
     2573        if ((int64_t)u64Tmp != (int32_t)u64Tmp)
     2574            return VERR_SUPDRV_VTG_BAD_HDR_PTR;
     2575        pVtgHdr->offProbeLocs = (int32_t)u64Tmp;
     2576    }
     2577
     2578    if (   !pVtgHdr->cbProbeLocs
     2579        || !pVtgHdr->cbProbes)
     2580        return VINF_SUCCESS;
     2581
     2582    /*
     2583     * Fake out.
     2584     */
    24102585    if (RT_UNLIKELY(g_u32FakeMode))
    24112586        return VINF_SUCCESS;
     2587
     2588    /*
     2589     * Create a string table for the function names in the location array.
     2590     * It's somewhat easier to do that here than from ring-0.
     2591     */
     2592    size_t const        cProbeLocs  = pVtgHdr->cbProbeLocs
     2593                                    / (pVtgHdr->cBits == 32 ? sizeof(VTGPROBELOC32) : sizeof(VTGPROBELOC64));
     2594    PVTGPROBELOC        paProbeLocs = (PVTGPROBELOC)((uintptr_t)pVtgHdr + pVtgHdr->offProbeLocs);
     2595    PSUPDRVTRACERSTRTAB pStrTab     = supr3TracerCreateStrTab((PVTGPROBELOC32)paProbeLocs,
     2596                                                              (PVTGPROBELOC64)paProbeLocs,
     2597                                                              cProbeLocs, (uintptr_t)pVtgHdr - uVtgHdrAddr,
     2598                                                              pVtgHdr->cBits == 32);
     2599    if (!pStrTab)
     2600        return VERR_NO_MEMORY;
     2601
    24122602
    24132603    /*
     
    24212611    Req.Hdr.fFlags          = SUPREQHDR_FLAGS_DEFAULT;
    24222612    Req.Hdr.rc              = VERR_INTERNAL_ERROR;
    2423     Req.u.In.pVtgHdr        = pVtgHdr;
     2613    Req.u.In.uVtgHdrAddr    = uVtgHdrAddr;
     2614    Req.u.In.R3PtrVtgHdr    = pVtgHdr;
     2615    Req.u.In.R3PtrStrTab    = pStrTab->pchStrTab;
     2616    Req.u.In.cbStrTab       = pStrTab->cbStrTab;
    24242617    Req.u.In.fFlags         = fFlags;
    24252618
     
    24512644    if (RT_SUCCESS(rc))
    24522645        rc = Req.Hdr.rc;
     2646
     2647    supr3TracerDestroyStrTab(pStrTab, (PVTGPROBELOC32)paProbeLocs, (PVTGPROBELOC64)paProbeLocs,
     2648                             cProbeLocs,  pVtgHdr->cBits == 32);
    24532649    return rc;
    24542650}
     
    24592655    /* Validate input. */
    24602656    AssertPtrReturn(pVtgHdr, VERR_INVALID_POINTER);
    2461 
    2462     /* fake */
     2657    AssertReturn(!memcmp(pVtgHdr->szMagic, VTGOBJHDR_MAGIC, sizeof(pVtgHdr->szMagic)), VERR_SUPDRV_VTG_MAGIC);
     2658
     2659    /*
     2660     * Don't bother if the object is empty.
     2661     */
     2662    if (   !pVtgHdr->cbProbeLocs
     2663        || !pVtgHdr->cbProbes)
     2664        return VINF_SUCCESS;
     2665
     2666    /*
     2667     * Fake out.
     2668     */
    24632669    if (RT_UNLIKELY(g_u32FakeMode))
    24642670        return VINF_SUCCESS;
     
    24822688}
    24832689
     2690
     2691DECLASM(void) suplibTracerFireProbe(PVTGPROBELOC pProbeLoc, PSUPTRACERUMODFIREPROBE pReq)
     2692{
     2693    pReq->Hdr.u32Cookie         = g_u32Cookie;
     2694    pReq->Hdr.u32SessionCookie  = g_u32SessionCookie;
     2695    Assert(pReq->Hdr.cbIn  == SUP_IOCTL_TRACER_UMOD_FIRE_PROBE_SIZE_IN);
     2696    Assert(pReq->Hdr.cbOut == SUP_IOCTL_TRACER_UMOD_FIRE_PROBE_SIZE_OUT);
     2697    pReq->Hdr.fFlags            = SUPREQHDR_FLAGS_DEFAULT;
     2698    pReq->Hdr.rc                = VINF_SUCCESS;
     2699
     2700    suplibOsIOCtl(&g_supLibData, SUP_IOCTL_TRACER_UMOD_FIRE_PROBE, pReq, SUP_IOCTL_TRACER_UMOD_FIRE_PROBE_SIZE);
     2701}
     2702
Note: See TracChangeset for help on using the changeset viewer.

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