diff --git a/src/plugins/debugger/gdb/gdbengine.h b/src/plugins/debugger/gdb/gdbengine.h index 41137705879d749e5228d5c7c1215f448a82ea95..c8ff6a6698d5cf83142379b3097d56134896d99f 100644 --- a/src/plugins/debugger/gdb/gdbengine.h +++ b/src/plugins/debugger/gdb/gdbengine.h @@ -210,6 +210,7 @@ private: void handleAsyncOutput(const GdbMi &data); void handleResultRecord(const GdbResultRecord &response); void handleFileExecAndSymbols(const GdbResultRecord &response, const QVariant &); + void handleExecContinue(const GdbResultRecord &response, const QVariant &); void handleExecRun(const GdbResultRecord &response, const QVariant &); void handleExecJumpToLine(const GdbResultRecord &response, const QVariant &); void handleExecRunToFunction(const GdbResultRecord &response, const QVariant &); diff --git a/tests/manual/trk/README b/tests/manual/trk/README new file mode 100644 index 0000000000000000000000000000000000000000..9428873eabf3510bc1f240d5dc1f961d46835284 --- /dev/null +++ b/tests/manual/trk/README @@ -0,0 +1,2 @@ +Run ./run.sh in one terminal. +Run ./gdb-symbian in a second terminal. diff --git a/tests/manual/trk/adapter.cpp b/tests/manual/trk/adapter.cpp index a9e53d082be3f301b84e31c76d437ebd4a4c516a..bb63735acb621e5ad3252afb09692892099d95bd 100644 --- a/tests/manual/trk/adapter.cpp +++ b/tests/manual/trk/adapter.cpp @@ -112,6 +112,7 @@ private: void handleSetBreakpoint(const TrkResult &result); void handleClearBreakpoint(const TrkResult &result); void handleContinue(const TrkResult &result); + void handleSignalContinue(const TrkResult &result); void handleReadInfo(const TrkResult &result); void handleWaitForFinished(const TrkResult &result); void handleStep(const TrkResult &result); @@ -359,7 +360,21 @@ void Adapter::writeToGdb(const QByteArray &msg, const QByteArray &logNote) void Adapter::handleGdbResponse(const QByteArray &response) { // http://sourceware.org/gdb/current/onlinedocs/gdb_34.html - if (response == "g") { + + if (0) {} + + else if (response.startsWith("C")) { + // C sig[;addr] Continue with signal sig (hex signal number) + //Reply: See section D.3 Stop Reply Packets, for the reply specifications. + bool ok = false; + uint signalNumber = response.mid(1).toInt(&ok, 16); + QByteArray ba; + appendInt(&ba, m_session.pid); + appendInt(&ba, m_session.tid); + sendTrkMessage(0x18, CB(handleSignalContinue), ba, signalNumber); // Continue + } + + else if (response == "g") { // Read general registers. //writeToGdb("00000000", "read registers"); QByteArray ba; @@ -392,20 +407,68 @@ void Adapter::handleGdbResponse(const QByteArray &response) + QByteArray::number(m_session.currentThread)); } + else if (response == "k") { + // kill + QByteArray ba; + appendByte(&ba, 0); // Sub-command: Delete Process + appendInt(&ba, m_session.pid); + sendTrkMessage(0x41, CB(handleDeleteProcess), ba); // Delete Item + } + 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); + //qDebug() << "GDB ADDR: " << hexNumber(addr) << " " << hexNumber(len); readMemory(addr, len); } - else if (response == "pf") { - // current instruction pointer? - writeToGdb("0000", "current IP"); + else if (response.startsWith("p")) { + // 0xf == current instruction pointer? + //writeToGdb("0000", "current IP"); + #if 0 + A1 = 0, first integer-like argument + A4 = 3, last integer-like argument + AP = 11, + IP = 12, + SP = 13, Contains address of top of stack + LR = 14, address to return to from a function call + PC = 15, Contains program counter + F0 = 16, first floating point register + F3 = 19, last floating point argument register + F7 = 23, last floating point register + FPS = 24, floating point status register + PS = 25, Contains processor status + WR0, WMMX data registers. + WR15 = WR0 + 15, + WC0, WMMX control registers. + WCSSF = WC0 + 2, + WCASF = WC0 + 3, + WC7 = WC0 + 7, + WCGR0, WMMX general purpose registers. + WCGR3 = WCGR0 + 3, + WCGR7 = WCGR0 + 7, + NUM_REGS, + + // Other useful registers. + FP = 11, Frame register in ARM code, if used. + THUMB_FP = 7, Frame register in Thumb code, if used. + NUM_ARG_REGS = 4, + LAST_ARG = A4, + NUM_FP_ARG_REGS = 4, + LAST_FP_ARG = F3 + #endif + bool ok = false; + uint registerNumber = response.mid(1).toInt(&ok, 16); + if (registerNumber < registerCount) { + QByteArray ba; + appendInt(&ba, m_snapshot.registers[registerNumber]); + writeToGdb(ba.toHex(), "read single known register"); + } else { + writeToGdb("0000", "read single unknown register"); + } } else if (response == "qAttached") { @@ -438,6 +501,12 @@ void Adapter::handleGdbResponse(const QByteArray &response) writeToGdb(QByteArray()); } + else if (response == "qSymbol::") { + // Notify the target that GDB is prepared to serve symbol lookup requests. + writeToGdb("OK", "no further symbols needed"); + //writeToGdb("qSymbol:" + QByteArray("_Z7E32Mainv").toHex(), "ask for more"); + } + else if (response == "QStartNoAckMode") { //$qSupported#37 //logMessage("Handling 'QStartNoAckMode'"); @@ -445,6 +514,16 @@ void Adapter::handleGdbResponse(const QByteArray &response) m_gdbAckMode = false; } + else if (response == "vCont?") { + // actions supported by the vCont packet + writeToGdb(""); + //writeToGdb("vCont;c"); + } + + //else if (response.startsWith("vCont")) { + // // vCont[;action[:thread-id]]...' + //} + else if (response.startsWith("?")) { // Indicate the reason the target halted. // The reply is the same as for step and continue. @@ -506,7 +585,7 @@ void Adapter::timerEvent(QTimerEvent *) tryTrkRead(); } -unsigned char Adapter::nextTrkWriteToken() +byte Adapter::nextTrkWriteToken() { ++m_trkWriteToken; if (m_trkWriteToken == 0) @@ -881,18 +960,7 @@ 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 + QByteArray ba = result.data.toHex(); writeToGdb(ba, "register contents"); } @@ -903,7 +971,7 @@ void Adapter::handleReadMemory(const TrkResult &result) uint blockaddr = result.cookie.toInt(); //qDebug() << "READING " << ba.size() << " BYTES: " // << quoteUnprintableLatin1(ba) - // << "ADDR: " << QByteArray::number(blockaddr, 16) + // << "ADDR: " << hexNumber(blockaddr) // << "COOKIE: " << result.cookie; m_snapshot.memory[blockaddr] = ba; } @@ -924,7 +992,7 @@ void Adapter::reportReadMemory(const TrkResult &result) ba = ba.mid(addr % memoryChunkSize, len); // qDebug() << "REPORTING MEMORY " << ba.size() - // << " ADDR: " << QByteArray::number(blockaddr, 16) << " LEN: " << len + // << " ADDR: " << hexNumber(blockaddr) << " LEN: " << len // << " BYTES: " << quoteUnprintableLatin1(ba); writeToGdb(ba.toHex(), "memory contents"); @@ -994,34 +1062,28 @@ void Adapter::handleClearBreakpoint(const TrkResult &result) logMessage("CLEAR BREAKPOINT "); } +void Adapter::handleSignalContinue(const TrkResult &result) +{ + int signalNumber = result.cookie.toInt(); + logMessage(" HANDLE SIGNAL CONTINUE: " + stringFromArray(result.data)); + qDebug() << "NUMBER" << signalNumber; + writeToGdb("O" + QByteArray("Console output").toHex()); + writeToGdb("W81"); // "Process exited with result 1 +} + 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(handleContinue), - // formatInt(m_session.pid) + formatInt(m_session.tid)); - //} } 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(handleContinue), - // formatInt(m_session.pid) + formatInt(m_session.tid)); - //} } 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(handleContinue), - // formatInt(m_session.pid) + formatInt(m_session.tid)); - //} } void Adapter::handleStep(const TrkResult &result) diff --git a/tests/manual/trk/run.sh b/tests/manual/trk/run.sh index f3aeba721735717a6f633374644755dabfd64032..6d1eb1421498751527e0a512e8920d19ead7ff28 100755 --- a/tests/manual/trk/run.sh +++ b/tests/manual/trk/run.sh @@ -8,12 +8,12 @@ killall adapter trkserver > /dev/null 2>&1 trkservername="TRKSERVER-4"; gdbserverip=127.0.0.1 gdbserverport=2226 -replaysource=dump.txt +memorydump=TrkDump-78-6a-40-00.bin fuser -n tcp -k ${gdbserverport} rm /tmp/${trkservername} -./trkserver ${trkservername} ${replaysource} & +./trkserver ${trkservername} ${memorydump} & trkserverpid=$! sleep 1 @@ -22,19 +22,13 @@ sleep 1 adapterpid=$! echo " +# This is generated. Changes will be lost. set remote noack-packet on +set endian big target remote ${gdbserverip}:${gdbserverport} file filebrowseapp.sym -quit -" > gdb.txt - -./arm-gdb -x gdb.txt - -#sleep 4 - -kill -s USR1 ${adapterpid} -kill -s USR1 ${trkserverpid} - -echo +" > .gdbinit +#kill -s USR1 ${adapterpid} +#kill -s USR1 ${trkserverpid} #killall arm-gdb diff --git a/tests/manual/trk/trkserver.cpp b/tests/manual/trk/trkserver.cpp index ce3e6fb18feb77fcda5900ac31fe5280b0683ed6..48ce6c3aff5056c920c3fa12d204ef046542039e 100644 --- a/tests/manual/trk/trkserver.cpp +++ b/tests/manual/trk/trkserver.cpp @@ -72,7 +72,7 @@ Inferior::Inferior() { pid = 0x000008F5; tid = 0x000008F6; - codeseg = 0x78674000; + codeseg = 0x786A4000; dataseg = 0x00400000; } @@ -85,7 +85,7 @@ public: ~TrkServer(); void setServerName(const QString &name) { m_serverName = name; } - void setReplaySource(const QString &source) { m_replaySource = source; } + void setMemoryDumpName(const QString &source) { m_memoryDumpName = source; } void startServer(); private slots: @@ -97,22 +97,25 @@ private slots: private: void logMessage(const QString &msg); + byte nextNotificationToken(); QString m_serverName; - QString m_replaySource; + QString m_memoryDumpName; QByteArray m_adapterReadBuffer; - QList<QByteArray> m_replayData; + QByteArray m_memoryData; QLocalServer m_server; int m_lastSent; QLocalSocket *m_adapterConnection; Inferior m_inferior; + byte m_notificationToken; }; TrkServer::TrkServer() { m_adapterConnection = 0; + m_notificationToken = 0; } TrkServer::~TrkServer() @@ -123,13 +126,13 @@ TrkServer::~TrkServer() void TrkServer::startServer() { - QFile file(m_replaySource); + QFile file(m_memoryDumpName); file.open(QIODevice::ReadOnly); - m_replayData = file.readAll().split('\n'); + m_memoryData = file.readAll(); file.close(); - logMessage(QString("Read %1 lines of data from %2") - .arg(m_replayData.size()).arg(m_replaySource)); + logMessage(QString("Read %1 bytes of data from %2") + .arg(m_memoryData.size()).arg(m_memoryDumpName)); m_lastSent = 0; if (!m_server.listen(m_serverName)) { @@ -149,26 +152,11 @@ void TrkServer::logMessage(const QString &msg) void TrkServer::handleConnection() { - //QByteArray block; - - //QByteArray msg = m_replayData[m_lastSent ++]; - - //QDataStream out(&block, QIODevice::WriteOnly); - //out.setVersion(QDataStream::Qt_4_0); - //out << (quint16)0; - //out << m_replayData; - //out.device()->seek(0); - //out << (quint16)(block.size() - sizeof(quint16)); - m_adapterConnection = m_server.nextPendingConnection(); connect(m_adapterConnection, SIGNAL(disconnected()), m_adapterConnection, SLOT(deleteLater())); connect(m_adapterConnection, SIGNAL(readyRead()), this, SLOT(readFromAdapter())); - - //m_adapterConnection->write(block); - //m_adapterConnection->flush(); - //m_adapterConnection->disconnectFromHost(); } void TrkServer::readFromAdapter() @@ -198,6 +186,7 @@ void TrkServer::handleAdapterMessage(const TrkResult &result) data.append(char(0x00)); // No error switch (result.code) { case 0x00: { // Ping + m_notificationToken = 0; writeToAdapter(0x80, 0x00, data); break; } @@ -211,25 +200,58 @@ void TrkServer::handleAdapterMessage(const TrkResult &result) Q_UNUSED(option); ushort len = extractShort(p + 1); uint addr = extractInt(p + 3); - qDebug() << "ADDR: " << QByteArray::number(addr, 16) << " " - << QByteArray::number(len, 16); + //qDebug() << "MESSAGE: " << result.data.toHex(); + qDebug() << "ADDR: " << hexNumber(addr) << " " << hexNumber(len); + if (addr < m_inferior.codeseg + || addr + len >= m_inferior.codeseg + m_memoryData.size()) { + qDebug() << "ADDRESS OUTSIDE CODESEG: " << hexNumber(addr) + << hexNumber(m_inferior.codeseg); + for (int i = 0; i != len / 4; ++i) + appendInt(&data, 0xDEADBEEF); + } for (int i = 0; i != len; ++i) - appendByte(&data, i); + appendByte(&data, m_memoryData[addr - m_inferior.codeseg + i]); writeToAdapter(0x80, result.token, data); break; } case 0x12: { // Read Registers - appendInt(&data, 0x00000000, BigEndian); - appendInt(&data, 0xC924FFBC, BigEndian); + appendByte(&data, 0x00); + appendByte(&data, 0x00); + appendByte(&data, 0x00); + appendInt(&data, 0xC92D7FBC, 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); + appendInt(&data, 0x00000000, BigEndian); + appendInt(&data, 0x786A7970, BigEndian); + appendInt(&data, 0x00000000, BigEndian); + appendInt(&data, 0x00000000, BigEndian); + appendInt(&data, 0x00000012, BigEndian); + appendInt(&data, 0x00000040, BigEndian); + appendInt(&data, 0xC82AF210, BigEndian); + appendInt(&data, 0x00000000, BigEndian); + appendInt(&data, 0xC8000548, BigEndian); + appendInt(&data, 0x00403ED0, BigEndian); + appendInt(&data, 0x786A6BD8, BigEndian); + appendInt(&data, 0x786A4CC8, BigEndian); + appendInt(&data, 0x68000010, BigEndian); writeToAdapter(0x80, result.token, data); break; } + case 0x18: { // Continue + writeToAdapter(0x80, result.token, data); // ACK Package + + if (0) { // Fake "Stop" + QByteArray note; + appendInt(¬e, 0); // FIXME: use proper address + appendInt(¬e, m_inferior.pid); + appendInt(¬e, m_inferior.tid); + appendByte(¬e, 0x00); + appendByte(¬e, 0x00); + writeToAdapter(0x90, nextNotificationToken(), note); + } + + break; + } case 0x40: { // Create Item appendInt(&data, m_inferior.pid, BigEndian); appendInt(&data, m_inferior.tid, BigEndian); @@ -238,6 +260,20 @@ void TrkServer::handleAdapterMessage(const TrkResult &result) writeToAdapter(0x80, result.token, data); break; } + case 0x41: { // Delete Item + writeToAdapter(0x80, result.token, data); + + // A Process? + // Command: 0xA1 Notify Deleted + //[A1 02 00 00 00 00 00 00 00 00 01 B5] + QByteArray note; // FIXME + appendByte(¬e, 0); + appendByte(¬e, 0); + appendInt(¬e, 0); + appendInt(¬e, m_inferior.pid); + writeToAdapter(0xA1, nextNotificationToken(), note); + break; + } default: data[0] = 0x10; // Command not supported writeToAdapter(0xff, result.token, data); @@ -246,6 +282,14 @@ void TrkServer::handleAdapterMessage(const TrkResult &result) } +byte TrkServer::nextNotificationToken() +{ + ++m_notificationToken; + if (m_notificationToken == 0) + ++m_notificationToken; + return m_notificationToken; +} + int main(int argc, char *argv[]) { if (argc < 3) { @@ -262,7 +306,7 @@ int main(int argc, char *argv[]) TrkServer server; server.setServerName(argv[1]); - server.setReplaySource(argv[2]); + server.setMemoryDumpName(argv[2]); server.startServer(); return app.exec(); diff --git a/tests/manual/trk/trkutils.cpp b/tests/manual/trk/trkutils.cpp index 8a3b67a9f39e0ef7cedea4c32f1e05e3dd73fcc7..3ab9d57d0f2c8672316f4658499fd732ff0f2b9f 100644 --- a/tests/manual/trk/trkutils.cpp +++ b/tests/manual/trk/trkutils.cpp @@ -35,6 +35,11 @@ namespace trk { +QByteArray hexNumber(uint n) +{ + return QByteArray::number(n, 16); +} + QString TrkResult::toString() const { QString res = stringFromByte(code) + "[" + stringFromByte(token); @@ -236,15 +241,15 @@ void appendInt(QByteArray *ba, uint i, Endianness endian) int b1 = i % 256; i -= b1; i /= 256; int b0 = i % 256; i -= b0; i /= 256; 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); + } else { + ba->append(b3); + ba->append(b2); + ba->append(b1); + ba->append(b0); } } diff --git a/tests/manual/trk/trkutils.h b/tests/manual/trk/trkutils.h index 81e50c66147249ececeb431146d53ea014fcc06d..2bb3965a7b0ce81db9557d81b040500f30605f59 100644 --- a/tests/manual/trk/trkutils.h +++ b/tests/manual/trk/trkutils.h @@ -72,7 +72,7 @@ enum CodeMode enum TargetConstants { - registerCount = 16, + registerCount = 17, memoryChunkSize = 256 }; @@ -147,6 +147,7 @@ struct TrkResult QByteArray frameMessage(byte command, byte token, const QByteArray &data); TrkResult extractResult(QByteArray *buffer); QByteArray errorMessage(byte code); +QByteArray hexNumber(uint n); } // namespace trk