OSDN Git Service

Debugger: Use Startparameters.debuggerCommand for command.
[qt-creator-jp/qt-creator-jp.git] / src / plugins / debugger / cdb / cdbengine.cpp
1 /**************************************************************************
2 **
3 ** This file is part of Qt Creator
4 **
5 ** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
6 **
7 ** Contact: Nokia Corporation (qt-info@nokia.com)
8 **
9 ** No Commercial Usage
10 **
11 ** This file contains pre-release code and may not be distributed.
12 ** You may use this file in accordance with the terms and conditions
13 ** contained in the Technology Preview License Agreement accompanying
14 ** this package.
15 **
16 ** GNU Lesser General Public License Usage
17 **
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file.  Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Nokia gives you certain additional
26 ** rights.  These rights are described in the Nokia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** If you have questions regarding the use of this file, please contact
30 ** Nokia at qt-info@nokia.com.
31 **
32 **************************************************************************/
33
34 #include "cdbengine.h"
35 #include "debuggerstartparameters.h"
36 #include "disassemblerlines.h"
37 #include "cdboptions.h"
38 #include "cdboptionspage.h"
39 #include "bytearrayinputstream.h"
40 #include "breakpoint.h"
41 #include "breakhandler.h"
42 #include "stackframe.h"
43 #include "stackhandler.h"
44 #include "watchhandler.h"
45 #include "threadshandler.h"
46 #include "moduleshandler.h"
47 #include "debuggeractions.h"
48 #include "debuggercore.h"
49 #include "registerhandler.h"
50 #include "disassembleragent.h"
51 #include "memoryagent.h"
52 #include "debuggerrunner.h"
53 #include "debuggertooltipmanager.h"
54 #include "cdbparsehelpers.h"
55 #include "watchutils.h"
56 #include "gdb/gdbmi.h"
57 #include "shared/cdbsymbolpathlisteditor.h"
58
59 #include <coreplugin/icore.h>
60 #include <texteditor/itexteditor.h>
61 #include <projectexplorer/toolchain.h>
62 #include <projectexplorer/projectexplorerconstants.h>
63
64 #include <utils/synchronousprocess.h>
65 #include <utils/winutils.h>
66 #include <utils/qtcassert.h>
67 #include <utils/savedaction.h>
68 #include <utils/consoleprocess.h>
69
70 #include <QtCore/QCoreApplication>
71 #include <QtCore/QFileInfo>
72 #include <QtCore/QDir>
73 #include <QtCore/QDebug>
74 #include <QtCore/QTextStream>
75 #include <QtCore/QDateTime>
76 #include <QtGui/QToolTip>
77 #include <QtGui/QMainWindow>
78 #include <QtGui/QMessageBox>
79
80 #ifdef Q_OS_WIN
81 #    include <utils/winutils.h>
82 #    include "dbgwinutils.h"
83 #endif
84
85 #include <cctype>
86
87 Q_DECLARE_METATYPE(Debugger::Internal::DisassemblerAgent*)
88 Q_DECLARE_METATYPE(Debugger::Internal::MemoryAgent*)
89
90 enum { debug = 0 };
91 enum { debugLocals = 0 };
92 enum { debugWatches = 0 };
93 enum { debugBreakpoints = 0 };
94
95 #if 0
96 #  define STATE_DEBUG(state, func, line, notifyFunc) qDebug("%s in %s at %s:%d", notifyFunc, stateName(state), func, line);
97 #else
98 #  define STATE_DEBUG(state, func, line, notifyFunc)
99 #endif
100
101 /*!
102     \class Debugger::Internal::CdbEngine
103
104     Cdb engine version 2: Run the CDB process on pipes and parse its output.
105     The engine relies on a CDB extension Qt Creator provides as an extension
106     library (32/64bit), which is loaded into cdb.exe. It serves to:
107
108     \list
109     \o Notify the engine about the state of the debugging session:
110         \list
111         \o idle: (hooked up with .idle_cmd) debuggee stopped
112         \o accessible: Debuggee stopped, cdb.exe accepts commands
113         \o inaccessible: Debuggee runs, no way to post commands
114         \o session active/inactive: Lost debuggee, terminating.
115         \endlist
116     \o Hook up with output/event callbacks and produce formatted output to be able
117        to catch application output and exceptions.
118     \o Provide some extension commands that produce output in a standardized (GDBMI)
119       format that ends up in handleExtensionMessage(), for example:
120       \list
121       \o pid     Return debuggee pid for interrupting.
122       \o locals  Print locals from SymbolGroup
123       \o expandLocals Expand locals in symbol group
124       \o registers, modules, threads
125       \endlist
126    \endlist
127
128    Debugger commands can be posted by calling:
129
130    \list
131
132     \o postCommand(): Does not expect a reply
133     \o postBuiltinCommand(): Run a builtin-command producing free-format, multiline output
134        that is captured by enclosing it in special tokens using the 'echo' command and
135        then invokes a callback with a CdbBuiltinCommand structure.
136     \o postExtensionCommand(): Run a command provided by the extension producing
137        one-line output and invoke a callback with a CdbExtensionCommand structure
138        (output is potentially split up in chunks).
139     \endlist
140
141
142     Startup sequence:
143     [Console: The console stub launches the process. On process startup,
144               launchCDB() is called with AttachExternal].
145     setupEngine() calls launchCDB() with the startparameters. The debuggee
146     runs into the initial breakpoint (session idle). EngineSetupOk is
147     notified (inferior still stopped). setupInferior() is then called
148     which does breakpoint synchronization and issues the extension 'pid'
149     command to obtain the inferior pid (which also hooks up the output callbacks).
150      handlePid() notifies notifyInferiorSetupOk.
151     runEngine() is then called which issues 'g' to continue the inferior.
152     Shutdown mostly uses notifyEngineSpontaneousShutdown() as cdb just quits
153     when the inferior exits (except attach modes).
154 */
155
156 using namespace ProjectExplorer;
157
158 namespace Debugger {
159 namespace Internal {
160
161 static const char localsPrefixC[] = "local.";
162
163 struct MemoryViewCookie
164 {
165     explicit MemoryViewCookie(MemoryAgent *a = 0, QObject *e = 0,
166                               quint64 addr = 0, quint64 l = 0) :
167         agent(a), editorToken(e), address(addr), length(l)
168     {}
169
170     MemoryAgent *agent;
171     QObject *editorToken;
172     quint64 address;
173     quint64 length;
174 };
175
176 } // namespace Internal
177 } // namespace Debugger
178
179 Q_DECLARE_METATYPE(Debugger::Internal::MemoryViewCookie)
180
181 namespace Debugger {
182 namespace Internal {
183
184 static inline bool isConsole(const DebuggerStartParameters &sp)
185 {
186     return (sp.startMode == StartInternal || sp.startMode == StartExternal)
187         && sp.useTerminal;
188 }
189
190 static QMessageBox *
191 nonModalMessageBox(QMessageBox::Icon icon, const QString &title, const QString &text)
192 {
193     QMessageBox *mb = new QMessageBox(icon, title, text, QMessageBox::Ok,
194                                       debuggerCore()->mainWindow());
195     mb->setAttribute(Qt::WA_DeleteOnClose);
196     mb->show();
197     return mb;
198 }
199
200 // Base data structure for command queue entries with callback
201 struct CdbCommandBase
202 {
203     typedef CdbEngine::BuiltinCommandHandler CommandHandler;
204
205     CdbCommandBase();
206     CdbCommandBase(const QByteArray  &cmd, int token, unsigned flags,
207                    unsigned nc, const QVariant &cookie);
208
209     int token;
210     unsigned flags;
211     QByteArray command;
212     QVariant cookie;
213     // Continue with another commands as specified in CommandSequenceFlags
214     unsigned commandSequence;
215 };
216
217 CdbCommandBase::CdbCommandBase() :
218     token(0), flags(0), commandSequence(0)
219 {
220 }
221
222 CdbCommandBase::CdbCommandBase(const QByteArray  &cmd, int t, unsigned f,
223                                unsigned nc, const QVariant &c) :
224     token(t), flags(f), command(cmd), cookie(c), commandSequence(nc)
225 {
226 }
227
228 // Queue entry for builtin commands producing free-format
229 // line-by-line output.
230 struct CdbBuiltinCommand : public CdbCommandBase
231 {
232     typedef CdbEngine::BuiltinCommandHandler CommandHandler;
233
234     CdbBuiltinCommand() {}
235     CdbBuiltinCommand(const QByteArray  &cmd, int token, unsigned flags,
236                       CommandHandler h,
237                       unsigned nc, const QVariant &cookie) :
238         CdbCommandBase(cmd, token, flags, nc, cookie), handler(h)
239     {}
240
241
242     QByteArray joinedReply() const;
243
244     CommandHandler handler;
245     QList<QByteArray> reply;
246 };
247
248 QByteArray CdbBuiltinCommand::joinedReply() const
249 {
250     if (reply.isEmpty())
251         return QByteArray();
252     QByteArray answer;
253     answer.reserve(120  * reply.size());
254     foreach (const QByteArray &l, reply) {
255         answer += l;
256         answer += '\n';
257     }
258     return answer;
259 }
260
261 // Queue entry for Qt Creator extension commands producing one-line
262 // output with success flag and error message.
263 struct CdbExtensionCommand : public CdbCommandBase
264 {
265     typedef CdbEngine::ExtensionCommandHandler CommandHandler;
266
267     CdbExtensionCommand() : success(false) {}
268     CdbExtensionCommand(const QByteArray  &cmd, int token, unsigned flags,
269                       CommandHandler h,
270                       unsigned nc, const QVariant &cookie) :
271         CdbCommandBase(cmd, token, flags, nc, cookie), handler(h),success(false) {}
272
273     CommandHandler handler;
274     QByteArray reply;
275     QByteArray errorMessage;
276     bool success;
277 };
278
279 template <class CommandPtrType>
280 int indexOfCommand(const QList<CommandPtrType> &l, int token)
281 {
282     const int count = l.size();
283     for (int i = 0; i < count; i++)
284         if (l.at(i)->token == token)
285             return i;
286     return -1;
287 }
288
289 static inline bool validMode(DebuggerStartMode sm)
290 {
291     switch (sm) {
292     case NoStartMode:
293     case AttachTcf:
294     case AttachCore:
295     case StartRemoteGdb:
296         return false;
297     default:
298         break;
299     }
300     return true;
301 }
302
303 // Accessed by RunControlFactory
304 DebuggerEngine *createCdbEngine(const DebuggerStartParameters &sp,
305     DebuggerEngine *masterEngine, QString *errorMessage)
306 {
307 #ifdef Q_OS_WIN
308     CdbOptionsPage *op = CdbOptionsPage::instance();
309     if (!op || !op->options()->isValid() || !validMode(sp.startMode)) {
310         *errorMessage = QLatin1String("Internal error: Invalid start parameters passed for thre CDB engine.");
311         return 0;
312     }
313     return new CdbEngine(sp, masterEngine, op->options());
314 #else
315     Q_UNUSED(masterEngine)
316     Q_UNUSED(sp)
317 #endif
318     *errorMessage = QString::fromLatin1("Unsupported debug mode");
319     return 0;
320 }
321
322 bool isCdbEngineEnabled()
323 {
324 #ifdef Q_OS_WIN
325     return CdbOptionsPage::instance() && CdbOptionsPage::instance()->options()->isValid();
326 #else
327     return false;
328 #endif
329 }
330
331 static inline QString msgNoCdbBinaryForToolChain(const ProjectExplorer::Abi &tc)
332 {
333     return CdbEngine::tr("There is no CDB binary available for binaries in format '%1'").arg(tc.toString());
334 }
335
336 static QString cdbBinary(const DebuggerStartParameters &sp)
337 {
338     if (!sp.debuggerCommand.isEmpty()) {
339         // Do not use a GDB binary if we got started for a project with MinGW runtime.
340         const bool abiMatch = sp.toolChainAbi.os() == ProjectExplorer::Abi::WindowsOS
341                     && sp.toolChainAbi.osFlavor() == ProjectExplorer::Abi::WindowsMsvcFlavor;
342         if (abiMatch)
343             return sp.debuggerCommand;
344     }
345     return debuggerCore()->debuggerForAbi(sp.toolChainAbi, CdbEngineType);
346 }
347
348 bool checkCdbConfiguration(const DebuggerStartParameters &sp, ConfigurationCheck *check)
349 {
350 #ifdef Q_OS_WIN
351     if (!isCdbEngineEnabled()) {
352         check->errorDetails.push_back(CdbEngine::tr("The CDB debug engine required for %1 is currently disabled.").
353                            arg(sp.toolChainAbi.toString()));
354         check->settingsCategory = QLatin1String(Debugger::Constants::DEBUGGER_SETTINGS_CATEGORY);
355         check->settingsPage = CdbOptionsPage::settingsId();
356         return false;
357     }
358
359     if (!validMode(sp.startMode)) {
360         check->errorDetails.push_back(CdbEngine::tr("The CDB engine does not support start mode %1.").arg(sp.startMode));
361         return false;
362     }
363
364     if (sp.toolChainAbi.binaryFormat() != Abi::PEFormat || sp.toolChainAbi.os() != Abi::WindowsOS) {
365         check->errorDetails.push_back(CdbEngine::tr("The CDB debug engine does not support the %1 ABI.").
366                                       arg(sp.toolChainAbi.toString()));
367         return false;
368     }
369
370     if (cdbBinary(sp).isEmpty()) {
371         check->errorDetails.push_back(msgNoCdbBinaryForToolChain(sp.toolChainAbi));
372         check->settingsCategory = QLatin1String(ProjectExplorer::Constants::TOOLCHAIN_SETTINGS_CATEGORY);
373         check->settingsPage = QLatin1String(ProjectExplorer::Constants::TOOLCHAIN_SETTINGS_CATEGORY);
374         return false;
375     }
376
377     return true;
378 #else
379     Q_UNUSED(sp);
380     check->errorDetails.push_back(QString::fromLatin1("Unsupported debug mode"));
381     return false;
382 #endif
383 }
384
385 void addCdbOptionPages(QList<Core::IOptionsPage *> *opts)
386 {
387 #ifdef Q_OS_WIN
388     opts->push_back(new CdbOptionsPage);
389 #else
390     Q_UNUSED(opts);
391 #endif
392 }
393
394 #define QT_CREATOR_CDB_EXT "qtcreatorcdbext"
395
396 static inline Utils::SavedAction *theAssemblerAction()
397 {
398     return debuggerCore()->action(OperateByInstruction);
399 }
400
401 CdbEngine::CdbEngine(const DebuggerStartParameters &sp,
402         DebuggerEngine *masterEngine, const OptionsPtr &options) :
403     DebuggerEngine(sp, masterEngine),
404     m_creatorExtPrefix("<qtcreatorcdbext>|"),
405     m_tokenPrefix("<token>"),
406     m_options(options),
407     m_effectiveStartMode(NoStartMode),
408     m_inferiorPid(0),
409     m_accessible(false),
410     m_specialStopMode(NoSpecialStop),
411     m_nextCommandToken(0),
412     m_currentBuiltinCommandIndex(-1),
413     m_extensionCommandPrefixBA("!"QT_CREATOR_CDB_EXT"."),
414     m_operateByInstructionPending(true),
415     m_operateByInstruction(true), // Default CDB setting
416     m_notifyEngineShutdownOnTermination(false),
417     m_hasDebuggee(false),
418     m_elapsedLogTime(0),
419     m_sourceStepInto(false),
420     m_watchPointX(0),
421     m_watchPointY(0),
422     m_ignoreCdbOutput(false)
423 {
424     connect(theAssemblerAction(), SIGNAL(triggered(bool)), this, SLOT(operateByInstructionTriggered(bool)));
425
426     setObjectName(QLatin1String("CdbEngine"));
427     connect(&m_process, SIGNAL(finished(int)), this, SLOT(processFinished()));
428     connect(&m_process, SIGNAL(error(QProcess::ProcessError)), this, SLOT(processError()));
429     connect(&m_process, SIGNAL(readyReadStandardOutput()), this, SLOT(readyReadStandardOut()));
430     connect(&m_process, SIGNAL(readyReadStandardError()), this, SLOT(readyReadStandardOut()));
431 }
432
433 void CdbEngine::init()
434 {
435     m_effectiveStartMode = NoStartMode;
436     m_inferiorPid = 0;
437     m_accessible = false;
438     m_specialStopMode = NoSpecialStop;
439     m_nextCommandToken  = 0;
440     m_currentBuiltinCommandIndex = -1;
441     m_operateByInstructionPending = theAssemblerAction()->isChecked();
442     m_operateByInstruction = true; // Default CDB setting
443     m_notifyEngineShutdownOnTermination = false;
444     m_hasDebuggee = false;
445     m_sourceStepInto = false;
446     m_watchPointX = m_watchPointY = 0;
447     m_ignoreCdbOutput = false;
448
449     m_outputBuffer.clear();
450     m_builtinCommandQueue.clear();
451     m_extensionCommandQueue.clear();
452     m_extensionMessageBuffer.clear();
453     m_pendingBreakpointMap.clear();
454     QTC_ASSERT(m_process.state() != QProcess::Running, Utils::SynchronousProcess::stopProcess(m_process); )
455 }
456
457 CdbEngine::~CdbEngine()
458 {
459 }
460
461 void CdbEngine::operateByInstructionTriggered(bool operateByInstruction)
462 {
463     if (state() == InferiorStopOk) {
464         syncOperateByInstruction(operateByInstruction);
465     } else {
466         // To be set next time session becomes accessible
467         m_operateByInstructionPending = operateByInstruction;
468     }
469 }
470
471 void CdbEngine::syncOperateByInstruction(bool operateByInstruction)
472 {
473     if (debug)
474         qDebug("syncOperateByInstruction current: %d new %d", m_operateByInstruction, operateByInstruction);
475     if (m_operateByInstruction == operateByInstruction)
476         return;
477     QTC_ASSERT(m_accessible, return; )
478     m_operateByInstruction = operateByInstruction;
479     postCommand(m_operateByInstruction ? QByteArray("l-t") : QByteArray("l+t"), 0);
480     postCommand(m_operateByInstruction ? QByteArray("l-s") : QByteArray("l+s"), 0);
481 }
482
483 bool CdbEngine::setToolTipExpression(const QPoint &mousePos,
484                                      TextEditor::ITextEditor *editor,
485                                      const DebuggerToolTipContext &contextIn)
486 {
487     if (debug)
488         qDebug() << Q_FUNC_INFO;
489     // Need a stopped debuggee and a cpp file in a valid frame
490     if (state() != InferiorStopOk || !isCppEditor(editor) || stackHandler()->currentIndex() < 0)
491         return false;
492     // Determine expression and function
493     int line;
494     int column;
495     DebuggerToolTipContext context = contextIn;
496     const QString exp = cppExpressionAt(editor, context.position, &line, &column, &context.function);
497     // Are we in the current stack frame
498     if (context.function.isEmpty() || exp.isEmpty() || context.function != stackHandler()->currentFrame().function)
499         return false;
500     // No numerical or any other expressions [yet]
501     if (!(exp.at(0).isLetter() || exp.at(0) == QLatin1Char('_')))
502         return false;
503     const QByteArray iname = QByteArray(localsPrefixC) + exp.toAscii();
504     const QModelIndex index = watchHandler()->itemIndex(iname);
505     if (!index.isValid())
506         return false;
507     DebuggerTreeViewToolTipWidget *tw = new DebuggerTreeViewToolTipWidget;
508     tw->setContext(context);
509     tw->setDebuggerModel(LocalsWatch);
510     tw->setExpression(exp);
511     tw->acquireEngine(this);
512     DebuggerToolTipManager::instance()->showToolTip(mousePos, editor, tw);
513     return true;
514 }
515
516 // Determine full path to the CDB extension library.
517 QString CdbEngine::extensionLibraryName(bool is64Bit)
518 {
519     // Determine extension lib name and path to use
520     QString rc;
521     QTextStream(&rc) << QFileInfo(QCoreApplication::applicationDirPath()).path()
522                      << "/lib/" << (is64Bit ? QT_CREATOR_CDB_EXT"64" : QT_CREATOR_CDB_EXT"32")
523                      << '/' << QT_CREATOR_CDB_EXT << ".dll";
524     return rc;
525 }
526
527 // Determine environment for CDB.exe, start out with run config and
528 // add CDB extension path merged with system value should there be one.
529 static QStringList mergeEnvironment(QStringList runConfigEnvironment,
530                                     QString cdbExtensionPath)
531 {
532     // Determine CDB extension path from Qt Creator
533     static const char cdbExtensionPathVariableC[] = "_NT_DEBUGGER_EXTENSION_PATH";
534     const QByteArray oldCdbExtensionPath = qgetenv(cdbExtensionPathVariableC);
535     if (!oldCdbExtensionPath.isEmpty()) {
536         cdbExtensionPath.append(QLatin1Char(';'));
537         cdbExtensionPath.append(QString::fromLocal8Bit(oldCdbExtensionPath));
538     }
539     // We do not assume someone sets _NT_DEBUGGER_EXTENSION_PATH in the run
540     // config, just to make sure, delete any existing entries
541     const QString cdbExtensionPathVariableAssign =
542             QLatin1String(cdbExtensionPathVariableC) + QLatin1Char('=');
543     for (QStringList::iterator it = runConfigEnvironment.begin(); it != runConfigEnvironment.end() ; ) {
544         if (it->startsWith(cdbExtensionPathVariableAssign)) {
545             it = runConfigEnvironment.erase(it);
546             break;
547         } else {
548             ++it;
549         }
550     }
551     runConfigEnvironment.append(cdbExtensionPathVariableAssign +
552                                 QDir::toNativeSeparators(cdbExtensionPath));
553     return runConfigEnvironment;
554 }
555
556 int CdbEngine::elapsedLogTime() const
557 {
558     const int elapsed = m_logTime.elapsed();
559     const int delta = elapsed - m_elapsedLogTime;
560     m_elapsedLogTime = elapsed;
561     return delta;
562 }
563
564 // Start the console stub with the sub process. Continue in consoleStubProcessStarted.
565 bool CdbEngine::startConsole(const DebuggerStartParameters &sp, QString *errorMessage)
566 {
567     if (debug)
568         qDebug("startConsole %s", qPrintable(sp.executable));
569     m_consoleStub.reset(new Utils::ConsoleProcess);
570     m_consoleStub->setMode(Utils::ConsoleProcess::Suspend);
571     connect(m_consoleStub.data(), SIGNAL(processMessage(QString, bool)),
572             SLOT(consoleStubMessage(QString, bool)));
573     connect(m_consoleStub.data(), SIGNAL(processStarted()),
574             SLOT(consoleStubProcessStarted()));
575     connect(m_consoleStub.data(), SIGNAL(wrapperStopped()),
576             SLOT(consoleStubExited()));
577     m_consoleStub->setWorkingDirectory(sp.workingDirectory);
578     m_consoleStub->setEnvironment(sp.environment);
579     if (!m_consoleStub->start(sp.executable, sp.processArgs)) {
580         *errorMessage = tr("The console process '%1' could not be started.").arg(sp.executable);
581         return false;
582     }
583     return true;
584 }
585
586 void CdbEngine::consoleStubMessage(const QString &msg, bool isError)
587 {
588     if (debug)
589         qDebug("consoleStubProcessMessage() in %s error=%d %s", stateName(state()), isError, qPrintable(msg));
590     if (isError) {
591         if (state() == EngineSetupRequested) {
592             STATE_DEBUG(state(), Q_FUNC_INFO, __LINE__, "notifyEngineSetupFailed")
593             notifyEngineSetupFailed();
594         } else {
595             STATE_DEBUG(state(), Q_FUNC_INFO, __LINE__, "notifyEngineIll")
596             notifyEngineIll();
597         }
598         nonModalMessageBox(QMessageBox::Critical, tr("Debugger Error"), msg);
599     } else {
600         showMessage(msg, AppOutput);
601     }
602 }
603
604 void CdbEngine::consoleStubProcessStarted()
605 {
606     if (debug)
607         qDebug("consoleStubProcessStarted() PID=%lld", m_consoleStub->applicationPID());
608     // Attach to console process.
609     DebuggerStartParameters attachParameters = startParameters();
610     attachParameters.executable.clear();
611     attachParameters.processArgs.clear();
612     attachParameters.attachPID = m_consoleStub->applicationPID();
613     attachParameters.startMode = AttachExternal;
614     showMessage(QString::fromLatin1("Attaching to %1...").arg(attachParameters.attachPID), LogMisc);
615     QString errorMessage;
616     if (!launchCDB(attachParameters, &errorMessage)) {
617         showMessage(errorMessage, LogError);
618         STATE_DEBUG(state(), Q_FUNC_INFO, __LINE__, "notifyEngineSetupFailed")
619         notifyEngineSetupFailed();
620     }
621 }
622
623 void CdbEngine::consoleStubExited()
624 {
625 }
626
627 void CdbEngine::setupEngine()
628 {
629     if (debug)
630         qDebug(">setupEngine");
631     // Nag to add symbol server
632     if (CdbSymbolPathListEditor::promptToAddSymbolServer(CdbOptions::settingsGroup(),
633                                                          &(m_options->symbolPaths)))
634         m_options->toSettings(Core::ICore::instance()->settings());
635
636     init();
637     if (!m_logTime.elapsed())
638         m_logTime.start();
639     QString errorMessage;
640     // Console: Launch the stub with the suspended application and attach to it
641     // CDB in theory has a command line option '-2' that launches a
642     // console, too, but that immediately closes when the debuggee quits.
643     // Use the Creator stub instead.
644     const DebuggerStartParameters &sp = startParameters();
645     const bool launchConsole = isConsole(sp);
646     m_effectiveStartMode = launchConsole ? AttachExternal : sp.startMode;
647     const bool ok = launchConsole ?
648                 startConsole(startParameters(), &errorMessage) :
649                 launchCDB(startParameters(), &errorMessage);
650     if (debug)
651         qDebug("<setupEngine ok=%d", ok);
652     if (!ok) {
653         showMessage(errorMessage, LogError);
654         STATE_DEBUG(state(), Q_FUNC_INFO, __LINE__, "notifyEngineSetupFailed")
655         notifyEngineSetupFailed();
656     }
657 }
658
659 bool CdbEngine::launchCDB(const DebuggerStartParameters &sp, QString *errorMessage)
660 {
661     if (debug)
662         qDebug("launchCDB startMode=%d", sp.startMode);
663     const QChar blank(QLatin1Char(' '));
664     // Start engine which will run until initial breakpoint:
665     // Determine binary (force MSVC), extension lib name and path to use
666     // The extension is passed as relative name with the path variable set
667     //(does not work with absolute path names)
668     const QString executable = cdbBinary(sp);
669     if (executable.isEmpty()) {
670         *errorMessage = tr("There is no CDB executable specified.");
671         return false;
672     }
673
674     const bool is64bit =
675 #ifdef Q_OS_WIN
676             Utils::winIs64BitBinary(executable);
677 #else
678             false;
679 #endif
680     const QFileInfo extensionFi(CdbEngine::extensionLibraryName(is64bit));
681     if (!extensionFi.isFile()) {
682         *errorMessage = QString::fromLatin1("Internal error: The extension %1 cannot be found.").
683                 arg(QDir::toNativeSeparators(extensionFi.absoluteFilePath()));
684         return false;
685     }
686     const QString extensionFileName = extensionFi.fileName();
687     // Prepare arguments
688     QStringList arguments;
689     const bool isRemote = sp.startMode == AttachToRemote;
690     if (isRemote) { // Must be first
691         arguments << QLatin1String("-remote") << sp.remoteChannel;
692     } else {
693         arguments << (QLatin1String("-a") + extensionFileName);
694     }
695     // Source line info/No terminal breakpoint / Pull extension
696     arguments << QLatin1String("-lines") << QLatin1String("-G")
697     // register idle (debuggee stop) notification
698               << QLatin1String("-c")
699               << QString::fromAscii(".idle_cmd " + m_extensionCommandPrefixBA + "idle");
700     if (sp.useTerminal) // Separate console
701         arguments << QLatin1String("-2");
702     if (!m_options->symbolPaths.isEmpty())
703         arguments << QLatin1String("-y") << m_options->symbolPaths.join(QString(QLatin1Char(';')));
704     if (!m_options->sourcePaths.isEmpty())
705         arguments << QLatin1String("-srcpath") << m_options->sourcePaths.join(QString(QLatin1Char(';')));
706     // Compile argument string preserving quotes
707     QString nativeArguments = m_options->additionalArguments;
708     switch (sp.startMode) {
709     case StartInternal:
710     case StartExternal:
711         if (!nativeArguments.isEmpty())
712             nativeArguments.push_back(blank);
713         nativeArguments += QDir::toNativeSeparators(sp.executable);
714         break;
715     case AttachToRemote:
716         break;
717     case AttachExternal:
718     case AttachCrashedExternal:
719         arguments << QLatin1String("-p") << QString::number(sp.attachPID);
720         if (sp.startMode == AttachCrashedExternal)
721             arguments << QLatin1String("-e") << sp.crashParameter << QLatin1String("-g");
722         break;
723     default:
724         *errorMessage = QString::fromLatin1("Internal error: Unsupported start mode %1.").arg(sp.startMode);
725         return false;
726     }
727     if (!sp.processArgs.isEmpty()) { // Complete native argument string.
728         if (!nativeArguments.isEmpty())
729             nativeArguments.push_back(blank);
730         nativeArguments += sp.processArgs;
731     }
732
733     const QString msg = QString::fromLatin1("Launching %1 %2\nusing %3 of %4.").
734             arg(QDir::toNativeSeparators(executable),
735                 arguments.join(QString(blank)) + blank + nativeArguments,
736                 QDir::toNativeSeparators(extensionFi.absoluteFilePath()),
737                 extensionFi.lastModified().toString(Qt::SystemLocaleShortDate));
738     showMessage(msg, LogMisc);
739
740     m_outputBuffer.clear();
741     m_process.setEnvironment(mergeEnvironment(sp.environment.toStringList(), extensionFi.absolutePath()));
742     if (!sp.workingDirectory.isEmpty())
743         m_process.setWorkingDirectory(sp.workingDirectory);
744
745 #ifdef Q_OS_WIN
746     if (!nativeArguments.isEmpty()) // Appends
747         m_process.setNativeArguments(nativeArguments);
748 #endif
749     m_process.start(executable, arguments);
750     if (!m_process.waitForStarted()) {
751         *errorMessage = QString::fromLatin1("Internal error: Cannot start process %1: %2").
752                 arg(QDir::toNativeSeparators(executable), m_process.errorString());
753         return false;
754     }
755 #ifdef Q_OS_WIN
756     const unsigned long pid = Utils::winQPidToPid(m_process.pid());
757 #else
758     const unsigned long pid = 0;
759 #endif
760     showMessage(QString::fromLatin1("%1 running as %2").
761                 arg(QDir::toNativeSeparators(executable)).arg(pid), LogMisc);
762     m_hasDebuggee = true;
763     if (isRemote) { // We do not get an 'idle' in a remote session, but are accessible
764         m_accessible = true;
765         const QByteArray loadCommand = QByteArray(".load ")
766                 + extensionFileName.toLocal8Bit();
767         postCommand(loadCommand, 0);
768         STATE_DEBUG(state(), Q_FUNC_INFO, __LINE__, "notifyEngineSetupOk")
769         notifyEngineSetupOk();
770     }
771     return true;
772 }
773
774 void CdbEngine::setupInferior()
775 {
776     if (debug)
777         qDebug("setupInferior");
778     attemptBreakpointSynchronization();
779     postCommand("sxn 0x4000001f", 0); // Do not break on WowX86 exceptions.
780     postExtensionCommand("pid", QByteArray(), 0, &CdbEngine::handlePid);
781 }
782
783 void CdbEngine::runEngine()
784 {
785     if (debug)
786         qDebug("runEngine");
787     // Resume the threads frozen by the console stub.
788     if (isConsole(startParameters()))
789         postCommand("~* m", 0);
790     foreach (const QString &breakEvent, m_options->breakEvents)
791             postCommand(QByteArray("sxe ") + breakEvent.toAscii(), 0);
792     postCommand("g", 0);
793 }
794
795 bool CdbEngine::commandsPending() const
796 {
797     return !m_builtinCommandQueue.isEmpty() || !m_extensionCommandQueue.isEmpty();
798 }
799
800 void CdbEngine::shutdownInferior()
801 {
802     if (debug)
803         qDebug("CdbEngine::shutdownInferior in state '%s', process running %d", stateName(state()),
804                isCdbProcessRunning());
805
806     if (!isCdbProcessRunning()) { // Direct launch: Terminated with process.
807         if (debug)
808             qDebug("notifyInferiorShutdownOk");
809         STATE_DEBUG(state(), Q_FUNC_INFO, __LINE__, "notifyInferiorShutdownOk")
810         notifyInferiorShutdownOk();
811         return;
812     }
813
814     if (m_accessible) {
815         if (m_effectiveStartMode == AttachExternal || m_effectiveStartMode == AttachCrashedExternal)
816             detachDebugger();
817         STATE_DEBUG(state(), Q_FUNC_INFO, __LINE__, "notifyInferiorShutdownOk")
818         notifyInferiorShutdownOk();
819     } else {
820         // A command got stuck.
821         if (commandsPending()) {
822             showMessage(QLatin1String("Cannot shut down inferior due to pending commands."), LogWarning);
823             STATE_DEBUG(state(), Q_FUNC_INFO, __LINE__, "notifyInferiorShutdownFailed")
824             notifyInferiorShutdownFailed();
825             return;
826         }
827         if (!canInterruptInferior()) {
828             showMessage(QLatin1String("Cannot interrupt the inferior."), LogWarning);
829             STATE_DEBUG(state(), Q_FUNC_INFO, __LINE__, "notifyInferiorShutdownFailed")
830             notifyInferiorShutdownFailed();
831             return;
832         }
833         interruptInferior(); // Calls us again
834     }
835 }
836
837 /* shutdownEngine/processFinished:
838  * Note that in the case of launching a process by the debugger, the debugger
839  * automatically quits a short time after reporting the session becoming
840  * inaccessible without debuggee (notifyInferiorExited). In that case,
841  * processFinished() must not report any arbitrarily notifyEngineShutdownOk()
842  * as not to confuse the state engine.
843  */
844
845 void CdbEngine::shutdownEngine()
846 {
847     if (debug)
848         qDebug("CdbEngine::shutdownEngine in state '%s', process running %d,"
849                "accessible=%d,commands pending=%d",
850                stateName(state()), isCdbProcessRunning(), m_accessible,
851                commandsPending());
852
853     if (!isCdbProcessRunning()) { // Direct launch: Terminated with process.
854         STATE_DEBUG(state(), Q_FUNC_INFO, __LINE__, "notifyEngineShutdownOk")
855         notifyEngineShutdownOk();
856         return;
857     }
858
859     // No longer trigger anything from messages
860     m_ignoreCdbOutput = true;
861     // Go for kill if there are commands pending.
862     if (m_accessible && !commandsPending()) {
863         // detach: Wait for debugger to finish.
864         if (m_effectiveStartMode == AttachExternal)
865             detachDebugger();
866         // Remote requires a bit more force to quit.
867         if (m_effectiveStartMode == AttachToRemote) {
868             postCommand(m_extensionCommandPrefixBA + "shutdownex", 0);
869             postCommand("qq", 0);
870         } else {
871             postCommand("q", 0);
872         }
873         m_notifyEngineShutdownOnTermination = true;
874         return;
875     } else {
876         // Remote process. No can do, currently
877         m_notifyEngineShutdownOnTermination = true;
878         Utils::SynchronousProcess::stopProcess(m_process);
879         return;
880     }
881     // Lost debuggee, debugger should quit anytime now
882     if (!m_hasDebuggee) {
883         m_notifyEngineShutdownOnTermination = true;
884         return;
885     }
886     interruptInferior();
887 }
888
889 void CdbEngine::processFinished()
890 {
891     if (debug)
892         qDebug("CdbEngine::processFinished %dms '%s' notify=%d (exit state=%d, ex=%d)",
893                elapsedLogTime(), stateName(state()), m_notifyEngineShutdownOnTermination,
894                m_process.exitStatus(), m_process.exitCode());
895
896     const bool crashed = m_process.exitStatus() == QProcess::CrashExit;
897     if (crashed) {
898         showMessage(tr("CDB crashed"), LogError); // not in your life.
899     } else {
900         showMessage(tr("CDB exited (%1)").arg(m_process.exitCode()), LogMisc);
901     }
902
903     if (m_notifyEngineShutdownOnTermination) {
904         if (crashed) {
905             if (debug)
906                 qDebug("notifyEngineIll");
907             STATE_DEBUG(state(), Q_FUNC_INFO, __LINE__, "notifyEngineIll")
908             notifyEngineIll();
909         } else {
910             STATE_DEBUG(state(), Q_FUNC_INFO, __LINE__, "notifyEngineShutdownOk")
911             notifyEngineShutdownOk();
912         }
913     } else {
914         STATE_DEBUG(state(), Q_FUNC_INFO, __LINE__, "notifyEngineSpontaneousShutdown")
915         notifyEngineSpontaneousShutdown();
916     }
917 }
918
919 void CdbEngine::detachDebugger()
920 {
921     postCommand(".detach", 0);
922 }
923
924 static inline bool isWatchIName(const QByteArray &iname)
925 {
926     return iname.startsWith("watch");
927 }
928
929 void CdbEngine::updateWatchData(const WatchData &dataIn,
930                                 const WatchUpdateFlags & flags)
931 {
932     if (debug || debugLocals || debugWatches)
933         qDebug("CdbEngine::updateWatchData() %dms accessible=%d %s incr=%d: %s",
934                elapsedLogTime(), m_accessible, stateName(state()),
935                flags.tryIncremental,
936                qPrintable(dataIn.toString()));
937
938     if (!m_accessible) // Add watch data while running?
939         return;
940
941     // New watch item?
942     if (isWatchIName(dataIn.iname) && dataIn.isValueNeeded()) {
943         QByteArray args;
944         ByteArrayInputStream str(args);
945         str << dataIn.iname << " \"" << dataIn.exp << '"';
946         postExtensionCommand("addwatch", args, 0,
947                              &CdbEngine::handleAddWatch, 0,
948                              qVariantFromValue(dataIn));
949         return;
950     }
951
952     if (!dataIn.hasChildren && !dataIn.isValueNeeded()) {
953         WatchData data = dataIn;
954         data.setAllUnneeded();
955         watchHandler()->insertData(data);
956         return;
957     }
958     updateLocalVariable(dataIn.iname);
959 }
960
961 void CdbEngine::handleAddWatch(const CdbExtensionCommandPtr &reply)
962 {
963     WatchData item = qvariant_cast<WatchData>(reply->cookie);
964     if (debugWatches)
965         qDebug() << "handleAddWatch ok="  << reply->success << item.iname;
966     if (reply->success) {
967         updateLocalVariable(item.iname);
968     } else {
969         item.setError(tr("Unable to add expression"));
970         watchHandler()->insertData(item);
971         showMessage(QString::fromLatin1("Unable to add watch item '%1'/'%2': %3").
972                     arg(QString::fromAscii(item.iname), QString::fromAscii(item.exp),
973                         reply->errorMessage), LogError);
974     }
975 }
976
977 void CdbEngine::addLocalsOptions(ByteArrayInputStream &str) const
978 {
979     if (debuggerCore()->boolSetting(VerboseLog))
980         str << blankSeparator << "-v";
981     if (debuggerCore()->boolSetting(UseDebuggingHelpers))
982         str << blankSeparator << "-c";
983     const QByteArray typeFormats = watchHandler()->typeFormatRequests();
984     if (!typeFormats.isEmpty())
985         str << blankSeparator << "-T " << typeFormats;
986     const QByteArray individualFormats = watchHandler()->individualFormatRequests();
987     if (!individualFormats.isEmpty())
988         str << blankSeparator << "-I " << individualFormats;
989 }
990
991 void CdbEngine::updateLocalVariable(const QByteArray &iname)
992 {
993     const bool isWatch = isWatchIName(iname);
994     if (debugWatches)
995         qDebug() << "updateLocalVariable watch=" << isWatch << iname;
996     QByteArray localsArguments;
997     ByteArrayInputStream str(localsArguments);
998     addLocalsOptions(str);
999     if (!isWatch) {
1000         const int stackFrame = stackHandler()->currentIndex();
1001         if (stackFrame < 0) {
1002             qWarning("Internal error; no stack frame in updateLocalVariable");
1003             return;
1004         }
1005         str << blankSeparator << stackFrame;
1006     }
1007     str << blankSeparator << iname;
1008     postExtensionCommand(isWatch ? "watches" : "locals", localsArguments, 0, &CdbEngine::handleLocals);
1009 }
1010
1011 unsigned CdbEngine::debuggerCapabilities() const
1012 {
1013     return DisassemblerCapability | RegisterCapability | ShowMemoryCapability
1014            |WatchpointCapability|JumpToLineCapability|AddWatcherCapability
1015            |BreakOnThrowAndCatchCapability // Sort-of: Can break on throw().
1016            |BreakModuleCapability;
1017 }
1018
1019 void CdbEngine::executeStep()
1020 {
1021     if (!m_operateByInstruction)
1022         m_sourceStepInto = true; // See explanation at handleStackTrace().
1023     postCommand(QByteArray("t"), 0); // Step into-> t (trace)
1024     STATE_DEBUG(state(), Q_FUNC_INFO, __LINE__, "notifyInferiorRunRequested")
1025     notifyInferiorRunRequested();
1026 }
1027
1028 void CdbEngine::executeStepOut()
1029 {
1030     postCommand(QByteArray("gu"), 0); // Step out-> gu (go up)
1031     STATE_DEBUG(state(), Q_FUNC_INFO, __LINE__, "notifyInferiorRunRequested")
1032     notifyInferiorRunRequested();
1033 }
1034
1035 void CdbEngine::executeNext()
1036 {
1037     postCommand(QByteArray("p"), 0); // Step over -> p
1038     STATE_DEBUG(state(), Q_FUNC_INFO, __LINE__, "notifyInferiorRunRequested")
1039     notifyInferiorRunRequested();
1040 }
1041
1042 void CdbEngine::executeStepI()
1043 {
1044     executeStep();
1045 }
1046
1047 void CdbEngine::executeNextI()
1048 {
1049     executeNext();
1050 }
1051
1052 void CdbEngine::continueInferior()
1053 {
1054     STATE_DEBUG(state(), Q_FUNC_INFO, __LINE__, "notifyInferiorRunRequested")
1055     notifyInferiorRunRequested();
1056     doContinueInferior();
1057 }
1058
1059 void CdbEngine::doContinueInferior()
1060 {
1061     postCommand(QByteArray("g"), 0);
1062 }
1063
1064 bool CdbEngine::canInterruptInferior() const
1065 {
1066     return m_effectiveStartMode != AttachToRemote && m_inferiorPid;
1067 }
1068
1069 void CdbEngine::interruptInferior()
1070 {
1071     if (debug)
1072         qDebug() << "CdbEngine::interruptInferior()" << stateName(state());
1073     if (canInterruptInferior()) {
1074         doInterruptInferior(NoSpecialStop);
1075     } else {
1076         showMessage(tr("Interrupting is not possible in remote sessions."), LogError);
1077         STATE_DEBUG(state(), Q_FUNC_INFO, __LINE__, "notifyInferiorStopOk")
1078         notifyInferiorStopOk();
1079         STATE_DEBUG(state(), Q_FUNC_INFO, __LINE__, "notifyInferiorRunRequested")
1080         notifyInferiorRunRequested();
1081         STATE_DEBUG(state(), Q_FUNC_INFO, __LINE__, "notifyInferiorRunOk")
1082         notifyInferiorRunOk();
1083     }
1084 }
1085
1086 void CdbEngine::doInterruptInferior(SpecialStopMode sm)
1087 {
1088 #ifdef Q_OS_WIN
1089     const SpecialStopMode oldSpecialMode = m_specialStopMode;
1090     m_specialStopMode = sm;
1091     QString errorMessage;
1092     showMessage(QString::fromLatin1("Interrupting process %1...").arg(m_inferiorPid), LogMisc);
1093     if (!winDebugBreakProcess(m_inferiorPid, &errorMessage)) {
1094         m_specialStopMode = oldSpecialMode;
1095         showMessage(QString::fromLatin1("Cannot interrupt process %1: %2").arg(m_inferiorPid).arg(errorMessage), LogError);
1096     }
1097 #else
1098     Q_UNUSED(sm)
1099 #endif
1100 }
1101
1102 void CdbEngine::executeRunToLine(const ContextData &data)
1103 {
1104     // Add one-shot breakpoint
1105     BreakpointParameters bp(BreakpointByFileAndLine);
1106     bp.fileName = data.fileName;
1107     bp.lineNumber = data.lineNumber;
1108     postCommand(cdbAddBreakpointCommand(bp, BreakpointId(-1), true), 0);
1109     continueInferior();
1110 }
1111
1112 void CdbEngine::executeRunToFunction(const QString &functionName)
1113 {
1114     // Add one-shot breakpoint
1115     BreakpointParameters bp(BreakpointByFunction);
1116     bp.functionName = functionName;
1117
1118     postCommand(cdbAddBreakpointCommand(bp, BreakpointId(-1), true), 0);
1119     continueInferior();
1120 }
1121
1122 void CdbEngine::setRegisterValue(int regnr, const QString &value)
1123 {
1124     const Registers registers = registerHandler()->registers();
1125     QTC_ASSERT(regnr < registers.size(), return)
1126     // Value is decimal or 0x-hex-prefixed
1127     QByteArray cmd;
1128     ByteArrayInputStream str(cmd);
1129     str << "r " << registers.at(regnr).name << '=' << value;
1130     postCommand(cmd, 0);
1131     reloadRegisters();
1132 }
1133
1134 void CdbEngine::executeJumpToLine(const ContextData &data)
1135 {
1136     QByteArray cmd;
1137     ByteArrayInputStream str(cmd);
1138     // Resolve source line address and go to that location
1139     str << "? `" << QDir::toNativeSeparators(data.fileName) << ':' << data.lineNumber << '`';
1140     const QVariant cookie = qVariantFromValue(data);
1141     postBuiltinCommand(cmd, 0, &CdbEngine::handleJumpToLineAddressResolution, 0, cookie);
1142 }
1143
1144 void CdbEngine::handleJumpToLineAddressResolution(const CdbBuiltinCommandPtr &cmd)
1145 {
1146     if (cmd->reply.isEmpty())
1147         return;
1148     // Evaluate expression: 5365511549 = 00000001`3fcf357d
1149     // Set register 'rip' to hex address and goto lcoation
1150     QByteArray answer = cmd->reply.front();
1151     const int equalPos = answer.indexOf(" = ");
1152     if (equalPos == -1)
1153         return;
1154     answer.remove(0, equalPos + 3);
1155     QTC_ASSERT(qVariantCanConvert<ContextData>(cmd->cookie), return);
1156     const ContextData cookie = qvariant_cast<ContextData>(cmd->cookie);
1157
1158     QByteArray registerCmd;
1159     ByteArrayInputStream str(registerCmd);
1160     // PC-register depending on 64/32bit.
1161     str << "r " << (startParameters().toolChainAbi.wordWidth() == 64 ? "rip" : "eip") << "=0x" << answer;
1162     postCommand(registerCmd, 0);
1163     gotoLocation(Location(cookie.fileName, cookie.lineNumber));
1164 }
1165
1166 void CdbEngine::assignValueInDebugger(const WatchData *w, const QString &expr, const QVariant &value)
1167 {
1168     if (debug)
1169         qDebug() << "CdbEngine::assignValueInDebugger" << w->iname << expr << value;
1170
1171     if (state() != InferiorStopOk || stackHandler()->currentIndex() < 0) {
1172         qWarning("Internal error: assignValueInDebugger: Invalid state or no stack frame.");
1173         return;
1174     }
1175
1176     QByteArray cmd;
1177     ByteArrayInputStream str(cmd);
1178     str << m_extensionCommandPrefixBA << "assign " << w->iname << '=' << value.toString();
1179     postCommand(cmd, 0);
1180     // Update all locals in case we change a union or something pointed to
1181     // that affects other variables, too.
1182     updateLocals();
1183 }
1184
1185 void CdbEngine::parseThreads(const GdbMi &data, int forceCurrentThreadId /* = -1 */)
1186 {
1187     int currentThreadId;
1188     Threads threads = ThreadsHandler::parseGdbmiThreads(data, &currentThreadId);
1189     threadsHandler()->setThreads(threads);
1190     threadsHandler()->setCurrentThreadId(forceCurrentThreadId >= 0 ?
1191                                          forceCurrentThreadId : currentThreadId);
1192 }
1193
1194 void CdbEngine::handleThreads(const CdbExtensionCommandPtr &reply)
1195 {
1196     if (debug)
1197         qDebug("CdbEngine::handleThreads success=%d", reply->success);
1198     if (reply->success) {
1199         GdbMi data;
1200         data.fromString(reply->reply);
1201         parseThreads(data);
1202         // Continue sequence
1203         postCommandSequence(reply->commandSequence);
1204     } else {
1205         showMessage(QString::fromLatin1(reply->errorMessage), LogError);
1206     }
1207 }
1208
1209 void CdbEngine::executeDebuggerCommand(const QString &command)
1210 {
1211     postCommand(command.toLocal8Bit(), QuietCommand);
1212 }
1213
1214 // Post command without callback
1215 void CdbEngine::postCommand(const QByteArray &cmd, unsigned flags)
1216 {
1217     if (debug)
1218         qDebug("CdbEngine::postCommand %dms '%s' %u %s\n",
1219                elapsedLogTime(), cmd.constData(), flags, stateName(state()));
1220     if (!(flags & QuietCommand))
1221         showMessage(QString::fromLocal8Bit(cmd), LogInput);
1222     m_process.write(cmd + '\n');
1223 }
1224
1225 // Post a built-in-command producing free-format output with a callback.
1226 // In order to catch the output, it is enclosed in 'echo' commands
1227 // printing a specially formatted token to be identifiable in the output.
1228 void CdbEngine::postBuiltinCommand(const QByteArray &cmd, unsigned flags,
1229                                    BuiltinCommandHandler handler,
1230                                    unsigned nextCommandFlag,
1231                                    const QVariant &cookie)
1232 {
1233     if (!m_accessible) {
1234         const QString msg = QString::fromLatin1("Attempt to issue builtin command '%1' to non-accessible session (%2)")
1235                 .arg(QString::fromLocal8Bit(cmd), QString::fromAscii(stateName(state())));
1236         showMessage(msg, LogError);
1237         return;
1238     }
1239     if (!flags & QuietCommand)
1240         showMessage(QString::fromLocal8Bit(cmd), LogInput);
1241
1242     const int token = m_nextCommandToken++;
1243     CdbBuiltinCommandPtr pendingCommand(new CdbBuiltinCommand(cmd, token, flags, handler, nextCommandFlag, cookie));
1244
1245     m_builtinCommandQueue.push_back(pendingCommand);
1246     // Enclose command in echo-commands for token
1247     QByteArray fullCmd;
1248     ByteArrayInputStream str(fullCmd);
1249     str << ".echo \"" << m_tokenPrefix << token << "<\"\n"
1250             << cmd << "\n.echo \"" << m_tokenPrefix << token << ">\"\n";
1251     if (debug)
1252         qDebug("CdbEngine::postBuiltinCommand %dms '%s' flags=%u token=%d %s next=%u, cookie='%s', pending=%d, sequence=0x%x",
1253                elapsedLogTime(), cmd.constData(), flags, token, stateName(state()), nextCommandFlag, qPrintable(cookie.toString()),
1254                m_builtinCommandQueue.size(), nextCommandFlag);
1255     if (debug > 1)
1256         qDebug("CdbEngine::postBuiltinCommand: resulting command '%s'\n",
1257                fullCmd.constData());
1258     m_process.write(fullCmd);
1259 }
1260
1261 // Post an extension command producing one-line output with a callback,
1262 // pass along token for identification in queue.
1263 void CdbEngine::postExtensionCommand(const QByteArray &cmd,
1264                                      const QByteArray &arguments,
1265                                      unsigned flags,
1266                                      ExtensionCommandHandler handler,
1267                                      unsigned nextCommandFlag,
1268                                      const QVariant &cookie)
1269 {
1270     if (!m_accessible) {
1271         const QString msg = QString::fromLatin1("Attempt to issue extension command '%1' to non-accessible session (%2)")
1272                 .arg(QString::fromLocal8Bit(cmd), QString::fromAscii(stateName(state())));
1273         showMessage(msg, LogError);
1274         return;
1275     }
1276
1277     const int token = m_nextCommandToken++;
1278
1279     // Format full command with token to be recognizeable in the output
1280     QByteArray fullCmd;
1281     ByteArrayInputStream str(fullCmd);
1282     str << m_extensionCommandPrefixBA << cmd << " -t " << token;
1283     if (!arguments.isEmpty())
1284         str <<  ' ' << arguments;
1285
1286     if (!flags & QuietCommand)
1287         showMessage(QString::fromLocal8Bit(fullCmd), LogInput);
1288
1289     CdbExtensionCommandPtr pendingCommand(new CdbExtensionCommand(fullCmd, token, flags, handler, nextCommandFlag, cookie));
1290
1291     m_extensionCommandQueue.push_back(pendingCommand);
1292     // Enclose command in echo-commands for token
1293     if (debug)
1294         qDebug("CdbEngine::postExtensionCommand %dms '%s' flags=%u token=%d %s next=%u, cookie='%s', pending=%d, sequence=0x%x",
1295                elapsedLogTime(), fullCmd.constData(), flags, token, stateName(state()), nextCommandFlag, qPrintable(cookie.toString()),
1296                m_extensionCommandQueue.size(), nextCommandFlag);
1297     m_process.write(fullCmd + '\n');
1298 }
1299
1300 void CdbEngine::activateFrame(int index)
1301 {
1302     // TODO: assembler,etc
1303     if (index < 0)
1304         return;
1305     const StackFrames &frames = stackHandler()->frames();
1306     QTC_ASSERT(index < frames.size(), return; )
1307
1308     const StackFrame frame = frames.at(index);
1309     if (debug || debugLocals)
1310         qDebug("activateFrame idx=%d '%s' %d", index,
1311                qPrintable(frame.file), frame.line);
1312     stackHandler()->setCurrentIndex(index);
1313     const bool showAssembler = !frames.at(index).isUsable();
1314     if (showAssembler) { // Assembly code: Clean out model and force instruction mode.
1315         watchHandler()->beginCycle();
1316         watchHandler()->endCycle();
1317         QAction *assemblerAction = theAssemblerAction();
1318         if (assemblerAction->isChecked()) {
1319             gotoLocation(frame);
1320         } else {
1321             assemblerAction->trigger(); // Seems to trigger update
1322         }
1323     } else {
1324         gotoLocation(frame);
1325         updateLocals(true);
1326     }
1327 }
1328
1329 void CdbEngine::updateLocals(bool forNewStackFrame)
1330 {
1331     typedef QHash<QByteArray, int> WatcherHash;
1332
1333     const int frameIndex = stackHandler()->currentIndex();
1334     if (frameIndex < 0) {
1335         watchHandler()->beginCycle();
1336         watchHandler()->endCycle();
1337         return;
1338     }
1339     const StackFrame frame = stackHandler()->currentFrame();
1340     if (!frame.isUsable()) {
1341         watchHandler()->beginCycle();
1342         watchHandler()->endCycle();
1343         return;
1344     }
1345     /* Watchers: Forcibly discard old symbol group as switching from
1346      * thread 0/frame 0 -> thread 1/assembly -> thread 0/frame 0 will otherwise re-use it
1347      * and cause errors as it seems to go 'stale' when switching threads.
1348      * Initial expand, get uninitialized and query */
1349     QByteArray arguments;
1350     ByteArrayInputStream str(arguments);
1351     str << "-D";
1352     // Pre-expand
1353     const QSet<QByteArray> expanded = watchHandler()->expandedINames();
1354     if (!expanded.isEmpty()) {
1355         str << blankSeparator << "-e ";
1356         int i = 0;
1357         foreach(const QByteArray &e, expanded) {
1358             if (i++)
1359                 str << ',';
1360             str << e;
1361         }
1362     }
1363     addLocalsOptions(str);
1364     // Uninitialized variables if desired
1365     if (debuggerCore()->boolSetting(UseCodeModel)) {
1366         QStringList uninitializedVariables;
1367         getUninitializedVariables(debuggerCore()->cppCodeModelSnapshot(),
1368                                   frame.function, frame.file, frame.line, &uninitializedVariables);
1369         if (!uninitializedVariables.isEmpty()) {
1370             str << blankSeparator << "-u ";
1371             int i = 0;
1372             foreach(const QString &u, uninitializedVariables) {
1373                 if (i++)
1374                     str << ',';
1375                 str << localsPrefixC << u;
1376             }
1377         }
1378     }
1379     // Perform watches synchronization
1380     str << blankSeparator << "-W";
1381     const WatcherHash watcherHash = WatchHandler::watcherNames();
1382     if (!watcherHash.isEmpty()) {
1383         const WatcherHash::const_iterator cend = watcherHash.constEnd();
1384         for (WatcherHash::const_iterator it = watcherHash.constBegin(); it != cend; ++it) {
1385             str << blankSeparator << "-w " << it.value() << " \"" << it.key() << '"';
1386         }
1387     }
1388
1389     // Required arguments: frame
1390     str << blankSeparator << frameIndex;
1391     watchHandler()->beginCycle();
1392     postExtensionCommand("locals", arguments, 0, &CdbEngine::handleLocals, 0, QVariant(forNewStackFrame));
1393 }
1394
1395 void CdbEngine::selectThread(int index)
1396 {
1397     if (index < 0 || index == threadsHandler()->currentThread())
1398         return;
1399
1400     resetLocation();
1401     const int newThreadId = threadsHandler()->threads().at(index).id;
1402     threadsHandler()->setCurrentThread(index);
1403
1404     const QByteArray cmd = "~" + QByteArray::number(newThreadId) + " s";
1405     postBuiltinCommand(cmd, 0, &CdbEngine::dummyHandler, CommandListStack);
1406 }
1407
1408 void CdbEngine::fetchDisassembler(DisassemblerAgent *agent)
1409 {
1410     QTC_ASSERT(m_accessible, return;)
1411     QByteArray cmd;
1412     ByteArrayInputStream str(cmd);
1413     str <<  "u " << hex << hexPrefixOn << agent->address() << " L40";
1414     const QVariant cookie = qVariantFromValue<DisassemblerAgent*>(agent);
1415     postBuiltinCommand(cmd, 0, &CdbEngine::handleDisassembler, 0, cookie);
1416 }
1417
1418 // Parse: "00000000`77606060 cc              int     3"
1419 void CdbEngine::handleDisassembler(const CdbBuiltinCommandPtr &command)
1420 {
1421     QTC_ASSERT(qVariantCanConvert<DisassemblerAgent*>(command->cookie), return;)
1422     DisassemblerAgent *agent = qvariant_cast<DisassemblerAgent*>(command->cookie);
1423     DisassemblerLines disassemblerLines;
1424     foreach(const QByteArray &line, command->reply)
1425         disassemblerLines.appendLine(DisassemblerLine(QString::fromLatin1(line)));
1426     agent->setContents(disassemblerLines);
1427 }
1428
1429 void CdbEngine::fetchMemory(MemoryAgent *agent, QObject *editor, quint64 addr, quint64 length)
1430 {
1431     if (!m_accessible) {
1432         qWarning("Internal error: Attempt to read memory from inaccessible session: %s", Q_FUNC_INFO);
1433         return;
1434     }
1435     if (debug)
1436         qDebug("CdbEngine::fetchMemory %llu bytes from 0x%llx", length, addr);
1437
1438     QByteArray args;
1439     ByteArrayInputStream str(args);
1440     str << addr << ' ' << length;
1441     const QVariant cookie = qVariantFromValue<MemoryViewCookie>(MemoryViewCookie(agent, editor, addr, length));
1442     postExtensionCommand("memory", args, 0, &CdbEngine::handleMemory, 0, cookie);
1443 }
1444
1445 void CdbEngine::handleMemory(const CdbExtensionCommandPtr &command)
1446 {
1447     QTC_ASSERT(qVariantCanConvert<MemoryViewCookie>(command->cookie), return;)
1448     const MemoryViewCookie memViewCookie = qvariant_cast<MemoryViewCookie>(command->cookie);
1449     if (command->success) {
1450         const QByteArray data = QByteArray::fromBase64(command->reply);
1451         if (unsigned(data.size()) == memViewCookie.length)
1452             memViewCookie.agent->addLazyData(memViewCookie.editorToken,
1453                                              memViewCookie.address, data);
1454     } else {
1455         showMessage(QString::fromLocal8Bit(command->errorMessage), LogError);
1456     }
1457 }
1458
1459 void CdbEngine::reloadModules()
1460 {
1461     postCommandSequence(CommandListModules);
1462 }
1463
1464 void CdbEngine::loadSymbols(const QString & /* moduleName */)
1465 {
1466 }
1467
1468 void CdbEngine::loadAllSymbols()
1469 {
1470 }
1471
1472 void CdbEngine::requestModuleSymbols(const QString &moduleName)
1473 {
1474     Q_UNUSED(moduleName)
1475 }
1476
1477 void CdbEngine::reloadRegisters()
1478 {
1479     postCommandSequence(CommandListRegisters);
1480 }
1481
1482 void CdbEngine::reloadSourceFiles()
1483 {
1484 }
1485
1486 void CdbEngine::reloadFullStack()
1487 {
1488     if (debug)
1489         qDebug("%s", Q_FUNC_INFO);
1490     postCommandSequence(CommandListStack);
1491 }
1492
1493 void CdbEngine::handlePid(const CdbExtensionCommandPtr &reply)
1494 {
1495     if (reply->success) {
1496         m_inferiorPid = reply->reply.toUInt();
1497         showMessage(QString::fromLatin1("Inferior pid: %1.").arg(m_inferiorPid), LogMisc);
1498         STATE_DEBUG(state(), Q_FUNC_INFO, __LINE__, "notifyInferiorSetupOk")
1499         notifyInferiorSetupOk();
1500     }  else {
1501         showMessage(QString::fromLatin1("Failed to determine inferior pid: %1").
1502                     arg(QLatin1String(reply->errorMessage)), LogError);
1503         STATE_DEBUG(state(), Q_FUNC_INFO, __LINE__, "notifyInferiorSetupFailed")
1504         notifyInferiorSetupFailed();
1505     }
1506 }
1507
1508 // Parse CDB gdbmi register syntax
1509 static inline Register parseRegister(const GdbMi &gdbmiReg)
1510 {
1511     Register reg;
1512     reg.name = gdbmiReg.findChild("name").data();
1513     const GdbMi description = gdbmiReg.findChild("description");
1514     if (description.type() != GdbMi::Invalid) {
1515         reg.name += " (";
1516         reg.name += description.data();
1517         reg.name += ')';
1518     }
1519     reg.value = QString::fromAscii(gdbmiReg.findChild("value").data());
1520     return reg;
1521 }
1522
1523 void CdbEngine::handleModules(const CdbExtensionCommandPtr &reply)
1524 {
1525     if (reply->success) {
1526         GdbMi value;
1527         value.fromString(reply->reply);
1528         if (value.type() == GdbMi::List) {
1529             Modules modules;
1530             modules.reserve(value.childCount());
1531             foreach (const GdbMi &gdbmiModule, value.children()) {
1532                 Module module;
1533                 module.moduleName = QString::fromAscii(gdbmiModule.findChild("name").data());
1534                 module.modulePath = QString::fromAscii(gdbmiModule.findChild("image").data());
1535                 module.startAddress = gdbmiModule.findChild("start").data().toULongLong(0, 0);
1536                 module.endAddress = gdbmiModule.findChild("end").data().toULongLong(0, 0);
1537                 if (gdbmiModule.findChild("deferred").type() == GdbMi::Invalid)
1538                     module.symbolsRead = Module::ReadOk;
1539                 modules.push_back(module);
1540             }
1541             modulesHandler()->setModules(modules);
1542         } else {
1543             showMessage(QString::fromLatin1("Parse error in modules response."), LogError);
1544             qWarning("Parse error in modules response:\n%s", reply->reply.constData());
1545         }
1546     }  else {
1547         showMessage(QString::fromLatin1("Failed to determine modules: %1").
1548                     arg(QLatin1String(reply->errorMessage)), LogError);
1549     }
1550     postCommandSequence(reply->commandSequence);
1551
1552 }
1553
1554 void CdbEngine::handleRegisters(const CdbExtensionCommandPtr &reply)
1555 {
1556     if (reply->success) {
1557         GdbMi value;
1558         value.fromString(reply->reply);
1559         if (value.type() == GdbMi::List) {
1560             Registers registers;
1561             registers.reserve(value.childCount());
1562             foreach (const GdbMi &gdbmiReg, value.children())
1563                 registers.push_back(parseRegister(gdbmiReg));
1564             registerHandler()->setRegisters(registers);
1565         } else {
1566             showMessage(QString::fromLatin1("Parse error in registers response."), LogError);
1567             qWarning("Parse error in registers response:\n%s", reply->reply.constData());
1568         }
1569     }  else {
1570         showMessage(QString::fromLatin1("Failed to determine registers: %1").
1571                     arg(QLatin1String(reply->errorMessage)), LogError);
1572     }
1573     postCommandSequence(reply->commandSequence);
1574 }
1575
1576 void CdbEngine::handleLocals(const CdbExtensionCommandPtr &reply)
1577 {
1578     if (reply->success) {
1579         QList<WatchData> watchData;
1580         GdbMi root;
1581         root.fromString(reply->reply);
1582         QTC_ASSERT(root.isList(), return ; )
1583         if (debugLocals) {
1584             qDebug() << root.toString(true, 4);
1585         }
1586         // Courtesy of GDB engine
1587         foreach (const GdbMi &child, root.children()) {
1588             WatchData dummy;
1589             dummy.iname = child.findChild("iname").data();
1590             dummy.name = QLatin1String(child.findChild("name").data());
1591             parseWatchData(watchHandler()->expandedINames(), dummy, child, &watchData);
1592         }
1593         watchHandler()->insertBulkData(watchData);
1594         watchHandler()->endCycle();
1595         if (debugLocals) {
1596             QDebug nsp = qDebug().nospace();
1597             nsp << "Obtained " << watchData.size() << " items:\n";
1598             foreach (const WatchData &wd, watchData)
1599                 nsp << wd.toString() <<'\n';
1600         }
1601         const bool forNewStackFrame = reply->cookie.toBool();
1602         if (forNewStackFrame)
1603             emit stackFrameCompleted();
1604     } else {
1605         showMessage(QString::fromLatin1(reply->errorMessage), LogError);
1606     }
1607 }
1608
1609 void CdbEngine::handleExpandLocals(const CdbExtensionCommandPtr &reply)
1610 {
1611     if (!reply->success)
1612         showMessage(QString::fromLatin1(reply->errorMessage), LogError);
1613 }
1614
1615 enum CdbExecutionStatus {
1616 CDB_STATUS_NO_CHANGE=0, CDB_STATUS_GO = 1, CDB_STATUS_GO_HANDLED = 2,
1617 CDB_STATUS_GO_NOT_HANDLED = 3, CDB_STATUS_STEP_OVER = 4,
1618 CDB_STATUS_STEP_INTO = 5, CDB_STATUS_BREAK = 6, CDB_STATUS_NO_DEBUGGEE = 7,
1619 CDB_STATUS_STEP_BRANCH = 8, CDB_STATUS_IGNORE_EVENT = 9,
1620 CDB_STATUS_RESTART_REQUESTED = 10, CDB_STATUS_REVERSE_GO = 11,
1621 CDB_STATUS_REVERSE_STEP_BRANCH = 12, CDB_STATUS_REVERSE_STEP_OVER = 13,
1622 CDB_STATUS_REVERSE_STEP_INTO = 14 };
1623
1624 static const char *cdbStatusName(unsigned long s)
1625 {
1626     switch (s) {
1627     case CDB_STATUS_NO_CHANGE:
1628         return "No change";
1629     case CDB_STATUS_GO:
1630         return "go";
1631     case CDB_STATUS_GO_HANDLED:
1632         return "go_handled";
1633     case CDB_STATUS_GO_NOT_HANDLED:
1634         return "go_not_handled";
1635     case CDB_STATUS_STEP_OVER:
1636         return "step_over";
1637     case CDB_STATUS_STEP_INTO:
1638         return "step_into";
1639     case CDB_STATUS_BREAK:
1640         return "break";
1641     case CDB_STATUS_NO_DEBUGGEE:
1642         return "no_debuggee";
1643     case CDB_STATUS_STEP_BRANCH:
1644         return "step_branch";
1645     case CDB_STATUS_IGNORE_EVENT:
1646         return "ignore_event";
1647     case CDB_STATUS_RESTART_REQUESTED:
1648         return "restart_requested";
1649     case CDB_STATUS_REVERSE_GO:
1650         return "reverse_go";
1651     case CDB_STATUS_REVERSE_STEP_BRANCH:
1652         return "reverse_step_branch";
1653     case CDB_STATUS_REVERSE_STEP_OVER:
1654         return "reverse_step_over";
1655     case CDB_STATUS_REVERSE_STEP_INTO:
1656         return "reverse_step_into";
1657     }
1658     return "unknown";
1659 }
1660
1661 /* Examine how to react to a stop. */
1662 enum StopActionFlags
1663 {
1664     // Report options
1665     StopReportLog = 0x1,
1666     StopReportStatusMessage = 0x2,
1667     StopReportParseError = 0x4,
1668     StopShowExceptionMessageBox = 0x8,
1669     // Notify stop or just continue
1670     StopNotifyStop = 0x10,
1671     StopIgnoreContinue = 0x20,
1672     // Hit on break in artificial stop thread (created by DebugBreak()).
1673     StopInArtificialThread = 0x40,
1674     StopShutdownInProgress = 0x80 // Shutdown in progress
1675 };
1676
1677 unsigned CdbEngine::examineStopReason(const GdbMi &stopReason,
1678                                       QString *message,
1679                                       QString *exceptionBoxMessage)
1680 {
1681     // Report stop reason (GDBMI)
1682     unsigned rc  = 0;
1683     if (targetState() == DebuggerFinished)
1684         rc |= StopShutdownInProgress;
1685     if (debug)
1686         qDebug("%s", stopReason.toString(true, 4).constData());
1687     const QByteArray reason = stopReason.findChild("reason").data();
1688     if (reason.isEmpty()) {
1689         *message = tr("Malformed stop response received.");
1690         rc |= StopReportParseError|StopNotifyStop;
1691         return rc;
1692     }
1693     // Additional stop messages occurring for debuggee function calls (widgetAt, etc). Just log.
1694     if (state() == InferiorStopOk) {
1695         *message = QString::fromLatin1("Ignored stop notification from function call (%1).").
1696                     arg(QString::fromAscii(reason));
1697         rc |= StopReportLog;
1698         return rc;
1699     }
1700     const int threadId = stopReason.findChild("threadId").data().toInt();
1701     if (reason == "breakpoint") {
1702         // Note: Internal breakpoints (run to line) are reported with id=0.
1703         BreakpointId id = 0;
1704         int number = 0;
1705         const GdbMi breakpointIdG = stopReason.findChild("breakpointId");
1706         if (breakpointIdG.isValid()) {
1707             id = breakpointIdG.data().toULongLong();
1708             if (id)
1709                 number = breakHandler()->response(id).number;
1710         }
1711         if (id && breakHandler()->type(id) == Watchpoint) {
1712             *message = msgWatchpointTriggered(id, number, breakHandler()->address(id), QString::number(threadId));
1713         } else {
1714             *message = msgBreakpointTriggered(id, number, QString::number(threadId));
1715         }
1716         rc |= StopReportStatusMessage|StopNotifyStop;
1717         return rc;
1718     }
1719     if (reason == "exception") {
1720         WinException exception;
1721         exception.fromGdbMI(stopReason);
1722         QString description = exception.toString();
1723 #ifdef Q_OS_WIN
1724         // It is possible to hit on a startup trap while stepping (if something
1725         // pulls DLLs. Avoid showing a 'stopped' Message box.
1726         if (exception.exceptionCode == winExceptionStartupCompleteTrap)
1727             return StopNotifyStop;
1728         if (exception.exceptionCode == winExceptionCtrlPressed) {
1729             // Detect interruption by pressing Ctrl in a console and force a switch to thread 0.
1730             *message = msgInterrupted();
1731             rc |= StopReportStatusMessage|StopNotifyStop|StopInArtificialThread;
1732             return rc;
1733         }
1734         if (isDebuggerWinException(exception.exceptionCode)) {
1735             rc |= StopReportStatusMessage|StopNotifyStop;
1736             // Detect interruption by DebugBreak() and force a switch to thread 0.
1737             if (exception.function == "ntdll!DbgBreakPoint")
1738                 rc |= StopInArtificialThread;
1739             *message = msgInterrupted();
1740             return rc;
1741         }
1742 #endif
1743         *exceptionBoxMessage = msgStoppedByException(description, QString::number(threadId));
1744         *message = description;
1745         rc |= StopShowExceptionMessageBox|StopReportStatusMessage|StopNotifyStop;
1746         return rc;
1747     }
1748     *message = msgStopped(QLatin1String(reason));
1749     rc |= StopReportStatusMessage|StopNotifyStop;
1750     return rc;
1751 }
1752
1753 void CdbEngine::handleSessionIdle(const QByteArray &messageBA)
1754 {
1755     if (!m_hasDebuggee)
1756         return;
1757
1758     if (debug)
1759         qDebug("CdbEngine::handleSessionIdle %dms '%s' in state '%s', special mode %d",
1760                elapsedLogTime(), messageBA.constData(),
1761                stateName(state()), m_specialStopMode);
1762
1763     // Switch source level debugging
1764     syncOperateByInstruction(m_operateByInstructionPending);
1765
1766     // Engine-special stop reasons: Breakpoints and setup
1767     const SpecialStopMode specialStopMode =  m_specialStopMode;
1768
1769     m_specialStopMode = NoSpecialStop;
1770
1771     switch(specialStopMode) {
1772     case SpecialStopSynchronizeBreakpoints:
1773         if (debug)
1774             qDebug("attemptBreakpointSynchronization in special stop");
1775         attemptBreakpointSynchronization();
1776         doContinueInferior();
1777         return;
1778     case SpecialStopGetWidgetAt:
1779         postWidgetAtCommand();
1780         return;
1781     case NoSpecialStop:
1782         break;
1783     }
1784
1785     if (state() == EngineSetupRequested) { // Temporary stop at beginning
1786         STATE_DEBUG(state(), Q_FUNC_INFO, __LINE__, "notifyEngineSetupOk")
1787         notifyEngineSetupOk();
1788         return;
1789     }
1790
1791     // Further examine stop and report to user
1792     QString message;
1793     QString exceptionBoxMessage;
1794     GdbMi stopReason;
1795     stopReason.fromString(messageBA);
1796     int forcedThreadId = -1;
1797     const unsigned stopFlags = examineStopReason(stopReason, &message, &exceptionBoxMessage);
1798     // Do the non-blocking log reporting
1799     if (stopFlags & StopReportLog)
1800         showMessage(message, LogMisc);
1801     if (stopFlags & StopReportStatusMessage)
1802         showStatusMessage(message);
1803     if (stopFlags & StopReportParseError)
1804         showMessage(message, LogError);
1805     // Ignore things like WOW64
1806     if (stopFlags & StopIgnoreContinue) {
1807         postCommand("g", 0);
1808         return;
1809     }
1810     // Notify about state and send off command sequence to get stack, etc.
1811     if (stopFlags & StopNotifyStop) {
1812         if (state() == InferiorStopRequested) {
1813             STATE_DEBUG(state(), Q_FUNC_INFO, __LINE__, "notifyInferiorStopOk")
1814             notifyInferiorStopOk();
1815         } else {
1816             STATE_DEBUG(state(), Q_FUNC_INFO, __LINE__, "notifyInferiorSpontaneousStop")
1817             notifyInferiorSpontaneousStop();
1818         }
1819         // Prevent further commands from being sent if shutdown is in progress
1820         if (stopFlags & StopShutdownInProgress) {
1821             showMessage(QString::fromLatin1("Shutdown request detected..."));
1822             return;
1823         }
1824         const bool sourceStepInto = m_sourceStepInto;
1825         m_sourceStepInto = false;
1826         // Start sequence to get all relevant data.
1827         if (stopFlags & StopInArtificialThread) {
1828             showMessage(tr("Switching to main thread..."), LogMisc);
1829             postCommand("~0 s", 0);
1830             forcedThreadId = 0;
1831             // Re-fetch stack again.
1832             postCommandSequence(CommandListStack);
1833         } else {
1834             const GdbMi stack = stopReason.findChild("stack");
1835             if (stack.isValid()) {
1836                 if (parseStackTrace(stack, sourceStepInto) & ParseStackStepInto) {
1837                     executeStep(); // Hit on a frame while step into, see parseStackTrace().
1838                     return;
1839                 }
1840             } else {
1841                 showMessage(QString::fromAscii(stopReason.findChild("stackerror").data()), LogError);
1842             }
1843         }
1844         const GdbMi threads = stopReason.findChild("threads");
1845         if (threads.isValid()) {
1846             parseThreads(threads, forcedThreadId);
1847         } else {
1848             showMessage(QString::fromAscii(stopReason.findChild("threaderror").data()), LogError);
1849         }
1850         // Fire off remaining commands asynchronously
1851         if (!m_pendingBreakpointMap.isEmpty())
1852             postCommandSequence(CommandListBreakPoints);
1853         if (debuggerCore()->isDockVisible(QLatin1String(Constants::DOCKWIDGET_REGISTER)))
1854             postCommandSequence(CommandListRegisters);
1855         if (debuggerCore()->isDockVisible(QLatin1String(Constants::DOCKWIDGET_MODULES)))
1856             postCommandSequence(CommandListModules);
1857     }
1858     // After the sequence has been sent off and CDB is pondering the commands,
1859     // pop up a message box for exceptions.
1860     if (stopFlags & StopShowExceptionMessageBox)
1861         showStoppedByExceptionMessageBox(exceptionBoxMessage);
1862 }
1863
1864 void CdbEngine::handleSessionAccessible(unsigned long cdbExState)
1865 {
1866     const DebuggerState s = state();
1867     if (!m_hasDebuggee || s == InferiorRunOk) // suppress reports
1868         return;
1869
1870     if (debug)
1871         qDebug("CdbEngine::handleSessionAccessible %dms in state '%s'/'%s', special mode %d",
1872                elapsedLogTime(), cdbStatusName(cdbExState), stateName(state()), m_specialStopMode);
1873
1874     switch(s) {
1875     case EngineShutdownRequested:
1876         shutdownEngine();
1877         break;
1878     case InferiorShutdownRequested:
1879         shutdownInferior();
1880         break;
1881     default:
1882         break;
1883     }
1884 }
1885
1886 void CdbEngine::handleSessionInaccessible(unsigned long cdbExState)
1887 {
1888     const DebuggerState s = state();
1889
1890     // suppress reports
1891     if (!m_hasDebuggee || (s == InferiorRunOk && cdbExState != CDB_STATUS_NO_DEBUGGEE))
1892         return;
1893
1894     if (debug)
1895         qDebug("CdbEngine::handleSessionInaccessible %dms in state '%s', '%s', special mode %d",
1896                elapsedLogTime(), cdbStatusName(cdbExState), stateName(state()), m_specialStopMode);
1897
1898     switch (state()) {
1899     case EngineSetupRequested:
1900         break;
1901     case EngineRunRequested:
1902         STATE_DEBUG(state(), Q_FUNC_INFO, __LINE__, "notifyEngineRunAndInferiorRunOk")
1903         notifyEngineRunAndInferiorRunOk();
1904         break;
1905     case InferiorRunOk:
1906     case InferiorStopOk:
1907         // Inaccessible without debuggee (exit breakpoint)
1908         // We go for spontaneous engine shutdown instead.
1909         if (cdbExState == CDB_STATUS_NO_DEBUGGEE) {
1910             if (debug)
1911                 qDebug("Lost debuggeee");
1912             m_hasDebuggee = false;
1913         }
1914         break;
1915     case InferiorRunRequested:
1916         STATE_DEBUG(state(), Q_FUNC_INFO, __LINE__, "notifyInferiorRunOk")
1917         notifyInferiorRunOk();
1918         resetLocation();
1919         break;
1920     case EngineShutdownRequested:
1921         break;
1922     default:
1923         break;
1924     }
1925 }
1926
1927 void CdbEngine::handleExtensionMessage(char t, int token, const QByteArray &what, const QByteArray &message)
1928 {
1929     if (debug > 1) {
1930         QDebug nospace = qDebug().nospace();
1931         nospace << "handleExtensionMessage " << t << ' ' << token << ' ' << what
1932                 << ' ' << stateName(state());
1933         if (t == 'N' || debug > 1) {
1934             nospace << ' ' << message;
1935         } else {
1936             nospace << ' ' << message.size() << " bytes";
1937         }
1938     }
1939
1940     // Is there a reply expected, some command queued?
1941     if (t == 'R' || t == 'N') {
1942         if (token == -1) { // Default token, user typed in extension command
1943             showMessage(QString::fromLatin1(message), LogMisc);
1944             return;
1945         }
1946         const int index = indexOfCommand(m_extensionCommandQueue, token);
1947         if (index != -1) {
1948             // Did the command finish? Take off queue and complete, invoke CB
1949             const CdbExtensionCommandPtr command = m_extensionCommandQueue.takeAt(index);
1950             if (t == 'R') {
1951                 command->success = true;
1952                 command->reply = message;
1953             } else {
1954                 command->success = false;
1955                 command->errorMessage = message;
1956             }
1957             if (debug)
1958                 qDebug("### Completed extension command '%s', token=%d, pending=%d",
1959                        command->command.constData(), command->token, m_extensionCommandQueue.size());
1960             if (command->handler)
1961                 (this->*(command->handler))(command);
1962             return;
1963         }
1964     }
1965
1966     if (what == "debuggee_output") {
1967         showMessage(StringFromBase64EncodedUtf16(message), AppOutput);
1968         return;
1969     }
1970
1971     if (what == "event") {
1972         showStatusMessage(QString::fromAscii(message),  5000);
1973         return;
1974     }
1975
1976     if (what == "session_accessible") {
1977         if (!m_accessible) {
1978             m_accessible = true;
1979             handleSessionAccessible(message.toULong());
1980         }
1981         return;
1982     }
1983
1984     if (what == "session_inaccessible") {
1985         if (m_accessible) {
1986             m_accessible = false;
1987             handleSessionInaccessible(message.toULong());
1988         }
1989         return;
1990     }
1991
1992     if (what == "session_idle") {
1993         handleSessionIdle(message);
1994         return;
1995     }
1996
1997     if (what == "exception") {
1998         WinException exception;
1999         GdbMi gdbmi;
2000         gdbmi.fromString(message);
2001         exception.fromGdbMI(gdbmi);
2002         const QString message = exception.toString(true);
2003         showStatusMessage(message);
2004 #ifdef Q_OS_WIN // Report C++ exception in application output as well.
2005         if (exception.exceptionCode == winExceptionCppException)
2006             showMessage(message + QLatin1Char('\n'), AppOutput);
2007 #endif
2008         return;
2009     }
2010
2011     return;
2012 }
2013
2014 // Check for a CDB prompt '0:000> ' ('process:thread> ')..no regexps for QByteArray...
2015 enum { CdbPromptLength = 7 };
2016
2017 static inline bool isCdbPrompt(const QByteArray &c)
2018 {
2019     return c.size() >= CdbPromptLength && c.at(6) == ' ' && c.at(5) == '>' && c.at(1) == ':'
2020             && std::isdigit(c.at(0)) &&  std::isdigit(c.at(2)) && std::isdigit(c.at(3))
2021             && std::isdigit(c.at(4));
2022 }
2023
2024 // Check for '<token>32>' or '<token>32<'
2025 static inline bool checkCommandToken(const QByteArray &tokenPrefix, const QByteArray &c,
2026                                   int *token, bool *isStart)
2027 {
2028     *token = 0;
2029     *isStart = false;
2030     const int tokenPrefixSize = tokenPrefix.size();
2031     const int size = c.size();
2032     if (size < tokenPrefixSize + 2 || !std::isdigit(c.at(tokenPrefixSize)))
2033         return false;
2034     switch (c.at(size - 1)) {
2035     case '>':
2036         *isStart = false;
2037         break;
2038     case '<':
2039         *isStart = true;
2040         break;
2041     default:
2042         return false;
2043     }
2044     if (!c.startsWith(tokenPrefix))
2045         return false;
2046     bool ok;
2047     *token = c.mid(tokenPrefixSize, size - tokenPrefixSize - 1).toInt(&ok);
2048     return ok;
2049 }
2050
2051 void CdbEngine::parseOutputLine(QByteArray line)
2052 {
2053     // The hooked output callback in the extension suppresses prompts,
2054     // it should happen only in initial and exit stages. Note however that
2055     // if the output is not hooked, sequences of prompts are possible which
2056     // can mix things up.
2057     while (isCdbPrompt(line))
2058         line.remove(0, CdbPromptLength);
2059     // An extension notification (potentially consisting of several chunks)
2060     if (line.startsWith(m_creatorExtPrefix)) {
2061         // "<qtcreatorcdbext>|type_char|token|remainingChunks|serviceName|message"
2062         const char type = line.at(m_creatorExtPrefix.size());
2063         // integer token
2064         const int tokenPos = m_creatorExtPrefix.size() + 2;
2065         const int tokenEndPos = line.indexOf('|', tokenPos);
2066         QTC_ASSERT(tokenEndPos != -1, return)
2067         const int token = line.mid(tokenPos, tokenEndPos - tokenPos).toInt();
2068         // remainingChunks
2069         const int remainingChunksPos = tokenEndPos + 1;
2070         const int remainingChunksEndPos = line.indexOf('|', remainingChunksPos);
2071         QTC_ASSERT(remainingChunksEndPos != -1, return)
2072         const int remainingChunks = line.mid(remainingChunksPos, remainingChunksEndPos - remainingChunksPos).toInt();
2073         // const char 'serviceName'
2074         const int whatPos = remainingChunksEndPos + 1;
2075         const int whatEndPos = line.indexOf('|', whatPos);
2076         QTC_ASSERT(whatEndPos != -1, return)
2077         const QByteArray what = line.mid(whatPos, whatEndPos - whatPos);
2078         // Build up buffer, call handler once last chunk was encountered
2079         m_extensionMessageBuffer += line.mid(whatEndPos + 1);
2080         if (remainingChunks == 0) {
2081             handleExtensionMessage(type, token, what, m_extensionMessageBuffer);
2082             m_extensionMessageBuffer.clear();
2083         }
2084         return;
2085     }
2086     // Check for command start/end tokens within which the builtin command
2087     // output is enclosed
2088     int token = 0;
2089     bool isStartToken = false;
2090     const bool isCommandToken = checkCommandToken(m_tokenPrefix, line, &token, &isStartToken);
2091     if (debug > 1)
2092         qDebug("Reading CDB stdout '%s',\n  isCommand=%d, token=%d, isStart=%d, current=%d",
2093                line.constData(), isCommandToken, token, isStartToken, m_currentBuiltinCommandIndex);
2094
2095     // If there is a current command, wait for end of output indicated by token,
2096     // command, trigger handler and finish, else append to its output.
2097     if (m_currentBuiltinCommandIndex != -1) {
2098         QTC_ASSERT(!isStartToken && m_currentBuiltinCommandIndex < m_builtinCommandQueue.size(), return; );
2099         const CdbBuiltinCommandPtr &currentCommand = m_builtinCommandQueue.at(m_currentBuiltinCommandIndex);
2100         if (isCommandToken) {
2101             // Did the command finish? Invoke callback and remove from queue.
2102             if (debug)
2103                 qDebug("### Completed builtin command '%s', token=%d, %d lines, pending=%d",
2104                        currentCommand->command.constData(), currentCommand->token,
2105                        currentCommand->reply.size(), m_builtinCommandQueue.size() - 1);
2106             QTC_ASSERT(token == currentCommand->token, return; );
2107             if (currentCommand->handler)
2108                 (this->*(currentCommand->handler))(currentCommand);
2109             m_builtinCommandQueue.removeAt(m_currentBuiltinCommandIndex);
2110             m_currentBuiltinCommandIndex = -1;
2111         } else {
2112             // Record output of current command
2113             currentCommand->reply.push_back(line);
2114         }
2115         return;
2116     } // m_currentCommandIndex
2117     if (isCommandToken) {
2118         // Beginning command token encountered, start to record output.
2119         const int index = indexOfCommand(m_builtinCommandQueue, token);
2120         QTC_ASSERT(isStartToken && index != -1, return; );
2121         m_currentBuiltinCommandIndex = index;
2122         const CdbBuiltinCommandPtr &currentCommand = m_builtinCommandQueue.at(m_currentBuiltinCommandIndex);
2123         if (debug)
2124             qDebug("### Gathering output for '%s' token %d", currentCommand->command.constData(), currentCommand->token);
2125         return;
2126     }
2127
2128     showMessage(QString::fromLocal8Bit(line), LogMisc);
2129 }
2130
2131 void CdbEngine::readyReadStandardOut()
2132 {
2133     if (m_ignoreCdbOutput)
2134         return;
2135     m_outputBuffer += m_process.readAllStandardOutput();
2136     // Split into lines and parse line by line.
2137     while (true) {
2138         const int endOfLinePos = m_outputBuffer.indexOf('\n');
2139         if (endOfLinePos == -1) {
2140             break;
2141         } else {
2142             // Check for '\r\n'
2143             QByteArray line = m_outputBuffer.left(endOfLinePos);
2144             if (!line.isEmpty() && line.at(line.size() - 1) == '\r')
2145                 line.truncate(line.size() - 1);
2146             parseOutputLine(line);
2147             m_outputBuffer.remove(0, endOfLinePos + 1);
2148         }
2149     }
2150 }
2151
2152 void CdbEngine::readyReadStandardError()
2153 {
2154     showMessage(QString::fromLocal8Bit(m_process.readAllStandardError()), LogError);
2155 }
2156
2157 void CdbEngine::processError()
2158 {
2159     showMessage(m_process.errorString(), LogError);
2160 }
2161
2162 #if 0
2163 // Join breakpoint ids for a multi-breakpoint id commands like 'bc', 'be', 'bd'
2164 static QByteArray multiBreakpointCommand(const char *cmdC, const Breakpoints &bps)
2165 {
2166     QByteArray cmd(cmdC);
2167     ByteArrayInputStream str(cmd);
2168     foreach(const BreakpointData *bp, bps)
2169         str << ' ' << bp->bpNumber;
2170     return cmd;
2171 }
2172 #endif
2173
2174 bool CdbEngine::stateAcceptsBreakpointChanges() const
2175 {
2176     switch (state()) {
2177     case InferiorRunOk:
2178     case InferiorStopOk:
2179     return true;
2180     default:
2181         break;
2182     }
2183     return false;
2184 }
2185
2186 bool CdbEngine::acceptsBreakpoint(BreakpointId id) const
2187 {
2188     return DebuggerEngine::isCppBreakpoint(breakHandler()->breakpointData(id));
2189 }
2190
2191 void CdbEngine::attemptBreakpointSynchronization()
2192 {
2193     if (debug)
2194         qDebug("attemptBreakpointSynchronization in %s", stateName(state()));
2195     // Check if there is anything to be done at all.
2196     BreakHandler *handler = breakHandler();
2197     // Take ownership of the breakpoint. Requests insertion. TODO: Cpp only?
2198     foreach (BreakpointId id, handler->unclaimedBreakpointIds())
2199         if (acceptsBreakpoint(id))
2200             handler->setEngine(id, this);
2201
2202     // Quick check: is there a need to change something? - Populate module cache
2203     bool changed = false;
2204     const BreakpointIds ids = handler->engineBreakpointIds(this);
2205     foreach (BreakpointId id, ids) {
2206         switch (handler->state(id)) {
2207         case BreakpointInsertRequested:
2208         case BreakpointRemoveRequested:
2209         case BreakpointChangeRequested:
2210             changed = true;
2211             break;
2212         case BreakpointInserted: {
2213             // Collect the new modules matching the files.
2214             // In the future, that information should be obtained from the build system.
2215             const BreakpointParameters &data = handler->breakpointData(id);
2216             if (data.type == BreakpointByFileAndLine && !data.module.isEmpty())
2217                 m_fileNameModuleHash.insert(data.fileName, data.module);
2218         }
2219         break;
2220         default:
2221             break;
2222         }
2223     }
2224
2225     if (debugBreakpoints)
2226         qDebug("attemptBreakpointSynchronizationI %dms accessible=%d, %s %d breakpoints, changed=%d",
2227                elapsedLogTime(), m_accessible, stateName(state()), ids.size(), changed);
2228     if (!changed)
2229         return;
2230
2231     if (!m_accessible) {
2232         // No nested calls.
2233         if (m_specialStopMode != SpecialStopSynchronizeBreakpoints)
2234             doInterruptInferior(SpecialStopSynchronizeBreakpoints);
2235         return;
2236     }
2237     // Add/Change breakpoints and store pending ones in map, since
2238     // Breakhandler::setResponse() on pending breakpoints clears the pending flag.
2239     // handleBreakPoints will the complete that information and set it on the break handler.
2240     bool addedChanged = false;
2241     foreach (BreakpointId id, ids) {
2242         BreakpointParameters parameters = handler->breakpointData(id);
2243         BreakpointResponse response;
2244         response.fromParameters(parameters);
2245         // If we encountered that file and have a module for it: Add it.
2246         if (parameters.type == BreakpointByFileAndLine && parameters.module.isEmpty()) {
2247             const QHash<QString, QString>::const_iterator it = m_fileNameModuleHash.constFind(parameters.fileName);
2248             if (it != m_fileNameModuleHash.constEnd())
2249                 parameters.module = it.value();
2250         }
2251         switch (handler->state(id)) {
2252         case BreakpointInsertRequested:
2253             postCommand(cdbAddBreakpointCommand(parameters, id, false), 0);
2254             if (!parameters.enabled)
2255                 postCommand("bd " + QByteArray::number(id), 0);
2256             handler->notifyBreakpointInsertProceeding(id);
2257             handler->notifyBreakpointInsertOk(id);
2258             m_pendingBreakpointMap.insert(id, response);
2259             addedChanged = true;
2260             if (debugBreakpoints)
2261                 qDebug("Adding %llu %s\n", id, qPrintable(response.toString()));
2262             break;
2263         case BreakpointChangeRequested:
2264             handler->notifyBreakpointChangeProceeding(id);
2265             if (parameters.enabled != handler->response(id).enabled) {
2266                 // Change enabled/disabled breakpoints without triggering update.
2267                 postCommand((parameters.enabled ? "be " : "bd ") + QByteArray::number(id), 0);
2268                 response.pending = false;
2269                 response.enabled = parameters.enabled;
2270                 handler->setResponse(id, response);
2271             } else {
2272                 // Delete and re-add, triggering update
2273                 addedChanged = true;
2274                 postCommand("bc " + QByteArray::number(id), 0);
2275                 postCommand(cdbAddBreakpointCommand(parameters, id, false), 0);
2276                 m_pendingBreakpointMap.insert(id, response);
2277             }
2278             handler->notifyBreakpointChangeOk(id);
2279             if (debugBreakpoints)
2280                 qDebug("Changing %llu %s\n", id, qPrintable(response.toString()));
2281             break;
2282         case BreakpointRemoveRequested:
2283             postCommand("bc " + QByteArray::number(id), 0);
2284             handler->notifyBreakpointRemoveProceeding(id);
2285             handler->notifyBreakpointRemoveOk(id);
2286             m_pendingBreakpointMap.remove(id);
2287             break;
2288         default:
2289             break;
2290         }
2291     }
2292     // List breakpoints and send responses
2293     if (addedChanged)
2294         postCommandSequence(CommandListBreakPoints);
2295 }
2296
2297 QString CdbEngine::normalizeFileName(const QString &f)
2298 {
2299     QMap<QString, QString>::const_iterator it = m_normalizedFileCache.constFind(f);
2300     if (it != m_normalizedFileCache.constEnd())
2301         return it.value();
2302     const QString winF = QDir::toNativeSeparators(f);
2303 #ifdef Q_OS_WIN
2304     QString normalized = winNormalizeFileName(winF);
2305 #else
2306     QString normalized = winF;
2307 #endif
2308     if (normalized.isEmpty()) { // At least upper case drive letter
2309         normalized = winF;
2310         if (normalized.size() > 2 && normalized.at(1) == QLatin1Char(':'))
2311             normalized[0] = normalized.at(0).toUpper();
2312     }
2313     m_normalizedFileCache.insert(f, normalized);
2314     return normalized;
2315 }
2316
2317 // Parse frame from GDBMI. Duplicate of the gdb code, but that
2318 // has more processing.
2319 static StackFrames parseFrames(const GdbMi &gdbmi)
2320 {
2321     StackFrames rc;
2322     const int count = gdbmi.childCount();
2323     rc.reserve(count);
2324     for (int i = 0; i  < count; i++) {
2325         const GdbMi &frameMi = gdbmi.childAt(i);
2326         StackFrame frame;
2327         frame.level = i;
2328         const GdbMi fullName = frameMi.findChild("fullname");
2329         if (fullName.isValid()) {
2330             frame.file = QFile::decodeName(fullName.data());
2331             frame.line = frameMi.findChild("line").data().toInt();
2332             frame.usable = QFileInfo(frame.file).isFile();
2333         }
2334         frame.function = QLatin1String(frameMi.findChild("func").data());
2335         frame.from = QLatin1String(frameMi.findChild("from").data());
2336         frame.address = frameMi.findChild("addr").data().toULongLong(0, 16);
2337         rc.push_back(frame);
2338     }
2339     return rc;
2340 }
2341
2342 unsigned CdbEngine::parseStackTrace(const GdbMi &data, bool sourceStepInto)
2343 {
2344     // Parse frames, find current. Special handling for step into:
2345     // When stepping into on an actual function (source mode) by executing 't', an assembler
2346     // frame pointing at the jmp instruction is hit (noticeable by top function being
2347     // 'ILT+'). If that is the case, execute another 't' to step into the actual function.    .
2348     // Note that executing 't 2' does not work since it steps 2 instructions on a non-call code line.
2349     int current = -1;
2350     StackFrames frames = parseFrames(data);
2351     const int count = frames.size();
2352     for (int i = 0; i < count; i++) {
2353         const bool hasFile = !frames.at(i).file.isEmpty();
2354         // jmp-frame hit by step into, do another 't' and abort sequence.
2355         if (!hasFile && i == 0 && sourceStepInto && frames.at(i).function.contains(QLatin1String("ILT+"))) {
2356             showMessage(QString::fromAscii("Step into: Call instruction hit, performing additional step..."), LogMisc);
2357             return ParseStackStepInto;
2358         }
2359         if (hasFile) {
2360             frames[i].file = QDir::cleanPath(normalizeFileName(frames.at(i).file));
2361             if (current == -1 && frames[i].usable)
2362                 current = i;
2363         }
2364     }
2365     if (count && current == -1) // No usable frame, use assembly.
2366         current = 0;
2367     // Set
2368     stackHandler()->setFrames(frames);
2369     activateFrame(current);
2370     return 0;
2371 }
2372
2373 void CdbEngine::handleStackTrace(const CdbExtensionCommandPtr &command)
2374 {
2375     if (command->success) {
2376         GdbMi data;
2377         data.fromString(command->reply);
2378         parseStackTrace(data, false);
2379         postCommandSequence(command->commandSequence);
2380     } else {
2381         showMessage(command->errorMessage, LogError);
2382     }
2383 }
2384
2385 void CdbEngine::dummyHandler(const CdbBuiltinCommandPtr &command)
2386 {
2387     postCommandSequence(command->commandSequence);
2388 }
2389
2390 // Post a sequence of standard commands: Trigger next once one completes successfully
2391 void CdbEngine::postCommandSequence(unsigned mask)
2392 {
2393     if (debug)
2394         qDebug("postCommandSequence 0x%x\n", mask);
2395
2396     if (!mask)
2397         return;
2398     if (mask & CommandListThreads) {
2399         postExtensionCommand("threads", QByteArray(), 0, &CdbEngine::handleThreads, mask & ~CommandListThreads);
2400         return;
2401     }
2402     if (mask & CommandListStack) {
2403         postExtensionCommand("stack", QByteArray(), 0, &CdbEngine::handleStackTrace, mask & ~CommandListStack);
2404         return;
2405     }
2406     if (mask & CommandListRegisters) {
2407         QTC_ASSERT(threadsHandler()->currentThread() >= 0,  return; )
2408         postExtensionCommand("registers", QByteArray(), 0, &CdbEngine::handleRegisters, mask & ~CommandListRegisters);
2409         return;
2410     }
2411     if (mask & CommandListModules) {
2412         postExtensionCommand("modules", QByteArray(), 0, &CdbEngine::handleModules, mask & ~CommandListModules);
2413         return;
2414     }
2415     if (mask & CommandListBreakPoints) {
2416         postExtensionCommand("breakpoints", QByteArray("-v"), 0,
2417                              &CdbEngine::handleBreakPoints, mask & ~CommandListBreakPoints);
2418         return;
2419     }
2420 }
2421
2422 void CdbEngine::handleWidgetAt(const CdbExtensionCommandPtr &reply)
2423 {
2424     bool success = false;
2425     QString message;
2426     do {
2427         if (!reply->success) {
2428             message = QString::fromAscii(reply->errorMessage);
2429             break;
2430         }
2431         // Should be "namespace::QWidget:0x555"
2432         QString watchExp = QString::fromAscii(reply->reply);
2433         const int sepPos = watchExp.lastIndexOf(QLatin1Char(':'));
2434         if (sepPos == -1) {
2435             message = QString::fromAscii("Invalid output: %1").arg(watchExp);
2436             break;
2437         }
2438         // 0x000 -> nothing found
2439         if (!watchExp.mid(sepPos + 1).toULongLong(0, 0)) {
2440             message = QString::fromAscii("No widget could be found at %1, %2.").arg(m_watchPointX).arg(m_watchPointY);
2441             break;
2442         }
2443         // Turn into watch expression: "*(namespace::QWidget*)0x555"
2444         watchExp.replace(sepPos, 1, QLatin1String("*)"));
2445         watchExp.insert(0, QLatin1String("*("));
2446         watchHandler()->watchExpression(watchExp);
2447         success = true;
2448     } while (false);
2449     if (!success)
2450         showMessage(message, LogWarning);
2451     m_watchPointX = m_watchPointY = 0;
2452 }
2453
2454 static inline void formatCdbBreakPointResponse(BreakpointId id, const BreakpointResponse &r,
2455                                                   QTextStream &str)
2456 {
2457     str << "Obtained breakpoint " << id << " (#" << r.number << ')';
2458     if (r.pending) {
2459         str << ", pending";
2460     } else {
2461         str.setIntegerBase(16);
2462         str << ", at 0x" << r.address;
2463         str.setIntegerBase(10);
2464     }
2465     if (!r.enabled)
2466         str << ", disabled";
2467     if (!r.module.isEmpty())
2468         str << ", module: '" << r.module << '\'';
2469     str << '\n';
2470 }
2471
2472 void CdbEngine::handleBreakPoints(const CdbExtensionCommandPtr &reply)
2473 {
2474     if (debugBreakpoints)
2475         qDebug("CdbEngine::handleBreakPoints: sucess=%d: %s", reply->success, reply->reply.constData());
2476     if (!reply->success) {
2477         showMessage(QString::fromAscii(reply->errorMessage), LogError);
2478         return;
2479     }
2480     GdbMi value;
2481     value.fromString(reply->reply);
2482     if (value.type() != GdbMi::List) {
2483         showMessage(QString::fromAscii("Unabled to parse breakpoints reply"), LogError);
2484         return;
2485     }
2486     handleBreakPoints(value);
2487 }
2488
2489 void CdbEngine::handleBreakPoints(const GdbMi &value)
2490 {
2491     // Report all obtained parameters back. Note that not all parameters are reported
2492     // back, so, match by id and complete
2493     if (debugBreakpoints)
2494         qDebug("\nCdbEngine::handleBreakPoints with %d", value.childCount());
2495     QString message;
2496     QTextStream str(&message);
2497     BreakHandler *handler = breakHandler();
2498     foreach (const GdbMi &breakPointG, value.children()) {
2499         BreakpointResponse reportedResponse;
2500         const BreakpointId id = parseBreakPoint(breakPointG, &reportedResponse);
2501         if (debugBreakpoints)
2502             qDebug("  Parsed %llu: pending=%d %s\n", id, reportedResponse.pending,
2503                    qPrintable(reportedResponse.toString()));
2504
2505         if (!reportedResponse.pending) {
2506             const PendingBreakPointMap::iterator it = m_pendingBreakpointMap.find(id);
2507             if (it != m_pendingBreakpointMap.end()) {
2508                 // Complete the response and set on handler.
2509                 BreakpointResponse &currentResponse = it.value();
2510                 currentResponse.number = reportedResponse.number;
2511                 currentResponse.address = reportedResponse.address;
2512                 currentResponse.module = reportedResponse.module;
2513                 currentResponse.pending = reportedResponse.pending;
2514                 currentResponse.enabled = reportedResponse.enabled;
2515                 formatCdbBreakPointResponse(id, currentResponse, str);
2516                 handler->setResponse(id, currentResponse);
2517                 m_pendingBreakpointMap.erase(it);
2518             }
2519         } // not pending reported
2520     } // foreach
2521     if (m_pendingBreakpointMap.empty()) {
2522         str << QLatin1String("All breakpoints have been resolved.\n");
2523     } else {
2524         str << QString::fromLatin1("%1 breakpoint(s) pending...\n").arg(m_pendingBreakpointMap.size());
2525     }
2526     showMessage(message, LogMisc);
2527 }
2528
2529 void CdbEngine::watchPoint(const QPoint &p)
2530 {
2531     m_watchPointX = p.x();
2532     m_watchPointY = p.y();
2533     switch (state()) {
2534     case InferiorStopOk:
2535         postWidgetAtCommand();
2536         break;
2537     case InferiorRunOk:
2538         // "Select Widget to Watch" from a running application is currently not
2539         // supported. It could be implemented via SpecialStopGetWidgetAt-mode,
2540         // but requires some work as not to confuse the engine by state-change notifications
2541         // emitted by the debuggee function call.
2542         showMessage(tr("\"Select Widget to Watch\": Please stop the application first."), LogWarning);
2543         break;
2544     default:
2545         showMessage(tr("\"Select Widget to Watch\": Not supported in state '%1'.").
2546                     arg(QString::fromAscii(stateName(state()))), LogWarning);
2547         break;
2548     }
2549 }
2550
2551 void CdbEngine::postWidgetAtCommand()
2552 {
2553     QByteArray arguments = QByteArray::number(m_watchPointX);
2554     arguments.append(' ');
2555     arguments.append(QByteArray::number(m_watchPointY));
2556     postExtensionCommand("widgetat", arguments, 0, &CdbEngine::handleWidgetAt, 0);
2557 }
2558
2559 } // namespace Internal
2560 } // namespace Debugger