Index: /trunk/include/iprt/darwin/machkernel.h
===================================================================
--- /trunk/include/iprt/darwin/machkernel.h	(revision 37573)
+++ /trunk/include/iprt/darwin/machkernel.h	(revision 37573)
@@ -0,0 +1,84 @@
+/* $Id$ */
+/** @file
+ * IPRT - mach_kernel symbol resolving hack, R0 Driver, Darwin.
+ */
+
+/*
+ * Copyright (C) 2011 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+ * VirtualBox OSE distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ */
+
+#ifndef ___iprt_darwin_machkernel_h
+#define ___iprt_darwin_machkernel_h
+
+#include <iprt/types.h>
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_rt_darwin_machkernel  Mach Kernel Symbols (Ring-0 only)
+ * @addtogroup grp_rt
+ * @{
+ */
+
+/** Handle to the mach kernel symbol database (darwin/r0 only). */
+typedef R3R0PTRTYPE(struct RTR0MACHKERNELINT *) RTR0MACHKERNEL;
+/** Pointer to a mach kernel symbol database handle. */
+typedef RTR0MACHKERNEL                         *PRTR0MACHKERNEL;
+/** Nil mach kernel symbol database handle. */
+#define NIL_RTR0MACHKERNEL                      ((RTR0MACHKERNEL)0)
+
+
+/**
+ * Opens symbol table of the mach_kernel.
+ *
+ * @returns IPRT status code.
+ * @param   pszMachKernel   The path to the mach_kernel image.
+ * @param   phKernel        Where to return a mach kernel symbol database
+ *                          handle on success.  Call RTR0MachKernelClose on it
+ *                          when done.
+ */
+RTDECL(int) RTR0MachKernelOpen(const char *pszMachKernel, PRTR0MACHKERNEL phKernel);
+
+/**
+ * Frees up the internal scratch data when done looking up symbols.
+ *
+ * @param   pThis               The internal scratch data.
+ */
+RTDECL(int) RTR0MachKernelClose(RTR0MACHKERNEL hKernel);
+
+/**
+ * Looks up a kernel symbol.
+ *
+ * @returns VINF_SUCCESS if found, *ppvValue set.
+ * @retval  VERR_SYMBOL_NOT_FOUND if not found.
+ * @retval  VERR_INVALID_HANDLE
+ * @retval  VERR_INVALID_POINTER
+ *
+ * @param   hKernel             The mach kernel handle.
+ * @param   pszSymbol           The name of the symbol to look up, omitting the
+ *                              leading underscore.
+ * @param   ppvValue            Where to store the symbol address (optional).
+ */
+RTDECL(int) RTR0MachKernelGetSymbol(RTR0MACHKERNEL hKernel, const char *pszSymbol, void **ppvValue);
+
+/** @} */
+RT_C_DECLS_END
+
+#endif
+
Index: /trunk/src/VBox/Runtime/r0drv/darwin/mach_kernel-r0drv-darwin.cpp
===================================================================
--- /trunk/src/VBox/Runtime/r0drv/darwin/mach_kernel-r0drv-darwin.cpp	(revision 37572)
+++ /trunk/src/VBox/Runtime/r0drv/darwin/mach_kernel-r0drv-darwin.cpp	(revision 37573)
@@ -38,5 +38,7 @@
 RT_C_DECLS_END
 #endif
-#include "../../include/internal/iprt.h"
+
+#include "internal/iprt.h"
+#include <iprt/darwin/machkernel.h>
 
 #ifdef IN_RING0  /* till RTFILE is changed in types.h */
@@ -57,5 +59,5 @@
 #include <iprt/mem.h>
 #include <iprt/string.h>
-#include "../../include/internal/ldrMach-O.h"
+#include "internal/ldrMach-O.h"
 
 /** @def MY_CPU_TYPE
@@ -122,5 +124,5 @@
  * and successfully resolving their addresses.
  */
-typedef struct RTR0DARWINKERNEL
+typedef struct RTR0MACHKERNELINT
 {
     /** @name Result.
@@ -162,6 +164,5 @@
     /** Buffer space. */
     char                abBuf[_4K];
-} RTR0DARWINKERNEL;
-typedef RTR0DARWINKERNEL *PRTR0DARWINKERNEL;
+} RTR0MACHKERNELINT;
 
 
@@ -170,5 +171,5 @@
 *******************************************************************************/
 #ifdef DEBUG
-static bool g_fBreakpointOnError = true;
+static bool g_fBreakpointOnError = false;
 #endif
 
@@ -315,33 +316,16 @@
 
 /**
- * Frees up the internal scratch data when done looking up symbols.
- *
- * @param   pKernel             The internal scratch data.
- */
-static void rtR0DarwinMachKernelClose(PRTR0DARWINKERNEL pKernel)
-{
-    RTMemFree(pKernel->pachStrTab);
-    pKernel->pachStrTab = NULL;
-
-    RTMemFree(pKernel->paSyms);
-    pKernel->paSyms = NULL;
-
-    RTMemFree(pKernel);
-}
-
-
-/**
  * Close and free up resources we no longer needs.
  *
- * @param   pKernel             The internal scratch data.
+ * @param   pThis               The internal scratch data.
  */
-static void rtR0DarwinMachKernelLoadDone(PRTR0DARWINKERNEL pKernel)
-{
-    RTFileClose(pKernel->hFile);
-    pKernel->hFile = NIL_RTFILE;
-
-    RTMemFree(pKernel->pLoadCmds);
-    pKernel->pLoadCmds = NULL;
-    memset((void *)&pKernel->apSections[0], 0, sizeof(pKernel->apSections[0]) * MACHO_MAX_SECT);
+static void rtR0MachKernelLoadDone(RTR0MACHKERNELINT *pThis)
+{
+    RTFileClose(pThis->hFile);
+    pThis->hFile = NIL_RTFILE;
+
+    RTMemFree(pThis->pLoadCmds);
+    pThis->pLoadCmds = NULL;
+    memset((void *)&pThis->apSections[0], 0, sizeof(pThis->apSections[0]) * MACHO_MAX_SECT);
 }
 
@@ -352,12 +336,12 @@
  *
  * @returns The symbol address on success, 0 on failure.
- * @param   pKernel             The internal scratch data.
+ * @param   pThis               The internal scratch data.
  * @param   pszSymbol           The symbol to resolve.  Automatically prefixed
  *                              with an underscore.
  */
-static uintptr_t rtR0DarwinMachKernelLookup(PRTR0DARWINKERNEL pKernel, const char *pszSymbol)
-{
-    uint32_t const  cSyms = pKernel->cSyms;
-    MY_NLIST const *pSym = pKernel->paSyms;
+static uintptr_t rtR0MachKernelLookup(RTR0MACHKERNELINT *pThis, const char *pszSymbol)
+{
+    uint32_t const  cSyms = pThis->cSyms;
+    MY_NLIST const *pSym = pThis->paSyms;
 
 #if 1
@@ -368,5 +352,5 @@
             continue;
 
-        const char *pszTabName= &pKernel->pachStrTab[(uint32_t)pSym->n_un.n_strx];
+        const char *pszTabName= &pThis->pachStrTab[(uint32_t)pSym->n_un.n_strx];
         if (   *pszTabName == '_'
             && strcmp(pszTabName + 1, pszSymbol) == 0)
@@ -398,7 +382,7 @@
  *
  * @returns IPRT status code.
- * @param   pKernel             The internal scratch data.
+ * @param   pThis               The internal scratch data.
  */
-static int rtR0DarwinMachKernelCheckStandardSymbols(PRTR0DARWINKERNEL pKernel)
+static int rtR0MachKernelCheckStandardSymbols(RTR0MACHKERNELINT *pThis)
 {
     static struct
@@ -516,5 +500,5 @@
     for (unsigned i = 0; i < RT_ELEMENTS(s_aStandardCandles); i++)
     {
-        uintptr_t uAddr = rtR0DarwinMachKernelLookup(pKernel, s_aStandardCandles[i].pszName);
+        uintptr_t uAddr = rtR0MachKernelLookup(pThis, s_aStandardCandles[i].pszName);
 #ifdef IN_RING0
         if (uAddr != s_aStandardCandles[i].uAddr)
@@ -535,26 +519,26 @@
  *
  * @returns IPRT status code.
- * @param   pKernel             The internal scratch data.
+ * @param   pThis               The internal scratch data.
  */
-static int rtR0DarwinMachKernelLoadSymTab(PRTR0DARWINKERNEL pKernel)
+static int rtR0MachKernelLoadSymTab(RTR0MACHKERNELINT *pThis)
 {
     /*
      * Load the tables.
      */
-    pKernel->paSyms = (MY_NLIST *)RTMemAllocZ(pKernel->cSyms * sizeof(MY_NLIST));
-    if (!pKernel->paSyms)
+    pThis->paSyms = (MY_NLIST *)RTMemAllocZ(pThis->cSyms * sizeof(MY_NLIST));
+    if (!pThis->paSyms)
         return VERR_NO_MEMORY;
 
-    int rc = RTFileReadAt(pKernel->hFile, pKernel->offArch + pKernel->offSyms,
-                          pKernel->paSyms, pKernel->cSyms * sizeof(MY_NLIST), NULL);
+    int rc = RTFileReadAt(pThis->hFile, pThis->offArch + pThis->offSyms,
+                          pThis->paSyms, pThis->cSyms * sizeof(MY_NLIST), NULL);
     if (RT_FAILURE(rc))
         return rc;
 
-    pKernel->pachStrTab = (char *)RTMemAllocZ(pKernel->cbStrTab + 1);
-    if (!pKernel->pachStrTab)
+    pThis->pachStrTab = (char *)RTMemAllocZ(pThis->cbStrTab + 1);
+    if (!pThis->pachStrTab)
         return VERR_NO_MEMORY;
 
-    rc = RTFileReadAt(pKernel->hFile, pKernel->offArch + pKernel->offStrTab,
-                      pKernel->pachStrTab, pKernel->cbStrTab, NULL);
+    rc = RTFileReadAt(pThis->hFile, pThis->offArch + pThis->offStrTab,
+                      pThis->pachStrTab, pThis->cbStrTab, NULL);
     if (RT_FAILURE(rc))
         return rc;
@@ -563,5 +547,5 @@
      * The first string table symbol must be a zero length name.
      */
-    if (pKernel->pachStrTab[0] != '\0')
+    if (pThis->pachStrTab[0] != '\0')
         RETURN_VERR_BAD_EXE_FORMAT;
 
@@ -570,11 +554,11 @@
      */
     const char     *pszPrev = "";
-    uint32_t const  cSyms   = pKernel->cSyms;
-    MY_NLIST const  *pSym   = pKernel->paSyms;
+    uint32_t const  cSyms   = pThis->cSyms;
+    MY_NLIST const  *pSym   = pThis->paSyms;
     for (uint32_t iSym = 0; iSym < cSyms; iSym++, pSym++)
     {
-        if ((uint32_t)pSym->n_un.n_strx >= pKernel->cbStrTab)
+        if ((uint32_t)pSym->n_un.n_strx >= pThis->cbStrTab)
             RETURN_VERR_BAD_EXE_FORMAT;
-        const char *pszSym = &pKernel->pachStrTab[(uint32_t)pSym->n_un.n_strx];
+        const char *pszSym = &pThis->pachStrTab[(uint32_t)pSym->n_un.n_strx];
 #ifdef IN_RING3
         RTAssertMsg2("%05i: %02x:%08x %02x %04x %s\n", iSym, pSym->n_sect, pSym->n_value, pSym->n_type, pSym->n_desc, pszSym);
@@ -591,12 +575,12 @@
                     if (pSym->n_sect == MACHO_NO_SECT)
                         RETURN_VERR_BAD_EXE_FORMAT;
-                    if (pSym->n_sect > pKernel->cSections)
+                    if (pSym->n_sect > pThis->cSections)
                         RETURN_VERR_BAD_EXE_FORMAT;
                     if (pSym->n_desc & ~(REFERENCED_DYNAMICALLY))
                         RETURN_VERR_BAD_EXE_FORMAT;
-                    if (pSym->n_value < pKernel->apSections[pSym->n_sect - 1]->addr)
-                        RETURN_VERR_BAD_EXE_FORMAT;
-                    if (   pSym->n_value - pKernel->apSections[pSym->n_sect - 1]->addr
-                        > pKernel->apSections[pSym->n_sect - 1]->size)
+                    if (pSym->n_value < pThis->apSections[pSym->n_sect - 1]->addr)
+                        RETURN_VERR_BAD_EXE_FORMAT;
+                    if (   pSym->n_value - pThis->apSections[pSym->n_sect - 1]->addr
+                        > pThis->apSections[pSym->n_sect - 1]->size)
                         RETURN_VERR_BAD_EXE_FORMAT;
                     break;
@@ -606,5 +590,5 @@
                     if (pSym->n_sect != MACHO_NO_SECT)
 #else
-                    if (pSym->n_sect > pKernel->cSections)
+                    if (pSym->n_sect > pThis->cSections)
 #endif
                         RETURN_VERR_BAD_EXE_FORMAT;
@@ -640,20 +624,20 @@
  *
  * @returns IPRT status code.
- * @param   pKernel             The internal scratch data.
+ * @param   pThis               The internal scratch data.
  */
-static int rtR0DarwinMachKernelLoadCommands(PRTR0DARWINKERNEL pKernel)
-{
-    pKernel->offStrTab = 0;
-    pKernel->cbStrTab  = 0;
-    pKernel->offSyms   = 0;
-    pKernel->cSyms     = 0;
-    pKernel->cSections = 0;
-
-    pKernel->pLoadCmds = (load_command_t *)RTMemAlloc(pKernel->cbLoadCmds);
-    if (!pKernel->pLoadCmds)
+static int rtR0MachKernelLoadCommands(RTR0MACHKERNELINT *pThis)
+{
+    pThis->offStrTab = 0;
+    pThis->cbStrTab  = 0;
+    pThis->offSyms   = 0;
+    pThis->cSyms     = 0;
+    pThis->cSections = 0;
+
+    pThis->pLoadCmds = (load_command_t *)RTMemAlloc(pThis->cbLoadCmds);
+    if (!pThis->pLoadCmds)
         return VERR_NO_MEMORY;
 
-    int rc = RTFileReadAt(pKernel->hFile, pKernel->offArch + sizeof(MY_MACHO_HEADER),
-                          pKernel->pLoadCmds, pKernel->cbLoadCmds, NULL);
+    int rc = RTFileReadAt(pThis->hFile, pThis->offArch + sizeof(MY_MACHO_HEADER),
+                          pThis->pLoadCmds, pThis->cbLoadCmds, NULL);
     if (RT_FAILURE(rc))
         return rc;
@@ -663,14 +647,14 @@
      * table location.
      */
-    load_command_t const   *pCmd = pKernel->pLoadCmds;
+    load_command_t const   *pCmd = pThis->pLoadCmds;
     for (uint32_t iCmd = 0; ; iCmd++)
     {
         /* cmd index & offset. */
-        uintptr_t offCmd = (uintptr_t)pCmd - (uintptr_t)pKernel->pLoadCmds;
-        if (offCmd == pKernel->cbLoadCmds && iCmd == pKernel->cLoadCmds)
+        uintptr_t offCmd = (uintptr_t)pCmd - (uintptr_t)pThis->pLoadCmds;
+        if (offCmd == pThis->cbLoadCmds && iCmd == pThis->cLoadCmds)
             break;
-        if (offCmd + sizeof(*pCmd) > pKernel->cbLoadCmds)
+        if (offCmd + sizeof(*pCmd) > pThis->cbLoadCmds)
             RETURN_VERR_BAD_EXE_FORMAT;
-        if (iCmd >= pKernel->cLoadCmds)
+        if (iCmd >= pThis->cLoadCmds)
             RETURN_VERR_BAD_EXE_FORMAT;
 
@@ -678,5 +662,5 @@
         if (pCmd->cmdsize < sizeof(*pCmd))
             RETURN_VERR_BAD_EXE_FORMAT;
-        if (pCmd->cmdsize > pKernel->cbLoadCmds)
+        if (pCmd->cmdsize > pThis->cbLoadCmds)
             RETURN_VERR_BAD_EXE_FORMAT;
         if (RT_ALIGN_32(pCmd->cmdsize, 4) != pCmd->cmdsize)
@@ -697,8 +681,8 @@
                     RETURN_VERR_BAD_EXE_FORMAT;
 
-                pKernel->offStrTab = pSymTab->stroff;
-                pKernel->cbStrTab  = pSymTab->strsize;
-                pKernel->offSyms   = pSymTab->symoff;
-                pKernel->cSyms     = pSymTab->nsyms;
+                pThis->offStrTab = pSymTab->stroff;
+                pThis->cbStrTab  = pSymTab->strsize;
+                pThis->offSyms   = pSymTab->symoff;
+                pThis->cSyms     = pSymTab->nsyms;
                 break;
             }
@@ -796,7 +780,7 @@
 
                     /* Add to the section table. */
-                    if (pKernel->cSections == MACHO_MAX_SECT)
-                        RETURN_VERR_BAD_EXE_FORMAT;
-                    pKernel->apSections[pKernel->cSections++] = &paSects[i];
+                    if (pThis->cSections == MACHO_MAX_SECT)
+                        RETURN_VERR_BAD_EXE_FORMAT;
+                    pThis->apSections[pThis->cSections++] = &paSects[i];
                 }
 
@@ -866,21 +850,21 @@
  *
  * @returns IPRT status code.
- * @param   pKernel             The internal scratch data.
+ * @param   pThis               The internal scratch data.
  */
-static int rtR0DarwinMachKernelLoadFileHeaders(PRTR0DARWINKERNEL pKernel)
+static int rtR0MachKernelLoadFileHeaders(RTR0MACHKERNELINT *pThis)
 {
     uint32_t i;
 
-    pKernel->offArch = 0;
-    pKernel->cbArch  = 0;
+    pThis->offArch = 0;
+    pThis->cbArch  = 0;
 
     /*
      * Read the first bit of the file, parse the FAT if found there.
      */
-    int rc = RTFileReadAt(pKernel->hFile, 0, pKernel->abBuf, sizeof(fat_header_t) + sizeof(fat_arch_t) * 16, NULL);
+    int rc = RTFileReadAt(pThis->hFile, 0, pThis->abBuf, sizeof(fat_header_t) + sizeof(fat_arch_t) * 16, NULL);
     if (RT_FAILURE(rc))
         return rc;
 
-    fat_header_t   *pFat        = (fat_header *)pKernel->abBuf;
+    fat_header_t   *pFat        = (fat_header *)pThis->abBuf;
     fat_arch_t     *paFatArches = (fat_arch_t *)(pFat + 1);
 
@@ -912,11 +896,11 @@
                 && paFatArches[i].cpusubtype == MY_CPU_SUBTYPE_ALL)
             {
-                pKernel->offArch = paFatArches[i].offset;
-                pKernel->cbArch  = paFatArches[i].size;
-                if (!pKernel->cbArch)
-                    RETURN_VERR_BAD_EXE_FORMAT;
-                if (pKernel->offArch < sizeof(fat_header_t) + sizeof(fat_arch_t) * pFat->nfat_arch)
-                    RETURN_VERR_BAD_EXE_FORMAT;
-                if (pKernel->offArch + pKernel->cbArch <= pKernel->offArch)
+                pThis->offArch = paFatArches[i].offset;
+                pThis->cbArch  = paFatArches[i].size;
+                if (!pThis->cbArch)
+                    RETURN_VERR_BAD_EXE_FORMAT;
+                if (pThis->offArch < sizeof(fat_header_t) + sizeof(fat_arch_t) * pFat->nfat_arch)
+                    RETURN_VERR_BAD_EXE_FORMAT;
+                if (pThis->offArch + pThis->cbArch <= pThis->offArch)
                     RETURN_VERR_LDR_ARCH_MISMATCH;
                 break;
@@ -930,8 +914,8 @@
      * Read the Mach-O header and validate it.
      */
-    rc = RTFileReadAt(pKernel->hFile, pKernel->offArch, pKernel->abBuf, sizeof(MY_MACHO_HEADER), NULL);
+    rc = RTFileReadAt(pThis->hFile, pThis->offArch, pThis->abBuf, sizeof(MY_MACHO_HEADER), NULL);
     if (RT_FAILURE(rc))
         return rc;
-    MY_MACHO_HEADER const *pHdr = (MY_MACHO_HEADER const *)pKernel->abBuf;
+    MY_MACHO_HEADER const *pHdr = (MY_MACHO_HEADER const *)pThis->abBuf;
     if (pHdr->magic != MY_MACHO_MAGIC)
     {
@@ -961,43 +945,68 @@
         RETURN_VERR_LDR_UNEXPECTED;
 
-    pKernel->cLoadCmds  = pHdr->ncmds;
-    pKernel->cbLoadCmds = pHdr->sizeofcmds;
+    pThis->cLoadCmds  = pHdr->ncmds;
+    pThis->cbLoadCmds = pHdr->sizeofcmds;
     return VINF_SUCCESS;
 }
 
 
-/**
- * Opens symbol table of the mach_kernel.
- *
- * @returns IPRT status code.
- * @param   pszMachKernel   The path to the mach_kernel image.
- * @param   ppHandle        Where to return a handle on success.
- *                          Call rtR0DarwinMachKernelClose on it
- *                          when done.
- */
-static int rtR0DarwinMachKernelOpen(const char *pszMachKernel, PRTR0DARWINKERNEL *ppHandle)
-{
-    *ppHandle = NULL;
-    PRTR0DARWINKERNEL pKernel = (PRTR0DARWINKERNEL)RTMemAllocZ(sizeof(*pKernel));
-    if (!pKernel)
+RTDECL(int) RTR0MachKernelOpen(const char *pszMachKernel, PRTR0MACHKERNEL phKernel)
+{
+    *phKernel = NIL_RTR0MACHKERNEL;
+
+    RTR0MACHKERNELINT *pThis = (RTR0MACHKERNELINT *)RTMemAllocZ(sizeof(*pThis));
+    if (!pThis)
         return VERR_NO_MEMORY;
-    pKernel->hFile = NIL_RTFILE;
-
-    int rc = RTFileOpen(&pKernel->hFile, pszMachKernel, RTFILE_O_READ | RTFILE_O_OPEN | RTFILE_O_DENY_WRITE);
+    pThis->hFile = NIL_RTFILE;
+
+    int rc = RTFileOpen(&pThis->hFile, pszMachKernel, RTFILE_O_READ | RTFILE_O_OPEN | RTFILE_O_DENY_WRITE);
     if (RT_SUCCESS(rc))
-        rc = rtR0DarwinMachKernelLoadFileHeaders(pKernel);
+        rc = rtR0MachKernelLoadFileHeaders(pThis);
     if (RT_SUCCESS(rc))
-        rc = rtR0DarwinMachKernelLoadCommands(pKernel);
+        rc = rtR0MachKernelLoadCommands(pThis);
     if (RT_SUCCESS(rc))
-        rc = rtR0DarwinMachKernelLoadSymTab(pKernel);
+        rc = rtR0MachKernelLoadSymTab(pThis);
     if (RT_SUCCESS(rc))
-        rc = rtR0DarwinMachKernelCheckStandardSymbols(pKernel);
-
-    rtR0DarwinMachKernelLoadDone(pKernel);
+        rc = rtR0MachKernelCheckStandardSymbols(pThis);
+
+    rtR0MachKernelLoadDone(pThis);
     if (RT_SUCCESS(rc))
-        *ppHandle = pKernel;
+        *phKernel = pThis;
     else
-        rtR0DarwinMachKernelClose(pKernel);
+        RTR0MachKernelClose(pThis);
     return rc;
 }
 
+
+RTR0DECL(int) RTR0MachKernelGetSymbol(RTR0MACHKERNEL hKernel, const char *pszSymbol, void **ppvValue)
+{
+    RTR0MACHKERNELINT *pThis = hKernel;
+    AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
+
+    uintptr_t uValue = rtR0MachKernelLookup(pThis, pszSymbol);
+    if (ppvValue)
+        *ppvValue = (void *)uValue;
+    if (!uValue)
+        return VERR_SYMBOL_NOT_FOUND;
+    return VINF_SUCCESS;
+}
+
+
+RTR0DECL(int) RTR0MachKernelClose(RTR0MACHKERNEL hKernel)
+{
+    if (hKernel == NIL_RTR0MACHKERNEL)
+        return VINF_SUCCESS;
+
+    RTR0MACHKERNELINT *pThis = hKernel;
+    AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
+
+    RTMemFree(pThis->pachStrTab);
+    pThis->pachStrTab = NULL;
+
+    RTMemFree(pThis->paSyms);
+    pThis->paSyms = NULL;
+
+    RTMemFree(pThis);
+    return VINF_SUCCESS;
+}
+
Index: /trunk/src/VBox/Runtime/testcase/Makefile.kmk
===================================================================
--- /trunk/src/VBox/Runtime/testcase/Makefile.kmk	(revision 37572)
+++ /trunk/src/VBox/Runtime/testcase/Makefile.kmk	(revision 37573)
@@ -578,5 +578,8 @@
 
 tstRTDarwinMachKernel_TEMPLATE = VBOXR3TSTEXE
-tstRTDarwinMachKernel_SOURCES  = tstRTDarwinMachKernel.cpp
+tstRTDarwinMachKernel_INCS     = ../include
+tstRTDarwinMachKernel_SOURCES  = \
+	tstRTDarwinMachKernel.cpp \
+	../r0drv/darwin/mach_kernel-r0drv-darwin.cpp
 
 ntGetTimerResolution_SOURCES = ntGetTimerResolution.cpp
Index: /trunk/src/VBox/Runtime/testcase/tstRTDarwinMachKernel.cpp
===================================================================
--- /trunk/src/VBox/Runtime/testcase/tstRTDarwinMachKernel.cpp	(revision 37572)
+++ /trunk/src/VBox/Runtime/testcase/tstRTDarwinMachKernel.cpp	(revision 37573)
@@ -25,23 +25,23 @@
  */
 
+
 /*******************************************************************************
 *   Header Files                                                               *
 *******************************************************************************/
+#include <iprt/darwin/machkernel.h>
 #include <iprt/err.h>
 #include <iprt/string.h>
 #include <iprt/test.h>
 
-#include "../r0drv/darwin/mach_kernel-r0drv-darwin.cpp"
 
 
 static void dotest(const char *pszMachKernel)
 {
-    PRTR0DARWINKERNEL pKernel;
-    RTTESTI_CHECK_RC_RETV(rtR0DarwinMachKernelOpen(pszMachKernel, &pKernel), VINF_SUCCESS);
+    RTR0MACHKERNEL hKernel;
+    RTTESTI_CHECK_RC_RETV(RTR0MachKernelOpen(pszMachKernel, &hKernel), VINF_SUCCESS);
     static const char * const s_apszSyms[] =
     {
         "ast_pending",
-        "i386_signal_cpu",
-        "i386_cpu_IPI",
+        "cpu_interrupt",
         "dtrace_register",
         "dtrace_suspend",
@@ -49,9 +49,15 @@
     for (unsigned i = 0; i < RT_ELEMENTS(s_apszSyms); i++)
     {
-        uintptr_t uPtr = rtR0DarwinMachKernelLookup(pKernel, s_apszSyms[i]);
-        RTTestIPrintf(RTTESTLVL_ALWAYS, "%p %s\n", uPtr, s_apszSyms[i]);
-        RTTESTI_CHECK(uPtr != 0);
+        void *pvValue = NULL;
+        int rc = RTR0MachKernelGetSymbol(hKernel, s_apszSyms[i], &pvValue);
+        RTTestIPrintf(RTTESTLVL_ALWAYS, "%Rrc %p %s\n", rc, pvValue, s_apszSyms[i]);
+        RTTESTI_CHECK_RC(rc, VINF_SUCCESS);
+        if (RT_SUCCESS(rc))
+            RTTESTI_CHECK_RC(RTR0MachKernelGetSymbol(hKernel, s_apszSyms[i], NULL), VINF_SUCCESS);
     }
-    rtR0DarwinMachKernelClose(pKernel);
+
+    RTTESTI_CHECK_RC(RTR0MachKernelGetSymbol(hKernel, "no_such_symbol_name_really", NULL), VERR_SYMBOL_NOT_FOUND);
+    RTTESTI_CHECK_RC(RTR0MachKernelClose(hKernel), VINF_SUCCESS);
+    RTTESTI_CHECK_RC(RTR0MachKernelClose(NIL_RTR0MACHKERNEL), VINF_SUCCESS);
 }
 
@@ -60,5 +66,5 @@
 {
     RTTEST hTest;
-    RTEXITCODE rcExit = RTTestInitAndCreate("tstRTDarwinMachKernel", &hTest);
+    RTEXITCODE rcExit = RTTestInitAndCreate("tstRTMachKernel", &hTest);
     if (rcExit != RTEXITCODE_SUCCESS)
         return rcExit;
