Index: /trunk/include/iprt/err.h
===================================================================
--- /trunk/include/iprt/err.h	(revision 46047)
+++ /trunk/include/iprt/err.h	(revision 46048)
@@ -1502,4 +1502,6 @@
 /** Internal processing error in the debug module reader code. */
 #define VERR_DBG_MOD_IPE                        (-689)
+/** The symbol size was adjusted while adding it. */
+#define VINF_DBG_ADJUSTED_SYM_SIZE              (-690)
 /** @} */
 
Index: /trunk/include/iprt/win/lazy-dbghelp.h
===================================================================
--- /trunk/include/iprt/win/lazy-dbghelp.h	(revision 46047)
+++ /trunk/include/iprt/win/lazy-dbghelp.h	(revision 46048)
@@ -66,4 +66,8 @@
 #define SymInitialize RTLDRLAZY_FUNC_NAME(dbghelp, SymInitialize)
 
+RTLDRLAZY_FUNC(dbghelp, BOOL, WINAPI, SymCleanup, (HANDLE a1), (a1), FALSE);
+#undef SymCleanup
+#define SymCleanup RTLDRLAZY_FUNC_NAME(dbghelp, SymCleanup)
+
 RTLDRLAZY_FUNC(dbghelp, DWORD, WINAPI, SymGetOptions, (VOID), (), 0);
 #undef SymGetOptions
@@ -85,4 +89,14 @@
 #define SymLoadModuleEx RTLDRLAZY_FUNC_NAME(dbghelp, SymLoadModuleEx)
 
+RTLDRLAZY_FUNC(dbghelp, DWORD64, WINAPI, SymLoadModuleExW,
+               (HANDLE a1, HANDLE a2, PCWSTR a3, PCWSTR a4, DWORD64 a5, DWORD a6, PMODLOAD_DATA a7, DWORD a8),
+               (a1, a2, a3, a4, a5, a6, a7, a8), 0);
+#undef SymLoadModuleExW
+#define SymLoadModuleExW RTLDRLAZY_FUNC_NAME(dbghelp, SymLoadModuleExW)
+
+RTLDRLAZY_FUNC(dbghelp, DWORD64, WINAPI, SymUnloadModule64, (HANDLE a1, DWORD64 a2), (a1, a2), 0);
+#undef SymUnloadModule64
+#define SymUnloadModule64 RTLDRLAZY_FUNC_NAME(dbghelp, SymUnloadModule64)
+
 RTLDRLAZY_FUNC(dbghelp, BOOL, WINAPI, SymEnumSymbols,
                (HANDLE a1, DWORD a2, PCSTR a3, PSYM_ENUMERATESYMBOLS_CALLBACK a4, PVOID a5),
@@ -91,4 +105,10 @@
 #define SymEnumSymbols RTLDRLAZY_FUNC_NAME(dbghelp, SymEnumSymbols)
 
+RTLDRLAZY_FUNC(dbghelp, BOOL, WINAPI, SymEnumLinesW,
+               (HANDLE a1, ULONG64 a2, PCWSTR a3, PCWSTR a4, PSYM_ENUMLINES_CALLBACKW a5, PVOID a6),
+               (a1, a2, a3, a4, a5, a6), FALSE);
+#undef SymEnumLinesW
+#define SymEnumLinesW RTLDRLAZY_FUNC_NAME(dbghelp, SymEnumLinesW)
+
 RTLDRLAZY_FUNC(dbghelp, BOOL, WINAPI, SymGetModuleInfo64, (HANDLE a1, DWORD64 a2, PIMAGEHLP_MODULE64 a3), (a1, a2, a3), FALSE);
 #undef SymGetModuleInfo64
@@ -96,4 +116,6 @@
 
 
+
+
 #endif
 
Index: /trunk/src/VBox/Runtime/Makefile.kmk
===================================================================
--- /trunk/src/VBox/Runtime/Makefile.kmk	(revision 46047)
+++ /trunk/src/VBox/Runtime/Makefile.kmk	(revision 46048)
@@ -544,4 +544,5 @@
 
 RuntimeR3_SOURCES.win = \
+	common/dbg/dbgmoddbghelp.cpp \
 	generic/cdrom-generic.cpp \
 	generic/RTDirExists-generic.cpp \
Index: /trunk/src/VBox/Runtime/common/dbg/dbgmod.cpp
===================================================================
--- /trunk/src/VBox/Runtime/common/dbg/dbgmod.cpp	(revision 46047)
+++ /trunk/src/VBox/Runtime/common/dbg/dbgmod.cpp	(revision 46048)
@@ -277,4 +277,8 @@
         if (RT_SUCCESS(rc))
             rc = rtDbgModDebugInterpreterRegister(&g_rtDbgModVtDbgDwarf);
+#ifdef RT_OS_WINDOWS
+        if (RT_SUCCESS(rc))
+            rc = rtDbgModDebugInterpreterRegister(&g_rtDbgModVtDbgDbgHelp);
+#endif
         if (RT_SUCCESS(rc))
             rc = rtDbgModImageInterpreterRegister(&g_rtDbgModVtImgLdr);
Index: /trunk/src/VBox/Runtime/common/dbg/dbgmodcontainer.cpp
===================================================================
--- /trunk/src/VBox/Runtime/common/dbg/dbgmodcontainer.cpp	(revision 46047)
+++ /trunk/src/VBox/Runtime/common/dbg/dbgmodcontainer.cpp	(revision 46048)
@@ -383,7 +383,15 @@
                     VERR_DBG_INVALID_SEGMENT_INDEX);
     AssertMsgReturn(    iSeg >= RTDBGSEGIDX_SPECIAL_FIRST
-                    ||  off + cb <= pThis->paSegs[iSeg].cb,
+                    ||  off <= pThis->paSegs[iSeg].cb,
                     ("off=%RTptr cb=%RTptr cbSeg=%RTptr\n", off, cb, pThis->paSegs[iSeg].cb),
                     VERR_DBG_INVALID_SEGMENT_OFFSET);
+
+    /* Be a little relaxed wrt to the symbol size. */
+    int rc = VINF_SUCCESS;
+    if (off + cb > pThis->paSegs[iSeg].cb)
+    {
+        cb = pThis->paSegs[iSeg].cb - off;
+        rc = VINF_DBG_ADJUSTED_SYM_SIZE;
+    }
 
     /*
@@ -401,5 +409,4 @@
     pSymbol->fFlags             = fFlags;
     pSymbol->NameCore.pszString = RTStrCacheEnterN(g_hDbgModStrCache, pszSymbol, cchSymbol);
-    int rc;
     if (pSymbol->NameCore.pszString)
     {
@@ -416,5 +423,5 @@
                         *piOrdinal = pThis->iNextSymbolOrdinal;
                     pThis->iNextSymbolOrdinal++;
-                    return VINF_SUCCESS;
+                    return rc;
                 }
 
Index: /trunk/src/VBox/Runtime/common/dbg/dbgmoddbghelp.cpp
===================================================================
--- /trunk/src/VBox/Runtime/common/dbg/dbgmoddbghelp.cpp	(revision 46048)
+++ /trunk/src/VBox/Runtime/common/dbg/dbgmoddbghelp.cpp	(revision 46048)
@@ -0,0 +1,465 @@
+/* $Id$ */
+/** @file
+ * IPRT - Debug Info Reader Using DbgHelp.dll if Present.
+ */
+
+/*
+ * Copyright (C) 2013 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.
+ */
+
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#define LOG_GROUP   RTLOGGROUP_DBG
+#include <iprt/dbg.h>
+#include "internal/iprt.h"
+
+#include <iprt/asm.h>
+#include <iprt/ctype.h>
+#include <iprt/err.h>
+#include <iprt/list.h>
+#include <iprt/log.h>
+#include <iprt/mem.h>
+#include <iprt/path.h>
+#include <iprt/string.h>
+#include "internal/dbgmod.h"
+
+#include <Windows.h>
+#include <Dbghelp.h>
+#include <iprt/win/lazy-dbghelp.h>
+
+
+/*******************************************************************************
+*   Structures and Typedefs                                                    *
+*******************************************************************************/
+/** For passing arguments to DbgHelp.dll callback. */
+typedef struct RTDBGMODBGHELPARGS
+{
+    RTDBGMOD        hCnt;
+    PRTDBGMODINT    pMod;
+    uint64_t        uModAddr;
+
+    /** UTF-8 version of the previous file name. */
+    char           *pszPrev;
+    /** Copy of the previous file name. */
+    PRTUTF16        pwszPrev;
+    /** Number of bytes pwszPrev points to. */
+    size_t          cbPrevUtf16Alloc;
+} RTDBGMODBGHELPARGS;
+
+
+
+/** @interface_method_impl{RTDBGMODVTDBG,pfnLineByAddr} */
+static DECLCALLBACK(int) rtDbgModDbgHelp_LineByAddr(PRTDBGMODINT pMod, RTDBGSEGIDX iSeg, RTUINTPTR off,
+                                                  PRTINTPTR poffDisp, PRTDBGLINE pLineInfo)
+{
+    RTDBGMOD hCnt = (RTDBGMOD)pMod->pvDbgPriv;
+    return RTDbgModLineByAddr(hCnt, iSeg, off, poffDisp, pLineInfo);
+}
+
+
+/** @interface_method_impl{RTDBGMODVTDBG,pfnLineByOrdinal} */
+static DECLCALLBACK(int) rtDbgModDbgHelp_LineByOrdinal(PRTDBGMODINT pMod, uint32_t iOrdinal, PRTDBGLINE pLineInfo)
+{
+    RTDBGMOD hCnt = (RTDBGMOD)pMod->pvDbgPriv;
+    return RTDbgModLineByOrdinal(hCnt, iOrdinal, pLineInfo);
+}
+
+
+/** @interface_method_impl{RTDBGMODVTDBG,pfnLineCount} */
+static DECLCALLBACK(uint32_t) rtDbgModDbgHelp_LineCount(PRTDBGMODINT pMod)
+{
+    RTDBGMOD hCnt = (RTDBGMOD)pMod->pvDbgPriv;
+    return RTDbgModLineCount(hCnt);
+}
+
+
+/** @interface_method_impl{RTDBGMODVTDBG,pfnLineAdd} */
+static DECLCALLBACK(int) rtDbgModDbgHelp_LineAdd(PRTDBGMODINT pMod, const char *pszFile, size_t cchFile, uint32_t uLineNo,
+                                                 uint32_t iSeg, RTUINTPTR off, uint32_t *piOrdinal)
+{
+    RTDBGMOD hCnt = (RTDBGMOD)pMod->pvDbgPriv;
+    Assert(!pszFile[cchFile]); NOREF(cchFile);
+    return RTDbgModLineAdd(hCnt, pszFile, uLineNo, iSeg, off, piOrdinal);
+}
+
+
+/** @interface_method_impl{RTDBGMODVTDBG,pfnSymbolByAddr} */
+static DECLCALLBACK(int) rtDbgModDbgHelp_SymbolByAddr(PRTDBGMODINT pMod, RTDBGSEGIDX iSeg, RTUINTPTR off, uint32_t fFlags,
+                                                      PRTINTPTR poffDisp, PRTDBGSYMBOL pSymInfo)
+{
+    RTDBGMOD hCnt = (RTDBGMOD)pMod->pvDbgPriv;
+    return RTDbgModSymbolByAddr(hCnt, iSeg, off, fFlags, poffDisp, pSymInfo);
+}
+
+
+/** @interface_method_impl{RTDBGMODVTDBG,pfnSymbolByName} */
+static DECLCALLBACK(int) rtDbgModDbgHelp_SymbolByName(PRTDBGMODINT pMod, const char *pszSymbol, size_t cchSymbol,
+                                                      PRTDBGSYMBOL pSymInfo)
+{
+    RTDBGMOD hCnt = (RTDBGMOD)pMod->pvDbgPriv;
+    Assert(!pszSymbol[cchSymbol]);
+    return RTDbgModSymbolByName(hCnt, pszSymbol/*, cchSymbol*/, pSymInfo);
+}
+
+
+/** @interface_method_impl{RTDBGMODVTDBG,pfnSymbolByOrdinal} */
+static DECLCALLBACK(int) rtDbgModDbgHelp_SymbolByOrdinal(PRTDBGMODINT pMod, uint32_t iOrdinal, PRTDBGSYMBOL pSymInfo)
+{
+    RTDBGMOD hCnt = (RTDBGMOD)pMod->pvDbgPriv;
+    return RTDbgModSymbolByOrdinal(hCnt, iOrdinal, pSymInfo);
+}
+
+
+/** @interface_method_impl{RTDBGMODVTDBG,pfnSymbolCount} */
+static DECLCALLBACK(uint32_t) rtDbgModDbgHelp_SymbolCount(PRTDBGMODINT pMod)
+{
+    RTDBGMOD hCnt = (RTDBGMOD)pMod->pvDbgPriv;
+    return RTDbgModSymbolCount(hCnt);
+}
+
+
+/** @interface_method_impl{RTDBGMODVTDBG,pfnSymbolAdd} */
+static DECLCALLBACK(int) rtDbgModDbgHelp_SymbolAdd(PRTDBGMODINT pMod, const char *pszSymbol, size_t cchSymbol,
+                                                   RTDBGSEGIDX iSeg, RTUINTPTR off, RTUINTPTR cb, uint32_t fFlags,
+                                                   uint32_t *piOrdinal)
+{
+    RTDBGMOD hCnt = (RTDBGMOD)pMod->pvDbgPriv;
+    Assert(!pszSymbol[cchSymbol]); NOREF(cchSymbol);
+    return RTDbgModSymbolAdd(hCnt, pszSymbol, iSeg, off, cb, fFlags, piOrdinal);
+}
+
+
+/** @interface_method_impl{RTDBGMODVTDBG,pfnSegmentByIndex} */
+static DECLCALLBACK(int) rtDbgModDbgHelp_SegmentByIndex(PRTDBGMODINT pMod, RTDBGSEGIDX iSeg, PRTDBGSEGMENT pSegInfo)
+{
+    RTDBGMOD hCnt = (RTDBGMOD)pMod->pvDbgPriv;
+    return RTDbgModSegmentByIndex(hCnt, iSeg, pSegInfo);
+}
+
+
+/** @interface_method_impl{RTDBGMODVTDBG,pfnSegmentCount} */
+static DECLCALLBACK(RTDBGSEGIDX) rtDbgModDbgHelp_SegmentCount(PRTDBGMODINT pMod)
+{
+    RTDBGMOD hCnt = (RTDBGMOD)pMod->pvDbgPriv;
+    return RTDbgModSegmentCount(hCnt);
+}
+
+
+/** @interface_method_impl{RTDBGMODVTDBG,pfnSegmentAdd} */
+static DECLCALLBACK(int) rtDbgModDbgHelp_SegmentAdd(PRTDBGMODINT pMod, RTUINTPTR uRva, RTUINTPTR cb, const char *pszName, size_t cchName,
+                                                    uint32_t fFlags, PRTDBGSEGIDX piSeg)
+{
+    RTDBGMOD hCnt = (RTDBGMOD)pMod->pvDbgPriv;
+    Assert(!pszName[cchName]); NOREF(cchName);
+    return RTDbgModSegmentAdd(hCnt, uRva, cb, pszName, fFlags, piSeg);
+}
+
+
+/** @interface_method_impl{RTDBGMODVTDBG,pfnImageSize} */
+static DECLCALLBACK(RTUINTPTR) rtDbgModDbgHelp_ImageSize(PRTDBGMODINT pMod)
+{
+    RTDBGMOD hCnt = (RTDBGMOD)pMod->pvDbgPriv;
+    RTUINTPTR cb1 = RTDbgModImageSize(hCnt);
+    RTUINTPTR cb2 = pMod->pImgVt->pfnImageSize(pMod);
+    return RT_MAX(cb1, cb2);
+}
+
+
+/** @interface_method_impl{RTDBGMODVTDBG,pfnRvaToSegOff} */
+static DECLCALLBACK(RTDBGSEGIDX) rtDbgModDbgHelp_RvaToSegOff(PRTDBGMODINT pMod, RTUINTPTR uRva, PRTUINTPTR poffSeg)
+{
+    RTDBGMOD hCnt = (RTDBGMOD)pMod->pvDbgPriv;
+    return RTDbgModRvaToSegOff(hCnt, uRva, poffSeg);
+}
+
+
+/** @interface_method_impl{RTDBGMODVTDBG,pfnClose} */
+static DECLCALLBACK(int) rtDbgModDbgHelp_Close(PRTDBGMODINT pMod)
+{
+    RTDBGMOD hCnt = (RTDBGMOD)pMod->pvDbgPriv;;
+    RTDbgModRelease(hCnt);
+    pMod->pvDbgPriv = NULL;
+    return VINF_SUCCESS;
+}
+
+
+/**
+ * SymEnumLinesW callback that adds a line number to the container.
+ *
+ * @returns TRUE, FALSE if we're out of memory.
+ * @param   pLineInfo           Line number information.
+ * @param   pvUser              Pointer to a RTDBGMODBGHELPARGS structure.
+ */
+static BOOL CALLBACK rtDbgModDbgHelpCopyLineNumberCallback(PSRCCODEINFOW pLineInfo, PVOID pvUser)
+{
+    RTDBGMODBGHELPARGS *pArgs  = (RTDBGMODBGHELPARGS *)pvUser;
+
+    /*
+     * To save having to call RTUtf16ToUtf8 every time, we keep a copy of the
+     * previous file name both as UTF-8 and UTF-16.
+     */
+    /** @todo we could combine RTUtf16Len and memcmp... */
+    size_t cbLen  = (RTUtf16Len(pLineInfo->FileName) + 1) * sizeof(RTUTF16);
+    if (   !pArgs->pwszPrev
+        || memcmp(pArgs->pwszPrev, pLineInfo->FileName, cbLen) )
+    {
+        if (pArgs->cbPrevUtf16Alloc >= cbLen)
+            memcpy(pArgs->pwszPrev, pLineInfo->FileName, cbLen);
+        else
+        {
+            RTMemFree(pArgs->pwszPrev);
+            pArgs->cbPrevUtf16Alloc = cbLen;
+            pArgs->pwszPrev = (PRTUTF16)RTMemDupEx(pLineInfo->FileName, cbLen, pArgs->cbPrevUtf16Alloc - cbLen);
+            if (!pArgs->pwszPrev)
+                pArgs->cbPrevUtf16Alloc = 0;
+        }
+
+        RTStrFree(pArgs->pszPrev);
+        pArgs->pszPrev = NULL;
+        int rc = RTUtf16ToUtf8(pLineInfo->FileName, &pArgs->pszPrev);
+        if (RT_FAILURE(rc))
+        {
+            SetLastError(ERROR_OUTOFMEMORY);
+            Log(("rtDbgModDbgHelpCopyLineNumberCallback: Out of memory\n"));
+            return FALSE;
+        }
+    }
+
+    /*
+     * Add the line number to the container.
+     */
+    int rc = RTDbgModLineAdd(pArgs->hCnt, pArgs->pszPrev, pLineInfo->LineNumber,
+                             RTDBGSEGIDX_RVA, pLineInfo->Address - pArgs->uModAddr, NULL);
+    Log((" %#018x %05u  %s  [%Rrc]\n", pLineInfo->Address, pLineInfo->LineNumber, rc));
+    NOREF(rc);
+
+    return TRUE;
+}
+
+
+/**
+ * Copies the line numbers into the container.
+ *
+ * @returns IPRT status code.
+ * @param   pMod                The debug module.
+ * @param   hCnt                The container that will keep the symbols.
+ * @param   hFake               The fake process handle.
+ * @param   uModAddr            The module load address.
+ */
+static int rtDbgModDbgHelpCopyLineNumbers(PRTDBGMODINT pMod, RTDBGMOD hCnt, HANDLE hFake, uint64_t uModAddr)
+{
+    RTDBGMODBGHELPARGS Args;
+    Args.hCnt             = hCnt;
+    Args.pMod             = pMod;
+    Args.uModAddr         = uModAddr;
+    Args.pszPrev          = NULL;
+    Args.pwszPrev         = NULL;
+    Args.cbPrevUtf16Alloc = 0;
+
+    int rc;
+    if (SymEnumLinesW(hFake, uModAddr, NULL /*pszObj*/, NULL /*pszFile*/, rtDbgModDbgHelpCopyLineNumberCallback, &Args))
+        rc = VINF_SUCCESS;
+    else
+    {
+        rc = RTErrConvertFromWin32(GetLastError());
+        Log(("Line number enum: %Rrc (%u)\n", rc, GetLastError()));
+        if (rc == VERR_NOT_SUPPORTED)
+            rc = VINF_SUCCESS;
+    }
+
+    RTStrFree(Args.pszPrev);
+    RTMemFree(Args.pwszPrev);
+    return rc;
+}
+
+
+/**
+ * SymEnumSymbols callback that adds a symbol to the container.
+ *
+ * @returns TRUE
+ * @param   pSymInfo            The symbol information.
+ * @param   cbSymbol            The symbol size (estimated).
+ * @param   pvUser              Pointer to a RTDBGMODBGHELPARGS structure.
+ */
+static BOOL CALLBACK rtDbgModDbgHelpCopySymbolsCallback(PSYMBOL_INFO pSymInfo, ULONG cbSymbol, PVOID pvUser)
+{
+    RTDBGMODBGHELPARGS *pArgs = (RTDBGMODBGHELPARGS *)pvUser;
+
+    int rc = RTDbgModSymbolAdd(pArgs->hCnt, pSymInfo->Name, RTDBGSEGIDX_RVA,
+                               pSymInfo->Address - pArgs->uModAddr, cbSymbol, 0, NULL);
+    Log(("  %#018x LB %#07x  %s  [%Rrc]\n", pSymInfo->Address, cbSymbol, pSymInfo->Name, rc));
+    NOREF(rc);
+
+    return TRUE;
+}
+
+
+/**
+ * Copies the symbols into the container.
+ *
+ * @returns IPRT status code.
+ * @param   pMod                The debug module.
+ * @param   hCnt                The container that will keep the symbols.
+ * @param   hFake               The fake process handle.
+ * @param   uModAddr            The module load address.
+ */
+static int rtDbgModDbgHelpCopySymbols(PRTDBGMODINT pMod, RTDBGMOD hCnt, HANDLE hFake, uint64_t uModAddr)
+{
+    RTDBGMODBGHELPARGS Args;
+    Args.hCnt     = hCnt;
+    Args.pMod     = pMod;
+    Args.uModAddr = uModAddr;
+    int rc;
+    if (SymEnumSymbols(hFake, uModAddr, NULL, rtDbgModDbgHelpCopySymbolsCallback, &Args))
+        rc = VINF_SUCCESS;
+    else
+    {
+        rc = RTErrConvertFromWin32(GetLastError());
+        Log(("SymEnumSymbols: %Rrc (%u)\n", rc, GetLastError()));
+    }
+    return rc;
+}
+
+
+/** @callback_method_impl{FNRTLDRENUMSEGS, Copies the PE segments over into
+ *                       the container.} */
+static DECLCALLBACK(int) rtDbgModDbgHelpAddSegmentsCallback(RTLDRMOD hLdrMod, PCRTLDRSEG pSeg, void *pvUser)
+{
+    RTDBGMOD hCnt = (RTDBGMOD)pvUser;
+
+    Log(("Segment %.*s: LinkAddress=%#llx RVA=%#llx cb=%#llx\n",
+         pSeg->cchName, pSeg->pchName, (uint64_t)pSeg->LinkAddress, (uint64_t)pSeg->RVA, pSeg->cb));
+    NOREF(hLdrMod);
+    char *pszName = (char *)pSeg->pchName;
+    if (pszName[pSeg->cchName])
+    {
+        pszName = (char *)alloca(pSeg->cchName + 1);
+        memcpy(pszName, pSeg->pchName, pSeg->cchName);
+        pszName[pSeg->cchName] = '\0';
+    }
+
+    RTLDRADDR cb = RT_MAX(pSeg->cb, pSeg->cbMapped);
+    return RTDbgModSegmentAdd(hCnt, pSeg->RVA, cb, pszName, 0 /*fFlags*/, NULL);
+}
+
+
+/** @interface_method_impl{RTDBGMODVTDBG,pfnTryOpen} */
+static DECLCALLBACK(int) rtDbgModDbgHelp_TryOpen(PRTDBGMODINT pMod)
+{
+    /*
+     * Currently only support external files with a executable already present.
+     */
+    if (!pMod->pszDbgFile)
+        return VERR_DBG_NO_MATCHING_INTERPRETER;
+    if (!pMod->pImgVt)
+        return VERR_DBG_NO_MATCHING_INTERPRETER;
+
+    /*
+     * Try load the module into an empty address space.
+     */
+    static uint32_t volatile s_uFakeHandle = 0x3940000;
+    HANDLE hFake;
+    do
+        hFake = (HANDLE)(uintptr_t)ASMAtomicIncU32(&s_uFakeHandle);
+    while (hFake == NULL || hFake == INVALID_HANDLE_VALUE);
+
+    int rc;
+    if (SymInitialize(hFake, NULL /*SearchPath*/, FALSE /*fInvalidProcess*/))
+    {
+        SymSetOptions(SYMOPT_LOAD_LINES | SymGetOptions());
+
+        PRTUTF16 pwszDbgFile;
+        rc = RTStrToUtf16(pMod->pszDbgFile, &pwszDbgFile);
+        if (RT_SUCCESS(rc))
+        {
+            uint64_t uModAddr = SymLoadModuleExW(hFake, NULL /*hFile*/, pwszDbgFile, NULL /*pszModName*/,
+                                                 0 /*uLoadAddr*/, 0 /*cbImage*/, NULL /*pModData*/, 0 /*fFlags*/);
+            if (uModAddr != 0)
+            {
+                /*
+                 * Create a container for copying the information into.
+                 */
+                RTDBGMOD hCnt;
+                rc = RTDbgModCreate(&hCnt, pMod->pszName, 0 /*cbSeg*/, 0 /*fFlags*/);
+                if (RT_SUCCESS(rc))
+                {
+                    rc = pMod->pImgVt->pfnEnumSegments(pMod, rtDbgModDbgHelpAddSegmentsCallback, hCnt);
+                    if (RT_SUCCESS(rc))
+                        rc = rtDbgModDbgHelpCopySymbols(pMod, hCnt, hFake, uModAddr);
+                    if (RT_SUCCESS(rc))
+                        rc = rtDbgModDbgHelpCopyLineNumbers(pMod, hCnt, hFake, uModAddr);
+                    if (RT_SUCCESS(rc))
+                    {
+                        pMod->pvDbgPriv = hCnt;
+                        pMod->pDbgVt    = &g_rtDbgModVtDbgDbgHelp;
+                        hCnt = NIL_RTDBGMOD;
+                    }
+                    RTDbgModRelease(hCnt);
+                }
+
+                SymUnloadModule64(hFake, uModAddr);
+            }
+            else
+                rc = RTErrConvertFromWin32(GetLastError());
+            RTUtf16Free(pwszDbgFile);
+        }
+
+        BOOL fRc2 = SymCleanup(hFake); Assert(fRc2); NOREF(fRc2);
+    }
+    else
+        rc = RTErrConvertFromWin32(GetLastError());
+    return rc;
+}
+
+
+
+/** Virtual function table for the DBGHELP debug info reader. */
+DECL_HIDDEN_CONST(RTDBGMODVTDBG) const g_rtDbgModVtDbgDbgHelp =
+{
+    /*.u32Magic = */            RTDBGMODVTDBG_MAGIC,
+    /*.fSupports = */           RT_DBGTYPE_CODEVIEW,
+    /*.pszName = */             "dbghelp",
+    /*.pfnTryOpen = */          rtDbgModDbgHelp_TryOpen,
+    /*.pfnClose = */            rtDbgModDbgHelp_Close,
+
+    /*.pfnRvaToSegOff = */      rtDbgModDbgHelp_RvaToSegOff,
+    /*.pfnImageSize = */        rtDbgModDbgHelp_ImageSize,
+
+    /*.pfnSegmentAdd = */       rtDbgModDbgHelp_SegmentAdd,
+    /*.pfnSegmentCount = */     rtDbgModDbgHelp_SegmentCount,
+    /*.pfnSegmentByIndex = */   rtDbgModDbgHelp_SegmentByIndex,
+
+    /*.pfnSymbolAdd = */        rtDbgModDbgHelp_SymbolAdd,
+    /*.pfnSymbolCount = */      rtDbgModDbgHelp_SymbolCount,
+    /*.pfnSymbolByOrdinal = */  rtDbgModDbgHelp_SymbolByOrdinal,
+    /*.pfnSymbolByName = */     rtDbgModDbgHelp_SymbolByName,
+    /*.pfnSymbolByAddr = */     rtDbgModDbgHelp_SymbolByAddr,
+
+    /*.pfnLineAdd = */          rtDbgModDbgHelp_LineAdd,
+    /*.pfnLineCount = */        rtDbgModDbgHelp_LineCount,
+    /*.pfnLineByOrdinal = */    rtDbgModDbgHelp_LineByOrdinal,
+    /*.pfnLineByAddr = */       rtDbgModDbgHelp_LineByAddr,
+
+    /*.u32EndMagic = */         RTDBGMODVTDBG_MAGIC
+};
+
+
Index: /trunk/src/VBox/Runtime/common/ldr/ldrPE.cpp
===================================================================
--- /trunk/src/VBox/Runtime/common/ldr/ldrPE.cpp	(revision 46047)
+++ /trunk/src/VBox/Runtime/common/ldr/ldrPE.cpp	(revision 46048)
@@ -929,6 +929,78 @@
 static DECLCALLBACK(int) rtldrPE_EnumSegments(PRTLDRMODINTERNAL pMod, PFNRTLDRENUMSEGS pfnCallback, void *pvUser)
 {
-    NOREF(pMod); NOREF(pfnCallback); NOREF(pvUser);
-    return VINF_NOT_SUPPORTED;
+    PRTLDRMODPE pModPe = (PRTLDRMODPE)pMod;
+    RTLDRSEG    SegInfo;
+
+    /*
+     * The first section is a fake one covering the headers.
+     */
+    SegInfo.pchName     = "NtHdrs";
+    SegInfo.cchName     = 6;
+    SegInfo.SelFlat     = 0;
+    SegInfo.Sel16bit    = 0;
+    SegInfo.fFlags      = 0;
+    SegInfo.fProt       = RTMEM_PROT_READ;
+    SegInfo.Alignment   = 1;
+    SegInfo.LinkAddress = 0;
+    SegInfo.RVA         = SegInfo.LinkAddress;
+    SegInfo.offFile     = 0;
+    SegInfo.cb          = pModPe->cbHeaders;
+    SegInfo.cbFile      = pModPe->cbHeaders;
+    SegInfo.cbMapped    = pModPe->cbHeaders;
+    if ((pModPe->paSections[0].Characteristics & IMAGE_SCN_TYPE_NOLOAD))
+        SegInfo.cbMapped = pModPe->paSections[0].VirtualAddress;
+    int rc = pfnCallback(pMod, &SegInfo, pvUser);
+
+    /*
+     * Then all the normal sections.
+     */
+    PCIMAGE_SECTION_HEADER pSh = pModPe->paSections;
+    for (uint32_t i = 0; i < pModPe->cSections && rc == VINF_SUCCESS; i++, pSh++)
+    {
+        SegInfo.pchName         = (const char *)&pSh->Name[0];
+        SegInfo.cchName         = (uint32_t)RTStrNLen(SegInfo.pchName, sizeof(pSh->Name));
+        SegInfo.SelFlat         = 0;
+        SegInfo.Sel16bit        = 0;
+        SegInfo.fFlags          = 0;
+        SegInfo.fProt           = RTMEM_PROT_NONE;
+        if (pSh->Characteristics & IMAGE_SCN_MEM_READ)
+            SegInfo.fProt       |= RTMEM_PROT_READ;
+        if (pSh->Characteristics & IMAGE_SCN_MEM_WRITE)
+            SegInfo.fProt       |= RTMEM_PROT_WRITE;
+        if (pSh->Characteristics & IMAGE_SCN_MEM_EXECUTE)
+            SegInfo.fProt       |= RTMEM_PROT_EXEC;
+        SegInfo.Alignment       = (pSh->Characteristics & IMAGE_SCN_ALIGN_MASK) >> IMAGE_SCN_ALIGN_SHIFT;
+        if (SegInfo.Alignment > 0)
+            SegInfo.Alignment   = RT_BIT_64(SegInfo.Alignment - 1);
+        if (pSh->Characteristics & IMAGE_SCN_TYPE_NOLOAD)
+        {
+            SegInfo.LinkAddress = NIL_RTLDRADDR;
+            SegInfo.RVA         = NIL_RTLDRADDR;
+            SegInfo.cbMapped    = pSh->Misc.VirtualSize;
+        }
+        else
+        {
+            SegInfo.LinkAddress = pSh->VirtualAddress;
+            SegInfo.RVA         = SegInfo.LinkAddress;
+            SegInfo.cbMapped    = RT_ALIGN(SegInfo.cb, SegInfo.Alignment);
+            if (i + 1 < pModPe->cSections && !(pSh[1].Characteristics & IMAGE_SCN_TYPE_NOLOAD))
+                SegInfo.cbMapped = pSh[1].VirtualAddress - pSh->VirtualAddress;
+        }
+        SegInfo.cb              = pSh->Misc.VirtualSize;
+        if (pSh->PointerToRawData == 0 || pSh->SizeOfRawData == 0)
+        {
+            SegInfo.offFile     = -1;
+            SegInfo.cbFile      = 0;
+        }
+        else
+        {
+            SegInfo.offFile     = pSh->PointerToRawData;
+            SegInfo.cbFile      = pSh->SizeOfRawData;
+        }
+
+        rc = pfnCallback(pMod, &SegInfo, pvUser);
+    }
+
+    return rc;
 }
 
@@ -938,6 +1010,37 @@
                                                         uint32_t *piSeg, PRTLDRADDR poffSeg)
 {
-    NOREF(pMod); NOREF(LinkAddress); NOREF(piSeg); NOREF(poffSeg);
-    return VERR_NOT_IMPLEMENTED;
+    PRTLDRMODPE pModPe = (PRTLDRMODPE)pMod;
+
+    /* Note! LinkAddress == RVA */
+
+    /* Special header segment. */
+    if (LinkAddress < pModPe->paSections[0].VirtualAddress)
+    {
+        *piSeg   = 0;
+        *poffSeg = LinkAddress;
+        return VINF_SUCCESS;
+    }
+
+    /*
+     * Search the normal sections. (Could do this in binary fashion, they're
+     * sorted, but too much bother right now.)
+     */
+    if (LinkAddress > pModPe->cbImage)
+        return VERR_LDR_INVALID_LINK_ADDRESS;
+    uint32_t                i       = pModPe->cSections;
+    PCIMAGE_SECTION_HEADER  paShs   = pModPe->paSections;
+    while (i-- > 0)
+        if (!(paShs[i].Characteristics & IMAGE_SCN_TYPE_NOLOAD))
+        {
+            uint32_t uAddr = paShs[i].VirtualAddress;
+            if (LinkAddress >= uAddr)
+            {
+                *poffSeg = LinkAddress - uAddr;
+                *piSeg   = i + 1;
+                return VINF_SUCCESS;
+            }
+        }
+
+    return VERR_LDR_INVALID_LINK_ADDRESS;
 }
 
@@ -946,6 +1049,10 @@
 static DECLCALLBACK(int) rtldrPE_LinkAddressToRva(PRTLDRMODINTERNAL pMod, RTLDRADDR LinkAddress, PRTLDRADDR pRva)
 {
-    NOREF(pMod); NOREF(LinkAddress); NOREF(pRva);
-    return VERR_NOT_IMPLEMENTED;
+    PRTLDRMODPE pModPe = (PRTLDRMODPE)pMod;
+
+    if (LinkAddress > pModPe->cbImage)
+        return VERR_LDR_INVALID_LINK_ADDRESS;
+    *pRva = LinkAddress;
+    return VINF_SUCCESS;
 }
 
@@ -955,6 +1062,17 @@
                                                 PRTLDRADDR pRva)
 {
-    NOREF(pMod); NOREF(iSeg); NOREF(offSeg); NOREF(pRva);
-    return VERR_NOT_IMPLEMENTED;
+    PRTLDRMODPE pModPe = (PRTLDRMODPE)pMod;
+
+    if (iSeg > pModPe->cSections)
+        return VERR_LDR_INVALID_SEG_OFFSET;
+
+    /** @todo should validate offSeg here... too lazy right now. */
+    if (iSeg == 0)
+        *pRva = offSeg;
+    else if (pModPe->paSections[iSeg].Characteristics & IMAGE_SCN_TYPE_NOLOAD)
+        return VERR_LDR_INVALID_SEG_OFFSET;
+    else
+        *pRva = offSeg + pModPe->paSections[iSeg].VirtualAddress;
+    return VINF_SUCCESS;
 }
 
@@ -964,6 +1082,8 @@
                                                 uint32_t *piSeg, PRTLDRADDR poffSeg)
 {
-    NOREF(pMod); NOREF(Rva); NOREF(piSeg); NOREF(poffSeg);
-    return VERR_NOT_IMPLEMENTED;
+    int rc = rtldrPE_LinkAddressToSegOffset(pMod, Rva, piSeg, poffSeg);
+    if (RT_FAILURE(rc))
+        rc = VERR_LDR_INVALID_RVA;
+    return rc;
 }
 
Index: /trunk/src/VBox/Runtime/include/internal/dbgmod.h
===================================================================
--- /trunk/src/VBox/Runtime/include/internal/dbgmod.h	(revision 46047)
+++ /trunk/src/VBox/Runtime/include/internal/dbgmod.h	(revision 46048)
@@ -554,5 +554,9 @@
 extern DECLHIDDEN(RTDBGMODVTDBG const)  g_rtDbgModVtDbgDwarf;
 extern DECLHIDDEN(RTDBGMODVTDBG const)  g_rtDbgModVtDbgNm;
+#ifdef RT_OS_WINDOWS
+extern DECLHIDDEN(RTDBGMODVTDBG const)  g_rtDbgModVtDbgDbgHelp;
+#endif
 extern DECLHIDDEN(RTDBGMODVTDBG const)  g_rtDbgModVtDbgDeferred;
+
 extern DECLHIDDEN(RTDBGMODVTIMG const)  g_rtDbgModVtImgLdr;
 extern DECLHIDDEN(RTDBGMODVTIMG const)  g_rtDbgModVtImgDeferred;
Index: /trunk/src/VBox/Runtime/include/internal/ldrPE.h
===================================================================
--- /trunk/src/VBox/Runtime/include/internal/ldrPE.h	(revision 46047)
+++ /trunk/src/VBox/Runtime/include/internal/ldrPE.h	(revision 46048)
@@ -145,5 +145,6 @@
 #define  IMAGE_SCN_ALIGN_4096BYTES  0x00D00000
 #define  IMAGE_SCN_ALIGN_8192BYTES  0x00E00000
-#define  IMAGE_SCN_ALIGN_MASK  0x00F00000
+#define  IMAGE_SCN_ALIGN_MASK   0x00F00000
+#define  IMAGE_SCN_ALIGN_SHIFT  20
 
 #define  IMAGE_SCN_LNK_NRELOC_OVFL  0x01000000
