OSDN Git Service

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