SUPDrvTracer.cpp revision a66ec044d2a64d926996cd24da5faadccb070be3
248c89033c87fed7229aa29bbbc4f4698fb13687vboxsync * VBoxDrv - The VirtualBox Support Driver - Tracer Interface.
248c89033c87fed7229aa29bbbc4f4698fb13687vboxsync * Copyright (C) 2012 Oracle Corporation
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync * available from http://www.virtualbox.org. This file is free software;
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync * you can redistribute it and/or modify it under the terms of the GNU
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync * General Public License (GPL) as published by the Free Software
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync * The contents of this file may alternatively be used under the terms
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync * of the Common Development and Distribution License Version 1.0
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync * VirtualBox OSE distribution, in which case the provisions of the
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync * CDDL are applicable instead of those of the GPL.
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync * You may elect to license modified versions of this file under the
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync * terms and conditions of either the GPL or the CDDL or both.
750df3fe104e01cadbc3d5bd20243055d283d4e5vboxsync/*******************************************************************************
750df3fe104e01cadbc3d5bd20243055d283d4e5vboxsync* Header Files *
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync*******************************************************************************/
750df3fe104e01cadbc3d5bd20243055d283d4e5vboxsync/*******************************************************************************
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync* Structures and Typedefs *
5050fc8de0b121eab1b738d7c1007cde4903284dvboxsync*******************************************************************************/
c89333d3e41e439ed9e74768000edc399d3e72e6vboxsync/** Pointer to a user tracer module registration record. */
750df3fe104e01cadbc3d5bd20243055d283d4e5vboxsync * Data for a tracepoint provider.
c89333d3e41e439ed9e74768000edc399d3e72e6vboxsync /** The entry in the provider list for this image. */
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync /** The entry in the per session provider list for this image. */
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync /** The core structure. */
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync /** Pointer to the image this provider resides in. NULL if it's a
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync * driver. */
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync /** The session this provider is associated with if registered via
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync * SUPR0VtgRegisterDrv. NULL if pImage is set. */
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync /** The user tracepoint module associated with this provider. NULL if
750df3fe104e01cadbc3d5bd20243055d283d4e5vboxsync * pImage is set. */
750df3fe104e01cadbc3d5bd20243055d283d4e5vboxsync /** Used to indicate that we've called pfnProviderDeregistered already and it
750df3fe104e01cadbc3d5bd20243055d283d4e5vboxsync * failed because the provider was busy. Next time we must try
750df3fe104e01cadbc3d5bd20243055d283d4e5vboxsync * pfnProviderDeregisterZombie.
750df3fe104e01cadbc3d5bd20243055d283d4e5vboxsync * @remarks This does not necessiarly mean the provider is in the zombie
750df3fe104e01cadbc3d5bd20243055d283d4e5vboxsync * list. See supdrvTracerCommonDeregisterImpl. */
750df3fe104e01cadbc3d5bd20243055d283d4e5vboxsync /** Set if the provider has been successfully registered with the
750df3fe104e01cadbc3d5bd20243055d283d4e5vboxsync * tracer. */
750df3fe104e01cadbc3d5bd20243055d283d4e5vboxsync /** The provider name (for logging purposes). */
750df3fe104e01cadbc3d5bd20243055d283d4e5vboxsync/** Pointer to the data for a tracepoint provider. */
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync * User tracer module VTG data copy.
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync /** Magic (SUDPRVVTGCOPY_MAGIC). */
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync /** Refernece counter (we expect to share a lot of these). */
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync /** The size of the */
ffb50166c9adb4ae583b914d405197035cf890advboxsync /** Image type flags. */
ffb50166c9adb4ae583b914d405197035cf890advboxsync /** Hash list entry (SUPDRVDEVEXT::aTrackerUmodHash). */
ffb50166c9adb4ae583b914d405197035cf890advboxsync /** The VTG object header.
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync * The rest of the data follows immediately afterwards. First the object,
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync * then the probe locations and finally the probe location string table. All
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync * pointers are fixed up to point within this data. */
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync/** Pointer to a VTG object copy. */
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync/** Magic value for SUPDRVVTGCOPY. */
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync * User tracer module registration record.
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync /** Magic (SUPDRVTRACERUMOD_MAGIC). */
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync /** List entry. This is anchored in SUPDRVSESSION::UmodList. */
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync /** The address of the ring-3 VTG header. */
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync /** Pointer to the ring-0 copy of the VTG data. */
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync /** The memory object that locks down the user memory. */
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync /** The memory object that maps the locked memory into kernel space. */
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync /** Pointer to the probe enabled-count array within the mapping. */
248c89033c87fed7229aa29bbbc4f4698fb13687vboxsync /** Pointer to the probe location array within the mapping. */
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync /** The address of the ring-3 probe locations. */
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync /** The lookup table index. */
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync /** The module bit count. */
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync /** The size of a probe location record. */
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync /** The number of probe locations. */
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync /** Ring-0 probe location info. */
b4d7b4dbcc45b8bde7502aa129440d92d7ffd038vboxsync/** Magic value for SUPDRVVTGCOPY. */
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync/*******************************************************************************
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync* Defined Constants And Macros *
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync*******************************************************************************/
462e60a19d02a99b2b1a5c08dff74bb0808d707cvboxsync/** Simple SUPR0Printf-style logging. */
462e60a19d02a99b2b1a5c08dff74bb0808d707cvboxsync/*******************************************************************************
462e60a19d02a99b2b1a5c08dff74bb0808d707cvboxsync* Global Variables *
462e60a19d02a99b2b1a5c08dff74bb0808d707cvboxsync*******************************************************************************/
462e60a19d02a99b2b1a5c08dff74bb0808d707cvboxsync/** The address of the current probe fire routine for kernel mode. */
462e60a19d02a99b2b1a5c08dff74bb0808d707cvboxsyncPFNRT g_pfnSupdrvProbeFireKernel = supdrvTracerProbeFireStub;
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync/*******************************************************************************
462e60a19d02a99b2b1a5c08dff74bb0808d707cvboxsync* Internal Functions *
462e60a19d02a99b2b1a5c08dff74bb0808d707cvboxsync*******************************************************************************/
462e60a19d02a99b2b1a5c08dff74bb0808d707cvboxsyncstatic void supdrvVtgReleaseObjectCopy(PSUPDRVDEVEXT pDevExt, PSUPDRVVTGCOPY pThis);
462e60a19d02a99b2b1a5c08dff74bb0808d707cvboxsync * Validates a VTG string against length and characterset limitations.
cd5df721f068659172f3bf95de8fedeb465f057dvboxsync * @returns VINF_SUCCESS, VERR_SUPDRV_VTG_BAD_STRING or
462e60a19d02a99b2b1a5c08dff74bb0808d707cvboxsync * VERR_SUPDRV_VTG_STRING_TOO_LONG.
462e60a19d02a99b2b1a5c08dff74bb0808d707cvboxsync * @param psz The string.
462e60a19d02a99b2b1a5c08dff74bb0808d707cvboxsync /*RTAssertMsg2("off=%u '%s'\n", off, psz);*/
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync/** Used by the validation code below. */
11b175175a0ed424b8e8354acda681ad0adde0f8vboxsync MY_CHECK_MSG_RET(a_Expr, ("%s: Validation failed on line " RT_XSTR(__LINE__) ": " #a_Expr "\n", __FUNCTION__), a_rc)
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync/** Used by the validation code below. */
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync#define MY_CHECK_MSG_RET(a_Expr, a_PrintfArgs, a_rc) \
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync do { if (RT_UNLIKELY(!(a_Expr))) { SUPR0Printf a_PrintfArgs; return (a_rc); } } while (0)
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync/** Used by the validation code below. */
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync if ((uintptr_t)(p) - (uintptr_t)pbImage > cbImage) \
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync SUPR0Printf("supdrvVtgValidate: " #rc " - p=%p pbImage=%p cbImage=%#zxline=%u %s\n", \
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync return (rc); \
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync else if (!RT_VALID_PTR(p)) \
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync return (rc); \
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync } while (0)
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync * Validates the VTG object header.
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync * @returns VBox status code.
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync * @param pVtgHdr The header.
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync * @param uVtgHdrAddr The address where the header is actually
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync * @param cbVtgObj The alleged size of the header.
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync * @param pbImage The image base, if available.
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync * @param cbImage The image size, if available.
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync * @param fUmod Whether this is a user module.
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsyncstatic int supdrvVtgValidateHdr(PVTGOBJHDR pVtgHdr, RTUINTPTR uVtgHdrAddr, const uint8_t *pbImage, size_t cbImage, bool fUmod)
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync unsigned i;
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync#define MY_VALIDATE_SIZE(cb, cMin, cMax, cbUnit, rcBase) \
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync SUPR0Printf("supdrvVtgValidateHdr: " #rcBase "_TOO_FEW - cb=%#zx cMin=%#zx cbUnit=%#zx line=%u %s\n", \
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync (size_t)(cb), (size_t)(cMin), (size_t)cbUnit, __LINE__, #cb); \
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync SUPR0Printf("supdrvVtgValidateHdr: " #rcBase "_TOO_MUCH - cb=%#zx cMax=%#zx cbUnit=%#zx line=%u %s\n", \
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync (size_t)(cb), (size_t)(cMax), (size_t)cbUnit, __LINE__, #cb); \
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync SUPR0Printf("supdrvVtgValidateHdr: " #rcBase "_NOT_MULTIPLE - cb=%#zx cbUnit=%#zx line=%u %s\n", \
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync } while (0)
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync#define MY_VALIDATE_OFF(off, cb, cMin, cMax, cbUnit, cbAlign, rcBase) \
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync SUPR0Printf("supdrvVtgValidateHdr: " #rcBase "_OFF - off=%#x cb=%#x pVtgHdr=%p cbVtgHdr=%#zx line=%u %s\n", \
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync SUPR0Printf("supdrvVtgValidateHdr: " #rcBase "_OFF - off=%#x align=%#zx line=%u %s\n", \
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync MY_VALIDATE_SIZE(cb, cMin, cMax, cbUnit, rcBase); \
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync } while (0)
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync * Make sure both pbImage and cbImage are NULL/0 if one if of them is.
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync MY_WITHIN_IMAGE(pVtgHdr, VERR_SUPDRV_VTG_BAD_HDR_PTR);
cd5df721f068659172f3bf95de8fedeb465f057dvboxsync MY_WITHIN_IMAGE((uint8_t *)pVtgHdr + cbVtgObj - 1, VERR_SUPDRV_VTG_BAD_HDR_PTR);
5050fc8de0b121eab1b738d7c1007cde4903284dvboxsync SUPR0Printf("supdrvVtgValidateHdr: VERR_SUPDRV_TRACER_TOO_LARGE - cbVtgObj=%#x\n", cbVtgObj);
5050fc8de0b121eab1b738d7c1007cde4903284dvboxsync * Set the probe location array offset and size members.
5050fc8de0b121eab1b738d7c1007cde4903284dvboxsync uint64_t u64Tmp = pVtgHdr->uProbeLocsEnd.u64 - pVtgHdr->uProbeLocs.u64;
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync SUPR0Printf("supdrvVtgValidateHdr: VERR_SUPDRV_VTG_BAD_HDR_TOO_MUCH - u64Tmp=%#llx ProbeLocs=%#llx ProbeLocsEnd=%#llx\n",
5050fc8de0b121eab1b738d7c1007cde4903284dvboxsync u64Tmp, pVtgHdr->uProbeLocs.u64, pVtgHdr->uProbeLocsEnd.u64);
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync /* The loader and/or ld64-97.17 seems not to generate fixups for our
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync __VTGObj section. Detect this by comparing them with the
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync u64VtgObjSectionStart member and assume max image size of 4MB. */
5050fc8de0b121eab1b738d7c1007cde4903284dvboxsync uint64_t offDelta = uVtgHdrAddr - pVtgHdr->u64VtgObjSectionStart;
510567648d46488f4166e5f69ffffe3eeeeec4d9vboxsync SUPR0Printf("supdrvVtgValidateHdr: VERR_SUPDRV_VTG_BAD_HDR_PTR - u64Tmp=%#llx uProbeLocs=%#llx uVtgHdrAddr=%RTptr\n",
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync * The non-area description fields.
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync if (memcmp(pVtgHdr->szMagic, VTGOBJHDR_MAGIC, sizeof(pVtgHdr->szMagic)))
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync MY_CHECK_RET(pVtgHdr->au32Reserved1[0] == 0, VERR_SUPDRV_VTG_BAD_HDR_MISC);
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync MY_CHECK_RET(pVtgHdr->au32Reserved1[1] == 0, VERR_SUPDRV_VTG_BAD_HDR_MISC);
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync MY_CHECK_RET(!RTUuidIsNull(&pVtgHdr->Uuid), VERR_SUPDRV_VTG_BAD_HDR_MISC);
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync * Check the individual area descriptors.
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync MY_VALIDATE_OFF(pVtgHdr->offStrTab, pVtgHdr->cbStrTab, 4, _1M, sizeof(char), sizeof(uint8_t), VERR_SUPDRV_VTG_BAD_HDR);
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync MY_VALIDATE_OFF(pVtgHdr->offArgLists, pVtgHdr->cbArgLists, 1, _32K, sizeof(uint32_t), sizeof(uint32_t), VERR_SUPDRV_VTG_BAD_HDR);
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync MY_VALIDATE_OFF(pVtgHdr->offProbes, pVtgHdr->cbProbes, 1, _32K, sizeof(VTGDESCPROBE), sizeof(uint32_t), VERR_SUPDRV_VTG_BAD_HDR);
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync MY_VALIDATE_OFF(pVtgHdr->offProviders, pVtgHdr->cbProviders, 1, 16, sizeof(VTGDESCPROVIDER), sizeof(uint32_t), VERR_SUPDRV_VTG_BAD_HDR);
5050fc8de0b121eab1b738d7c1007cde4903284dvboxsync MY_VALIDATE_OFF(pVtgHdr->offProbeEnabled, pVtgHdr->cbProbeEnabled, 1, _32K, sizeof(uint32_t), sizeof(uint32_t), VERR_SUPDRV_VTG_BAD_HDR);
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync MY_WITHIN_IMAGE(pVtgHdr->uProbeLocs.p, VERR_SUPDRV_VTG_BAD_HDR_PTR);
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync MY_WITHIN_IMAGE(pVtgHdr->uProbeLocsEnd.p, VERR_SUPDRV_VTG_BAD_HDR_PTR);
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync MY_VALIDATE_SIZE( pVtgHdr->cbProbeLocs, 1, _128K, sizeof(VTGPROBELOC), VERR_SUPDRV_VTG_BAD_HDR);
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync MY_VALIDATE_SIZE( pVtgHdr->cbProbeLocs, 1, _8K, sizeof(VTGPROBELOC32), VERR_SUPDRV_VTG_BAD_HDR);
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync MY_VALIDATE_SIZE( pVtgHdr->cbProbeLocs, 1, _8K, sizeof(VTGPROBELOC64), VERR_SUPDRV_VTG_BAD_HDR);
5050fc8de0b121eab1b738d7c1007cde4903284dvboxsync /* Will check later that offProbeLocs are following closely on the
5050fc8de0b121eab1b738d7c1007cde4903284dvboxsync enable count array, so no need to validate the offset here. */
5050fc8de0b121eab1b738d7c1007cde4903284dvboxsync * Some additional consistency checks.
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync if ( pVtgHdr->uProbeLocsEnd.u64 - pVtgHdr->uProbeLocs.u64 != pVtgHdr->cbProbeLocs
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync || (int64_t)(pVtgHdr->uProbeLocs.u64 - uVtgHdrAddr) != pVtgHdr->offProbeLocs)
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync SUPR0Printf("supdrvVtgValidateHdr: VERR_SUPDRV_VTG_BAD_HDR_MISC - uProbeLocs=%#llx uProbeLocsEnd=%#llx offProbeLocs=%#llx cbProbeLocs=%#x uVtgHdrAddr=%RTptr\n",
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync pVtgHdr->uProbeLocs.u64, pVtgHdr->uProbeLocsEnd.u64, pVtgHdr->offProbeLocs, pVtgHdr->cbProbeLocs, uVtgHdrAddr);
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync if (pVtgHdr->cbProbes / sizeof(VTGDESCPROBE) != pVtgHdr->cbProbeEnabled / sizeof(uint32_t))
5050fc8de0b121eab1b738d7c1007cde4903284dvboxsync SUPR0Printf("supdrvVtgValidateHdr: VERR_SUPDRV_VTG_BAD_HDR_MISC - cbProbeEnabled=%#zx cbProbes=%#zx\n",
5050fc8de0b121eab1b738d7c1007cde4903284dvboxsync * Check that there are no overlapping areas. This is a little bit ugly...
5050fc8de0b121eab1b738d7c1007cde4903284dvboxsync paAreas = (struct VTGAREAS const *)&pVtgHdr->offStrTab;
5050fc8de0b121eab1b738d7c1007cde4903284dvboxsync for (i = 0; i < cAreas; i++)
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync SUPR0Printf("supdrvVtgValidateHdr: VERR_SUPDRV_VTG_BAD_HDR_MISC - overlapping areas %d and %d\n", i, i-1);
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync && (uint32_t)-pVtgHdr->offProbeLocs < pVtgHdr->cbProbeLocs)
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync SUPR0Printf("supdrvVtgValidateHdr: VERR_SUPDRV_VTG_BAD_HDR_MISC - probe locations overlaps the header\n");
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync * Check that the object size is correct.
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync if (pVtgHdr->cbObj != pVtgHdr->offProbeEnabled + pVtgHdr->cbProbeEnabled)
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync SUPR0Printf("supdrvVtgValidateHdr: VERR_SUPDRV_VTG_BAD_HDR_MISC - bad header size %#x, expected %#x\n",
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync pVtgHdr->cbObj, pVtgHdr->offProbeEnabled + pVtgHdr->cbProbeEnabled);
cd5df721f068659172f3bf95de8fedeb465f057dvboxsync * Validates the VTG data.
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync * @returns VBox status code.
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync * @param pVtgHdr The VTG object header of the data to validate.
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync * @param uVtgHdrAddr The address where the header is actually
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync * @param pbImage The image base. For validating the probe
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync * locations.
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync * @param cbImage The image size to go with @a pbImage.
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync * @param fUmod Whether this is a user module.
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsyncstatic int supdrvVtgValidate(PVTGOBJHDR pVtgHdr, RTUINTPTR uVtgHdrAddr, const uint8_t *pbImage, size_t cbImage, bool fUmod)
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync rc = supdrvVtgValidateString((char *)pVtgHdr + pVtgHdr->offStrTab + (a_offStrTab)); \
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync } while (0)
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync if ((Attr).u8Code <= (uint8_t)kVTGStability_Invalid || (Attr).u8Code >= (uint8_t)kVTGStability_End) \
5050fc8de0b121eab1b738d7c1007cde4903284dvboxsync if ((Attr).u8Data <= (uint8_t)kVTGStability_Invalid || (Attr).u8Data >= (uint8_t)kVTGStability_End) \
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync if ((Attr).u8DataDep <= (uint8_t)kVTGClass_Invalid || (Attr).u8DataDep >= (uint8_t)kVTGClass_End) \
5050fc8de0b121eab1b738d7c1007cde4903284dvboxsync } while (0)
5050fc8de0b121eab1b738d7c1007cde4903284dvboxsync * The header.
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync rc = supdrvVtgValidateHdr(pVtgHdr, uVtgHdrAddr, pbImage, cbImage, fUmod);
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync * Validate the providers.
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync cProviders = i = pVtgHdr->cbProviders / sizeof(VTGDESCPROVIDER);
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync while (i-- > 0)
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync PCVTGDESCPROVIDER pProvider = (PCVTGDESCPROVIDER)((uintptr_t)pVtgHdr + pVtgHdr->offProviders) + i;
5050fc8de0b121eab1b738d7c1007cde4903284dvboxsync MY_CHECK_RET(pProvider->iFirstProbe < pVtgHdr->cbProbeEnabled / sizeof(uint32_t), VERR_SUPDRV_VTG_BAD_PROVIDER);
5050fc8de0b121eab1b738d7c1007cde4903284dvboxsync MY_CHECK_RET((uint32_t)pProvider->iFirstProbe + pProvider->cProbes <= pVtgHdr->cbProbeEnabled / sizeof(uint32_t),
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync MY_CHECK_RET(pProvider->bReserved == 0, VERR_SUPDRV_VTG_BAD_PROVIDER);
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync * Validate probes.
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync while (i-- > 0)
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync PCVTGDESCPROBE pProbe = (PCVTGDESCPROBE)( (uintptr_t)pVtgHdr + pVtgHdr->offProbes) + i;
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync PCVTGDESCPROVIDER pProvider = (PCVTGDESCPROVIDER)((uintptr_t)pVtgHdr + pVtgHdr->offProviders) + pProbe->idxProvider;
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync PCVTGDESCARGLIST pArgList = (PCVTGDESCARGLIST)( (uintptr_t)pVtgHdr + pVtgHdr->offArgLists + pProbe->offArgList );
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync MY_CHECK_RET(pProbe->offArgList < pVtgHdr->cbArgLists, VERR_SUPDRV_VTG_BAD_PROBE);
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync MY_CHECK_RET((pProbe->offArgList & 3) == 0, VERR_SUPDRV_VTG_BAD_PROBE);
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync MY_CHECK_RET(pProbe->idxEnabled == i, VERR_SUPDRV_VTG_BAD_PROBE); /* The lists are parallel. */
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync MY_CHECK_RET(pProbe->idxProvider < cProviders, VERR_SUPDRV_VTG_BAD_PROBE);
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync MY_CHECK_RET(i - pProvider->iFirstProbe < pProvider->cProbes, VERR_SUPDRV_VTG_BAD_PROBE);
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync if (pProbe->offObjHdr != (intptr_t)pVtgHdr - (intptr_t)pProbe)
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync SUPR0Printf("supdrvVtgValidate: VERR_SUPDRV_TRACER_BAD_ARG_FLAGS - iProbe=%u offObjHdr=%d expected %zd\n",
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync i, pProbe->offObjHdr, (intptr_t)pVtgHdr - (intptr_t)pProbe);
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync /* The referenced argument list. */
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync SUPR0Printf("supdrvVtgValidate: VERR_SUPDRV_TRACER_BAD_ARG_FLAGS - iProbe=%u cArgs=%u\n", i, pArgList->cArgs);
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync SUPR0Printf("supdrvVtgValidate: VERR_SUPDRV_TRACER_BAD_ARG_FLAGS - iProbe=%u fHaveLargeArgs=%d\n", i, pArgList->fHaveLargeArgs);
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync SUPR0Printf("supdrvVtgValidate: VERR_SUPDRV_TRACER_BAD_ARG_FLAGS - reserved MBZ iProbe=%u\n", i);
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync while (iArg-- > 0)
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync uint32_t const fType = pArgList->aArgs[iArg].fType;
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync SUPR0Printf("supdrvVtgValidate: VERR_SUPDRV_TRACER_BAD_ARG_FLAGS - fType=%#x iArg=%u iProbe=%u (#0)\n", fType, iArg, i);
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync switch (pArgList->aArgs[iArg].fType & VTG_TYPE_SIZE_MASK)
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync if (pArgList->aArgs[iArg].fType & VTG_TYPE_FIXED_SIZED)
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync SUPR0Printf("supdrvVtgValidate: VERR_SUPDRV_TRACER_BAD_ARG_FLAGS - fType=%#x iArg=%u iProbe=%u (#1)\n", fType, iArg, i);
5050fc8de0b121eab1b738d7c1007cde4903284dvboxsync SUPR0Printf("supdrvVtgValidate: VERR_SUPDRV_TRACER_BAD_ARG_FLAGS - fType=%#x iArg=%u iProbe=%u (#2)\n", fType, iArg, i);
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync if (VTG_TYPE_IS_LARGE(pArgList->aArgs[iArg].fType))
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync if ((uint8_t)fHaveLargeArgs != pArgList->fHaveLargeArgs)
c99b597540585068d22dde4c9f74730305f24097vboxsync SUPR0Printf("supdrvVtgValidate: VERR_SUPDRV_TRACER_BAD_ARG_FLAGS - iProbe=%u fHaveLargeArgs=%d expected %d\n",
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync * Check that pacProbeEnabled is all zeros.
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync uint32_t const *pcProbeEnabled = (uint32_t const *)((uintptr_t)pVtgHdr + pVtgHdr->offProbeEnabled);
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync while (i-- > 0)
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync MY_CHECK_RET(pcProbeEnabled[0] == 0, VERR_SUPDRV_VTG_BAD_PROBE_ENABLED);
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync * Probe locations.
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync PVTGPROBELOC paProbeLocs = (PVTGPROBELOC)((intptr_t)pVtgHdr + pVtgHdr->offProbeLocs);
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync while (i-- > 0)
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync MY_CHECK_RET(paProbeLocs[i].uLine < _1G, VERR_SUPDRV_VTG_BAD_PROBE_LOC);
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync MY_CHECK_RET(paProbeLocs[i].fEnabled == false, VERR_SUPDRV_VTG_BAD_PROBE_LOC);
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync MY_CHECK_RET(paProbeLocs[i].idProbe == 0, VERR_SUPDRV_VTG_BAD_PROBE_LOC);
c99b597540585068d22dde4c9f74730305f24097vboxsync MY_WITHIN_IMAGE(paProbeLocs[i].pszFunction, VERR_SUPDRV_VTG_BAD_PROBE_LOC);
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync offTmp = (uintptr_t)paProbeLocs[i].pProbe - (uintptr_t)pVtgHdr->offProbes - (uintptr_t)pVtgHdr;
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync#ifdef RT_OS_DARWIN /* See header validation code. */
b8bb9c9f6b8ebfd0a7d6df0c0289f9fe80241750vboxsync uint64_t offDelta = uVtgHdrAddr - pVtgHdr->u64VtgObjSectionStart;
5050fc8de0b121eab1b738d7c1007cde4903284dvboxsync paProbeLocs[i].pProbe = (PVTGDESCPROBE)((uintptr_t)paProbeLocs[i].pProbe + offDelta);
5050fc8de0b121eab1b738d7c1007cde4903284dvboxsync MY_CHECK_RET(offTmp < pVtgHdr->cbProbes, VERR_SUPDRV_VTG_BAD_PROBE_LOC);
5050fc8de0b121eab1b738d7c1007cde4903284dvboxsync MY_CHECK_RET(offTmp / sizeof(VTGDESCPROBE) * sizeof(VTGDESCPROBE) == offTmp, VERR_SUPDRV_VTG_BAD_PROBE_LOC);
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync * Gets a string from the string table.
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync * @returns Pointer to the string.
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync * @param pVtgHdr The VTG object header.
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync * @param offStrTab The string table offset.
5050fc8de0b121eab1b738d7c1007cde4903284dvboxsyncstatic const char *supdrvVtgGetString(PVTGOBJHDR pVtgHdr, uint32_t offStrTab)
5050fc8de0b121eab1b738d7c1007cde4903284dvboxsync return (char *)pVtgHdr + pVtgHdr->offStrTab + offStrTab;
5050fc8de0b121eab1b738d7c1007cde4903284dvboxsync * Frees the provider structure and associated resources.
5050fc8de0b121eab1b738d7c1007cde4903284dvboxsync * @param pProv The provider to free.
5050fc8de0b121eab1b738d7c1007cde4903284dvboxsyncstatic void supdrvTracerFreeProvider(PSUPDRVTPPROVIDER pProv)
5050fc8de0b121eab1b738d7c1007cde4903284dvboxsync LOG_TRACER(("Freeing tracepoint provider '%s' / %p\n", pProv->szName, pProv->Core.TracerData.DTrace.idProvider));
5050fc8de0b121eab1b738d7c1007cde4903284dvboxsync * Unlinks and deregisters a provider.
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync * If the provider is still busy, it will be put in the zombie list.
5050fc8de0b121eab1b738d7c1007cde4903284dvboxsync * @param pDevExt The device extension.
b8bb9c9f6b8ebfd0a7d6df0c0289f9fe80241750vboxsync * @param pProv The provider.
5050fc8de0b121eab1b738d7c1007cde4903284dvboxsync * @remarks The caller owns mtxTracer.
5050fc8de0b121eab1b738d7c1007cde4903284dvboxsyncstatic void supdrvTracerDeregisterVtgObj(PSUPDRVDEVEXT pDevExt, PSUPDRVTPPROVIDER pProv)
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync rc = pDevExt->pTracerOps->pfnProviderDeregister(pDevExt->pTracerOps, &pProv->Core);
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync RTListAppend(&pDevExt->TracerProviderZombieList, &pProv->ListEntry);
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync LOG_TRACER(("Invalidated provider '%s' / %p and put it on the zombie list (rc=%Rrc)\n",
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync pProv->szName, pProv->Core.TracerData.DTrace.idProvider, rc));
5050fc8de0b121eab1b738d7c1007cde4903284dvboxsync * Processes the zombie list.
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync * @param pDevExt The device extension.
5050fc8de0b121eab1b738d7c1007cde4903284dvboxsyncstatic void supdrvTracerProcessZombies(PSUPDRVDEVEXT pDevExt)
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync RTListForEachSafe(&pDevExt->TracerProviderZombieList, pProv, pProvNext, SUPDRVTPPROVIDER, ListEntry)
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync int rc = pDevExt->pTracerOps->pfnProviderDeregisterZombie(pDevExt->pTracerOps, &pProv->Core);
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync * Unregisters all providers, including zombies, waiting for busy providers to
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync * go idle and unregister smoothly.
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync * This may block.
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync * @param pDevExt The device extension.
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsyncstatic void supdrvTracerRemoveAllProviders(PSUPDRVDEVEXT pDevExt)
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync * Unregister all probes (there should only be one).
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync RTListForEachSafe(&pDevExt->TracerProviderList, pProv, pProvNext, SUPDRVTPPROVIDER, ListEntry)
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync * Try unregister zombies now, sleep on busy ones and tracer opens.
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync for (i = 0; ; i++)
cd5df721f068659172f3bf95de8fedeb465f057dvboxsync /* Zombies */
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync RTListForEachSafe(&pDevExt->TracerProviderZombieList, pProv, pProvNext, SUPDRVTPPROVIDER, ListEntry)
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync LOG_TRACER(("supdrvTracerRemoveAllProviders: Attemting to unregister '%s' / %p...\n",
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync pProv->szName, pProv->Core.TracerData.DTrace.idProvider));
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync rc = pDevExt->pTracerOps->pfnProviderDeregisterZombie(pDevExt->pTracerOps, &pProv->Core);
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync else if (!(i & 0xf))
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync SUPR0Printf("supdrvTracerRemoveAllProviders: Waiting on busy provider '%s' / %p (rc=%d)\n",
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync pProv->szName, pProv->Core.TracerData.DTrace.idProvider, rc);
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync LOG_TRACER(("supdrvTracerRemoveAllProviders: Failed to unregister provider '%s' / %p - rc=%d\n",
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync pProv->szName, pProv->Core.TracerData.DTrace.idProvider, rc));
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync fEmpty = RTListIsEmpty(&pDevExt->TracerProviderZombieList);
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync /* Tracer opens. */
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync if (!(i & 0xf))
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync SUPR0Printf("supdrvTracerRemoveAllProviders: Waiting on %u opens\n", pDevExt->cTracerOpens);
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync LOG_TRACER(("supdrvTracerRemoveAllProviders: Waiting on %u opens\n", pDevExt->cTracerOpens));
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync /* Delay...*/
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync * Registers the VTG tracepoint providers of a driver.
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync * @returns VBox status code.
2e4df4fd9eace3c61be68bb5eb12a93f9a79334dvboxsync * @param pszName The driver name.
2e4df4fd9eace3c61be68bb5eb12a93f9a79334dvboxsync * @param pVtgHdr The VTG object header.
2e4df4fd9eace3c61be68bb5eb12a93f9a79334dvboxsync * @param pImage The image if applicable.
2e4df4fd9eace3c61be68bb5eb12a93f9a79334dvboxsync * @param pSession The session if applicable.
2e4df4fd9eace3c61be68bb5eb12a93f9a79334dvboxsync * @param pUmod The associated user tracepoint module if
2e4df4fd9eace3c61be68bb5eb12a93f9a79334dvboxsync * applicable.
2e4df4fd9eace3c61be68bb5eb12a93f9a79334dvboxsync * @param pszModName The module name.
2e4df4fd9eace3c61be68bb5eb12a93f9a79334dvboxsyncstatic int supdrvTracerRegisterVtgObj(PSUPDRVDEVEXT pDevExt, PVTGOBJHDR pVtgHdr, PSUPDRVLDRIMAGE pImage,
2e4df4fd9eace3c61be68bb5eb12a93f9a79334dvboxsync PSUPDRVSESSION pSession, PSUPDRVTRACERUMOD pUmod, const char *pszModName)
2e4df4fd9eace3c61be68bb5eb12a93f9a79334dvboxsync * Validate input.
2e4df4fd9eace3c61be68bb5eb12a93f9a79334dvboxsync AssertPtrNullReturn(pSession, VERR_INVALID_POINTER);
2e4df4fd9eace3c61be68bb5eb12a93f9a79334dvboxsync rc = supdrvVtgValidate(pVtgHdr, (uintptr_t)pVtgHdr,
2e4df4fd9eace3c61be68bb5eb12a93f9a79334dvboxsync (const uint8_t *)pImage->pvImage, pImage->cbImageBits,
2e4df4fd9eace3c61be68bb5eb12a93f9a79334dvboxsync false /*fUmod*/);
2e4df4fd9eace3c61be68bb5eb12a93f9a79334dvboxsync rc = supdrvVtgValidate(pVtgHdr, (uintptr_t)pVtgHdr, NULL, 0, pUmod != NULL);
2e4df4fd9eace3c61be68bb5eb12a93f9a79334dvboxsync * Check that there aren't any obvious duplicates.
2e4df4fd9eace3c61be68bb5eb12a93f9a79334dvboxsync * (Yes, this isn't race free, but it's good enough for now.)
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync if (pImage || !pSession || pSession->R0Process == NIL_RTPROCESS)
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync RTListForEach(&pDevExt->TracerProviderList, pProv, SUPDRVTPPROVIDER, ListEntry)
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync RTListForEach(&pSession->TpProviders, pProv, SUPDRVTPPROVIDER, SessionListEntry)
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync * Register the providers.
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync i = pVtgHdr->cbProviders / sizeof(VTGDESCPROVIDER);
750df3fe104e01cadbc3d5bd20243055d283d4e5vboxsync while (i-- > 0)
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync PVTGDESCPROVIDER pDesc = (PVTGDESCPROVIDER)((uintptr_t)pVtgHdr + pVtgHdr->offProviders) + i;
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync const char *pszName = supdrvVtgGetString(pVtgHdr, pDesc->offName);
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync size_t const cchName = strlen(pszName) + (pUmod ? 16 : 0);
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync pProv = (PSUPDRVTPPROVIDER)RTMemAllocZ(RT_OFFSETOF(SUPDRVTPPROVIDER, szName[cchName + 1 + cchModName + 1]));
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync pProv->Core.pszModName = &pProv->szName[cchName + 1];
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync pProv->Core.paProbeLocsRO = (PCVTGPROBELOC )((uintptr_t)pVtgHdr + pVtgHdr->offProbeLocs);
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync pProv->Core.pvProbeLocsEn = (void *)((uintptr_t)pVtgHdr + pVtgHdr->offProbeLocs);
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync pProv->Core.pacProbeEnabled = (uint32_t *)((uintptr_t)pVtgHdr + pVtgHdr->offProbeEnabled);
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync pProv->Core.pacProbeEnabled = pUmod->pacProbeEnabled;
5050fc8de0b121eab1b738d7c1007cde4903284dvboxsync pProv->Core.paR0Probes = (PSUPDRVPROBEINFO)&pUmod->aProbeLocs[pUmod->cProbeLocs];
750df3fe104e01cadbc3d5bd20243055d283d4e5vboxsync RTStrPrintf(pProv->szName, cchName + 1, "%s%u", pszName, (uint32_t)pSession->Process);
750df3fe104e01cadbc3d5bd20243055d283d4e5vboxsync memcpy((void *)pProv->Core.pszModName, pszModName, cchModName + 1);
5050fc8de0b121eab1b738d7c1007cde4903284dvboxsync * Do the actual registration and list manipulations while holding
5050fc8de0b121eab1b738d7c1007cde4903284dvboxsync * down the lock.
5050fc8de0b121eab1b738d7c1007cde4903284dvboxsync rc = pDevExt->pTracerOps->pfnProviderRegister(pDevExt->pTracerOps, &pProv->Core);
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync RTListAppend(&pDevExt->TracerProviderList, &pProv->ListEntry);
ebe46865faa75932265b29148843c6c54ffcb6a4vboxsync RTListAppend(&pSession->TpProviders, &pProv->SessionListEntry);
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync LOG_TRACER(("Registered tracepoint provider '%s' in '%s' -> %p\n",
c89333d3e41e439ed9e74768000edc399d3e72e6vboxsync pProv->szName, pszModName, pProv->Core.TracerData.DTrace.idProvider));
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync LOG_TRACER(("Failed to register tracepoint provider '%s' in '%s' -> %Rrc\n",
5050fc8de0b121eab1b738d7c1007cde4903284dvboxsync * In case of failure, we have to undo any providers we already
5050fc8de0b121eab1b738d7c1007cde4903284dvboxsync * managed to register.
b8bb9c9f6b8ebfd0a7d6df0c0289f9fe80241750vboxsync RTListForEachReverseSafe(&pDevExt->TracerProviderList, pProv, pProvNext, SUPDRVTPPROVIDER, ListEntry)
d3b1b01528fe21777281edf167f8deca06f86e39vboxsync RTListForEachSafe(&pSession->TpProviders, pProv, pProvNext, SUPDRVTPPROVIDER, SessionListEntry)
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync * Registers the VTG tracepoint providers of a driver.
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync * @returns VBox status code.
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync * @param pSession The support driver session handle.
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync * @param pVtgHdr The VTG header.
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync * @param pszName The driver name.
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsyncSUPR0DECL(int) SUPR0TracerRegisterDrv(PSUPDRVSESSION pSession, PVTGOBJHDR pVtgHdr, const char *pszName)
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync AssertReturn(SUP_IS_SESSION_VALID(pSession), VERR_INVALID_PARAMETER);
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync AssertReturn(pSession->R0Process == NIL_RTR0PROCESS, VERR_INVALID_PARAMETER);
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync LOG_TRACER(("SUPR0TracerRegisterDrv: pSession=%p pVtgHdr=%p pszName=%s\n", pSession, pVtgHdr, pszName));
0dd3967035b8a02985920baa57f948dc542b9388vboxsync rc = supdrvTracerRegisterVtgObj(pSession->pDevExt, pVtgHdr, NULL /*pImage*/, pSession, NULL /*pUmod*/, pszName);
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync * Try unregister zombies while we have a chance.
c89333d3e41e439ed9e74768000edc399d3e72e6vboxsync * Deregister the VTG tracepoint providers of a driver.
c89333d3e41e439ed9e74768000edc399d3e72e6vboxsync * @param pSession The support driver session handle.
c89333d3e41e439ed9e74768000edc399d3e72e6vboxsync * @param pVtgHdr The VTG header.
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsyncSUPR0DECL(void) SUPR0TracerDeregisterDrv(PSUPDRVSESSION pSession)
c89333d3e41e439ed9e74768000edc399d3e72e6vboxsync AssertReturnVoid(pSession->R0Process == NIL_RTR0PROCESS);
0dd3967035b8a02985920baa57f948dc542b9388vboxsync LOG_TRACER(("SUPR0TracerDeregisterDrv: pSession=%p\n", pSession));
0dd3967035b8a02985920baa57f948dc542b9388vboxsync * Search for providers belonging to this driver session.
0dd3967035b8a02985920baa57f948dc542b9388vboxsync RTListForEachSafe(&pSession->TpProviders, pProv, pProvNext, SUPDRVTPPROVIDER, SessionListEntry)
6475559a7e0e52892efbab4fbdedc879f6866109vboxsync * Try unregister zombies while we have a chance.
c89333d3e41e439ed9e74768000edc399d3e72e6vboxsync * Registers the VTG tracepoint providers of a module loaded by
c89333d3e41e439ed9e74768000edc399d3e72e6vboxsync * the support driver.
c89333d3e41e439ed9e74768000edc399d3e72e6vboxsync * This should be called from the ModuleInit code.
c89333d3e41e439ed9e74768000edc399d3e72e6vboxsync * @returns VBox status code.
c89333d3e41e439ed9e74768000edc399d3e72e6vboxsync * @param hMod The module handle.
c89333d3e41e439ed9e74768000edc399d3e72e6vboxsync * @param pVtgHdr The VTG header.
c89333d3e41e439ed9e74768000edc399d3e72e6vboxsyncSUPR0DECL(int) SUPR0TracerRegisterModule(void *hMod, PVTGOBJHDR pVtgHdr)
c89333d3e41e439ed9e74768000edc399d3e72e6vboxsync LOG_TRACER(("SUPR0TracerRegisterModule: %p\n", pVtgHdr));
0dd3967035b8a02985920baa57f948dc542b9388vboxsync * Validate input and context.
c89333d3e41e439ed9e74768000edc399d3e72e6vboxsync AssertReturn(pDevExt->pLdrInitImage == pImage, VERR_WRONG_ORDER);
c89333d3e41e439ed9e74768000edc399d3e72e6vboxsync AssertReturn(pDevExt->hLdrInitThread == RTThreadNativeSelf(), VERR_WRONG_ORDER);
c89333d3e41e439ed9e74768000edc399d3e72e6vboxsync AssertReturn((uintptr_t)pVtgHdr - (uintptr_t)pImage->pvImage < pImage->cbImageBits, VERR_INVALID_PARAMETER);
f75c6db919d277952ca03b7acf643e5e3ac96cafvboxsync * Do the job.
f75c6db919d277952ca03b7acf643e5e3ac96cafvboxsync rc = supdrvTracerRegisterVtgObj(pDevExt, pVtgHdr, pImage, NULL /*pSession*/, NULL /*pUmod*/, pImage->szName);
f75c6db919d277952ca03b7acf643e5e3ac96cafvboxsync LOG_TRACER(("SUPR0TracerRegisterModule: rc=%d\n", rc));
f75c6db919d277952ca03b7acf643e5e3ac96cafvboxsync * Try unregister zombies while we have a chance.
f75c6db919d277952ca03b7acf643e5e3ac96cafvboxsync * Registers the tracer implementation.
f75c6db919d277952ca03b7acf643e5e3ac96cafvboxsync * This should be called from the ModuleInit code or from a ring-0 session.
805a319b88bdf29b369da48402c58897a5e8b65dvboxsync * @returns VBox status code.
0c80e8c5ac4249337af378ff41c60033c9fff59fvboxsync * @param hMod The module handle.
805a319b88bdf29b369da48402c58897a5e8b65dvboxsync * @param pSession Ring-0 session handle.
805a319b88bdf29b369da48402c58897a5e8b65dvboxsync * @param pReg Pointer to the tracer registration structure.
805a319b88bdf29b369da48402c58897a5e8b65dvboxsync * @param ppHlp Where to return the tracer helper method table.
805a319b88bdf29b369da48402c58897a5e8b65dvboxsyncSUPR0DECL(int) SUPR0TracerRegisterImpl(void *hMod, PSUPDRVSESSION pSession, PCSUPDRVTRACERREG pReg, PCSUPDRVTRACERHLP *ppHlp)
805a319b88bdf29b369da48402c58897a5e8b65dvboxsync * Validate input and context.
c89333d3e41e439ed9e74768000edc399d3e72e6vboxsync AssertReturn(pSession == NULL, VERR_INVALID_PARAMETER);
c89333d3e41e439ed9e74768000edc399d3e72e6vboxsync AssertReturn(pDevExt->pLdrInitImage == pImage, VERR_WRONG_ORDER);
3c6306a66deef467e3c13483dd6529e1e1c6b822vboxsync AssertReturn(pDevExt->hLdrInitThread == RTThreadNativeSelf(), VERR_WRONG_ORDER);
805a319b88bdf29b369da48402c58897a5e8b65dvboxsync AssertReturn(SUP_IS_SESSION_VALID(pSession), VERR_INVALID_PARAMETER);
c89333d3e41e439ed9e74768000edc399d3e72e6vboxsync AssertReturn(pSession->R0Process == NIL_RTR0PROCESS, VERR_INVALID_PARAMETER);
c89333d3e41e439ed9e74768000edc399d3e72e6vboxsync AssertReturn(pReg->u32Magic == SUPDRVTRACERREG_MAGIC, VERR_INVALID_MAGIC);
750df3fe104e01cadbc3d5bd20243055d283d4e5vboxsync AssertReturn(pReg->u32Version == SUPDRVTRACERREG_VERSION, VERR_VERSION_MISMATCH);
c89333d3e41e439ed9e74768000edc399d3e72e6vboxsync AssertReturn(pReg->uEndMagic == SUPDRVTRACERREG_MAGIC, VERR_VERSION_MISMATCH);
c89333d3e41e439ed9e74768000edc399d3e72e6vboxsync AssertPtrReturn(pReg->pfnProbeFireKernel, VERR_INVALID_POINTER);
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync AssertPtrReturn(pReg->pfnProbeFireUser, VERR_INVALID_POINTER);
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync AssertPtrReturn(pReg->pfnTracerOpen, VERR_INVALID_POINTER);
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync AssertPtrReturn(pReg->pfnTracerIoCtl, VERR_INVALID_POINTER);
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync AssertPtrReturn(pReg->pfnTracerClose, VERR_INVALID_POINTER);
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync AssertPtrReturn(pReg->pfnProviderRegister, VERR_INVALID_POINTER);
750df3fe104e01cadbc3d5bd20243055d283d4e5vboxsync AssertPtrReturn(pReg->pfnProviderDeregister, VERR_INVALID_POINTER);
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync AssertPtrReturn(pReg->pfnProviderDeregisterZombie, VERR_INVALID_POINTER);
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync * Do the job.
750df3fe104e01cadbc3d5bd20243055d283d4e5vboxsync LOG_TRACER(("SUPR0TracerRegisterImpl: pReg=%p\n", pReg));
750df3fe104e01cadbc3d5bd20243055d283d4e5vboxsync g_pfnSupdrvProbeFireKernel = (PFNRT)pDevExt->pTracerOps->pfnProbeFireKernel;
c89333d3e41e439ed9e74768000edc399d3e72e6vboxsync * Iterate the already loaded modules and register their providers.
c89333d3e41e439ed9e74768000edc399d3e72e6vboxsync RTListForEach(&pDevExt->TracerProviderList, pProv, SUPDRVTPPROVIDER, ListEntry)
c89333d3e41e439ed9e74768000edc399d3e72e6vboxsync int rc2 = pDevExt->pTracerOps->pfnProviderRegister(pDevExt->pTracerOps, &pProv->Core);
c89333d3e41e439ed9e74768000edc399d3e72e6vboxsync SUPR0Printf("SUPR0TracerRegisterImpl: Failed to register provider %s::%s - rc=%d\n",
c89333d3e41e439ed9e74768000edc399d3e72e6vboxsync * Common tracer implementation deregistration code.
c89333d3e41e439ed9e74768000edc399d3e72e6vboxsync * The caller sets fTracerUnloading prior to calling this function.
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync * @param pDevExt The device extension structure.
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsyncstatic void supdrvTracerCommonDeregisterImpl(PSUPDRVDEVEXT pDevExt)
ffb50166c9adb4ae583b914d405197035cf890advboxsync * Reinstall the stub probe-fire function.
5050fc8de0b121eab1b738d7c1007cde4903284dvboxsync g_pfnSupdrvProbeFireKernel = supdrvTracerProbeFireStub;
462e60a19d02a99b2b1a5c08dff74bb0808d707cvboxsync * Disassociate the tracer implementation from all providers.
462e60a19d02a99b2b1a5c08dff74bb0808d707cvboxsync * We will have to wait on busy providers.
5050fc8de0b121eab1b738d7c1007cde4903284dvboxsync for (i = 0; ; i++)
462e60a19d02a99b2b1a5c08dff74bb0808d707cvboxsync /* Live providers. */
5050fc8de0b121eab1b738d7c1007cde4903284dvboxsync RTListForEachSafe(&pDevExt->TracerProviderList, pProv, pProvNext, SUPDRVTPPROVIDER, ListEntry)
ffb50166c9adb4ae583b914d405197035cf890advboxsync LOG_TRACER(("supdrvTracerCommonDeregisterImpl: Attemting to unregister '%s' / %p...\n",
ffb50166c9adb4ae583b914d405197035cf890advboxsync pProv->szName, pProv->Core.TracerData.DTrace.idProvider));
3c6306a66deef467e3c13483dd6529e1e1c6b822vboxsync rc = pDevExt->pTracerOps->pfnProviderDeregister(pDevExt->pTracerOps, &pProv->Core);
c89333d3e41e439ed9e74768000edc399d3e72e6vboxsync rc = pDevExt->pTracerOps->pfnProviderDeregisterZombie(pDevExt->pTracerOps, &pProv->Core);
c89333d3e41e439ed9e74768000edc399d3e72e6vboxsync if (!(i & 0xf))
c89333d3e41e439ed9e74768000edc399d3e72e6vboxsync SUPR0Printf("supdrvTracerCommonDeregisterImpl: Waiting on busy provider '%s' / %p (rc=%d)\n",
c89333d3e41e439ed9e74768000edc399d3e72e6vboxsync pProv->szName, pProv->Core.TracerData.DTrace.idProvider, rc);
c89333d3e41e439ed9e74768000edc399d3e72e6vboxsync LOG_TRACER(("supdrvTracerCommonDeregisterImpl: Failed to unregister provider '%s' / %p - rc=%d\n",
c89333d3e41e439ed9e74768000edc399d3e72e6vboxsync pProv->szName, pProv->Core.TracerData.DTrace.idProvider, rc));
c89333d3e41e439ed9e74768000edc399d3e72e6vboxsync /* Zombies providers. */
c89333d3e41e439ed9e74768000edc399d3e72e6vboxsync RTListForEachSafe(&pDevExt->TracerProviderZombieList, pProv, pProvNext, SUPDRVTPPROVIDER, ListEntry)
c89333d3e41e439ed9e74768000edc399d3e72e6vboxsync LOG_TRACER(("supdrvTracerCommonDeregisterImpl: Attemting to unregister '%s' / %p (zombie)...\n",
c89333d3e41e439ed9e74768000edc399d3e72e6vboxsync pProv->szName, pProv->Core.TracerData.DTrace.idProvider));
c89333d3e41e439ed9e74768000edc399d3e72e6vboxsync rc = pDevExt->pTracerOps->pfnProviderDeregisterZombie(pDevExt->pTracerOps, &pProv->Core);
c89333d3e41e439ed9e74768000edc399d3e72e6vboxsync if (!(i & 0xf))
c89333d3e41e439ed9e74768000edc399d3e72e6vboxsync SUPR0Printf("supdrvTracerCommonDeregisterImpl: Waiting on busy provider '%s' / %p (rc=%d)\n",
0dd3967035b8a02985920baa57f948dc542b9388vboxsync pProv->szName, pProv->Core.TracerData.DTrace.idProvider, rc);
c89333d3e41e439ed9e74768000edc399d3e72e6vboxsync LOG_TRACER(("supdrvTracerCommonDeregisterImpl: Failed to unregister provider '%s' / %p - rc=%d\n",
c89333d3e41e439ed9e74768000edc399d3e72e6vboxsync pProv->szName, pProv->Core.TracerData.DTrace.idProvider, rc));
c89333d3e41e439ed9e74768000edc399d3e72e6vboxsync /* Tracer opens. */
c89333d3e41e439ed9e74768000edc399d3e72e6vboxsync if (!(i & 0xf))
ffb50166c9adb4ae583b914d405197035cf890advboxsync SUPR0Printf("supdrvTracerCommonDeregisterImpl: Waiting on %u opens\n", pDevExt->cTracerOpens);
c89333d3e41e439ed9e74768000edc399d3e72e6vboxsync LOG_TRACER(("supdrvTracerCommonDeregisterImpl: Waiting on %u opens\n", pDevExt->cTracerOpens));
c89333d3e41e439ed9e74768000edc399d3e72e6vboxsync /* Tracer calls. */
b4d7b4dbcc45b8bde7502aa129440d92d7ffd038vboxsync if (!(i & 0xf))
b4d7b4dbcc45b8bde7502aa129440d92d7ffd038vboxsync SUPR0Printf("supdrvTracerCommonDeregisterImpl: Waiting on %u callers\n", pDevExt->cTracerCallers);
ffb50166c9adb4ae583b914d405197035cf890advboxsync LOG_TRACER(("supdrvTracerCommonDeregisterImpl: Waiting on %u callers\n", pDevExt->cTracerCallers));
ffb50166c9adb4ae583b914d405197035cf890advboxsync /* Done? */
ffb50166c9adb4ae583b914d405197035cf890advboxsync /* Delay...*/
ffb50166c9adb4ae583b914d405197035cf890advboxsync * Deregister the tracer implementation.
ffb50166c9adb4ae583b914d405197035cf890advboxsync * Deregister a tracer implementation.
ffb50166c9adb4ae583b914d405197035cf890advboxsync * This should be called from the ModuleTerm code or from a ring-0 session.
ffb50166c9adb4ae583b914d405197035cf890advboxsync * @returns VBox status code.
750df3fe104e01cadbc3d5bd20243055d283d4e5vboxsync * @param hMod The module handle.
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync * @param pSession Ring-0 session handle.
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsyncSUPR0DECL(int) SUPR0TracerDeregisterImpl(void *hMod, PSUPDRVSESSION pSession)
ffb50166c9adb4ae583b914d405197035cf890advboxsync * Validate input and context.
c89333d3e41e439ed9e74768000edc399d3e72e6vboxsync AssertReturn(pSession == NULL, VERR_INVALID_PARAMETER);
c89333d3e41e439ed9e74768000edc399d3e72e6vboxsync AssertReturn(SUP_IS_SESSION_VALID(pSession), VERR_INVALID_PARAMETER);
c89333d3e41e439ed9e74768000edc399d3e72e6vboxsync AssertReturn(pSession->R0Process == NIL_RTR0PROCESS, VERR_INVALID_PARAMETER);
c89333d3e41e439ed9e74768000edc399d3e72e6vboxsync * Do the job.
750df3fe104e01cadbc3d5bd20243055d283d4e5vboxsync LOG_TRACER(("SUPR0TracerDeregisterImpl: Unloading ...\n"));
c89333d3e41e439ed9e74768000edc399d3e72e6vboxsync LOG_TRACER(("SUPR0TracerDeregisterImpl: ... done.\n"));
750df3fe104e01cadbc3d5bd20243055d283d4e5vboxsync * The probe function is a bit more fun since we need tail jump optimizating.
750df3fe104e01cadbc3d5bd20243055d283d4e5vboxsync * Since we cannot ship yasm sources for linux and freebsd, owing to the cursed
c89333d3e41e439ed9e74768000edc399d3e72e6vboxsync * rebuilding of the kernel module from scratch at install time, we have to
ffb50166c9adb4ae583b914d405197035cf890advboxsync * deploy some ugly gcc inline assembly here.
750df3fe104e01cadbc3d5bd20243055d283d4e5vboxsync#if defined(__GNUC__) && (defined(RT_OS_FREEBSD) || defined(RT_OS_LINUX))
ffb50166c9adb4ae583b914d405197035cf890advboxsync .section .text \n\
ffb50166c9adb4ae583b914d405197035cf890advboxsync .p2align 2,,3 \n\
ffb50166c9adb4ae583b914d405197035cf890advboxsync .global SUPR0TracerFireProbe \n\
ffb50166c9adb4ae583b914d405197035cf890advboxsyncSUPR0TracerFireProbe: \n\
750df3fe104e01cadbc3d5bd20243055d283d4e5vboxsync movq g_pfnSupdrvProbeFireKernel(%rip), %rax \n\
750df3fe104e01cadbc3d5bd20243055d283d4e5vboxsync jmp *%rax \n\
ffb50166c9adb4ae583b914d405197035cf890advboxsync movl g_pfnSupdrvProbeFireKernel, %eax \n\
6475559a7e0e52892efbab4fbdedc879f6866109vboxsync jmp *%eax \n\
6475559a7e0e52892efbab4fbdedc879f6866109vboxsync .type supdrvTracerProbeFireStub,@function \n\
6475559a7e0e52892efbab4fbdedc879f6866109vboxsync .global supdrvTracerProbeFireStub \n\
6475559a7e0e52892efbab4fbdedc879f6866109vboxsyncsupdrvTracerProbeFireStub: \n\
6475559a7e0e52892efbab4fbdedc879f6866109vboxsync .previous \n\
6475559a7e0e52892efbab4fbdedc879f6866109vboxsync# if 0 /* Slickedit on windows highlighting fix */
462e60a19d02a99b2b1a5c08dff74bb0808d707cvboxsync * Module unloading hook, called after execution in the module have ceased.
ffb50166c9adb4ae583b914d405197035cf890advboxsync * @param pDevExt The device extension structure.
6475559a7e0e52892efbab4fbdedc879f6866109vboxsync * @param pImage The image being unloaded.
462e60a19d02a99b2b1a5c08dff74bb0808d707cvboxsyncvoid VBOXCALL supdrvTracerModuleUnloading(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage)
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync * If it is the tracer image, we have to unload all the providers.
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync LOG_TRACER(("supdrvTracerModuleUnloading: Unloading tracer ...\n"));
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync LOG_TRACER(("supdrvTracerModuleUnloading: ... done.\n"));
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync * Unregister all providers belonging to this image.
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync RTListForEachSafe(&pDevExt->TracerProviderList, pProv, pProvNext, SUPDRVTPPROVIDER, ListEntry)
553a2f0d8ef91a6dad8de4eef206ff093af53a5dvboxsync * Try unregister zombies while we have a chance.
if (!cRefs)
static PSUPDRVVTGCOPY supdrvVtgFindObjectCopyLocked(PRTLISTANCHOR pHashList, PCVTGOBJHDR pHdr, uint32_t cbStrTab, uint32_t fFlags)
return pCur;
return NULL;
static PSUPDRVVTGCOPY supdrvVtgFindObjectCopy(PSUPDRVDEVEXT pDevExt, PCVTGOBJHDR pHdr, uint32_t cbStrTab, uint32_t fFlags)
PRTLISTANCHOR pHashList = &pDevExt->aTrackerUmodHash[pHdr->Uuid.au8[3] % RT_ELEMENTS(pDevExt->aTrackerUmodHash)];
return pRet;
static int supdrvVtgCreateObjectCopy(PSUPDRVDEVEXT pDevExt, PCVTGOBJHDR pVtgHdr, RTR3PTR R3PtrVtgHdr, RTUINTPTR uVtgHdrAddr,
int rc;
size_t const cProbeLocs = pVtgHdr->cbProbeLocs / (pVtgHdr->cBits == 32 ? sizeof(VTGPROBELOC32) : sizeof(VTGPROBELOC64));
if (!pThis)
return VERR_NO_MEMORY;
uint32_t i;
for (i = 0; i < cProbeLocs; i++)
for (i = 0; i < cProbeLocs; i++)
rc = supdrvVtgValidate(&pThis->Hdr, (uintptr_t)&pThis->Hdr, (uint8_t *)&pThis->Hdr, cb, false /*fUmod*/);
return rc;
return rc;
static void supdrvTracerUmodClearProbeIds(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, PSUPDRVTRACERUMOD pUmod)
uint32_t i;
static int supdrvTracerUmodSetProbeIds(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, PSUPDRVTRACERUMOD pUmod)
uint32_t i;
return VINF_SUCCESS;
int rc;
return VERR_INVALID_CONTEXT;
return VERR_INVALID_PARAMETER;
return rc;
return rc;
if (!pUmod)
return VERR_NO_MEMORY;
rc = RTR0MemObjLockUser(&pUmod->hMemObjLock, R3PtrLock, cbLock, RTMEM_PROT_READ | RTMEM_PROT_WRITE, NIL_RTR0PROCESS);
rc = RTR0MemObjMapKernel(&pUmod->hMemObjMap, pUmod->hMemObjLock, (void *)-1, 0, RTMEM_PROT_READ | RTMEM_PROT_WRITE);
rc = supdrvVtgCreateObjectCopy(pDevExt, &Hdr, R3PtrVtgHdr, uVtgHdrAddr, R3PtrStrTab, cbStrTab, fFlags, pUmod);
return VINF_SUCCESS;
return rc;
int VBOXCALL supdrvIOCtl_TracerUmodDeregister(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, RTR3PTR R3PtrVtgHdr)
uint32_t i;
int rc;
if ( pUmod
if (pUmod)
return rc;
static void supdrvTracerUmodProbeFire(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, PSUPDRVTRACERUSRCTX pCtx)
== R3PtrProbeLoc))
&& pVtgCopy))
pDevExt->pTracerOps->pfnProbeFireUser(pDevExt->pTracerOps, pSession, pCtx, &pVtgCopy->Hdr, pProbeLocRO);
void VBOXCALL supdrvIOCtl_TracerUmodProbeFire(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, PSUPDRVTRACERUSRCTX pCtx)
int VBOXCALL supdrvIOCtl_TracerOpen(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, uint32_t uCookie, uintptr_t uArg)
int rc;
rc = pDevExt->pTracerOps->pfnTracerOpen(pDevExt->pTracerOps, pSession, uCookie, uArg, &pSession->uTracerData);
return rc;
int rc;
return rc;
int VBOXCALL supdrvIOCtl_TracerIOCtl(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, uintptr_t uCmd, uintptr_t uArg, int32_t *piRetVal)
int rc;
*piRetVal = 0;
rc = pDevExt->pTracerOps->pfnTracerIoCtl(pDevExt->pTracerOps, pSession, uTracerData, uCmd, uArg, piRetVal);
return rc;
uint32_t i;
#ifdef VBOX_WITH_NATIVE_DTRACE
#ifdef VBOX_WITH_DTRACE_R0DRV
rc = supdrvTracerRegisterVtgObj(pDevExt, &g_VTGObjHeader, NULL /*pImage*/, NULL /*pSession*/, NULL /*pUmod*/, "vboxdrv");
return rc;
return VINF_SUCCESS;
return rc;