Index: trunk/include/VBox/dbgf.h
===================================================================
--- trunk/include/VBox/dbgf.h	(revision 8799)
+++ trunk/include/VBox/dbgf.h	(revision 8800)
@@ -1530,23 +1530,6 @@
 
 
-/**
- * Scan guest memory for an exact byte string.
- *
- * @returns VBox status codes:
- * @retval  VINF_SUCCESS and *pGCPtrHit on success.
- * @retval  VERR_DBGF_MEM_NOT_FOUND if not found.
- * @retval  VERR_INVALID_POINTER if any of the pointer arguments are invalid.
- * @retval  VERR_INVALID_ARGUMENT if any other arguments are invalid.
- *
- * @param   pVM         The VM handle.
- * @param   pAddress    Where to store the mixed address.
- * @param   cbRange     The number of bytes to scan.
- * @param   pabNeedle   What to search for - exact search.
- * @param   cbNeedle    Size of the search byte string.
- * @param   pHitAddress Where to put the address of the first hit.
- *
- * @thread  Any thread.
- */
 DBGFR3DECL(int) DBGFR3MemScan(PVM pVM, PCDBGFADDRESS pAddress, RTGCUINTPTR cbRange, const uint8_t *pabNeedle, size_t cbNeedle, PDBGFADDRESS pHitAddress);
+DBGFR3DECL(int) DBGFR3MemRead(PVM pVM, PCDBGFADDRESS pAddress, void *pvBuf, size_t cbRead);
 
 
@@ -1690,8 +1673,8 @@
 #define DBGFOSREG_MAGIC     0x19830808
 
-DBGFR3DECL(int)     DBGFR3OSRegister(PVM pVM, PDBGFOSREG pReg);
-DBGFR3DECL(int)     DBGFR3OSDeregister(PVM pVM, PDBGFOSREG pReg);
+DBGFR3DECL(int)     DBGFR3OSRegister(PVM pVM, PCDBGFOSREG pReg);
+DBGFR3DECL(int)     DBGFR3OSDeregister(PVM pVM, PCDBGFOSREG pReg);
 DBGFR3DECL(int)     DBGFR3OSDetect(PVM pVM, char *pszName, size_t cchName);
-DBGFR3DECL(int)     DBGFR3OSNameAndVersion(PVM pVM, char *pszName, size_t cchName, char *pszVersion, size_t cchVersion);
+DBGFR3DECL(int)     DBGFR3OSQueryNameAndVersion(PVM pVM, char *pszName, size_t cchName, char *pszVersion, size_t cchVersion);
 DBGFR3DECL(void *)  DBGFR3OSQueryInterface(PVM pVM, DBGFOSINTERFACE enmIf);
 
Index: trunk/src/VBox/Debugger/DBGCCommands.cpp
===================================================================
--- trunk/src/VBox/Debugger/DBGCCommands.cpp	(revision 8799)
+++ trunk/src/VBox/Debugger/DBGCCommands.cpp	(revision 8800)
@@ -67,4 +67,5 @@
 static DECLCALLBACK(int) dbgcCmdEcho(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult);
 static DECLCALLBACK(int) dbgcCmdRunScript(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult);
+static DECLCALLBACK(int) dbgcCmdDetect(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult);
 
 
@@ -167,4 +168,5 @@
     { "exit",       0,        0,        NULL,               0,                          NULL,               0,          dbgcCmdQuit,        "",                     "Exits the debugger." },
     { "format",     1,        1,        &g_aArgAny[0],      ELEMENTS(g_aArgAny),        NULL,               0,          dbgcCmdFormat,      "",                     "Evaluates an expression and formats it." },
+    { "detect",     0,        0,        NULL,               0,                          NULL,               0,          dbgcCmdDetect,      "",                     "Detects or re-detects the guest os and starts the OS specific digger." },
     { "harakiri",   0,        0,        NULL,               0,                          NULL,               0,          dbgcCmdHarakiri,    "",                     "Kills debugger process." },
     { "help",       0,        ~0,       &g_aArgHelp[0],     ELEMENTS(g_aArgHelp),       NULL,               0,          dbgcCmdHelp,        "[cmd/op [..]]",        "Display help. For help about info items try 'info help'." },
@@ -716,4 +718,42 @@
 
     NOREF(pCmd); NOREF(pResult); NOREF(pVM);
+    return rc;
+}
+
+
+/**
+ * The 'detect' command.
+ *
+ * @returns VBox status.
+ * @param   pCmd        Pointer to the command descriptor (as registered).
+ * @param   pCmdHlp     Pointer to command helper functions.
+ * @param   pVM         Pointer to the current VM (if any).
+ * @param   paArgs      Pointer to (readonly) array of arguments.
+ * @param   cArgs       Number of arguments in the array.
+ */
+static DECLCALLBACK(int) dbgcCmdDetect(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult)
+{
+    /* check that the parser did what it's supposed to do. */
+    if (cArgs != 0)
+        return pCmdHlp->pfnPrintf(pCmdHlp, NULL, "parser error\n");
+
+    /*
+     * Perform the detection.
+     */
+    char szName[64];
+    int rc = DBGFR3OSDetect(pVM, szName, sizeof(szName));
+    if (RT_FAILURE(rc))
+        return pCmdHlp->pfnVBoxError(pCmdHlp, rc, "Executing DBGFR3OSDetect().");
+    if (rc == VINF_SUCCESS)
+    {
+        rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL, "Guest OS: %s\n", szName);
+        char szVersion[64];
+        int rc2 = DBGFR3OSQueryNameAndVersion(pVM, NULL, 0, szVersion, sizeof(szVersion));
+        if (RT_SUCCESS(rc2))
+            rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL, "Version : %s\n", szVersion);
+    }
+    else
+        rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL, "Unable to figure out which guest OS it is, sorry.\n");
+    NOREF(pCmd); NOREF(pResult); NOREF(paArgs);
     return rc;
 }
Index: trunk/src/VBox/Debugger/DBGConsole.cpp
===================================================================
--- trunk/src/VBox/Debugger/DBGConsole.cpp	(revision 8799)
+++ trunk/src/VBox/Debugger/DBGConsole.cpp	(revision 8800)
@@ -158,4 +158,5 @@
 
 #include "DBGCInternal.h"
+#include "DBGPlugIns.h"
 
 
@@ -2047,16 +2048,42 @@
             rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL,
                                          "Current VM is %08x\n" /** @todo get and print the VM name! */
-                                         "VBoxDbg> ",
-                                         pDbgc->pVM);
+                                         , pDbgc->pVM);
         }
         else
             rc = pDbgc->CmdHlp.pfnVBoxError(&pDbgc->CmdHlp, rc, "When trying to attach to VM %p\n", pDbgc->pVM);
     }
-    else
+
+    /*
+     * Load plugins.
+     * This is currently hardcoded simplicity.
+     */
+    if (RT_SUCCESS(rc) && pVM)
+    {
+        static PCDBGFOSREG s_aPlugIns[] =
+        {
+            //&g_DBGDiggerFreeBSD,
+            //&g_DBGDiggerLinux,
+            //&g_DBGDiggerOS2,
+            &g_DBGDiggerSolaris,
+            //&g_DBGDiggerWinNt
+        };
+
+        pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "Loading Plugins:");
+        for (unsigned i = 0; i < RT_ELEMENTS(s_aPlugIns); i++)
+        {
+            pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, " %s", s_aPlugIns[i]->szName);
+            rc = DBGFR3OSRegister(pVM, s_aPlugIns[i]);
+            if (RT_FAILURE(rc) && rc != VERR_ALREADY_LOADED)
+                pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "->%Rrc", rc);
+        }
+        pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\n");
+    }
+
+    if (RT_SUCCESS(rc))
         rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL,
                                      "VBoxDbg> ");
 
     /*
-     * Run the main loop.
+     * Run the debugger main loop.
      */
     if (RT_SUCCESS(rc))
Index: trunk/src/VBox/Debugger/DBGPlugInSolaris.cpp
===================================================================
--- trunk/src/VBox/Debugger/DBGPlugInSolaris.cpp	(revision 8800)
+++ trunk/src/VBox/Debugger/DBGPlugInSolaris.cpp	(revision 8800)
@@ -0,0 +1,352 @@
+/* $Id$ */
+/** @file
+ * DBGPlugInSolaris - Debugger and Guest OS Digger Plugin For Solaris.
+ */
+
+/*
+ * Copyright (C) 2008 Sun Microsystems, Inc.
+ *
+ * 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.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
+ * Clara, CA 95054 USA or visit http://www.sun.com if you need
+ * additional information or have any questions.
+ */
+
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include "DBGPlugIns.h"
+#include <VBox/dbgf.h>
+#include <iprt/string.h>
+
+
+/*******************************************************************************
+*   Structures and Typedefs                                                    *
+*******************************************************************************/
+
+/** @name InternalSolaris structures
+ * @{ */
+
+typedef struct SOL32_modctl
+{
+    uint32_t    mod_next;               /**<  0 */
+    uint32_t    mod_prev;               /**<  4 */
+    int32_t     mod_id;                 /**<  8 */
+    uint32_t    mod_mp;                 /**<  c Pointer to the kernel runtime loader bits. */
+    uint32_t    mod_inprogress_thread;  /**< 10 */
+    uint32_t    mod_modinfo;            /**< 14 */
+    uint32_t    mod_linkage;            /**< 18 */
+    uint32_t    mod_filename;           /**< 1c */
+    uint32_t    mod_modname;            /**< 20 */
+    int8_t      mod_busy;               /**< 24 */
+    int8_t      mod_want;               /**< 25 */
+    int8_t      mod_prim;               /**< 26 this is 1 for 'unix' and a few others. */
+    int8_t      mod_unused_padding;     /**< 27 */
+    int32_t     mod_ref;                /**< 28 */
+    int8_t      mod_loaded;             /**< 2c */
+    int8_t      mod_installed;          /**< 2d */
+    int8_t      mod_loadflags;          /**< 2e */
+    int8_t      mod_delay_unload;       /**< 2f */
+    uint32_t    mod_requisites;         /**< 30 */
+    uint32_t    mod___unused;           /**< 34 */
+    int32_t     mod_loadcnt;            /**< 38 */
+    int32_t     mod_nenabled;           /**< 3c */
+    uint32_t    mod_text;               /**< 40 */
+    uint32_t    mod_text_size;          /**< 44 */
+    int32_t     mod_gencount;           /**< 48 */
+    uint32_t    mod_requisite_loading;  /**< 4c */
+} SOL32_modctl_t;
+AssertCompileSize(SOL32_modctl_t, 0x50);
+
+/** @} */
+
+
+/**
+ * Solaris guest OS digger instance data.
+ */
+typedef struct DBGDIGGERSOLARIS
+{
+    /** Whether the information is valid or not.
+     * (For fending off illegal interface method calls.) */
+    bool fValid;
+
+    /** Address of the 'unix' text segment.
+     * This is set during probing. */
+    DBGFADDRESS AddrUnixText;
+    /** Address of the 'unix' text segment.
+     * This is set during probing. */
+    DBGFADDRESS AddrUnixData;
+    /** Address of the 'unix' modctl_t (aka modules). */
+    DBGFADDRESS AddrUnixModCtl;
+
+} DBGDIGGERSOLARIS;
+/** Pointer to the solaris guest OS digger instance data. */
+typedef DBGDIGGERSOLARIS *PDBGDIGGERSOLARIS;
+
+
+/*******************************************************************************
+*   Defined Constants And Macros                                               *
+*******************************************************************************/
+/** Validates a 32-bit solaris kernel address */
+#define SOL32_VALID_ADDRESS(Addr)   ((Addr) > UINT32_C(0x80000000) && (Addr) < UINT32_C(0xfffff000))
+
+
+
+/*******************************************************************************
+*   Internal Functions                                                         *
+*******************************************************************************/
+static DECLCALLBACK(int)  dbgDiggerSolarisInit(PVM pVM, void *pvData);
+
+
+
+/**
+ * @copydoc DBGFOSREG::pfnQueryInterface
+ */
+static DECLCALLBACK(void *) dbgDiggerSolarisQueryInterface(PVM pVM, void *pvData, DBGFOSINTERFACE enmIf)
+{
+    return NULL;
+}
+
+
+/**
+ * @copydoc DBGFOSREG::pfnQueryVersion
+ */
+static DECLCALLBACK(int)  dbgDiggerSolarisQueryVersion(PVM pVM, void *pvData, char *pszVersion, size_t cchVersion)
+{
+    PDBGDIGGERSOLARIS pThis = (PDBGDIGGERSOLARIS)pvData;
+    Assert(pThis->fValid);
+
+    return VERR_NOT_IMPLEMENTED;
+}
+
+
+/**
+ * @copydoc DBGFOSREG::pfnTerm
+ */
+static DECLCALLBACK(void)  dbgDiggerSolarisTerm(PVM pVM, void *pvData)
+{
+    PDBGDIGGERSOLARIS pThis = (PDBGDIGGERSOLARIS)pvData;
+    Assert(pThis->fValid);
+
+    pThis->fValid = false;
+}
+
+
+/**
+ * @copydoc DBGFOSREG::pfnRefresh
+ */
+static DECLCALLBACK(int)  dbgDiggerSolarisRefresh(PVM pVM, void *pvData)
+{
+    PDBGDIGGERSOLARIS pThis = (PDBGDIGGERSOLARIS)pvData;
+    Assert(pThis->fValid);
+
+    /*
+     * For now we'll flush and reload everything.
+     */
+    dbgDiggerSolarisTerm(pVM, pvData);
+    return dbgDiggerSolarisInit(pVM, pvData);
+}
+
+
+/**
+ * @copydoc DBGFOSREG::pfnInit
+ */
+static DECLCALLBACK(int)  dbgDiggerSolarisInit(PVM pVM, void *pvData)
+{
+    PDBGDIGGERSOLARIS pThis = (PDBGDIGGERSOLARIS)pvData;
+    Assert(!pThis->fValid);
+    int rc;
+
+    /*
+     * Find the 'unix' modctl_t structure (aka modules).
+     * We know it resides in the unix data segment.
+     */
+    DBGFR3AddrFromFlat(pVM, &pThis->AddrUnixModCtl, 0);
+
+    DBGFADDRESS     CurAddr = pThis->AddrUnixData;
+    DBGFADDRESS     MaxAddr;
+    DBGFR3AddrFromFlat(pVM, &MaxAddr, CurAddr.FlatPtr + 0x01000000);
+    const uint8_t  *pbExpr = (const uint8_t *)&pThis->AddrUnixText.FlatPtr;
+    const uint32_t  cbExpr = sizeof(uint32_t);//pThis->AddrUnixText.FlatPtr < _4G ? sizeof(uint32_t) : sizeof(uint64_t)
+    while (   CurAddr.FlatPtr < MaxAddr.FlatPtr
+           && CurAddr.FlatPtr >= pThis->AddrUnixData.FlatPtr)
+    {
+        DBGFADDRESS HitAddr;
+        rc = DBGFR3MemScan(pVM, &CurAddr, MaxAddr.FlatPtr - CurAddr.FlatPtr, pbExpr, cbExpr, &HitAddr);
+        if (RT_FAILURE(rc))
+            break;
+
+        /*
+         * Read out the modctl_t structure.
+         */
+        DBGFADDRESS ModCtlAddr;
+        DBGFR3AddrFromFlat(pVM, &ModCtlAddr, HitAddr.FlatPtr - RT_OFFSETOF(SOL32_modctl_t, mod_text));
+        SOL32_modctl_t ModCtl;
+        rc = DBGFR3MemRead(pVM, &ModCtlAddr, &ModCtl, sizeof(ModCtl));
+        if (RT_SUCCESS(rc))
+        {
+            if (    SOL32_VALID_ADDRESS(ModCtl.mod_next)
+                &&  SOL32_VALID_ADDRESS(ModCtl.mod_prev)
+                &&  ModCtl.mod_id == 0
+                &&  SOL32_VALID_ADDRESS(ModCtl.mod_mp)
+                &&  SOL32_VALID_ADDRESS(ModCtl.mod_filename)
+                &&  SOL32_VALID_ADDRESS(ModCtl.mod_modname)
+                &&  ModCtl.mod_prim == 1
+                &&  ModCtl.mod_loaded == 1
+                &&  ModCtl.mod_installed == 1
+                &&  ModCtl.mod_requisites == 0
+                &&  ModCtl.mod_loadcnt == 1
+                /*&&  ModCtl.mod_text == pThis->AddrUnixText.FlatPtr*/
+                &&  ModCtl.mod_text_size < UINT32_C(0xfec00000) - UINT32_C(0xfe800000) )
+            {
+                char szUnix[5];
+                DBGFADDRESS NameAddr;
+                DBGFR3AddrFromFlat(pVM, &NameAddr, ModCtl.mod_modname);
+                rc = DBGFR3MemRead(pVM, &NameAddr, &szUnix, sizeof(szUnix));
+                if (RT_SUCCESS(rc))
+                {
+                    if (!strcmp(szUnix, "unix"))
+                    {
+                        pThis->AddrUnixModCtl = ModCtlAddr;
+                        break;
+                    }
+                    Log(("sol32 mod_name=%.*s\n", sizeof(szUnix), szUnix));
+                }
+            }
+        }
+
+        /* next */
+        DBGFR3AddrFromFlat(pVM, &CurAddr, HitAddr.FlatPtr + cbExpr);
+    }
+
+    /*
+     * Walk the module chain and add the modules and their symbols.
+     */
+    if (pThis->AddrUnixModCtl.FlatPtr)
+    {
+        int iMod = 0;
+        CurAddr = pThis->AddrUnixModCtl;
+        do
+        {
+            /* read it */
+            SOL32_modctl_t ModCtl;
+            rc = DBGFR3MemRead(pVM, &CurAddr, &ModCtl, sizeof(ModCtl));
+            if (RT_FAILURE(rc))
+            {
+                LogRel(("sol32: bad modctl_t chain: %RGv - %Rrc\n", iMod, CurAddr.FlatPtr, rc));
+                break;
+            }
+
+            /* process it. */
+
+
+            /* next */
+            if (!SOL32_VALID_ADDRESS(ModCtl.mod_next))
+            {
+                LogRel(("sol32: bad modctl_t chain at %RGv: %RGv\n", iMod, CurAddr.FlatPtr, (RTGCUINTPTR)ModCtl.mod_next));
+                break;
+            }
+            if (++iMod >= 1024)
+            {
+                LogRel(("sol32: too many modules (%d)\n", iMod));
+                break;
+            }
+            DBGFR3AddrFromFlat(pVM, &CurAddr, ModCtl.mod_next);
+        } while (CurAddr.FlatPtr != pThis->AddrUnixModCtl.FlatPtr);
+    }
+
+    pThis->fValid = true;
+    return VINF_SUCCESS;
+}
+
+
+/**
+ * @copydoc DBGFOSREG::pfnProbe
+ */
+static DECLCALLBACK(bool)  dbgDiggerSolarisProbe(PVM pVM, void *pvData)
+{
+    PDBGDIGGERSOLARIS pThis = (PDBGDIGGERSOLARIS)pvData;
+
+    /*
+     * Look for "SunOS Release" in the text segment.
+     */
+    DBGFADDRESS Addr;
+    DBGFR3AddrFromFlat(pVM, &Addr, 0xfe800000);
+    RTGCUINTPTR cbRange = 0xfec00000 - 0xfe800000;
+
+    DBGFADDRESS HitAddr;
+    static const uint8_t s_abSunRelease[] = "SunOS Release ";
+    int rc = DBGFR3MemScan(pVM, &Addr, cbRange, s_abSunRelease, sizeof(s_abSunRelease) - 1, &HitAddr);
+    if (RT_FAILURE(rc))
+        return false;
+
+    /*
+     * Look for the copy right string too, just to be sure.
+     */
+    static const uint8_t s_abSMI[] = "Sun Microsystems, Inc.";
+    rc = DBGFR3MemScan(pVM, &Addr, cbRange, s_abSMI, sizeof(s_abSMI) - 1, &HitAddr);
+    if (RT_FAILURE(rc))
+        return false;
+
+    /*
+     * Remember the unix text and data addresses (32-bit vs 64-bit).
+     */
+    pThis->AddrUnixText = Addr;
+//    if (pThis->AddrUnixText.FlatPtr == 0xfe800000)
+    {
+        DBGFR3AddrFromFlat(pVM, &Addr, 0xfec00000);
+        pThis->AddrUnixData = Addr;
+    }
+//    else
+//    {
+//        DBGFR3AddrFromFlat(pVM, &Addr, UINT64_C(0xwhateveritis));
+//        pThis->AddrUnixData = Addr;
+//    }
+
+    return true;
+}
+
+
+/**
+ * @copydoc DBGFOSREG::pfnDestruct
+ */
+static DECLCALLBACK(void)  dbgDiggerSolarisDestruct(PVM pVM, void *pvData)
+{
+
+}
+
+
+/**
+ * @copydoc DBGFOSREG::pfnConstruct
+ */
+static DECLCALLBACK(int)  dbgDiggerSolarisConstruct(PVM pVM, void *pvData)
+{
+    return VINF_SUCCESS;
+}
+
+
+const DBGFOSREG g_DBGDiggerSolaris =
+{
+    /* .u32Magic = */           DBGFOSREG_MAGIC,
+    /* .fFlags = */             0,
+    /* .cbData = */             sizeof(DBGDIGGERSOLARIS),
+    /* .szName = */             "Solaris",
+    /* .pfnConstruct = */       dbgDiggerSolarisConstruct,
+    /* .pfnDestruct = */        dbgDiggerSolarisDestruct,
+    /* .pfnProbe = */           dbgDiggerSolarisProbe,
+    /* .pfnInit = */            dbgDiggerSolarisInit,
+    /* .pfnRefresh = */         dbgDiggerSolarisRefresh,
+    /* .pfnTerm = */            dbgDiggerSolarisTerm,
+    /* .pfnQueryVersion = */    dbgDiggerSolarisQueryVersion,
+    /* .pfnQueryInterface = */  dbgDiggerSolarisQueryInterface,
+    /* .u32EndMagic = */        DBGFOSREG_MAGIC
+};
+
Index: trunk/src/VBox/Debugger/DBGPlugIns.h
===================================================================
--- trunk/src/VBox/Debugger/DBGPlugIns.h	(revision 8800)
+++ trunk/src/VBox/Debugger/DBGPlugIns.h	(revision 8800)
@@ -0,0 +1,41 @@
+/* $Id$ */
+/** @file
+ * DBGPlugIns - Debugger Plug-Ins.
+ *
+ * This is just a temporary static wrapper for what may eventually
+ * become some fancy dynamic stuff.
+ */
+
+/*
+ * Copyright (C) 2008 Sun Microsystems, Inc.
+ *
+ * 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.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
+ * Clara, CA 95054 USA or visit http://www.sun.com if you need
+ * additional information or have any questions.
+ */
+
+#ifndef ___DBGPlugIns_h
+#define ___DBGPlugIns_h
+
+#include <VBox/dbgf.h>
+
+__BEGIN_DECLS
+
+extern const DBGFOSREG g_DBGDiggerFreeBSD;
+extern const DBGFOSREG g_DBGDiggerLinux;
+extern const DBGFOSREG g_DBGDiggerOS2;
+extern const DBGFOSREG g_DBGDiggerSolaris;
+extern const DBGFOSREG g_DBGDiggerWinNt;
+
+__END_DECLS
+
+#endif
+
Index: trunk/src/VBox/Debugger/Makefile.kmk
===================================================================
--- trunk/src/VBox/Debugger/Makefile.kmk	(revision 8799)
+++ trunk/src/VBox/Debugger/Makefile.kmk	(revision 8800)
@@ -56,5 +56,6 @@
 	DBGCEmulateCodeView.cpp \
 	DBGCOps.cpp \
-	DBGCTcp.cpp
+	DBGCTcp.cpp \
+	DBGPlugInSolaris.cpp
 
 
Index: trunk/src/VBox/Debugger/testcase/tstDBGCStubs.cpp
===================================================================
--- trunk/src/VBox/Debugger/testcase/tstDBGCStubs.cpp	(revision 8799)
+++ trunk/src/VBox/Debugger/testcase/tstDBGCStubs.cpp	(revision 8800)
@@ -282,5 +282,21 @@
     return VERR_INTERNAL_ERROR;
 }
+DBGFR3DECL(int) DBGFR3MemRead(PVM pVM, PCDBGFADDRESS pAddress, void *pvBuf, size_t cbRead)
+{
+    return VERR_INTERNAL_ERROR;
+}
 DBGFR3DECL(void) DBGFR3AddrFromPhys(PVM pVM, PDBGFADDRESS pAddress, RTGCPHYS PhysAddr)
 {
 }
+DBGFR3DECL(int) DBGFR3OSRegister(PVM pVM, PCDBGFOSREG pReg)
+{
+    return VERR_INTERNAL_ERROR;
+}
+DBGFR3DECL(int) DBGFR3OSDetect(PVM pVM, char *pszName, size_t cchName)
+{
+    return VERR_INTERNAL_ERROR;
+}
+DBGFR3DECL(int) DBGFR3OSQueryNameAndVersion(PVM pVM, char *pszName, size_t cchName, char *pszVersion, size_t cchVersion)
+{
+    return VERR_INTERNAL_ERROR;
+}
Index: trunk/src/VBox/VMM/DBGFMem.cpp
===================================================================
--- trunk/src/VBox/VMM/DBGFMem.cpp	(revision 8799)
+++ trunk/src/VBox/VMM/DBGFMem.cpp	(revision 8800)
@@ -116,2 +116,58 @@
 
 
+/**
+ * Read guest memory.
+ *
+ * @returns VBox status code.
+ * @param   pVM             Pointer to the shared VM structure.
+ * @param   pAddress        Where to start reading.
+ * @param   pvBuf           Where to store the data we've read.
+ * @param   cbRead          The number of bytes to read.
+ */
+static DECLCALLBACK(int) dbgfR3MemRead(PVM pVM, PCDBGFADDRESS pAddress, void *pvBuf, size_t cbRead)
+{
+    /*
+     * Validate the input we use, PGM does the rest.
+     */
+    if (!DBGFR3AddrIsValid(pVM, pAddress))
+        return VERR_INVALID_POINTER;
+    if (!VALID_PTR(pvBuf))
+        return VERR_INVALID_POINTER;
+    if (DBGFADDRESS_IS_HMA(pAddress))
+        return VERR_INVALID_POINTER;
+
+    /*
+     * Select DBGF worker by addressing mode.
+     */
+    int rc;
+    PGMMODE enmMode = PGMGetGuestMode(pVM);
+    if (    enmMode == PGMMODE_REAL
+        ||  enmMode == PGMMODE_PROTECTED
+        ||  DBGFADDRESS_IS_PHYS(pAddress) )
+        rc = PGMPhysReadGCPhys(pVM, pvBuf, pAddress->FlatPtr, cbRead);
+    else
+        rc = PGMPhysReadGCPtr(pVM, pvBuf, pAddress->FlatPtr, cbRead);
+    return rc;
+}
+
+
+/**
+ * Read guest memory.
+ *
+ * @returns VBox status code.
+ * @param   pVM             Pointer to the shared VM structure.
+ * @param   pAddress        Where to start reading.
+ * @param   pvBuf           Where to store the data we've read.
+ * @param   cbRead          The number of bytes to read.
+ */
+DBGFR3DECL(int) DBGFR3MemRead(PVM pVM, PCDBGFADDRESS pAddress, void *pvBuf, size_t cbRead)
+{
+    PVMREQ pReq;
+    int rc = VMR3ReqCallU(pVM->pUVM, &pReq, RT_INDEFINITE_WAIT, 0, (PFNRT)dbgfR3MemRead, 4,
+                          pVM, pAddress, pvBuf, cbRead);
+    if (VBOX_SUCCESS(rc))
+        rc = pReq->iStatus;
+    VMR3ReqFree(pReq);
+
+    return rc;
+}
Index: trunk/src/VBox/VMM/DBGFOS.cpp
===================================================================
--- trunk/src/VBox/VMM/DBGFOS.cpp	(revision 8799)
+++ trunk/src/VBox/VMM/DBGFOS.cpp	(revision 8800)
@@ -38,4 +38,45 @@
 
 /**
+ * EMT worker function for DBGFR3OSRegister.
+ *
+ * @returns VBox status code.
+ * @param   pVM     Pointer to the shared VM structure.
+ * @param   pReg    The registration structure.
+ */
+static DECLCALLBACK(int) dbgfR3OSRegister(PVM pVM, PDBGFOSREG pReg)
+{
+    /* more validations. */
+    for (PDBGFOS pOS = pVM->dbgf.s.pOSHead; pOS; pOS = pOS->pNext)
+        if (!strcmp(pOS->pReg->szName, pReg->szName))
+        {
+            Log(("dbgfR3OSRegister: %s -> VERR_ALREADY_LOADED\n", pReg->szName));
+            return VERR_ALREADY_LOADED;
+        }
+
+    /*
+     * Allocate a new structure, call the constructor and link it into the list.
+     */
+    PDBGFOS pOS = (PDBGFOS)MMR3HeapAllocZ(pVM, MM_TAG_DBGF_OS, RT_OFFSETOF(DBGFOS, abData[pReg->cbData]));
+    AssertReturn(pOS, VERR_NO_MEMORY);
+    pOS->pReg = pReg;
+
+    int rc = pOS->pReg->pfnConstruct(pVM, pOS->abData);
+    if (RT_SUCCESS(rc))
+    {
+        pOS->pNext = pVM->dbgf.s.pOSHead;
+        pVM->dbgf.s.pOSHead = pOS;
+    }
+    else
+    {
+        if (pOS->pReg->pfnDestruct)
+            pOS->pReg->pfnDestruct(pVM, pOS->abData);
+        MMR3HeapFree(pOS);
+    }
+
+    return VINF_SUCCESS;
+}
+
+
+/**
  * Registers a guest OS digger.
  *
@@ -46,11 +87,11 @@
  * @param   pVM     Pointer to the shared VM structure.
  * @param   pReg    The registration structure.
- */
-DBGFR3DECL(int) DBGFR3OSRegister(PVM pVM, PDBGFOSREG pReg)
+ * @thread  Any.
+ */
+DBGFR3DECL(int) DBGFR3OSRegister(PVM pVM, PCDBGFOSREG pReg)
 {
     /*
      * Validate intput.
      */
-    VM_ASSERT_EMT_RETURN(pVM, VERR_VM_THREAD_NOT_EMT);
     AssertPtrReturn(pReg, VERR_INVALID_POINTER);
     AssertReturn(pReg->u32Magic == DBGFOSREG_MAGIC, VERR_INVALID_MAGIC);
@@ -58,5 +99,5 @@
     AssertReturn(!pReg->fFlags, VERR_INVALID_PARAMETER);
     AssertReturn(pReg->cbData < _2G, VERR_INVALID_PARAMETER);
-    AssertReturn(!pReg->szName[0], VERR_INVALID_NAME);
+    AssertReturn(pReg->szName[0], VERR_INVALID_NAME);
     AssertReturn(memchr(&pReg->szName[0], '\0', sizeof(pReg->szName)), VERR_INVALID_NAME);
     AssertPtrReturn(pReg->pfnConstruct, VERR_INVALID_POINTER);
@@ -68,28 +109,15 @@
     AssertPtrReturn(pReg->pfnQueryVersion, VERR_INVALID_POINTER);
     AssertPtrReturn(pReg->pfnQueryInterface, VERR_INVALID_POINTER);
-    for (PDBGFOS pOS = pVM->dbgf.s.pOSHead; pOS; pOS = pOS->pNext)
-        AssertMsgReturn(!strcmp(pOS->pReg->szName, pReg->szName), ("%s\n", pReg->szName), VERR_ALREADY_EXISTS);
-
-    /*
-     * Allocate a new structure, call the constructor and link it into the list.
-     */
-    PDBGFOS pOS = (PDBGFOS)MMR3HeapAllocZ(pVM, MM_TAG_DBGF_OS, RT_OFFSETOF(DBGFOS, abData[pReg->cbData]));
-    AssertReturn(pOS, VERR_NO_MEMORY);
-    pOS->pReg = pReg;
-
-    int rc = pOS->pReg->pfnConstruct(pVM, pOS->abData);
+
+    /*
+     * Pass it on to the EMT.
+     */
+    PVMREQ pReq;
+    int rc = VMR3ReqCallU(pVM->pUVM, &pReq, RT_INDEFINITE_WAIT, 0, (PFNRT)dbgfR3OSRegister, 2, pVM, pReg);
     if (RT_SUCCESS(rc))
-    {
-        pOS->pNext = pVM->dbgf.s.pOSHead;
-        pVM->dbgf.s.pOSHead = pOS;
-    }
-    else
-    {
-        if (pOS->pReg->pfnDestruct)
-            pOS->pReg->pfnDestruct(pVM, pOS->abData);
-        MMR3HeapFree(pOS);
-    }
-
-    return VINF_SUCCESS;
+        rc = pReq->iStatus;
+    VMR3ReqFree(pReq);
+
+    return rc;
 }
 
@@ -126,8 +154,5 @@
 
 /**
- * Detectes the guest OS and try dig out symbols and useful stuff.
- *
- * When called the 2nd time, symbols will be updated that if the OS
- * is the same.
+ * EMT worker function for DBGFR3OSDetect.
  *
  * @returns VBox status code.
@@ -139,14 +164,9 @@
  * @param   cchName     Size of the buffer.
  */
-DBGFR3DECL(int) DBGFR3OSDetect(PVM pVM, char *pszName, size_t cchName)
-{
-    VM_ASSERT_EMT_RETURN(pVM, VERR_VM_THREAD_NOT_EMT);
-    AssertPtrNullReturn(pszName, VERR_INVALID_POINTER);
-
+static DECLCALLBACK(int) dbgfR3OSDetect(PVM pVM, char *pszName, size_t cchName)
+{
     /*
      * Cycle thru the detection routines.
      */
-    if (pszName && cchName)
-        *pszName = '\0';
     PDBGFOS const pOldOS = pVM->dbgf.s.pCurOS;
     pVM->dbgf.s.pCurOS = NULL;
@@ -178,8 +198,39 @@
 
 /**
- * Queries the name and/or version string for the guest OS.
- *
- * It goes without saying that this querying is done using the current
- * guest OS digger and not additions or user configuration.
+ * Detectes the guest OS and try dig out symbols and useful stuff.
+ *
+ * When called the 2nd time, symbols will be updated that if the OS
+ * is the same.
+ *
+ * @returns VBox status code.
+ * @retval  VINF_SUCCESS if successfully detected.
+ * @retval  VINF_DBGF_OS_NOT_DETCTED if we cannot figure it out.
+ *
+ * @param   pVM         Pointer to the shared VM structure.
+ * @param   pszName     Where to store the OS name. Empty string if not detected.
+ * @param   cchName     Size of the buffer.
+ * @thread  Any.
+ */
+DBGFR3DECL(int) DBGFR3OSDetect(PVM pVM, char *pszName, size_t cchName)
+{
+    AssertPtrNullReturn(pszName, VERR_INVALID_POINTER);
+    if (pszName && cchName)
+        *pszName = '\0';
+
+    /*
+     * Pass it on to the EMT.
+     */
+    PVMREQ pReq;
+    int rc = VMR3ReqCallU(pVM->pUVM, &pReq, RT_INDEFINITE_WAIT, 0, (PFNRT)dbgfR3OSDetect, 3, pVM, pszName, cchName);
+    if (RT_SUCCESS(rc))
+        rc = pReq->iStatus;
+    VMR3ReqFree(pReq);
+
+    return rc;
+}
+
+
+/**
+ * EMT worker function for DBGFR3OSQueryNameAndVersion
  *
  * @returns VBox status code.
@@ -190,18 +241,6 @@
  * @param   cchVersion      The size of the version buffer.
  */
-DBGFR3DECL(int) DBGFR3OSNameAndVersion(PVM pVM, char *pszName, size_t cchName, char *pszVersion, size_t cchVersion)
-{
-    VM_ASSERT_EMT_RETURN(pVM, VERR_VM_THREAD_NOT_EMT);
-    AssertPtrNullReturn(pszName, VERR_INVALID_POINTER);
-    AssertPtrNullReturn(pszVersion, VERR_INVALID_POINTER);
-
-    /*
-     * Initialize the output up front.
-     */
-    if (pszName && cchName)
-        *pszName = '\0';
-    if (pszVersion && cchVersion)
-        *pszVersion = '\0';
-
+static DECLCALLBACK(int) dbgfR3OSQueryNameAndVersion(PVM pVM, char *pszName, size_t cchName, char *pszVersion, size_t cchVersion)
+{
     /*
      * Any known OS?
@@ -237,4 +276,68 @@
 
 /**
+ * Queries the name and/or version string for the guest OS.
+ *
+ * It goes without saying that this querying is done using the current
+ * guest OS digger and not additions or user configuration.
+ *
+ * @returns VBox status code.
+ * @param   pVM             Pointer to the shared VM structure.
+ * @param   pszName         Where to store the OS name. Optional.
+ * @param   cchName         The size of the name buffer.
+ * @param   pszVersion      Where to store the version string. Optional.
+ * @param   cchVersion      The size of the version buffer.
+ * @thread  Any.
+ */
+DBGFR3DECL(int) DBGFR3OSQueryNameAndVersion(PVM pVM, char *pszName, size_t cchName, char *pszVersion, size_t cchVersion)
+{
+    AssertPtrNullReturn(pszName, VERR_INVALID_POINTER);
+    AssertPtrNullReturn(pszVersion, VERR_INVALID_POINTER);
+
+    /*
+     * Initialize the output up front.
+     */
+    if (pszName && cchName)
+        *pszName = '\0';
+    if (pszVersion && cchVersion)
+        *pszVersion = '\0';
+
+    /*
+     * Pass it on to the EMT.
+     */
+    PVMREQ pReq;
+    int rc = VMR3ReqCallU(pVM->pUVM, &pReq, RT_INDEFINITE_WAIT, 0, (PFNRT)dbgfR3OSQueryNameAndVersion,
+                          5, pVM, pszName, cchName, pszVersion, cchVersion);
+    if (RT_SUCCESS(rc))
+        rc = pReq->iStatus;
+    VMR3ReqFree(pReq);
+
+    return rc;
+}
+
+
+/**
+ * EMT worker for DBGFR3OSQueryInterface.
+ *
+ * @param   pVM         Pointer to the shared VM structure.
+ * @param   enmIf       The interface identifier.
+ * @param   ppvIf       Where to store the interface pointer on success.
+ */
+static DECLCALLBACK(void) dbgfR3OSQueryInterface(PVM pVM, DBGFOSINTERFACE enmIf, void **ppvIf)
+{
+    if (pVM->dbgf.s.pCurOS)
+    {
+        *ppvIf = pVM->dbgf.s.pCurOS->pReg->pfnQueryInterface(pVM, pVM->dbgf.s.pCurOS->abData, enmIf);
+        if (*ppvIf)
+        {
+            /** @todo Create EMT wrapper for the returned interface once we've defined one...
+             * Just keep a list of wrapper together with the OS instance. */
+        }
+    }
+    else
+        *ppvIf = NULL;
+}
+
+
+/**
  * Query an optional digger interface.
  *
@@ -243,11 +346,19 @@
  * @param   pVM         Pointer to the shared VM structure.
  * @param   enmIf       The interface identifier.
+ * @thread  Any.
  */
 DBGFR3DECL(void *) DBGFR3OSQueryInterface(PVM pVM, DBGFOSINTERFACE enmIf)
 {
     AssertMsgReturn(enmIf > DBGFOSINTERFACE_INVALID && enmIf < DBGFOSINTERFACE_END, ("%d\n", enmIf), NULL);
-    if (pVM->dbgf.s.pCurOS)
-        return pVM->dbgf.s.pCurOS->pReg->pfnQueryInterface(pVM, pVM->dbgf.s.pCurOS->abData, enmIf);
-    return NULL;
-}
-
+
+    /*
+     * Pass it on to the EMT.
+     */
+    void *pvIf = NULL;
+    PVMREQ pReq;
+    VMR3ReqCallVoidU(pVM->pUVM, &pReq, RT_INDEFINITE_WAIT, (PFNRT)dbgfR3OSQueryInterface, 3, pVM, enmIf, &pvIf);
+    VMR3ReqFree(pReq);
+
+    return pvIf;
+}
+
