trkgdbadapter.cpp 66.9 KB
Newer Older
1
2
3
4
/**************************************************************************
**
** This file is part of Qt Creator
**
hjk's avatar
hjk committed
5
** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** GNU Lesser General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://qt.nokia.com/contact.
**
**************************************************************************/

hjk's avatar
hjk committed
30
#include "trkgdbadapter.h"
31

32
#include "launcher.h"
33
#include "symbiandevicemanager.h"
34
35
#include "s60debuggerbluetoothstarter.h"
#include "bluetoothlistener_gui.h"
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
36

37
#include "registerhandler.h"
hjk's avatar
hjk committed
38
#include "threadshandler.h"
39
#include "debuggeractions.h"
40
#include "debuggerstringutils.h"
41
#include "watchutils.h"
hjk's avatar
hjk committed
42
#ifndef STANDALONE_RUNNER
43
#include "gdbengine.h"
hjk's avatar
hjk committed
44
#endif
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
45
46

#include <utils/qtcassert.h>
47
#include <utils/savedaction.h>
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
48
49
50

#include <QtCore/QTimer>
#include <QtCore/QDir>
51
52
#include <QtNetwork/QTcpServer>
#include <QtNetwork/QTcpSocket>
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
53

hjk's avatar
hjk committed
54
55
56
#ifdef Q_OS_WIN
#  include <windows.h>
#else
57
58
59
#  include <sys/types.h>
#  include <unistd.h>
#endif
60

hjk's avatar
hjk committed
61
62
63
64
#define CB(callback) \
    static_cast<GdbEngine::AdapterCallback>(&TrkGdbAdapter::callback), \
    STRINGIFY(callback)

hjk's avatar
hjk committed
65
#define TrkCB(s) TrkCallback(this, &TrkGdbAdapter::s)
66
67
68

using namespace trk;

69
70
namespace Debugger {
namespace Internal {
71
using namespace Symbian;
72

73
74
static inline void appendByte(QByteArray *ba, trk::byte b) { ba->append(b); }

75
76
77
78
79
///////////////////////////////////////////////////////////////////////////
//
// TrkGdbAdapter
//
///////////////////////////////////////////////////////////////////////////
80

81
82
83
84
85
86
87
88
/* Thread handling:
 * TRK does not report thread creation/termination. So, if we receive
 * a stop in a different thread, we store an additional thread in snapshot.
 * When continuing in trkContinueAll(), we delete this thread, since we cannot
 * know whether it will exist at the next stop.
 * Also note that threads continue running in Symbian even if one crashes.
 * TODO: Stop all threads once one stops? */

89
TrkGdbAdapter::TrkGdbAdapter(GdbEngine *engine) :
hjk's avatar
hjk committed
90
    AbstractGdbAdapter(engine),
91
92
    m_running(false),
    m_gdbAckMode(true),
hjk's avatar
hjk committed
93
    m_verbose(0)
94
{
hjk's avatar
hjk committed
95
    m_bufferedMemoryRead = true;
96
97
    // Disable buffering if gdb's dcache is used.
    m_bufferedMemoryRead = false;
hjk's avatar
hjk committed
98

hjk's avatar
hjk committed
99
100
    m_gdbServer = 0;
    m_gdbConnection = 0;
hjk's avatar
hjk committed
101
    m_snapshot.reset();
dt's avatar
dt committed
102
#ifdef Q_OS_WIN
103
    const DWORD portOffset = GetCurrentProcessId() % 100;
dt's avatar
dt committed
104
#else
105
    const uid_t portOffset = getuid();
dt's avatar
dt committed
106
#endif
107
    m_gdbServerName = _("127.0.0.1:%1").arg(2222 + portOffset);
108

109
    setVerbose(theDebuggerBoolSetting(VerboseLog));
110

111
112
    connect(theDebuggerAction(VerboseLog), SIGNAL(valueChanged(QVariant)),
        this, SLOT(setVerbose(QVariant)));
113
114
}

hjk's avatar
hjk committed
115
TrkGdbAdapter::~TrkGdbAdapter()
116
{
Friedemann Kleint's avatar
Friedemann Kleint committed
117
    cleanup();
hjk's avatar
hjk committed
118
    logMessage("Shutting down.\n");
119
120
}

121
122
123
124
125
126
127
128
void TrkGdbAdapter::setVerbose(const QVariant &value)
{
    setVerbose(value.toInt());
}

void TrkGdbAdapter::setVerbose(int verbose)
{
    m_verbose = verbose;
129
130
    if (!m_trkDevice.isNull())
        m_trkDevice->setVerbose(m_verbose);
131
132
}

hjk's avatar
hjk committed
133
void TrkGdbAdapter::trkLogMessage(const QString &msg)
134
135
136
137
{
    logMessage("TRK " + msg);
}

hjk's avatar
hjk committed
138
void TrkGdbAdapter::setGdbServerName(const QString &name)
139
140
141
142
{
    m_gdbServerName = name;
}

hjk's avatar
hjk committed
143
QString TrkGdbAdapter::gdbServerIP() const
144
145
146
147
148
149
150
{
    int pos = m_gdbServerName.indexOf(':');
    if (pos == -1)
        return m_gdbServerName;
    return m_gdbServerName.left(pos);
}

hjk's avatar
hjk committed
151
uint TrkGdbAdapter::gdbServerPort() const
152
153
154
155
156
157
158
{
    int pos = m_gdbServerName.indexOf(':');
    if (pos == -1)
        return 0;
    return m_gdbServerName.mid(pos + 1).toUInt();
}

159
QByteArray TrkGdbAdapter::trkContinueMessage(uint threadId)
160
161
162
{
    QByteArray ba;
    appendInt(&ba, m_session.pid);
163
    appendInt(&ba, threadId);
164
165
166
    return ba;
}

167
QByteArray TrkGdbAdapter::trkWriteRegisterMessage(trk::byte reg, uint value)
168
169
170
171
172
173
174
175
176
177
178
{
    QByteArray ba;
    appendByte(&ba, 0); // ?
    appendShort(&ba, reg);
    appendShort(&ba, reg);
    appendInt(&ba, m_session.pid);
    appendInt(&ba, m_session.tid);
    appendInt(&ba, value);
    return ba;
}

179
180
QByteArray TrkGdbAdapter::trkReadMemoryMessage(const MemoryRange &range)
{
181
    return trk::Launcher::readMemoryMessage(m_session.pid, m_session.tid, range.from, range.size());
182
183
}

hjk's avatar
hjk committed
184
185
186
187
188
189
190
191
192
193
194
195
196
QByteArray TrkGdbAdapter::trkWriteMemoryMessage(uint addr, const QByteArray &data)
{
    QByteArray ba;
    ba.reserve(11 + data.size());
    appendByte(&ba, 0x08); // Options, FIXME: why?
    appendShort(&ba, data.size());
    appendInt(&ba, addr);
    appendInt(&ba, m_session.pid);
    appendInt(&ba, m_session.tid);
    ba.append(data);
    return ba;
}

197
QByteArray TrkGdbAdapter::trkStepRangeMessage()
hjk's avatar
hjk committed
198
{
199
    //qDebug() << "STEP ON " << hexxNumber(m_snapshot.registers[RegisterPC]);
200
201
    uint from = m_snapshot.lineFromAddress;
    uint to = m_snapshot.lineToAddress;
202
    const uint pc = m_snapshot.registerValue(m_session.tid, RegisterPC);
203
    trk::byte option = 0x01; // Step into.
204
205
    if (m_snapshot.stepOver)
        option = 0x11;  // Step over.
206
    if (from <= pc && pc <= to) {
207
        //to = qMax(to - 4, from);
208
        //to = qMax(to - 4, from);
209
        showMessage("STEP IN " + hexxNumber(from) + " " + hexxNumber(to)
210
            + " INSTEAD OF " + hexxNumber(pc));
211
212
213
214
    } else {
        from = pc;
        to = pc;
    }
215
216
    logMessage(QString::fromLatin1("Stepping from 0x%1 to 0x%2 (current PC=0x%3), option 0x%4").
               arg(from, 0, 16).arg(to, 0, 16).arg(pc).arg(option, 0, 16));
217
218
219
    QByteArray ba;
    ba.reserve(17);
    appendByte(&ba, option);
220
221
    appendInt(&ba, from); // Start address
    appendInt(&ba, to); // End address
hjk's avatar
hjk committed
222
223
224
225
226
    appendInt(&ba, m_session.pid);
    appendInt(&ba, m_session.tid);
    return ba;
}

227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
QByteArray TrkGdbAdapter::trkDeleteProcessMessage()
{
    QByteArray ba;
    ba.reserve(6);
    appendByte(&ba, 0); // ?
    appendByte(&ba, 0); // Sub-command: Delete Process
    appendInt(&ba, m_session.pid);
    return ba;
}

QByteArray TrkGdbAdapter::trkInterruptMessage()
{
    QByteArray ba;
    ba.reserve(9);
    // Stop the thread (2) or the process (1) or the whole system (0).
    // We choose 2, as 1 does not seem to work.
    appendByte(&ba, 2);
    appendInt(&ba, m_session.pid);
245
    appendInt(&ba, m_session.mainTid); // threadID: 4 bytes Variable number of bytes.
246
247
248
    return ba;
}

hjk's avatar
hjk committed
249
void TrkGdbAdapter::emitDelayedInferiorSetupFailed(const QString &msg)
250
251
{
    m_adapterFailMessage = msg;
hjk's avatar
hjk committed
252
    QTimer::singleShot(0, this, SLOT(slotEmitDelayedInferiorSetupFailed()));
253
254
}

hjk's avatar
hjk committed
255
void TrkGdbAdapter::slotEmitDelayedInferiorSetupFailed()
256
{
hjk's avatar
hjk committed
257
    m_engine->notifyInferiorSetupFailed(m_adapterFailMessage);
258
259
}

260

261
void TrkGdbAdapter::logMessage(const QString &msg, int logChannel)
262
{
263
264
    if (m_verbose || logChannel != LogDebug)
        showMessage("TRK LOG: " + msg, logChannel);
265
266
267
268
269
}

//
// Gdb
//
hjk's avatar
hjk committed
270
void TrkGdbAdapter::handleGdbConnection()
271
272
{
    logMessage("HANDLING GDB CONNECTION");
hjk's avatar
hjk committed
273
274
275
    QTC_ASSERT(m_gdbConnection == 0, /**/);
    m_gdbConnection = m_gdbServer->nextPendingConnection();
    QTC_ASSERT(m_gdbConnection, return);
276
277
278
279
280
281
282
283
284
285
286
    connect(m_gdbConnection, SIGNAL(disconnected()),
            m_gdbConnection, SLOT(deleteLater()));
    connect(m_gdbConnection, SIGNAL(readyRead()),
            this, SLOT(readGdbServerCommand()));
}

static inline QString msgGdbPacket(const QString &p)
{
    return QLatin1String("gdb:                              ") + p;
}

hjk's avatar
hjk committed
287
void TrkGdbAdapter::readGdbServerCommand()
288
{
hjk's avatar
hjk committed
289
    QTC_ASSERT(m_gdbConnection, return);
290
291
292
    QByteArray packet = m_gdbConnection->readAll();
    m_gdbReadBuffer.append(packet);

293
    logMessage("gdb: -> " + currentTime() + ' ' + QString::fromAscii(packet));
294
295
296
297
298
299
300
301
302
303
304
305
306
307
    if (packet != m_gdbReadBuffer)
        logMessage("buffer: " + m_gdbReadBuffer);

    QByteArray &ba = m_gdbReadBuffer;
    while (ba.size()) {
        char code = ba.at(0);
        ba = ba.mid(1);

        if (code == '+') {
            //logMessage("ACK");
            continue;
        }

        if (code == '-') {
308
            logMessage("NAK: Retransmission requested", LogError);
309
310
            // This seems too harsh.
            //emit adapterCrashed("Communication problem encountered.");
311
312
313
314
315
316
317
318
319
320
321
            continue;
        }

        if (code == char(0x03)) {
            logMessage("INTERRUPT RECEIVED");
            interruptInferior();
            continue;
        }

        if (code != '$') {
            logMessage("Broken package (2) " + quoteUnprintableLatin1(ba)
322
                + hexNumber(code), LogError);
323
324
325
326
327
328
            continue;
        }

        int pos = ba.indexOf('#');
        if (pos == -1) {
            logMessage("Invalid checksum format in "
329
                + quoteUnprintableLatin1(ba), LogError);
330
331
332
333
334
335
336
            continue;
        }

        bool ok = false;
        uint checkSum = ba.mid(pos + 1, 2).toUInt(&ok, 16);
        if (!ok) {
            logMessage("Invalid checksum format 2 in "
337
                + quoteUnprintableLatin1(ba), LogError);
338
339
340
341
            return;
        }

        //logMessage(QString("Packet checksum: %1").arg(checkSum));
342
        trk::byte sum = 0;
343
344
345
346
347
        for (int i = 0; i < pos; ++i)
            sum += ba.at(i);

        if (sum != checkSum) {
            logMessage(QString("ERROR: Packet checksum wrong: %1 %2 in "
348
                + quoteUnprintableLatin1(ba)).arg(checkSum).arg(sum), LogError);
349
350
351
352
353
354
355
356
        }

        QByteArray cmd = ba.left(pos);
        ba.remove(0, pos + 3);
        handleGdbServerCommand(cmd);
    }
}

hjk's avatar
hjk committed
357
bool TrkGdbAdapter::sendGdbServerPacket(const QByteArray &packet, bool doFlush)
358
359
{
    if (!m_gdbConnection) {
360
        logMessage(_("Cannot write to gdb: No connection (%1)")
361
            .arg(_(packet)), LogError);
362
363
364
        return false;
    }
    if (m_gdbConnection->state() != QAbstractSocket::ConnectedState) {
365
        logMessage(_("Cannot write to gdb: Not connected (%1)")
366
            .arg(_(packet)), LogError);
367
368
369
        return false;
    }
    if (m_gdbConnection->write(packet) == -1) {
370
        logMessage(_("Cannot write to gdb: %1 (%2)")
371
            .arg(m_gdbConnection->errorString()).arg(_(packet)), LogError);
372
373
374
375
376
377
378
        return false;
    }
    if (doFlush)
        m_gdbConnection->flush();
    return true;
}

hjk's avatar
hjk committed
379
void TrkGdbAdapter::sendGdbServerAck()
380
381
382
{
    if (!m_gdbAckMode)
        return;
hjk's avatar
hjk committed
383
    logMessage("gdb: <- +");
384
    sendGdbServerPacket(QByteArray(1, '+'), false);
385
386
}

hjk's avatar
hjk committed
387
void TrkGdbAdapter::sendGdbServerMessage(const QByteArray &msg, const QByteArray &logNote)
388
{
389
    trk::byte sum = 0;
390
391
392
393
394
395
396
397
398
    for (int i = 0; i != msg.size(); ++i)
        sum += msg.at(i);

    char checkSum[30];
    qsnprintf(checkSum, sizeof(checkSum) - 1, "%02x ", sum);

    //logMessage(QString("Packet checksum: %1").arg(sum));

    QByteArray packet;
399
    packet.append('$');
400
401
402
403
    packet.append(msg);
    packet.append('#');
    packet.append(checkSum);
    int pad = qMax(0, 24 - packet.size());
404
    logMessage("gdb: <- " + currentTime() + ' ' + packet + QByteArray(pad, ' ') + logNote);
405
406
407
    sendGdbServerPacket(packet, true);
}

hjk's avatar
hjk committed
408
void TrkGdbAdapter::sendGdbServerMessageAfterTrkResponse(const QByteArray &msg,
409
410
411
412
413
414
    const QByteArray &logNote)
{
    QByteArray ba = msg + char(1) + logNote;
    sendTrkMessage(TRK_WRITE_QUEUE_NOOP_CODE, TrkCB(reportToGdb), "", ba); // Answer gdb
}

hjk's avatar
hjk committed
415
void TrkGdbAdapter::reportToGdb(const TrkResult &result)
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
{
    QByteArray message = result.cookie.toByteArray();
    QByteArray note;
    int pos = message.lastIndexOf(char(1)); // HACK
    if (pos != -1) {
        note = message.mid(pos + 1);
        message = message.left(pos);
    }
    message.replace("@CODESEG@", hexNumber(m_session.codeseg));
    message.replace("@DATASEG@", hexNumber(m_session.dataseg));
    message.replace("@PID@", hexNumber(m_session.pid));
    message.replace("@TID@", hexNumber(m_session.tid));
    sendGdbServerMessage(message, note);
}

hjk's avatar
hjk committed
431
QByteArray TrkGdbAdapter::trkBreakpointMessage(uint addr, uint len, bool armMode)
432
433
434
435
436
437
438
439
440
441
442
443
{
    QByteArray ba;
    appendByte(&ba, 0x82);  // unused option
    appendByte(&ba, armMode /*bp.mode == ArmMode*/ ? 0x00 : 0x01);
    appendInt(&ba, addr);
    appendInt(&ba, len);
    appendInt(&ba, 0x00000001);
    appendInt(&ba, m_session.pid);
    appendInt(&ba, 0xFFFFFFFF);
    return ba;
}

444
445
446
447
448
449
450
451
452
453
454
455
static QByteArray msgStepRangeReceived(unsigned from, unsigned to, bool over)
{
    QByteArray rc = "Stepping range received for step ";
    rc += over ? "over" : "into";
    rc += " (0x";
    rc += QByteArray::number(from, 16);
    rc += " to 0x";
    rc += QByteArray::number(to, 16);
    rc += ')';
    return rc;
}

hjk's avatar
hjk committed
456
void TrkGdbAdapter::handleGdbServerCommand(const QByteArray &cmd)
457
458
459
460
461
462
463
464
465
466
{
    // http://sourceware.org/gdb/current/onlinedocs/gdb_34.html
    if (0) {}

    else if (cmd == "!") {
        sendGdbServerAck();
        //sendGdbServerMessage("", "extended mode not enabled");
        sendGdbServerMessage("OK", "extended mode enabled");
    }

467
    else if (cmd.startsWith('?')) {
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
        logMessage(msgGdbPacket(QLatin1String("Query halted")));
        // Indicate the reason the target halted.
        // The reply is the same as for step and continue.
        sendGdbServerAck();
        // The command below will trigger fetching a stack trace while
        // the process does not seem to be fully functional. Most notably
        // the PC points to a 0x9..., which is not in "our" range
        //sendGdbServerMessage("T05library:r;", "target halted (library load)");
        //sendGdbServerMessage("S05", "target halted (trap)");
        sendGdbServerMessage("S00", "target halted (trap)");
        //sendGdbServerMessage("O" + QByteArray("Starting...").toHex());
    }

    else if (cmd == "c") {
        logMessage(msgGdbPacket(QLatin1String("Continue")));
        sendGdbServerAck();
484
485
        m_running = true;
        trkContinueAll("gdb 'c'");
486
487
    }

488
    else if (cmd.startsWith('C')) {
489
490
491
        logMessage(msgGdbPacket(QLatin1String("Continue with signal")));
        // C sig[;addr] Continue with signal sig (hex signal number)
        //Reply: See section D.3 Stop Reply Packets, for the reply specifications.
492
        //TODO: Meaning of the message is not clear.
493
494
        sendGdbServerAck();
        bool ok = false;
495
496
497
498
499
        const uint signalNumber = cmd.mid(1).toUInt(&ok, 16);
        logMessage(QString::fromLatin1("Not implemented 'Continue with signal' %1: ").arg(signalNumber), LogWarning);
        sendGdbServerMessage("O" + QByteArray("Console output").toHex());
        sendGdbServerMessage("W81"); // "Process exited with result 1
        trkContinueAll("gdb 'C'");
500
501
    }

502
    else if (cmd.startsWith('D')) {
503
504
505
506
507
508
        sendGdbServerAck();
        sendGdbServerMessage("OK", "shutting down");
    }

    else if (cmd == "g") {
        // Read general registers.
509
        if (m_snapshot.registersValid(m_session.tid)) {
510
            //qDebug() << "Using cached register contents";
hjk's avatar
hjk committed
511
512
513
514
            logMessage(msgGdbPacket(QLatin1String("Read registers")));
            sendGdbServerAck();
            reportRegisters();
        } else {
515
516
            //qDebug() << "Fetching register contents";
            sendGdbServerAck();
hjk's avatar
hjk committed
517
518
            sendTrkMessage(0x12,
                TrkCB(handleAndReportReadRegisters),
519
                Launcher::readRegistersMessage(m_session.pid, m_session.tid));
hjk's avatar
hjk committed
520
        }
521
522
    }

523
524
525
    else if (cmd == "gg") {
        // Force re-reading general registers for debugging purpose.
        sendGdbServerAck();
526
        m_snapshot.setRegistersValid(m_session.tid, false);
527
528
        sendTrkMessage(0x12,
            TrkCB(handleAndReportReadRegisters),
529
            Launcher::readRegistersMessage(m_session.pid, m_session.tid));
530
531
    }

532
    else if (cmd.startsWith("salstep,")) {
533
534
        // Receive address range for current line for future use when stepping.
        sendGdbServerAck();
535
        m_snapshot.parseGdbStepRange(cmd, false);
536
        sendGdbServerMessage("", msgStepRangeReceived(m_snapshot.lineFromAddress, m_snapshot.lineToAddress, m_snapshot.stepOver));
537
538
    }

539
    else if (cmd.startsWith("salnext,")) {
540
541
        // Receive address range for current line for future use when stepping.
        sendGdbServerAck();
542
        m_snapshot.parseGdbStepRange(cmd, true);
543
        sendGdbServerMessage("", msgStepRangeReceived(m_snapshot.lineFromAddress, m_snapshot.lineToAddress, m_snapshot.stepOver));
544
545
    }

546
547
    else if (cmd.startsWith("Hc")) {
        sendGdbServerAck();
548
        gdbSetCurrentThread(cmd, "Set current thread for step & continue ");
549
550
551
552
    }

    else if (cmd.startsWith("Hg")) {
        sendGdbServerAck();
553
        gdbSetCurrentThread(cmd, "Set current thread ");
554
555
    }

hjk's avatar
hjk committed
556
557
    else if (cmd == "k" || cmd.startsWith("vKill")) {
        // Kill inferior process
558
        logMessage(msgGdbPacket(QLatin1String("kill")));
hjk's avatar
hjk committed
559
        sendTrkMessage(0x41, TrkCB(handleDeleteProcess),
560
            trkDeleteProcessMessage(), "Delete process");
561
562
    }

563
    else if (cmd.startsWith('m')) {
564
565
566
        logMessage(msgGdbPacket(QLatin1String("Read memory")));
        // m addr,length
        sendGdbServerAck();
567
568
569
        const QPair<quint64, unsigned> addrLength = parseGdbReadMemoryRequest(cmd);
        if (addrLength.second) {
            readMemory(addrLength.first, addrLength.second, m_bufferedMemoryRead);
570
571
572
573
        } else {
            sendGdbServerMessage("E20", "Error " + cmd);
        }
    }
574

575
    else if (cmd.startsWith('p')) {
576
577
578
579
580
        logMessage(msgGdbPacket(QLatin1String("read register")));
        // 0xf == current instruction pointer?
        //sendGdbServerMessage("0000", "current IP");
        sendGdbServerAck();
        bool ok = false;
581
        const uint registerNumber = cmd.mid(1).toUInt(&ok, 16);
582
583
584
585
586
        const int threadIndex = m_snapshot.indexOfThread(m_session.tid);
        QTC_ASSERT(threadIndex != -1, return)
        const Symbian::Thread &thread =  m_snapshot.threadInfo[threadIndex];
        if (thread.registerValid) {
            sendGdbServerMessage(thread.gdbReportSingleRegister(registerNumber), thread.gdbSingleRegisterLogMessage(registerNumber));
587
        } else {
588
            //qDebug() << "Fetching single register";
hjk's avatar
hjk committed
589
590
            sendTrkMessage(0x12,
                TrkCB(handleAndReportReadRegister),
591
                Launcher::readRegistersMessage(m_session.pid, m_session.tid), registerNumber);
592
593
594
        }
    }

595
    else if (cmd.startsWith('P')) {
596
597
598
        logMessage(msgGdbPacket(QLatin1String("write register")));
        // $Pe=70f96678#d3
        sendGdbServerAck();
599
        const QPair<uint, uint> regnumValue = parseGdbWriteRegisterWriteRequest(cmd);
600
        // FIXME: Assume all goes well.
601
602
        m_snapshot.setRegisterValue(m_session.tid, regnumValue.first, regnumValue.second);
        QByteArray ba = trkWriteRegisterMessage(regnumValue.first, regnumValue.second);
603
604
605
606
        sendTrkMessage(0x13, TrkCB(handleWriteRegister), ba, "Write register");
        // Note that App TRK refuses to write registers 13 and 14
    }

607
608
609
610
611
    else if (cmd == "qAttached") {
        //$qAttached#8f
        // 1: attached to an existing process
        // 0: created a new process
        sendGdbServerAck();
612
613
        sendGdbServerMessage(QByteArray(1, '0'), "new process created");
        //sendGdbServerMessage('1', "attached to existing process");
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
        //sendGdbServerMessage("E01", "new process created");
    }

    else if (cmd.startsWith("qC")) {
        logMessage(msgGdbPacket(QLatin1String("query thread id")));
        // Return the current thread ID
        //$qC#b4
        sendGdbServerAck();
        sendGdbServerMessageAfterTrkResponse("QC@TID@");
    }

    else if (cmd.startsWith("qSupported")) {
        //$qSupported#37
        //$qSupported:multiprocess+#c6
        //logMessage("Handling 'qSupported'");
hjk's avatar
hjk committed
629
        sendGdbServerAck();
630
        sendGdbServerMessage(Symbian::gdbQSupported);
hjk's avatar
hjk committed
631
632
    }

633
634
635
    else if (cmd.startsWith("qThreadExtraInfo")) {
        // $qThreadExtraInfo,1f9#55
        sendGdbServerAck();
636
        sendGdbServerMessage(m_snapshot.gdbQThreadExtraInfo(cmd));
637
638
    }

hjk's avatar
hjk committed
639
    else if (cmd == "qfDllInfo") {
640
641
642
643
644
645
        // That's the _first_ query package.
        // Happens with  gdb 6.4.50.20060226-cvs / CodeSourcery.
        // Never made it into FSF gdb that got qXfer:libraries:read instead.
        // http://sourceware.org/ml/gdb/2007-05/msg00038.html
        // Name=hexname,TextSeg=textaddr[,DataSeg=dataaddr]
        sendGdbServerAck();
646
        sendGdbServerMessage(m_session.gdbQsDllInfo(), "library information transferred");
647
648
649
650
    }

    else if (cmd == "qsDllInfo") {
        // That's a following query package
hjk's avatar
hjk committed
651
        sendGdbServerAck();
652
        sendGdbServerMessage(QByteArray(1, 'l'), "library information transfer finished");
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
    }

    else if (cmd == "qPacketInfo") {
        // happens with  gdb 6.4.50.20060226-cvs / CodeSourcery
        // deprecated by qSupported?
        sendGdbServerAck();
        sendGdbServerMessage("", "FIXME: nothing?");
    }

    else if (cmd == "qOffsets") {
        sendGdbServerAck();
        sendGdbServerMessageAfterTrkResponse("TextSeg=@CODESEG@;DataSeg=@DATASEG@");
    }

    else if (cmd == "qSymbol::") {
        if (m_verbose)
            logMessage(msgGdbPacket(QLatin1String("notify can handle symbol lookup")));
        // Notify the target that GDB is prepared to serve symbol lookup requests.
        sendGdbServerAck();
        if (1)
            sendGdbServerMessage("OK", "no further symbols needed");
        else
hjk's avatar
hjk committed
675
676
            sendGdbServerMessage("qSymbol:" + QByteArray("_Z7E32Mainv").toHex(),
                "ask for more");
677
678
679
680
681
    }

    else if (cmd.startsWith("qXfer:features:read:target.xml:")) {
        //  $qXfer:features:read:target.xml:0,7ca#46...Ack
        sendGdbServerAck();
682
        sendGdbServerMessage(Symbian::gdbArchitectureXml);
hjk's avatar
hjk committed
683
684
685
686
687
    }

    else if (cmd == "qfThreadInfo") {
        // That's the _first_ query package.
        sendGdbServerAck();
688
        sendGdbServerMessage(m_snapshot.gdbQsThreadInfo(), "thread information transferred");
hjk's avatar
hjk committed
689
690
691
692
693
    }

    else if (cmd == "qsThreadInfo") {
        // That's a following query package
        sendGdbServerAck();
694
        sendGdbServerMessage(QByteArray(1, 'l'), "thread information transfer finished");
695
696
    }

697
698
    else if (cmd.startsWith("qXfer:libraries:read")) {
        sendGdbServerAck();
699
        sendGdbServerMessage(m_session.gdbLibraryList(), "library information transferred");
700
701
    }

702
703
    else if (cmd == "QStartNoAckMode") {
        //$qSupported#37
hjk's avatar
hjk committed
704
        logMessage("Handling 'QStartNoAckMode'");
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
        sendGdbServerAck();
        sendGdbServerMessage("OK", "ack no-ack mode");
        m_gdbAckMode = false;
    }

    else if (cmd.startsWith("QPassSignals")) {
        // list of signals to pass directly to inferior
        // $QPassSignals:e;10;14;17;1a;1b;1c;21;24;25;4c;#8f
        // happens only if "QPassSignals+;" is qSupported
        sendGdbServerAck();
        // FIXME: use the parameters
        sendGdbServerMessage("OK", "passing signals accepted");
    }

    else if (cmd == "s" || cmd.startsWith("vCont;s")) {
720
        const uint pc = m_snapshot.registerValue(m_session.tid, RegisterPC);
721
        logMessage(msgGdbPacket(QString::fromLatin1("Step range from 0x%1").
722
                                arg(pc, 0, 16)));
723
        sendGdbServerAck();
724
        //m_snapshot.reset();
725
        m_running = true;
726
727
        QByteArray ba = trkStepRangeMessage();
        sendTrkMessage(0x19, TrkCB(handleStep), ba, "Step range");
728
729
    }

hjk's avatar
hjk committed
730
731
732
733
734
735
736
    else if (cmd.startsWith('T')) {
        // FIXME: check whether thread is alive
        sendGdbServerAck();
        sendGdbServerMessage("OK"); // pretend all is well
        //sendGdbServerMessage("E nn");
    }

737
738
739
740
    else if (cmd == "vCont?") {
        // actions supported by the vCont packet
        sendGdbServerAck();
        //sendGdbServerMessage("OK"); // we don't support vCont.
741
        sendGdbServerMessage("vCont;c;C;s;S");
742
743
744
745
746
    }

    else if (cmd == "vCont;c") {
        // vCont[;action[:thread-id]]...'
        sendGdbServerAck();
747
        //m_snapshot.reset();
748
        m_running = true;
749
        trkContinueAll("gdb 'vCont;c'");
750
751
752
753
    }

    else if (cmd.startsWith("Z0,") || cmd.startsWith("Z1,")) {
        // Insert breakpoint
hjk's avatar
hjk committed
754
        sendGdbServerAck();
755
756
        logMessage(msgGdbPacket(QLatin1String("Insert breakpoint")));
        // $Z0,786a4ccc,4#99
757
758
        const QPair<quint64, unsigned> addrLen = parseGdbSetBreakpointRequest(cmd);
        if (addrLen.first) {
759
760
            //qDebug() << "ADDR: " << hexNumber(addr) << " LEN: " << len;
            logMessage(_("Inserting breakpoint at 0x%1, %2")
761
762
763
764
765
766
                .arg(addrLen.first, 0, 16).arg(addrLen.second));
            const bool armMode = addrLen.second == 4;
            const QByteArray ba = trkBreakpointMessage(addrLen.first, addrLen.second, armMode);
            sendTrkMessage(0x1B, TrkCB(handleAndReportSetBreakpoint), ba, QVariant(addrLen.first));
        } else {
            logMessage("MISPARSED BREAKPOINT '" + cmd + "')", LogError);
767
        }
768
769
770
771
    }

    else if (cmd.startsWith("z0,") || cmd.startsWith("z1,")) {
        // Remove breakpoint
hjk's avatar
hjk committed
772
        sendGdbServerAck();
773
774
775
776
        logMessage(msgGdbPacket(QLatin1String("Remove breakpoint")));
        // $z0,786a4ccc,4#99
        const int pos = cmd.lastIndexOf(',');
        bool ok = false;
777
778
        const uint addr = cmd.mid(3, pos - 3).toUInt(&ok, 16);
        const uint len = cmd.mid(pos + 1).toUInt(&ok, 16);
779
780
        const uint bp = m_session.addressToBP[addr];
        if (bp == 0) {
781
            logMessage(_("NO RECORDED BP AT 0x%1, %2")
782
                .arg(addr, 0, 16).arg(len), LogError);
hjk's avatar
hjk committed
783
            sendGdbServerMessage("E00");
784
785
786
        } else {
            m_session.addressToBP.remove(addr);
            QByteArray ba;
787
            appendInt(&ba, bp);
788
789
790
791
792
            sendTrkMessage(0x1C, TrkCB(handleClearBreakpoint), ba, addr);
        }
    }

    else if (cmd.startsWith("qPart:") || cmd.startsWith("qXfer:"))  {
hjk's avatar
hjk committed
793
        QByteArray data = cmd.mid(1 + cmd.indexOf(':'));
794
795
796
797
798
        // "qPart:auxv:read::0,147": Read OS auxiliary data (see info aux)
        bool handled = false;
        if (data.startsWith("auxv:read::")) {
            const int offsetPos = data.lastIndexOf(':') + 1;
            const int commaPos = data.lastIndexOf(',');
799
            if (commaPos != -1) {
800
801
                bool ok1 = false, ok2 = false;
                const int offset = data.mid(offsetPos,  commaPos - offsetPos)
802
803
                    .toUInt(&ok1, 16);
                const int length = data.mid(commaPos + 1).toUInt(&ok2, 16);
804
                if (ok1 && ok2) {
Tobias Hunger's avatar
Tobias Hunger committed
805
                    const QString msg = _("Read of OS auxiliary "
806
                        "vector (%1, %2) not implemented.").arg(offset).arg(length);
807
                    logMessage(msgGdbPacket(msg), LogWarning);
808
809
810
811
812
                    sendGdbServerMessage("E20", msg.toLatin1());
                    handled = true;
                }
            }
        } // auxv read
hjk's avatar
hjk committed
813

814
815
816
        if (!handled) {
            const QString msg = QLatin1String("FIXME unknown 'XFER'-request: ")
                + QString::fromAscii(cmd);
817
            logMessage(msgGdbPacket(msg), LogWarning);
818
819
820
821
822
            sendGdbServerMessage("E20", msg.toLatin1());
        }
    } // qPart/qXfer
    else {
        logMessage(msgGdbPacket(QLatin1String("FIXME unknown: ")
823
            + QString::fromAscii(cmd)), LogWarning);
824
825
826
    }
}

827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
void TrkGdbAdapter::gdbSetCurrentThread(const QByteArray &cmd, const char *why)
{
    // Thread ID from Hg/Hc commands: '-1': All, '0': arbitrary, else hex thread id.
    const QByteArray id = cmd.mid(2);
    const int threadId = id == "-1" ? -1 : id.toInt(0, 16);
    const QByteArray message = QByteArray(why) + QByteArray::number(threadId);
    logMessage(msgGdbPacket(QString::fromLatin1(message)));
    // Set thread for subsequent operations (`m', `M', `g', `G', et.al.).
    // for 'other operations.  0 - any thread
    //$Hg0#df
    m_session.tid = threadId <= 0 ? m_session.mainTid : uint(threadId);
    sendGdbServerMessage("OK", message);
}

void TrkGdbAdapter::trkContinueAll(const char *why)
{
    if (why)
        logMessage(QString::fromLatin1("Continuing %1 threads (%2)").
                   arg(m_snapshot.threadInfo.size()).arg(QString::fromLatin1(why)));

    // Starting from the last one, continue all threads.
    QTC_ASSERT(!m_snapshot.threadInfo.isEmpty(), return; );
    trkContinueNext(m_snapshot.threadInfo.size() - 1);
}

void TrkGdbAdapter::trkContinueNext(int threadIndex)
{
    const uint threadId = m_snapshot.threadInfo.at(threadIndex).id;
    logMessage(QString::fromLatin1("Continuing thread 0x%1 of %2").
               arg(threadId,0, 16).arg(m_snapshot.threadInfo.size()));
    sendTrkMessage(0x18, TrkCallback(this, &TrkGdbAdapter::handleTrkContinueNext),
                   trkContinueMessage(threadId), QVariant(threadIndex));
}

void TrkGdbAdapter::handleTrkContinueNext(const TrkResult &result)
{
hjk's avatar
hjk committed
863
    const int index = result.cookie.toInt();
864
865
866
867
868
869
870
871
872
873
874
875
876
    if (result.errorCode()) {
        logMessage("Error continuing thread: " + result.errorString(), LogError);
        return;
    }
    // Remove the thread (unless main) if it is continued since we
    // do not get thread creation/deletion events
    QTC_ASSERT(index < m_snapshot.threadInfo.size(), return; );
    if (m_snapshot.threadInfo.at(index).id != m_session.mainTid)
        m_snapshot.threadInfo.remove(index);
    if (index > 0 && m_running) // Stopped in-between
        trkContinueNext(index - 1);
}

877
void TrkGdbAdapter::sendTrkMessage(trk::byte code, TrkCallback callback,
878
879
    const QByteArray &data, const QVariant &cookie)
{
880
881
882
    if (m_verbose >= 2)
        logMessage("trk: -> " + QByteArray::number(code, 16) + "  "
            + stringFromArray(data));
883
    m_trkDevice->sendTrkMessage(code, callback, data, cookie);
884
885
}

886
void TrkGdbAdapter::sendTrkAck(trk::byte token)
887
{
888
    //logMessage(QString("SENDING ACKNOWLEDGEMENT FOR TOKEN %1").arg(int(token)));
889
    m_trkDevice->sendTrkAck(token);
890
891
}

hjk's avatar
hjk committed
892
void TrkGdbAdapter::handleTrkError(const QString &msg)
893
{
894
    logMessage("## TRK ERROR: " + msg, LogError);
895
    m_engine->handleAdapterCrashed("TRK problem encountered:\n" + msg);
896
897
}

hjk's avatar
hjk committed
898
void TrkGdbAdapter::handleTrkResult(const TrkResult &result)
899
{
900
901
    if (m_verbose >= 2)
        logMessage("trk: <- " + result.toString());
902
    if (result.isDebugOutput) {
903
904
905
        // It looks like those messages _must not_ be acknowledged.
        // If we do so, TRK will complain about wrong sequencing.
        //sendTrkAck(result.token);
906
        logMessage(QString::fromAscii(result.data), AppOutput);
907
908
909
        sendGdbServerMessage("O" + result.data.toHex());
        return;
    }
910
    //logMessage("READ TRK " + result.toString());
911
912
913
914
915
916
917
918
919
    QByteArray prefix = "READ BUF:                                       ";
    QByteArray str = result.toString().toUtf8();
    switch (result.code) {
        case 0x80: // ACK
            break;
        case 0xff: { // NAK. This mostly means transmission error, not command failed.
            QString logMsg;
            QTextStream(&logMsg) << prefix << "NAK: for token=" << result.token
                << " ERROR: " << errorMessage(result.data.at(0)) << ' ' << str;
920
            logMessage(logMsg, LogError);
921
922
            break;
        }
Friedemann Kleint's avatar
Friedemann Kleint committed
923
        case TrkNotifyStopped: {  // 0x90 Notified Stopped
924
            // 90 01   78 6a 40 40   00 00 07 23   00 00 07 24  00 00
925
            showMessage(_("RESET SNAPSHOT (NOTIFY STOPPED)"));
926
            m_snapshot.reset();
927
928
929
930
931
932
            QString reason;
            uint addr;
            uint pid;
            uint tid;
            trk::Launcher::parseNotifyStopped(result.data, &pid, &tid, &addr, &reason);
            const QString msg = trk::Launcher::msgStopped(pid, tid, addr, reason);
933
            // Unknown thread: Add.
hjk's avatar
hjk committed
934
            m_session.tid = tid;
935
            if (m_snapshot.indexOfThread(tid) == -1)
hjk's avatar
hjk committed
936
                m_snapshot.addThread(tid);
937
938
            m_snapshot.setThreadState(tid, reason);

939
            logMessage(prefix + msg);
940
            showMessage(msg, LogMisc);
941
942
943
944
945
946
947
948
949
950
            sendTrkAck(result.token);
            if (addr) {
                // Todo: Do not send off GdbMessages if a synced gdb
                // query is pending, queue instead
                if (m_running) {
                    m_running = false;
                }
            } else {
                logMessage(QLatin1String("Ignoring stop at 0"));
            }
951

Tobias Hunger's avatar
Tobias Hunger committed
952
#            if 1
hjk's avatar
hjk committed
953
            // We almost always need register values, so get them
954
            // now before informing gdb about the stop.s
955
            //qDebug() << "Auto-fetching registers";
hjk's avatar
hjk committed
956
957
            sendTrkMessage(0x12,
                TrkCB(handleAndReportReadRegistersAfterStop),
958
                Launcher::readRegistersMessage(m_session.pid, m_session.tid));
Tobias Hunger's avatar
Tobias Hunger committed
959
#            else
960
961
962
963
            // As a source-line step typically consists of
            // several instruction steps, better avoid the multiple
            // roundtrips through TRK in favour of an additional
            // roundtrip through gdb. But gdb will ask for all registers.
Tobias Hunger's avatar
Tobias Hunger committed
964
#                if 1
965
                sendGdbServerMessage("S05", "Target stopped");
Tobias Hunger's avatar
Tobias Hunger committed
966
#                else
967
968
969
                QByteArray ba = "T05";
                appendRegister(&ba, RegisterPSGdb, addr);
                sendGdbServerMessage(ba, "Registers");
Tobias Hunger's avatar
Tobias Hunger committed
970
971
#                endif
#            endif
972
973
            break;
        }
Friedemann Kleint's avatar
Friedemann Kleint committed
974
        case TrkNotifyException: { // 0x91 Notify Exception (obsolete)
975
            showMessage(_("RESET SNAPSHOT (NOTIFY EXCEPTION)"));
976
            m_snapshot.reset();
977
            logMessage(prefix + "NOTE: EXCEPTION  " + str, AppError);
978
979
980
981
            sendTrkAck(result.token);
            break;
        }
        case 0x92: { //
982
            showMessage(_("RESET SNAPSHOT (NOTIFY INTERNAL ERROR)"));
983
            m_snapshot.reset();
984
            logMessage(prefix + "NOTE: INTERNAL ERROR: " + str, LogError);
985
986
987
988
989
990
            sendTrkAck(result.token);
            break;
        }

        // target->host OS notification
        case 0xa0: { // Notify Created
991
992
            // Sending this ACK does not seem to make a difference. Why?
            //sendTrkAck(result.token);
993
            m_snapshot.resetMemory();
994
            const char *data = result.data.data();
995
            const trk::byte error = result.data.at(0);
996
            // type: 1 byte; for dll item, this value is 2.
997
            const trk::byte type = result.data.at(1);
998
            const uint tid = extractInt(data + 6);
999
1000
1001
            const Library lib = Library(result);
            m_session.libraries.push_back(lib);
            m_session.modules += QString::fromAscii(lib.name);
1002
1003
1004
1005
1006
            QString logMsg;
            QTextStream str(&logMsg);
            str << prefix << " NOTE: LIBRARY LOAD: token=" << result.token;
            if (error)
                str << " ERROR: " << int(error);
1007
1008
1009
1010
            str << " TYPE: " << int(type) << " PID: " << lib.pid << " TID:   " <<  tid;
            str << " CODE: " << hexxNumber(lib.codeseg);
            str << " DATA: " << hexxNumber(lib.dataseg);
            str << " NAME: '" << lib.name << '\'';
1011
1012
            if (tid && tid != unsigned(-1) && m_snapshot.indexOfThread(tid) == -1)
                m_snapshot.addThread(tid);
1013
            logMessage(logMsg);
1014
1015
1016
1017
            // This lets gdb trigger a register update etc.
            // With CS gdb 6.4 we get a non-standard $qfDllInfo#7f+ request
            // afterwards, so don't use it for now.
            //sendGdbServerMessage("T05library:;");
1018
1019
1020
1021
1022
/*
            // Causes too much "stopped" (by SIGTRAP) messages that need
            // to be answered by "continue". Auto-continuing each SIGTRAP
            // is not possible as this is also the real message for a user
            // initiated interrupt.
1023
1024
1025
            sendGdbServerMessage("T05load:Name=" + lib.name.toHex()
                + ",TextSeg=" + hexNumber(lib.codeseg)
                + ",DataSeg=" + hexNumber(lib.dataseg) + ';');
1026
*/
1027
1028
1029
1030
1031
1032
1033
1034

            // After 'continue' the very first time after starting debugging
            // a process some library load events are generated, these are
            // actually static dependencies for the process. For these libraries,
            // the thread id is -1 which means the debugger doesn't have
            // to continue. The debugger can safely assume that the
            // thread resumption will be handled by the agent itself.
            if (tid != unsigned(-1))
1035
                sendTrkMessage(0x18, TrkCallback(), trkContinueMessage(m_session.mainTid), "CONTINUE");
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
            break;
        }
        case 0xa1: { // NotifyDeleted
            const ushort itemType = extractByte(result.data.data() + 1);
            const ushort len = result.data.size() > 12
                ? extractShort(result.data.data() + 10) : ushort(0);
            const QString name = len
                ? QString::fromAscii(result.data.mid(12, len)) : QString();
            if (!name.isEmpty())
                m_session.modules.removeAll(name);
1046
            logMessage(_("%1 %2 UNLOAD: %3")
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
                .arg(QString::fromAscii(prefix))
                .arg(itemType ? QLatin1String("LIB") : QLatin1String("PROCESS"))
                .arg(name));
            sendTrkAck(result.token);
            if (itemType == 0) {
                sendGdbServerMessage("W00", "Process exited");
                //sendTrkMessage(0x02, TrkCB(handleDisconnect));
            }
            break;
        }
        case 0xa2: { // NotifyProcessorStarted
            logMessage(prefix + "NOTE: PROCESSOR STARTED: " + str);
            sendTrkAck(result.token);
            break;
        }
        case 0xa6: { // NotifyProcessorStandby
            logMessage(prefix + "NOTE: PROCESSOR STANDBY: " + str);
            sendTrkAck(result.token);
            break;
        }
        case 0xa7: { // NotifyProcessorReset
            logMessage(prefix + "NOTE: PROCESSOR RESET: " + str);
            sendTrkAck(result.token);
            break;
        }
        default: {
1073
            logMessage(prefix + "INVALID: " + str, LogError);
1074
1075
1076
1077
1078
            break;
        }
    }
}

hjk's avatar
hjk committed
1079
void TrkGdbAdapter::handleCpuType(const TrkResult &result)
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
{
    //---TRK------------------------------------------------------
    //  Command: 0x80 Acknowledge
    //    Error: 0x00
    // [80 03 00  04 00 00 04 00 00 00]
    m_session.cpuMajor = result.data[1];
    m_session.cpuMinor = result.data[2];
    m_session.bigEndian = result.data[3];
    m_session.defaultTypeSize = result.data[4];
    m_session.fpTypeSize = result.data[5];
    m_session.extended1TypeSize = result.data[6];
    //m_session.extended2TypeSize = result.data[6];
    QString logMsg;
    QTextStream(&logMsg) << "HANDLE CPU TYPE: CPU=" << m_session.cpuMajor << '.'
        << m_session.cpuMinor << " bigEndian=" << m_session.bigEndian
        << " defaultTypeSize=" << m_session.defaultTypeSize
        << " fpTypeSize=" << m_session.fpTypeSize
        << " extended1TypeSize=" <<  m_session.extended1TypeSize;
    logMessage(logMsg);
}

hjk's avatar
hjk committed
1101
1102
1103
void TrkGdbAdapter::handleDeleteProcess(const TrkResult &result)
{
    Q_UNUSED(result);
Robert Loehning's avatar
Robert Loehning committed
1104
    logMessage("Inferior process killed");
hjk's avatar
hjk committed
1105
1106
1107
1108
1109
1110
1111
    //sendTrkMessage(0x01, TrkCB(handleDeleteProcess2)); // Ping
    sendTrkMessage(0x02, TrkCB(handleDeleteProcess2)); // Disconnect
}

void