diff --git a/tests/manual/trk/adapter.cpp b/tests/manual/trk/adapter.cpp index 4b69fa16b3348321f8250a147ca4d8a62a2a1f01..70910f8ed8a5bc998049cacfbb7892f65937a9c0 100644 --- a/tests/manual/trk/adapter.cpp +++ b/tests/manual/trk/adapter.cpp @@ -32,6 +32,7 @@ #include <QtCore/QCoreApplication> #include <QtCore/QQueue> #include <QtCore/QTimer> +#include <QtCore/QStringList> #include <QtNetwork/QTcpServer> #include <QtNetwork/QTcpSocket> @@ -57,6 +58,41 @@ using namespace trk; enum { TRK_SYNC = 0x7f }; + +enum { KnownRegisters = RegisterPSGdb + 1}; + +static const char *registerNames[KnownRegisters] = +{ + "A1", "A2", "A3", "A4", + 0, 0, 0, 0, + 0, 0, 0, "AP", + "IP", "SP", "LR", "PC", + "PSTrk", 0, 0, 0, + 0, 0, 0, 0, + 0, "PSGdb" +}; + +static inline void dumpRegister(int n, uint value, QByteArray &a) +{ + a += ' '; + if (n < KnownRegisters && registerNames[n]) { + a += registerNames[n]; + } else { + a += '#'; + a += QByteArray::number(n); + } + a += "=0x"; + a += QByteArray::number(value, 16); +} + +struct AdapterOptions { + AdapterOptions() : verbose(1) {} + + int verbose; + QString gdbServer; + QString trkServer; +}; + #define CB(s) &Adapter::s class Adapter : public QObject @@ -68,6 +104,7 @@ public: ~Adapter(); void setGdbServerName(const QString &name); void setTrkServerName(const QString &name) { m_trkServerName = name; } + void setVerbose(int verbose) { m_verbose = verbose; } bool startServer(); private: @@ -78,7 +115,7 @@ private: typedef void (Adapter::*TrkCallBack)(const TrkResult &); - struct TrkMessage + struct TrkMessage { TrkMessage() { code = token = 0; callBack = 0; } byte code; @@ -160,7 +197,7 @@ private: void sendGdbAckMessage(); // - void logMessage(const QString &msg); + void logMessage(const QString &msg, bool force = false); QTcpServer m_gdbServer; QTcpSocket *m_gdbConnection; @@ -172,6 +209,7 @@ private: // Debuggee state Session m_session; // global-ish data (process id, target information) Snapshot m_snapshot; // local-ish data (memory and registers) + int m_verbose; }; Adapter::Adapter() @@ -207,7 +245,7 @@ Adapter::~Adapter() // Gdb m_gdbServer.close(); //>disconnectFromServer(); - logMessage("Shutting down.\n"); + logMessage("Shutting down.\n", true); } void Adapter::setGdbServerName(const QString &name) @@ -225,7 +263,7 @@ void Adapter::setGdbServerName(const QString &name) bool Adapter::startServer() { if (!openTrkPort(m_trkServerName)) { - logMessage("Unable to connect to TRK server"); + logMessage("Unable to connect to TRK server " + m_trkServerName + " " +m_trkDevice->errorString(), true); return false; } @@ -244,21 +282,22 @@ bool Adapter::startServer() 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) - .arg(m_gdbServer.errorString())); + .arg(m_gdbServer.errorString()), true); return false; } - logMessage(QString("Gdb server running on port %1. Run arm-gdb now.") - .arg(m_gdbServer.serverPort())); + logMessage(QString("Gdb server running on %1:%2. Run arm-gdb now.") + .arg(m_gdbServerName).arg(m_gdbServer.serverPort()), true); connect(&m_gdbServer, SIGNAL(newConnection()), this, SLOT(handleGdbConnection())); return true; } -void Adapter::logMessage(const QString &msg) +void Adapter::logMessage(const QString &msg, bool force) { - qDebug() << "ADAPTER: " << qPrintable(msg); + if (m_verbose || force) + qDebug("ADAPTER: %s ", qPrintable(msg)); } // @@ -306,7 +345,7 @@ void Adapter::readFromGdb() } if (code != '$') { - logMessage("Broken package (2) " + quoteUnprintableLatin1(ba) + logMessage("Broken package (2) " + quoteUnprintableLatin1(ba) + hexNumber(code)); continue; } @@ -436,7 +475,7 @@ void Adapter::handleGdbResponse(const QByteArray &response) 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. + //Reply: See section D.3 Stop Reply Packets, for the reply specifications. sendGdbAckMessage(); bool ok = false; uint signalNumber = response.mid(1).toInt(&ok, 16); @@ -466,7 +505,7 @@ void Adapter::handleGdbResponse(const QByteArray &response) appendByte(&ba, RegisterCount - 1); // last register appendInt(&ba, m_session.pid); appendInt(&ba, m_session.tid); - + sendTrkMessage(0x12, CB(handleAndReportReadRegisters), ba); } @@ -526,37 +565,40 @@ void Adapter::handleGdbResponse(const QByteArray &response) F7 = 23, last floating point register FPS = 24, floating point status register PS = 25, Contains processor status - WR0, WMMX data registers. + WR0, WMMX data registers. WR15 = WR0 + 15, - WC0, WMMX control registers. + WC0, WMMX control registers. WCSSF = WC0 + 2, WCASF = WC0 + 3, WC7 = WC0 + 7, - WCGR0, WMMX general purpose registers. + 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, + // 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); + const uint registerNumber = response.mid(1).toInt(&ok, 16); + QByteArray logMsg = "read register"; if (registerNumber == RegisterPSGdb) { QByteArray ba; appendInt(&ba, m_snapshot.registers[RegisterPSTrk]); - sendGdbMessage(ba.toHex(), "read processor status register"); + dumpRegister(registerNumber, m_snapshot.registers[RegisterPSTrk], logMsg); + sendGdbMessage(ba.toHex(), logMsg); } else if (registerNumber < RegisterCount) { QByteArray ba; appendInt(&ba, m_snapshot.registers[registerNumber]); - sendGdbMessage(ba.toHex(), "read single known register"); + dumpRegister(registerNumber, m_snapshot.registers[registerNumber], logMsg); + sendGdbMessage(ba.toHex(), logMsg); } else { - sendGdbMessage("0000", "read single unknown register"); + sendGdbMessage("0000", "read single unknown register #" + QByteArray::number(registerNumber)); //sendGdbMessage("E01", "read single unknown register"); } } @@ -584,7 +626,7 @@ void Adapter::handleGdbResponse(const QByteArray &response) //$qSupported:multiprocess+#c6 //logMessage("Handling 'qSupported'"); sendGdbAckMessage(); - if (0) + if (0) sendGdbMessage(QByteArray(), "nothing supported"); else sendGdbMessage( @@ -601,7 +643,7 @@ void Adapter::handleGdbResponse(const QByteArray &response) sendGdbAckMessage(); sendGdbMessage("", "FIXME: nothing?"); } - + else if (response == "qOffsets") { sendGdbAckMessage(); startInferiorIfNeeded(); @@ -1093,7 +1135,12 @@ void Adapter::handleAndReportReadRegisters(const TrkResult &result) QByteArray ba; for (int i = 0; i < 16; ++i) ba += hexNumber(m_snapshot.registers[i], 8); - sendGdbMessage(ba, "register contents"); + QByteArray logMsg = "contents"; + if (m_verbose > 1) { + for (int i = 0; i < RegisterCount; ++i) + dumpRegister(i, m_snapshot.registers[i], logMsg); + } + sendGdbMessage(ba, logMsg); } void Adapter::handleReadMemory(const TrkResult &result) @@ -1127,7 +1174,16 @@ void Adapter::reportReadMemory(const TrkResult &result) // << " ADDR: " << hexNumber(blockaddr) << " LEN: " << len // << " BYTES: " << quoteUnprintableLatin1(ba); - sendGdbMessage(ba.toHex(), "memory contents"); + QByteArray logMsg = "memory contents"; + if (m_verbose > 1) { + logMsg += " addr: 0x"; + logMsg += QByteArray::number(addr, 16); + logMsg += " length "; + logMsg += QByteArray::number(len); + logMsg += " :"; + logMsg += stringFromArray(ba, 16); + } + sendGdbMessage(ba.toHex(), logMsg); } void Adapter::setTrkBreakpoint(const Breakpoint &bp) @@ -1335,22 +1391,52 @@ void Adapter::interruptInferior() sendTrkMessage(0x1A, 0, ba, "Interrupting..."); } -int main(int argc, char *argv[]) +static bool readAdapterArgs(const QStringList &args, AdapterOptions *o) { - if (argc < 3) { - qDebug() << "Usage: " << argv[0] << " <trkservername> <gdbserverport>"; - return 1; - } + int argNumber = 0; + const QStringList::const_iterator cend = args.constEnd(); + QStringList::const_iterator it = args.constBegin(); + for (++it; it != cend; ++it) { + if (it->startsWith(QLatin1Char('-'))) { + if (*it == QLatin1String("-v")) { + o->verbose++; + } else if (*it == QLatin1String("-q")) { + o->verbose = 0; + } + } else { + switch (argNumber++) { + case 0: + o->trkServer = *it; + break; + case 1: + o->gdbServer = *it; + break; + } + } + } + return !o->gdbServer.isEmpty(); +} +int main(int argc, char *argv[]) +{ #ifdef Q_OS_UNIX signal(SIGUSR1, signalHandler); #endif QCoreApplication app(argc, argv); + AdapterOptions options; + + if (!readAdapterArgs(app.arguments(), &options)) { + qDebug("Usage: %s [-v|-q] <trkservername> <gdbserverport>\n" + "Options: -v verbose\n" + " -q quiet\n", argv[0]); + return 1; + } Adapter adapter; - adapter.setTrkServerName(argv[1]); - adapter.setGdbServerName(argv[2]); + adapter.setTrkServerName(options.trkServer); + adapter.setGdbServerName(options.gdbServer); + adapter.setVerbose(options.verbose); if (adapter.startServer()) return app.exec(); return 4; diff --git a/tests/manual/trk/run.sh b/tests/manual/trk/run.sh index a0d14cadeae347928a903ad4d54ede3c58056fbd..807c9f3f1750179e6ce67ebebc8f5e9d5b98f5a6 100755 --- a/tests/manual/trk/run.sh +++ b/tests/manual/trk/run.sh @@ -1,5 +1,26 @@ #!/bin/sh +ADAPTER_OPTIONS="" +TRKSERVEROPTIONS="" + +while expr " $1" : " -.*" >/dev/null +do + if [ " $1" = " -av" ] + then + ADAPTER_OPTIONS="$ADAPTER_OPTIONS -v" + elif [ " $1" = " -aq" ] + then + ADAPTER_OPTIONS="$ADAPTER_OPTIONS -q" + elif [ " $1" = " -tv" ] + then + TRKSERVEROPTIONS="$TRKSERVEROPTIONS -v" + elif [ " $1" = " -tq" ] + then + TRKSERVEROPTIONS="$TRKSERVEROPTIONS -q" + fi + shift 1 +done + make || exit 1 killall -s USR1 adapter trkserver > /dev/null 2>&1 @@ -15,12 +36,12 @@ memorydump=TrkDump-78-6a-40-00-BigEndian.bin fuser -n tcp -k ${gdbserverport} rm /tmp/${trkservername} -./trkserver ${trkservername} ${memorydump} & +./trkserver $TRKSERVEROPTIONS ${trkservername} ${memorydump} & trkserverpid=$! sleep 1 -./adapter ${trkservername} ${gdbserverip}:${gdbserverport} & +./adapter $ADAPTER_OPTIONS ${trkservername} ${gdbserverip}:${gdbserverport} & adapterpid=$! echo "# This is generated. Changes will be lost. diff --git a/tests/manual/trk/trkserver.cpp b/tests/manual/trk/trkserver.cpp index d5780f28adc49097db1ef7e90e804f4fc5013784..c36169b059154de862d270bc194d5106bedac79f 100644 --- a/tests/manual/trk/trkserver.cpp +++ b/tests/manual/trk/trkserver.cpp @@ -31,6 +31,7 @@ #include <QtCore/QCoreApplication> #include <QtCore/QFile> +#include <QtCore/QStringList> #include <QtNetwork/QLocalServer> #include <QtNetwork/QLocalSocket> @@ -49,13 +50,22 @@ void signalHandler(int) using namespace trk; +struct TrkOptions { + TrkOptions() : verbose(1) {} + + int verbose; + QString serverName; + QString dumpName; +}; + + // Format of the replay source is something like // ---IDE------------------------------------------------------ // Command: 0x05 Support Mask // [05 02] //---TRK------------------------------------------------------ // Command: 0x80 Acknowledge -// Error: 0x00 +// Error: 0x0 // [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...] @@ -107,6 +117,7 @@ public: void setServerName(const QString &name) { m_serverName = name; } void setMemoryDumpName(const QString &source) { m_memoryDumpName = source; } + void setVerbose(int v) { m_verbose = v; } void startServer(); private slots: @@ -117,7 +128,7 @@ private slots: void handleAdapterMessage(const TrkResult &result); private: - void logMessage(const QString &msg); + void logMessage(const QString &msg, bool force = 0); byte nextNotificationToken(); QString m_serverName; @@ -131,9 +142,10 @@ private: QLocalSocket *m_adapterConnection; Inferior m_inferior; byte m_notificationToken; + int m_verbose; }; -TrkServer::TrkServer() +TrkServer::TrkServer() : m_verbose(1) { m_adapterConnection = 0; m_notificationToken = 0; @@ -158,17 +170,18 @@ void TrkServer::startServer() m_lastSent = 0; if (!m_server.listen(m_serverName)) { logMessage(QString("Error: Unable to start the TRK server %1: %2.") - .arg(m_serverName).arg(m_server.errorString())); + .arg(m_serverName).arg(m_server.errorString()), true); return; } - logMessage("The TRK server is running. Run the adapter now."); + logMessage("The TRK server '" + m_serverName + "'is running. Run the adapter now.", true); connect(&m_server, SIGNAL(newConnection()), this, SLOT(handleConnection())); } -void TrkServer::logMessage(const QString &msg) +void TrkServer::logMessage(const QString &msg, bool force) { - qDebug() << "TRKSERVER: " << qPrintable(msg); + if (m_verbose || force) + qDebug("TRKSERVER: %s", qPrintable(msg)); } void TrkServer::handleConnection() @@ -326,23 +339,51 @@ byte TrkServer::nextNotificationToken() return m_notificationToken; } -int main(int argc, char *argv[]) +static bool readTrkArgs(const QStringList &args, TrkOptions *o) { - if (argc < 3) { - qDebug() << "Usage: " << argv[0] << " <trkservername>" - << " <replaysource>"; - return 1; + int argNumber = 0; + const QStringList::const_iterator cend = args.constEnd(); + QStringList::const_iterator it = args.constBegin(); + for (++it; it != cend; ++it) { + if (it->startsWith(QLatin1Char('-'))) { + if (*it == QLatin1String("-v")) { + o->verbose++; + } else if (*it == QLatin1String("-q")) { + o->verbose = 0; + } + } else { + switch (argNumber++) { + case 0: + o->serverName = *it; + break; + case 1: + o->dumpName = *it; + break; + } + } } + return !o->dumpName.isEmpty(); +} +int main(int argc, char *argv[]) +{ #ifdef Q_OS_UNIX signal(SIGUSR1, signalHandler); #endif QCoreApplication app(argc, argv); + TrkOptions options; + if (!readTrkArgs(app.arguments(), &options)) { + qWarning("Usage: %s [-v|-q] <trkservername> <replaysource>\n" + "Options: -v verbose\n" + " -q quiet\n", argv[0]); + return 1; + } TrkServer server; - server.setServerName(argv[1]); - server.setMemoryDumpName(argv[2]); + server.setServerName(options.serverName); + server.setMemoryDumpName(options.dumpName); + server.setVerbose(options.verbose); server.startServer(); return app.exec(); diff --git a/tests/manual/trk/trkutils.cpp b/tests/manual/trk/trkutils.cpp index 4c132de3d71d7d0f83cb3a46110f6af4927bc99e..bcae69cab99ba5e3e3d8e987f9e2da9226f3f945 100644 --- a/tests/manual/trk/trkutils.cpp +++ b/tests/manual/trk/trkutils.cpp @@ -206,11 +206,12 @@ QString stringFromByte(byte c) return QString("%1 ").arg(c, 2, 16, QChar('0')); } -QString stringFromArray(const QByteArray &ba) +QString stringFromArray(const QByteArray &ba, int maxLen) { QString str; QString ascii; - for (int i = 0; i < ba.size(); ++i) { + const int size = maxLen == -1 ? ba.size() : qMin(ba.size(), maxLen); + for (int i = 0; i < size; ++i) { //if (i == 5 || i == ba.size() - 2) // str += " "; int c = byte(ba.at(i)); @@ -218,6 +219,10 @@ QString stringFromArray(const QByteArray &ba) if (i >= 8 && i < ba.size() - 2) ascii += QChar(c).isPrint() ? QChar(c) : QChar('.'); } + if (size != ba.size()) { + str += "..."; + ascii += "..."; + } return str + " " + ascii; } diff --git a/tests/manual/trk/trkutils.h b/tests/manual/trk/trkutils.h index 5b575f6c449e6a9f48d9f9dbb8015f4f4984b598..d5c89701c2a17dd0a736cf72e19a1b98e915122f 100644 --- a/tests/manual/trk/trkutils.h +++ b/tests/manual/trk/trkutils.h @@ -50,7 +50,7 @@ QString quoteUnprintableLatin1(const QByteArray &ba); // produces "xx " QString stringFromByte(byte c); // produces "xx xx xx " -QString stringFromArray(const QByteArray &ba); +QString stringFromArray(const QByteArray &ba, int maxLen = - 1); enum Endianness { @@ -152,7 +152,7 @@ QByteArray frameMessage(byte command, byte token, const QByteArray &data); ushort isValidTrkResult(const QByteArray &buffer); TrkResult extractResult(QByteArray *buffer); QByteArray errorMessage(byte code); -QByteArray hexNumber(uint n, int digits = 0); +QByteArray hexNumber(uint n, int digits = 0); } // namespace trk