diff --git a/tests/manual/trk/adapter.cpp b/tests/manual/trk/adapter.cpp index bd3ae8cca4dee3f82f408f491d3994ef73929af5..a03d6725e35781403649b163aa47655c5754599f 100644 --- a/tests/manual/trk/adapter.cpp +++ b/tests/manual/trk/adapter.cpp @@ -105,9 +105,10 @@ static inline void dumpRegister(int n, uint value, QByteArray &a) } struct AdapterOptions { - AdapterOptions() : verbose(1) {} + AdapterOptions() : verbose(1),registerEndianness(BigEndian) {} int verbose; + Endianness registerEndianness; QString gdbServer; QString trkServer; }; @@ -124,6 +125,7 @@ public: void setGdbServerName(const QString &name); void setTrkServerName(const QString &name) { m_trkServerName = name; } void setVerbose(int verbose) { m_verbose = verbose; } + void setRegisterEndianness(Endianness r) { m_registerEndianness = r; } bool startServer(); private: @@ -136,19 +138,21 @@ private: struct TrkMessage { - TrkMessage() { code = token = 0; callBack = 0; } + TrkMessage() : code(0), token(0), callBack(0), invokeOnFailure(0) {} byte code; byte token; QByteArray data; QVariant cookie; TrkCallBack callBack; + bool invokeOnFailure; }; bool openTrkPort(const QString &port); // or server name for local server void sendTrkMessage(byte code, - TrkCallBack callBack = 0, + TrkCallBack calBack = 0, const QByteArray &data = QByteArray(), - const QVariant &cookie = QVariant()); + const QVariant &cookie = QVariant(), + bool invokeOnFailure = false); // adds message to 'send' queue void queueTrkMessage(const TrkMessage &msg); void tryTrkWrite(); @@ -229,9 +233,11 @@ private: Session m_session; // global-ish data (process id, target information) Snapshot m_snapshot; // local-ish data (memory and registers) int m_verbose; + Endianness m_registerEndianness; }; -Adapter::Adapter() +Adapter::Adapter() : + m_registerEndianness(BigEndian) { // Trk #if USE_NATIVE @@ -305,8 +311,8 @@ bool Adapter::startServer() return false; } - logMessage(QString("Gdb server running on %1:%2. Run arm-gdb now.") - .arg(m_gdbServerName).arg(m_gdbServer.serverPort()), true); + logMessage(QString("Gdb server running on %1:%2.\nRegister endianness: %3\nRun arm-gdb now.") + .arg(m_gdbServerName).arg(m_gdbServer.serverPort()).arg(m_registerEndianness), true); connect(&m_gdbServer, SIGNAL(newConnection()), this, SLOT(handleGdbConnection())); @@ -608,12 +614,12 @@ void Adapter::handleGdbResponse(const QByteArray &response) QByteArray logMsg = "read register"; if (registerNumber == RegisterPSGdb) { QByteArray ba; - appendInt(&ba, m_snapshot.registers[RegisterPSTrk]); + appendInt(&ba, m_snapshot.registers[RegisterPSTrk], m_registerEndianness); dumpRegister(registerNumber, m_snapshot.registers[RegisterPSTrk], logMsg); sendGdbMessage(ba.toHex(), logMsg); } else if (registerNumber < RegisterCount) { QByteArray ba; - appendInt(&ba, m_snapshot.registers[registerNumber]); + appendInt(&ba, m_snapshot.registers[registerNumber], m_registerEndianness); dumpRegister(registerNumber, m_snapshot.registers[registerNumber], logMsg); sendGdbMessage(ba.toHex(), logMsg); } else { @@ -793,7 +799,7 @@ byte Adapter::nextTrkWriteToken() } void Adapter::sendTrkMessage(byte code, TrkCallBack callBack, - const QByteArray &data, const QVariant &cookie) + const QByteArray &data, const QVariant &cookie, bool invokeOnFailure) { TrkMessage msg; msg.code = code; @@ -801,6 +807,7 @@ void Adapter::sendTrkMessage(byte code, TrkCallBack callBack, msg.callBack = callBack; msg.data = data; msg.cookie = cookie; + msg.invokeOnFailure = invokeOnFailure; queueTrkMessage(msg); } @@ -945,7 +952,6 @@ void Adapter::handleResult(const TrkResult &result) result1.cookie = msg.cookie; TrkCallBack cb = msg.callBack; if (cb) { - //logMessage("HANDLE: " << stringFromArray(result.data)); (this->*cb)(result1); } else { QString msg = result.cookie.toString(); @@ -956,8 +962,14 @@ void Adapter::handleResult(const TrkResult &result) } case 0xff: { // NAK logMessage(prefix + "NAK: " + str); - //logMessage(prefix << "TOKEN: " << result.token); logMessage(prefix + "ERROR: " + errorMessage(result.data.at(0))); + TrkMessage msg = m_writtenTrkMessages.take(result.token); + // Invoke failure if desired + if (msg.callBack && msg.invokeOnFailure) { + TrkResult result1 = result; + result1.cookie = msg.cookie; + (this->*msg.callBack)(result1); + } break; } case 0x90: { // Notified Stopped @@ -1153,9 +1165,11 @@ void Adapter::handleAndReportReadRegisters(const TrkResult &result) } //QByteArray ba = result.data.toHex(); QByteArray ba; - for (int i = 0; i < 16; ++i) - ba += hexNumber(m_snapshot.registers[i], 8); - QByteArray logMsg = "contents"; + for (int i = 0; i < 16; ++i) { + const uint reg = m_registerEndianness == LittleEndian ? swapEndian(m_snapshot.registers[i]) : m_snapshot.registers[i]; + ba += hexNumber(reg, 8); + } + QByteArray logMsg = "register contents"; if (m_verbose > 1) { for (int i = 0; i < RegisterCount; ++i) dumpRegister(i, m_snapshot.registers[i], logMsg); @@ -1163,16 +1177,20 @@ void Adapter::handleAndReportReadRegisters(const TrkResult &result) sendGdbMessage(ba, logMsg); } +static inline QString msgMemoryReadError(uint addr) +{ + return QString::fromLatin1("Memory read error at: 0x%1").arg(addr, 0 ,16); +} + 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: " << hexNumber(blockaddr) - // << "COOKIE: " << result.cookie; - m_snapshot.memory[blockaddr] = ba; + const uint blockaddr = result.cookie.toInt(); + if (result.code == 0xff) { + logMessage(msgMemoryReadError(blockaddr)); + } else { + const QByteArray ba = result.data.mid(1); + m_snapshot.memory.insert(blockaddr , ba); + } } // Format log message for memory access with some smartness about registers @@ -1208,20 +1226,31 @@ QByteArray Adapter::memoryReadLogMessage(uint addr, uint len, const QByteArray & void Adapter::reportReadMemory(const TrkResult &result) { - qulonglong cookie = result.cookie.toLongLong(); - uint addr = cookie >> 32; - uint len = uint(cookie); + const qulonglong cookie = result.cookie.toLongLong(); + const uint addr = cookie >> 32; + const uint len = uint(cookie); + // Gdb accepts less memory according to documentation. + // Send E on complete failure. 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); + const Snapshot::Memory::const_iterator it = m_snapshot.memory.constFind(blockaddr); + if (it == m_snapshot.memory.constEnd()) + break; + ba.append(it.value()); + } + const int previousChunkOverlap = addr % MemoryChunkSize; + if (previousChunkOverlap != 0 && ba.size() > previousChunkOverlap) + ba.remove(0, previousChunkOverlap); + if (ba.size() > int(len)) + ba.truncate(len); + if (ba.isEmpty()) { + ba = "E20"; + sendGdbMessage(ba, msgMemoryReadError(addr).toLatin1()); + } else { + sendGdbMessage(ba.toHex(), memoryReadLogMessage(addr, len, ba)); } - - ba = ba.mid(addr % MemoryChunkSize, len); - sendGdbMessage(ba.toHex(), memoryReadLogMessage(addr, len, ba)); } void Adapter::setTrkBreakpoint(const Breakpoint &bp) @@ -1393,7 +1422,7 @@ void Adapter::readMemory(uint addr, uint len) appendInt(&ba, m_session.pid); appendInt(&ba, m_session.tid); // Read Memory - sendTrkMessage(0x10, CB(handleReadMemory), ba, QVariant(blockaddr)); + sendTrkMessage(0x10, CB(handleReadMemory), ba, QVariant(blockaddr), true); } } qulonglong cookie = (qulonglong(addr) << 32) + len; @@ -1440,6 +1469,8 @@ static bool readAdapterArgs(const QStringList &args, AdapterOptions *o) o->verbose++; } else if (*it == QLatin1String("-q")) { o->verbose = 0; + } else if (*it == QLatin1String("-l")) { + o->registerEndianness = LittleEndian; } } else { switch (argNumber++) { @@ -1465,9 +1496,10 @@ int main(int argc, char *argv[]) AdapterOptions options; if (!readAdapterArgs(app.arguments(), &options)) { - qDebug("Usage: %s [-v|-q] <trkservername> <gdbserverport>\n" + qDebug("Usage: %s [-v|-q] [-l] <trkservername> <gdbserverport>\n" "Options: -v verbose\n" - " -q quiet\n", argv[0]); + " -q quiet\n" + " -l Set register endianness to little\n", argv[0]); return 1; } @@ -1475,6 +1507,7 @@ int main(int argc, char *argv[]) adapter.setTrkServerName(options.trkServer); adapter.setGdbServerName(options.gdbServer); adapter.setVerbose(options.verbose); + adapter.setRegisterEndianness(options.registerEndianness); if (adapter.startServer()) return app.exec(); return 4; diff --git a/tests/manual/trk/run.sh b/tests/manual/trk/run.sh index 807c9f3f1750179e6ce67ebebc8f5e9d5b98f5a6..3201dab858e0778d4f144c21d7fab1196dae7634 100755 --- a/tests/manual/trk/run.sh +++ b/tests/manual/trk/run.sh @@ -2,6 +2,8 @@ ADAPTER_OPTIONS="" TRKSERVEROPTIONS="" +DUMP_POSTFIX='-BigEndian.bin' +ENDIANESS='big' while expr " $1" : " -.*" >/dev/null do @@ -17,6 +19,11 @@ do elif [ " $1" = " -tq" ] then TRKSERVEROPTIONS="$TRKSERVEROPTIONS -q" + elif [ " $1" = " -l" ] + then + DUMP_POSTFIX='.bin' + ENDIANESS='little' + ADAPTER_OPTIONS="$ADAPTER_OPTIONS -l" fi shift 1 done @@ -30,24 +37,23 @@ userid=`id -u` trkservername="TRKSERVER-${userid}"; gdbserverip=127.0.0.1 gdbserverport=$[2222 + ${userid}] -memorydump=TrkDump-78-6a-40-00.bin -memorydump=TrkDump-78-6a-40-00-BigEndian.bin fuser -n tcp -k ${gdbserverport} rm /tmp/${trkservername} -./trkserver $TRKSERVEROPTIONS ${trkservername} ${memorydump} & +MEMORYDUMP="TrkDump-78-6a-40-00$DUMP_POSTFIX" +ADDITIONAL_DUMPS="0x00402000$DUMP_POSTFIX 0x786a4000$DUMP_POSTFIX 0x00600000$DUMP_POSTFIX" +./trkserver $TRKSERVEROPTIONS ${trkservername} ${MEMORYDUMP} ${ADDITIONAL_DUMPS}& trkserverpid=$! sleep 1 - ./adapter $ADAPTER_OPTIONS ${trkservername} ${gdbserverip}:${gdbserverport} & adapterpid=$! echo "# This is generated. Changes will be lost. #set remote noack-packet on set confirm off -set endian big +set endian $ENDIANESS #set debug remote 1 #target remote ${gdbserverip}:${gdbserverport} target extended-remote ${gdbserverip}:${gdbserverport} diff --git a/tests/manual/trk/trkserver.cpp b/tests/manual/trk/trkserver.cpp index e8eb82f95920ce1d0980823a46aaf67da01f9742..911d87b2c9ee46d8977bb38cc09c017e64424974 100644 --- a/tests/manual/trk/trkserver.cpp +++ b/tests/manual/trk/trkserver.cpp @@ -314,8 +314,6 @@ bool TrkServer::handleMemoryRequest(uint addr, ushort len, byte option, QByteArr return true; } } - for (int i = 0; i != len / 4; ++i) - appendInt(ba, 0xDEADBEEF); logMessage(QString::fromLatin1("ADDRESS OUTSIDE ANY SEGMENTS: 0X%1").arg(addr, 0, 16), true); return false; } @@ -340,8 +338,12 @@ void TrkServer::handleAdapterMessage(const TrkResult &result) Q_UNUSED(option); const ushort len = extractShort(p + 1); const uint addr = extractInt(p + 3);; - handleMemoryRequest(addr, len, option, &data); - writeToAdapter(0x80, result.token, data); + if (handleMemoryRequest(addr, len, option, &data)) { + writeToAdapter(0x80, result.token, data); + } else { + data[0] =32; // NAK, bad hair day + writeToAdapter(0xff, result.token, data); + } break; } case 0x12: { // Read Registers diff --git a/tests/manual/trk/trkutils.cpp b/tests/manual/trk/trkutils.cpp index bcae69cab99ba5e3e3d8e987f9e2da9226f3f945..43395ea99af9521f6d197c520bf8e50d941cf39e 100644 --- a/tests/manual/trk/trkutils.cpp +++ b/tests/manual/trk/trkutils.cpp @@ -298,6 +298,9 @@ QByteArray errorMessage(byte code) return "Unknown error"; } - +uint swapEndian(uint in) +{ + return (in>>24) | ((in<<8) & 0x00FF0000) | ((in>>8) & 0x0000FF00) | (in<<24); +} } // namespace trk diff --git a/tests/manual/trk/trkutils.h b/tests/manual/trk/trkutils.h index 92dd8c72339741a40d72de6af3b973c44279de0c..95b000133072756e52c8d43565c71852cc9d39c6 100644 --- a/tests/manual/trk/trkutils.h +++ b/tests/manual/trk/trkutils.h @@ -177,6 +177,8 @@ ushort isValidTrkResult(const QByteArray &buffer); TrkResult extractResult(QByteArray *buffer); QByteArray errorMessage(byte code); QByteArray hexNumber(uint n, int digits = 0); +uint swapEndian(uint in); + } // namespace trk