Index: /trunk/src/VBox/HostDrivers/Support/SUPDrv.cpp
===================================================================
--- /trunk/src/VBox/HostDrivers/Support/SUPDrv.cpp	(revision 75281)
+++ /trunk/src/VBox/HostDrivers/Support/SUPDrv.cpp	(revision 75282)
@@ -138,5 +138,5 @@
 static int                  supdrvIOCtl_LdrFree(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, PSUPLDRFREE pReq);
 static int                  supdrvIOCtl_LdrLockDown(PSUPDRVDEVEXT pDevExt);
-static int                  supdrvIOCtl_LdrGetSymbol(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, PSUPLDRGETSYMBOL pReq);
+static int                  supdrvIOCtl_LdrQuerySymbol(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, PSUPLDRGETSYMBOL pReq);
 static int                  supdrvIDC_LdrGetSymbol(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, PSUPDRVIDCREQGETSYM pReq);
 static int                  supdrvLdrSetVMMR0EPs(PSUPDRVDEVEXT pDevExt, void *pvVMMR0, void *pvVMMR0EntryFast, void *pvVMMR0EntryEx);
@@ -1803,5 +1803,5 @@
 
             /* execute */
-            pReq->Hdr.rc = supdrvIOCtl_LdrGetSymbol(pDevExt, pSession, pReq);
+            pReq->Hdr.rc = supdrvIOCtl_LdrQuerySymbol(pDevExt, pSession, pReq);
             return 0;
         }
@@ -5152,28 +5152,31 @@
 
     /*
-     * Allocate and copy the tables.
+     * Allocate and copy the tables if non-native.
      * (No need to do try/except as this is a buffered request.)
      */
-    pImage->cbStrTab = pReq->u.In.cbStrTab;
-    if (pImage->cbStrTab)
-    {
-        pImage->pachStrTab = (char *)RTMemAlloc(pImage->cbStrTab);
-        if (pImage->pachStrTab)
-            memcpy(pImage->pachStrTab, &pReq->u.In.abImage[pReq->u.In.offStrTab], pImage->cbStrTab);
-        else
-            rc = supdrvLdrLoadError(VERR_NO_MEMORY, pReq, "Out of memory for string table: %#x", pImage->cbStrTab);
-        SUPDRV_CHECK_SMAP_CHECK(pDevExt, RT_NOTHING);
-    }
-
-    pImage->cSymbols = pReq->u.In.cSymbols;
-    if (RT_SUCCESS(rc) && pImage->cSymbols)
-    {
-        size_t  cbSymbols = pImage->cSymbols * sizeof(SUPLDRSYM);
-        pImage->paSymbols = (PSUPLDRSYM)RTMemAlloc(cbSymbols);
-        if (pImage->paSymbols)
-            memcpy(pImage->paSymbols, &pReq->u.In.abImage[pReq->u.In.offSymbols], cbSymbols);
-        else
-            rc = supdrvLdrLoadError(VERR_NO_MEMORY, pReq, "Out of memory for symbol table: %#x", cbSymbols);
-        SUPDRV_CHECK_SMAP_CHECK(pDevExt, RT_NOTHING);
+    if (pImage->fNative)
+    {
+        pImage->cbStrTab = pReq->u.In.cbStrTab;
+        if (pImage->cbStrTab)
+        {
+            pImage->pachStrTab = (char *)RTMemAlloc(pImage->cbStrTab);
+            if (pImage->pachStrTab)
+                memcpy(pImage->pachStrTab, &pReq->u.In.abImage[pReq->u.In.offStrTab], pImage->cbStrTab);
+            else
+                rc = supdrvLdrLoadError(VERR_NO_MEMORY, pReq, "Out of memory for string table: %#x", pImage->cbStrTab);
+            SUPDRV_CHECK_SMAP_CHECK(pDevExt, RT_NOTHING);
+        }
+
+        pImage->cSymbols = pReq->u.In.cSymbols;
+        if (RT_SUCCESS(rc) && pImage->cSymbols)
+        {
+            size_t  cbSymbols = pImage->cSymbols * sizeof(SUPLDRSYM);
+            pImage->paSymbols = (PSUPLDRSYM)RTMemAlloc(cbSymbols);
+            if (pImage->paSymbols)
+                memcpy(pImage->paSymbols, &pReq->u.In.abImage[pReq->u.In.offSymbols], cbSymbols);
+            else
+                rc = supdrvLdrLoadError(VERR_NO_MEMORY, pReq, "Out of memory for symbol table: %#x", cbSymbols);
+            SUPDRV_CHECK_SMAP_CHECK(pDevExt, RT_NOTHING);
+        }
     }
 
@@ -5401,5 +5404,5 @@
 
 /**
- * Gets the address of a symbol in an open image.
+ * Queries the address of a symbol in an open image.
  *
  * @returns IPRT status code.
@@ -5408,5 +5411,5 @@
  * @param   pReq        The request buffer.
  */
-static int supdrvIOCtl_LdrGetSymbol(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, PSUPLDRGETSYMBOL pReq)
+static int supdrvIOCtl_LdrQuerySymbol(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, PSUPLDRGETSYMBOL pReq)
 {
     PSUPDRVLDRIMAGE pImage;
@@ -5418,5 +5421,5 @@
     void           *pvSymbol = NULL;
     int             rc = VERR_SYMBOL_NOT_FOUND;
-    Log3(("supdrvIOCtl_LdrGetSymbol: pvImageBase=%p szSymbol=\"%s\"\n", pReq->u.In.pvImageBase, pReq->u.In.szSymbol));
+    Log3(("supdrvIOCtl_LdrQuerySymbol: pvImageBase=%p szSymbol=\"%s\"\n", pReq->u.In.pvImageBase, pReq->u.In.szSymbol));
 
     /*
@@ -5443,19 +5446,24 @@
 
     /*
-     * Search the symbol strings.
+     * Search the image exports / symbol strings.
      *
      * Note! The int32_t is for native loading on solaris where the data
      *       and text segments are in very different places.
      */
-    pchStrings = pImage->pachStrTab;
-    paSyms     = pImage->paSymbols;
-    for (i = 0; i < pImage->cSymbols; i++)
-    {
-        if (    paSyms[i].offName + cbSymbol <= pImage->cbStrTab
-            &&  !memcmp(pchStrings + paSyms[i].offName, pReq->u.In.szSymbol, cbSymbol))
-        {
-            pvSymbol = (uint8_t *)pImage->pvImage + (int32_t)paSyms[i].offSymbol;
-            rc = VINF_SUCCESS;
-            break;
+    if (pImage->fNative)
+        rc = supdrvOSLdrQuerySymbol(pDevExt, pImage, pReq->u.In.szSymbol, cbSymbol - 1, &pvSymbol);
+    else
+    {
+        pchStrings = pImage->pachStrTab;
+        paSyms     = pImage->paSymbols;
+        for (i = 0; i < pImage->cSymbols; i++)
+        {
+            if (    paSyms[i].offName + cbSymbol <= pImage->cbStrTab
+                &&  !memcmp(pchStrings + paSyms[i].offName, pReq->u.In.szSymbol, cbSymbol))
+            {
+                pvSymbol = (uint8_t *)pImage->pvImage + (int32_t)paSyms[i].offSymbol;
+                rc = VINF_SUCCESS;
+                break;
+            }
         }
     }
@@ -5529,19 +5537,29 @@
         {
             /*
-             * Search the symbol strings.
+             * Search the image exports / symbol strings.
              */
-            const char *pchStrings = pImage->pachStrTab;
-            PCSUPLDRSYM paSyms     = pImage->paSymbols;
-            for (i = 0; i < pImage->cSymbols; i++)
-            {
-                if (    paSyms[i].offName + cbSymbol <= pImage->cbStrTab
-                    &&  !memcmp(pchStrings + paSyms[i].offName, pszSymbol, cbSymbol))
+            if (pImage->fNative)
+            {
+                rc = supdrvOSLdrQuerySymbol(pDevExt, pImage, pszSymbol, cbSymbol - 1, (void **)&pReq->u.Out.pfnSymbol);
+                if (RT_SUCCESS(rc))
+                    rc = supdrvLdrAddUsage(pSession, pImage);
+            }
+            else
+            {
+                const char *pchStrings = pImage->pachStrTab;
+                PCSUPLDRSYM paSyms     = pImage->paSymbols;
+                rc = VERR_SYMBOL_NOT_FOUND;
+                for (i = 0; i < pImage->cSymbols; i++)
                 {
-                    /*
-                     * Found it! Calc the symbol address and add a reference to the module.
-                     */
-                    pReq->u.Out.pfnSymbol = (PFNRT)((uintptr_t)pImage->pvImage + (int32_t)paSyms[i].offSymbol);
-                    rc = supdrvLdrAddUsage(pSession, pImage);
-                    break;
+                    if (    paSyms[i].offName + cbSymbol <= pImage->cbStrTab
+                        &&  !memcmp(pchStrings + paSyms[i].offName, pszSymbol, cbSymbol))
+                    {
+                        /*
+                         * Found it! Calc the symbol address and add a reference to the module.
+                         */
+                        pReq->u.Out.pfnSymbol = (PFNRT)((uintptr_t)pImage->pvImage + (int32_t)paSyms[i].offSymbol);
+                        rc = supdrvLdrAddUsage(pSession, pImage);
+                        break;
+                    }
                 }
             }
Index: /trunk/src/VBox/HostDrivers/Support/SUPDrvInternal.h
===================================================================
--- /trunk/src/VBox/HostDrivers/Support/SUPDrvInternal.h	(revision 75281)
+++ /trunk/src/VBox/HostDrivers/Support/SUPDrvInternal.h	(revision 75282)
@@ -946,5 +946,4 @@
 int  VBOXCALL   supdrvOSLdrLoad(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage, const uint8_t *pbImageBits, PSUPLDRLOAD pReq);
 
-
 /**
  * Unload the image (only called if supdrvOSLdrOpen returned success).
@@ -965,4 +964,17 @@
  */
 void VBOXCALL   supdrvOSLdrNotifyUnloaded(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage);
+
+/**
+ * Queries a symbol address is a native module.
+ *
+ * @returns IPRT status code.
+ * @param   pDevExt             The device globals.
+ * @param   pImage              The image to search.
+ * @param   pszSymbol           The symbol to search for.
+ * @param   cchSymbol           The length of the symbol.
+ * @param   ppvSymbol           Where to return the symbol address if found.
+ */
+int  VBOXCALL   supdrvOSLdrQuerySymbol(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage,
+                                       const char *pszSymbol, size_t cchSymbol, void **ppvSymbol);
 
 
Index: /trunk/src/VBox/HostDrivers/Support/darwin/SUPDrv-darwin.cpp
===================================================================
--- /trunk/src/VBox/HostDrivers/Support/darwin/SUPDrv-darwin.cpp	(revision 75281)
+++ /trunk/src/VBox/HostDrivers/Support/darwin/SUPDrv-darwin.cpp	(revision 75282)
@@ -1537,4 +1537,28 @@
 
 
+int  VBOXCALL   supdrvOSLdrQuerySymbol(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage,
+                                       const char *pszSymbol, size_t cchSymbol, void **ppvSymbol)
+{
+#ifdef VBOX_WITH_DARWIN_R0_DARWIN_IMAGE_VERIFICATION
+    /*
+     * Just hand the problem to RTLdrGetSymbolEx.
+     */
+    RTLDRADDR uValueFound;
+    int rc = RTLdrGetSymbolEx(pImage->hLdrMod, pImage->pvImage, (uintptr_t)pImage->pvImage, UINT32_MAX, pszSymbol, &uValueFound);
+    if (RT_SUCCESS(rc))
+    {
+        *ppvSymbol = (void *)(uintptr_t)uValueFound;
+        return VINF_SUCCESS;
+    }
+    RT_NOREF(pDevExt, cchSymbol);
+    return rc;
+
+#else
+    RT_NOREF(pDevExt, pImage, pszSymbol, cchSymbol, ppvSymbol);
+    return VERR_WRONG_ORDER;
+#endif
+}
+
+
 int  VBOXCALL   supdrvOSLdrLoad(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage, const uint8_t *pbImageBits, PSUPLDRLOAD pReq)
 {
Index: /trunk/src/VBox/HostDrivers/Support/freebsd/SUPDrv-freebsd.c
===================================================================
--- /trunk/src/VBox/HostDrivers/Support/freebsd/SUPDrv-freebsd.c	(revision 75281)
+++ /trunk/src/VBox/HostDrivers/Support/freebsd/SUPDrv-freebsd.c	(revision 75282)
@@ -592,4 +592,12 @@
 
 
+int  VBOXCALL   supdrvOSLdrQuerySymbol(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage,
+                                       const char *pszSymbol, size_t cchSymbol, void **ppvSymbol)
+{
+    RT_NOREF(pDevExt, pImage, pszSymbol, cchSymbol, ppvSymbol);
+    return VERR_WRONG_ORDER;
+}
+
+
 #ifdef SUPDRV_WITH_MSR_PROBER
 
Index: /trunk/src/VBox/HostDrivers/Support/linux/SUPDrv-linux.c
===================================================================
--- /trunk/src/VBox/HostDrivers/Support/linux/SUPDrv-linux.c	(revision 75281)
+++ /trunk/src/VBox/HostDrivers/Support/linux/SUPDrv-linux.c	(revision 75282)
@@ -1218,4 +1218,15 @@
 
 
+int  VBOXCALL   supdrvOSLdrQuerySymbol(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage,
+                                       const char *pszSymbol, size_t cchSymbol, void **ppvSymbol)
+{
+#ifdef VBOX_WITH_NON_PROD_HACK_FOR_PERF_STACKS
+# error "implement me!"
+#endif
+    RT_NOREF(pDevExt, pImage, pszSymbol, cchSymbol, ppvSymbol);
+    return VERR_WRONG_ORDER;
+}
+
+
 #ifdef SUPDRV_WITH_MSR_PROBER
 
Index: /trunk/src/VBox/HostDrivers/Support/os2/SUPDrv-os2.cpp
===================================================================
--- /trunk/src/VBox/HostDrivers/Support/os2/SUPDrv-os2.cpp	(revision 75281)
+++ /trunk/src/VBox/HostDrivers/Support/os2/SUPDrv-os2.cpp	(revision 75282)
@@ -465,4 +465,12 @@
 
 
+int  VBOXCALL   supdrvOSLdrQuerySymbol(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage,
+                                       const char *pszSymbol, size_t cchSymbol, void **ppvSymbol)
+{
+    RT_NOREF(pDevExt, pImage, pszSymbol, cchSymbol, ppvSymbol);
+    return VERR_WRONG_ORDER;
+}
+
+
 #ifdef SUPDRV_WITH_MSR_PROBER
 
Index: /trunk/src/VBox/HostDrivers/Support/solaris/SUPDrv-solaris.c
===================================================================
--- /trunk/src/VBox/HostDrivers/Support/solaris/SUPDrv-solaris.c	(revision 75281)
+++ /trunk/src/VBox/HostDrivers/Support/solaris/SUPDrv-solaris.c	(revision 75282)
@@ -1241,4 +1241,12 @@
 
 
+int  VBOXCALL   supdrvOSLdrQuerySymbol(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage,
+                                       const char *pszSymbol, size_t cchSymbol, void **ppvSymbol)
+{
+    RT_NOREF(pDevExt, pImage, pszSymbol, cchSymbol, ppvSymbol);
+    return VERR_WRONG_ORDER;
+}
+
+
 #ifdef SUPDRV_WITH_MSR_PROBER
 
Index: /trunk/src/VBox/HostDrivers/Support/win/SUPDrv-win.cpp
===================================================================
--- /trunk/src/VBox/HostDrivers/Support/win/SUPDrv-win.cpp	(revision 75281)
+++ /trunk/src/VBox/HostDrivers/Support/win/SUPDrv-win.cpp	(revision 75282)
@@ -2083,4 +2083,5 @@
 }
 
+
 void VBOXCALL   supdrvOSLdrNotifyUnloaded(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage)
 {
@@ -2088,13 +2089,15 @@
 }
 
-/*
- * Note! Similar code in rtR0DbgKrnlNtParseModule.
- */
-int  VBOXCALL   supdrvOSLdrValidatePointer(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage, void *pv,
-                                           const uint8_t *pbImageBits, const char *pszSymbol)
-{
-#if 1
-    RT_NOREF(pDevExt, pbImageBits);
+
+/**
+ * Common worker for supdrvOSLdrQuerySymbol and supdrvOSLdrValidatePointer.
+ *
+ * @note    Similar code in rtR0DbgKrnlNtParseModule.
+ */
+static int supdrvOSLdrValidatePointerOrQuerySymbol(PSUPDRVLDRIMAGE pImage, void *pv, const char *pszSymbol,
+                                                   size_t cchSymbol, void **ppvSymbol)
+{
     AssertReturn(pImage->pvNtSectionObj, VERR_INVALID_STATE);
+    Assert(pszSymbol || !ppvSymbol);
 
     /*
@@ -2104,5 +2107,5 @@
     uint32_t const  cbMapping      = pImage->cbImageBits;
     uint32_t const  uRvaToValidate = (uint32_t)((uintptr_t)pv - (uintptr_t)pbMapping);
-    AssertReturn(uRvaToValidate < cbMapping, VERR_INTERNAL_ERROR_3);
+    AssertReturn(uRvaToValidate < cbMapping || ppvSymbol, VERR_INTERNAL_ERROR_3);
 
     uint32_t const  offNtHdrs = *(uint16_t *)pbMapping == IMAGE_DOS_SIGNATURE
@@ -2128,5 +2131,5 @@
     {
         SUPR0Printf("SUPDrv: No exports in %s!\n", pImage->szName);
-        return VERR_NOT_FOUND;
+        return ppvSymbol ? VERR_SYMBOL_NOT_FOUND : VERR_NOT_FOUND;
     }
     AssertReturn(   ExpDir.Size >= sizeof(IMAGE_EXPORT_DIRECTORY)
@@ -2143,5 +2146,5 @@
     {
         SUPR0Printf("SUPDrv: No exports in %s!\n", pImage->szName);
-        return VERR_NOT_FOUND;
+        return ppvSymbol ? VERR_SYMBOL_NOT_FOUND : VERR_NOT_FOUND;
     }
 
@@ -2170,22 +2173,25 @@
      */
     uint32_t iExportOrdinal = UINT32_MAX;
-    for (uint32_t i = 0; i < cExports; i++)
-        if (paoffExports[i] == uRvaToValidate)
-        {
-            iExportOrdinal = i;
-            break;
-        }
-    if (iExportOrdinal == UINT32_MAX)
-    {
-        SUPR0Printf("SUPDrv: No export with rva %#x (%s) in %s!\n", uRvaToValidate, pszSymbol, pImage->szName);
-        return VERR_NOT_FOUND;
-    }
-
-    /*
-     * Can we validate the symbol name too?  If so, just do a linear search.
-     */
-    if (pszSymbol && RT_C_IS_UPPER(*pszSymbol))
-    {
-        size_t const cchSymbol  = strlen(pszSymbol);
+    if (!ppvSymbol)
+    {
+        for (uint32_t i = 0; i < cExports; i++)
+            if (paoffExports[i] == uRvaToValidate)
+            {
+                iExportOrdinal = i;
+                break;
+            }
+        if (iExportOrdinal == UINT32_MAX)
+        {
+            SUPR0Printf("SUPDrv: No export with rva %#x (%s) in %s!\n", uRvaToValidate, pszSymbol, pImage->szName);
+            return VERR_NOT_FOUND;
+        }
+    }
+
+    /*
+     * Can we validate the symbol name too or should we find a name?
+     * If so, just do a linear search.
+     */
+    if (pszSymbol && (RT_C_IS_UPPER(*pszSymbol) || ppvSymbol))
+    {
         for (uint32_t i = 0; i < cNamedExports; i++)
         {
@@ -2193,5 +2199,5 @@
             AssertReturn(offName < cbMapping, VERR_BAD_EXE_FORMAT);
             uint32_t const     cchMaxName = cbMapping - offName;
-            const char * const pszName    = (const char *)&pbImageBits[offName];
+            const char * const pszName    = (const char *)&pbMapping[offName];
             const char * const pszEnd     = (const char *)memchr(pszName, '\0', cchMaxName);
             AssertReturn(pszEnd, VERR_BAD_EXE_FORMAT);
@@ -2200,20 +2206,45 @@
                 && memcmp(pszName, pszSymbol, cchSymbol) == 0)
             {
-                if (pau16NameOrdinals[i] == iExportOrdinal)
+                if (ppvSymbol)
+                {
+                    iExportOrdinal = pau16NameOrdinals[i];
+                    if (   iExportOrdinal < cExports
+                        && paoffExports[iExportOrdinal] < cbMapping)
+                    {
+                        *ppvSymbol = (void *)(paoffExports[iExportOrdinal] + pbMapping);
+                        return VINF_SUCCESS;
+                    }
+                }
+                else if (pau16NameOrdinals[i] == iExportOrdinal)
                     return VINF_SUCCESS;
-                SUPR0Printf("SUPDrv: Different exports found for %s and rva %#x in %s: %#x vs %#x\n",
-                            pszSymbol, uRvaToValidate, pImage->szName, pau16NameOrdinals[i], iExportOrdinal);
+                else
+                    SUPR0Printf("SUPDrv: Different exports found for %s and rva %#x in %s: %#x vs %#x\n",
+                                pszSymbol, uRvaToValidate, pImage->szName, pau16NameOrdinals[i], iExportOrdinal);
                 return VERR_LDR_BAD_FIXUP;
             }
         }
-        SUPR0Printf("SUPDrv: No export named %s (%#x) in %s!\n", pszSymbol, uRvaToValidate, pImage->szName);
+        if (!ppvSymbol)
+            SUPR0Printf("SUPDrv: No export named %s (%#x) in %s!\n", pszSymbol, uRvaToValidate, pImage->szName);
         return VERR_SYMBOL_NOT_FOUND;
     }
     return VINF_SUCCESS;
-
-#else
-    NOREF(pDevExt); NOREF(pImage); NOREF(pv); NOREF(pbImageBits); NOREF(pszSymbol);
-    return VERR_NOT_SUPPORTED;
-#endif
+}
+
+
+int  VBOXCALL   supdrvOSLdrValidatePointer(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage, void *pv,
+                                           const uint8_t *pbImageBits, const char *pszSymbol)
+{
+    RT_NOREF(pDevExt, pbImageBits);
+    return supdrvOSLdrValidatePointerOrQuerySymbol(pImage, pv, pszSymbol, pszSymbol ? strlen(pszSymbol) : 0, NULL);
+}
+
+
+int  VBOXCALL   supdrvOSLdrQuerySymbol(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage,
+                                       const char *pszSymbol, size_t cchSymbol, void **ppvSymbol)
+{
+    RT_NOREF(pDevExt);
+    AssertReturn(ppvSymbol, VERR_INVALID_PARAMETER);
+    AssertReturn(pszSymbol, VERR_INVALID_PARAMETER);
+    return supdrvOSLdrValidatePointerOrQuerySymbol(pImage, NULL, pszSymbol, cchSymbol, ppvSymbol);
 }
 
