Trk: Add verbosity options.

This commit is contained in:
Friedemann Kleint
2009-07-28 12:54:25 +02:00
parent c35714f904
commit 2918119a3b
5 changed files with 208 additions and 55 deletions

View File

@@ -32,6 +32,7 @@
#include <QtCore/QCoreApplication> #include <QtCore/QCoreApplication>
#include <QtCore/QQueue> #include <QtCore/QQueue>
#include <QtCore/QTimer> #include <QtCore/QTimer>
#include <QtCore/QStringList>
#include <QtNetwork/QTcpServer> #include <QtNetwork/QTcpServer>
#include <QtNetwork/QTcpSocket> #include <QtNetwork/QTcpSocket>
@@ -57,6 +58,41 @@ using namespace trk;
enum { TRK_SYNC = 0x7f }; 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 #define CB(s) &Adapter::s
class Adapter : public QObject class Adapter : public QObject
@@ -68,6 +104,7 @@ public:
~Adapter(); ~Adapter();
void setGdbServerName(const QString &name); void setGdbServerName(const QString &name);
void setTrkServerName(const QString &name) { m_trkServerName = name; } void setTrkServerName(const QString &name) { m_trkServerName = name; }
void setVerbose(int verbose) { m_verbose = verbose; }
bool startServer(); bool startServer();
private: private:
@@ -78,7 +115,7 @@ private:
typedef void (Adapter::*TrkCallBack)(const TrkResult &); typedef void (Adapter::*TrkCallBack)(const TrkResult &);
struct TrkMessage struct TrkMessage
{ {
TrkMessage() { code = token = 0; callBack = 0; } TrkMessage() { code = token = 0; callBack = 0; }
byte code; byte code;
@@ -160,7 +197,7 @@ private:
void sendGdbAckMessage(); void sendGdbAckMessage();
// //
void logMessage(const QString &msg); void logMessage(const QString &msg, bool force = false);
QTcpServer m_gdbServer; QTcpServer m_gdbServer;
QTcpSocket *m_gdbConnection; QTcpSocket *m_gdbConnection;
@@ -172,6 +209,7 @@ private:
// Debuggee state // Debuggee state
Session m_session; // global-ish data (process id, target information) Session m_session; // global-ish data (process id, target information)
Snapshot m_snapshot; // local-ish data (memory and registers) Snapshot m_snapshot; // local-ish data (memory and registers)
int m_verbose;
}; };
Adapter::Adapter() Adapter::Adapter()
@@ -207,7 +245,7 @@ Adapter::~Adapter()
// Gdb // Gdb
m_gdbServer.close(); m_gdbServer.close();
//>disconnectFromServer(); //>disconnectFromServer();
logMessage("Shutting down.\n"); logMessage("Shutting down.\n", true);
} }
void Adapter::setGdbServerName(const QString &name) void Adapter::setGdbServerName(const QString &name)
@@ -225,7 +263,7 @@ void Adapter::setGdbServerName(const QString &name)
bool Adapter::startServer() bool Adapter::startServer()
{ {
if (!openTrkPort(m_trkServerName)) { 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; return false;
} }
@@ -244,21 +282,22 @@ bool Adapter::startServer()
if (!m_gdbServer.listen(QHostAddress(m_gdbServerName), m_gdbServerPort)) { if (!m_gdbServer.listen(QHostAddress(m_gdbServerName), m_gdbServerPort)) {
logMessage(QString("Unable to start the gdb server at %1:%2: %3.") logMessage(QString("Unable to start the gdb server at %1:%2: %3.")
.arg(m_gdbServerName).arg(m_gdbServerPort) .arg(m_gdbServerName).arg(m_gdbServerPort)
.arg(m_gdbServer.errorString())); .arg(m_gdbServer.errorString()), true);
return false; return false;
} }
logMessage(QString("Gdb server running on port %1. Run arm-gdb now.") logMessage(QString("Gdb server running on %1:%2. Run arm-gdb now.")
.arg(m_gdbServer.serverPort())); .arg(m_gdbServerName).arg(m_gdbServer.serverPort()), true);
connect(&m_gdbServer, SIGNAL(newConnection()), connect(&m_gdbServer, SIGNAL(newConnection()),
this, SLOT(handleGdbConnection())); this, SLOT(handleGdbConnection()));
return true; 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 != '$') { if (code != '$') {
logMessage("Broken package (2) " + quoteUnprintableLatin1(ba) logMessage("Broken package (2) " + quoteUnprintableLatin1(ba)
+ hexNumber(code)); + hexNumber(code));
continue; continue;
} }
@@ -436,7 +475,7 @@ void Adapter::handleGdbResponse(const QByteArray &response)
else if (response.startsWith("C")) { else if (response.startsWith("C")) {
// C sig[;addr] Continue with signal sig (hex signal number) // 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(); sendGdbAckMessage();
bool ok = false; bool ok = false;
uint signalNumber = response.mid(1).toInt(&ok, 16); uint signalNumber = response.mid(1).toInt(&ok, 16);
@@ -466,7 +505,7 @@ void Adapter::handleGdbResponse(const QByteArray &response)
appendByte(&ba, RegisterCount - 1); // last register appendByte(&ba, RegisterCount - 1); // last register
appendInt(&ba, m_session.pid); appendInt(&ba, m_session.pid);
appendInt(&ba, m_session.tid); appendInt(&ba, m_session.tid);
sendTrkMessage(0x12, CB(handleAndReportReadRegisters), ba); sendTrkMessage(0x12, CB(handleAndReportReadRegisters), ba);
} }
@@ -526,37 +565,40 @@ void Adapter::handleGdbResponse(const QByteArray &response)
F7 = 23, last floating point register F7 = 23, last floating point register
FPS = 24, floating point status register FPS = 24, floating point status register
PS = 25, Contains processor status PS = 25, Contains processor status
WR0, WMMX data registers. WR0, WMMX data registers.
WR15 = WR0 + 15, WR15 = WR0 + 15,
WC0, WMMX control registers. WC0, WMMX control registers.
WCSSF = WC0 + 2, WCSSF = WC0 + 2,
WCASF = WC0 + 3, WCASF = WC0 + 3,
WC7 = WC0 + 7, WC7 = WC0 + 7,
WCGR0, WMMX general purpose registers. WCGR0, WMMX general purpose registers.
WCGR3 = WCGR0 + 3, WCGR3 = WCGR0 + 3,
WCGR7 = WCGR0 + 7, WCGR7 = WCGR0 + 7,
NUM_REGS, NUM_REGS,
// Other useful registers. // Other useful registers.
FP = 11, Frame register in ARM code, if used. FP = 11, Frame register in ARM code, if used.
THUMB_FP = 7, Frame register in Thumb code, if used. THUMB_FP = 7, Frame register in Thumb code, if used.
NUM_ARG_REGS = 4, NUM_ARG_REGS = 4,
LAST_ARG = A4, LAST_ARG = A4,
NUM_FP_ARG_REGS = 4, NUM_FP_ARG_REGS = 4,
LAST_FP_ARG = F3 LAST_FP_ARG = F3
#endif #endif
bool ok = false; 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) { if (registerNumber == RegisterPSGdb) {
QByteArray ba; QByteArray ba;
appendInt(&ba, m_snapshot.registers[RegisterPSTrk]); 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) { } else if (registerNumber < RegisterCount) {
QByteArray ba; QByteArray ba;
appendInt(&ba, m_snapshot.registers[registerNumber]); 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 { } else {
sendGdbMessage("0000", "read single unknown register"); sendGdbMessage("0000", "read single unknown register #" + QByteArray::number(registerNumber));
//sendGdbMessage("E01", "read single unknown register"); //sendGdbMessage("E01", "read single unknown register");
} }
} }
@@ -584,7 +626,7 @@ void Adapter::handleGdbResponse(const QByteArray &response)
//$qSupported:multiprocess+#c6 //$qSupported:multiprocess+#c6
//logMessage("Handling 'qSupported'"); //logMessage("Handling 'qSupported'");
sendGdbAckMessage(); sendGdbAckMessage();
if (0) if (0)
sendGdbMessage(QByteArray(), "nothing supported"); sendGdbMessage(QByteArray(), "nothing supported");
else else
sendGdbMessage( sendGdbMessage(
@@ -601,7 +643,7 @@ void Adapter::handleGdbResponse(const QByteArray &response)
sendGdbAckMessage(); sendGdbAckMessage();
sendGdbMessage("", "FIXME: nothing?"); sendGdbMessage("", "FIXME: nothing?");
} }
else if (response == "qOffsets") { else if (response == "qOffsets") {
sendGdbAckMessage(); sendGdbAckMessage();
startInferiorIfNeeded(); startInferiorIfNeeded();
@@ -1093,7 +1135,12 @@ void Adapter::handleAndReportReadRegisters(const TrkResult &result)
QByteArray ba; QByteArray ba;
for (int i = 0; i < 16; ++i) for (int i = 0; i < 16; ++i)
ba += hexNumber(m_snapshot.registers[i], 8); 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) void Adapter::handleReadMemory(const TrkResult &result)
@@ -1127,7 +1174,16 @@ void Adapter::reportReadMemory(const TrkResult &result)
// << " ADDR: " << hexNumber(blockaddr) << " LEN: " << len // << " ADDR: " << hexNumber(blockaddr) << " LEN: " << len
// << " BYTES: " << quoteUnprintableLatin1(ba); // << " 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) void Adapter::setTrkBreakpoint(const Breakpoint &bp)
@@ -1335,22 +1391,52 @@ void Adapter::interruptInferior()
sendTrkMessage(0x1A, 0, ba, "Interrupting..."); sendTrkMessage(0x1A, 0, ba, "Interrupting...");
} }
static bool readAdapterArgs(const QStringList &args, AdapterOptions *o)
{
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[]) int main(int argc, char *argv[])
{ {
if (argc < 3) {
qDebug() << "Usage: " << argv[0] << " <trkservername> <gdbserverport>";
return 1;
}
#ifdef Q_OS_UNIX #ifdef Q_OS_UNIX
signal(SIGUSR1, signalHandler); signal(SIGUSR1, signalHandler);
#endif #endif
QCoreApplication app(argc, argv); 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 adapter;
adapter.setTrkServerName(argv[1]); adapter.setTrkServerName(options.trkServer);
adapter.setGdbServerName(argv[2]); adapter.setGdbServerName(options.gdbServer);
adapter.setVerbose(options.verbose);
if (adapter.startServer()) if (adapter.startServer())
return app.exec(); return app.exec();
return 4; return 4;

View File

@@ -1,5 +1,26 @@
#!/bin/sh #!/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 make || exit 1
killall -s USR1 adapter trkserver > /dev/null 2>&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} fuser -n tcp -k ${gdbserverport}
rm /tmp/${trkservername} rm /tmp/${trkservername}
./trkserver ${trkservername} ${memorydump} & ./trkserver $TRKSERVEROPTIONS ${trkservername} ${memorydump} &
trkserverpid=$! trkserverpid=$!
sleep 1 sleep 1
./adapter ${trkservername} ${gdbserverip}:${gdbserverport} & ./adapter $ADAPTER_OPTIONS ${trkservername} ${gdbserverip}:${gdbserverport} &
adapterpid=$! adapterpid=$!
echo "# This is generated. Changes will be lost. echo "# This is generated. Changes will be lost.

View File

@@ -31,6 +31,7 @@
#include <QtCore/QCoreApplication> #include <QtCore/QCoreApplication>
#include <QtCore/QFile> #include <QtCore/QFile>
#include <QtCore/QStringList>
#include <QtNetwork/QLocalServer> #include <QtNetwork/QLocalServer>
#include <QtNetwork/QLocalSocket> #include <QtNetwork/QLocalSocket>
@@ -49,13 +50,22 @@ void signalHandler(int)
using namespace trk; using namespace trk;
struct TrkOptions {
TrkOptions() : verbose(1) {}
int verbose;
QString serverName;
QString dumpName;
};
// Format of the replay source is something like // Format of the replay source is something like
// ---IDE------------------------------------------------------ // ---IDE------------------------------------------------------
// Command: 0x05 Support Mask // Command: 0x05 Support Mask
// [05 02] // [05 02]
//---TRK------------------------------------------------------ //---TRK------------------------------------------------------
// Command: 0x80 Acknowledge // Command: 0x80 Acknowledge
// Error: 0x00 // Error: 0x0
// [80 02 00 7E 00 4F 5F 01 00 00 00 0F 1F 00 00 00 // [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...] // 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 setServerName(const QString &name) { m_serverName = name; }
void setMemoryDumpName(const QString &source) { m_memoryDumpName = source; } void setMemoryDumpName(const QString &source) { m_memoryDumpName = source; }
void setVerbose(int v) { m_verbose = v; }
void startServer(); void startServer();
private slots: private slots:
@@ -117,7 +128,7 @@ private slots:
void handleAdapterMessage(const TrkResult &result); void handleAdapterMessage(const TrkResult &result);
private: private:
void logMessage(const QString &msg); void logMessage(const QString &msg, bool force = 0);
byte nextNotificationToken(); byte nextNotificationToken();
QString m_serverName; QString m_serverName;
@@ -131,9 +142,10 @@ private:
QLocalSocket *m_adapterConnection; QLocalSocket *m_adapterConnection;
Inferior m_inferior; Inferior m_inferior;
byte m_notificationToken; byte m_notificationToken;
int m_verbose;
}; };
TrkServer::TrkServer() TrkServer::TrkServer() : m_verbose(1)
{ {
m_adapterConnection = 0; m_adapterConnection = 0;
m_notificationToken = 0; m_notificationToken = 0;
@@ -158,17 +170,18 @@ void TrkServer::startServer()
m_lastSent = 0; m_lastSent = 0;
if (!m_server.listen(m_serverName)) { if (!m_server.listen(m_serverName)) {
logMessage(QString("Error: Unable to start the TRK server %1: %2.") 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; 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())); 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() void TrkServer::handleConnection()
@@ -326,23 +339,51 @@ byte TrkServer::nextNotificationToken()
return m_notificationToken; return m_notificationToken;
} }
static bool readTrkArgs(const QStringList &args, TrkOptions *o)
{
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[]) int main(int argc, char *argv[])
{ {
if (argc < 3) {
qDebug() << "Usage: " << argv[0] << " <trkservername>"
<< " <replaysource>";
return 1;
}
#ifdef Q_OS_UNIX #ifdef Q_OS_UNIX
signal(SIGUSR1, signalHandler); signal(SIGUSR1, signalHandler);
#endif #endif
QCoreApplication app(argc, argv); 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; TrkServer server;
server.setServerName(argv[1]); server.setServerName(options.serverName);
server.setMemoryDumpName(argv[2]); server.setMemoryDumpName(options.dumpName);
server.setVerbose(options.verbose);
server.startServer(); server.startServer();
return app.exec(); return app.exec();

View File

@@ -206,11 +206,12 @@ QString stringFromByte(byte c)
return QString("%1 ").arg(c, 2, 16, QChar('0')); return QString("%1 ").arg(c, 2, 16, QChar('0'));
} }
QString stringFromArray(const QByteArray &ba) QString stringFromArray(const QByteArray &ba, int maxLen)
{ {
QString str; QString str;
QString ascii; 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) //if (i == 5 || i == ba.size() - 2)
// str += " "; // str += " ";
int c = byte(ba.at(i)); int c = byte(ba.at(i));
@@ -218,6 +219,10 @@ QString stringFromArray(const QByteArray &ba)
if (i >= 8 && i < ba.size() - 2) if (i >= 8 && i < ba.size() - 2)
ascii += QChar(c).isPrint() ? QChar(c) : QChar('.'); ascii += QChar(c).isPrint() ? QChar(c) : QChar('.');
} }
if (size != ba.size()) {
str += "...";
ascii += "...";
}
return str + " " + ascii; return str + " " + ascii;
} }

View File

@@ -50,7 +50,7 @@ QString quoteUnprintableLatin1(const QByteArray &ba);
// produces "xx " // produces "xx "
QString stringFromByte(byte c); QString stringFromByte(byte c);
// produces "xx xx xx " // produces "xx xx xx "
QString stringFromArray(const QByteArray &ba); QString stringFromArray(const QByteArray &ba, int maxLen = - 1);
enum Endianness enum Endianness
{ {
@@ -152,7 +152,7 @@ QByteArray frameMessage(byte command, byte token, const QByteArray &data);
ushort isValidTrkResult(const QByteArray &buffer); ushort isValidTrkResult(const QByteArray &buffer);
TrkResult extractResult(QByteArray *buffer); TrkResult extractResult(QByteArray *buffer);
QByteArray errorMessage(byte code); QByteArray errorMessage(byte code);
QByteArray hexNumber(uint n, int digits = 0); QByteArray hexNumber(uint n, int digits = 0);
} // namespace trk } // namespace trk