diff --git a/src/plugins/debugger/cdb/cdbbreakpoint.cpp b/src/plugins/debugger/cdb/cdbbreakpoint.cpp
index 035c5d76fca5dc19baaf6f0449cae2dbe518cd1d..345ed2f96807cb23c5464d0ecd0d0a944ebabe88 100644
--- a/src/plugins/debugger/cdb/cdbbreakpoint.cpp
+++ b/src/plugins/debugger/cdb/cdbbreakpoint.cpp
@@ -28,6 +28,7 @@
 **************************************************************************/
 
 #include "cdbbreakpoint.h"
+#include "cdbmodules.h"
 #include "breakhandler.h"
 #include "cdbdebugengine_p.h"
 
@@ -279,20 +280,48 @@ bool CDBBreakPoint::getBreakPoints(IDebugControl4* debugControl, QList<CDBBreakP
     return true;
 }
 
+
 // Synchronize (halted) engine breakpoints with those of the BreakHandler.
 bool CDBBreakPoint::synchronizeBreakPoints(IDebugControl4* debugControl,
+                                           IDebugSymbols3 *syms,
                                            BreakHandler *handler,
                                            QString *errorMessage)
 {    
     typedef QMap<CDBBreakPoint, int> BreakPointIndexMap;
-    BreakPointIndexMap breakPointIndexMap;
-    // convert BreakHandler's bps into a map of BreakPoint->BreakHandler->Index
     if (debugCDB)
         qDebug() << Q_FUNC_INFO;
 
+    BreakPointIndexMap breakPointIndexMap;
+    // convert BreakHandler's bps into a map of BreakPoint->BreakHandler->Index
+    // Ignore invalid functions (that could not be found) as they make
+    // the debugger hang.
     const int handlerCount = handler->size();
-    for (int i=0; i < handlerCount; ++i)
-        breakPointIndexMap.insert(CDBBreakPoint(*handler->at(i)), i);
+    const QChar moduleDelimiter = QLatin1Char('!');
+    for (int i=0; i < handlerCount; ++i) {
+        BreakpointData *bd = handler->at(i);
+        // Function breakpoints: Are the module names specified?
+        bool breakPointOk = false;
+        if (bd->funcName.isEmpty()) {
+            breakPointOk = true;
+        } else {
+            switch (resolveSymbol(syms, &bd->funcName, errorMessage)) {
+            case ResolveSymbolOk:
+                breakPointOk = true;
+                break;
+            case ResolveSymbolAmbiguous:
+                qWarning("Warning: %s\n", qPrintable(*errorMessage));
+                breakPointOk = true;
+                break;
+            case ResolveSymbolNotFound:
+            case ResolveSymbolError:
+                qWarning("Warning: %s\n", qPrintable(*errorMessage));
+                break;
+            };
+        } // function breakpoint
+        if (breakPointOk)
+            breakPointIndexMap.insert(CDBBreakPoint(*bd), i);
+    }
+    errorMessage->clear();
     // get number of engine breakpoints
     ULONG engineCount;
     if (!getBreakPointCount(debugControl, &engineCount, errorMessage))
diff --git a/src/plugins/debugger/cdb/cdbbreakpoint.h b/src/plugins/debugger/cdb/cdbbreakpoint.h
index 2abdddcb94273e211e4dfe80de4b497eb5ebecd5..3040c0895f030692d0950e80539f59becd7b3531 100644
--- a/src/plugins/debugger/cdb/cdbbreakpoint.h
+++ b/src/plugins/debugger/cdb/cdbbreakpoint.h
@@ -72,7 +72,8 @@ struct CDBBreakPoint {
     static bool getBreakPointCount(IDebugControl4* debugControl, ULONG *count, QString *errorMessage = 0);
     static bool getBreakPoints(IDebugControl4* debugControl, QList<CDBBreakPoint> *bps, QString *errorMessage);
     // Synchronize (halted) engine with BreakHandler.
-    static bool synchronizeBreakPoints(IDebugControl4* ctl, BreakHandler *bh, QString *errorMessage);
+    static bool synchronizeBreakPoints(IDebugControl4* ctl, IDebugSymbols3 *syms,
+                                       BreakHandler *bh, QString *errorMessage);
 
     // Return a 'canonical' file (using '/' and capitalized drive letter)
     static QString canonicalSourceFile(const QString &f);
diff --git a/src/plugins/debugger/cdb/cdbdebugengine.cpp b/src/plugins/debugger/cdb/cdbdebugengine.cpp
index 77efd2d4d0b264aac4c493874e44eaabc4958ebd..cf42ce3faf25bbe91a5d79d87256afe6829b5487 100644
--- a/src/plugins/debugger/cdb/cdbdebugengine.cpp
+++ b/src/plugins/debugger/cdb/cdbdebugengine.cpp
@@ -208,7 +208,7 @@ CdbDebugEnginePrivate::CdbDebugEnginePrivate(DebuggerManager *parent, CdbDebugEn
     m_currentStackTrace(0),
     m_firstActivatedFrame(true),
     m_mode(AttachCore)
-{   
+{
 }
 
 bool CdbDebugEnginePrivate::init(QString *errorMessage)
@@ -252,7 +252,7 @@ bool CdbDebugEnginePrivate::init(QString *errorMessage)
     hr = lib.debugCreate( __uuidof(IDebugRegisters2), reinterpret_cast<void**>(&m_pDebugRegisters));
     if (FAILED(hr)) {
         *errorMessage = QString::fromLatin1("Creation of IDebugRegisters2 failed: %1").arg(msgDebugEngineComResult(hr));
-        return false;    
+        return false;
     }
     if (debugCDB)
         qDebug() << QString::fromLatin1("CDB Initialization succeeded, interrupt time out %1s.").arg(getInterruptTimeOutSecs(m_pDebugControl));
@@ -299,7 +299,7 @@ void CdbDebugEnginePrivate::clearForRun()
 }
 
 void CdbDebugEnginePrivate::cleanStackTrace()
-{    
+{
     if (m_currentStackTrace) {
         delete m_currentStackTrace;
         m_currentStackTrace = 0;
@@ -366,7 +366,7 @@ void CdbDebugEnginePrivate::clearDisplay()
 }
 
 bool CdbDebugEngine::startDebugger()
-{    
+{
     m_d->clearDisplay();
     m_d->m_debuggerManager->showStatusMessage("Starting Debugger", -1);
     QString errorMessage;
@@ -489,7 +489,7 @@ void CdbDebugEngine::exitDebugger()
         // Terminate or detach if we are running
         HRESULT hr;
         switch (m_d->m_mode) {
-        case AttachExternal:            
+        case AttachExternal:
             wasRunning = m_d->isDebuggeeRunning();
             if (wasRunning) { // Process must be stopped in order to detach
                 m_d->interruptInterferiorProcess(&errorMessage);
@@ -502,7 +502,7 @@ void CdbDebugEngine::exitDebugger()
                 qDebug() << Q_FUNC_INFO << "detached" << msgDebugEngineComResult(hr);
             break;
         case StartExternal:
-        case StartInternal:            
+        case StartInternal:
             wasRunning = m_d->isDebuggeeRunning();
             if (wasRunning) { // Process must be stopped in order to terminate
                 m_d->interruptInterferiorProcess(&errorMessage);
@@ -569,7 +569,7 @@ bool CdbDebugEnginePrivate::updateLocals(int frameIndex,
         qDebug() << Q_FUNC_INFO << "\n    " << frameIndex << formatWatchList(incompletes);
 
     m_engine->filterEvaluateWatchers(&incompletes, wh);
-    if (!incompletes.empty()) {        
+    if (!incompletes.empty()) {
         const QString msg = QLatin1String("Warning: Locals left in incomplete list: ") + formatWatchList(incompletes);
         qWarning("%s\n", qPrintable(msg));
     }
@@ -613,7 +613,7 @@ void CdbDebugEngine::filterEvaluateWatchers(QList<WatchData> *wd, WatchHandler *
     bool placeHolderSeen = false;
     for (WatchList::iterator it = wd->begin(); it != wd->end(); ) {
         if (it->iname.startsWith(watcherPrefix)) {
-            const bool isPlaceHolder = it->exp.startsWith(lessThan) && it->exp.endsWith(greaterThan);            
+            const bool isPlaceHolder = it->exp.startsWith(lessThan) && it->exp.endsWith(greaterThan);
             if (isPlaceHolder) {
                 if (!placeHolderSeen) { // Max one place holder
                     it->setChildCount(0);
@@ -624,7 +624,7 @@ void CdbDebugEngine::filterEvaluateWatchers(QList<WatchData> *wd, WatchHandler *
             } else {
                 evaluateWatcher(&(*it));
                 wh->insertData(*it);
-            }            
+            }
             it = wd->erase(it);
         } else {
             ++it;
@@ -778,7 +778,7 @@ bool CdbDebugEnginePrivate::continueInferiorProcess(QString *errorMessage)
 
 // Continue process with notifications
 bool CdbDebugEnginePrivate::continueInferior(QString *errorMessage)
-{   
+{
     ULONG executionStatus;
     if (!getExecutionStatus(m_pDebugControl, &executionStatus, errorMessage))
         return false;
@@ -817,7 +817,7 @@ bool CdbDebugEnginePrivate::interruptInterferiorProcess(QString *errorMessage)
         *errorMessage = QString::fromLatin1("DebugBreakProcess failed: %1").arg(Core::Utils::winErrorMessage(GetLastError()));
         return false;
     }
-#if 0    
+#if 0
     const HRESULT hr = m_pDebugControl->SetInterrupt(DEBUG_INTERRUPT_ACTIVE|DEBUG_INTERRUPT_EXIT);
     if (FAILED(hr)) {
         *errorMessage = QString::fromLatin1("Unable to interrupt debuggee after %1s: %2").
@@ -864,7 +864,7 @@ void CdbDebugEngine::assignValueInDebugger(const QString &expr, const QString &v
     if (debugCDB)
         qDebug() << Q_FUNC_INFO << expr << value;
     const int frameIndex = m_d->m_debuggerManagerAccess->stackHandler()->currentIndex();
-    QString errorMessage;    
+    QString errorMessage;
     bool success = false;
     do {
         QString newValue;
@@ -872,7 +872,7 @@ void CdbDebugEngine::assignValueInDebugger(const QString &expr, const QString &v
         if (!sg)
             break;
         if (!sg->assignValue(expr, value, &newValue, &errorMessage))
-            break;        
+            break;
         // Update view
         WatchHandler *watchHandler = m_d->m_debuggerManagerAccess->watchHandler();
         if (WatchData *fwd = watchHandler->findData(expr)) {
@@ -1032,6 +1032,7 @@ bool CdbDebugEnginePrivate::attemptBreakpointSynchronization(QString *errorMessa
     }
 
     return CDBBreakPoint::synchronizeBreakPoints(m_pDebugControl,
+                                                 m_pDebugSymbols,
                                                  m_debuggerManagerAccess->breakHandler(),
                                                  errorMessage);
 }
@@ -1045,7 +1046,7 @@ void CdbDebugEngine::saveSessionData()
 }
 
 void CdbDebugEngine::reloadDisassembler()
-{    
+{
     enum { ContextLines = 40 };
     // Do we have a top stack frame?
     const ULONG64 offset = m_d->m_currentStackTrace ? m_d->m_currentStackTrace->instructionOffset() : ULONG64(0);
@@ -1140,7 +1141,7 @@ void CdbDebugEngine::timerEvent(QTimerEvent* te)
             break;
         case E_UNEXPECTED: // Occurs on ExitProcess.
             killWatchTimer();
-            break;        
+            break;
     }
 }
 
@@ -1260,6 +1261,10 @@ void CdbDebugEnginePrivate::updateStackTrace()
         qWarning("%s: failed to create trace context: %s", Q_FUNC_INFO, qPrintable(errorMessage));
         return;
     }
+    // Disassembling slows things down a bit. Assembler is still available via menu.
+#if 0
+    m_engine->reloadDisassembler(); // requires stack trace
+#endif
     const QList<StackFrame> stackFrames = m_currentStackTrace->frames();
     // find the first usable frame and select it
     int current = -1;
@@ -1275,7 +1280,7 @@ void CdbDebugEnginePrivate::updateStackTrace()
     if (current >= 0) {
         m_debuggerManagerAccess->stackHandler()->setCurrentIndex(current);
         m_engine->activateFrame(current);
-    }    
+    }
 }
 
 
diff --git a/src/plugins/debugger/cdb/cdbmodules.cpp b/src/plugins/debugger/cdb/cdbmodules.cpp
index 6e97800e8437f0cbde01b3c30f580a7fdd6dcd72..70e8bd7d52379716dd8c98965a6d490702cd9dbf 100644
--- a/src/plugins/debugger/cdb/cdbmodules.cpp
+++ b/src/plugins/debugger/cdb/cdbmodules.cpp
@@ -77,5 +77,61 @@ bool getModuleList(IDebugSymbols3 *syms, QList<Module> *modules, QString *errorM
     return true;
 }
 
+// Search symbols matching a pattern
+bool searchSymbols(IDebugSymbols3 *syms, const QString &pattern,
+                   QStringList *matches, QString *errorMessage)
+{
+    matches->clear();    
+    ULONG64 handle;
+    // E_NOINTERFACE means "no match"
+    HRESULT hr = syms->StartSymbolMatchWide(pattern.utf16(), &handle);
+    if (hr == E_NOINTERFACE) {
+        syms->EndSymbolMatch(handle);
+        return true;
+    }
+    if (FAILED(hr)) {
+        *errorMessage= msgComFailed("StartSymbolMatchWide", hr);
+        return false;
+    }
+    WCHAR wszBuf[MAX_PATH];
+    while (true) {
+        hr = syms->GetNextSymbolMatchWide(handle, wszBuf, MAX_PATH - 1, 0, 0);
+        if (hr == E_NOINTERFACE)
+            break;
+        if (hr == S_OK)
+            matches->push_back(QString::fromUtf16(wszBuf));
+    }
+    syms->EndSymbolMatch(handle);
+    if (matches->empty())
+        *errorMessage = QString::fromLatin1("No symbol matches '%1'.").arg(pattern);
+    return true;
+}
+
+// Add missing the module specifier: "main" -> "project!main"
+
+ResolveSymbolResult resolveSymbol(IDebugSymbols3 *syms, QString *symbol,
+                                  QString *errorMessage)
+{
+    // Is it an incomplete symbol?
+    if (symbol->contains(QLatin1Char('!')))
+        return ResolveSymbolOk;
+    // 'main' is a #define for gdb, but not for VS
+    if (*symbol == QLatin1String("qMain"))
+        *symbol = QLatin1String("main");
+    // resolve
+    QStringList matches;
+    if (!searchSymbols(syms, *symbol, &matches, errorMessage))
+        return ResolveSymbolError;
+    if (matches.empty())
+        return ResolveSymbolNotFound;
+    *symbol = matches.front();
+    if (matches.size() > 1) {
+        *errorMessage = QString::fromLatin1("Ambiguous symbol '%1': %2").
+                        arg(*symbol, matches.join(QString(QLatin1Char(' '))));
+        return ResolveSymbolAmbiguous;
+    }
+    return ResolveSymbolOk;
+}
+
 }
 }
diff --git a/src/plugins/debugger/cdb/cdbmodules.h b/src/plugins/debugger/cdb/cdbmodules.h
index 3a959b7f5751a5c9b355053775cef7d8219647b5..a7be7a943215a24887f49b22a97640a67e55a827 100644
--- a/src/plugins/debugger/cdb/cdbmodules.h
+++ b/src/plugins/debugger/cdb/cdbmodules.h
@@ -42,6 +42,17 @@ namespace Internal {
 class Module;
 
 bool getModuleList(IDebugSymbols3 *syms, QList<Module> *modules, QString *errorMessage);
+// Search symbols matching a pattern
+bool searchSymbols(IDebugSymbols3 *syms, const QString &pattern,
+                   QStringList *matches, QString *errorMessage);
+
+// ResolveSymbol: For symbols that are missing the module specifier,
+// find the module and expand: "main" -> "project!main".
+
+enum ResolveSymbolResult { ResolveSymbolOk, ResolveSymbolAmbiguous,
+                           ResolveSymbolNotFound, ResolveSymbolError };
+
+ResolveSymbolResult resolveSymbol(IDebugSymbols3 *syms, QString *symbol, QString *errorMessage);
 
 }
 }