diff --git a/src/libs/utils/consoleprocess_win.cpp b/src/libs/utils/consoleprocess_win.cpp
index 969823c582b54f166e5e499677e84f1aeee6d16b..aa9f0d24659a8581c3929b41d84881784ae10c7c 100644
--- a/src/libs/utils/consoleprocess_win.cpp
+++ b/src/libs/utils/consoleprocess_win.cpp
@@ -28,6 +28,7 @@
 **************************************************************************/
 
 #include "consoleprocess.h"
+#include "winutils.h"
 
 #include <QtCore/QCoreApplication>
 #include <QtCore/QDir>
@@ -122,7 +123,7 @@ bool ConsoleProcess::start(const QString &program, const QStringList &args)
         delete m_tempFile;
         m_tempFile = 0;
         stubServerShutdown();
-        emit processError(tr("The process could not be started!"));
+        emit processError(tr("The process '%1' could not be started: %2").arg(cmdLine, winErrorMessage(GetLastError())));
         return false;
     }
 
@@ -173,18 +174,6 @@ void ConsoleProcess::stubConnectionAvailable()
     connect(m_stubSocket, SIGNAL(readyRead()), SLOT(readStubOutput()));
 }
 
-static QString errorMsg(int code)
-{
-    LPVOID lpMsgBuf;
-
-    int len = FormatMessage(
-        FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
-        NULL, (DWORD)code, 0, (LPTSTR)&lpMsgBuf, 0, NULL);
-    QString ret = QString::fromUtf16((ushort *)lpMsgBuf, len);
-    LocalFree(lpMsgBuf);
-    return ret;
-}
-
 void ConsoleProcess::readStubOutput()
 {
     while (m_stubSocket->canReadLine()) {
@@ -192,10 +181,10 @@ void ConsoleProcess::readStubOutput()
         out.chop(2); // \r\n
         if (out.startsWith("err:chdir ")) {
             emit processError(tr("Cannot change to working directory %1: %2")
-                              .arg(workingDirectory(), errorMsg(out.mid(10).toInt())));
+                              .arg(workingDirectory(), winErrorMessage(out.mid(10).toInt())));
         } else if (out.startsWith("err:exec ")) {
             emit processError(tr("Cannot execute %1: %2")
-                              .arg(m_executable, errorMsg(out.mid(9).toInt())));
+                              .arg(m_executable, winErrorMessage(out.mid(9).toInt())));
         } else if (out.startsWith("pid ")) {
             // Will not need it any more
             delete m_tempFile;
@@ -207,7 +196,7 @@ void ConsoleProcess::readStubOutput()
                     FALSE, m_appPid);
             if (m_hInferior == NULL) {
                 emit processError(tr("Cannot obtain a handle to the inferior: %1")
-                                  .arg(errorMsg(GetLastError())));
+                                  .arg(winErrorMessage(GetLastError())));
                 // Uhm, and now what?
                 continue;
             }
@@ -237,7 +226,7 @@ void ConsoleProcess::inferiorExited()
 
     if (!GetExitCodeProcess(m_hInferior, &chldStatus))
         emit processError(tr("Cannot obtain exit status from inferior: %1")
-                          .arg(errorMsg(GetLastError())));
+                          .arg(winErrorMessage(GetLastError())));
     cleanupInferior();
     m_appStatus = QProcess::NormalExit;
     m_appCode = chldStatus;
diff --git a/src/libs/utils/utils.pro b/src/libs/utils/utils.pro
index e8a5451602faf968633c92b3f3ed4658c8d8ec13..5c33948ae12ad77f6a19099dce9513eb42975500 100644
--- a/src/libs/utils/utils.pro
+++ b/src/libs/utils/utils.pro
@@ -26,8 +26,13 @@ SOURCES += \
     submiteditorwidget.cpp \
     synchronousprocess.cpp
 
-win32:SOURCES += consoleprocess_win.cpp
-else:SOURCES += consoleprocess_unix.cpp
+win32 {
+    SOURCES += consoleprocess_win.cpp \
+               winutils.cpp
+    HEADERS += winutils.h
+} else {
+    SOURCES += consoleprocess_unix.cpp
+}
 
 HEADERS += \
     utils_global.h \
diff --git a/src/libs/utils/winutils.cpp b/src/libs/utils/winutils.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..3fd789707e6812e8ee3840b903811e4b44092bd0
--- /dev/null
+++ b/src/libs/utils/winutils.cpp
@@ -0,0 +1,56 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact:  Qt Software Information (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+**
+**************************************************************************/
+
+#include "winutils.h"
+#include <windows.h>
+
+#include <QtCore/QString>
+
+namespace Core {
+namespace Utils {
+
+QWORKBENCH_UTILS_EXPORT QString winErrorMessage(unsigned long error)
+{
+    QString rc = QString::fromLatin1("#%1: ").arg(error);
+    ushort *lpMsgBuf;
+
+    const int len = FormatMessage(
+            FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
+            NULL, error, 0, (LPTSTR)&lpMsgBuf, 0, NULL);
+    if (len) {
+        rc = QString::fromUtf16(lpMsgBuf, len);
+        LocalFree(lpMsgBuf);
+    } else {
+        rc += QString::fromLatin1("<unknown error>");
+    }
+    return rc;
+}
+
+} // namespace Utils
+} // namespace Core
diff --git a/src/libs/utils/winutils.h b/src/libs/utils/winutils.h
new file mode 100644
index 0000000000000000000000000000000000000000..112537502998213a2259492ab6d93786d50d4b97
--- /dev/null
+++ b/src/libs/utils/winutils.h
@@ -0,0 +1,48 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact:  Qt Software Information (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+**
+**************************************************************************/
+
+#ifndef WINUTILS_H
+#define WINUTILS_H
+
+#include "utils_global.h"
+
+QT_BEGIN_NAMESPACE
+class QString;
+QT_END_NAMESPACE
+
+namespace Core {
+namespace Utils {
+
+// Helper to format a Windows error message, taking the
+// code as returned by the GetLastError()-API.
+QWORKBENCH_UTILS_EXPORT QString winErrorMessage(unsigned long error);
+
+} // namespace Utils
+} // namespace Core
+#endif // WINUTILS_H
diff --git a/src/plugins/debugger/cdb/cdbdebugengine.cpp b/src/plugins/debugger/cdb/cdbdebugengine.cpp
index 42525ede28faa42947ce69cac93c90d3e62a0533..4217378cf2ea758cae186bf9024e6b9a4656ff80 100644
--- a/src/plugins/debugger/cdb/cdbdebugengine.cpp
+++ b/src/plugins/debugger/cdb/cdbdebugengine.cpp
@@ -198,7 +198,7 @@ bool CdbDebugEngine::startDebugger()
     m_d->m_pDebugSymbols->SetSymbolOptions(SYMOPT_CASE_INSENSITIVE | SYMOPT_UNDNAME | SYMOPT_LOAD_LINES | SYMOPT_OMAP_FIND_NEAREST | SYMOPT_AUTO_PUBLICS);
     //m_pDebugSymbols->AddSymbolOptions(SYMOPT_CASE_INSENSITIVE | SYMOPT_UNDNAME | SYMOPT_DEFERRED_LOADS | SYMOPT_DEBUG | SYMOPT_LOAD_LINES | SYMOPT_OMAP_FIND_NEAREST | SYMOPT_AUTO_PUBLICS | SYMOPT_NO_IMAGE_SEARCH);
 
-    if (m_d->m_debuggerManager->startMode() == DebuggerManager::AttachExternal) {
+    if (m_d->m_debuggerManager->startMode() == AttachExternal) {
         qWarning("CdbDebugEngine: attach to process not yet implemented!");
         return false;
     } else {
diff --git a/src/plugins/debugger/debugger.pro b/src/plugins/debugger/debugger.pro
index 7e302efff62bfb77324e55ca3fd6dbcb43389cd5..accff656e85b464a5bd17206bdf926300956be8d 100644
--- a/src/plugins/debugger/debugger.pro
+++ b/src/plugins/debugger/debugger.pro
@@ -86,4 +86,7 @@ HEADERS += $$PWD/modeltest.h
 DEFINES += USE_MODEL_TEST=1
 }
 
-CONFIG(cdbdebugger):include(cdb\cdb.pri)
+win32 {
+    include(win/win.pri)
+    CONFIG(cdbdebugger):include(cdb\cdb.pri)
+}    
diff --git a/src/plugins/debugger/debuggerconstants.h b/src/plugins/debugger/debuggerconstants.h
index e9f07442999d75d40b62460e1dce44140e9fa456..c1369aa3298d93eb87150a2ae646aa0105601281 100644
--- a/src/plugins/debugger/debuggerconstants.h
+++ b/src/plugins/debugger/debuggerconstants.h
@@ -53,6 +53,9 @@ const char * const GDBRUNNING           = "Gdb.Running";
 
 const char * const PROPERTY_REGISTER_FORMAT = "Debugger.Property.RegisterFormat";
 
+namespace Internal {
+    enum { debug = 0 };
+}
 } // namespace Constants
 } // namespace Debugger
 
diff --git a/src/plugins/debugger/debuggermanager.cpp b/src/plugins/debugger/debuggermanager.cpp
index 3b1a0acffa4dd8a36c23592bb60730cf7936ea5d..3f21b4a4a1e384cf19144ffd2f875efc08d97b86 100644
--- a/src/plugins/debugger/debuggermanager.cpp
+++ b/src/plugins/debugger/debuggermanager.cpp
@@ -52,7 +52,9 @@
 #include "watchhandler.h"
 
 #include "debuggerdialogs.h"
-
+#ifdef Q_OS_WIN
+#  include "peutils.h"
+#endif
 #include <utils/qtcassert.h>
 
 #include <QtCore/QDebug>
@@ -432,6 +434,8 @@ void DebuggerManager::init()
     winEngine = createWinEngine(this);
     scriptEngine = createScriptEngine(this);
     setDebuggerType(GdbDebugger);
+    if (Debugger::Constants::Internal::debug)
+        qDebug() << Q_FUNC_INFO << gdbEngine << winEngine << scriptEngine;
 }
 
 void DebuggerManager::setDebuggerType(DebuggerType type)
@@ -549,7 +553,8 @@ void DebuggerManager::clearStatusMessage()
 void DebuggerManager::showStatusMessage(const QString &msg, int timeout)
 {
     Q_UNUSED(timeout)
-    //qDebug() << "STATUS: " << msg;
+    if (Debugger::Constants::Internal::debug)
+        qDebug() << "STATUS MSG: " << msg;
     showDebuggerOutput("status:", msg);
     m_statusLabel->setText("   " + msg);
     if (timeout > 0) {
@@ -594,8 +599,9 @@ void DebuggerManager::notifyInferiorExited()
 
 void DebuggerManager::notifyInferiorPidChanged(int pid)
 {
+    if (Debugger::Constants::Internal::debug)
+        qDebug() << Q_FUNC_INFO << pid;
     //QMessageBox::warning(0, "PID", "PID: " + QString::number(pid)); 
-    //qDebug() << "PID: " << pid; 
     emit inferiorPidChanged(pid);
 }
 
@@ -606,11 +612,11 @@ void DebuggerManager::showApplicationOutput(const QString &str)
 
 void DebuggerManager::shutdown()
 {
-    //qDebug() << "DEBUGGER_MANAGER SHUTDOWN START";
-    if (m_engine) {
-        //qDebug() << "SHUTTING DOWN ENGINE" << m_engine;
+    if (Debugger::Constants::Internal::debug)
+        qDebug() << Q_FUNC_INFO << m_engine;
+
+    if (m_engine)
         m_engine->shutdown();
-    }
     m_engine = 0;
 
     delete scriptEngine;
@@ -673,6 +679,9 @@ void DebuggerManager::toggleBreakpoint()
 
 void DebuggerManager::toggleBreakpoint(const QString &fileName, int lineNumber)
 {
+    if (Debugger::Constants::Internal::debug)
+        qDebug() << Q_FUNC_INFO << fileName << lineNumber;
+
     QTC_ASSERT(m_engine, return);
     QTC_ASSERT(m_breakHandler, return);
     if (status() != DebuggerInferiorRunning
@@ -779,8 +788,43 @@ void DebuggerManager::attachCore()
         emit debuggingFinished();
 }
 
+// Figure out the debugger type of an exexcutable
+static bool determineDebuggerType(const QString &executable,
+                                  DebuggerManager::DebuggerType *dt,
+                                  QString *errorMessage)
+{
+    if (executable.endsWith(QLatin1String(".js"))) {
+        *dt = DebuggerManager::ScriptDebugger;
+        return true;
+    }
+#ifndef Q_WS_WIN
+    *dt = DebuggerManager::GdbDebugger;
+    return true;
+#else
+    // If a file has PDB files, it has been compiled by VS.
+    QStringList pdbFiles;
+    if (!getPDBFiles(executable, &pdbFiles, errorMessage))
+        return false;
+    if (pdbFiles.empty()) {
+        *dt = DebuggerManager::GdbDebugger;
+        return true;
+    }
+    // We need the CDB debugger in order to be able to debug VS
+    // executables
+    if (!winEngine) {
+        *errorMessage = DebuggerManager::tr("Debugging VS executables is not supported.");
+        return false;
+    }
+    *dt = DebuggerManager::WinDebugger;
+    return true;
+#endif
+}
+
 bool DebuggerManager::startNewDebugger(DebuggerStartMode mode)
 {
+    if (Debugger::Constants::Internal::debug)
+        qDebug() << Q_FUNC_INFO << mode;
+
     m_startMode = mode;
     // FIXME: Clean up
 
@@ -858,11 +902,18 @@ bool DebuggerManager::startNewDebugger(DebuggerStartMode mode)
 
     emit debugModeRequested();
 
-    if (m_executable.endsWith(".js"))
-        setDebuggerType(ScriptDebugger);
-    else 
-        setDebuggerType(GdbDebugger);
+    DebuggerType type;
+    QString errorMessage;
+    if (!determineDebuggerType(m_executable, &type, &errorMessage)) {
+        QMessageBox::warning(mainWindow(), tr("Warning"),
+                tr("Cannot debug '%1': %2").arg(m_executable, errorMessage));
+        return false;
+
+    }
+    if (Debugger::Constants::Internal::debug)
+        qDebug() << m_executable << type;
 
+    setDebuggerType(type);
     setStatus(DebuggerProcessStartingUp);
     if (!m_engine->startDebugger()) {
         setStatus(DebuggerProcessNotReady);
@@ -886,7 +937,9 @@ void DebuggerManager::cleanupViews()
 
 void DebuggerManager::exitDebugger()
 {
-    //qDebug() << "DebuggerManager::exitDebugger";
+    if (Debugger::Constants::Internal::debug)
+        qDebug() << Q_FUNC_INFO;
+
     if (m_engine)
         m_engine->exitDebugger();
     cleanupViews();
@@ -962,6 +1015,9 @@ void DebuggerManager::nextIExec()
 
 void DebuggerManager::executeDebuggerCommand(const QString &command)
 {
+    if (Debugger::Constants::Internal::debug)
+        qDebug() << Q_FUNC_INFO <<command;
+
     QTC_ASSERT(m_engine, return);
     m_engine->executeDebuggerCommand(command);
 }
@@ -1030,6 +1086,9 @@ void DebuggerManager::watchExpression(const QString &expression)
 
 void DebuggerManager::setBreakpoint(const QString &fileName, int lineNumber)
 {
+    if (Debugger::Constants::Internal::debug)
+        qDebug() << Q_FUNC_INFO << fileName << lineNumber;
+
     QTC_ASSERT(m_breakHandler, return);
     QTC_ASSERT(m_engine, return);
     m_breakHandler->setBreakpoint(fileName, lineNumber);
@@ -1062,7 +1121,8 @@ void DebuggerManager::breakAtMain()
 
 void DebuggerManager::setStatus(int status)
 {
-    //qDebug() << "STATUS CHANGE: from" << m_status << "to" << status;
+    if (Debugger::Constants::Internal::debug)
+        qDebug() << Q_FUNC_INFO << "STATUS CHANGE: from" << m_status << "to" << status;
 
     if (status == m_status)
         return;
@@ -1179,8 +1239,9 @@ void DebuggerManager::continueExec()
 
 void DebuggerManager::interruptDebuggingRequest()
 {
+    if (Debugger::Constants::Internal::debug)
+        qDebug() << Q_FUNC_INFO << status();
     QTC_ASSERT(m_engine, return);
-    //qDebug() << "INTERRUPTING AT" << status();
     bool interruptIsExit = (status() != DebuggerInferiorRunning);
     if (interruptIsExit)
         exitDebugger();
@@ -1197,8 +1258,11 @@ void DebuggerManager::runToLineExec()
     QString fileName;
     int lineNumber = -1;
     emit currentTextEditorRequested(&fileName, &lineNumber, 0);
-    if (!fileName.isEmpty())
+    if (!fileName.isEmpty()) {
+        if (Debugger::Constants::Internal::debug)
+            qDebug() << Q_FUNC_INFO << fileName << lineNumber;
         m_engine->runToLineExec(fileName, lineNumber);
+    }
 }
 
 void DebuggerManager::runToFunctionExec()
@@ -1228,7 +1292,9 @@ void DebuggerManager::runToFunctionExec()
             }
         }
     }
-    //qDebug() << "RUN TO FUNCTION " << functionName;
+    if (Debugger::Constants::Internal::debug)
+        qDebug() << Q_FUNC_INFO << functionName;
+
     if (!functionName.isEmpty())
         m_engine->runToFunctionExec(functionName);
 }
@@ -1238,8 +1304,11 @@ void DebuggerManager::jumpToLineExec()
     QString fileName;
     int lineNumber = -1;
     emit currentTextEditorRequested(&fileName, &lineNumber, 0);
-    if (!fileName.isEmpty())
+    if (!fileName.isEmpty()) {
+        if (Debugger::Constants::Internal::debug)
+            qDebug() << Q_FUNC_INFO << fileName << lineNumber;
         m_engine->jumpToLineExec(fileName, lineNumber);
+    }
 }
 
 void DebuggerManager::resetLocation()
diff --git a/src/plugins/debugger/win/peutils.cpp b/src/plugins/debugger/win/peutils.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..23cabb8bc3bf0a3b04032ee4742e96ebe058a94b
--- /dev/null
+++ b/src/plugins/debugger/win/peutils.cpp
@@ -0,0 +1,279 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact:  Qt Software Information (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+**
+**************************************************************************/
+
+#include "peutils.h"
+
+#include <utils/winutils.h>
+#include <QtCore/QStringList>
+#include <QtCore/QDebug>
+#include <windows.h>
+
+using Core::Utils::winErrorMessage;
+
+// Create a pointer from base and offset when rummaging around in
+// a memory mapped file
+
+template <class Ptr>
+        inline Ptr *makePtr(void *base, ptrdiff_t offset)
+{
+    return reinterpret_cast<Ptr*>(static_cast<char*>(base) + offset);
+}
+
+// CodeView header
+struct CV_HEADER
+{
+    DWORD CvSignature; // NBxx
+    LONG  Offset;      // Always 0 for NB10
+};
+
+// CodeView NB10 debug information of a PDB 2.00 file (VS 6)
+struct CV_INFO_PDB20
+{
+    CV_HEADER  Header;
+    DWORD      Signature;
+    DWORD      Age;
+    BYTE       PdbFileName[1];
+};
+
+// CodeView RSDS debug information of a PDB 7.00 file
+struct CV_INFO_PDB70
+{
+    DWORD      CvSignature;
+    GUID       Signature;
+    DWORD      Age;
+    BYTE       PdbFileName[1];
+};
+
+// Retrieve the NT image header of an executable via the legacy DOS header.
+static IMAGE_NT_HEADERS *getNtHeader(void *fileMemory, QString *errorMessage)
+{
+    IMAGE_DOS_HEADER *dosHeader = static_cast<PIMAGE_DOS_HEADER>(fileMemory);
+    // Check DOS header consistency
+    if (IsBadReadPtr(dosHeader, sizeof(IMAGE_DOS_HEADER))
+        || dosHeader->e_magic != IMAGE_DOS_SIGNATURE) {
+        *errorMessage = QString::fromLatin1("DOS header check failed.");
+        return 0;
+    }
+    // Retrieve NT header
+    IMAGE_NT_HEADERS *ntHeaders = makePtr<IMAGE_NT_HEADERS>(dosHeader, dosHeader->e_lfanew);
+    // check NT header consistency
+    if (IsBadReadPtr(ntHeaders, sizeof(ntHeaders->Signature))
+        || ntHeaders->Signature != IMAGE_NT_SIGNATURE
+        || IsBadReadPtr(&ntHeaders->FileHeader, sizeof(IMAGE_FILE_HEADER))) {
+        *errorMessage = QString::fromLatin1("NT header check failed.");
+        return 0;
+    }
+    // Check magic
+    const WORD magic = ntHeaders->OptionalHeader.Magic;
+#ifdef  __GNUC__ // MinGW does not have complete 64bit definitions.
+    if (magic != 0x10b) {
+        *errorMessage = QString::fromLatin1("NT header check failed; magic %1 is not that of a 32-bit executable.").
+                        arg(magic);
+        return 0;
+    }
+#else
+    if (magic != IMAGE_NT_OPTIONAL_HDR32_MAGIC && magic != IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
+        *errorMessage = QString::fromLatin1("NT header check failed; magic %1 is none of %2, %3.").
+                        arg(magic).arg(IMAGE_NT_OPTIONAL_HDR32_MAGIC).arg(IMAGE_NT_OPTIONAL_HDR64_MAGIC);
+        return 0;
+    }
+#endif
+    // Check section headers
+    IMAGE_SECTION_HEADER *sectionHeaders = IMAGE_FIRST_SECTION(ntHeaders);
+    if (IsBadReadPtr(sectionHeaders, ntHeaders->FileHeader.NumberOfSections * sizeof(IMAGE_SECTION_HEADER))) {
+        *errorMessage = QString::fromLatin1("NT header section header check failed.");
+        return 0;
+    }
+    return ntHeaders;
+}
+
+// Find the COFF section an RVA belongs to and convert to file offset
+static bool getFileOffsetFromRVA(IMAGE_NT_HEADERS *ntHeaders, DWORD rva, DWORD* fileOffset)
+{
+    IMAGE_SECTION_HEADER *sectionHeader = IMAGE_FIRST_SECTION(ntHeaders);
+    for( int i = 0; i < ntHeaders->FileHeader.NumberOfSections; i++, sectionHeader++ ) {
+        const DWORD sectionSize = sectionHeader->Misc.VirtualSize ?
+                                  sectionHeader->Misc.VirtualSize : sectionHeader->SizeOfRawData;
+        if ((rva >= sectionHeader->VirtualAddress) && (rva < sectionHeader->VirtualAddress + sectionSize)) {
+            const DWORD diff = sectionHeader->VirtualAddress - sectionHeader->PointerToRawData;
+            *fileOffset = rva - diff;
+            return true;
+        }
+    }
+    return false;
+}
+
+// Retrieve debug directory and number of entries
+static bool getDebugDirectory(IMAGE_NT_HEADERS *ntHeaders,
+			      void *fileMemory,
+                              IMAGE_DEBUG_DIRECTORY **debugDir,
+			      int *count,
+			      QString *errorMessage)
+{
+    DWORD debugDirRva = 0;
+    DWORD debugDirSize;
+    *debugDir = 0;
+    *count = 0;
+#ifdef  __GNUC__ // MinGW does not have complete 64bit definitions.
+    typedef IMAGE_OPTIONAL_HEADER IMAGE_OPTIONAL_HEADER32;
+#else
+    // Find the virtual address
+    const bool is64Bit = ntHeaders->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC;
+    if (is64Bit) {
+        IMAGE_OPTIONAL_HEADER64 *optionalHeader64 = reinterpret_cast<IMAGE_OPTIONAL_HEADER64*>(&(ntHeaders->OptionalHeader));
+        debugDirRva = optionalHeader64->DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress;
+        debugDirSize = optionalHeader64->DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].Size;
+    } else {
+#endif
+        IMAGE_OPTIONAL_HEADER32 *optionalHeader32 = reinterpret_cast<IMAGE_OPTIONAL_HEADER32*>(&(ntHeaders->OptionalHeader));
+        debugDirRva = optionalHeader32->DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress;
+        debugDirSize = optionalHeader32->DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].Size;
+#ifndef  __GNUC__
+    }
+#endif
+    // Empty. This is the case for MinGW binaries
+    if (debugDirSize == 0)
+        return true;    
+    // Look up in  file
+    DWORD debugDirOffset;
+    if (!getFileOffsetFromRVA(ntHeaders, debugDirRva, &debugDirOffset)) {
+        *errorMessage = QString::fromLatin1("Unable to locate debug dir RVA %1/%2.").arg(debugDirRva).arg(debugDirSize);
+        return false;
+    }
+    *debugDir = makePtr<IMAGE_DEBUG_DIRECTORY>(fileMemory, debugDirOffset);
+    // Check
+    if (IsBadReadPtr(*debugDir, debugDirSize) || debugDirSize < sizeof(IMAGE_DEBUG_DIRECTORY)) {
+        *errorMessage = QString::fromLatin1("Debug directory corrupted.");
+        return 0;
+    }
+
+    *count = debugDirSize / sizeof(IMAGE_DEBUG_DIRECTORY);
+    return debugDir;
+}
+
+// Return the PDB file of a Code View debug section
+static QString getPDBFileOfCodeViewSection(void *debugInfo, DWORD size)
+{
+    static const DWORD CV_SIGNATURE_NB10 = 0x3031424e; // '01BN';
+    static const DWORD CV_SIGNATURE_RSDS = 0x53445352; // 'SDSR';
+    if (IsBadReadPtr(debugInfo, size) || size < sizeof(DWORD))
+        return QString();
+
+    const DWORD cvSignature = *static_cast<DWORD*>(debugInfo);
+    if (cvSignature == CV_SIGNATURE_NB10) {
+        CV_INFO_PDB20* cvInfo = static_cast<CV_INFO_PDB20*>(debugInfo);
+        if (IsBadReadPtr(debugInfo, sizeof(CV_INFO_PDB20)))
+            return QString();
+        CHAR* pdbFileName = reinterpret_cast<CHAR*>(cvInfo->PdbFileName);
+        if (IsBadStringPtrA(pdbFileName, UINT_MAX))
+            return QString();
+        return QString::fromLocal8Bit(pdbFileName);
+    }
+    if (cvSignature == CV_SIGNATURE_RSDS) {
+        CV_INFO_PDB70* cvInfo = static_cast<CV_INFO_PDB70*>(debugInfo);
+        if (IsBadReadPtr(debugInfo, sizeof(CV_INFO_PDB70)))
+            return QString();
+        CHAR* pdbFileName = reinterpret_cast<CHAR*>(cvInfo->PdbFileName);
+        if (IsBadStringPtrA(pdbFileName, UINT_MAX))
+            return QString();
+        return QString::fromLocal8Bit(pdbFileName);
+    }
+    return QString();
+}
+
+// Collect all PDB files of all debug sections
+static void collectPDBfiles(void *fileMemory, IMAGE_DEBUG_DIRECTORY *directoryBase, int count, QStringList *pdbFiles)
+{
+    for (int i = 0; i < count; i++, directoryBase++)
+        if (directoryBase->Type == IMAGE_DEBUG_TYPE_CODEVIEW) {
+           const QString pdb = getPDBFileOfCodeViewSection(static_cast<char*>(fileMemory) + directoryBase->PointerToRawData, directoryBase->SizeOfData);
+           if (!pdb.isEmpty())
+               pdbFiles->push_back(pdb);
+       }
+}
+
+namespace Debugger {
+namespace Internal {
+   
+bool getPDBFiles(const QString &peExecutableFileName, QStringList *rc, QString *errorMessage)
+{
+    HANDLE hFile = NULL;
+    HANDLE hFileMap = NULL;
+    void *fileMemory = 0;
+    bool success = false;
+
+    rc->clear();
+    do {
+        // Create a memory mapping of the file
+        hFile = CreateFile(reinterpret_cast<const WCHAR*>(peExecutableFileName.utf16()), GENERIC_READ, FILE_SHARE_READ, NULL,
+                             OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+        if (hFile == INVALID_HANDLE_VALUE || hFile == NULL) {
+            *errorMessage = QString::fromLatin1("Cannot open '%1': %2").arg(peExecutableFileName, winErrorMessage(GetLastError()));
+            break;
+        }
+
+        hFileMap = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
+        if (hFileMap == NULL) {
+            *errorMessage = QString::fromLatin1("Cannot create file mapping of '%1': %2").arg(peExecutableFileName, winErrorMessage(GetLastError()));
+            break;
+        }
+
+        fileMemory = MapViewOfFile(hFileMap, FILE_MAP_READ, 0, 0, 0);
+        if(!fileMemory) {
+            *errorMessage = QString::fromLatin1("Cannot map '%1': %2").arg(peExecutableFileName, winErrorMessage(GetLastError()));
+            break;
+        }
+
+        IMAGE_NT_HEADERS *ntHeaders = getNtHeader(fileMemory, errorMessage);
+        if (!ntHeaders)
+            break;
+
+        int debugSectionCount;
+        IMAGE_DEBUG_DIRECTORY *debugDir;
+        if (!getDebugDirectory(ntHeaders, fileMemory, &debugDir, &debugSectionCount, errorMessage))
+            return false;
+        if (debugSectionCount)
+            collectPDBfiles(fileMemory, debugDir, debugSectionCount, rc);
+        success = true;
+    }  while(false);
+
+    if (fileMemory)
+        UnmapViewOfFile(fileMemory);
+
+    if (hFileMap != NULL)
+        CloseHandle(hFileMap);
+
+    if (hFile != NULL && hFile != INVALID_HANDLE_VALUE)
+        CloseHandle(hFile);
+
+    return success;
+}
+
+}
+}
diff --git a/src/plugins/debugger/win/peutils.h b/src/plugins/debugger/win/peutils.h
new file mode 100644
index 0000000000000000000000000000000000000000..c9885991be903527b0052dfd07fa4c3304dae017
--- /dev/null
+++ b/src/plugins/debugger/win/peutils.h
@@ -0,0 +1,51 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact:  Qt Software Information (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+**
+**************************************************************************/
+
+#ifndef PEUTILS_H
+#define PEUTILS_H
+
+#include <QtCore/qnamespace.h>
+
+QT_BEGIN_NAMESPACE
+class QStringList;
+class QString;
+QT_END_NAMESPACE
+
+/* Helper functions to extract information from PE Win32 executable
+ * files (cf dumpbin utility). */
+namespace Debugger {
+namespace Internal {
+
+// Return a list of Program-Database (*.pdb) files a PE executable refers to. */
+bool getPDBFiles(const QString &peExecutableFileName, QStringList *rc, QString *errorMessage);
+
+}
+}
+
+#endif // PEUTILS_H
diff --git a/src/plugins/debugger/win/win.pri b/src/plugins/debugger/win/win.pri
new file mode 100644
index 0000000000000000000000000000000000000000..7eaa43a63007e497879432e8e2497c3c256c4556
--- /dev/null
+++ b/src/plugins/debugger/win/win.pri
@@ -0,0 +1,3 @@
+INCLUDEPATH+=$$PWD
+SOURCES += $$PWD/peutils.cpp
+HEADERS += $$PWD/peutils.h