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