Index: unk/kProfile/Makefile
===================================================================
--- /trunk/kProfile/Makefile	(revision 3525)
+++ 	(revision )
@@ -1,167 +1,0 @@
-# $Id: $
-## @file
-#
-# kProfiler Mark 2
-#
-# Copyright (c) 2006 knut st. osmundsen <bird-src-spam@anduin.net.de>
-#
-#
-# This file is part of kLIBC.
-#
-# kLIBC is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# kLIBC is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with kLIBC; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-#
-#
-
-
-DEPTH = ../../../..
-include $(PATH_KBUILD)/header.kmk
-
-#LIBRARIES   = kPrf2GC kPrf2R0
-DLLS        = kPrf2
-PROGRAMS    = kPrf2Read tst
-
-
-#
-# Our template.
-#
-TEMPLATE_kPrf2 = kProfiler Template
-TEMPLATE_kPrf2_TOOL             = GCC3
-TEMPLATE_kPrf2_TOOL.os2         = GCC3OMF
-TEMPLATE_kPrf2_TOOL.win32       = VCC70
-TEMPLATE_kPrf2_ASTOOL           = NASM
-
-TEMPLATE_kPrf2_DEFS.freebsd     = __FREEBSD__
-TEMPLATE_kPrf2_DEFS.l4          = __L4__
-TEMPLATE_kPrf2_DEFS.linux       = __LINUX__
-TEMPLATE_kPrf2_DEFS.os2         = __OS2__
-TEMPLATE_kPrf2_DEFS.win32       = __WIN32__
-TEMPLATE_kPrf2_DEFS.win64       = __WIN64__
-
-TEMPLATE_kPrf2_CXXFLAGS.freebsd = -g
-TEMPLATE_kPrf2_CXXFLAGS.l4      = -g
-TEMPLATE_kPrf2_CXXFLAGS.linux   = -g
-TEMPLATE_kPrf2_CXXFLAGS.os2     = -g
-TEMPLATE_kPrf2_CXXFLAGS.win32   = -Zi -Zl -MD -W3 -GF -GR-
-ifneq ($(BUILD_TYPE),debug)
-TEMPLATE_kPrf2_CXXFLAGS.freebsd+= -O3
-TEMPLATE_kPrf2_CXXFLAGS.l4     += -O3
-TEMPLATE_kPrf2_CXXFLAGS.linux  += -O3
-TEMPLATE_kPrf2_CXXFLAGS.os2    += -O3
-TEMPLATE_kPrf2_CXXFLAGS.win32  += -O2xtg -Oi -Ob2
-endif
-TEMPLATE_kPrf2_CXXFLAGS.win64   = $(TEMPLATE_kPrf2_CXXFLAGS.win32)
-
-TEMPLATE_kPrf2_ASFLAGS.freebsd  = -f elf32 -g
-TEMPLATE_kPrf2_ASFLAGS.l4       = -f elf32 -g
-TEMPLATE_kPrf2_ASFLAGS.linux    = -f elf32 -g
-TEMPLATE_kPrf2_ASFLAGS.os2      = -f omf
-TEMPLATE_kPrf2_ASFLAGS.win32    = -f win32 -g
-
-TEMPLATE_kPrf2_INCS.win32  	    = \
-	$(PATH_DEV)/x86.win32/vcc70/include \
-	$(PATH_DEV)/x86.win32/sdk200209/include
-
-TEMPLATE_kPrf2_LDFLAGS.freebsd  = -g
-TEMPLATE_kPrf2_LDFLAGS.l4       = -g
-TEMPLATE_kPrf2_LDFLAGS.linux    = -g
-TEMPLATE_kPrf2_LDFLAGS.os2      = -g
-TEMPLATE_kPrf2_LDFLAGS.win32    = /DEBUG
-TEMPLATE_kPrf2_LDFLAGS.win64    = /DEBUG
-
-TEMPLATE_kPrf2_LIBS.freebsd     =
-TEMPLATE_kPrf2_LIBS.l4          =
-TEMPLATE_kPrf2_LIBS.linux       =
-TEMPLATE_kPrf2_LIBS.os2         =
-TEMPLATE_kPrf2_LIBS.win32       = \
-	$(PATH_TOOL_VCC70_LIB)/msvcrt.lib \
-	$(PATH_TOOL_VCC70_LIB)/msvcprt.lib \
-	$(PATH_TOOL_VCC70_LIB)/oldnames.lib \
-	$(PATH_DEV)/x86.win32/sdk200209/lib/Kernel32.Lib \
-	$(PATH_DEV)/x86.win32/sdk200209/lib/psapi.Lib
-
-
-#
-# kPrf2 - The profiler module.
-#
-kPrf2_TEMPLATE      = kPrf2
-kPrf2_DEFS.x86      = KPRF_BITS=32
-kPrf2_DEFS.amd64    = KPRF_BITS=64
-
-kPrf2_SOURCES       = \
-	kProfileR3.cpp
-#	kProfileGC.cpp
-#	kProfileR0.cpp
-
-kPrf2_SOURCES.win32 = \
-	dllmain-win32.cpp \
-	kPrf2-win32.def \
-	prfx86msc.asm
-prfx86msc.asm_DEFS.win32 = \
-	KPRF_ENTER=_KPrfEnter \
-	KPRF_LEAVE=_KPrfLeave
-
-
-
-#
-# kPrf2Read - The read & producer of statistics.
-#
-kPrf2Read_TEMPLATE = kPrf2
-kPrf2Read_INCS = \
-	$(PATH_CURRENT)/../include \
-	$(PATH_ROOT)/include
-kPrf2Read_DEFS = IN_RING3 IN_RT_R3
-kPrf2Read_SOURCES  = \
-	kPrf2Read.cpp \
-	dbgmodule.cpp \
-	dbgline.cpp \
-	dbgsymbol.cpp
-ifeq ($(filter-out win32 win64,$(BUILD_TARGET)),)
-kPrf2Read_SOURCES += dbgModPE-win32.cpp
-else
-kPrf2Read_SOURCES += dbgModPE-generic.cpp
-endif
-kPrf2Read_LIBS  = \
-	$(LIB_RUNTIME)
-kPrf2Read_LIBS.win32 = \
-	$(PATH_DEV)/x86.win32/sdk200209/lib/uuid.Lib \
-	$(PATH_DEV)/x86.win32/sdk200209/lib/Version.Lib
-
-
-
-tst_TOOL = VCC70
-tst_CFLAGS = -GH -Gh -Zi -Zl -GR- -GX- -GF- -MD -W3 -wd4244
-tst_SOURCES = tst.c
-tst.c_CFLAGS = -Od
-tst_LDFLAGS = /DEBUG
-tst_LIBS = \
-	$(PATH_TOOL_VCC70_LIB)/msvcrt.lib \
-	$(PATH_TOOL_VCC70_LIB)/msvcprt.lib \
-	$(PATH_TOOL_VCC70_LIB)/oldnames.lib \
-	$(PATH_DEV)/x86.win32/sdk200209/lib/Kernel32.Lib \
-	$(PATH_kPrf2)/kPrf2.lib
-
-# Generate the rules
-include $(PATH_KBUILD)/footer.kmk
-
-
-#
-# Aliases for .cpp.h files so we can more easily do syntax checking from the editor.
-#
-CORE := $(wildcard *core*.cpp.h *core*.h.h)
-$(CORE:.h=.o) $(CORE:.h=.obj) : kProfileR3.o
-
-READ := $(wildcard *read*.cpp.h *read*.h.h)
-$(READ:.h=.o) $(READ:.h=.obj) : kPrf2Read.o
-
Index: /trunk/kProfile/Makefile.kmk
===================================================================
--- /trunk/kProfile/Makefile.kmk	(revision 3526)
+++ /trunk/kProfile/Makefile.kmk	(revision 3526)
@@ -0,0 +1,177 @@
+# $Id: $
+## @file
+#
+# kProfiler Mark 2
+#
+# Copyright (c) 2006 knut st. osmundsen <bird-src-spam@anduin.net.de>
+#
+#
+# This file is part of kLIBC.
+#
+# kLIBC is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# kLIBC is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with kLIBC; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+#
+#
+
+DEPTH = ..
+include $(PATH_KBUILD)/header.kmk
+
+#LIBRARIES   = kPrf2GC kPrf2R0
+DLLS        = kPrf2
+PROGRAMS    = kPrf2Read
+
+
+#
+# Our template.
+#
+TEMPLATE_kPrf2 = kProfiler Template
+TEMPLATE_kPrf2_TOOL             = GCC3
+TEMPLATE_kPrf2_TOOL.os2         = GCC3OMF
+TEMPLATE_kPrf2_TOOL.win.x86     = VCC70
+TEMPLATE_kPrf2_TOOL.win.amd64   = VCC80AMD64
+TEMPLATE_kPrf2_ASTOOL           = YASM
+TEMPLATE_kPrf2_ASTOOL.os2       = NASM
+
+TEMPLATE_kPrf2_SDKS.win         = WINPSDK
+
+TEMPLATE_kPrf2_DEFS.freebsd     = KPRF_OS_FREEBSD
+TEMPLATE_kPrf2_DEFS.linux       = KPRF_OS_LINUX
+TEMPLATE_kPrf2_DEFS.os2         = KPRF_OS_OS2
+TEMPLATE_kPrf2_DEFS.win         = KPRF_OS_WINDOWS
+
+TEMPLATE_kPrf2_CXXFLAGS.freebsd = -g
+TEMPLATE_kPrf2_CXXFLAGS.linux   = -g
+TEMPLATE_kPrf2_CXXFLAGS.os2     = -g
+TEMPLATE_kPrf2_CXXFLAGS.win     = -Zi -Zl -MD -W3 -GF -GR-
+ifneq ($(BUILD_TYPE),debug)
+TEMPLATE_kPrf2_CXXFLAGS.freebsd+= -O3
+TEMPLATE_kPrf2_CXXFLAGS.linux  += -O3
+TEMPLATE_kPrf2_CXXFLAGS.os2    += -O3
+TEMPLATE_kPrf2_CXXFLAGS.win    += -O2xtg -Oi -Ob2
+endif
+
+TEMPLATE_kPrf2_ASFLAGS.freebsd  = -f elf
+TEMPLATE_kPrf2_ASFLAGS.linux    = -f elf
+TEMPLATE_kPrf2_ASFLAGS.os2      = -f omf
+TEMPLATE_kPrf2_ASFLAGS.win.x86  = -f win32 -g cv8
+TEMPLATE_kPrf2_ASFLAGS.win.amd64 = -f win64 -g cv8
+
+#TEMPLATE_kPrf2_INCS.win   	    = \
+#	$(PATH_DEV)/x86.win32/vcc70/include \
+#	$(PATH_DEV)/x86.win32/sdk200209/include
+
+TEMPLATE_kPrf2_LDFLAGS.freebsd  = -g
+TEMPLATE_kPrf2_LDFLAGS.linux    = -g
+TEMPLATE_kPrf2_LDFLAGS.os2      = -g
+TEMPLATE_kPrf2_LDFLAGS.win      = /DEBUG
+
+TEMPLATE_kPrf2_LIBS.freebsd     =
+TEMPLATE_kPrf2_LIBS.linux       =
+TEMPLATE_kPrf2_LIBS.os2         =
+TEMPLATE_kPrf2_LIBS.win        = \
+	$(PATH_SDK_WINPSDK_LIB)/psapi.Lib
+TEMPLATE_kPrf2_LIBS.win.x86     = \
+	$(PATH_TOOL_VCC70_LIB)/msvcrt.lib \
+	$(PATH_TOOL_VCC70_LIB)/msvcprt.lib \
+	$(PATH_TOOL_VCC70_LIB)/oldnames.lib
+
+
+#
+# kPrf2 - The profiler module.
+#
+kPrf2_TEMPLATE      = kPrf2
+kPrf2_DEFS.x86      = KPRF_BITS=32
+kPrf2_DEFS.amd64    = KPRF_BITS=64
+
+kPrf2_SOURCES       = \
+	kProfileR3.cpp
+#	kProfileGC.cpp
+#	kProfileR0.cpp
+
+kPrf2_SOURCES.win = \
+	dllmain-win.cpp \
+	prf$(BUILD_TARGET_ARCH)msc.asm \
+	kPrf2-win-$(BUILD_TARGET_ARCH).def
+prfx86msc.asm_DEFS.win.x86 = \
+	KPRF_ENTER=_KPrfEnter \
+	KPRF_LEAVE=_KPrfLeave
+
+
+
+#
+# kPrf2Read - The read & producer of statistics.
+#
+kPrf2Read_TEMPLATE = kPrf2
+kPrf2Read_SOURCES  = \
+	kPrf2Read.cpp
+
+# kDbg stuff
+KDBG_ROOT ?= $(PATH_CURRENT)/../kProfile
+kPrf2Read_INCS += $(KDBG_ROOT)
+kPrf2Read_SOURCES += \
+	dbgmodule.cpp \
+	dbgline.cpp \
+	dbgsymbol.cpp
+ifeq ($(BUILD_TARGET),win)
+kPrf2Read_SOURCES.win += dbgModPE-win.cpp
+else
+kPrf2Read_SOURCES += dbgModPE-generic.cpp
+endif
+
+# kLdr stuff
+KLDR_ROOT ?= $(PATH_CURRENT)/../kLdr
+kPrf2Read_INCS += $(KLDR_ROOT)
+
+# IPRT stuff
+VBOX_ROOT ?= y:/coding/vbox/svn/trunk
+kPrf2Read_INCS += $(VBOX_ROOT)/include
+kPrf2Read_DEFS += IN_RING3 IN_RT_R3 KDBG_USE_IPRT KCOMMON_ALREADY_INCLUDED_STD_TYPES
+ifeq ($(BUILD_TARGET),win)
+kPrf2Read_LIBS = \
+	$(VBOX_ROOT)/out/$(BUILD_TARGET).$(BUILD_TARGET_ARCH)/$(BUILD_TYPE)/lib/VBoxRT$(SUFF_LIB)
+else
+kPrf2Read_LIBS = \
+	$(VBOX_ROOT)/out/$(BUILD_TARGET).$(BUILD_TARGET_ARCH)/$(BUILD_TYPE)/bin/VBoxRT$(SUFF_DLL)
+endif
+
+
+#
+# A simple testcase.
+#
+PROGRAMS.win.x86 += tst
+tst_TOOL = VCC70
+tst_SDKS = WINPSDK
+tst_CFLAGS = -GH -Gh -Zi -Zl -GR- -GX- -GF- -MD -W3 -wd4244
+tst_SOURCES = tst.c
+tst.c_CFLAGS = -Od
+tst_LDFLAGS = /DEBUG
+tst_LIBS = \
+	$(PATH_TOOL_VCC70_LIB)/msvcrt.lib \
+	$(PATH_TOOL_VCC70_LIB)/msvcprt.lib \
+	$(PATH_TOOL_VCC70_LIB)/oldnames.lib \
+	$(PATH_kPrf2)/kPrf2.lib
+
+# Generate the rules
+include $(PATH_KBUILD)/footer.kmk
+
+
+#
+# Aliases for .cpp.h files so we can more easily do syntax checking from the editor.
+#
+CORE := $(wildcard *core*.cpp.h *core*.h.h)
+$(CORE:.h=.o) $(CORE:.h=.obj) : kProfileR3.o
+
+READ := $(wildcard *read*.cpp.h *read*.h.h)
+$(READ:.h=.o) $(READ:.h=.obj) : kPrf2Read.o
+
Index: /trunk/kProfile/dbgModPE-generic.cpp
===================================================================
--- /trunk/kProfile/dbgModPE-generic.cpp	(revision 3525)
+++ /trunk/kProfile/dbgModPE-generic.cpp	(revision 3526)
@@ -37,6 +37,7 @@
 #include <iprt/thread.h>
 #include <iprt/alloca.h>
+#include "kDbgBase.h"
 #include "DBGInternal.h"
-#include "internal/ldrPE.h"
+#include "kLdrModPE.h"
 
 
@@ -276,13 +277,13 @@
      */
     IMAGE_FILE_HEADER FHdr;
-    int rc = RTFileReadAt(File, offHdr + OFFSETOF(IMAGE_NT_HEADERS32, FileHeader), &FHdr, sizeof(FHdr), NULL);
+    int rc = RTFileReadAt(File, offHdr + KDBG_OFFSETOF(IMAGE_NT_HEADERS32, FileHeader), &FHdr, sizeof(FHdr), NULL);
     AssertRCReturn(rc, rc);
 
     uint32_t cbImage;
     if (FHdr.SizeOfOptionalHeader == sizeof(IMAGE_OPTIONAL_HEADER32))
-        rc = RTFileReadAt(File, offHdr + OFFSETOF(IMAGE_NT_HEADERS32, OptionalHeader.SizeOfImage),
+        rc = RTFileReadAt(File, offHdr + KDBG_OFFSETOF(IMAGE_NT_HEADERS32, OptionalHeader.SizeOfImage),
                           &cbImage, sizeof(cbImage), NULL);
     else if (FHdr.SizeOfOptionalHeader == sizeof(IMAGE_OPTIONAL_HEADER64))
-        rc = RTFileReadAt(File, offHdr + OFFSETOF(IMAGE_NT_HEADERS64, OptionalHeader.SizeOfImage),
+        rc = RTFileReadAt(File, offHdr + KDBG_OFFSETOF(IMAGE_NT_HEADERS64, OptionalHeader.SizeOfImage),
                           &cbImage, sizeof(cbImage), NULL);
     else
@@ -293,5 +294,5 @@
      * Allocate the module and read/construct the section headers.
      */
-    PRTDBGMODPE pModPe = (PRTDBGMODPE)RTMemAlloc(OFFSETOF(RTDBGMODPE, aSections[FHdr.NumberOfSections + 2]));
+    PRTDBGMODPE pModPe = (PRTDBGMODPE)RTMemAlloc(KDBG_OFFSETOF(RTDBGMODPE, aSections[FHdr.NumberOfSections + 2]));
     AssertReturn(pModPe, VERR_NO_MEMORY);
     pModPe->Core.u32Magic   = RTDBGMOD_MAGIC;
@@ -300,5 +301,5 @@
     pModPe->cbImage         = cbImage;
     pModPe->cSections       = 1 + FHdr.NumberOfSections;
-    rc = RTFileReadAt(File, offHdr + OFFSETOF(IMAGE_NT_HEADERS32, OptionalHeader) + FHdr.SizeOfOptionalHeader,
+    rc = RTFileReadAt(File, offHdr + KDBG_OFFSETOF(IMAGE_NT_HEADERS32, OptionalHeader) + FHdr.SizeOfOptionalHeader,
                       &pModPe->aSections[1], sizeof(pModPe->aSections[0]) * FHdr.NumberOfSections, NULL);
     if (RT_SUCCESS(rc))
Index: /trunk/kProfile/dbgModPE-win.cpp
===================================================================
--- /trunk/kProfile/dbgModPE-win.cpp	(revision 3526)
+++ /trunk/kProfile/dbgModPE-win.cpp	(revision 3526)
@@ -0,0 +1,676 @@
+/* $Id: $ */
+/** @file
+ *
+ * kProfile Mark 2 - Debug Info Reader, DbgHelp Base Reader.
+ *
+ * Copyright (c) 2006 knut st. osmundsen <bird-src-spam@anduin.net.de>
+ *
+ *
+ * This file is part of kLIBC.
+ *
+ * kLIBC is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * kLIBC is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with kLIBC; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include <Windows.h>
+#define _IMAGEHLP64
+#include <DbgHelp.h>
+
+#include <iprt/file.h>
+#include <iprt/string.h>
+#include <iprt/alloc.h>
+#include <iprt/assert.h>
+#include <iprt/asm.h>
+#include <iprt/err.h>
+#include <iprt/thread.h>
+#include <iprt/alloca.h>
+#include "kDbgBase.h"
+#include "DBGInternal.h"
+
+
+//#include "internal/ldrPE.h"
+
+/*******************************************************************************
+*   Global Variables                                                           *
+*******************************************************************************/
+/** The dbghelp.dll module handle. */
+static HMODULE g_hDbgHelp = NULL;
+/** Pointer to the dbhelp.dll SymInitialize function. */
+static BOOL (WINAPI *g_pfnSymInitialize)(IN HANDLE,IN LPSTR,IN BOOL);
+/** Pointer to the dbhelp.dll SymCleanup function. */
+static BOOL (WINAPI *g_pfnSymCleanup)(IN HANDLE);
+/** Pointer to the dbhelp.dll SymSetOptions function. */
+static DWORD (WINAPI *g_pfnSymSetOptions)(IN DWORD);
+/** Pointer to the dbhelp.dll SymLoadModule64 function. */
+static DWORD64 (WINAPI *g_pfnSymLoadModule64)(IN HANDLE, IN HANDLE, IN PCSTR, IN PCSTR ModuleName, IN DWORD64, IN DWORD);
+/** Pointer to the dbhelp.dll SymFromAddr function. */
+static DWORD (WINAPI *g_pfnSymFromAddr)(IN HANDLE, IN DWORD64, OUT PDWORD64, OUT PSYMBOL_INFO);
+/** Pointer to the dbhelp.dll SymGetLineFromAddr64 function. */
+static DWORD (WINAPI *g_pfnSymGetLineFromAddr64)(IN HANDLE, IN DWORD64, OUT PDWORD64, OUT PIMAGEHLP_LINE64);
+
+
+
+/*******************************************************************************
+*   Structures and Typedefs                                                    *
+*******************************************************************************/
+/**
+ * A dbghelp based PE debug reader.
+ */
+typedef struct RTDBGMODPE
+{
+    /** The common module core. */
+    RTDBGMOD    Core;
+    /** The image base. */
+    DWORD64     ImageBase;
+    /** The "process" handle we present dbghelp. */
+    HANDLE      hSymInst;
+    /** The image size. */
+    uint32_t    cbImage;
+    /** The number of sections. (We've added the implicit header section.) */
+    int32_t     cSections;
+    /** The section headers (variable size). The first section is the
+     * implicit header section.*/
+    IMAGE_SECTION_HEADER    aSections[1];
+} RTDBGMODPE, *PRTDBGMODPE;
+
+
+/**
+ * Calcs the RVA for a segment:offset address.
+ *
+ * @returns IPRT status code.
+ *
+ * @param   pModPe      The PE debug module instance.
+ * @param   iSegment    The segment number. Special segments are dealt with as well.
+ * @param   off         The segment offset.
+ * @param   puRVA       Where to store the RVA on success.
+ */
+static int rtDbgModPeSegOffToRVA(PRTDBGMODPE pModPe, int32_t iSegment, RTUINTPTR off, uint32_t *puRVA)
+{
+    if (iSegment >= 0)
+    {
+        AssertMsgReturn(iSegment < pModPe->cSections, ("iSegment=%RX32 cSections=%RX32\n", iSegment, pModPe->cSections),
+                        VERR_DBGMOD_INVALID_ADDRESS);
+        AssertMsgReturn(off < pModPe->aSections[iSegment].Misc.VirtualSize,
+                        ("off=%RTptr VirtualSize=%RX32\n", off, pModPe->aSections[iSegment].Misc.VirtualSize),
+                        VERR_DBGMOD_INVALID_ADDRESS);
+        *puRVA = pModPe->aSections[iSegment].VirtualAddress + off;
+        return VINF_SUCCESS;
+    }
+
+    if (iSegment == RTDBGSEG_RVA)
+    {
+        AssertMsgReturn(off < pModPe->cbImage, ("off=%RTptr, cbImage=%RX32\n", off, pModPe->cbImage),
+                        VERR_DBGMOD_INVALID_ADDRESS);
+        *puRVA = off;
+        return VINF_SUCCESS;
+    }
+    AssertMsgFailedReturn(("iSegment=%RI32\n", iSegment), VERR_DBGMOD_INVALID_ADDRESS);
+}
+
+
+/**
+ * Calcs the segment:offset address for a RVA.
+ *
+ * @returns IPRT status code.
+ *
+ * @param   pModPe      The PE debug module instance.
+ * @param   uRVA        The RVA.
+ * @param   piSegment   Where to store the segment number.
+ * @param   poff        Where to store the segment offset.
+ */
+static int rtDbgModPeRVAToSegOff(PRTDBGMODPE pModPe, uint32_t uRVA, int32_t *piSegment, RTUINTPTR *poff)
+{
+    AssertMsgReturn(uRVA < pModPe->cbImage, ("uRVA=%RX32, cbImage=%RX32\n", uRVA, pModPe->cbImage),
+                    VERR_DBGMOD_INVALID_ADDRESS);
+    for (int32_t iSegment = 0; iSegment < pModPe->cSections; iSegment++)
+    {
+        /** @todo should probably be less strict about address in the alignment gaps. */
+        uint32_t off = uRVA - pModPe->aSections[iSegment].VirtualAddress;
+        if (off < pModPe->aSections[iSegment].Misc.VirtualSize)
+        {
+            *poff = off;
+            *piSegment = iSegment;
+            return VINF_SUCCESS;
+        }
+    }
+    AssertMsgFailedReturn(("uRVA=%RX32\n", uRVA), VERR_DBGMOD_INVALID_ADDRESS);
+}
+
+
+/**
+ * @copydoc RTDBGMODOPS::pfnQueryLine
+ */
+static DECLCALLBACK(int) rtDbgModPEQueryLine(PRTDBGMOD pMod, int32_t iSegment, RTUINTPTR off, PRTDBGLINE pLine)
+{
+    PRTDBGMODPE pModPe = (PRTDBGMODPE)pMod;
+
+    /*
+     * Translate the address to an RVA.
+     */
+    uint32_t uRVA;
+    int rc = rtDbgModPeSegOffToRVA(pModPe, iSegment, off, &uRVA);
+    if (RT_SUCCESS(rc))
+    {
+        DWORD64 off;
+        IMAGEHLP_LINE64 Line;
+        Line.SizeOfStruct = sizeof(Line);
+        if (g_pfnSymGetLineFromAddr64(pModPe->hSymInst, pModPe->ImageBase + uRVA, &off, &Line))
+        {
+            pLine->RVA = (RTUINTPTR)(Line.Address - pModPe->ImageBase);
+            rc = rtDbgModPeRVAToSegOff(pModPe, pLine->RVA, &pLine->iSegment, &pLine->offSegment);
+            pLine->iLine = Line.LineNumber;
+            pLine->cchFile = strlen(Line.FileName);
+            if (pLine->cchFile >= sizeof(pLine->szFile))
+                pLine->cchFile = sizeof(pLine->szFile) - 1;
+            memcpy(pLine->szFile, Line.FileName, pLine->cchFile + 1);
+        }
+        else
+        {
+            DWORD Err = GetLastError();
+            rc = RTErrConvertFromWin32(Err);
+        }
+    }
+    return rc;
+}
+
+
+/**
+ * @copydoc RTDBGMODOPS::pfnQuerySymbol
+ */
+static DECLCALLBACK(int) rtDbgModPEQuerySymbol(PRTDBGMOD pMod, int32_t iSegment, RTUINTPTR off, PRTDBGSYMBOL pSym)
+{
+    PRTDBGMODPE pModPe = (PRTDBGMODPE)pMod;
+
+    /*
+     * Translate the address to an RVA.
+     */
+    uint32_t uRVA;
+    int rc = rtDbgModPeSegOffToRVA(pModPe, iSegment, off, &uRVA);
+    if (RT_SUCCESS(rc))
+    {
+        DWORD64 off;
+        union
+        {
+            SYMBOL_INFO Sym;
+            char        achBuffer[sizeof(SYMBOL_INFO) + RTDBG_SYMBOL_MAX];
+        } Buf;
+        Buf.Sym.SizeOfStruct = sizeof(SYMBOL_INFO);
+        Buf.Sym.MaxNameLen = RTDBG_SYMBOL_MAX;
+        if (g_pfnSymFromAddr(pModPe->hSymInst, pModPe->ImageBase + uRVA, &off, &Buf.Sym))
+        {
+            pSym->cb     = Buf.Sym.Size;
+            pSym->fFlags = 0;
+            if (Buf.Sym.Flags & SYMFLAG_FUNCTION)
+                pSym->fFlags |= RTDBGSYM_FLAGS_CODE;
+            else if (Buf.Sym.Flags & SYMFLAG_CONSTANT)
+                pSym->fFlags |= RTDBGSYM_FLAGS_ABS; /** @todo SYMFLAG_CONSTANT must be tested - documentation is too brief to say what is really meant here.*/
+            else
+                pSym->fFlags |= RTDBGSYM_FLAGS_DATA;
+            if (Buf.Sym.Flags & SYMFLAG_EXPORT)
+                pSym->fFlags |= RTDBGSYM_FLAGS_EXPORTED;
+            if ((Buf.Sym.Flags & (SYMFLAG_VALUEPRESENT | SYMFLAG_CONSTANT)) == (SYMFLAG_VALUEPRESENT | SYMFLAG_CONSTANT))
+            {
+                pSym->iSegment   = RTDBGSEG_ABS;
+                pSym->offSegment = (RTUINTPTR)Buf.Sym.Value;
+                pSym->RVA        = (RTUINTPTR)Buf.Sym.Value;
+            }
+            else
+            {
+                pSym->RVA        = (RTUINTPTR)(Buf.Sym.Address - pModPe->ImageBase);
+                rc = rtDbgModPeRVAToSegOff(pModPe, pSym->RVA, &pSym->iSegment, &pSym->offSegment);
+            }
+            pSym->cchName = (uint16_t)Buf.Sym.NameLen;
+            if (pSym->cchName >= sizeof(pSym->szName))
+                pSym->cchName = sizeof(pSym->szName) - 1;
+            memcpy(pSym->szName, Buf.Sym.Name, Buf.Sym.NameLen);
+            pSym->szName[Buf.Sym.NameLen] = '\0';
+        }
+        else
+        {
+            DWORD Err = GetLastError();
+            rc = RTErrConvertFromWin32(Err);
+        }
+    }
+    return rc;
+}
+
+
+/**
+ * @copydoc RTDBGMODOPS::pfnClose
+ */
+static DECLCALLBACK(int) rtDbgModPEClose(PRTDBGMOD pMod)
+{
+    PRTDBGMODPE pModPe = (PRTDBGMODPE)pMod;
+
+    if (g_pfnSymCleanup(pModPe->hSymInst))
+        return VINF_SUCCESS;
+
+    DWORD Err = GetLastError();
+    int rc = RTErrConvertFromWin32(Err);
+    AssertMsgFailed(("SymInitialize failed: Err=%d rc=%Rrc\n", Err, rc));
+    return rc;
+}
+
+
+/**
+ * Methods for a PE module.
+ */
+static const RTDBGMODOPS g_rtDbgModPEOps =
+{
+    "PE (dbghelp)",
+    rtDbgModPEClose,
+    rtDbgModPEQuerySymbol,
+    rtDbgModPEQueryLine
+};
+
+
+/**
+ * Checks if the specified dbghelp.dll is usable.
+ *
+ * @returns IPRT status code.
+ *
+ * @param   pszPath     the path to the dbghelp.dll.
+ */
+static int rtDbgModPETryDbgHelp(const char *pszPath, uint32_t *pu32FileVersionMS, uint32_t *pu32FileVersionLS)
+{
+    int rc;
+    DWORD dwHandle = 0;
+    DWORD cb = GetFileVersionInfoSize(pszPath, &dwHandle);
+    if (cb > 0)
+    {
+        void *pvBuf = alloca(cb);
+        if (GetFileVersionInfo(pszPath, dwHandle, cb, pvBuf))
+        {
+            UINT cbValue = 0;
+            VS_FIXEDFILEINFO *pFileInfo;
+            if (VerQueryValue(pvBuf, "\\", (void **)&pFileInfo, &cbValue))
+            {
+                if (    *pu32FileVersionMS < pFileInfo->dwFileVersionMS
+                    ||  (   *pu32FileVersionMS == pFileInfo->dwFileVersionMS
+                         && *pu32FileVersionLS  > pFileInfo->dwFileVersionLS))
+                {
+                    *pu32FileVersionMS = pFileInfo->dwFileVersionMS;
+                    *pu32FileVersionLS = pFileInfo->dwFileVersionLS;
+                }
+                if (pFileInfo->dwFileVersionMS >= 0x60004)
+                    rc = VINF_SUCCESS;
+                else
+                    rc = VERR_VERSION_MISMATCH;
+            }
+            else
+                rc = VERR_GENERAL_FAILURE;
+        }
+        else
+            rc = RTErrConvertFromWin32(GetLastError());
+    }
+    else
+        rc = RTErrConvertFromWin32(GetLastError());
+    return rc;
+}
+
+
+/**
+ * Find the dbghelp.dll
+ */
+static int rtDbgModPEFindDbgHelp(char *pszPath, size_t cchPath)
+{
+    /*
+     * Try the current directory.
+     */
+    uint32_t FileVersionMS = 0;
+    uint32_t FileVersionLS = 0;
+    int rc = VERR_GENERAL_FAILURE;
+    static char s_szDbgHelp[] = "\\dbghelp.dll";
+    if (GetCurrentDirectory(cchPath - sizeof(s_szDbgHelp) + 1, pszPath))
+    {
+        strcat(pszPath, s_szDbgHelp);
+        int rc2 = rtDbgModPETryDbgHelp(pszPath, &FileVersionMS, &FileVersionLS);
+        if (RT_SUCCESS(rc2))
+            return rc2;
+        if (rc != VERR_VERSION_MISMATCH)
+            rc = rc2;
+    }
+
+    /*
+     * Try the application directory.
+     */
+    if (GetModuleFileName(NULL, pszPath, cchPath - sizeof(s_szDbgHelp) + 1))
+    {
+        strcat(strrchr(pszPath, '\\'), s_szDbgHelp);
+        int rc2 = rtDbgModPETryDbgHelp(pszPath, &FileVersionMS, &FileVersionLS);
+        if (RT_SUCCESS(rc))
+            return rc2;
+        if (rc != VERR_VERSION_MISMATCH)
+            rc = rc2;
+    }
+
+    /*
+     * Try the windows directory.
+     */
+    if (GetSystemDirectory(pszPath, cchPath - sizeof(s_szDbgHelp) + 1))
+    {
+        strcat(pszPath, s_szDbgHelp);
+        int rc2 = rtDbgModPETryDbgHelp(pszPath, &FileVersionMS, &FileVersionLS);
+        if (RT_SUCCESS(rc2))
+            return rc2;
+        if (rc != VERR_VERSION_MISMATCH)
+            rc = rc2;
+    }
+
+    /*
+     * Try the windows directory.
+     */
+    if (GetWindowsDirectory(pszPath, cchPath - sizeof(s_szDbgHelp) + 1))
+    {
+        strcat(pszPath, s_szDbgHelp);
+        int rc2 = rtDbgModPETryDbgHelp(pszPath, &FileVersionMS, &FileVersionLS);
+        if (RT_SUCCESS(rc2))
+            return rc2;
+        if (rc != VERR_VERSION_MISMATCH)
+            rc = rc2;
+    }
+
+    /*
+     * Try the path.
+     */
+    /** @todo find the actual path specs, I'm probably not doing this 100% correctly here. */
+    DWORD cb = GetEnvironmentVariable("PATH", NULL, 0) + 64;
+    char *pszSearchPath = (char *) alloca(cb);
+    if (GetEnvironmentVariable("PATH", pszSearchPath, cb) < cb)
+    {
+        char *psz = pszSearchPath;
+        while (*psz)
+        {
+            /* find the end of the path. */
+            char *pszEnd = strchr(psz, ';');
+            if (!pszEnd)
+                pszEnd = strchr(psz, '\0');
+            if (pszEnd != psz)
+            {
+                /* construct filename and try it out */
+                memcpy(pszPath, psz, pszEnd - psz);
+                memcpy(&pszPath[pszEnd - psz], s_szDbgHelp, sizeof(s_szDbgHelp));
+                int rc2 = rtDbgModPETryDbgHelp(pszPath, &FileVersionMS, &FileVersionLS);
+                if (RT_SUCCESS(rc2))
+                    return rc2;
+                if (rc != VERR_VERSION_MISMATCH)
+                    rc = rc2;
+            }
+
+            /* next path */
+            if (!*pszEnd)
+                break;
+            psz = pszEnd + 1;
+        }
+    }
+
+    if (rc == VERR_VERSION_MISMATCH)
+        AssertMsgFailed(("dbghelp.dll found, but it was ancient! The highest file version found was 0x%08x'%08x.\n"
+                         "This program require a file version of at least 0x00060004'00000000. Please download\n"
+                         "the latest windbg and use the dbghelp.dll from that package. Just put it somewhere in\n"
+                         "the PATH and we'll find it.\n", FileVersionMS, FileVersionLS));
+    else
+        AssertMsgFailed(("dbghelp.dll was not found! Download the latest windbg and use the dbghelp.dll\n"
+                         "from that package - just put it somewhere in the PATH and we'll find it.\n"));
+    return rc;
+}
+
+
+/**
+ * Loads the dbghelp.dll, check that it's the right version, and
+ * resolves all the symbols we need.
+ *
+ * @returns IPRT status code.
+ */
+static int rtDbgModPELoadDbgHelp(void)
+{
+    if (g_hDbgHelp)
+        return VINF_SUCCESS;
+
+    /* primitive locking - make some useful API for this kind of spinning! */
+    static volatile uint32_t s_u32Lock = 0;
+    while (!ASMAtomicCmpXchgU32(&s_u32Lock, 1, 0))
+        while (s_u32Lock)
+            RTThreadYield();
+    if (g_hDbgHelp)
+    {
+        ASMAtomicXchgU32(&s_u32Lock, 0);
+        return VINF_SUCCESS;
+    }
+
+    /*
+     * Load it - try current dir first.
+     */
+    char szPath[260];
+    int rc = rtDbgModPEFindDbgHelp(szPath, sizeof(szPath));
+    if (RT_FAILURE(rc))
+    {
+        ASMAtomicXchgU32(&s_u32Lock, 0);
+        return rc;
+    }
+
+    HMODULE hmod = LoadLibraryEx(szPath, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
+    if (!hmod)
+    {
+        DWORD Err = GetLastError();
+        int rc = RTErrConvertFromWin32(Err);
+        AssertMsgFailedReturn(("Failed to load '%s', Err=%d rc=%Rrc\n", szPath, Err, rc), rc);
+    }
+
+    /*
+     * Check the API version (too).
+     */
+    LPAPI_VERSION (WINAPI *pfnImagehlpApiVersion)(VOID);
+    FARPROC *ppfn = (FARPROC *)&pfnImagehlpApiVersion;
+    *ppfn = GetProcAddress(hmod, "ImagehlpApiVersion");
+    if (*ppfn)
+    {
+        LPAPI_VERSION pVersion = pfnImagehlpApiVersion();
+        if (    pVersion
+            &&  (   pVersion->MajorVersion > 4
+                 || (pVersion->MajorVersion == 4 && pVersion->MinorVersion > 0)
+                 || (pVersion->MajorVersion == 4 && pVersion->MinorVersion == 0 && pVersion->Revision >= 5)
+                )
+           )
+        {
+            /*
+             * Resolve the entrypoints we need.
+             */
+            static const struct
+            {
+                const char *pszName;
+                FARPROC *ppfn;
+            }   s_aFunctions[] =
+            {
+                { "SymInitialize",      (FARPROC *)&g_pfnSymInitialize },
+                { "SymCleanup",         (FARPROC *)&g_pfnSymCleanup },
+                { "SymSetOptions",      (FARPROC *)&g_pfnSymSetOptions },
+                { "SymLoadModule64",    (FARPROC *)&g_pfnSymLoadModule64 },
+                { "SymFromAddr",        (FARPROC *)&g_pfnSymFromAddr },
+                { "SymFromAddr",        (FARPROC *)&g_pfnSymFromAddr },
+                { "SymGetLineFromAddr64", (FARPROC *)&g_pfnSymGetLineFromAddr64 },
+            };
+            for (unsigned i = 0; i < ELEMENTS(s_aFunctions); i++)
+            {
+                FARPROC pfn = GetProcAddress(hmod, s_aFunctions[i].pszName);
+                if (!pfn)
+                {
+                    DWORD Err = GetLastError();
+                    rc = RTErrConvertFromWin32(Err);
+                    AssertMsgFailed(("Failed to resolve %s in dbghelp, Err=%d rc=%Rrc\n",
+                                     s_aFunctions[i].pszName, Err, rc));
+                    break;
+                }
+                *s_aFunctions[i].ppfn = pfn;
+            }
+            if (RT_SUCCESS(rc))
+            {
+                ASMAtomicXchgSize(&g_hDbgHelp, hmod);
+                ASMAtomicXchgU32(&s_u32Lock, 0);
+                return VINF_SUCCESS;
+            }
+        }
+        else
+        {
+            rc = VERR_VERSION_MISMATCH;
+            AssertMsgFailed(("ImagehlpApiVersion -> %p and MajorVersion=%d.\n", pVersion, pVersion ? pVersion->MajorVersion : 0));
+        }
+    }
+    else
+    {
+        DWORD Err = GetLastError();
+        rc = RTErrConvertFromWin32(Err);
+        AssertMsgFailed(("Failed to resolve ImagehlpApiVersionEx in dbghelp, Err=%d rc=%Rrc\n", Err, rc));
+    }
+    FreeLibrary(hmod);
+    ASMAtomicXchgU32(&s_u32Lock, 0);
+    return rc;
+}
+
+
+/**
+ * Opens the debug info for a PE image using the windows dbghelp library.
+ *
+ * @returns IPRT status code.
+ *
+ * @param   File                The handle to the module.
+ * @param   offHdr              The offset of the PE header.
+ * @param   pszModulePath       The path to the module.
+ * @param   ppDbgMod            Where to store the module handle.
+ *
+ */
+int rtDbgModPEOpen(RTFILE File, RTFOFF offHdr, const char *pszModulePath, PRTDBGMOD *ppDbgMod)
+{
+    /*
+     * We need to read the section headers and get the image size.
+     */
+    IMAGE_FILE_HEADER FHdr;
+    int rc = RTFileReadAt(File, offHdr + KDBG_OFFSETOF(IMAGE_NT_HEADERS32, FileHeader), &FHdr, sizeof(FHdr), NULL);
+    AssertRCReturn(rc, rc);
+
+    uint32_t cbImage;
+    if (FHdr.SizeOfOptionalHeader == sizeof(IMAGE_OPTIONAL_HEADER32))
+        rc = RTFileReadAt(File, offHdr + KDBG_OFFSETOF(IMAGE_NT_HEADERS32, OptionalHeader.SizeOfImage),
+                          &cbImage, sizeof(cbImage), NULL);
+    else if (FHdr.SizeOfOptionalHeader == sizeof(IMAGE_OPTIONAL_HEADER64))
+        rc = RTFileReadAt(File, offHdr + KDBG_OFFSETOF(IMAGE_NT_HEADERS64, OptionalHeader.SizeOfImage),
+                          &cbImage, sizeof(cbImage), NULL);
+    else
+        AssertFailedReturn(VERR_BAD_EXE_FORMAT);
+    AssertRCReturn(rc, rc);
+
+    /*
+     * Load dbghelp.dll.
+     */
+    rc = rtDbgModPELoadDbgHelp();
+    if (RT_FAILURE(rc))
+        return rc;
+
+    /*
+     * Allocate the module and read/construct the section headers.
+     */
+    PRTDBGMODPE pModPe = (PRTDBGMODPE)RTMemAlloc(KDBG_OFFSETOF(RTDBGMODPE, aSections[FHdr.NumberOfSections + 2]));
+    AssertReturn(pModPe, VERR_NO_MEMORY);
+    pModPe->Core.u32Magic   = RTDBGMOD_MAGIC;
+    pModPe->Core.pOps       = &g_rtDbgModPEOps;
+    pModPe->Core.File       = File;
+    pModPe->cbImage         = cbImage;
+    pModPe->cSections       = 1 + FHdr.NumberOfSections;
+    rc = RTFileReadAt(File, offHdr + KDBG_OFFSETOF(IMAGE_NT_HEADERS32, OptionalHeader) + FHdr.SizeOfOptionalHeader,
+                      &pModPe->aSections[1], sizeof(pModPe->aSections[0]) * FHdr.NumberOfSections, NULL);
+    if (RT_SUCCESS(rc))
+    {
+        PIMAGE_SECTION_HEADER pSH = &pModPe->aSections[0];
+        memcpy(pSH->Name, "headers", sizeof(pSH->Name));
+        pSH->Misc.VirtualSize       = pModPe->aSections[1].VirtualAddress;
+        pSH->VirtualAddress         = 0;
+        pSH->SizeOfRawData          = pSH->Misc.VirtualSize;
+        pSH->PointerToRawData       = 0;
+        pSH->PointerToRelocations   = 0;
+        pSH->PointerToLinenumbers   = 0;
+        pSH->NumberOfRelocations    = 0;
+        pSH->NumberOfLinenumbers    = 0;
+        pSH->Characteristics        = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_ALIGN_4BYTES | IMAGE_SCN_MEM_READ;
+
+        uint32_t uTheEnd = pModPe->aSections[FHdr.NumberOfSections].VirtualAddress
+                         + pModPe->aSections[FHdr.NumberOfSections].Misc.VirtualSize;
+        if (uTheEnd < cbImage)
+        {
+            pSH = &pModPe->aSections[pModPe->cSections++];
+            memcpy(pSH->Name, "tail\0\0\0", sizeof(pSH->Name));
+            pSH->Misc.VirtualSize       = cbImage - uTheEnd;
+            pSH->VirtualAddress         = uTheEnd;
+            pSH->SizeOfRawData          = pSH->Misc.VirtualSize;
+            pSH->PointerToRawData       = 0;
+            pSH->PointerToRelocations   = 0;
+            pSH->PointerToLinenumbers   = 0;
+            pSH->NumberOfRelocations    = 0;
+            pSH->NumberOfLinenumbers    = 0;
+            pSH->Characteristics        = IMAGE_SCN_CNT_UNINITIALIZED_DATA | IMAGE_SCN_ALIGN_1BYTES | IMAGE_SCN_MEM_READ;
+        }
+
+        /*
+         * Find a new dbghelp handle.
+         *
+         * We assume 4GB of handles outlast most debugging sessions, or in anyways that
+         * when we start reusing handles they are no longer in use. :-)
+         */
+        static volatile uint32_t s_u32LastHandle = 1;
+        HANDLE hSymInst = (HANDLE)ASMAtomicIncU32(&s_u32LastHandle);
+        while (     hSymInst == INVALID_HANDLE_VALUE
+               ||   hSymInst == (HANDLE)0
+               ||   hSymInst == GetCurrentProcess())
+            hSymInst = (HANDLE)ASMAtomicIncU32(&s_u32LastHandle);
+
+        /*
+         * Initialize dbghelp and try open the specified module.
+         */
+        if (g_pfnSymInitialize(hSymInst, NULL, FALSE))
+        {
+            g_pfnSymSetOptions(SYMOPT_LOAD_LINES | SYMOPT_AUTO_PUBLICS | SYMOPT_ALLOW_ABSOLUTE_SYMBOLS);
+
+            RTFileSeek(File, 0, RTFILE_SEEK_BEGIN, NULL); /* don't know if this is required or not... */
+            DWORD64 ImageBase = g_pfnSymLoadModule64(hSymInst, (HANDLE)File, pszModulePath, NULL, 0x00400000, 0);
+            if (ImageBase)
+            {
+                pModPe->hSymInst    = hSymInst;
+                pModPe->ImageBase   = ImageBase;
+                *ppDbgMod = &pModPe->Core;
+                return rc;
+            }
+
+            DWORD Err = GetLastError();
+            rc = RTErrConvertFromWin32(Err);
+            AssertMsgFailed(("SymLoadModule64 failed: Err=%d rc=%Rrc\n", Err, rc));
+            g_pfnSymCleanup(hSymInst);
+        }
+        else
+        {
+            DWORD Err = GetLastError();
+            rc = RTErrConvertFromWin32(Err);
+            AssertMsgFailed(("SymInitialize failed: Err=%d rc=%Rrc\n", Err, rc));
+        }
+    }
+    else
+        AssertRC(rc);
+
+    RTMemFree(pModPe);
+    return rc;
+}
+
Index: unk/kProfile/dbgModPE-win32.cpp
===================================================================
--- /trunk/kProfile/dbgModPE-win32.cpp	(revision 3525)
+++ 	(revision )
@@ -1,675 +1,0 @@
-/* $Id: $ */
-/** @file
- *
- * kProfile Mark 2 - Debug Info Reader, DbgHelp Base Reader.
- *
- * Copyright (c) 2006 knut st. osmundsen <bird-src-spam@anduin.net.de>
- *
- *
- * This file is part of kLIBC.
- *
- * kLIBC is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * kLIBC is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with kLIBC; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- */
-
-
-/*******************************************************************************
-*   Header Files                                                               *
-*******************************************************************************/
-#include <Windows.h>
-#define _IMAGEHLP64
-#include <DbgHelp.h>
-
-#include <iprt/file.h>
-#include <iprt/string.h>
-#include <iprt/alloc.h>
-#include <iprt/assert.h>
-#include <iprt/asm.h>
-#include <iprt/err.h>
-#include <iprt/thread.h>
-#include <iprt/alloca.h>
-#include "DBGInternal.h"
-
-
-//#include "internal/ldrPE.h"
-
-/*******************************************************************************
-*   Global Variables                                                           *
-*******************************************************************************/
-/** The dbghelp.dll module handle. */
-static HMODULE g_hDbgHelp = NULL;
-/** Pointer to the dbhelp.dll SymInitialize function. */
-static BOOL (WINAPI *g_pfnSymInitialize)(IN HANDLE,IN LPSTR,IN BOOL);
-/** Pointer to the dbhelp.dll SymCleanup function. */
-static BOOL (WINAPI *g_pfnSymCleanup)(IN HANDLE);
-/** Pointer to the dbhelp.dll SymSetOptions function. */
-static DWORD (WINAPI *g_pfnSymSetOptions)(IN DWORD);
-/** Pointer to the dbhelp.dll SymLoadModule64 function. */
-static DWORD64 (WINAPI *g_pfnSymLoadModule64)(IN HANDLE, IN HANDLE, IN PCSTR, IN PCSTR ModuleName, IN DWORD64, IN DWORD);
-/** Pointer to the dbhelp.dll SymFromAddr function. */
-static DWORD (WINAPI *g_pfnSymFromAddr)(IN HANDLE, IN DWORD64, OUT PDWORD64, OUT PSYMBOL_INFO);
-/** Pointer to the dbhelp.dll SymGetLineFromAddr64 function. */
-static DWORD (WINAPI *g_pfnSymGetLineFromAddr64)(IN HANDLE, IN DWORD64, OUT PDWORD64, OUT PIMAGEHLP_LINE64);
-
-
-
-/*******************************************************************************
-*   Structures and Typedefs                                                    *
-*******************************************************************************/
-/**
- * A dbghelp based PE debug reader.
- */
-typedef struct RTDBGMODPE
-{
-    /** The common module core. */
-    RTDBGMOD    Core;
-    /** The image base. */
-    DWORD64     ImageBase;
-    /** The "process" handle we present dbghelp. */
-    HANDLE      hSymInst;
-    /** The image size. */
-    uint32_t    cbImage;
-    /** The number of sections. (We've added the implicit header section.) */
-    int32_t     cSections;
-    /** The section headers (variable size). The first section is the
-     * implicit header section.*/
-    IMAGE_SECTION_HEADER    aSections[1];
-} RTDBGMODPE, *PRTDBGMODPE;
-
-
-/**
- * Calcs the RVA for a segment:offset address.
- *
- * @returns IPRT status code.
- *
- * @param   pModPe      The PE debug module instance.
- * @param   iSegment    The segment number. Special segments are dealt with as well.
- * @param   off         The segment offset.
- * @param   puRVA       Where to store the RVA on success.
- */
-static int rtDbgModPeSegOffToRVA(PRTDBGMODPE pModPe, int32_t iSegment, RTUINTPTR off, uint32_t *puRVA)
-{
-    if (iSegment >= 0)
-    {
-        AssertMsgReturn(iSegment < pModPe->cSections, ("iSegment=%RX32 cSections=%RX32\n", iSegment, pModPe->cSections),
-                        VERR_DBGMOD_INVALID_ADDRESS);
-        AssertMsgReturn(off < pModPe->aSections[iSegment].Misc.VirtualSize,
-                        ("off=%RTptr VirtualSize=%RX32\n", off, pModPe->aSections[iSegment].Misc.VirtualSize),
-                        VERR_DBGMOD_INVALID_ADDRESS);
-        *puRVA = pModPe->aSections[iSegment].VirtualAddress + off;
-        return VINF_SUCCESS;
-    }
-
-    if (iSegment == RTDBGSEG_RVA)
-    {
-        AssertMsgReturn(off < pModPe->cbImage, ("off=%RTptr, cbImage=%RX32\n", off, pModPe->cbImage),
-                        VERR_DBGMOD_INVALID_ADDRESS);
-        *puRVA = off;
-        return VINF_SUCCESS;
-    }
-    AssertMsgFailedReturn(("iSegment=%RI32\n", iSegment), VERR_DBGMOD_INVALID_ADDRESS);
-}
-
-
-/**
- * Calcs the segment:offset address for a RVA.
- *
- * @returns IPRT status code.
- *
- * @param   pModPe      The PE debug module instance.
- * @param   uRVA        The RVA.
- * @param   piSegment   Where to store the segment number.
- * @param   poff        Where to store the segment offset.
- */
-static int rtDbgModPeRVAToSegOff(PRTDBGMODPE pModPe, uint32_t uRVA, int32_t *piSegment, RTUINTPTR *poff)
-{
-    AssertMsgReturn(uRVA < pModPe->cbImage, ("uRVA=%RX32, cbImage=%RX32\n", uRVA, pModPe->cbImage),
-                    VERR_DBGMOD_INVALID_ADDRESS);
-    for (int32_t iSegment = 0; iSegment < pModPe->cSections; iSegment++)
-    {
-        /** @todo should probably be less strict about address in the alignment gaps. */
-        uint32_t off = uRVA - pModPe->aSections[iSegment].VirtualAddress;
-        if (off < pModPe->aSections[iSegment].Misc.VirtualSize)
-        {
-            *poff = off;
-            *piSegment = iSegment;
-            return VINF_SUCCESS;
-        }
-    }
-    AssertMsgFailedReturn(("uRVA=%RX32\n", uRVA), VERR_DBGMOD_INVALID_ADDRESS);
-}
-
-
-/**
- * @copydoc RTDBGMODOPS::pfnQueryLine
- */
-static DECLCALLBACK(int) rtDbgModPEQueryLine(PRTDBGMOD pMod, int32_t iSegment, RTUINTPTR off, PRTDBGLINE pLine)
-{
-    PRTDBGMODPE pModPe = (PRTDBGMODPE)pMod;
-
-    /*
-     * Translate the address to an RVA.
-     */
-    uint32_t uRVA;
-    int rc = rtDbgModPeSegOffToRVA(pModPe, iSegment, off, &uRVA);
-    if (RT_SUCCESS(rc))
-    {
-        DWORD64 off;
-        IMAGEHLP_LINE64 Line;
-        Line.SizeOfStruct = sizeof(Line);
-        if (g_pfnSymGetLineFromAddr64(pModPe->hSymInst, pModPe->ImageBase + uRVA, &off, &Line))
-        {
-            pLine->RVA = (RTUINTPTR)(Line.Address - pModPe->ImageBase);
-            rc = rtDbgModPeRVAToSegOff(pModPe, pLine->RVA, &pLine->iSegment, &pLine->offSegment);
-            pLine->iLine = Line.LineNumber;
-            pLine->cchFile = strlen(Line.FileName);
-            if (pLine->cchFile >= sizeof(pLine->szFile))
-                pLine->cchFile = sizeof(pLine->szFile) - 1;
-            memcpy(pLine->szFile, Line.FileName, pLine->cchFile + 1);
-        }
-        else
-        {
-            DWORD Err = GetLastError();
-            rc = RTErrConvertFromWin32(Err);
-        }
-    }
-    return rc;
-}
-
-
-/**
- * @copydoc RTDBGMODOPS::pfnQuerySymbol
- */
-static DECLCALLBACK(int) rtDbgModPEQuerySymbol(PRTDBGMOD pMod, int32_t iSegment, RTUINTPTR off, PRTDBGSYMBOL pSym)
-{
-    PRTDBGMODPE pModPe = (PRTDBGMODPE)pMod;
-
-    /*
-     * Translate the address to an RVA.
-     */
-    uint32_t uRVA;
-    int rc = rtDbgModPeSegOffToRVA(pModPe, iSegment, off, &uRVA);
-    if (RT_SUCCESS(rc))
-    {
-        DWORD64 off;
-        union
-        {
-            SYMBOL_INFO Sym;
-            char        achBuffer[sizeof(SYMBOL_INFO) + RTDBG_SYMBOL_MAX];
-        } Buf;
-        Buf.Sym.SizeOfStruct = sizeof(SYMBOL_INFO);
-        Buf.Sym.MaxNameLen = RTDBG_SYMBOL_MAX;
-        if (g_pfnSymFromAddr(pModPe->hSymInst, pModPe->ImageBase + uRVA, &off, &Buf.Sym))
-        {
-            pSym->cb     = Buf.Sym.Size;
-            pSym->fFlags = 0;
-            if (Buf.Sym.Flags & SYMFLAG_FUNCTION)
-                pSym->fFlags |= RTDBGSYM_FLAGS_CODE;
-            else if (Buf.Sym.Flags & SYMFLAG_CONSTANT)
-                pSym->fFlags |= RTDBGSYM_FLAGS_ABS; /** @todo SYMFLAG_CONSTANT must be tested - documentation is too brief to say what is really meant here.*/
-            else
-                pSym->fFlags |= RTDBGSYM_FLAGS_DATA;
-            if (Buf.Sym.Flags & SYMFLAG_EXPORT)
-                pSym->fFlags |= RTDBGSYM_FLAGS_EXPORTED;
-            if ((Buf.Sym.Flags & (SYMFLAG_VALUEPRESENT | SYMFLAG_CONSTANT)) == (SYMFLAG_VALUEPRESENT | SYMFLAG_CONSTANT))
-            {
-                pSym->iSegment   = RTDBGSEG_ABS;
-                pSym->offSegment = (RTUINTPTR)Buf.Sym.Value;
-                pSym->RVA        = (RTUINTPTR)Buf.Sym.Value;
-            }
-            else
-            {
-                pSym->RVA        = (RTUINTPTR)(Buf.Sym.Address - pModPe->ImageBase);
-                rc = rtDbgModPeRVAToSegOff(pModPe, pSym->RVA, &pSym->iSegment, &pSym->offSegment);
-            }
-            pSym->cchName = (uint16_t)Buf.Sym.NameLen;
-            if (pSym->cchName >= sizeof(pSym->szName))
-                pSym->cchName = sizeof(pSym->szName) - 1;
-            memcpy(pSym->szName, Buf.Sym.Name, Buf.Sym.NameLen);
-            pSym->szName[Buf.Sym.NameLen] = '\0';
-        }
-        else
-        {
-            DWORD Err = GetLastError();
-            rc = RTErrConvertFromWin32(Err);
-        }
-    }
-    return rc;
-}
-
-
-/**
- * @copydoc RTDBGMODOPS::pfnClose
- */
-static DECLCALLBACK(int) rtDbgModPEClose(PRTDBGMOD pMod)
-{
-    PRTDBGMODPE pModPe = (PRTDBGMODPE)pMod;
-
-    if (g_pfnSymCleanup(pModPe->hSymInst))
-        return VINF_SUCCESS;
-
-    DWORD Err = GetLastError();
-    int rc = RTErrConvertFromWin32(Err);
-    AssertMsgFailed(("SymInitialize failed: Err=%d rc=%Rrc\n", Err, rc));
-    return rc;
-}
-
-
-/**
- * Methods for a PE module.
- */
-static const RTDBGMODOPS g_rtDbgModPEOps =
-{
-    "PE (dbghelp)",
-    rtDbgModPEClose,
-    rtDbgModPEQuerySymbol,
-    rtDbgModPEQueryLine
-};
-
-
-/**
- * Checks if the specified dbghelp.dll is usable.
- *
- * @returns IPRT status code.
- *
- * @param   pszPath     the path to the dbghelp.dll.
- */
-static int rtDbgModPETryDbgHelp(const char *pszPath, uint32_t *pu32FileVersionMS, uint32_t *pu32FileVersionLS)
-{
-    int rc;
-    DWORD dwHandle = 0;
-    DWORD cb = GetFileVersionInfoSize(pszPath, &dwHandle);
-    if (cb > 0)
-    {
-        void *pvBuf = alloca(cb);
-        if (GetFileVersionInfo(pszPath, dwHandle, cb, pvBuf))
-        {
-            UINT cbValue = 0;
-            VS_FIXEDFILEINFO *pFileInfo;
-            if (VerQueryValue(pvBuf, "\\", (void **)&pFileInfo, &cbValue))
-            {
-                if (    *pu32FileVersionMS < pFileInfo->dwFileVersionMS
-                    ||  (   *pu32FileVersionMS == pFileInfo->dwFileVersionMS
-                         && *pu32FileVersionLS  > pFileInfo->dwFileVersionLS))
-                {
-                    *pu32FileVersionMS = pFileInfo->dwFileVersionMS;
-                    *pu32FileVersionLS = pFileInfo->dwFileVersionLS;
-                }
-                if (pFileInfo->dwFileVersionMS >= 0x60004)
-                    rc = VINF_SUCCESS;
-                else
-                    rc = VERR_VERSION_MISMATCH;
-            }
-            else
-                rc = VERR_GENERAL_FAILURE;
-        }
-        else
-            rc = RTErrConvertFromWin32(GetLastError());
-    }
-    else
-        rc = RTErrConvertFromWin32(GetLastError());
-    return rc;
-}
-
-
-/**
- * Find the dbghelp.dll
- */
-static int rtDbgModPEFindDbgHelp(char *pszPath, size_t cchPath)
-{
-    /*
-     * Try the current directory.
-     */
-    uint32_t FileVersionMS = 0;
-    uint32_t FileVersionLS = 0;
-    int rc = VERR_GENERAL_FAILURE;
-    static char s_szDbgHelp[] = "\\dbghelp.dll";
-    if (GetCurrentDirectory(cchPath - sizeof(s_szDbgHelp) + 1, pszPath))
-    {
-        strcat(pszPath, s_szDbgHelp);
-        int rc2 = rtDbgModPETryDbgHelp(pszPath, &FileVersionMS, &FileVersionLS);
-        if (RT_SUCCESS(rc2))
-            return rc2;
-        if (rc != VERR_VERSION_MISMATCH)
-            rc = rc2;
-    }
-
-    /*
-     * Try the application directory.
-     */
-    if (GetModuleFileName(NULL, pszPath, cchPath - sizeof(s_szDbgHelp) + 1))
-    {
-        strcat(strrchr(pszPath, '\\'), s_szDbgHelp);
-        int rc2 = rtDbgModPETryDbgHelp(pszPath, &FileVersionMS, &FileVersionLS);
-        if (RT_SUCCESS(rc))
-            return rc2;
-        if (rc != VERR_VERSION_MISMATCH)
-            rc = rc2;
-    }
-
-    /*
-     * Try the windows directory.
-     */
-    if (GetSystemDirectory(pszPath, cchPath - sizeof(s_szDbgHelp) + 1))
-    {
-        strcat(pszPath, s_szDbgHelp);
-        int rc2 = rtDbgModPETryDbgHelp(pszPath, &FileVersionMS, &FileVersionLS);
-        if (RT_SUCCESS(rc2))
-            return rc2;
-        if (rc != VERR_VERSION_MISMATCH)
-            rc = rc2;
-    }
-
-    /*
-     * Try the windows directory.
-     */
-    if (GetWindowsDirectory(pszPath, cchPath - sizeof(s_szDbgHelp) + 1))
-    {
-        strcat(pszPath, s_szDbgHelp);
-        int rc2 = rtDbgModPETryDbgHelp(pszPath, &FileVersionMS, &FileVersionLS);
-        if (RT_SUCCESS(rc2))
-            return rc2;
-        if (rc != VERR_VERSION_MISMATCH)
-            rc = rc2;
-    }
-
-    /*
-     * Try the path.
-     */
-    /** @todo find the actual path specs, I'm probably not doing this 100% correctly here. */
-    DWORD cb = GetEnvironmentVariable("PATH", NULL, 0) + 64;
-    char *pszSearchPath = (char *) alloca(cb);
-    if (GetEnvironmentVariable("PATH", pszSearchPath, cb) < cb)
-    {
-        char *psz = pszSearchPath;
-        while (*psz)
-        {
-            /* find the end of the path. */
-            char *pszEnd = strchr(psz, ';');
-            if (!pszEnd)
-                pszEnd = strchr(psz, '\0');
-            if (pszEnd != psz)
-            {
-                /* construct filename and try it out */
-                memcpy(pszPath, psz, pszEnd - psz);
-                memcpy(&pszPath[pszEnd - psz], s_szDbgHelp, sizeof(s_szDbgHelp));
-                int rc2 = rtDbgModPETryDbgHelp(pszPath, &FileVersionMS, &FileVersionLS);
-                if (RT_SUCCESS(rc2))
-                    return rc2;
-                if (rc != VERR_VERSION_MISMATCH)
-                    rc = rc2;
-            }
-
-            /* next path */
-            if (!*pszEnd)
-                break;
-            psz = pszEnd + 1;
-        }
-    }
-
-    if (rc == VERR_VERSION_MISMATCH)
-        AssertMsgFailed(("dbghelp.dll found, but it was ancient! The highest file version found was 0x%08x'%08x.\n"
-                         "This program require a file version of at least 0x00060004'00000000. Please download\n"
-                         "the latest windbg and use the dbghelp.dll from that package. Just put it somewhere in\n"
-                         "the PATH and we'll find it.\n", FileVersionMS, FileVersionLS));
-    else
-        AssertMsgFailed(("dbghelp.dll was not found! Download the latest windbg and use the dbghelp.dll\n"
-                         "from that package - just put it somewhere in the PATH and we'll find it.\n"));
-    return rc;
-}
-
-
-/**
- * Loads the dbghelp.dll, check that it's the right version, and
- * resolves all the symbols we need.
- *
- * @returns IPRT status code.
- */
-static int rtDbgModPELoadDbgHelp(void)
-{
-    if (g_hDbgHelp)
-        return VINF_SUCCESS;
-
-    /* primitive locking - make some useful API for this kind of spinning! */
-    static volatile uint32_t s_u32Lock = 0;
-    while (!ASMAtomicCmpXchgU32(&s_u32Lock, 1, 0))
-        while (s_u32Lock)
-            RTThreadYield();
-    if (g_hDbgHelp)
-    {
-        ASMAtomicXchgU32(&s_u32Lock, 0);
-        return VINF_SUCCESS;
-    }
-
-    /*
-     * Load it - try current dir first.
-     */
-    char szPath[260];
-    int rc = rtDbgModPEFindDbgHelp(szPath, sizeof(szPath));
-    if (RT_FAILURE(rc))
-    {
-        ASMAtomicXchgU32(&s_u32Lock, 0);
-        return rc;
-    }
-
-    HMODULE hmod = LoadLibraryEx(szPath, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
-    if (!hmod)
-    {
-        DWORD Err = GetLastError();
-        int rc = RTErrConvertFromWin32(Err);
-        AssertMsgFailedReturn(("Failed to load '%s', Err=%d rc=%Rrc\n", szPath, Err, rc), rc);
-    }
-
-    /*
-     * Check the API version (too).
-     */
-    LPAPI_VERSION (WINAPI *pfnImagehlpApiVersion)(VOID);
-    FARPROC *ppfn = (FARPROC *)&pfnImagehlpApiVersion;
-    *ppfn = GetProcAddress(hmod, "ImagehlpApiVersion");
-    if (*ppfn)
-    {
-        LPAPI_VERSION pVersion = pfnImagehlpApiVersion();
-        if (    pVersion
-            &&  (   pVersion->MajorVersion > 4
-                 || (pVersion->MajorVersion == 4 && pVersion->MinorVersion > 0)
-                 || (pVersion->MajorVersion == 4 && pVersion->MinorVersion == 0 && pVersion->Revision >= 5)
-                )
-           )
-        {
-            /*
-             * Resolve the entrypoints we need.
-             */
-            static const struct
-            {
-                const char *pszName;
-                FARPROC *ppfn;
-            }   s_aFunctions[] =
-            {
-                { "SymInitialize",      (FARPROC *)&g_pfnSymInitialize },
-                { "SymCleanup",         (FARPROC *)&g_pfnSymCleanup },
-                { "SymSetOptions",      (FARPROC *)&g_pfnSymSetOptions },
-                { "SymLoadModule64",    (FARPROC *)&g_pfnSymLoadModule64 },
-                { "SymFromAddr",        (FARPROC *)&g_pfnSymFromAddr },
-                { "SymFromAddr",        (FARPROC *)&g_pfnSymFromAddr },
-                { "SymGetLineFromAddr64", (FARPROC *)&g_pfnSymGetLineFromAddr64 },
-            };
-            for (unsigned i = 0; i < ELEMENTS(s_aFunctions); i++)
-            {
-                FARPROC pfn = GetProcAddress(hmod, s_aFunctions[i].pszName);
-                if (!pfn)
-                {
-                    DWORD Err = GetLastError();
-                    rc = RTErrConvertFromWin32(Err);
-                    AssertMsgFailed(("Failed to resolve %s in dbghelp, Err=%d rc=%Rrc\n",
-                                     s_aFunctions[i].pszName, Err, rc));
-                    break;
-                }
-                *s_aFunctions[i].ppfn = pfn;
-            }
-            if (RT_SUCCESS(rc))
-            {
-                ASMAtomicXchgSize(&g_hDbgHelp, hmod);
-                ASMAtomicXchgU32(&s_u32Lock, 0);
-                return VINF_SUCCESS;
-            }
-        }
-        else
-        {
-            rc = VERR_VERSION_MISMATCH;
-            AssertMsgFailed(("ImagehlpApiVersion -> %p and MajorVersion=%d.\n", pVersion, pVersion ? pVersion->MajorVersion : 0));
-        }
-    }
-    else
-    {
-        DWORD Err = GetLastError();
-        rc = RTErrConvertFromWin32(Err);
-        AssertMsgFailed(("Failed to resolve ImagehlpApiVersionEx in dbghelp, Err=%d rc=%Rrc\n", Err, rc));
-    }
-    FreeLibrary(hmod);
-    ASMAtomicXchgU32(&s_u32Lock, 0);
-    return rc;
-}
-
-
-/**
- * Opens the debug info for a PE image using the windows dbghelp library.
- *
- * @returns IPRT status code.
- *
- * @param   File                The handle to the module.
- * @param   offHdr              The offset of the PE header.
- * @param   pszModulePath       The path to the module.
- * @param   ppDbgMod            Where to store the module handle.
- *
- */
-int rtDbgModPEOpen(RTFILE File, RTFOFF offHdr, const char *pszModulePath, PRTDBGMOD *ppDbgMod)
-{
-    /*
-     * We need to read the section headers and get the image size.
-     */
-    IMAGE_FILE_HEADER FHdr;
-    int rc = RTFileReadAt(File, offHdr + OFFSETOF(IMAGE_NT_HEADERS32, FileHeader), &FHdr, sizeof(FHdr), NULL);
-    AssertRCReturn(rc, rc);
-
-    uint32_t cbImage;
-    if (FHdr.SizeOfOptionalHeader == sizeof(IMAGE_OPTIONAL_HEADER32))
-        rc = RTFileReadAt(File, offHdr + OFFSETOF(IMAGE_NT_HEADERS32, OptionalHeader.SizeOfImage),
-                          &cbImage, sizeof(cbImage), NULL);
-    else if (FHdr.SizeOfOptionalHeader == sizeof(IMAGE_OPTIONAL_HEADER64))
-        rc = RTFileReadAt(File, offHdr + OFFSETOF(IMAGE_NT_HEADERS64, OptionalHeader.SizeOfImage),
-                          &cbImage, sizeof(cbImage), NULL);
-    else
-        AssertFailedReturn(VERR_BAD_EXE_FORMAT);
-    AssertRCReturn(rc, rc);
-
-    /*
-     * Load dbghelp.dll.
-     */
-    rc = rtDbgModPELoadDbgHelp();
-    if (RT_FAILURE(rc))
-        return rc;
-
-    /*
-     * Allocate the module and read/construct the section headers.
-     */
-    PRTDBGMODPE pModPe = (PRTDBGMODPE)RTMemAlloc(OFFSETOF(RTDBGMODPE, aSections[FHdr.NumberOfSections + 2]));
-    AssertReturn(pModPe, VERR_NO_MEMORY);
-    pModPe->Core.u32Magic   = RTDBGMOD_MAGIC;
-    pModPe->Core.pOps       = &g_rtDbgModPEOps;
-    pModPe->Core.File       = File;
-    pModPe->cbImage         = cbImage;
-    pModPe->cSections       = 1 + FHdr.NumberOfSections;
-    rc = RTFileReadAt(File, offHdr + OFFSETOF(IMAGE_NT_HEADERS32, OptionalHeader) + FHdr.SizeOfOptionalHeader,
-                      &pModPe->aSections[1], sizeof(pModPe->aSections[0]) * FHdr.NumberOfSections, NULL);
-    if (RT_SUCCESS(rc))
-    {
-        PIMAGE_SECTION_HEADER pSH = &pModPe->aSections[0];
-        memcpy(pSH->Name, "headers", sizeof(pSH->Name));
-        pSH->Misc.VirtualSize       = pModPe->aSections[1].VirtualAddress;
-        pSH->VirtualAddress         = 0;
-        pSH->SizeOfRawData          = pSH->Misc.VirtualSize;
-        pSH->PointerToRawData       = 0;
-        pSH->PointerToRelocations   = 0;
-        pSH->PointerToLinenumbers   = 0;
-        pSH->NumberOfRelocations    = 0;
-        pSH->NumberOfLinenumbers    = 0;
-        pSH->Characteristics        = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_ALIGN_4BYTES | IMAGE_SCN_MEM_READ;
-
-        uint32_t uTheEnd = pModPe->aSections[FHdr.NumberOfSections].VirtualAddress
-                         + pModPe->aSections[FHdr.NumberOfSections].Misc.VirtualSize;
-        if (uTheEnd < cbImage)
-        {
-            pSH = &pModPe->aSections[pModPe->cSections++];
-            memcpy(pSH->Name, "tail\0\0\0", sizeof(pSH->Name));
-            pSH->Misc.VirtualSize       = cbImage - uTheEnd;
-            pSH->VirtualAddress         = uTheEnd;
-            pSH->SizeOfRawData          = pSH->Misc.VirtualSize;
-            pSH->PointerToRawData       = 0;
-            pSH->PointerToRelocations   = 0;
-            pSH->PointerToLinenumbers   = 0;
-            pSH->NumberOfRelocations    = 0;
-            pSH->NumberOfLinenumbers    = 0;
-            pSH->Characteristics        = IMAGE_SCN_CNT_UNINITIALIZED_DATA | IMAGE_SCN_ALIGN_1BYTES | IMAGE_SCN_MEM_READ;
-        }
-
-        /*
-         * Find a new dbghelp handle.
-         *
-         * We assume 4GB of handles outlast most debugging sessions, or in anyways that
-         * when we start reusing handles they are no longer in use. :-)
-         */
-        static volatile uint32_t s_u32LastHandle = 1;
-        HANDLE hSymInst = (HANDLE)ASMAtomicIncU32(&s_u32LastHandle);
-        while (     hSymInst == INVALID_HANDLE_VALUE
-               ||   hSymInst == (HANDLE)0
-               ||   hSymInst == GetCurrentProcess())
-            hSymInst = (HANDLE)ASMAtomicIncU32(&s_u32LastHandle);
-
-        /*
-         * Initialize dbghelp and try open the specified module.
-         */
-        if (g_pfnSymInitialize(hSymInst, NULL, FALSE))
-        {
-            g_pfnSymSetOptions(SYMOPT_LOAD_LINES | SYMOPT_AUTO_PUBLICS | SYMOPT_ALLOW_ABSOLUTE_SYMBOLS);
-
-            RTFileSeek(File, 0, RTFILE_SEEK_BEGIN, NULL); /* don't know if this is required or not... */
-            DWORD64 ImageBase = g_pfnSymLoadModule64(hSymInst, (HANDLE)File, pszModulePath, NULL, 0x00400000, 0);
-            if (ImageBase)
-            {
-                pModPe->hSymInst    = hSymInst;
-                pModPe->ImageBase   = ImageBase;
-                *ppDbgMod = &pModPe->Core;
-                return rc;
-            }
-
-            DWORD Err = GetLastError();
-            rc = RTErrConvertFromWin32(Err);
-            AssertMsgFailed(("SymLoadModule64 failed: Err=%d rc=%Rrc\n", Err, rc));
-            g_pfnSymCleanup(hSymInst);
-        }
-        else
-        {
-            DWORD Err = GetLastError();
-            rc = RTErrConvertFromWin32(Err);
-            AssertMsgFailed(("SymInitialize failed: Err=%d rc=%Rrc\n", Err, rc));
-        }
-    }
-    else
-        AssertRC(rc);
-
-    RTMemFree(pModPe);
-    return rc;
-}
-
Index: /trunk/kProfile/dbgline.cpp
===================================================================
--- /trunk/kProfile/dbgline.cpp	(revision 3525)
+++ /trunk/kProfile/dbgline.cpp	(revision 3526)
@@ -34,4 +34,5 @@
 
 #include "dbg.h"
+#include "kDbgBase.h"
 
 
@@ -50,5 +51,5 @@
 {
     AssertMsgReturn(VALID_PTR(pLine), ("%p\n", pLine), NULL);
-    size_t cb = OFFSETOF(RTDBGLINE, szFile[pLine->cchFile + 1]);
+    size_t cb = KDBG_OFFSETOF(RTDBGLINE, szFile[pLine->cchFile + 1]);
     return (PRTDBGLINE)RTMemDup(pLine, cb);
 }
Index: /trunk/kProfile/dbgmodule.cpp
===================================================================
--- /trunk/kProfile/dbgmodule.cpp	(revision 3525)
+++ /trunk/kProfile/dbgmodule.cpp	(revision 3526)
@@ -29,13 +29,17 @@
 *   Header Files                                                               *
 *******************************************************************************/
-#include <iprt/file.h>
-#include <iprt/string.h>
-#include <iprt/err.h>
-#include <iprt/assert.h>
-#include <iprt/alloc.h>
-
+#ifdef KDBG_USE_IPRT
+# include <iprt/file.h>
+# include <iprt/string.h>
+# include <iprt/err.h>
+# include <iprt/assert.h>
+# include <iprt/alloc.h>
+#else
+#endif
+
+#include "kDbgBase.h"
 #include "DBGInternal.h"
-#include "internal/ldrMZ.h"
-#include "internal/ldrPE.h"
+#include <kLdrModMZ.h>
+#include <kLdrModPE.h>
 
 
@@ -79,5 +83,5 @@
         /* new header? */
         uint32_t offNewHeader;
-        rc = RTFileReadAt(File, OFFSETOF(IMAGE_DOS_HEADER, e_lfanew), &offNewHeader, sizeof(offNewHeader), NULL);
+        rc = RTFileReadAt(File, KDBG_OFFSETOF(IMAGE_DOS_HEADER, e_lfanew), &offNewHeader, sizeof(offNewHeader), NULL);
         if (RT_SUCCESS(rc) && offNewHeader)
         {
Index: /trunk/kProfile/dbgsymbol.cpp
===================================================================
--- /trunk/kProfile/dbgsymbol.cpp	(revision 3525)
+++ /trunk/kProfile/dbgsymbol.cpp	(revision 3526)
@@ -33,4 +33,5 @@
 #include <iprt/alloc.h>
 
+#include "kDbgBase.h"
 #include "dbg.h"
 
@@ -50,5 +51,5 @@
 {
     AssertMsgReturn(VALID_PTR(pSymbol), ("%p\n", pSymbol), NULL);
-    size_t cb = OFFSETOF(RTDBGSYMBOL, szName[pSymbol->cchName + 1]);
+    size_t cb = KDBG_OFFSETOF(RTDBGSYMBOL, szName[pSymbol->cchName + 1]);
     return (PRTDBGSYMBOL)RTMemDup(pSymbol, cb);
 }
Index: /trunk/kProfile/dllmain-win.cpp
===================================================================
--- /trunk/kProfile/dllmain-win.cpp	(revision 3526)
+++ /trunk/kProfile/dllmain-win.cpp	(revision 3526)
@@ -0,0 +1,49 @@
+
+
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include <Windows.h>
+
+#include "kProfileR3.h"
+
+
+
+/**
+ * The DLL Main for the IPRT DLL.
+ *
+ * This is required for profiling, it is not (currently) used for any
+ * other purposes. (It could be used to track the death of alian threads
+ * perhaps, if we decide to adopt them automatically.)
+ *
+ * @returns Success indicator.
+ * @param   hInstDll        The instance handle of the DLL. (i.e. the module handle)
+ * @param   fdwReason       The reason why we're here. This is a 'flag' for reasons of
+ *                          tradition, it's really a kind of enum.
+ * @param   pReserved       Reserved / undocumented something.
+ */
+BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, PVOID pReserved)
+{
+    switch (fdwReason)
+    {
+        case DLL_PROCESS_ATTACH:
+            if (kPrfInitialize())
+                return FALSE;
+            break;
+
+        case DLL_PROCESS_DETACH:
+            kPrfTerminate();
+            break;
+
+        case DLL_THREAD_ATTACH:
+            break;
+
+        case DLL_THREAD_DETACH:
+            kPrfTerminateThread();
+            break;
+    }
+
+    return TRUE;
+}
+
Index: unk/kProfile/dllmain-win32.cpp
===================================================================
--- /trunk/kProfile/dllmain-win32.cpp	(revision 3525)
+++ 	(revision )
@@ -1,49 +1,0 @@
-
-
-
-/*******************************************************************************
-*   Header Files                                                               *
-*******************************************************************************/
-#include <Windows.h>
-
-#include "kProfileR3.h"
-
-
-
-/**
- * The DLL Main for the IPRT DLL.
- *
- * This is required for profiling, it is not (currently) used for any
- * other purposes. (It could be used to track the death of alian threads
- * perhaps, if we decide to adopt them automatically.)
- *
- * @returns Success indicator.
- * @param   hInstDll        The instance handle of the DLL. (i.e. the module handle)
- * @param   fdwReason       The reason why we're here. This is a 'flag' for reasons of
- *                          tradition, it's really a kind of enum.
- * @param   pReserved       Reserved / undocumented something.
- */
-BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, PVOID pReserved)
-{
-    switch (fdwReason)
-    {
-        case DLL_PROCESS_ATTACH:
-            if (kPrfInitialize())
-                return FALSE;
-            break;
-
-        case DLL_PROCESS_DETACH:
-            kPrfTerminate();
-            break;
-
-        case DLL_THREAD_ATTACH:
-            break;
-
-        case DLL_THREAD_DETACH:
-            kPrfTerminateThread();
-            break;
-    }
-
-    return TRUE;
-}
-
Index: /trunk/kProfile/kDbgBase.h
===================================================================
--- /trunk/kProfile/kDbgBase.h	(revision 3526)
+++ /trunk/kProfile/kDbgBase.h	(revision 3526)
@@ -0,0 +1,168 @@
+/* $Id$ */
+/** @file
+ *
+ * kDbg - The Debug Info Reader, Base Definitions and Typedefs.
+ *
+ * Copyright (c) 2006-2007 knut st. osmundsen <bird@anduin.net>
+ *
+ *
+ * This file is part of kDbg.
+ *
+ * kDbg is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * kDbg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with kDbg; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef ___kDbgBase_h___
+#define ___kDbgBase_h___
+
+
+/** @defgroup grp_kDbgBase  kDbgBase - Base Definitions And Typedefs
+ * @{ */
+
+/*
+ * kDbg depend on size_t, [u]intNN_t, [u]intptr_t and some related constants.
+ * If KDBG_ALREADY_INCLUDED_STD_TYPES or KCOMMON_ALREADY_INCLUDED_STD_TYPES
+ * is defined, these has already been defined.
+ */
+#if !defined(KDBG_ALREADY_INCLUDED_STD_TYPES) && !defined(KCOMMON_ALREADY_INCLUDED_STD_TYPES)
+# define KCOMMON_ALREADY_INCLUDED_STD_TYPES 1
+# include <sys/types.h>
+# include <stddef.h>
+# ifdef _MSC_VER
+   typedef signed char          int8_t;
+   typedef unsigned char        uint8_t;
+   typedef signed short         int16_t;
+   typedef unsigned short       uint16_t;
+   typedef signed int           int32_t;
+   typedef unsigned int         uint32_t;
+   typedef signed __int64       int64_t;
+   typedef unsigned __int64     uint64_t;
+   typedef int64_t              intmax_t;
+   typedef uint64_t             uintmax_t;
+#  define UINT8_C(c)            (c)
+#  define UINT16_C(c)           (c)
+#  define UINT32_C(c)           (c ## U)
+#  define UINT64_C(c)           (c ## ULL)
+#  define INT8_C(c)             (c)
+#  define INT16_C(c)            (c)
+#  define INT32_C(c)            (c)
+#  define INT64_C(c)            (c ## LL)
+#  define INT8_MIN              (INT8_C(-0x7f) - 1)
+#  define INT16_MIN             (INT16_C(-0x7fff) - 1)
+#  define INT32_MIN             (INT32_C(-0x7fffffff) - 1)
+#  define INT64_MIN             (INT64_C(-0x7fffffffffffffff) - 1)
+#  define INT8_MAX              INT8_C(0x7f)
+#  define INT16_MAX             INT16_C(0x7fff)
+#  define INT32_MAX             INT32_C(0x7fffffff)
+#  define INT64_MAX             INT64_C(0x7fffffffffffffff)
+#  define UINT8_MAX             UINT8_C(0xff)
+#  define UINT16_MAX            UINT16_C(0xffff)
+#  define UINT32_MAX            UINT32_C(0xffffffff)
+#  define UINT64_MAX            UINT64_C(0xffffffffffffffff)
+# else
+#  include <stdint.h>
+# endif
+#endif /* !KDBG_ALREADY_INCLUDED_STD_TYPES && !KCOMMON_ALREADY_INCLUDED_STD_TYPES */
+
+
+/** Get the minimum of two values. */
+#define KDBG_MIN(a, b)              ((a) <= (b) ? (a) : (b))
+/** Get the maximum of two values. */
+#define KDBG_MAX(a, b)              ((a) >= (b) ? (a) : (b))
+/** Calculate the offset of a structure member. */
+#define KDBG_OFFSETOF(strct, memb)  ( (size_t)( &((strct *)0)->memb ) )
+/** Align a size_t value. */
+#define KDBG_ALIGN_Z(val, align)    ( ((val) + ((align) - 1)) & ~(size_t)((align) - 1) )
+/** Align a void * value. */
+#define KDBG_ALIGN_P(pv, align)     ( (void *)( ((uintptr_t)(pv) + ((align) - 1)) & ~(uintptr_t)((align) - 1) ) )
+/** Align a size_t value. */
+#define KDBG_ALIGN_ADDR(val, align) ( ((val) + ((align) - 1)) & ~(KLDRADDR)((align) - 1) )
+/** Number of elements in an array. */
+#define KDBG_ELEMENTS(a)            ( sizeof(a) / sizeof((a)[0]) )
+
+
+/** @def KDBG_LITTLE_ENDIAN
+ * The kDbg build is for a little endian target. */
+/** @def KDBG_BIG_ENDIAN
+ * The kDbg build is for a big endian target. */
+#if !defined(KDBG_LITTLE_ENDIAN) && !defined(KDBG_BIG_ENDIAN)
+# define KDBG_LITTLE_ENDIAN
+#endif
+#ifdef __DOXYGEN__
+# define KDBG_BIG_ENDIAN
+#endif
+
+
+/** @name Endian Conversion
+ * @{ */
+
+/** @def KDBG_E2E_U16
+ * Convert the endian of an unsigned 16-bit value. */
+# define KDBG_E2E_U16(u16)      ( (uint16_t) (((u16) >> 8) | ((u16) << 8)) )
+/** @def KDBG_E2E_U32
+ * Convert the endian of an unsigned 32-bit value. */
+# define KDBG_E2E_U32(u32)      (   ( ((u32) & UINT32_C(0xff000000)) >> 24 ) \
+                                  | ( ((u32) & UINT32_C(0x00ff0000)) >>  8 ) \
+                                  | ( ((u32) & UINT32_C(0x0000ff00)) <<  8 ) \
+                                  | ( ((u32) & UINT32_C(0x000000ff)) << 24 ) \
+                                )
+/** @def KDBG_E2E_U64
+ * Convert the endian of an unsigned 64-bit value. */
+# define KDBG_E2E_U64(u64)      (   ( ((u64) & UINT64_C(0xff00000000000000)) >> 56 ) \
+                                  | ( ((u64) & UINT64_C(0x00ff000000000000)) >> 40 ) \
+                                  | ( ((u64) & UINT64_C(0x0000ff0000000000)) >> 24 ) \
+                                  | ( ((u64) & UINT64_C(0x000000ff00000000)) >>  8 ) \
+                                  | ( ((u64) & UINT64_C(0x00000000ff000000)) <<  8 ) \
+                                  | ( ((u64) & UINT64_C(0x0000000000ff0000)) << 24 ) \
+                                  | ( ((u64) & UINT64_C(0x000000000000ff00)) << 40 ) \
+                                  | ( ((u64) & UINT64_C(0x00000000000000ff)) << 56 ) \
+                                )
+
+/** @def KDBG_LE2H_U16
+ * Unsigned 16-bit little-endian to host endian. */
+/** @def KDBG_LE2H_U32
+ * Unsigned 32-bit little-endian to host endian. */
+/** @def KDBG_LE2H_U64
+ * Unsigned 64-bit little-endian to host endian. */
+/** @def KDBG_BE2H_U16
+ * Unsigned 16-bit big-endian to host endian. */
+/** @def KDBG_BE2H_U32
+ * Unsigned 32-bit big-endian to host endian. */
+/** @def KDBG_BE2H_U64
+ * Unsigned 64-bit big-endian to host endian. */
+#ifdef KDBG_LITTLE_ENDIAN
+# define KDBG_LE2H_U16(u16)  ((uint16_t)(u16))
+# define KDBG_LE2H_U32(u32)  ((uint32_t)(u32))
+# define KDBG_LE2H_U64(u64)  ((uint32_t)(u32))
+# define KDBG_BE2H_U16(u16)  KDBG_E2E_U16(u16)
+# define KDBG_BE2H_U32(u32)  KDBG_E2E_U32(u32)
+# define KDBG_BE2H_U64(u64)  KDBG_E2E_U64(u64)
+#elif defined(KDBG_BIG_ENDIAN)
+# define KDBG_LE2H_U16(u16)  KDBG_E2E_U16(u16)
+# define KDBG_LE2H_U32(u32)  KDBG_E2E_U32(u32)
+# define KDBG_LE2H_U32(u64)  KDBG_E2E_U64(u64)
+# define KDBG_BE2H_U16(u16)  ((uint16_t)(u16))
+# define KDBG_BE2H_U32(u32)  ((uint32_t)(u32))
+# define KDBG_BE2H_U64(u64)  ((uint32_t)(u32))
+#else
+# error "KDBG_BIG_ENDIAN or KDBG_LITTLE_ENDIAN is supposed to be defined."
+#endif
+
+/** @} */
+
+/** @} */
+
+#endif
+
Index: /trunk/kProfile/kPrf2-win-amd64.def
===================================================================
--- /trunk/kProfile/kPrf2-win-amd64.def	(revision 3526)
+++ /trunk/kProfile/kPrf2-win-amd64.def	(revision 3526)
@@ -0,0 +1,5 @@
+LIBRARY kPrf2
+EXPORTS
+    _penter
+    _pexit
+    KPrfInit
Index: /trunk/kProfile/kPrf2-win-x86.def
===================================================================
--- /trunk/kProfile/kPrf2-win-x86.def	(revision 3526)
+++ /trunk/kProfile/kPrf2-win-x86.def	(revision 3526)
@@ -0,0 +1,5 @@
+LIBRARY kPrf2
+EXPORTS
+    _penter
+    _pexit
+    KPrfInit
Index: unk/kProfile/kPrf2-win32.def
===================================================================
--- /trunk/kProfile/kPrf2-win32.def	(revision 3525)
+++ 	(revision )
@@ -1,5 +1,0 @@
-LIBRARY kPrf2
-EXPORTS
-    _penter
-    _pexit
-    KPrfInit
Index: /trunk/kProfile/kPrf2Read.cpp
===================================================================
--- /trunk/kProfile/kPrf2Read.cpp	(revision 3525)
+++ /trunk/kProfile/kPrf2Read.cpp	(revision 3526)
@@ -34,10 +34,24 @@
 #include <string.h>
 #include <stdarg.h>
-
-/* iprt dependencies */
+#if 0
+# ifdef KPRF_OS_WINDOWS
+#  include <malloc.h>
+typedef unsigned char uint8_t;
+typedef signed char int8_t;
+typedef unsigned short uint16_t;
+typedef signed short int16_t;
+typedef unsigned int uint32_t;
+typedef signed int int32_t;
+typedef unsigned _int64 uint64_t;
+typedef signed _int64 int64_t;
+typedef size_t uintptr_t;
+# else
+#  include <stdint.h>
+# endif
+#else
+    /* iprt mode */
 #include <iprt/types.h>
 #include <iprt/err.h>
 #include <iprt/avl.h>
-#include "dbg.h"
 #if 1
 # include <iprt/alloc.h>
@@ -45,4 +59,7 @@
 # define free(pv) RTMemFree(pv)
 #endif
+#endif
+
+#include "dbg.h"
 
 
Index: /trunk/kProfile/kProfileR3.cpp
===================================================================
--- /trunk/kProfile/kProfileR3.cpp	(revision 3525)
+++ /trunk/kProfile/kProfileR3.cpp	(revision 3526)
@@ -4,10 +4,17 @@
 *   Header Files                                                               *
 *******************************************************************************/
-#if defined(__WIN32__) || defined(__WIN64__)
+#if defined(KPRF_OS_WINDOWS)
 # include <windows.h>
 # include <psapi.h>
 # include <malloc.h>
-# define IN_RING3
-# include <iprt/stdint.h> /* Temporary IPRT convenience */
+typedef unsigned char uint8_t;
+typedef signed char int8_t;
+typedef unsigned short uint16_t;
+typedef signed short int16_t;
+typedef unsigned int uint32_t;
+typedef signed int int32_t;
+typedef unsigned _int64 uint64_t;
+typedef signed _int64 int64_t;
+typedef size_t uintptr_t;
 # if _MSC_VER >= 1400
 #  include <intrin.h>
@@ -15,5 +22,5 @@
 # endif
 
-#elif defined(__LINUX__) || defined(__FREEBSD__)
+#elif defined(KPRF_OS_LINUX) || defined(KPRF_OS_FREEBSD)
 # define KPRF_USE_PTHREAD
 # include <pthread.h>
@@ -28,7 +35,7 @@
 # endif
 
-#elif defined(__OS2__)
+#elif defined(KPRF_OS_OS2)
 # define INCL_BASE
-# include <os2s.h>
+# include <os2.h>
 # include <stdint.h>
 # include <sys/fmutex.h>
@@ -44,5 +51,5 @@
 #define KPRF_NAME(Suffix)               KPrf##Suffix
 #define KPRF_TYPE(Prefix,Suffix)        Prefix##KPRF##Suffix
-#if defined(__WIN32__) || defined(__WIN64__) || defined(__OS2__)
+#if defined(KPRF_OS_WINDOWS) || defined(KPRF_OS_OS2)
 # define KPRF_DECL_FUNC(type, name)     extern "C"  __declspec(dllexport) type __cdecl KPRF_NAME(name)
 #else
@@ -53,6 +60,5 @@
 #  define KPRF_ASSERT(expr) do { if (!(expr)) { __asm__ __volatile__("int3\n\tnop\n\t");} } while (0)
 # else
-#  define KPRF_ASSERT(expr) do { if (!(expr)) { __asm int 3 \
-                            } } while (0)
+#  define KPRF_ASSERT(expr) do { if (!(expr)) { __debugbreak(); } } while (0)
 # endif
 #else
@@ -70,7 +76,7 @@
 #if defined(KPRF_USE_PTHREAD)
 typedef pthread_mutex_t     KPRF_TYPE(,MUTEX);
-#elif defined(__WIN32__) || defined(__WIN64__)
+#elif defined(KPRF_OS_WINDOWS)
 typedef CRITICAL_SECTION    KPRF_TYPE(,MUTEX);
-#elif defined(__OS2__)
+#elif defined(KPRF_OS_OS2)
 typedef struct _fmutex      KPRF_TYPE(,MUTEX);
 #endif
@@ -82,5 +88,5 @@
 /** Read/Write lock type. */
 typedef pthread_rwlock_t    KPRF_TYPE(,RWLOCK);
-#elif defined(__WIN32__) || defined(__WIN64__) || defined(__OS2__)
+#elif defined(KPRF_OS_WINDOWS) || defined(KPRF_OS_OS2)
 /** Read/Write lock state. */
 typedef enum KPRF_TYPE(,RWLOCKSTATE)
@@ -108,10 +114,10 @@
     /** The current number of waiting writers. */
     uint32_t                cWritersWaiting;
-# if defined(__WIN32__) || defined(__WIN64__)
+# if defined(KPRF_OS_WINDOWS)
     /** The handle of the event object on which the waiting readers block. (manual reset). */
     HANDLE                  hevReaders;
     /** The handle of the event object on which the waiting writers block. (manual reset). */
     HANDLE                  hevWriters;
-# elif defined(__OS2__)
+# elif defined(KPRF_OS_OS2)
     /** The handle of the event semaphore on which the waiting readers block. */
     HEV                     hevReaders;
@@ -132,5 +138,5 @@
 *******************************************************************************/
 /** The TLS index / key. */
-#if defined(__WIN32__) || defined(__WIN64__)
+#if defined(KPRF_OS_WINDOWS)
 static DWORD                g_dwThreadTLS = TLS_OUT_OF_INDEXES;
 
@@ -138,5 +144,5 @@
 static pthread_key_t        g_ThreadKey = (pthread_key_t)-1;
 
-#elif defined(__OS2__)
+#elif defined(KPRF_OS_OS2)
 static KPRF_TYPE(P,THREAD) *g_ppThread = NULL;
 
@@ -187,5 +193,5 @@
 
 /* Win32/64 */
-#if defined(__WIN32__) || defined(__WIN64__)
+#if defined(KPRF_OS_WINDOWS)
     pThread = (KPRF_TYPE(P,THREAD))TlsGetValue(g_dwThreadTLS);
 
@@ -194,5 +200,5 @@
     pThread = (KPRF_TYPE(P,THREAD))pthread_getspecific(g_ThreadKey);
 
-#elif defined(__OS2__)
+#elif defined(KPRF_OS_OS2)
     pThread = *g_ppThread;
 
@@ -215,5 +221,5 @@
 {
 /* Win32/64 */
-#if defined(__WIN32__) || defined(__WIN64__)
+#if defined(KPRF_OS_WINDOWS)
     uintptr_t ThreadId = (uintptr_t)GetCurrentThreadId();
 
@@ -222,5 +228,5 @@
     uintptr_t ThreadId = (uintptr_t)pthread_self();
 
-#elif defined(__OS2__)
+#elif defined(KPRF_OS_OS2)
     PTIB pTib;
     PPIB pPib;
@@ -245,8 +251,8 @@
 {
 /* Win32/64 */
-#if defined(__WIN32__) || defined(__WIN64__)
+#if defined(KPRF_OS_WINDOWS)
     uintptr_t ThreadId = (uintptr_t)GetProcessId(GetCurrentProcess());
 
-#elif defined(__OS2__)
+#elif defined(KPRF_OS_OS2)
     PTIB pTib;
     PPIB pPib;
@@ -275,5 +281,5 @@
 {
 /* Win32/64 */
-#if defined(__WIN32__) || defined(__WIN64__)
+#if defined(KPRF_OS_WINDOWS)
     BOOL fRc = TlsSetValue(g_dwThreadTLS, pThread);
 
@@ -282,5 +288,5 @@
     int rc = pthread_setspecific(g_ThreadKey, pThread);
 
-#elif defined(__OS2__)
+#elif defined(KPRF_OS_OS2)
     *g_ppThread = pThread;
 
@@ -333,5 +339,5 @@
 {
 #if defined(HAVE_INTRIN)
-    _InterlockedExchange((int32_t *)pu32, (const int32_t)u32);
+    _InterlockedExchange((long volatile *)pu32, (const long)u32);
 
 #elif defined(__GNUC__)
@@ -404,5 +410,5 @@
 {
 #if defined(HAVE_INTRIN)
-    _InterlockedExchangeAdd32((volatile int32_t *)pu32, (const int32_t)u32);
+    _InterlockedExchangeAdd((volatile long *)pu32, (const long)u32);
 
 #elif defined(__GNUC__)
@@ -482,9 +488,9 @@
     return -1;
 
-#elif defined(__WIN32__) || defined(__WIN64__)
+#elif defined(KPRF_OS_WINDOWS)
     InitializeCriticalSection(pMutex);
     return 0;
 
-#elif defined(__OS2__)
+#elif defined(KPRF_OS_OS2)
     if (!_fmutex_create(pMutex, 0))
         return 0;
@@ -503,8 +509,8 @@
     pthread_mutex_destroy(pMutex);
 
-#elif defined(__WIN32__) || defined(__WIN64__)
+#elif defined(KPRF_OS_WINDOWS)
     DeleteCriticalSection(pMutex);
 
-#elif defined(__OS2__)
+#elif defined(KPRF_OS_OS2)
     _fmutex_close(pMutex);
 #endif
@@ -517,5 +523,5 @@
 static inline void kPrfMutexAcquire(KPRF_TYPE(P,MUTEX) pMutex)
 {
-#if defined(__WIN32__) || defined(__WIN64__)
+#if defined(KPRF_OS_WINDOWS)
     EnterCriticalSection(pMutex);
 
@@ -523,5 +529,5 @@
     pthread_mutex_lock(pMutex);
 
-#elif defined(__OS2__)
+#elif defined(KPRF_OS_OS2)
     fmutex_request(pMutex);
 #endif
@@ -535,5 +541,5 @@
 static inline void kPrfMutexRelease(KPRF_TYPE(P,MUTEX) pMutex)
 {
-#if defined(__WIN32__) || defined(__WIN64__)
+#if defined(KPRF_OS_WINDOWS)
     LeaveCriticalSection(pMutex);
 
@@ -541,5 +547,5 @@
     pthread_mutex_lock(pMutex);
 
-#elif defined(__OS2__)
+#elif defined(KPRF_OS_OS2)
     fmutex_request(pMutex);
 #endif
@@ -568,5 +574,5 @@
     return -1;
 
-#elif defined(__WIN32__) || defined(__WIN64__) || defined(__OS2__)
+#elif defined(KPRF_OS_WINDOWS) || defined(KPRF_OS_OS2)
     if (kPrfMutexInit(&pRWLock->Mutex))
         return -1;
@@ -575,5 +581,5 @@
     pRWLock->cWritersWaiting = 0;
     pRWLock->enmState = RWLOCK_STATE_SHARED;
-# if defined(__WIN32__) || defined(__WIN64__)
+# if defined(KPRF_OS_WINDOWS)
     pRWLock->hevReaders = CreateEvent(NULL, TRUE, TRUE, NULL);
     pRWLock->hevWriters = CreateEvent(NULL, FALSE, FALSE, NULL);
@@ -584,5 +590,5 @@
     CloseHandle(pRWLock->hevWriters);
 
-# elif defined(__OS2__)
+# elif defined(KPRF_OS_OS2)
     APIRET rc = DosCreateEventSem(NULL, &pRWLock->hevReaders, 0, TRUE);
     if (!rc)
@@ -614,5 +620,5 @@
     pthread_rwlock_destroy(pRWLock);
 
-#elif defined(__WIN32__) || defined(__WIN64__) || defined(__OS2__)
+#elif defined(KPRF_OS_WINDOWS) || defined(KPRF_OS_OS2)
     if (pRWLock->enmState == RWLOCK_STATE_UNINITIALIZED)
         return;
@@ -623,5 +629,5 @@
     pRWLock->cReadersWaiting = 0;
     pRWLock->cWritersWaiting = 0;
-# if defined(__WIN32__) || defined(__WIN64__)
+# if defined(KPRF_OS_WINDOWS)
     CloseHandle(pRWLock->hevReaders);
     pRWLock->hevReaders = INVALID_HANDLE_VALUE;
@@ -629,5 +635,5 @@
     pRWLock->hevWriters = INVALID_HANDLE_VALUE;
 
-# elif defined(__OS2__)
+# elif defined(KPRF_OS_OS2)
     DosCloseEventSem(pRWLock->hevReaders);
     pRWLock->hevReaders = NULLHANDLE;
@@ -648,5 +654,5 @@
     pthread_rwlock_rdlock(pRWLock);
 
-#elif defined(__WIN32__) || defined(__WIN64__) || defined(__OS2__)
+#elif defined(KPRF_OS_WINDOWS) || defined(KPRF_OS_OS2)
     if (pRWLock->enmState == RWLOCK_STATE_UNINITIALIZED)
         return;
@@ -664,9 +670,9 @@
         /* have to wait */
         KPRF_ATOMIC_INC32(&pRWLock->cReadersWaiting);
-# if defined(__WIN32__) || defined(__WIN64__)
+# if defined(KPRF_OS_WINDOWS)
         HANDLE hev = pRWLock->hevReaders;
         ResetEvent(hev);
 
-# elif defined(__OS2__)
+# elif defined(KPRF_OS_OS2)
         HEV    hev = pRWLock->hevReaders;
         ULONG cIgnored;
@@ -676,5 +682,5 @@
         kPrfMutexRelease(&pRWLock->Mutex);
 
-# if defined(__WIN32__) || defined(__WIN64__)
+# if defined(KPRF_OS_WINDOWS)
         switch (WaitForSingleObject(hev, INFINITE))
         {
@@ -688,5 +694,5 @@
         }
 
-# elif defined(__OS2__)
+# elif defined(KPRF_OS_OS2)
         switch (DosWaitEventSem(hev, SEM_INDEFINITE_WAIT))
         {
@@ -723,5 +729,5 @@
     pthread_rwlock_unlock(pRWLock);
 
-#elif defined(__WIN32__) || defined(__WIN64__) || defined(__OS2__)
+#elif defined(KPRF_OS_WINDOWS) || defined(KPRF_OS_OS2)
     if (pRWLock->enmState == RWLOCK_STATE_UNINITIALIZED)
         return;
@@ -747,7 +753,7 @@
      * Wake up one (or more on OS/2) waiting writers.
      */
-# if defined(__WIN32__) || defined(__WIN64__)
+# if defined(KPRF_OS_WINDOWS)
     SetEvent(pRWLock->hevWriters);
-# elif defined(__OS2__)
+# elif defined(KPRF_OS_OS2)
     DosPostEvent(pRWLock->hevwriters);
 # endif
@@ -767,5 +773,5 @@
     pthread_rwlock_wrlock(pRWLock);
 
-#elif defined(__WIN32__) || defined(__WIN64__) || defined(__OS2__)
+#elif defined(KPRF_OS_WINDOWS) || defined(KPRF_OS_OS2)
     if (pRWLock->enmState == RWLOCK_STATE_UNINITIALIZED)
         return;
@@ -790,11 +796,11 @@
     for (;;)
     {
-# if defined(__WIN32__) || defined(__WIN64__)
+# if defined(KPRF_OS_WINDOWS)
         HANDLE hev = pRWLock->hevWriters;
-# elif defined(__OS2__)
+# elif defined(KPRF_OS_OS2)
         HEV    hev = pRWLock->hevWriters;
 # endif
         kPrfMutexRelease(&pRWLock->Mutex);
-# if defined(__WIN32__) || defined(__WIN64__)
+# if defined(KPRF_OS_WINDOWS)
         switch (WaitForSingleObject(hev, INFINITE))
         {
@@ -809,5 +815,5 @@
         }
 
-# elif defined(__OS2__)
+# elif defined(KPRF_OS_OS2)
         switch (DosWaitEventSem(hev, SEM_INDEFINITE_WAIT))
         {
@@ -853,5 +859,5 @@
     pthread_rwlock_unlock(pRWLock);
 
-#elif defined(__WIN32__) || defined(__WIN64__) || defined(__OS2__)
+#elif defined(KPRF_OS_WINDOWS) || defined(KPRF_OS_OS2)
     if (pRWLock->enmState == RWLOCK_STATE_UNINITIALIZED)
         return;
@@ -878,7 +884,7 @@
      * Someone is waiting, wake them up as we change the state.
      */
-# if defined(__WIN32__) || defined(__WIN64__)
+# if defined(KPRF_OS_WINDOWS)
     HANDLE hev = INVALID_HANDLE_VALUE;
-# elif defined(__OS2__)
+# elif defined(KPRF_OS_OS2)
     HEV    hev = NULLHANDLE;
 # endif
@@ -894,7 +900,7 @@
         hev = pRWLock->hevReaders;
     }
-# if defined(__WIN32__) || defined(__WIN64__)
+# if defined(KPRF_OS_WINDOWS)
     SetEvent(hev);
-# elif defined(__OS2__)
+# elif defined(KPRF_OS_OS2)
     DosPostEvent(pRWLock->hevwriters);
 # endif
@@ -919,5 +925,5 @@
                          KPRF_TYPE(P,UPTR) puBasePtr, KPRF_TYPE(P,UPTR) pcbSegmentMinusOne)
 {
-#if defined(__WIN32__) || defined(__WIN64__)
+#if defined(KPRF_OS_WINDOWS)
     /*
      * Enumerate the module handles.
@@ -1037,5 +1043,5 @@
     }
 
-#elif defined(__OS2__)
+#elif defined(KPRF_OS_OS2)
     /*
      * Just ask the loader.
@@ -1118,5 +1124,5 @@
      * Some limit stuff in posix / ansi also comes to mind... */
 
-#elif defined(__OS2__)
+#elif defined(KPRF_OS_OS2)
     PTIB pTib;
     PPIB pPib;
@@ -1148,9 +1154,9 @@
 static char *kPrfGetEnvString(const char *pszVar, char *pszValue, uint32_t cchValue, const char *pszDefault)
 {
-#if defined(__WIN32__) || defined(__WIN64__)
+#if defined(KPRF_OS_WINDOWS)
     if (GetEnvironmentVariable(pszVar, pszValue, cchValue))
         return pszValue;
 
-#elif defined(__OS2__)
+#elif defined(KPRF_OS_OS2)
     PSZ pszValue;
     if (    !DosScanEnv((PCSZ)pszVar, &pszValue)
@@ -1187,5 +1193,5 @@
 static uint32_t kPrfGetEnvValue(const char *pszVar, uint32_t uDefault)
 {
-#if defined(__WIN32__) || defined(__WIN64__)
+#if defined(KPRF_OS_WINDOWS)
     char szBuf[128];
     const char *pszValue = szBuf;
@@ -1193,5 +1199,5 @@
         pszValue = NULL;
 
-#elif defined(__OS2__)
+#elif defined(KPRF_OS_OS2)
     PSZ pszValue;
     if (DosScanEnv((PCSZ)pszVar, &pszValue))
@@ -1275,5 +1281,5 @@
 static void *kPrfAllocMem(uint32_t cb)
 {
-#if defined(__WIN32__) || defined(__WIN64__)
+#if defined(KPRF_OS_WINDOWS)
     void *pv = VirtualAlloc(NULL, cb, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
 
@@ -1281,5 +1287,5 @@
     void *pv = mmap(NULL, cb, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
 
-#elif defined(__OS2__)
+#elif defined(KPRF_OS_OS2)
     void *pv;
 # ifdef INCL_DOSEXAPIS
@@ -1304,5 +1310,5 @@
 static void kPrfFreeMem(void *pv)
 {
-#if defined(__WIN32__) || defined(__WIN64__)
+#if defined(KPRF_OS_WINDOWS)
     VirtualFree(pv, 0, MEM_RELEASE);
 
@@ -1310,5 +1316,5 @@
     munmap(pv, 0); /** @todo check if 0 is allowed here.. */
 
-#elif defined(__OS2__)
+#elif defined(KPRF_OS_OS2)
 # ifdef INCL_DOSEXAPIS
     DosFreeMemEx(&pv);
@@ -1338,5 +1344,5 @@
 static int kPrfWriteFile(const char *pszName, const void *pvData, uint32_t cbData)
 {
-#if defined(__WIN32__) || defined(__WIN64__)
+#if defined(KPRF_OS_WINDOWS)
     int rc = -1;
     HANDLE hFile = CreateFile(pszName,GENERIC_WRITE, FILE_SHARE_READ, NULL,
@@ -1352,5 +1358,5 @@
     return rc;
 
-#elif defined(__OS2__)
+#elif defined(KPRF_OS_OS2)
     HFILE hFile;
     ULONG ulAction = 0;
@@ -1436,5 +1442,5 @@
                      * Allocate the TLS entry.
                      */
-#if defined(__WIN32__) || defined(__WIN64__)
+#if defined(KPRF_OS_WINDOWS)
                     g_dwThreadTLS = TlsAlloc();
                     if (g_dwThreadTLS != TLS_OUT_OF_INDEXES)
@@ -1444,5 +1450,5 @@
                     if (!rc)
 
-#elif defined(__OS2__)
+#elif defined(KPRF_OS_OS2)
                     int rc = DosAllocThreadLocalMemory(sizeof(void *), (PULONG*)&g_ppThread); /** @todo check if this is a count or a size. */
                     if (!rc)
@@ -1489,7 +1495,7 @@
         return -1;
 
-#if defined(__WIN32__) || defined(__WIN64__)
+#if defined(KPRF_OS_WINDOWS)
     Sleep(10);
-#elif defined(__OS2__)
+#elif defined(KPRF_OS_OS2)
     DosSleep(10);
 #else
@@ -1505,5 +1511,5 @@
      * Use the stack space to fill in process details.
      */
-#if defined(__WIN32__) || defined(__WIN64__)
+#if defined(KPRF_OS_WINDOWS)
     /* all is one single string */
     const char *pszCommandLine = GetCommandLine();
@@ -1511,5 +1517,5 @@
         KPRF_NAME(SetCommandLine)(pHdr, 1, &pszCommandLine);
 
-#elif defined(__OS2__) || defined(__OS2__)
+#elif defined(KPRF_OS_OS2) || defined(KPRF_OS_OS2)
     PTIB pTib;
     PPIB pPib;
@@ -1575,5 +1581,5 @@
      */
     kPrfFreeMem(pHdr);
-#if defined(__WIN32__) || defined(__WIN64__)
+#if defined(KPRF_OS_WINDOWS)
     TlsFree(g_dwThreadTLS);
     g_dwThreadTLS = TLS_OUT_OF_INDEXES;
@@ -1583,5 +1589,5 @@
     g_ThreadKey = (pthread_key_t)-1;
 
-#elif defined(__OS2__)
+#elif defined(KPRF_OS_OS2)
     DosFreeThreadLocalMemory((PULONG)g_ppThread);
     g_ppThread = NULL;
Index: /trunk/kProfile/prfamd64msc.asm
===================================================================
--- /trunk/kProfile/prfamd64msc.asm	(revision 3526)
+++ /trunk/kProfile/prfamd64msc.asm	(revision 3526)
@@ -0,0 +1,390 @@
+; $Id: $
+;; @file
+;
+; kProfiler MK2 - Microsoft C/C++ Compiler Interaction, AMD64.
+;
+;
+; Copyright (c) 2006 knut st. osmundsen <bird-src-spam@anduin.net.de>
+;
+;
+; This file is part of kLIBC.
+;
+; kLIBC is free software; you can redistribute it and/or modify
+; it under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2 of the License, or
+; (at your option) any later version.
+;
+; kLIBC is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with kLIBC; if not, write to the Free Software
+; Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+;
+;
+
+[section .data]
+;
+g_fCalibrated:
+        dd 0
+g_OverheadAdj:
+        dd 0
+
+[section .text]
+
+extern KPRF_ENTER
+extern KPRF_LEAVE
+
+global _penter
+global _pexit
+
+;ifdef  UNDEFINED
+global common_return_path
+global common_overhead
+global common_no_overhead
+global calibrate
+global calib_inner_update_minimum
+global calib_inner_next
+global calib_outer_dec
+global calib_outer_inc
+global calib_done
+global calib_nullproc
+;endif
+
+
+;;
+; On x86 the call to this function has been observed to be put before
+; creating the stack frame, as the very first instruction in the function.
+;
+; Thus the stack layout is as follows:
+;       24      return address of the calling function.
+;       20      our return address - the address of the calling function + 5.
+;       1c      eax
+;       18      edx
+;       14      eflags
+;       10      ecx
+;       c       tsc high       - param 3
+;       8       tsc low
+;       4       frame pointer  - param 2
+;       0       function ptr   - param 1
+;
+;
+align 16
+_penter:
+        ; save volatile register and get the time stamp.
+        push    eax
+        push    edx
+        rdtsc
+        pushfd
+        push    ecx
+
+        ; setting up the enter call frame (cdecl).
+        sub     esp, 4 + 4 + 8
+        mov     [esp + 0ch], edx        ; Param 3 - the timestamp
+        mov     [esp + 08h], eax
+        lea     edx, [esp + 24h]        ; Param 2 - frame pointer (pointer to the return address of the function calling us)
+        mov     [esp + 04h], edx
+        mov     eax, [esp + 20h]        ; Param 1 - The function address
+        sub     eax, 5                  ; call instruction
+        mov     [esp], eax
+
+        call    KPRF_ENTER
+        jmp     common_return_path
+
+
+;;
+; On x86 the call to this function has been observed to be put right before
+; return instruction. This fact matters since since we have to calc the same
+; stack address as in _penter.
+;
+; Thus the stack layout is as follows:
+;       24      return address of the calling function.
+;       20      our return address - the address of the calling function + 5.
+;       1c      eax
+;       18      edx
+;       14      eflags
+;       10      ecx
+;       c       tsc high       - param 3
+;       8       tsc low
+;       4       frame pointer  - param 2
+;       0       function ptr   - param 1
+;
+;
+align 16
+_pexit:
+        ; save volatile register and get the time stamp.
+        push    eax
+        push    edx
+        rdtsc
+        pushfd
+        push    ecx
+
+        ; setting up the leave call frame (cdecl).
+        sub     esp, 4 + 4 + 8
+        mov     [esp + 0ch], edx        ; Param 3 - the timestamp
+        mov     [esp + 08h], eax
+        lea     edx, [esp + 24h]        ; Param 2 - frame pointer (pointer to the return address of the function calling us)
+        mov     [esp + 04h], edx
+        mov     eax, [esp + 20h]        ; Param 1 - Some address in the function.
+        sub     eax, 5                  ; call instruction
+        mov     [esp], eax
+
+        call    KPRF_LEAVE
+        jmp common_return_path
+
+
+;;
+; This is the common return path for both the enter and exit hooks.
+; It's kept common because we can then use the same overhead adjustment
+; and save some calibration efforts. It also saves space :-)
+align 16
+common_return_path:
+        ; Update overhead
+        test    eax, eax
+        jz      common_no_overhead
+        cmp     byte [g_fCalibrated], 0
+        jnz     common_overhead
+        call    calibrate
+common_overhead:
+        mov     ecx, eax                ; ecx <- pointer to overhead counter.
+        mov     eax, [g_OverheadAdj]    ; apply the adjustment before reading tsc
+        sub     [esp + 08h], eax
+        sbb     dword [esp + 0ch], 0
+
+        rdtsc
+        sub     eax, [esp + 08h]
+        sbb     edx, [esp + 0ch]
+        add     [ecx], eax
+        adc     [ecx + 4], edx
+common_no_overhead:
+        add     esp, 4 + 4 + 8
+
+        ; restore volatile registers.
+        pop     ecx
+        popfd
+        pop     edx
+        pop     eax
+        ret
+
+;;
+; Data esi points to while we're calibrating.
+struc CALIBDATA
+    .OverheadLo resd 1
+    .OverheadHi resd 1
+    .ProfiledLo resd 1
+    .ProfiledHi resd 1
+    .EnterTSLo  resd 1
+    .EnterTSHi  resd 1
+    .MinLo      resd 1
+    .MinHi      resd 1
+endstruc
+
+
+
+align 16
+;;
+; Do necessary calibrations.
+;
+calibrate:
+        ; prolog
+        push    ebp
+        mov     ebp, esp
+        pushfd
+        pushad
+        sub     esp, CALIBDATA_size
+        mov     esi, esp                ; esi points to the CALIBDATA
+
+        ;
+        ; Indicate that we have finished calibrating.
+        ;
+        mov     eax, 1
+        xchg    dword [g_fCalibrated], eax
+
+        ;
+        ; The outer loop - find the right adjustment.
+        ;
+        mov     ebx, 200h               ; loop counter.
+calib_outer_loop:
+
+        ;
+        ; The inner loop - calls the function number of times to establish a
+        ;                  good minimum value
+        ;
+        mov     ecx, 200h
+        mov     dword [esi + CALIBDATA.MinLo], 0ffffffffh
+        mov     dword [esi + CALIBDATA.MinHi], 07fffffffh
+calib_inner_loop:
+
+        ; zero the overhead and profiled times.
+        xor     eax, eax
+        mov     [esi + CALIBDATA.OverheadLo], eax
+        mov     [esi + CALIBDATA.OverheadHi], eax
+        mov     [esi + CALIBDATA.ProfiledLo], eax
+        mov     [esi + CALIBDATA.ProfiledHi], eax
+        call    calib_nullproc
+
+        ; subtract the overhead
+        mov     eax, [esi + CALIBDATA.ProfiledLo]
+        mov     edx, [esi + CALIBDATA.ProfiledHi]
+        sub     eax, [esi + CALIBDATA.OverheadLo]
+        sbb     edx, [esi + CALIBDATA.OverheadHi]
+
+        ; update the minimum value.
+        test    edx, 080000000h
+        jnz near calib_outer_dec        ; if negative, just simplify and shortcut
+        cmp     edx, [esi + CALIBDATA.MinHi]
+        jg      calib_inner_next
+        jl      calib_inner_update_minimum
+        cmp     eax, [esi + CALIBDATA.MinLo]
+        jge     calib_inner_next
+calib_inner_update_minimum:
+        mov     [esi + CALIBDATA.MinLo], eax
+        mov     [esi + CALIBDATA.MinHi], edx
+calib_inner_next:
+        loop    calib_inner_loop
+
+        ; Is the minimum value acceptable?
+        test    dword [esi + CALIBDATA.MinHi], 80000000h
+        jnz     calib_outer_dec         ; simplify if negative.
+        cmp     dword [esi + CALIBDATA.MinHi], 0
+        jnz     calib_outer_inc         ; this shouldn't be possible
+        cmp     dword [esi + CALIBDATA.MinLo], 1fh
+        jbe     calib_outer_dec         ; too low - 2 ticks per pair is the minimum!
+        cmp     dword [esi + CALIBDATA.MinLo], 30h
+        jbe     calib_done              ; this is fine!
+calib_outer_inc:
+        inc     dword [g_OverheadAdj]
+        jmp     calib_outer_next
+calib_outer_dec:
+        cmp     dword [g_OverheadAdj], 1
+        je      calib_done
+        dec     dword [g_OverheadAdj]
+calib_outer_next:
+        dec     ebx
+        jnz     calib_outer_loop
+calib_done:
+
+        ; epilog
+        add     esp, CALIBDATA_size
+        popad
+        popfd
+        leave
+        ret
+
+
+
+
+;;
+; The calibration _penter - this must be identical to the real thing except for the KPRF call.
+align 16
+calib_penter:
+        ; This part must be identical
+        push    eax
+        push    edx
+        rdtsc
+        pushfd
+        push    ecx
+
+        ; store the entry
+        mov     [esi + CALIBDATA.EnterTSLo], eax
+        mov     [esi + CALIBDATA.EnterTSHi], edx
+
+        ; create the call frame
+        push    edx
+        push    eax
+        push    0
+        push    0
+
+        lea     eax, [esi + CALIBDATA.OverheadLo]
+        jmp     common_overhead
+
+
+;;
+; The calibration _pexit - this must be identical to the real thing except for the KPRF call.
+align 16
+calib_pexit:
+        ; This part must be identical
+        push    eax
+        push    edx
+        rdtsc
+        pushfd
+        push    ecx
+
+        ; update the time
+        push    eax
+        push    edx
+        sub     eax, [esi + CALIBDATA.EnterTSLo]
+        sbb     edx, [esi + CALIBDATA.EnterTSHi]
+        add     [esi + CALIBDATA.ProfiledLo], eax
+        adc     [esi + CALIBDATA.ProfiledHi], edx
+        pop     edx
+        pop     eax
+
+        ; create the call frame
+        push    edx
+        push    eax
+        push    0
+        push    0
+
+        lea     eax, [esi + CALIBDATA.EnterTSLo]
+        jmp     common_overhead
+
+
+;;
+; The 'function' we're profiling.
+; The general idea is that each pair should take something like 2-10 ticks.
+;
+; (Btw. If we don't use multiple pairs here, we end up with the wrong result.)
+align 16
+calib_nullproc:
+        call    calib_penter ;0
+        call    calib_pexit
+
+        call    calib_penter ;1
+        call    calib_pexit
+
+        call    calib_penter ;2
+        call    calib_pexit
+
+        call    calib_penter ;3
+        call    calib_pexit
+
+        call    calib_penter ;4
+        call    calib_pexit
+
+        call    calib_penter ;5
+        call    calib_pexit
+
+        call    calib_penter ;6
+        call    calib_pexit
+
+        call    calib_penter ;7
+        call    calib_pexit
+
+        call    calib_penter ;8
+        call    calib_pexit
+
+        call    calib_penter ;9
+        call    calib_pexit
+
+        call    calib_penter ;a
+        call    calib_pexit
+
+        call    calib_penter ;b
+        call    calib_pexit
+
+        call    calib_penter ;c
+        call    calib_pexit
+
+        call    calib_penter ;d
+        call    calib_pexit
+
+        call    calib_penter ;e
+        call    calib_pexit
+
+        call    calib_penter ;f
+        call    calib_pexit
+        ret
+
Index: /trunk/kProfile/prfx86msc.asm
===================================================================
--- /trunk/kProfile/prfx86msc.asm	(revision 3525)
+++ /trunk/kProfile/prfx86msc.asm	(revision 3526)
@@ -46,6 +46,4 @@
 global common_no_overhead
 global calibrate
-global outer_calibration_loop
-global inner_calibration_loop
 global calib_inner_update_minimum
 global calib_inner_next
Index: /trunk/kProfile/tst.c
===================================================================
--- /trunk/kProfile/tst.c	(revision 3526)
+++ /trunk/kProfile/tst.c	(revision 3526)
@@ -0,0 +1,48 @@
+#include <stdio.h>
+
+#ifdef _MSC_VER
+void __cdecl _penter(void);
+void __cdecl _pexit(void);
+__declspec(naked) int  naked(void)
+{
+    __asm
+    {
+        call    _penter
+        call    _pexit
+        xor     eax, eax
+        ret
+    }
+}
+
+#endif
+
+int bar(void)
+{
+    unsigned i;
+    for (i = 0; i < 1000; i += 7)
+        i += i & 1;
+    return i;
+}
+
+int foo(void)
+{
+    unsigned i, rc = 0;
+    for (i = 0; i < 1000; i++)
+        rc += bar();
+#ifdef _MSC_VER
+    for (; i < 2000; i++)
+        rc += naked();
+#endif
+    return i;
+}
+
+int main()
+{
+    int rc;
+    printf("hello");
+    fflush(stdout);
+    rc = foo();
+    printf("world\n");
+    return rc;
+}
+
