From ab6a3d378028c41bcba4273c6b9adaeafefe009d Mon Sep 17 00:00:00 2001
From: hjk <qtc-committer@nokia.com>
Date: Fri, 17 Jul 2009 12:13:38 +0200
Subject: [PATCH] debugger: implementation progress in the trk manual test

---
 tests/manual/trk/adapter.cpp   | 423 ++++++++++++++++++++++-----------
 tests/manual/trk/run.sh        |   7 +-
 tests/manual/trk/trkserver.cpp |  51 ++++
 tests/manual/trk/trkutils.cpp  |  57 +++--
 tests/manual/trk/trkutils.h    |  36 ++-
 5 files changed, 407 insertions(+), 167 deletions(-)

diff --git a/tests/manual/trk/adapter.cpp b/tests/manual/trk/adapter.cpp
index 7b0fccfef7a..a9e53d082be 100644
--- a/tests/manual/trk/adapter.cpp
+++ b/tests/manual/trk/adapter.cpp
@@ -51,8 +51,9 @@ void signalHandler(int)
 
 using namespace trk;
 
-#define CB(s) &Adapter::s
+enum { TRK_SYNC = 0x7f };
 
+#define CB(s) &Adapter::s
 
 class Adapter : public QObject
 {
@@ -65,7 +66,6 @@ public:
     void setTrkServerName(const QString &name) { m_trkServerName = name; }
     void startServer();
 
-
 private:
     //
     // TRK
@@ -76,16 +76,19 @@ private:
 
     struct TrkMessage 
     {
-        TrkMessage() { token = 0; callBack = 0; }
-        byte command;
+        TrkMessage() { code = token = 0; callBack = 0; }
+        byte code;
         byte token;
         QByteArray data;
+        QVariant cookie;
         TrkCallBack callBack;
     };
 
     bool openTrkPort(const QString &port); // or server name for local server
-    void sendTrkMessage(byte command, TrkCallBack callBack = 0,
-        const QByteArray &lit = QByteArray());
+    void sendTrkMessage(byte code,
+        TrkCallBack callBack = 0,
+        const QByteArray &data = QByteArray(),
+        const QVariant &cookie = QVariant());
     // adds message to 'send' queue
     void queueTrkMessage(const TrkMessage &msg);
     void tryTrkWrite();
@@ -103,27 +106,28 @@ private:
     void timerEvent(QTimerEvent *ev);
     byte nextTrkWriteToken();
 
-    void handleTrkCpuType(const TrkResult &result);
-    void handleTrkCreateProcess(const TrkResult &result);
-    void handleTrkDeleteProcess(const TrkResult &result);
-    void handleTrkSetBreakpoint(const TrkResult &result);
-    void handleTrkClearBreakpoint(const TrkResult &result);
-    void handleTrkContinue(const TrkResult &result);
-    void handleTrkReadInfo(const TrkResult &result);
-    void handleTrkWaitForFinished(const TrkResult &result);
-    void handleTrkStep(const TrkResult &result);
-    void handleTrkStop(const TrkResult &result);
-    void handleTrkReadRegisters(const TrkResult &result);
-    void handleTrkWriteRegisters(const TrkResult &result);
-    void handleTrkReadMemory(const TrkResult &result);
-    void handleTrkWriteMemory(const TrkResult &result);
-    void handleTrkSupportMask(const TrkResult &result);
-    void handleTrkDisconnect(const TrkResult &result);
-
+    void handleCpuType(const TrkResult &result);
+    void handleCreateProcess(const TrkResult &result);
+    void handleDeleteProcess(const TrkResult &result);
+    void handleSetBreakpoint(const TrkResult &result);
+    void handleClearBreakpoint(const TrkResult &result);
+    void handleContinue(const TrkResult &result);
+    void handleReadInfo(const TrkResult &result);
+    void handleWaitForFinished(const TrkResult &result);
+    void handleStep(const TrkResult &result);
+    void handleStop(const TrkResult &result);
+    void handleSupportMask(const TrkResult &result);
+    void handleDisconnect(const TrkResult &result);
+
+    void handleAndReportCreateProcess(const TrkResult &result);
+    void handleAndReportReadRegisters(const TrkResult &result);
+    void handleReadMemory(const TrkResult &result);
+    void reportReadMemory(const TrkResult &result);
 
     void setTrkBreakpoint(const Breakpoint &bp);
     void clearTrkBreakpoint(const Breakpoint &bp);
-    void handleTrkResult(const TrkResult &data);
+    void handleResult(const TrkResult &data);
+    void readMemory(uint addr, uint len);
 
     QLocalSocket *m_trkDevice;
 
@@ -137,7 +141,6 @@ private:
     bool m_trkWriteBusy;
 
     QList<Breakpoint> m_breakpoints;
-    Session m_session;
 
     //
     // Gdb
@@ -145,7 +148,7 @@ private:
     Q_SLOT void handleGdbConnection();
     Q_SLOT void readFromGdb();
     void handleGdbResponse(const QByteArray &ba);
-    void writeToGdb(const QByteArray &msg, bool addAck = true);
+    void writeToGdb(const QByteArray &msg, const QByteArray &logNote = QByteArray());
     void writeAckToGdb();
 
     //
@@ -158,7 +161,9 @@ private:
     QByteArray m_gdbReadBuffer;
     bool m_gdbAckMode;
 
-    uint m_registers[100];
+    // Debuggee state
+    Session m_session; // global-ish data (process id, target information)
+    SnapShot m_snapshot; // local-ish data (memory and registers)
 };
 
 Adapter::Adapter()
@@ -218,24 +223,16 @@ void Adapter::startServer()
 
     sendTrkInitialPing();
     sendTrkMessage(0x01); // Connect
-    sendTrkMessage(0x05, CB(handleTrkSupportMask));
-    sendTrkMessage(0x06, CB(handleTrkCpuType));
+    sendTrkMessage(0x05, CB(handleSupportMask));
+    sendTrkMessage(0x06, CB(handleCpuType));
     sendTrkMessage(0x04); // Versions
     sendTrkMessage(0x09); // Unrecognized command
-    sendTrkMessage(0x4a, 0,
-        "10 " + formatString("C:\\data\\usingdlls.sisx")); // Open File
-    sendTrkMessage(0x4B, 0, "00 00 00 01 73 1C 3A C8"); // Close File
-
-    QByteArray exe = "C:\\sys\\bin\\UsingDLLs.exe";
-    exe.append('\0');
-    exe.append('\0');
-    sendTrkMessage(0x40, CB(handleTrkCreateProcess),
-        "00 00 00 " + formatString(exe)); // Create Item
+    //sendTrkMessage(0x4a, 0,
+    //    "10 " + formatString("C:\\data\\usingdlls.sisx")); // Open File
+    //sendTrkMessage(0x4B, 0, "00 00 00 01 73 1C 3A C8"); // Close File
 
     logMessage("Connected to TRK server");
 
-return;
-
     if (!m_gdbServer.listen(QHostAddress(m_gdbServerName), m_gdbServerPort)) {
         logMessage(QString("Unable to start the gdb server at %1:%2: %3.")
             .arg(m_gdbServerName).arg(m_gdbServerPort)
@@ -336,84 +333,122 @@ void Adapter::writeAckToGdb()
     m_gdbConnection->write(packet);
 }
 
-void Adapter::writeToGdb(const QByteArray &msg, bool addAck)
+void Adapter::writeToGdb(const QByteArray &msg, const QByteArray &logNote)
 {
-    uint sum = 0;
+    ushort sum = 0;
     for (int i = 0; i != msg.size(); ++i)
         sum += msg.at(i);
-    QByteArray checkSum = QByteArray::number(sum % 256, 16);
+
+    char checkSum[30];
+    qsnprintf(checkSum, sizeof(checkSum) - 1, "%02x ", sum);
+
     //logMessage(QString("Packet checksum: %1").arg(sum));
 
     QByteArray packet;
-    if (addAck)
+    if (m_gdbAckMode)
         packet.append("+");
     packet.append("$");
     packet.append(msg);
     packet.append('#');
-    if (checkSum.size() < 2)
-        packet.append('0');
     packet.append(checkSum);
-    logMessage("gdb: <- " + packet);
+    int pad = qMax(0, 24 - packet.size());
+    logMessage("gdb: <- " + packet + QByteArray(pad, ' ') + logNote);
     m_gdbConnection->write(packet);
 }
 
 void Adapter::handleGdbResponse(const QByteArray &response)
 {
     // http://sourceware.org/gdb/current/onlinedocs/gdb_34.html
-    if (response == "qSupported") {
-        //$qSupported#37
-        //logMessage("Handling 'qSupported'");
-        writeToGdb(QByteArray());
-    }
-
-    else if (response == "qAttached") {
-        //$qAttached#8f
-        // 1: attached to an existing process
-        // 0: created a new process
-        writeToGdb("0");
-    }
-
-    else if (response == "QStartNoAckMode") {
-        //$qSupported#37
-        //logMessage("Handling 'QStartNoAckMode'");
-        writeToGdb(QByteArray("OK"));
-        m_gdbAckMode = false;
-    }
-
-    else if (response == "g") {
+    if (response == "g") {
         // Read general registers.
-        writeToGdb("00000000");
+        //writeToGdb("00000000", "read registers");
+        QByteArray ba;
+        appendByte(&ba, 0); // ?
+        appendByte(&ba, 0); // ?
+        appendByte(&ba, 0); // ?
+
+        appendByte(&ba, 0); // first register
+        // FIXME: off by one?
+        appendByte(&ba, registerCount - 1); // last register
+        appendInt(&ba, m_session.pid);
+        appendInt(&ba, m_session.tid);
+        
+        sendTrkMessage(0x12, CB(handleAndReportReadRegisters), ba);
     }
 
     else if (response.startsWith("Hc")) {
         // Set thread for subsequent operations (`m', `M', `g', `G', et.al.).
         // for step and continue operations
         //$Hc-1#09
-        writeToGdb("OK");
+        writeToGdb("OK", "set current thread for step & continue");
     }
 
     else if (response.startsWith("Hg")) {
         // Set thread for subsequent operations (`m', `M', `g', `G', et.al.).
         // for 'other operations.  0 - any thread
         //$Hg0#df
-        writeToGdb("OK");
+        m_session.currentThread = response.mid(2).toInt();
+        writeToGdb("OK", "set current thread "
+            + QByteArray::number(m_session.currentThread));
+    }
+
+    else if (response.startsWith("m")) {
+        // m addr,length
+        int pos = response.indexOf(',');
+        bool ok = false;
+        uint addr = response.mid(1, pos - 1).toInt(&ok, 16);
+        uint len = response.mid(pos + 1).toInt(&ok, 16);
+        //qDebug() << "ADDR: " << QByteArray::number(addr, 16) << " "
+        //    << QByteArray::number(len, 16);
+        readMemory(addr, len);
     }
 
     else if (response == "pf") {
         // current instruction pointer?
-        writeToGdb("0000");
+        writeToGdb("0000", "current IP");
+    }
+
+    else if (response == "qAttached") {
+        //$qAttached#8f
+        // 1: attached to an existing process
+        // 0: created a new process
+        writeToGdb("0", "new process created");
+        //writeToGdb("1", "attached to existing process");
     }
 
     else if (response.startsWith("qC")) {
         // Return the current thread ID
         //$qC#b4
-        writeToGdb("QC-1");
+
+        // It's not started yet
+        QByteArray ba;
+        appendByte(&ba, 0); // ?
+        appendByte(&ba, 0); // ?
+        appendByte(&ba, 0); // ?
+
+        appendString(&ba, "C:\\sys\\bin\\filebrowseapp.exe", TargetByteOrder);
+        ba.append('\0');
+        ba.append('\0');
+        sendTrkMessage(0x40, CB(handleAndReportCreateProcess), ba); // Create Item
+    }
+
+    else if (response == "qSupported") {
+        //$qSupported#37
+        //logMessage("Handling 'qSupported'");
+        writeToGdb(QByteArray());
+    }
+
+    else if (response == "QStartNoAckMode") {
+        //$qSupported#37
+        //logMessage("Handling 'QStartNoAckMode'");
+        writeToGdb("OK", "ack no-ack mode");
+        m_gdbAckMode = false;
     }
 
     else if (response.startsWith("?")) {
         // Indicate the reason the target halted.
         // The reply is the same as for step and continue.
-        writeToGdb("S0b");
+        writeToGdb("S0b", "target halted");
         //$?#3f
         //$qAttached#8f
         //$qOffsets#4b
@@ -479,29 +514,22 @@ unsigned char Adapter::nextTrkWriteToken()
     return m_trkWriteToken;
 }
 
-void Adapter::sendTrkMessage(byte command, TrkCallBack callBack,
-    const QByteArray &lit)
+void Adapter::sendTrkMessage(byte code, TrkCallBack callBack,
+    const QByteArray &data, const QVariant &cookie)
 {
     TrkMessage msg;
-    msg.command = command;
+    msg.code = code;
     msg.token = nextTrkWriteToken();
     msg.callBack = callBack;
-    QList<QByteArray> list = lit.split(' ');
-    foreach (const QByteArray &item, list) {
-        if (item.isEmpty())
-            continue;
-        bool ok = false;
-        int i = item.toInt(&ok, 16);
-        msg.data.append(char(i));
-    }
-    //logMessage("PARSED: " << lit << " -> " << stringFromArray(data).toLatin1().data());
+    msg.data = data;
+    msg.cookie = cookie;
     queueTrkMessage(msg);
 }
 
 void Adapter::sendTrkInitialPing()
 {
     TrkMessage msg;
-    msg.command = 0x00; // Ping
+    msg.code = 0x00; // Ping
     msg.token = 0; // reset sequence count
     queueTrkMessage(msg);
 }
@@ -510,9 +538,9 @@ void Adapter::waitForTrkFinished()
 {
     TrkMessage msg;
     // initiate one last roundtrip to ensure all is flushed
-    msg.command = 0x00; // Ping
+    msg.code = 0x00; // Ping
     msg.token = nextTrkWriteToken();
-    msg.callBack = CB(handleTrkWaitForFinished);
+    msg.callBack = CB(handleWaitForFinished);
     queueTrkMessage(msg);
 }
 
@@ -520,7 +548,7 @@ void Adapter::sendTrkAck(byte token)
 {
     logMessage(QString("SENDING ACKNOWLEDGEMENT FOR TOKEN ").arg(int(token)));
     TrkMessage msg;
-    msg.command = 0x80;
+    msg.code = 0x80;
     msg.token = token;
     msg.data.append('\0');
     // The acknowledgement must not be queued!
@@ -541,12 +569,25 @@ void Adapter::tryTrkWrite()
     if (m_trkWriteQueue.isEmpty())
         return;
 
-    trkWrite(m_trkWriteQueue.dequeue());
+    TrkMessage msg = m_trkWriteQueue.dequeue();
+    if (msg.code == TRK_SYNC) {
+        //logMessage("TRK SYNC");
+        TrkResult result;
+        result.code = msg.code;
+        result.token = msg.token;
+        result.data = msg.data;
+        result.cookie = msg.cookie;
+        TrkCallBack cb = msg.callBack;
+        if (cb)
+            (this->*cb)(result);
+    } else {
+        trkWrite(msg);
+    }
 }
 
 void Adapter::trkWrite(const TrkMessage &msg)
 {
-    QByteArray ba = frameMessage(msg.command, msg.token, msg.data);
+    QByteArray ba = frameMessage(msg.code, msg.token, msg.data);
 
     m_writtenTrkMessages.insert(msg.token, msg);
     m_trkWriteBusy = true;
@@ -557,12 +598,12 @@ void Adapter::trkWrite(const TrkMessage &msg)
     if (!WriteFile(m_hdevice, ba.data(), ba.size(), &charsWritten, NULL))
         logMessage("WRITE ERROR: ");
 
-    logMessage("WRITE: " + stringFromArray(ba));
+    //logMessage("WRITE: " + stringFromArray(ba));
     FlushFileBuffers(m_hdevice);
 
 #else
 
-    logMessage("WRITE: " + stringFromArray(ba));
+    //logMessage("WRITE: " + stringFromArray(ba));
     if (!m_trkDevice->write(ba))
         logMessage("WRITE ERROR: " + m_trkDevice->errorString());
     m_trkDevice->flush();
@@ -606,13 +647,13 @@ void Adapter::tryTrkRead()
     }
 
     while (!m_trkReadQueue.isEmpty())
-        handleTrkResult(extractResult(&m_trkReadQueue));
+        handleResult(extractResult(&m_trkReadQueue));
 
     m_trkWriteBusy = false;
 }
 
 
-void Adapter::handleTrkResult(const TrkResult &result)
+void Adapter::handleResult(const TrkResult &result)
 {
     QByteArray prefix = "READ BUF:                                       ";
     QByteArray str = result.toString().toUtf8();
@@ -626,10 +667,12 @@ void Adapter::handleTrkResult(const TrkResult &result)
                 logMessage("NO ENTRY FOUND!");
             }
             TrkMessage msg = m_writtenTrkMessages.take(result.token);
+            TrkResult result1 = result;
+            result1.cookie = msg.cookie;
             TrkCallBack cb = msg.callBack;
             if (cb) {
                 //logMessage("HANDLE: " << stringFromArray(result.data));
-                (this->*cb)(result);
+                (this->*cb)(result1);
             }
             break;
         }
@@ -688,9 +731,10 @@ void Adapter::handleTrkResult(const TrkResult &result)
             logMessage(prefix + "NAME:  " + name);
             */
 
-            sendTrkMessage(0x18, CB(handleTrkContinue),
-                formatInt(m_session.pid) + formatInt(m_session.tid));
-
+            QByteArray ba;
+            appendInt(&ba, m_session.pid);
+            appendInt(&ba, m_session.tid);
+            sendTrkMessage(0x18, CB(handleContinue), ba);
             //sendTrkAck(result.token)
             break;
         }
@@ -721,7 +765,7 @@ void Adapter::handleTrkResult(const TrkResult &result)
     }
 }
 
-void Adapter::handleTrkCpuType(const TrkResult &result)
+void Adapter::handleCpuType(const TrkResult &result)
 {
     logMessage("HANDLE CPU TYPE: " + result.toString());
     //---TRK------------------------------------------------------
@@ -737,7 +781,7 @@ void Adapter::handleTrkCpuType(const TrkResult &result)
     //m_session.extended2TypeSize = result.data[6];
 }
 
-void Adapter::handleTrkCreateProcess(const TrkResult &result)
+void Adapter::handleCreateProcess(const TrkResult &result)
 {
     //---TRK------------------------------------------------------
     //  Command: 0x80 Acknowledge
@@ -773,10 +817,10 @@ void Adapter::handleTrkCreateProcess(const TrkResult &result)
     //  Command: 0x42 Read Info
     //          [42 0C 00 06 00 00 00 00 00 14 50 6F 6C 79 6D 6F
     //  72 70 68 69 63 44 4C 4C 32 2E 64 6C 6C 00]
-    sendTrkMessage(0x42, CB(handleTrkReadInfo),
+    sendTrkMessage(0x42, CB(handleReadInfo),
         "00 06 00 00 00 00 00 14 50 6F 6C 79 6D 6F "
         "72 70 68 69 63 44 4C 4C 32 2E 64 6C 6C 00");
-    //sendTrkMessage(0x42, CB(handleTrkReadInfo),
+    //sendTrkMessage(0x42, CB(handleReadInfo),
     //        "00 01 00 00 00 00");
     //---TRK------------------------------------------------------
     //  Command: 0x80 Acknowledge
@@ -788,7 +832,7 @@ void Adapter::handleTrkCreateProcess(const TrkResult &result)
     //  Command: 0x42 Read Info
     // [42 0D 00 06 00 00 00 00 00 14 50 6F 6C 79 6D 6F
     //  72 70 68 69 63 44 4C 4C 31 2E 64 6C 6C 00]
-    sendTrkMessage(0x42, CB(handleTrkReadInfo),
+    sendTrkMessage(0x42, CB(handleReadInfo),
         "00 06 00 00 00 00 00 14 50 6F 6C 79 6D 6F "
         "72 70 68 69 63 44 4C 4C 31 2E 64 6C 6C 00");
     //---TRK------------------------------------------------------
@@ -797,7 +841,7 @@ void Adapter::handleTrkCreateProcess(const TrkResult &result)
     // [80 0D 20]
 #endif
 
-    //sendTrkMessage(0x18, CB(handleTrkStop),
+    //sendTrkMessage(0x18, CB(handleStop),
     //    "01 " + formatInt(m_session.pid) + formatInt(m_session.tid));
 
     //---IDE------------------------------------------------------
@@ -805,9 +849,11 @@ void Adapter::handleTrkCreateProcess(const TrkResult &result)
     //ProcessID: 0x000001B5 (437)
     // ThreadID: 0x000001B6 (438)
     // [18 0E 00 00 01 B5 00 00 01 B6]
-    sendTrkMessage(0x18, CB(handleTrkContinue),
-        formatInt(m_session.pid) + formatInt(m_session.tid));
-    //sendTrkMessage(0x18, CB(handleTrkContinue),
+    QByteArray ba;
+    appendInt(&ba, m_session.pid);
+    appendInt(&ba, m_session.tid);
+    sendTrkMessage(0x18, CB(handleContinue), ba);
+    //sendTrkMessage(0x18, CB(handleContinue),
     //    formatInt(m_session.pid) + "ff ff ff ff");
     //---TRK------------------------------------------------------
     //  Command: 0x80 Acknowledge
@@ -815,6 +861,75 @@ void Adapter::handleTrkCreateProcess(const TrkResult &result)
     // [80 0E 00]
 }
 
+void Adapter::handleAndReportCreateProcess(const TrkResult &result)
+{
+    //logMessage("       RESULT: " + result.toString());
+    // [80 08 00   00 00 01 B5   00 00 01 B6   78 67 40 00   00 40 00 00]
+    const char *data = result.data.data();
+    m_session.pid = extractInt(data);
+    m_session.tid = extractInt(data + 4);
+    m_session.codeseg = extractInt(data + 8);
+    m_session.dataseg = extractInt(data + 12);
+
+    char buf[30];
+    qsnprintf(buf, sizeof(buf) - 1, "p%08x.%08x", m_session.pid, m_session.tid);
+    writeToGdb("QC" + QByteArray(buf), "current thread Id");
+}
+
+void Adapter::handleAndReportReadRegisters(const TrkResult &result)
+{
+    //logMessage("       RESULT: " + result.toString());
+    // [80 0B 00   00 00 00 00   C9 24 FF BC   00 00 00 00   00
+    //  60 00 00   00 00 00 00   78 67 79 70   00 00 00 00   00...]
+    QByteArray ba;
+#if 0
+    char buf[30];
+    const char *data = result.data.data();
+    for (int i = 0; i != registerCount; ++i) {
+        uint value = extractInt(data + 4 * i + 1);
+        qsnprintf(buf, sizeof(buf) - 1, "%08x", value);
+        ba.append(buf);
+    }
+#else
+    ba = result.data.toHex();
+#endif
+    writeToGdb(ba, "register contents");
+}
+
+void Adapter::handleReadMemory(const TrkResult &result)
+{
+    //logMessage("       RESULT READ MEMORY: " + result.data.toHex());
+    QByteArray ba = result.data.mid(1);
+    uint blockaddr = result.cookie.toInt();
+    //qDebug() << "READING " << ba.size() << " BYTES: "
+    //    << quoteUnprintableLatin1(ba)
+    //    << "ADDR: " << QByteArray::number(blockaddr, 16)
+    //    << "COOKIE: " << result.cookie;
+    m_snapshot.memory[blockaddr] = ba;
+}
+
+void Adapter::reportReadMemory(const TrkResult &result)
+{
+    qulonglong cookie = result.cookie.toLongLong();
+    uint addr = cookie >> 32;
+    uint len = uint(cookie);
+
+    QByteArray ba;
+    uint blockaddr = (addr / memoryChunkSize) * memoryChunkSize;
+    for (; blockaddr < addr + len; blockaddr += memoryChunkSize) {
+        QByteArray blockdata = m_snapshot.memory[blockaddr];
+        Q_ASSERT(!blockdata.isEmpty());
+        ba.append(blockdata);
+    }
+
+    ba = ba.mid(addr % memoryChunkSize, len);
+    // qDebug() << "REPORTING MEMORY " << ba.size()
+    //     << " ADDR: " << QByteArray::number(blockaddr, 16) << " LEN: " << len
+    //     << " BYTES: " << quoteUnprintableLatin1(ba);
+
+    writeToGdb(ba.toHex(), "memory contents");
+}
+
 void Adapter::setTrkBreakpoint(const Breakpoint &bp)
 {
     //---IDE------------------------------------------------------
@@ -828,12 +943,16 @@ void Adapter::setTrkBreakpoint(const Breakpoint &bp)
     // ThreadID: 0xffffffff (-1)
     // [1B 09 82 00 78 67 43 40 00 00 00 01 00 00 00 00
     //  00 00 01 B5 FF FF FF FF]
-    sendTrkMessage(0x1B, CB(handleTrkSetBreakpoint),
-        "82 "
-        + QByteArray(bp.mode == ArmMode ? "00 " : "01 ")
-        + formatInt(m_session.codeseg + bp.offset)
-        + "00 00 00 01 00 00 00 00 " + formatInt(m_session.pid)
-        + "FF FF FF FF");
+    QByteArray ba;
+    appendByte(&ba, 0x82);
+    appendByte(&ba, bp.mode == ArmMode ? 0x00 : 0x01);
+    appendInt(&ba, m_session.codeseg + bp.offset);
+    appendInt(&ba, 0x00000001);
+    appendInt(&ba, 0x00000001);
+    appendInt(&ba, m_session.pid);
+    appendInt(&ba, 0xFFFFFFFF);
+
+    sendTrkMessage(0x1B, CB(handleSetBreakpoint), ba);
     //m_session.toekn
 
     //---TRK------------------------------------------------------
@@ -842,7 +961,7 @@ void Adapter::setTrkBreakpoint(const Breakpoint &bp)
     // [80 09 00 00 00 00 0A]
 }
 
-void Adapter::handleTrkSetBreakpoint(const TrkResult &result)
+void Adapter::handleSetBreakpoint(const TrkResult &result)
 {
     //---TRK------------------------------------------------------
     //  Command: 0x80 Acknowledge
@@ -855,17 +974,17 @@ void Adapter::handleTrkSetBreakpoint(const TrkResult &result)
 
 void Adapter::clearTrkBreakpoint(const Breakpoint &bp)
 {
-    sendTrkMessage(0x1C, CB(handleTrkClearBreakpoint),
-        //formatInt(m_session.codeseg + bp.offset));
-        "00 " + formatShort(bp.number)
-            + formatInt(m_session.codeseg + bp.offset));
-
     //---IDE------------------------------------------------------
     //  Command: 0x1C Clear Break
     // [1C 25 00 00 00 0A 78 6A 43 40]
+    QByteArray ba;
+    appendByte(&ba, 0x00);
+    appendShort(&ba, bp.number);
+    appendInt(&ba, m_session.codeseg + bp.offset);
+    sendTrkMessage(0x1C, CB(handleClearBreakpoint), ba);
 }
 
-void Adapter::handleTrkClearBreakpoint(const TrkResult &result)
+void Adapter::handleClearBreakpoint(const TrkResult &result)
 {
     Q_UNUSED(result);
     //---TRK------------------------------------------------------
@@ -875,59 +994,59 @@ void Adapter::handleTrkClearBreakpoint(const TrkResult &result)
     logMessage("CLEAR BREAKPOINT ");
 }
 
-void Adapter::handleTrkContinue(const TrkResult &result)
+void Adapter::handleContinue(const TrkResult &result)
 {
     logMessage("   HANDLE CONTINUE: " + stringFromArray(result.data));
     //if (result.result.token)
         //logMessage("   ERROR: " + byte(result.result.token)
-    //    sendTrkMessage(0x18, CB(handleTrkContinue),
+    //    sendTrkMessage(0x18, CB(handleContinue),
     //        formatInt(m_session.pid) + formatInt(m_session.tid));
     //}
 }
 
-void Adapter::handleTrkDisconnect(const TrkResult &result)
+void Adapter::handleDisconnect(const TrkResult &result)
 {
     logMessage("   HANDLE DISCONNECT: " + stringFromArray(result.data));
      //if (result.result.token)
         //logMessage("   ERROR: " + byte(result.result.token)
-    //    sendTrkMessage(0x18, CB(handleTrkContinue),
+    //    sendTrkMessage(0x18, CB(handleContinue),
     //        formatInt(m_session.pid) + formatInt(m_session.tid));
     //}
 }
 
-void Adapter::handleTrkDeleteProcess(const TrkResult &result)
+void Adapter::handleDeleteProcess(const TrkResult &result)
 {
     logMessage("   HANDLE DELETE PROCESS: " + stringFromArray(result.data));
     //if (result.result.token)
         //logMessage("   ERROR: " + byte(result.token)
-    //    sendTrkMessage(0x18, CB(handleTrkContinue),
+    //    sendTrkMessage(0x18, CB(handleContinue),
     //        formatInt(m_session.pid) + formatInt(m_session.tid));
     //}
 }
 
-void Adapter::handleTrkStep(const TrkResult &result)
+void Adapter::handleStep(const TrkResult &result)
 {
     logMessage("   HANDLE STEP: " + stringFromArray(result.data));
 }
 
-void Adapter::handleTrkStop(const TrkResult &result)
+void Adapter::handleStop(const TrkResult &result)
 {
     logMessage("   HANDLE STOP: " + stringFromArray(result.data));
 }
 
 
-void Adapter::handleTrkReadInfo(const TrkResult &result)
+void Adapter::handleReadInfo(const TrkResult &result)
 {
     logMessage("   HANDLE READ INFO: " + stringFromArray(result.data));
 }
 
-void Adapter::handleTrkWaitForFinished(const TrkResult &result)
+void Adapter::handleWaitForFinished(const TrkResult &result)
 {
     logMessage("   FINISHED: " + stringFromArray(result.data));
     //qApp->exit(1);
 }
 
-void Adapter::handleTrkSupportMask(const TrkResult &result)
+void Adapter::handleSupportMask(const TrkResult &result)
 {
     const char *data = result.data.data();
     QByteArray str;
@@ -935,7 +1054,7 @@ void Adapter::handleTrkSupportMask(const TrkResult &result)
         //str.append("  [" + formatByte(data[i]) + "]: ");
         for (int j = 0; j < 8; ++j)
         if (data[i] & (1 << j))
-            str.append(formatByte(i * 8 + j));
+            str.append(QByteArray::number(i * 8 + j, 16));
     }
     logMessage("SUPPORTED: " + str);
 }
@@ -949,8 +1068,12 @@ void Adapter::cleanUp()
     //  Sub Cmd: Delete Process
     //ProcessID: 0x0000071F (1823)
     // [41 24 00 00 00 00 07 1F]
-    sendTrkMessage(0x41, CB(handleTrkDeleteProcess),
-        "00 00 " + formatInt(m_session.pid));
+    QByteArray ba;
+    appendByte(&ba, 0x00);
+    appendByte(&ba, 0x00);
+    appendInt(&ba, m_session.pid);
+    sendTrkMessage(0x41, CB(handleDeleteProcess), ba);
+
     //---TRK------------------------------------------------------
     //  Command: 0x80 Acknowledge
     //    Error: 0x00
@@ -988,12 +1111,38 @@ void Adapter::cleanUp()
     //---IDE------------------------------------------------------
     //  Command: 0x02 Disconnect
     // [02 27]
-    sendTrkMessage(0x02, CB(handleTrkDisconnect));
+    sendTrkMessage(0x02, CB(handleDisconnect));
     //---TRK------------------------------------------------------
     //  Command: 0x80 Acknowledge
     // Error: 0x00
 }
 
+void Adapter::readMemory(uint addr, uint len)
+{
+    Q_ASSERT(len < (2 << 16));
+
+    // We try to get medium-sized chunks of data from the device
+
+    QList <uint> blocksToFetch;
+    uint blockaddr = (addr / memoryChunkSize) * memoryChunkSize;
+    for (; blockaddr < addr + len; blockaddr += memoryChunkSize) {
+        QByteArray blockdata = m_snapshot.memory[blockaddr];
+        if (blockdata.isEmpty()) {
+            // fetch it
+            QByteArray ba;
+            appendByte(&ba, 0x08); // Options, FIXME: why?
+            appendShort(&ba, memoryChunkSize);
+            appendInt(&ba, blockaddr);
+            appendInt(&ba, m_session.pid);
+            appendInt(&ba, m_session.tid);
+            // Read Memory
+            sendTrkMessage(0x10, CB(handleReadMemory), ba, QVariant(blockaddr));
+        }
+    }
+    qulonglong cookie = (qulonglong(addr) << 32) + len;
+    sendTrkMessage(TRK_SYNC, CB(reportReadMemory), QByteArray(), cookie);
+}
+
 int main(int argc, char *argv[])
 {
     if (argc < 3) {
diff --git a/tests/manual/trk/run.sh b/tests/manual/trk/run.sh
index 3e84db45ff3..f3aeba72173 100755
--- a/tests/manual/trk/run.sh
+++ b/tests/manual/trk/run.sh
@@ -5,11 +5,14 @@ make || exit 1
 killall -s USR1 adapter trkserver > /dev/null 2>&1
 killall adapter trkserver > /dev/null 2>&1
 
-trkservername="TRKSERVER-3";
+trkservername="TRKSERVER-4";
 gdbserverip=127.0.0.1
-gdbserverport=2225
+gdbserverport=2226
 replaysource=dump.txt
 
+fuser -n tcp -k ${gdbserverport} 
+rm /tmp/${trkservername}
+
 ./trkserver ${trkservername} ${replaysource} &
 trkserverpid=$!
 
diff --git a/tests/manual/trk/trkserver.cpp b/tests/manual/trk/trkserver.cpp
index cc8cbf59e70..ce3e6fb18fe 100644
--- a/tests/manual/trk/trkserver.cpp
+++ b/tests/manual/trk/trkserver.cpp
@@ -59,6 +59,23 @@ using namespace trk;
 // [80 02 00 7E 00 4F 5F 01 00 00 00 0F 1F 00 00 00
 //  00 00 00 01 00 11 00 03 00 00 00 00 00 03 00 00...]
 
+struct Inferior
+{
+    Inferior();
+    uint pid;
+    uint tid;
+    uint codeseg;
+    uint dataseg;
+};
+
+Inferior::Inferior()
+{
+    pid = 0x000008F5;
+    tid = 0x000008F6;
+    codeseg = 0x78674000;
+    dataseg = 0x00400000;
+}
+
 class TrkServer : public QObject
 {
     Q_OBJECT
@@ -90,6 +107,7 @@ private:
     QLocalServer m_server;
     int m_lastSent;
     QLocalSocket *m_adapterConnection;
+    Inferior m_inferior;
 };
 
 TrkServer::TrkServer()
@@ -187,6 +205,39 @@ void TrkServer::handleAdapterMessage(const TrkResult &result)
             writeToAdapter(0x80, result.token, data);
             break;
         }
+        case 0x10: { // Read Memory
+            const char *p = result.data.data();
+            byte option = p[0];
+            Q_UNUSED(option);
+            ushort len = extractShort(p + 1);
+            uint addr = extractInt(p + 3); 
+            qDebug() << "ADDR: " << QByteArray::number(addr, 16) << " "
+                << QByteArray::number(len, 16);
+            for (int i = 0; i != len; ++i)
+                appendByte(&data, i);
+            writeToAdapter(0x80, result.token, data);
+            break;
+        }
+        case 0x12: { // Read Registers
+            appendInt(&data, 0x00000000, BigEndian);
+            appendInt(&data, 0xC924FFBC, BigEndian);
+            appendInt(&data, 0x00000000, BigEndian);
+            appendInt(&data, 0x00600000, BigEndian);
+            appendInt(&data, 0x78677970, BigEndian);
+            for (int i = 5; i < registerCount - 1; ++i)
+                appendInt(&data, i + (i << 16), BigEndian);
+            appendInt(&data, 0x78676B00, BigEndian);
+            writeToAdapter(0x80, result.token, data);
+            break;
+        }
+        case 0x40: { // Create Item
+            appendInt(&data, m_inferior.pid, BigEndian);
+            appendInt(&data, m_inferior.tid, BigEndian);
+            appendInt(&data, m_inferior.codeseg, BigEndian);
+            appendInt(&data, m_inferior.dataseg, BigEndian);
+            writeToAdapter(0x80, result.token, data);
+            break;
+        }
         default:
             data[0] = 0x10; // Command not supported
             writeToAdapter(0xff, result.token, data);
diff --git a/tests/manual/trk/trkutils.cpp b/tests/manual/trk/trkutils.cpp
index 681dcaefd25..8a3b67a9f39 100644
--- a/tests/manual/trk/trkutils.cpp
+++ b/tests/manual/trk/trkutils.cpp
@@ -117,7 +117,7 @@ TrkResult extractResult(QByteArray *buffer)
 
     result.code = data.at(0);
     result.token = data.at(1);
-    result.data = data.mid(2);
+    result.data = data.mid(2, data.size() - 3);
     //logMessage("   REST BUF: " << stringFromArray(*buffer));
     //logMessage("   CURR DATA: " << stringFromArray(data));
     //QByteArray prefix = "READ BUF:                                       ";
@@ -127,15 +127,15 @@ TrkResult extractResult(QByteArray *buffer)
 
 ushort extractShort(const char *data)
 {
-    return data[0] * 256 + data[1];
+    return byte(data[0]) * 256 + byte(data[1]);
 }
 
 uint extractInt(const char *data)
 {
-    uint res = data[0];
-    res *= 256; res += data[1];
-    res *= 256; res += data[2];
-    res *= 256; res += data[3];
+    uint res = byte(data[0]);
+    res *= 256; res += byte(data[1]);
+    res *= 256; res += byte(data[2]);
+    res *= 256; res += byte(data[3]);
     return res;
 }
 
@@ -213,38 +213,47 @@ QString stringFromArray(const QByteArray &ba)
     return str + "  " + ascii;
 }
 
-
-QByteArray formatByte(byte b)
+void appendByte(QByteArray *ba, byte b)
 {
-    char buf[30];
-    qsnprintf(buf, sizeof(buf) - 1, "%x ", b);
-    return buf;
+    ba->append(b);
 }
 
-QByteArray formatShort(ushort s)
+void appendShort(QByteArray *ba, ushort s, Endianness endian)
 {
-    char buf[30];
-    qsnprintf(buf, sizeof(buf) - 1, "%x %x ", s / 256, s % 256);
-    return buf;
+    if (endian == BigEndian) {
+        ba->append(s / 256);
+        ba->append(s % 256);
+    } else {
+        ba->append(s % 256);
+        ba->append(s / 256);
+    }
 }
 
-QByteArray formatInt(uint i)
+void appendInt(QByteArray *ba, uint i, Endianness endian)
 {
-    char buf[30];
     int b3 = i % 256; i -= b3; i /= 256;
     int b2 = i % 256; i -= b2; i /= 256;
     int b1 = i % 256; i -= b1; i /= 256;
     int b0 = i % 256; i -= b0; i /= 256;
-    qsnprintf(buf, sizeof(buf) - 1, "%x %x %x %x ", b0, b1, b2, b3);
-    return buf;
+    if (endian == BigEndian) {
+        ba->append(b3);
+        ba->append(b2);
+        ba->append(b1);
+        ba->append(b0);
+    } else {
+        ba->append(b0);
+        ba->append(b1);
+        ba->append(b2);
+        ba->append(b3);
+    }
 }
 
-QByteArray formatString(const QByteArray &str)
+void appendString(QByteArray *ba, const QByteArray &str, Endianness endian)
 {
-    QByteArray ba = formatShort(str.size());
-    foreach (byte b, str)
-        ba.append(formatByte(b));
-    return ba;
+    const int n = str.size();
+    appendShort(ba, n, endian);
+    for (int i = 0; i != n; ++i)
+        ba->append(str.at(i));
 }
 
 QByteArray errorMessage(byte code)
diff --git a/tests/manual/trk/trkutils.h b/tests/manual/trk/trkutils.h
index 8632541a45f..81e50c66147 100644
--- a/tests/manual/trk/trkutils.h
+++ b/tests/manual/trk/trkutils.h
@@ -33,6 +33,7 @@
 #include <QtCore/QByteArray>
 #include <QtCore/QHash>
 #include <QtCore/QString>
+#include <QtCore/QVariant>
 
 namespace trk {
 
@@ -51,10 +52,17 @@ QString stringFromByte(byte c);
 // produces "xx xx xx "
 QString stringFromArray(const QByteArray &ba);
 
-QByteArray formatByte(byte b);
-QByteArray formatShort(ushort s);
-QByteArray formatInt(uint i);
-QByteArray formatString(const QByteArray &str);
+enum Endianness
+{
+    LittleEndian,
+    BigEndian,
+    TargetByteOrder = BigEndian,
+};
+
+void appendByte(QByteArray *ba, byte b);
+void appendShort(QByteArray *ba, ushort s, Endianness = TargetByteOrder);
+void appendInt(QByteArray *ba, uint i, Endianness = TargetByteOrder);
+void appendString(QByteArray *ba, const QByteArray &str, Endianness = TargetByteOrder);
 
 enum CodeMode
 {
@@ -62,6 +70,12 @@ enum CodeMode
     ThumbMode,
 };
 
+enum TargetConstants
+{
+    registerCount = 16,
+    memoryChunkSize = 256
+};
+
 struct Session
 {
     Session() {
@@ -76,8 +90,11 @@ struct Session
         tid = 0;
         codeseg = 0;
         dataseg = 0;
+
+        currentThread = 0;
     }
 
+    // Trk feedback
     byte cpuMajor;
     byte cpuMinor;
     byte bigEndian;
@@ -90,6 +107,16 @@ struct Session
     uint codeseg;
     uint dataseg;
     QHash<uint, uint> tokenToBreakpointIndex;
+
+    // Gdb request
+    uint currentThread;
+};
+
+struct SnapShot
+{
+    uint registers[registerCount];
+    typedef QHash<uint, QByteArray> Memory;
+    Memory memory;
 };
 
 struct Breakpoint
@@ -113,6 +140,7 @@ struct TrkResult
     byte code;
     byte token;
     QByteArray data;
+    QVariant cookie;
 };
 
 // returns a QByteArray containing 0x01 0x90 <len> 0x7e encoded7d(ba) 0x7e
-- 
GitLab