OSDN Git Service

6b6ddd6ffb6762c8ad60d4e4684356286d83117d
[qt-creator-jp/qt-creator-jp.git] / src / plugins / debugger / gdb / trkgdbadapter.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 "trkgdbadapter.h"
35
36 #include "debuggerstartparameters.h"
37 #include "gdbmi.h"
38 #include "launcher.h"
39 #include "symbiandevicemanager.h"
40 #include "s60debuggerbluetoothstarter.h"
41 #include "bluetoothlistener_gui.h"
42
43 #include "registerhandler.h"
44 #include "threadshandler.h"
45 #include "debuggeractions.h"
46 #include "debuggercore.h"
47 #include "debuggerstringutils.h"
48 #include "watchutils.h"
49 #ifndef STANDALONE_RUNNER
50 #include "gdbengine.h"
51 #endif
52
53 #include <utils/qtcassert.h>
54 #include <utils/qtcprocess.h>
55 #include <utils/savedaction.h>
56
57 #include <QtCore/QTimer>
58 #include <QtCore/QDir>
59 #include <QtNetwork/QTcpServer>
60 #include <QtNetwork/QTcpSocket>
61
62 #ifdef Q_OS_WIN
63 #  include "dbgwinutils.h"
64 #else
65 #  include <sys/types.h>
66 #  include <unistd.h>
67 #endif
68
69 #define CB(callback) \
70     static_cast<GdbEngine::AdapterCallback>(&TrkGdbAdapter::callback), \
71     STRINGIFY(callback)
72
73 #define TrkCB(s) TrkCallback(this, &TrkGdbAdapter::s)
74
75 using namespace trk;
76
77 namespace Debugger {
78 namespace Internal {
79 using namespace Symbian;
80
81 static inline void appendByte(QByteArray *ba, trk::byte b) { ba->append(b); }
82
83 ///////////////////////////////////////////////////////////////////////////
84 //
85 // TrkGdbAdapter
86 //
87 ///////////////////////////////////////////////////////////////////////////
88
89 /* Thread handling:
90  * TRK does not report thread creation/termination. So, if we receive
91  * a stop in a different thread, we store an additional thread in snapshot.
92  * When continuing in trkContinueAll(), we delete this thread, since we cannot
93  * know whether it will exist at the next stop.
94  * Also note that threads continue running in Symbian even if one crashes.
95  * TODO: Stop all threads once one stops? */
96
97 TrkGdbAdapter::TrkGdbAdapter(GdbEngine *engine) :
98     AbstractGdbAdapter(engine),
99     m_running(false),
100     m_gdbAckMode(true),
101     m_verbose(0)
102 {
103     m_bufferedMemoryRead = true;
104     // Disable buffering if gdb's dcache is used.
105     m_bufferedMemoryRead = false;
106
107     m_gdbServer = 0;
108     m_gdbConnection = 0;
109     m_snapshot.reset();
110 #ifdef Q_OS_WIN
111     const unsigned long portOffset = winGetCurrentProcessId() % 100;
112 #else
113     const uid_t portOffset = getuid();
114 #endif
115     m_gdbServerName = _("127.0.0.1:%1").arg(2222 + portOffset);
116
117     setVerbose(debuggerCore()->boolSetting(VerboseLog));
118
119     connect(debuggerCore()->action(VerboseLog), SIGNAL(valueChanged(QVariant)),
120         this, SLOT(setVerbose(QVariant)));
121 }
122
123 TrkGdbAdapter::~TrkGdbAdapter()
124 {
125     cleanup();
126     logMessage("Shutting down.\n");
127 }
128
129 void TrkGdbAdapter::setVerbose(const QVariant &value)
130 {
131     setVerbose(value.toInt());
132 }
133
134 void TrkGdbAdapter::setVerbose(int verbose)
135 {
136     m_verbose = verbose;
137     if (!m_trkDevice.isNull())
138         m_trkDevice->setVerbose(m_verbose);
139 }
140
141 void TrkGdbAdapter::trkLogMessage(const QString &msg)
142 {
143     logMessage("TRK " + msg);
144 }
145
146 void TrkGdbAdapter::setGdbServerName(const QString &name)
147 {
148     m_gdbServerName = name;
149 }
150
151 QString TrkGdbAdapter::gdbServerIP() const
152 {
153     int pos = m_gdbServerName.indexOf(':');
154     if (pos == -1)
155         return m_gdbServerName;
156     return m_gdbServerName.left(pos);
157 }
158
159 uint TrkGdbAdapter::gdbServerPort() const
160 {
161     int pos = m_gdbServerName.indexOf(':');
162     if (pos == -1)
163         return 0;
164     return m_gdbServerName.mid(pos + 1).toUInt();
165 }
166
167 QByteArray TrkGdbAdapter::trkContinueMessage(uint threadId)
168 {
169     QByteArray ba;
170     appendInt(&ba, m_session.pid);
171     appendInt(&ba, threadId);
172     return ba;
173 }
174
175 QByteArray TrkGdbAdapter::trkWriteRegisterMessage(trk::byte reg, uint value)
176 {
177     QByteArray ba;
178     appendByte(&ba, 0); // ?
179     appendShort(&ba, reg);
180     appendShort(&ba, reg);
181     appendInt(&ba, m_session.pid);
182     appendInt(&ba, m_session.tid);
183     appendInt(&ba, value);
184     return ba;
185 }
186
187 QByteArray TrkGdbAdapter::trkReadMemoryMessage(const MemoryRange &range)
188 {
189     return trk::Launcher::readMemoryMessage(m_session.pid, m_session.tid, range.from, range.size());
190 }
191
192 QByteArray TrkGdbAdapter::trkWriteMemoryMessage(uint addr, const QByteArray &data)
193 {
194     QByteArray ba;
195     ba.reserve(11 + data.size());
196     appendByte(&ba, 0x08); // Options, FIXME: why?
197     appendShort(&ba, data.size());
198     appendInt(&ba, addr);
199     appendInt(&ba, m_session.pid);
200     appendInt(&ba, m_session.tid);
201     ba.append(data);
202     return ba;
203 }
204
205 QByteArray TrkGdbAdapter::trkStepRangeMessage()
206 {
207     //qDebug() << "STEP ON " << hexxNumber(m_snapshot.registers[RegisterPC]);
208     uint from = m_snapshot.lineFromAddress;
209     uint to = m_snapshot.lineToAddress;
210     const uint pc = m_snapshot.registerValue(m_session.tid, RegisterPC);
211     trk::byte option = 0x01; // Step into.
212     if (m_snapshot.stepOver)
213         option = 0x11;  // Step over.
214     if (from <= pc && pc <= to) {
215         //to = qMax(to - 4, from);
216         //to = qMax(to - 4, from);
217         showMessage(_("STEP IN ") + hexxNumber(from) + ' ' + hexxNumber(to)
218             + _(" INSTEAD OF ") + hexxNumber(pc));
219     } else {
220         from = pc;
221         to = pc;
222     }
223     logMessage(QString::fromLatin1("Stepping from 0x%1 to 0x%2 (current PC=0x%3), option 0x%4").
224                arg(from, 0, 16).arg(to, 0, 16).arg(pc).arg(option, 0, 16));
225     QByteArray ba;
226     ba.reserve(17);
227     appendByte(&ba, option);
228     appendInt(&ba, from); // Start address
229     appendInt(&ba, to); // End address
230     appendInt(&ba, m_session.pid);
231     appendInt(&ba, m_session.tid);
232     return ba;
233 }
234
235 QByteArray TrkGdbAdapter::trkDeleteProcessMessage()
236 {
237     QByteArray ba;
238     ba.reserve(6);
239     appendByte(&ba, 0); // ?
240     appendByte(&ba, 0); // Sub-command: Delete Process
241     appendInt(&ba, m_session.pid);
242     return ba;
243 }
244
245 QByteArray TrkGdbAdapter::trkInterruptMessage()
246 {
247     QByteArray ba;
248     ba.reserve(9);
249     // Stop the thread (2) or the process (1) or the whole system (0).
250     // We choose 2, as 1 does not seem to work.
251     appendByte(&ba, 2);
252     appendInt(&ba, m_session.pid);
253     appendInt(&ba, m_session.mainTid); // threadID: 4 bytes Variable number of bytes.
254     return ba;
255 }
256
257 void TrkGdbAdapter::emitDelayedInferiorSetupFailed(const QString &msg)
258 {
259     m_adapterFailMessage = msg;
260     QTimer::singleShot(0, this, SLOT(slotEmitDelayedInferiorSetupFailed()));
261 }
262
263 void TrkGdbAdapter::slotEmitDelayedInferiorSetupFailed()
264 {
265     m_engine->notifyInferiorSetupFailed(m_adapterFailMessage);
266 }
267
268
269 void TrkGdbAdapter::logMessage(const QString &msg, int logChannel)
270 {
271     if (m_verbose || logChannel != LogDebug)
272         showMessage("TRK LOG: " + msg, logChannel);
273     MEMORY_DEBUG("GDB: " << msg);
274 }
275
276 //
277 // Gdb
278 //
279 void TrkGdbAdapter::handleGdbConnection()
280 {
281     logMessage("HANDLING GDB CONNECTION");
282     QTC_ASSERT(m_gdbConnection == 0, /**/);
283     m_gdbConnection = m_gdbServer->nextPendingConnection();
284     QTC_ASSERT(m_gdbConnection, return);
285     connect(m_gdbConnection, SIGNAL(disconnected()),
286             m_gdbConnection, SLOT(deleteLater()));
287     connect(m_gdbConnection, SIGNAL(readyRead()),
288             this, SLOT(readGdbServerCommand()));
289 }
290
291 static inline QString msgGdbPacket(const QString &p)
292 {
293     return QLatin1String("gdb:                              ") + p;
294 }
295
296 void TrkGdbAdapter::readGdbServerCommand()
297 {
298     QTC_ASSERT(m_gdbConnection, return);
299     QByteArray packet = m_gdbConnection->readAll();
300     m_gdbReadBuffer.append(packet);
301
302     logMessage("gdb: -> " + currentTime() + ' ' + QString::fromAscii(packet));
303     if (packet != m_gdbReadBuffer)
304         logMessage(QLatin1String("buffer: ") + m_gdbReadBuffer);
305
306     QByteArray &ba = m_gdbReadBuffer;
307     while (ba.size()) {
308         char code = ba.at(0);
309         ba = ba.mid(1);
310
311         if (code == '+') {
312             //logMessage("ACK");
313             continue;
314         }
315
316         if (code == '-') {
317             logMessage("NAK: Retransmission requested", LogError);
318             // This seems too harsh.
319             //emit adapterCrashed("Communication problem encountered.");
320             continue;
321         }
322
323         if (code == char(0x03)) {
324             logMessage("INTERRUPT RECEIVED");
325             interruptInferior();
326             continue;
327         }
328
329         if (code != '$') {
330             logMessage("Broken package (2) " + quoteUnprintableLatin1(ba)
331                 + hexNumber(code), LogError);
332             continue;
333         }
334
335         int pos = ba.indexOf('#');
336         if (pos == -1) {
337             logMessage("Invalid checksum format in "
338                 + quoteUnprintableLatin1(ba), LogError);
339             continue;
340         }
341
342         bool ok = false;
343         uint checkSum = ba.mid(pos + 1, 2).toUInt(&ok, 16);
344         if (!ok) {
345             logMessage("Invalid checksum format 2 in "
346                 + quoteUnprintableLatin1(ba), LogError);
347             return;
348         }
349
350         //logMessage(QString("Packet checksum: %1").arg(checkSum));
351         trk::byte sum = 0;
352         for (int i = 0; i < pos; ++i)
353             sum += ba.at(i);
354
355         if (sum != checkSum) {
356             logMessage(QString("ERROR: Packet checksum wrong: %1 %2 in "
357                 + quoteUnprintableLatin1(ba)).arg(checkSum).arg(sum), LogError);
358         }
359
360         QByteArray cmd = ba.left(pos);
361         ba.remove(0, pos + 3);
362         handleGdbServerCommand(cmd);
363     }
364 }
365
366 bool TrkGdbAdapter::sendGdbServerPacket(const QByteArray &packet, bool doFlush)
367 {
368     if (!m_gdbConnection) {
369         logMessage(_("Cannot write to gdb: No connection (%1)")
370             .arg(_(packet)), LogError);
371         return false;
372     }
373     if (m_gdbConnection->state() != QAbstractSocket::ConnectedState) {
374         logMessage(_("Cannot write to gdb: Not connected (%1)")
375             .arg(_(packet)), LogError);
376         return false;
377     }
378     if (m_gdbConnection->write(packet) == -1) {
379         logMessage(_("Cannot write to gdb: %1 (%2)")
380             .arg(m_gdbConnection->errorString()).arg(_(packet)), LogError);
381         return false;
382     }
383     if (doFlush)
384         m_gdbConnection->flush();
385     return true;
386 }
387
388 void TrkGdbAdapter::sendGdbServerAck()
389 {
390     if (!m_gdbAckMode)
391         return;
392     logMessage("gdb: <- +");
393     sendGdbServerPacket(QByteArray(1, '+'), false);
394 }
395
396 void TrkGdbAdapter::sendGdbServerMessage(const QByteArray &msg, const QByteArray &logNote)
397 {
398     trk::byte sum = 0;
399     for (int i = 0; i != msg.size(); ++i)
400         sum += msg.at(i);
401
402     char checkSum[30];
403     qsnprintf(checkSum, sizeof(checkSum) - 1, "%02x ", sum);
404
405     //logMessage(QString("Packet checksum: %1").arg(sum));
406
407     QByteArray packet;
408     packet.append('$');
409     packet.append(msg);
410     packet.append('#');
411     packet.append(checkSum);
412     int pad = qMax(0, 24 - packet.size());
413     logMessage("gdb: <- " + currentTime() + ' ' + packet + QByteArray(pad, ' ') + logNote);
414     sendGdbServerPacket(packet, true);
415 }
416
417 void TrkGdbAdapter::sendGdbServerMessageAfterTrkResponse(const QByteArray &msg,
418     const QByteArray &logNote)
419 {
420     QByteArray ba = msg + char(1) + logNote;
421     sendTrkMessage(TRK_WRITE_QUEUE_NOOP_CODE, TrkCB(reportToGdb), "", ba); // Answer gdb
422 }
423
424 void TrkGdbAdapter::reportToGdb(const TrkResult &result)
425 {
426     QByteArray message = result.cookie.toByteArray();
427     QByteArray note;
428     int pos = message.lastIndexOf(char(1)); // HACK
429     if (pos != -1) {
430         note = message.mid(pos + 1);
431         message = message.left(pos);
432     }
433     message.replace("@CODESEG@", hexNumber(m_session.codeseg));
434     message.replace("@DATASEG@", hexNumber(m_session.dataseg));
435     message.replace("@PID@", hexNumber(m_session.pid));
436     message.replace("@TID@", hexNumber(m_session.tid));
437     sendGdbServerMessage(message, note);
438 }
439
440 QByteArray TrkGdbAdapter::trkBreakpointMessage(uint addr, uint len, bool armMode)
441 {
442     QByteArray ba;
443     appendByte(&ba, 0x82);  // unused option
444     appendByte(&ba, armMode /*bp.mode == ArmMode*/ ? 0x00 : 0x01);
445     appendInt(&ba, addr);
446     appendInt(&ba, len);
447     appendInt(&ba, 0x00000001);
448     appendInt(&ba, m_session.pid);
449     appendInt(&ba, 0xFFFFFFFF);
450     return ba;
451 }
452
453 static QByteArray msgStepRangeReceived(unsigned from, unsigned to, bool over)
454 {
455     QByteArray rc = "Stepping range received for step ";
456     rc += over ? "over" : "into";
457     rc += " (0x";
458     rc += QByteArray::number(from, 16);
459     rc += " to 0x";
460     rc += QByteArray::number(to, 16);
461     rc += ')';
462     return rc;
463 }
464
465 void TrkGdbAdapter::handleGdbServerCommand(const QByteArray &cmd)
466 {
467     // http://sourceware.org/gdb/current/onlinedocs/gdb_34.html
468     if (0) {}
469
470     else if (cmd == "!") {
471         sendGdbServerAck();
472         //sendGdbServerMessage("", "extended mode not enabled");
473         sendGdbServerMessage("OK", "extended mode enabled");
474     }
475
476     else if (cmd.startsWith('?')) {
477         logMessage(msgGdbPacket(QLatin1String("Query halted")));
478         // Indicate the reason the target halted.
479         // The reply is the same as for step and continue.
480         sendGdbServerAck();
481         // The command below will trigger fetching a stack trace while
482         // the process does not seem to be fully functional. Most notably
483         // the PC points to a 0x9..., which is not in "our" range
484         //sendGdbServerMessage("T05library:r;", "target halted (library load)");
485         //sendGdbServerMessage("S05", "target halted (trap)");
486         sendGdbServerMessage("S00", "target halted (trap)");
487         //sendGdbServerMessage("O" + QByteArray("Starting...").toHex());
488     }
489
490     else if (cmd == "c") {
491         logMessage(msgGdbPacket(QLatin1String("Continue")));
492         sendGdbServerAck();
493         m_running = true;
494         trkContinueAll("gdb 'c'");
495     }
496
497     else if (cmd.startsWith('C')) {
498         logMessage(msgGdbPacket(QLatin1String("Continue with signal")));
499         // C sig[;addr] Continue with signal sig (hex signal number)
500         //Reply: See section D.3 Stop Reply Packets, for the reply specifications.
501         //TODO: Meaning of the message is not clear.
502         sendGdbServerAck();
503         bool ok = false;
504         const uint signalNumber = cmd.mid(1).toUInt(&ok, 16);
505         logMessage(_("Not implemented 'Continue with signal' %1: ")
506             .arg(signalNumber), LogWarning);
507         sendGdbServerMessage('O' + QByteArray("Console output").toHex());
508         sendGdbServerMessage("W81"); // "Process exited with result 1
509         trkContinueAll("gdb 'C'");
510     }
511
512     else if (cmd.startsWith('D')) {
513         sendGdbServerAck();
514         sendGdbServerMessage("OK", "shutting down");
515     }
516
517     else if (cmd == "g") {
518         // Read general registers.
519         if (m_snapshot.registersValid(m_session.tid)) {
520             //qDebug() << "Using cached register contents";
521             logMessage(msgGdbPacket(QLatin1String("Read registers")));
522             sendGdbServerAck();
523             reportRegisters();
524         } else {
525             //qDebug() << "Fetching register contents";
526             sendGdbServerAck();
527             sendTrkMessage(0x12,
528                 TrkCB(handleAndReportReadRegisters),
529                 Launcher::readRegistersMessage(m_session.pid, m_session.tid));
530         }
531     }
532
533     else if (cmd == "gg") {
534         // Force re-reading general registers for debugging purpose.
535         sendGdbServerAck();
536         m_snapshot.setRegistersValid(m_session.tid, false);
537         sendTrkMessage(0x12,
538             TrkCB(handleAndReportReadRegisters),
539             Launcher::readRegistersMessage(m_session.pid, m_session.tid));
540     }
541
542     else if (cmd.startsWith("salstep,")) {
543         // Receive address range for current line for future use when stepping.
544         sendGdbServerAck();
545         m_snapshot.parseGdbStepRange(cmd, false);
546         sendGdbServerMessage("", msgStepRangeReceived(m_snapshot.lineFromAddress, m_snapshot.lineToAddress, m_snapshot.stepOver));
547     }
548
549     else if (cmd.startsWith("salnext,")) {
550         // Receive address range for current line for future use when stepping.
551         sendGdbServerAck();
552         m_snapshot.parseGdbStepRange(cmd, true);
553         sendGdbServerMessage("", msgStepRangeReceived(m_snapshot.lineFromAddress, m_snapshot.lineToAddress, m_snapshot.stepOver));
554     }
555
556     else if (cmd.startsWith("Hc")) {
557         sendGdbServerAck();
558         gdbSetCurrentThread(cmd, "Set current thread for step & continue ");
559     }
560
561     else if (cmd.startsWith("Hg")) {
562         sendGdbServerAck();
563         gdbSetCurrentThread(cmd, "Set current thread ");
564     }
565
566     else if (cmd == "k" || cmd.startsWith("vKill")) {
567         trkKill();
568     }
569
570     else if (cmd.startsWith('m')) {
571         logMessage(msgGdbPacket(QLatin1String("Read memory")));
572         // m addr,length
573         sendGdbServerAck();
574         const QPair<quint64, unsigned> addrLength = parseGdbReadMemoryRequest(cmd);
575         if (addrLength.second) {
576             readMemory(addrLength.first, addrLength.second, m_bufferedMemoryRead);
577         } else {
578             sendGdbServerMessage("E20", "Error " + cmd);
579         }
580     }
581
582     else if (cmd.startsWith('p')) {
583         logMessage(msgGdbPacket(QLatin1String("read register")));
584         // 0xf == current instruction pointer?
585         //sendGdbServerMessage("0000", "current IP");
586         sendGdbServerAck();
587         bool ok = false;
588         const uint registerNumber = cmd.mid(1).toUInt(&ok, 16);
589         const int threadIndex = m_snapshot.indexOfThread(m_session.tid);
590         QTC_ASSERT(threadIndex != -1, return)
591         const Symbian::Thread &thread =  m_snapshot.threadInfo[threadIndex];
592         if (thread.registerValid) {
593             sendGdbServerMessage(thread.gdbReportSingleRegister(registerNumber), thread.gdbSingleRegisterLogMessage(registerNumber));
594         } else {
595             //qDebug() << "Fetching single register";
596             sendTrkMessage(0x12,
597                 TrkCB(handleAndReportReadRegister),
598                 Launcher::readRegistersMessage(m_session.pid, m_session.tid), registerNumber);
599         }
600     }
601
602     else if (cmd.startsWith('P')) {
603         logMessage(msgGdbPacket(QLatin1String("write register")));
604         // $Pe=70f96678#d3
605         sendGdbServerAck();
606         const QPair<uint, uint> regnumValue = parseGdbWriteRegisterWriteRequest(cmd);
607         // FIXME: Assume all goes well.
608         m_snapshot.setRegisterValue(m_session.tid, regnumValue.first, regnumValue.second);
609         QByteArray ba = trkWriteRegisterMessage(regnumValue.first, regnumValue.second);
610         sendTrkMessage(0x13, TrkCB(handleWriteRegister), ba, "Write register");
611         // Note that App TRK refuses to write registers 13 and 14
612     }
613
614     else if (cmd == "qAttached") {
615         //$qAttached#8f
616         // 1: attached to an existing process
617         // 0: created a new process
618         sendGdbServerAck();
619         sendGdbServerMessage(QByteArray(1, '0'), "new process created");
620         //sendGdbServerMessage('1', "attached to existing process");
621         //sendGdbServerMessage("E01", "new process created");
622     }
623
624     else if (cmd.startsWith("qC")) {
625         logMessage(msgGdbPacket(QLatin1String("query thread id")));
626         // Return the current thread ID
627         //$qC#b4
628         sendGdbServerAck();
629         sendGdbServerMessageAfterTrkResponse("QC@TID@");
630     }
631
632     else if (cmd.startsWith("qSupported")) {
633         //$qSupported#37
634         //$qSupported:multiprocess+#c6
635         //logMessage("Handling 'qSupported'");
636         sendGdbServerAck();
637         sendGdbServerMessage(Symbian::gdbQSupported);
638     }
639
640     // Tracepoint handling as of gdb 7.2 onwards
641     else if (cmd == "qTStatus") { // Tracepoints
642         sendGdbServerAck();
643         sendGdbServerMessage("T0;tnotrun:0", QByteArray("No trace experiment running"));
644     }
645     // Trace variables  as of gdb 7.2 onwards
646     else if (cmd == "qTfV" || cmd == "qTsP" || cmd == "qTfP") {
647         sendGdbServerAck();
648         sendGdbServerMessage("l", QByteArray("No trace points"));
649     }
650
651     else if (cmd.startsWith("qThreadExtraInfo")) {
652         // $qThreadExtraInfo,1f9#55
653         sendGdbServerAck();
654         sendGdbServerMessage(m_snapshot.gdbQThreadExtraInfo(cmd));
655     }
656
657     else if (cmd == "qfDllInfo") {
658         // That's the _first_ query package.
659         // Happens with  gdb 6.4.50.20060226-cvs / CodeSourcery.
660         // Never made it into FSF gdb that got qXfer:libraries:read instead.
661         // http://sourceware.org/ml/gdb/2007-05/msg00038.html
662         // Name=hexname,TextSeg=textaddr[,DataSeg=dataaddr]
663         sendGdbServerAck();
664         sendGdbServerMessage(m_session.gdbQsDllInfo(), "library information transferred");
665     }
666
667     else if (cmd == "qsDllInfo") {
668         // That's a following query package
669         sendGdbServerAck();
670         sendGdbServerMessage(QByteArray(1, 'l'), "library information transfer finished");
671     }
672
673     else if (cmd == "qPacketInfo") {
674         // happens with  gdb 6.4.50.20060226-cvs / CodeSourcery
675         // deprecated by qSupported?
676         sendGdbServerAck();
677         sendGdbServerMessage("", "FIXME: nothing?");
678     }
679
680     else if (cmd == "qOffsets") {
681         sendGdbServerAck();
682         sendGdbServerMessageAfterTrkResponse("TextSeg=@CODESEG@;DataSeg=@DATASEG@");
683     }
684
685     else if (cmd == "qSymbol::") {
686         if (m_verbose)
687             logMessage(msgGdbPacket(QLatin1String("notify can handle symbol lookup")));
688         // Notify the target that GDB is prepared to serve symbol lookup requests.
689         sendGdbServerAck();
690         if (1)
691             sendGdbServerMessage("OK", "no further symbols needed");
692         else
693             sendGdbServerMessage("qSymbol:" + QByteArray("_Z7E32Mainv").toHex(),
694                 "ask for more");
695     }
696
697     else if (cmd.startsWith("qXfer:features:read:target.xml:")) {
698         //  $qXfer:features:read:target.xml:0,7ca#46...Ack
699         sendGdbServerAck();
700         sendGdbServerMessage(Symbian::gdbArchitectureXml);
701     }
702
703     else if (cmd == "qfThreadInfo") {
704         // That's the _first_ query package.
705         sendGdbServerAck();
706         sendGdbServerMessage(m_snapshot.gdbQsThreadInfo(), "thread information transferred");
707     }
708
709     else if (cmd == "qsThreadInfo") {
710         // That's a following query package
711         sendGdbServerAck();
712         sendGdbServerMessage(QByteArray(1, 'l'), "thread information transfer finished");
713     }
714
715     else if (cmd.startsWith("qXfer:libraries:read")) {
716         sendGdbServerAck();
717         sendGdbServerMessage(m_session.gdbLibraryList(), "library information transferred");
718     }
719
720     else if (cmd == "QStartNoAckMode") {
721         //$qSupported#37
722         logMessage("Handling 'QStartNoAckMode'");
723         sendGdbServerAck();
724         sendGdbServerMessage("OK", "ack no-ack mode");
725         m_gdbAckMode = false;
726     }
727
728     else if (cmd.startsWith("QPassSignals")) {
729         // list of signals to pass directly to inferior
730         // $QPassSignals:e;10;14;17;1a;1b;1c;21;24;25;4c;#8f
731         // happens only if "QPassSignals+;" is qSupported
732         sendGdbServerAck();
733         // FIXME: use the parameters
734         sendGdbServerMessage("OK", "passing signals accepted");
735     }
736
737     else if (cmd == "s" || cmd.startsWith("vCont;s")) {
738         const uint pc = m_snapshot.registerValue(m_session.tid, RegisterPC);
739         logMessage(msgGdbPacket(QString::fromLatin1("Step range from 0x%1").
740                                 arg(pc, 0, 16)));
741         sendGdbServerAck();
742         //m_snapshot.reset();
743         m_running = true;
744         QByteArray ba = trkStepRangeMessage();
745         sendTrkMessage(0x19, TrkCB(handleStep), ba, "Step range");
746     }
747
748     else if (cmd.startsWith('T')) {
749         // FIXME: check whether thread is alive
750         sendGdbServerAck();
751         sendGdbServerMessage("OK"); // pretend all is well
752         //sendGdbServerMessage("E nn");
753     }
754
755     else if (cmd == "vCont?") {
756         // actions supported by the vCont packet
757         sendGdbServerAck();
758         //sendGdbServerMessage("OK"); // we don't support vCont.
759         sendGdbServerMessage("vCont;c;C;s;S");
760     }
761
762     else if (cmd == "vCont;c") {
763         // vCont[;action[:thread-id]]...'
764         sendGdbServerAck();
765         //m_snapshot.reset();
766         m_running = true;
767         trkContinueAll("gdb 'vCont;c'");
768     }
769
770     else if (cmd.startsWith("Z0,") || cmd.startsWith("Z1,")) {
771         // Insert breakpoint
772         sendGdbServerAck();
773         logMessage(msgGdbPacket(QLatin1String("Insert breakpoint")));
774         // $Z0,786a4ccc,4#99
775         const QPair<quint64, unsigned> addrLen = parseGdbSetBreakpointRequest(cmd);
776         if (addrLen.first) {
777             //qDebug() << "ADDR: " << hexNumber(addr) << " LEN: " << len;
778             logMessage(_("Inserting breakpoint at 0x%1, %2")
779                 .arg(addrLen.first, 0, 16).arg(addrLen.second));
780             const bool armMode = addrLen.second == 4;
781             const QByteArray ba = trkBreakpointMessage(addrLen.first, addrLen.second, armMode);
782             sendTrkMessage(0x1B, TrkCB(handleAndReportSetBreakpoint), ba, QVariant(addrLen.first));
783         } else {
784             logMessage(QLatin1String("MISPARSED BREAKPOINT '") + cmd + "')", LogError);
785         }
786     }
787
788     else if (cmd.startsWith("z0,") || cmd.startsWith("z1,")) {
789         // Remove breakpoint
790         sendGdbServerAck();
791         logMessage(msgGdbPacket(QLatin1String("Remove breakpoint")));
792         // $z0,786a4ccc,4#99
793         const int pos = cmd.lastIndexOf(',');
794         bool ok = false;
795         const uint addr = cmd.mid(3, pos - 3).toUInt(&ok, 16);
796         const uint len = cmd.mid(pos + 1).toUInt(&ok, 16);
797         const uint bp = m_session.addressToBP[addr];
798         if (bp == 0) {
799             logMessage(_("NO RECORDED BP AT 0x%1, %2")
800                 .arg(addr, 0, 16).arg(len), LogError);
801             sendGdbServerMessage("E00");
802         } else {
803             m_session.addressToBP.remove(addr);
804             QByteArray ba;
805             appendInt(&ba, bp);
806             sendTrkMessage(0x1C, TrkCB(handleClearBreakpoint), ba, addr);
807         }
808     }
809
810     else if (cmd.startsWith("qPart:") || cmd.startsWith("qXfer:"))  {
811         QByteArray data = cmd.mid(1 + cmd.indexOf(':'));
812         // "qPart:auxv:read::0,147": Read OS auxiliary data (see info aux)
813         bool handled = false;
814         if (data.startsWith("auxv:read::")) {
815             const int offsetPos = data.lastIndexOf(':') + 1;
816             const int commaPos = data.lastIndexOf(',');
817             if (commaPos != -1) {
818                 bool ok1 = false, ok2 = false;
819                 const int offset = data.mid(offsetPos,  commaPos - offsetPos)
820                     .toUInt(&ok1, 16);
821                 const int length = data.mid(commaPos + 1).toUInt(&ok2, 16);
822                 if (ok1 && ok2) {
823                     const QString msg = _("Read of OS auxiliary "
824                         "vector (%1, %2) not implemented.").arg(offset).arg(length);
825                     logMessage(msgGdbPacket(msg), LogWarning);
826                     sendGdbServerMessage("E20", msg.toLatin1());
827                     handled = true;
828                 }
829             }
830         } // auxv read
831
832         if (!handled) {
833             const QString msg = QLatin1String("FIXME unknown 'XFER'-request: ")
834                 + QString::fromAscii(cmd);
835             logMessage(msgGdbPacket(msg), LogWarning);
836             sendGdbServerMessage("E20", msg.toLatin1());
837         }
838     } // qPart/qXfer
839
840     else if (cmd.startsWith('X')) {
841         logMessage(msgGdbPacket(QLatin1String("Write memory")));
842         // X addr,length
843         sendGdbServerAck();
844         const QPair<quint64, unsigned> addrLength = parseGdbReadMemoryRequest(cmd);
845         int pos = cmd.indexOf(':');
846         m_snapshot.resetMemory();
847         writeMemory(addrLength.first, cmd.mid(pos + 1, addrLength.second));
848     }
849
850     else {
851         logMessage(msgGdbPacket(QLatin1String("FIXME unknown: ")
852             + QString::fromAscii(cmd)), LogWarning);
853     }
854 }
855
856 void TrkGdbAdapter::gdbSetCurrentThread(const QByteArray &cmd, const char *why)
857 {
858     // Thread ID from Hg/Hc commands: '-1': All, '0': arbitrary, else hex thread id.
859     const QByteArray id = cmd.mid(2);
860     const int threadId = id == "-1" ? -1 : id.toInt(0, 16);
861     const QByteArray message = QByteArray(why) + QByteArray::number(threadId);
862     logMessage(msgGdbPacket(QString::fromLatin1(message)));
863     // Set thread for subsequent operations (`m', `M', `g', `G', et.al.).
864     // for 'other operations.  0 - any thread
865     //$Hg0#df
866     m_session.tid = threadId <= 0 ? m_session.mainTid : uint(threadId);
867     sendGdbServerMessage("OK", message);
868 }
869
870 void TrkGdbAdapter::trkKill()
871 {
872     // Kill inferior process
873     logMessage(msgGdbPacket(QLatin1String("kill")));
874     sendTrkMessage(0x41, TrkCB(handleDeleteProcess),
875         trkDeleteProcessMessage(), "Delete process");
876 }
877
878 void TrkGdbAdapter::trkContinueAll(const char *why)
879 {
880     if (why)
881         logMessage(QString::fromLatin1("Continuing %1 threads (%2)").
882                    arg(m_snapshot.threadInfo.size()).arg(QString::fromLatin1(why)));
883
884     // Starting from the last one, continue all threads.
885     QTC_ASSERT(!m_snapshot.threadInfo.isEmpty(), return; );
886     trkContinueNext(m_snapshot.threadInfo.size() - 1);
887 }
888
889 void TrkGdbAdapter::trkContinueNext(int threadIndex)
890 {
891     const uint threadId = m_snapshot.threadInfo.at(threadIndex).id;
892     logMessage(QString::fromLatin1("Continuing thread 0x%1 of %2").
893                arg(threadId,0, 16).arg(m_snapshot.threadInfo.size()));
894     sendTrkMessage(0x18, TrkCallback(this, &TrkGdbAdapter::handleTrkContinueNext),
895                    trkContinueMessage(threadId), QVariant(threadIndex));
896 }
897
898 void TrkGdbAdapter::handleTrkContinueNext(const TrkResult &result)
899 {
900     const int index = result.cookie.toInt();
901     if (result.errorCode()) {
902         logMessage("Error continuing thread: " + result.errorString(), LogError);
903         return;
904     }
905     // Remove the thread (unless main) if it is continued since we
906     // do not get thread creation/deletion events
907     QTC_ASSERT(index < m_snapshot.threadInfo.size(), return; );
908     if (m_snapshot.threadInfo.at(index).id != m_session.mainTid)
909         m_snapshot.threadInfo.remove(index);
910     if (index > 0 && m_running) // Stopped in-between
911         trkContinueNext(index - 1);
912 }
913
914 void TrkGdbAdapter::sendTrkMessage(trk::byte code, TrkCallback callback,
915     const QByteArray &data, const QVariant &cookie)
916 {
917     if (m_verbose >= 2)
918         logMessage("trk: -> " + QByteArray::number(code, 16) + "  "
919             + stringFromArray(data));
920     m_trkDevice->sendTrkMessage(code, callback, data, cookie);
921 }
922
923 void TrkGdbAdapter::sendTrkAck(trk::byte token)
924 {
925     //logMessage(QString("SENDING ACKNOWLEDGEMENT FOR TOKEN %1").arg(int(token)));
926     m_trkDevice->sendTrkAck(token);
927 }
928
929 void TrkGdbAdapter::handleTrkError(const QString &msg)
930 {
931     logMessage("## TRK ERROR: " + msg, LogError);
932     m_engine->handleAdapterCrashed("TRK problem encountered:\n" + msg);
933 }
934
935 void TrkGdbAdapter::handleTrkResult(const TrkResult &result)
936 {
937     if (m_verbose >= 2)
938         logMessage("trk: <- " + result.toString());
939     if (result.isDebugOutput) {
940         // It looks like those messages _must not_ be acknowledged.
941         // If we do so, TRK will complain about wrong sequencing.
942         //sendTrkAck(result.token);
943         logMessage(QString::fromAscii(result.data), AppOutput);
944         sendGdbServerMessage('O' + result.data.toHex());
945         return;
946     }
947     //logMessage("READ TRK " + result.toString());
948     QByteArray prefix = "READ BUF:                                       ";
949     QByteArray str = result.toString().toUtf8();
950     switch (result.code) {
951         case 0x80: // ACK
952             break;
953         case 0xff: { // NAK. This mostly means transmission error, not command failed.
954             QString logMsg;
955             QTextStream(&logMsg) << prefix << "NAK: for token=" << result.token
956                 << " ERROR: " << errorMessage(result.data.at(0)) << ' ' << str;
957             logMessage(logMsg, LogError);
958             break;
959         }
960         case TrkNotifyStopped: {  // 0x90 Notified Stopped
961             // 90 01   78 6a 40 40   00 00 07 23   00 00 07 24  00 00
962             showMessage(_("RESET SNAPSHOT (NOTIFY STOPPED)"));
963             MEMORY_DEBUG("WE STOPPED");
964             m_snapshot.reset();
965             MEMORY_DEBUG("  AFTER CLEANING: " << m_snapshot.memory.size() << " BLOCKS LEFT");
966             QString reason;
967             uint addr;
968             uint pid;
969             uint tid;
970             trk::Launcher::parseNotifyStopped(result.data, &pid, &tid, &addr, &reason);
971             const QString msg = trk::Launcher::msgStopped(pid, tid, addr, reason);
972             // Unknown thread: Add.
973             m_session.tid = tid;
974             if (m_snapshot.indexOfThread(tid) == -1)
975                 m_snapshot.addThread(tid);
976             m_snapshot.setThreadState(tid, reason);
977
978             logMessage(prefix + msg);
979             showMessage(msg, LogMisc);
980             sendTrkAck(result.token);
981             if (addr) {
982                 // Todo: Do not send off GdbMessages if a synced gdb
983                 // query is pending, queue instead
984                 if (m_running) {
985                     m_running = false;
986                 }
987             } else {
988                 logMessage(QLatin1String("Ignoring stop at 0"));
989             }
990
991 #            if 1
992             // We almost always need register values, so get them
993             // now before informing gdb about the stop.s
994             const int signalNumber = reason.contains(QLatin1String("exception"), Qt::CaseInsensitive)
995                                      || reason.contains(QLatin1String("panic"), Qt::CaseInsensitive) ?
996                         gdbServerSignalSegfault : gdbServerSignalTrap;
997             sendTrkMessage(0x12,
998                 TrkCB(handleAndReportReadRegistersAfterStop),
999                 Launcher::readRegistersMessage(m_session.pid, m_session.tid), signalNumber);
1000 #            else
1001             // As a source-line step typically consists of
1002             // several instruction steps, better avoid the multiple
1003             // roundtrips through TRK in favour of an additional
1004             // roundtrip through gdb. But gdb will ask for all registers.
1005 #                if 1
1006                 sendGdbServerMessage("S05", "Target stopped");
1007 #                else
1008                 QByteArray ba = "T05";
1009                 appendRegister(&ba, RegisterPSGdb, addr);
1010                 sendGdbServerMessage(ba, "Registers");
1011 #                endif
1012 #            endif
1013             break;
1014         }
1015         case TrkNotifyException: { // 0x91 Notify Exception (obsolete)
1016             showMessage(_("RESET SNAPSHOT (NOTIFY EXCEPTION)"));
1017             m_snapshot.reset();
1018             logMessage(prefix + _("NOTE: EXCEPTION  ") + str, AppError);
1019             sendTrkAck(result.token);
1020             break;
1021         }
1022         case 0x92: { //
1023             showMessage(_("RESET SNAPSHOT (NOTIFY INTERNAL ERROR)"));
1024             m_snapshot.reset();
1025             logMessage(prefix + _("NOTE: INTERNAL ERROR: ") + str, LogError);
1026             sendTrkAck(result.token);
1027             break;
1028         }
1029
1030         // target->host OS notification
1031         case 0xa0: { // Notify Created
1032             // Sending this ACK does not seem to make a difference. Why?
1033             //sendTrkAck(result.token);
1034             m_snapshot.resetMemory();
1035             const char *data = result.data.data();
1036             const trk::byte error = result.data.at(0);
1037             // type: 1 byte; for dll item, this value is 2.
1038             const trk::byte type = result.data.at(1);
1039             const uint tid = extractInt(data + 6);
1040             const Library lib = Library(result);
1041             m_session.libraries.push_back(lib);
1042             m_session.modules += QString::fromAscii(lib.name);
1043             QString logMsg;
1044             QTextStream str(&logMsg);
1045             str << prefix << " NOTE: LIBRARY LOAD: token=" << result.token;
1046             if (error)
1047                 str << " ERROR: " << int(error);
1048             str << " TYPE: " << int(type) << " PID: " << lib.pid << " TID:   " <<  tid;
1049             str << " CODE: " << hexxNumber(lib.codeseg);
1050             str << " DATA: " << hexxNumber(lib.dataseg);
1051             str << " NAME: '" << lib.name << '\'';
1052             if (tid && tid != unsigned(-1) && m_snapshot.indexOfThread(tid) == -1)
1053                 m_snapshot.addThread(tid);
1054             logMessage(logMsg);
1055             // Load local symbol file into gdb provided there is one
1056             if (lib.codeseg) {
1057                 const QString localSymFileName = Symbian::localSymFileForLibrary(lib.name, m_symbolFileFolder);
1058                 if (!localSymFileName.isEmpty()) {
1059                     showMessage(Symbian::msgLoadLocalSymFile(localSymFileName, lib.name, lib.codeseg), LogMisc);
1060                     m_engine->postCommand(Symbian::symFileLoadCommand(localSymFileName, lib.codeseg, lib.dataseg));
1061                 } // has local sym
1062             } // code seg
1063
1064             // This lets gdb trigger a register update etc.
1065             // With CS gdb 6.4 we get a non-standard $qfDllInfo#7f+ request
1066             // afterwards, so don't use it for now.
1067             //sendGdbServerMessage("T05library:;");
1068 /*
1069             // Causes too much "stopped" (by SIGTRAP) messages that need
1070             // to be answered by "continue". Auto-continuing each SIGTRAP
1071             // is not possible as this is also the real message for a user
1072             // initiated interrupt.
1073             sendGdbServerMessage("T05load:Name=" + lib.name.toHex()
1074                 + ",TextSeg=" + hexNumber(lib.codeseg)
1075                 + ",DataSeg=" + hexNumber(lib.dataseg) + ';');
1076 */
1077
1078             // After 'continue' the very first time after starting debugging
1079             // a process some library load events are generated, these are
1080             // actually static dependencies for the process. For these libraries,
1081             // the thread id is -1 which means the debugger doesn't have
1082             // to continue. The debugger can safely assume that the
1083             // thread resumption will be handled by the agent itself.
1084             if (tid != unsigned(-1))
1085                 sendTrkMessage(0x18, TrkCallback(), trkContinueMessage(m_session.mainTid), "CONTINUE");
1086             break;
1087         }
1088         case 0xa1: { // NotifyDeleted
1089             const ushort itemType = extractByte(result.data.data() + 1);
1090             const ushort len = result.data.size() > 12
1091                 ? extractShort(result.data.data() + 10) : ushort(0);
1092             const QString name = len
1093                 ? QString::fromAscii(result.data.mid(12, len)) : QString();
1094             if (!name.isEmpty())
1095                 m_session.modules.removeAll(name);
1096             logMessage(_("%1 %2 UNLOAD: %3")
1097                 .arg(QString::fromAscii(prefix))
1098                 .arg(itemType ? QLatin1String("LIB") : QLatin1String("PROCESS"))
1099                 .arg(name));
1100             sendTrkAck(result.token);
1101             if (itemType == 0) {
1102                 sendGdbServerMessage("W00", "Process exited");
1103                 //sendTrkMessage(0x02, TrkCB(handleDisconnect));
1104             }
1105             break;
1106         }
1107         case 0xa2: { // NotifyProcessorStarted
1108             logMessage(prefix + _("NOTE: PROCESSOR STARTED: ") + str);
1109             sendTrkAck(result.token);
1110             break;
1111         }
1112         case 0xa6: { // NotifyProcessorStandby
1113             logMessage(prefix + _("NOTE: PROCESSOR STANDBY: ") + str);
1114             sendTrkAck(result.token);
1115             break;
1116         }
1117         case 0xa7: { // NotifyProcessorReset
1118             logMessage(prefix + _("NOTE: PROCESSOR RESET: ") + str);
1119             sendTrkAck(result.token);
1120             break;
1121         }
1122         default: {
1123             logMessage(prefix + _("INVALID: ") + str, LogError);
1124             break;
1125         }
1126     }
1127 }
1128
1129 void TrkGdbAdapter::handleCpuType(const TrkResult &result)
1130 {
1131     //---TRK------------------------------------------------------
1132     //  Command: 0x80 Acknowledge
1133     //    Error: 0x00
1134     // [80 03 00  04 00 00 04 00 00 00]
1135     if (result.data.size() < 7) {
1136         logMessage(_("ERROR: CPUTYPE RESULT ") + result.errorString()
1137             + _(" NOT PARSABLE"), LogError);
1138         return;
1139     }
1140     m_session.cpuMajor = result.data[1];
1141     m_session.cpuMinor = result.data[2];
1142     m_session.bigEndian = result.data[3];
1143     m_session.defaultTypeSize = result.data[4];
1144     m_session.fpTypeSize = result.data[5];
1145     m_session.extended1TypeSize = result.data[6];
1146     //m_session.extended2TypeSize = result.data[6];
1147     QString logMsg;
1148     QTextStream(&logMsg) << "HANDLE CPU TYPE: CPU=" << m_session.cpuMajor << '.'
1149         << m_session.cpuMinor << " bigEndian=" << m_session.bigEndian
1150         << " defaultTypeSize=" << m_session.defaultTypeSize
1151         << " fpTypeSize=" << m_session.fpTypeSize
1152         << " extended1TypeSize=" <<  m_session.extended1TypeSize;
1153     logMessage(logMsg);
1154 }
1155
1156 void TrkGdbAdapter::handleDeleteProcess(const TrkResult &result)
1157 {
1158     Q_UNUSED(result);
1159     logMessage("Inferior process killed");
1160     //sendTrkMessage(0x01, TrkCB(handleDeleteProcess2)); // Ping
1161     sendTrkMessage(0x02, TrkCB(handleDeleteProcess2)); // Disconnect
1162 }
1163
1164 void TrkGdbAdapter::handleDeleteProcess2(const TrkResult &result)
1165 {
1166     Q_UNUSED(result);
1167     QString msg = QString::fromLatin1("App TRK disconnected");
1168
1169     const bool emergencyShutdown = m_gdbProc.state() != QProcess::Running;
1170     if (emergencyShutdown)
1171         msg += QString::fromLatin1(" (emergency shutdown");
1172     logMessage(msg);
1173     if (emergencyShutdown) {
1174         cleanup();
1175         m_engine->notifyAdapterShutdownOk();
1176     } else {
1177         sendGdbServerAck();
1178         sendGdbServerMessage("", "process killed");
1179     }
1180 }
1181
1182 void TrkGdbAdapter::handleReadRegisters(const TrkResult &result)
1183 {
1184     logMessage("       REGISTER RESULT: " + result.toString());
1185     // [80 0B 00   00 00 00 00   C9 24 FF BC   00 00 00 00   00
1186     //  60 00 00   00 00 00 00   78 67 79 70   00 00 00 00   00...]
1187     if (result.errorCode()) {
1188         logMessage("ERROR: " + result.errorString(), LogError);
1189         return;
1190     }
1191     const char *data = result.data.data() + 1; // Skip ok byte
1192     uint *registers = m_snapshot.registers(m_session.tid);
1193     QTC_ASSERT(registers, return;)
1194     for (int i = 0; i < RegisterCount; ++i)
1195         registers[i] = extractInt(data + 4 * i);
1196     m_snapshot.setRegistersValid(m_session.tid, true);
1197 }
1198
1199 void TrkGdbAdapter::handleWriteRegister(const TrkResult &result)
1200 {
1201     logMessage("       RESULT: " + result.toString() + result.cookie.toString());
1202     if (result.errorCode()) {
1203         logMessage("ERROR: " + result.errorString(), LogError);
1204         sendGdbServerMessage("E01");
1205         return;
1206     }
1207     sendGdbServerMessage("OK");
1208 }
1209
1210 void TrkGdbAdapter::reportRegisters()
1211 {
1212     const int threadIndex = m_snapshot.indexOfThread(m_session.tid);
1213     QTC_ASSERT(threadIndex != -1, return);
1214     const Symbian::Thread &thread = m_snapshot.threadInfo.at(threadIndex);
1215     sendGdbServerMessage(thread.gdbReportRegisters(), thread.gdbRegisterLogMessage(m_verbose));
1216 }
1217
1218 void TrkGdbAdapter::handleAndReportReadRegisters(const TrkResult &result)
1219 {
1220     handleReadRegisters(result);
1221     reportRegisters();
1222 }
1223
1224 void TrkGdbAdapter::handleAndReportReadRegister(const TrkResult &result)
1225 {
1226     handleReadRegisters(result);
1227     const uint registerNumber = result.cookie.toUInt();
1228     const int threadIndex = m_snapshot.indexOfThread(m_session.tid);
1229     QTC_ASSERT(threadIndex != -1, return);
1230     const Symbian::Thread &thread = m_snapshot.threadInfo.at(threadIndex);
1231     sendGdbServerMessage(thread.gdbReportSingleRegister(registerNumber), thread.gdbSingleRegisterLogMessage(registerNumber));
1232 }
1233
1234 void TrkGdbAdapter::handleAndReportReadRegistersAfterStop(const TrkResult &result)
1235 {
1236     handleReadRegisters(result);
1237     const bool reportThread = m_session.tid != m_session.mainTid;
1238     const int signalNumber = result.cookie.isValid() ? result.cookie.toInt() : int(gdbServerSignalTrap);
1239     sendGdbServerMessage(m_snapshot.gdbStopMessage(m_session.tid, signalNumber, reportThread),
1240                          "Stopped with registers in thread " + QByteArray::number(m_session.tid, 16));
1241 }
1242
1243 static QString msgMemoryReadError(int code, uint addr, uint len = 0)
1244 {
1245     const QString lenS = len ? QString::number(len) : QLatin1String("<unknown>");
1246     return _("Memory read error %1 at: 0x%2 %3")
1247         .arg(code).arg(addr, 0, 16).arg(lenS);
1248 }
1249
1250 void TrkGdbAdapter::handleReadMemoryBuffered(const TrkResult &result)
1251 {
1252     if (extractShort(result.data.data() + 1) + 3 != result.data.size())
1253         logMessage(_("\n BAD MEMORY RESULT: ") + result.data.toHex() + '\n', LogError);
1254     const MemoryRange range = result.cookie.value<MemoryRange>();
1255     MEMORY_DEBUG("HANDLE READ MEMORY ***BUFFERED*** FOR " << range);
1256     if (const int errorCode = result.errorCode()) {
1257         logMessage(_("TEMPORARY: ") + msgMemoryReadError(errorCode, range.from));
1258         logMessage(_("RETRYING UNBUFFERED"));
1259         // FIXME: This does not handle large requests properly.
1260         sendTrkMessage(0x10, TrkCB(handleReadMemoryUnbuffered),
1261             trkReadMemoryMessage(range), QVariant::fromValue(range));
1262         return;
1263     }
1264     const QByteArray ba = result.data.mid(3);
1265     MEMORY_DEBUG("INSERT KNOWN MEMORY RANGE: " << range << m_snapshot.memory.size() << " BLOCKS");
1266     m_snapshot.insertMemory(range, ba);
1267     tryAnswerGdbMemoryRequest(true);
1268 }
1269
1270 void TrkGdbAdapter::handleReadMemoryUnbuffered(const TrkResult &result)
1271 {
1272     if (extractShort(result.data.data() + 1) + 3 != result.data.size())
1273         logMessage(_("\n BAD MEMORY RESULT: ") + result.data.toHex() + '\n', LogError);
1274     const MemoryRange range = result.cookie.value<MemoryRange>();
1275     MEMORY_DEBUG("HANDLE READ MEMORY UNBUFFERED FOR " << range);
1276     if (const int errorCode = result.errorCode()) {
1277         logMessage(_("TEMPORARY: ") + msgMemoryReadError(errorCode, range.from));
1278         logMessage(_("RETRYING UNBUFFERED"));
1279 #if 1
1280         const QByteArray ba = "E20";
1281         sendGdbServerMessage(ba, msgMemoryReadError(32, range.from).toLatin1());
1282 #else
1283         // emit bogus data to make Python happy
1284         MemoryRange wanted = m_snapshot.wantedMemory;
1285         qDebug() << "SENDING BOGUS DATA FOR " << wanted;
1286         m_snapshot.insertMemory(wanted, QByteArray(wanted.size(), 0xa5));
1287         tryAnswerGdbMemoryRequest(false);
1288 #endif
1289         return;
1290     }
1291     const QByteArray ba = result.data.mid(3);
1292     m_snapshot.insertMemory(range, ba);
1293     MEMORY_DEBUG("INSERT KNOWN MEMORY RANGE: " << range << m_snapshot.memory.size() << " BLOCKS");
1294     tryAnswerGdbMemoryRequest(false);
1295 }
1296
1297 void TrkGdbAdapter::tryAnswerGdbMemoryRequest(bool buffered)
1298 {
1299     //logMessage("TRYING TO ANSWER MEMORY REQUEST ");
1300
1301     MemoryRange wanted = m_snapshot.wantedMemory;
1302     MemoryRange needed = m_snapshot.wantedMemory;
1303     MEMORY_DEBUG("WANTED: " << wanted);
1304     Snapshot::Memory::const_iterator it = m_snapshot.memory.begin();
1305     Snapshot::Memory::const_iterator et = m_snapshot.memory.end();
1306     for ( ; it != et; ++it) {
1307         MEMORY_DEBUG("   NEEDED STEP: " << needed);
1308         needed -= it.key();
1309     }
1310     MEMORY_DEBUG("NEEDED FINAL: " << needed);
1311
1312     if (needed.to == 0) {
1313         // FIXME: need to combine chunks first.
1314
1315         // All fine. Send package to gdb.
1316         it = m_snapshot.memory.begin();
1317         et = m_snapshot.memory.end();
1318         for ( ; it != et; ++it) {
1319             if (it.key().from <= wanted.from && wanted.to <= it.key().to) {
1320                 int offset = wanted.from - it.key().from;
1321                 int len = wanted.to - wanted.from;
1322                 QByteArray ba = it.value().mid(offset, len);
1323                 sendGdbServerMessage(ba.toHex(),
1324                                      m_snapshot.memoryReadLogMessage(wanted.from, m_session.tid, m_verbose, ba));
1325                 return;
1326             }
1327         }
1328         // Happens when chunks are not combined
1329         QTC_ASSERT(false, /**/);
1330         showMessage("CHUNKS NOT COMBINED");
1331 #        ifdef MEMORY_DEBUG
1332         qDebug() << "CHUNKS NOT COMBINED";
1333         it = m_snapshot.memory.begin();
1334         et = m_snapshot.memory.end();
1335         for ( ; it != et; ++it)
1336             qDebug() << hexNumber(it.key().from) << hexNumber(it.key().to);
1337         qDebug() << "WANTED" << wanted.from << wanted.to;
1338 #        endif
1339         sendGdbServerMessage("E22", "");
1340         return;
1341     }
1342
1343     MEMORY_DEBUG("NEEDED AND UNSATISFIED: " << needed);
1344     if (buffered) {
1345         uint blockaddr = (needed.from / MemoryChunkSize) * MemoryChunkSize;
1346         logMessage(_("Requesting buffered memory %1 bytes from 0x%2")
1347             .arg(MemoryChunkSize).arg(blockaddr, 0, 16));
1348         MemoryRange range(blockaddr, blockaddr + MemoryChunkSize);
1349         MEMORY_DEBUG("   FETCH BUFFERED MEMORY : " << range);
1350         sendTrkMessage(0x10, TrkCB(handleReadMemoryBuffered),
1351             trkReadMemoryMessage(range),
1352             QVariant::fromValue(range));
1353     } else { // Unbuffered, direct requests
1354         int len = needed.to - needed.from;
1355         logMessage(_("Requesting unbuffered memory %1 bytes from 0x%2")
1356             .arg(len).arg(needed.from, 0, 16));
1357         MEMORY_DEBUG("   FETCH UNBUFFERED MEMORY : " << needed);
1358         sendTrkMessage(0x10, TrkCB(handleReadMemoryUnbuffered),
1359             trkReadMemoryMessage(needed),
1360             QVariant::fromValue(needed));
1361     }
1362 }
1363
1364 /*
1365 void TrkGdbAdapter::reportReadMemoryBuffered(const TrkResult &result)
1366 {
1367     const MemoryRange range = result.cookie.value<MemoryRange>();
1368     // Gdb accepts less memory according to documentation.
1369     // Send E on complete failure.
1370     QByteArray ba;
1371     uint blockaddr = (range.from / MemoryChunkSize) * MemoryChunkSize;
1372     for (; blockaddr < addr + len; blockaddr += MemoryChunkSize) {
1373         const Snapshot::Memory::const_iterator it = m_snapshot.memory.constFind(blockaddr);
1374         if (it == m_snapshot.memory.constEnd())
1375             break;
1376         ba.append(it.value());
1377     }
1378     const int previousChunkOverlap = addr % MemoryChunkSize;
1379     if (previousChunkOverlap != 0 && ba.size() > previousChunkOverlap)
1380         ba.remove(0, previousChunkOverlap);
1381     if (ba.size() > int(len))
1382         ba.truncate(len);
1383
1384     if (ba.isEmpty()) {
1385         ba = "E20";
1386         sendGdbServerMessage(ba, msgMemoryReadError(32, addr, len).toLatin1());
1387     } else {
1388         sendGdbServerMessage(ba.toHex(), memoryReadLogMessage(addr, len, ba));
1389     }
1390 }
1391 */
1392
1393 void TrkGdbAdapter::handleStep(const TrkResult &result)
1394 {
1395     if (result.errorCode()) {
1396         logMessage("ERROR: " + result.errorString() + " in handleStep", LogError);
1397
1398         // Try fallback with Continue.
1399         showMessage("FALLBACK TO 'CONTINUE'");
1400         trkContinueAll("Step failed");
1401         //sendGdbServerMessage("S05", "Stepping finished");
1402
1403         // Doing nothing as below does not work as gdb seems to insist on
1404         // making some progress through a 'step'.
1405         //sendTrkMessage(0x12,
1406         //    TrkCB(handleAndReportReadRegistersAfterStop),
1407         //    Launcher::readRegistersMessage(m_session.pid, m_session.tid));
1408         return;
1409     }
1410     // The gdb server response is triggered later by the Stop Reply packet.
1411     logMessage("STEP FINISHED " + currentTime());
1412 }
1413
1414 void TrkGdbAdapter::handleAndReportSetBreakpoint(const TrkResult &result)
1415 {
1416     //---TRK------------------------------------------------------
1417     //  Command: 0x80 Acknowledge
1418     //    Error: 0x00
1419     // [80 09 00 00 00 00 0A]
1420     if (result.errorCode()) {
1421         logMessage("ERROR WHEN SETTING BREAKPOINT: " + result.errorString(), LogError);
1422         sendGdbServerMessage("E21");
1423         return;
1424     }
1425     uint bpnr = extractInt(result.data.data() + 1);
1426     uint addr = result.cookie.toUInt();
1427     m_session.addressToBP[addr] = bpnr;
1428     logMessage("SET BREAKPOINT " + hexxNumber(bpnr) + ' '
1429          + stringFromArray(result.data.data()));
1430     sendGdbServerMessage("OK");
1431     //sendGdbServerMessage("OK");
1432 }
1433
1434 void TrkGdbAdapter::handleClearBreakpoint(const TrkResult &result)
1435 {
1436     logMessage("CLEAR BREAKPOINT ");
1437     if (result.errorCode()) {
1438         logMessage("ERROR: " + result.errorString(), LogError);
1439         //return;
1440     }
1441     sendGdbServerMessage("OK");
1442 }
1443
1444 void TrkGdbAdapter::handleSupportMask(const TrkResult &result)
1445 {
1446     const char *data = result.data.data();
1447     QByteArray str;
1448     for (int i = 0; i < 32; ++i) {
1449         //str.append("  [" + formatByte(data[i]) + "]: ");
1450         for (int j = 0; j < 8; ++j)
1451         if (data[i] & (1 << j))
1452             str.append(QByteArray::number(i * 8 + j, 16));
1453     }
1454     logMessage(_("SUPPORTED: ") + str);
1455  }
1456
1457 void TrkGdbAdapter::handleTrkVersionsStartGdb(const TrkResult &result)
1458 {
1459     QString logMsg;
1460     QTextStream str(&logMsg);
1461     str << "Versions: ";
1462     if (result.data.size() >= 5) {
1463         str << "App TRK version " << int(result.data.at(1)) << '.'
1464             << int(result.data.at(2))
1465             << ", TRK protocol version " << int(result.data.at(3))
1466              << '.' << int(result.data.at(4));
1467     }
1468     logMessage(logMsg);
1469     // As we are called from the TrkDevice handler, do not lock up when shutting
1470     // down the device in case of gdb launch errors.
1471     QTimer::singleShot(0, this, SLOT(slotStartGdb()));
1472 }
1473
1474 void TrkGdbAdapter::slotStartGdb()
1475 {
1476     QStringList gdbArgs;
1477     gdbArgs.append(QLatin1String("--nx")); // Do not read .gdbinit file
1478     if (!m_engine->startGdb(gdbArgs)) {
1479         cleanup();
1480         return;
1481     }
1482     m_engine->handleAdapterStarted();
1483 }
1484
1485 void TrkGdbAdapter::handleDisconnect(const TrkResult & /*result*/)
1486 {
1487     logMessage(QLatin1String("App TRK disconnected"));
1488 }
1489
1490 void TrkGdbAdapter::readMemory(uint addr, uint len, bool buffered)
1491 {
1492     Q_ASSERT(len < (2 << 16));
1493
1494     // We try to get medium-sized chunks of data from the device
1495     if (m_verbose > 2)
1496         logMessage(_("readMemory %1 bytes from 0x%2 blocksize=%3")
1497             .arg(len).arg(addr, 0, 16).arg(MemoryChunkSize));
1498
1499     m_snapshot.wantedMemory = MemoryRange(addr, addr + len);
1500     tryAnswerGdbMemoryRequest(buffered);
1501 }
1502
1503 void TrkGdbAdapter::writeMemory(uint addr, const QByteArray &data)
1504 {
1505     Q_ASSERT(data.size() < (2 << 16));
1506     if (m_verbose > 2) {
1507         logMessage(_("writeMemory %1 bytes from 0x%2 blocksize=%3 data=%4")
1508             .arg(data.size()).arg(addr, 0, 16).arg(MemoryChunkSize).arg(QString::fromLatin1(data.toHex())));
1509     }
1510
1511     sendTrkMessage(0x11, TrkCB(handleWriteMemory),
1512         trkWriteMemoryMessage(addr, data));
1513 }
1514
1515 void TrkGdbAdapter::handleWriteMemory(const TrkResult &result)
1516 {
1517     logMessage("       RESULT: " + result.toString() + result.cookie.toString());
1518     if (result.errorCode()) {
1519         logMessage("ERROR: " + result.errorString(), LogError);
1520         sendGdbServerMessage("E01");
1521         return;
1522     }
1523     sendGdbServerMessage("OK");
1524 }
1525
1526 void TrkGdbAdapter::interruptInferior()
1527 {
1528     sendTrkMessage(0x1a, TrkCallback(), trkInterruptMessage(), "Interrupting...");
1529 }
1530
1531 void TrkGdbAdapter::trkDeviceRemoved(const SymbianUtils::SymbianDevice &dev)
1532 {
1533     if (state() != DebuggerNotReady && !m_trkDevice.isNull() && m_trkDevice->port() == dev.portName()) {
1534         const QString message = QString::fromLatin1("Device '%1' has been disconnected.").arg(dev.friendlyName());
1535         logMessage(message);
1536         m_engine->handleAdapterCrashed(message);
1537     }
1538 }
1539
1540 bool TrkGdbAdapter::initializeDevice(const QString &remoteChannel, QString *errorMessage)
1541 {
1542     if (remoteChannel.isEmpty()) {
1543         *errorMessage = tr("Port specification missing.");
1544         return false;
1545     }
1546     // Run config: Acquire from device manager.
1547     m_trkDevice = SymbianUtils::SymbianDeviceManager::instance()
1548         ->acquireDevice(remoteChannel);
1549     if (m_trkDevice.isNull()) {
1550         *errorMessage = tr("Unable to acquire a device on '%1'. It appears to be in use.").arg(remoteChannel);
1551         return false;
1552     }
1553     connect(SymbianUtils::SymbianDeviceManager::instance(), SIGNAL(deviceRemoved(const SymbianUtils::SymbianDevice)),
1554             this, SLOT(trkDeviceRemoved(SymbianUtils::SymbianDevice)));
1555     connect(m_trkDevice.data(), SIGNAL(messageReceived(trk::TrkResult)),
1556             this, SLOT(handleTrkResult(trk::TrkResult)));
1557     connect(m_trkDevice.data(), SIGNAL(error(QString)),
1558             this, SLOT(handleTrkError(QString)));
1559     connect(m_trkDevice.data(), SIGNAL(logMessage(QString)),
1560             this, SLOT(trkLogMessage(QString)));
1561     m_trkDevice->setVerbose(m_verbose);
1562
1563     // Prompt the user to start communication
1564     const trk::PromptStartCommunicationResult src =
1565             S60DebuggerBluetoothStarter::startCommunication(m_trkDevice,
1566                                                             0, errorMessage);
1567     switch (src) {
1568     case trk::PromptStartCommunicationConnected:
1569         break;
1570     case trk::PromptStartCommunicationCanceled:
1571         errorMessage->clear();
1572         return false;
1573     case trk::PromptStartCommunicationError:
1574         return false;
1575     }
1576     return true;
1577 }
1578
1579 void TrkGdbAdapter::startAdapter()
1580 {
1581     m_snapshot.fullReset();
1582
1583     // Retrieve parameters
1584     const DebuggerStartParameters &parameters = startParameters();
1585     m_remoteExecutable = parameters.executable;
1586     m_remoteArguments = parameters.processArgs;
1587     m_symbolFile = parameters.symbolFileName;
1588     if (!m_symbolFile.isEmpty())
1589         m_symbolFileFolder = QFileInfo(m_symbolFile).absolutePath();
1590     QString remoteChannel = parameters.remoteChannel;
1591     // FIXME: testing hack, remove!
1592     if (m_remoteArguments.startsWith(__("@sym@ "))) {
1593         QStringList pa = Utils::QtcProcess::splitArgs(m_remoteArguments);
1594         remoteChannel = pa.at(1);
1595         m_remoteExecutable = pa.at(2);
1596         m_symbolFile = pa.at(3);
1597         m_remoteArguments.clear();
1598     }
1599     // Unixish gdbs accept only forward slashes
1600     m_symbolFile.replace(QLatin1Char('\\'), QLatin1Char('/'));
1601     // Start
1602     QTC_ASSERT(state() == EngineSetupRequested, qDebug() << state());
1603     showMessage(_("TRYING TO START ADAPTER"));
1604     logMessage(QLatin1String("### Starting TrkGdbAdapter"));
1605
1606     // Prompt the user to start communication
1607     QString message;
1608     if (!initializeDevice(remoteChannel, &message)) {
1609         if (message.isEmpty()) {
1610             m_engine->handleAdapterStartFailed(QString(), QString());
1611         } else {
1612             logMessage(message, LogError);
1613             m_engine->handleAdapterStartFailed(message, QString());
1614         }
1615         return;
1616     }
1617
1618     QTC_ASSERT(m_gdbServer == 0, delete m_gdbServer);
1619     QTC_ASSERT(m_gdbConnection == 0, m_gdbConnection = 0);
1620     m_gdbServer = new QTcpServer(this);
1621
1622     if (!m_gdbServer->listen(QHostAddress(gdbServerIP()), gdbServerPort())) {
1623         QString msg = QString("Unable to start the gdb server at %1: %2.")
1624             .arg(m_gdbServerName).arg(m_gdbServer->errorString());
1625         logMessage(msg, LogError);
1626         m_engine->handleAdapterStartFailed(msg, QString());
1627         return;
1628     }
1629
1630     logMessage(QString("Gdb server running on %1.\nLittle endian assumed.")
1631         .arg(m_gdbServerName));
1632
1633     connect(m_gdbServer, SIGNAL(newConnection()),
1634         this, SLOT(handleGdbConnection()));
1635
1636     m_trkDevice->sendTrkInitialPing();
1637     sendTrkMessage(0x02); // Disconnect, as trk might be still connected
1638     sendTrkMessage(0x01); // Connect
1639     sendTrkMessage(0x05, TrkCB(handleSupportMask));
1640     sendTrkMessage(0x06, TrkCB(handleCpuType));
1641     sendTrkMessage(0x04, TrkCB(handleTrkVersionsStartGdb)); // Versions
1642 }
1643
1644 void TrkGdbAdapter::setupInferior()
1645 {
1646     QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << state());
1647     sendTrkMessage(0x40, TrkCB(handleCreateProcess),
1648                    trk::Launcher::startProcessMessage(m_remoteExecutable, m_remoteArguments));
1649 }
1650
1651 void TrkGdbAdapter::handleCreateProcess(const TrkResult &result)
1652 {
1653     QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << state());
1654     //  40 00 00]
1655     //logMessage("       RESULT: " + result.toString());
1656     // [80 08 00   00 00 01 B5   00 00 01 B6   78 67 40 00   00 40 00 00]
1657     if (result.errorCode()) {
1658         logMessage("ERROR: " + result.errorString(), LogError);
1659         QString msg = _("Cannot start executable \"%1\" on the device:\n%2")
1660             .arg(m_remoteExecutable).arg(result.errorString());
1661         // Delay cleanup as not to close a trk device from its read handler,
1662         // which blocks.
1663         emitDelayedInferiorSetupFailed(msg);
1664         return;
1665     }
1666     showMessage(_("RESET SNAPSHOT (NOTIFY CREATED)"));
1667     m_snapshot.fullReset();
1668     const char *data = result.data.data();
1669     m_session.pid = extractInt(data + 1);
1670     m_session.mainTid = m_session.tid = extractInt(data + 5);
1671     m_session.codeseg = extractInt(data + 9);
1672     m_session.dataseg = extractInt(data + 13);
1673     m_snapshot.addThread(m_session.mainTid);
1674     const QString startMsg =
1675         tr("Process started, PID: 0x%1, thread id: 0x%2, "
1676            "code segment: 0x%3, data segment: 0x%4.")
1677              .arg(m_session.pid, 0, 16).arg(m_session.tid, 0, 16)
1678              .arg(m_session.codeseg, 0, 16).arg(m_session.dataseg, 0, 16);
1679     logMessage(startMsg, LogMisc);
1680     // 26.8.2010: When paging occurs in S^3, bogus starting ROM addresses
1681     // like 0x500000 or 0x40000 are reported. Warn about symbol resolution errors.
1682     // Code duplicated in CodaAdapter. @TODO: Hopefully fixed in future TRK versions.
1683     if ((m_session.codeseg  & 0xFFFFF) == 0) {
1684         const QString warnMessage = tr("The reported code segment address (0x%1) might be invalid. Symbol resolution or setting breakoints may not work.").
1685                                     arg(m_session.codeseg, 0, 16);
1686         logMessage(warnMessage, LogError);
1687     }
1688
1689     m_engine->postCommand("set gnutarget arm-none-symbianelf");
1690
1691     const QByteArray symbolFile = m_symbolFile.toLocal8Bit();
1692     if (symbolFile.isEmpty()) {
1693         logMessage(_("WARNING: No symbol file available."), LogError);
1694     } else {
1695         // Does not seem to be necessary anymore.
1696         // FIXME: Startup sequence can be streamlined now as we do not
1697         // have to wait for the TRK startup to learn the load address.
1698         //m_engine->postCommand("add-symbol-file \"" + symbolFile + "\" "
1699         //    + QByteArray::number(m_session.codeseg));
1700         m_engine->postCommand("symbol-file \"" + symbolFile + "\"");
1701     }
1702     foreach(const QByteArray &s, Symbian::gdbStartupSequence())
1703         m_engine->postCommand(s);
1704     //m_engine->postCommand("set remotelogfile /tmp/gdb-remotelog");
1705     //m_engine->postCommand("set debug remote 1"); // FIXME: Make an option.
1706     m_engine->postCommand("target remote " + gdbServerName().toLatin1(),
1707         CB(handleTargetRemote));
1708 }
1709
1710 void TrkGdbAdapter::handleTargetRemote(const GdbResponse &record)
1711 {
1712     QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << state());
1713     if (record.resultClass == GdbResultDone) {
1714         m_engine->handleInferiorPrepared();
1715     } else {
1716         QString msg = tr("Connecting to TRK server adapter failed:\n")
1717             + QString::fromLocal8Bit(record.data.findChild("msg").data());
1718         m_engine->notifyInferiorSetupFailed(msg);
1719     }
1720 }
1721
1722 void TrkGdbAdapter::runEngine()
1723 {
1724     QTC_ASSERT(state() == EngineRunRequested, qDebug() << state());
1725     m_engine->notifyEngineRunAndInferiorStopOk();
1726     m_engine->continueInferiorInternal();
1727 }
1728
1729 //
1730 // AbstractGdbAdapter interface implementation
1731 //
1732
1733 void TrkGdbAdapter::write(const QByteArray &data)
1734 {
1735     // Write magic packets directly to TRK.
1736     if (data.startsWith("@#")) {
1737         QByteArray data1 = data.mid(2);
1738         if (data1.endsWith(char(10)))
1739             data1.chop(1);
1740         if (data1.endsWith(char(13)))
1741             data1.chop(1);
1742         if (data1.endsWith(' '))
1743             data1.chop(1);
1744         bool ok;
1745         uint addr = data1.toUInt(&ok, 0);
1746         qDebug() << "Writing: " << quoteUnprintableLatin1(data1) << addr;
1747         directStep(addr);
1748         return;
1749     }
1750     if (data.startsWith("@$")) {
1751         QByteArray ba = QByteArray::fromHex(data.mid(2));
1752         qDebug() << "Writing: " << quoteUnprintableLatin1(ba);
1753         if (ba.size() >= 1)
1754             sendTrkMessage(ba.at(0), TrkCB(handleDirectTrk), ba.mid(1));
1755         return;
1756     }
1757     if (data.startsWith("@@")) {
1758         // Read data
1759         sendTrkMessage(0x10, TrkCB(handleDirectWrite1),
1760                        Launcher::readMemoryMessage(m_session.pid, m_session.tid, m_session.dataseg, 12));
1761         return;
1762     }
1763     m_gdbProc.write(data);
1764 }
1765
1766 uint oldPC;
1767 QByteArray oldMem;
1768 uint scratch;
1769
1770 void TrkGdbAdapter::handleDirectWrite1(const TrkResult &response)
1771 {
1772     scratch = m_session.dataseg + 512;
1773     logMessage("DIRECT WRITE1: " + response.toString());
1774     if (const int errorCode = response.errorCode()) {
1775         logMessage("ERROR: " + response.errorString() + "in handleDirectWrite1", LogError);
1776     } else {
1777         oldMem = response.data.mid(3);
1778         oldPC = m_snapshot.registerValue(m_session.tid, RegisterPC);
1779         logMessage(_("READ MEM: ") + oldMem.toHex());
1780         //qDebug("READ MEM: " + oldMem.toHex());
1781         QByteArray ba;
1782         appendByte(&ba, 0xaa);
1783         appendByte(&ba, 0xaa);
1784         appendByte(&ba, 0xaa);
1785         appendByte(&ba, 0xaa);
1786
1787 #if 0
1788         // Arm:
1789         //  0:   e51f4004        ldr     r4, [pc, #-4]   ; 4 <.text+0x4>
1790         appendByte(&ba, 0x04);
1791         appendByte(&ba, 0x50);  // R5
1792         appendByte(&ba, 0x1f);
1793         appendByte(&ba, 0xe5);
1794 #else
1795         // Thumb:
1796         // subs  r0, #16
1797         appendByte(&ba, 0x08);
1798         appendByte(&ba, 0x3b);
1799         // subs  r0, #16
1800         appendByte(&ba, 0x08);
1801         appendByte(&ba, 0x3b);
1802         //
1803         appendByte(&ba, 0x08);
1804         appendByte(&ba, 0x3b);
1805         // subs  r0, #16
1806         appendByte(&ba, 0x08);
1807         appendByte(&ba, 0x3b);
1808 #endif
1809
1810         // Write data
1811         sendTrkMessage(0x11, TrkCB(handleDirectWrite2),
1812             trkWriteMemoryMessage(scratch, ba));
1813     }
1814 }
1815
1816 void TrkGdbAdapter::handleDirectWrite2(const TrkResult &response)
1817 {
1818     logMessage("DIRECT WRITE2: " + response.toString());
1819     if (const int errorCode = response.errorCode()) {
1820         logMessage("ERROR: " + response.errorString() + "in handleDirectWrite1", LogError);
1821     } else {
1822         // Check
1823         sendTrkMessage(0x10, TrkCB(handleDirectWrite3),
1824             trk::Launcher::readMemoryMessage(m_session.pid, m_session.tid, scratch, 12));
1825     }
1826 }
1827
1828 void TrkGdbAdapter::handleDirectWrite3(const TrkResult &response)
1829 {
1830     logMessage("DIRECT WRITE3: " + response.toString());
1831     if (const int errorCode = response.errorCode()) {
1832         logMessage("ERROR: " + response.errorString() + "in handleDirectWrite1", LogError);
1833     } else {
1834         // Set PC
1835         sendTrkMessage(0x13, TrkCB(handleDirectWrite4),
1836             trkWriteRegisterMessage(RegisterPC, scratch + 4));
1837     }
1838 }
1839
1840 void TrkGdbAdapter::handleDirectWrite4(const TrkResult &response)
1841 {
1842     m_snapshot.setRegisterValue(m_session.tid, RegisterPC, scratch + 4);
1843 return;
1844     logMessage("DIRECT WRITE4: " + response.toString());
1845     if (const int errorCode = response.errorCode()) {
1846         logMessage("ERROR: " + response.errorString() + "in handleDirectWrite1", LogError);
1847     } else {
1848         QByteArray ba1;
1849         appendByte(&ba1, 0x11); // options "step over"
1850         appendInt(&ba1, scratch + 4);
1851         appendInt(&ba1, scratch + 4);
1852         appendInt(&ba1, m_session.pid);
1853         appendInt(&ba1, m_session.tid);
1854         sendTrkMessage(0x19, TrkCB(handleDirectWrite5), ba1);
1855     }
1856 }
1857
1858 void TrkGdbAdapter::handleDirectWrite5(const TrkResult &response)
1859 {
1860     logMessage("DIRECT WRITE5: " + response.toString());
1861     if (const int errorCode = response.errorCode()) {
1862         logMessage("ERROR: " + response.errorString() + "in handleDirectWrite1", LogError);
1863     } else {
1864         // Restore PC
1865         sendTrkMessage(0x13, TrkCB(handleDirectWrite6),
1866             trkWriteRegisterMessage(RegisterPC, oldPC));
1867     }
1868 }
1869
1870 void TrkGdbAdapter::handleDirectWrite6(const TrkResult &response)
1871 {
1872     logMessage("DIRECT WRITE6: " + response.toString());
1873     if (const int errorCode = response.errorCode()) {
1874         logMessage("ERROR: " + response.errorString() + "in handleDirectWrite1", LogError);
1875     } else {
1876         // Restore memory
1877         sendTrkMessage(0x11, TrkCB(handleDirectWrite7),
1878             trkWriteMemoryMessage(scratch, oldMem));
1879     }
1880 }
1881
1882 void TrkGdbAdapter::handleDirectWrite7(const TrkResult &response)
1883 {
1884     logMessage("DIRECT WRITE7: " + response.toString());
1885     if (const int errorCode = response.errorCode()) {
1886         logMessage("ERROR: " + response.errorString() + "in handleDirectWrite1", LogError);
1887     } else {
1888         // Check
1889         sendTrkMessage(0x10, TrkCB(handleDirectWrite8),
1890                        trk::Launcher::readMemoryMessage(m_session.pid, m_session.tid,
1891                                                         scratch, 8));
1892     }
1893 }
1894
1895 void TrkGdbAdapter::handleDirectWrite8(const TrkResult &response)
1896 {
1897     logMessage("DIRECT WRITE8: " + response.toString());
1898     if (const int errorCode = response.errorCode()) {
1899         logMessage("ERROR: " + response.errorString() + "in handleDirectWrite1", LogError);
1900     } else {
1901         // Re-read registers
1902         sendTrkMessage(0x12,
1903             TrkCB(handleAndReportReadRegistersAfterStop),
1904             Launcher::readRegistersMessage(m_session.pid, m_session.tid));
1905     }
1906 }
1907
1908 void TrkGdbAdapter::handleDirectWrite9(const TrkResult &response)
1909 {
1910     logMessage("DIRECT WRITE9: " + response.toString());
1911 }
1912
1913 void TrkGdbAdapter::handleDirectTrk(const TrkResult &result)
1914 {
1915     logMessage("HANDLE DIRECT TRK: " + stringFromArray(result.data));
1916 }
1917
1918 void TrkGdbAdapter::directStep(uint addr)
1919 {
1920     // Write PC:
1921     qDebug() << "ADDR: " << addr;
1922     oldPC = m_snapshot.registerValue(m_session.tid, RegisterPC);
1923     m_snapshot.setRegisterValue(m_session.tid, RegisterPC, addr);
1924     QByteArray ba = trkWriteRegisterMessage(RegisterPC, addr);
1925     sendTrkMessage(0x13, TrkCB(handleDirectStep1), ba, "Write PC");
1926 }
1927
1928 void TrkGdbAdapter::handleDirectStep1(const TrkResult &result)
1929 {
1930     logMessage("HANDLE DIRECT STEP1: " + stringFromArray(result.data));
1931     QByteArray ba;
1932     const uint pc = oldPC = m_snapshot.registerValue(m_session.tid, RegisterPC);
1933     appendByte(&ba, 0x11); // options "step over"
1934     appendInt(&ba, pc);
1935     appendInt(&ba, pc);
1936     appendInt(&ba, m_session.pid);
1937     appendInt(&ba, m_session.tid);
1938     sendTrkMessage(0x19, TrkCB(handleDirectStep2), ba, "Direct step");
1939 }
1940
1941 void TrkGdbAdapter::handleDirectStep2(const TrkResult &result)
1942 {
1943     logMessage("HANDLE DIRECT STEP2: " + stringFromArray(result.data));
1944     m_snapshot.setRegisterValue(m_session.tid, RegisterPC, oldPC);
1945         QByteArray ba = trkWriteRegisterMessage(RegisterPC, oldPC);
1946     sendTrkMessage(0x13, TrkCB(handleDirectStep3), ba, "Write PC");
1947 }
1948
1949 void TrkGdbAdapter::handleDirectStep3(const TrkResult &result)
1950 {
1951     logMessage("HANDLE DIRECT STEP2: " + stringFromArray(result.data));
1952 }
1953
1954 void TrkGdbAdapter::cleanup()
1955 {
1956     if (!m_trkDevice.isNull()) {
1957         m_trkDevice->close();
1958         m_trkDevice->disconnect(this);
1959         SymbianUtils::SymbianDeviceManager::instance()->releaseDevice(m_trkDevice->port());
1960         m_trkDevice = TrkDevicePtr();
1961     }
1962
1963     delete m_gdbServer;
1964     m_gdbServer = 0;
1965 }
1966
1967 void TrkGdbAdapter::shutdownInferior()
1968 {
1969     m_engine->defaultInferiorShutdown("kill");
1970 }
1971
1972 void TrkGdbAdapter::shutdownAdapter()
1973 {
1974     if (m_gdbProc.state() == QProcess::Running) {
1975         cleanup();
1976         m_engine->notifyAdapterShutdownOk();
1977     } else {
1978         // Something is wrong, gdb crashed. Kill debuggee (see handleDeleteProcess2)
1979         if (m_trkDevice->isOpen()) {
1980             logMessage("Emergency shutdown of TRK", LogError);
1981             trkKill();
1982         }
1983     }
1984 }
1985
1986 void TrkGdbAdapter::trkReloadRegisters()
1987 {
1988     m_snapshot.syncRegisters(m_session.tid, m_engine->registerHandler());
1989 }
1990
1991 void TrkGdbAdapter::trkReloadThreads()
1992 {
1993     m_snapshot.syncThreads(m_engine->threadsHandler());
1994 }
1995
1996 } // namespace Internal
1997 } // namespace Debugger