forked from qt-creator/qt-creator
debugger: rework fetching of memory from device
still a few cases for chunked fetching missing
This commit is contained in:
@@ -3852,7 +3852,8 @@ void GdbEngine::handleFetchMemory(const GdbResponse &response)
|
|||||||
GdbMi data = memory0.findChild("data");
|
GdbMi data = memory0.findChild("data");
|
||||||
foreach (const GdbMi &child, data.children()) {
|
foreach (const GdbMi &child, data.children()) {
|
||||||
bool ok = true;
|
bool ok = true;
|
||||||
unsigned char c = child.data().toUInt(&ok, 0);
|
unsigned char c = '?';
|
||||||
|
c = child.data().toUInt(&ok, 0);
|
||||||
QTC_ASSERT(ok, return);
|
QTC_ASSERT(ok, return);
|
||||||
ba.append(c);
|
ba.append(c);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -53,9 +53,19 @@
|
|||||||
|
|
||||||
#define TrkCB(s) TrkCallback(this, &TrkGdbAdapter::s)
|
#define TrkCB(s) TrkCallback(this, &TrkGdbAdapter::s)
|
||||||
|
|
||||||
|
//#define DEBUG_MEMORY 1
|
||||||
|
#if DEBUG_MEMORY
|
||||||
|
# define MEMORY_DEBUG(s) qDebug() << s
|
||||||
|
#else
|
||||||
|
# define MEMORY_DEBUG(s)
|
||||||
|
#endif
|
||||||
|
#define MEMORY_DEBUGX(s) qDebug() << s
|
||||||
|
|
||||||
using namespace trk;
|
using namespace trk;
|
||||||
|
|
||||||
|
namespace Debugger {
|
||||||
|
namespace Internal {
|
||||||
|
|
||||||
enum { KnownRegisters = RegisterPSGdb + 1};
|
enum { KnownRegisters = RegisterPSGdb + 1};
|
||||||
|
|
||||||
static const char *registerNames[KnownRegisters] =
|
static const char *registerNames[KnownRegisters] =
|
||||||
@@ -83,8 +93,99 @@ static QByteArray dumpRegister(int n, uint value)
|
|||||||
return ba;
|
return ba;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace Debugger {
|
QDebug operator<<(QDebug d, MemoryRange range)
|
||||||
namespace Internal {
|
{
|
||||||
|
return d << QString("[%1,%2] (size %3) ")
|
||||||
|
.arg(range.from, 0, 16).arg(range.to, 0, 16).arg(range.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// MemoryRange
|
||||||
|
//
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
bool MemoryRange::intersects(const MemoryRange &other) const
|
||||||
|
{
|
||||||
|
Q_UNUSED(other);
|
||||||
|
return false; // FIXME
|
||||||
|
}
|
||||||
|
|
||||||
|
void MemoryRange::operator-=(const MemoryRange &other)
|
||||||
|
{
|
||||||
|
if (from == 0 && to == 0)
|
||||||
|
return;
|
||||||
|
MEMORY_DEBUG(" SUB: " << *this << " - " << other);
|
||||||
|
if (other.from <= from && to <= other.to) {
|
||||||
|
from = to = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (other.from <= from && other.to <= to) {
|
||||||
|
from = qMax(from, other.to);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (from <= other.from && to <= other.to) {
|
||||||
|
to = qMin(other.from, to);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// This would split the range.
|
||||||
|
QTC_ASSERT(false, qDebug() << "Memory::operator-() not handled for: "
|
||||||
|
<< *this << " - " << other);
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Snapshot
|
||||||
|
//
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
void Snapshot::reset()
|
||||||
|
{
|
||||||
|
memory.clear();
|
||||||
|
for (int i = 0; i < RegisterCount; ++i)
|
||||||
|
registers[i] = 0;
|
||||||
|
wantedMemory = MemoryRange();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Snapshot::insertMemory(const MemoryRange &range, const QByteArray &ba)
|
||||||
|
{
|
||||||
|
QTC_ASSERT(range.size() == ba.size(),
|
||||||
|
qDebug() << "RANGE: " << range << " BA SIZE: " << ba.size(); return);
|
||||||
|
|
||||||
|
MEMORY_DEBUG("INSERT: " << range);
|
||||||
|
// Try to combine with existing chunk.
|
||||||
|
Snapshot::Memory::iterator it = memory.begin();
|
||||||
|
Snapshot::Memory::iterator et = memory.end();
|
||||||
|
for ( ; it != et; ++it) {
|
||||||
|
if (range.from == it.key().to) {
|
||||||
|
MEMORY_DEBUG("COMBINING " << it.key() << " AND " << range);
|
||||||
|
QByteArray data = *it;
|
||||||
|
data.append(ba);
|
||||||
|
memory.remove(it.key());
|
||||||
|
memory.insert(MemoryRange(it.key().from, range.to), data);
|
||||||
|
MEMORY_DEBUG(" TO " << MemoryRange(it.key().from, range.to));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (it.key().from == range.to) {
|
||||||
|
MEMORY_DEBUG("COMBINING " << range << " AND " << it.key());
|
||||||
|
QByteArray data = ba;
|
||||||
|
data.append(*it);
|
||||||
|
memory.remove(it.key());
|
||||||
|
memory.insert(MemoryRange(range.from, it.key().to), data);
|
||||||
|
MEMORY_DEBUG(" TO " << MemoryRange(range.from, it.key().to));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Not combinable, add chunk.
|
||||||
|
memory.insert(range, ba);
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// TrkGdbAdapter
|
||||||
|
//
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
TrkGdbAdapter::TrkGdbAdapter(GdbEngine *engine, const TrkOptionsPtr &options) :
|
TrkGdbAdapter::TrkGdbAdapter(GdbEngine *engine, const TrkOptionsPtr &options) :
|
||||||
AbstractGdbAdapter(engine),
|
AbstractGdbAdapter(engine),
|
||||||
@@ -92,7 +193,7 @@ TrkGdbAdapter::TrkGdbAdapter(GdbEngine *engine, const TrkOptionsPtr &options) :
|
|||||||
m_running(false),
|
m_running(false),
|
||||||
m_gdbAckMode(true),
|
m_gdbAckMode(true),
|
||||||
m_verbose(2),
|
m_verbose(2),
|
||||||
m_bufferedMemoryRead(false),
|
m_bufferedMemoryRead(true),
|
||||||
m_waitCount(0)
|
m_waitCount(0)
|
||||||
{
|
{
|
||||||
m_gdbServer = 0;
|
m_gdbServer = 0;
|
||||||
@@ -223,18 +324,23 @@ QByteArray TrkGdbAdapter::trkWriteRegisterMessage(byte reg, uint value)
|
|||||||
return ba;
|
return ba;
|
||||||
}
|
}
|
||||||
|
|
||||||
QByteArray TrkGdbAdapter::trkReadMemoryMessage(uint addr, uint len)
|
QByteArray TrkGdbAdapter::trkReadMemoryMessage(uint from, uint len)
|
||||||
{
|
{
|
||||||
QByteArray ba;
|
QByteArray ba;
|
||||||
ba.reserve(11);
|
ba.reserve(11);
|
||||||
appendByte(&ba, 0x08); // Options, FIXME: why?
|
appendByte(&ba, 0x08); // Options, FIXME: why?
|
||||||
appendShort(&ba, len);
|
appendShort(&ba, len);
|
||||||
appendInt(&ba, addr);
|
appendInt(&ba, from);
|
||||||
appendInt(&ba, m_session.pid);
|
appendInt(&ba, m_session.pid);
|
||||||
appendInt(&ba, m_session.tid);
|
appendInt(&ba, m_session.tid);
|
||||||
return ba;
|
return ba;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QByteArray TrkGdbAdapter::trkReadMemoryMessage(const MemoryRange &range)
|
||||||
|
{
|
||||||
|
return trkReadMemoryMessage(range.from, range.size());
|
||||||
|
}
|
||||||
|
|
||||||
QByteArray TrkGdbAdapter::trkWriteMemoryMessage(uint addr, const QByteArray &data)
|
QByteArray TrkGdbAdapter::trkWriteMemoryMessage(uint addr, const QByteArray &data)
|
||||||
{
|
{
|
||||||
QByteArray ba;
|
QByteArray ba;
|
||||||
@@ -305,7 +411,7 @@ void TrkGdbAdapter::startInferiorEarly()
|
|||||||
static int direction = 0;
|
static int direction = 0;
|
||||||
direction = (direction + 1) % 4;
|
direction = (direction + 1) % 4;
|
||||||
showStatusMessage(_("Please start TRK on your device! %1")
|
showStatusMessage(_("Please start TRK on your device! %1")
|
||||||
.arg(QChar("/|\\-"[direction])));
|
.arg(QChar("/-\\|"[direction])));
|
||||||
}
|
}
|
||||||
// Do not loop forever
|
// Do not loop forever
|
||||||
if (m_waitCount++ < (m_options->mode == TrkOptions::BlueTooth ? 60 : 5)) {
|
if (m_waitCount++ < (m_options->mode == TrkOptions::BlueTooth ? 60 : 5)) {
|
||||||
@@ -633,7 +739,7 @@ void TrkGdbAdapter::handleGdbServerCommand(const QByteArray &cmd)
|
|||||||
break;
|
break;
|
||||||
} while (false);
|
} while (false);
|
||||||
if (len) {
|
if (len) {
|
||||||
readMemory(addr, len);
|
readMemory(addr, len, m_bufferedMemoryRead);
|
||||||
} else {
|
} else {
|
||||||
sendGdbServerMessage("E20", "Error " + cmd);
|
sendGdbServerMessage("E20", "Error " + cmd);
|
||||||
}
|
}
|
||||||
@@ -1184,27 +1290,14 @@ static QString msgMemoryReadError(int code, uint addr, uint len = 0)
|
|||||||
.arg(code).arg(addr, 0 ,16).arg(lenS);
|
.arg(code).arg(addr, 0 ,16).arg(lenS);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TrkGdbAdapter::handleReadMemoryBuffered(const TrkResult &result)
|
|
||||||
{
|
|
||||||
if (extractShort(result.data.data() + 1) + 3 != result.data.size())
|
|
||||||
logMessage("\n BAD MEMORY RESULT: " + result.data.toHex() + "\n");
|
|
||||||
const uint blockaddr = result.cookie.toUInt();
|
|
||||||
if (const int errorCode = result.errorCode()) {
|
|
||||||
logMessage(msgMemoryReadError(errorCode, blockaddr));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const QByteArray ba = result.data.mid(3);
|
|
||||||
m_snapshot.memory.insert(blockaddr, ba);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Format log message for memory access with some smartness about registers
|
// Format log message for memory access with some smartness about registers
|
||||||
QByteArray TrkGdbAdapter::memoryReadLogMessage(uint addr, uint len, const QByteArray &ba) const
|
QByteArray TrkGdbAdapter::memoryReadLogMessage(uint addr, const QByteArray &ba) const
|
||||||
{
|
{
|
||||||
QByteArray logMsg = "memory contents";
|
QByteArray logMsg = "memory contents";
|
||||||
if (m_verbose > 1) {
|
if (m_verbose > 1) {
|
||||||
logMsg += " addr: " + hexxNumber(addr);
|
logMsg += " addr: " + hexxNumber(addr);
|
||||||
// indicate dereferencing of registers
|
// indicate dereferencing of registers
|
||||||
if (len == 4) {
|
if (ba.size() == 4) {
|
||||||
if (addr == m_snapshot.registers[RegisterPC]) {
|
if (addr == m_snapshot.registers[RegisterPC]) {
|
||||||
logMsg += "[PC]";
|
logMsg += "[PC]";
|
||||||
} else if (addr == m_snapshot.registers[RegisterPSTrk]) {
|
} else if (addr == m_snapshot.registers[RegisterPSTrk]) {
|
||||||
@@ -1221,27 +1314,112 @@ QByteArray TrkGdbAdapter::memoryReadLogMessage(uint addr, uint len, const QByteA
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
logMsg += " length ";
|
logMsg += " length ";
|
||||||
logMsg += QByteArray::number(len);
|
logMsg += QByteArray::number(ba.size());
|
||||||
logMsg += " :";
|
logMsg += " :";
|
||||||
logMsg += stringFromArray(ba, 16).toAscii();
|
logMsg += stringFromArray(ba, 16).toAscii();
|
||||||
}
|
}
|
||||||
return logMsg;
|
return logMsg;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TrkGdbAdapter::reportReadMemoryBuffered(const TrkResult &result)
|
void TrkGdbAdapter::handleReadMemoryBuffered(const TrkResult &result)
|
||||||
{
|
{
|
||||||
const qulonglong cookie = result.cookie.toULongLong();
|
if (extractShort(result.data.data() + 1) + 3 != result.data.size())
|
||||||
const uint addr = cookie >> 32;
|
logMessage("\n BAD MEMORY RESULT: " + result.data.toHex() + "\n");
|
||||||
const uint len = uint(cookie);
|
const MemoryRange range = result.cookie.value<MemoryRange>();
|
||||||
reportReadMemoryBuffered(addr, len);
|
if (const int errorCode = result.errorCode()) {
|
||||||
|
logMessage(_("TEMPORARY: ") + msgMemoryReadError(errorCode, range.from));
|
||||||
|
logMessage(_("RETRYING UNBUFFERED"));
|
||||||
|
// FIXME: This does not handle large requests properly.
|
||||||
|
sendTrkMessage(0x10, TrkCB(handleReadMemoryUnbuffered),
|
||||||
|
trkReadMemoryMessage(range), QVariant::fromValue(range));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const QByteArray ba = result.data.mid(3);
|
||||||
|
m_snapshot.insertMemory(range, ba);
|
||||||
|
tryAnswerGdbMemoryRequest(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TrkGdbAdapter::reportReadMemoryBuffered(uint addr, uint len)
|
void TrkGdbAdapter::handleReadMemoryUnbuffered(const TrkResult &result)
|
||||||
{
|
{
|
||||||
|
if (extractShort(result.data.data() + 1) + 3 != result.data.size())
|
||||||
|
logMessage("\n BAD MEMORY RESULT: " + result.data.toHex() + "\n");
|
||||||
|
const MemoryRange range = result.cookie.value<MemoryRange>();
|
||||||
|
if (const int errorCode = result.errorCode()) {
|
||||||
|
logMessage(_("TEMPORARY: ") + msgMemoryReadError(errorCode, range.from));
|
||||||
|
logMessage(_("RETRYING UNBUFFERED"));
|
||||||
|
const QByteArray ba = "E20";
|
||||||
|
sendGdbServerMessage(ba, msgMemoryReadError(32, range.from).toLatin1());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const QByteArray ba = result.data.mid(3);
|
||||||
|
m_snapshot.insertMemory(range, ba);
|
||||||
|
tryAnswerGdbMemoryRequest(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TrkGdbAdapter::tryAnswerGdbMemoryRequest(bool buffered)
|
||||||
|
{
|
||||||
|
//logMessage("UNBUFFERED MEMORY READ: " + stringFromArray(result.data));
|
||||||
|
|
||||||
|
MemoryRange wanted = m_snapshot.wantedMemory;
|
||||||
|
MemoryRange needed = m_snapshot.wantedMemory;
|
||||||
|
MEMORY_DEBUG("WANTED: " << wanted);
|
||||||
|
Snapshot::Memory::const_iterator it = m_snapshot.memory.begin();
|
||||||
|
Snapshot::Memory::const_iterator et = m_snapshot.memory.end();
|
||||||
|
for ( ; it != et; ++it) {
|
||||||
|
MEMORY_DEBUG(" NEEDED: " << needed);
|
||||||
|
needed -= it.key();
|
||||||
|
}
|
||||||
|
MEMORY_DEBUG("NEEDED: " << needed);
|
||||||
|
|
||||||
|
if (needed.to == 0) {
|
||||||
|
// FIXME: need to combine chunks first.
|
||||||
|
|
||||||
|
// All fine. Send package to gdb.
|
||||||
|
it = m_snapshot.memory.begin();
|
||||||
|
et = m_snapshot.memory.end();
|
||||||
|
for ( ; it != et; ++it) {
|
||||||
|
if (it.key().from <= wanted.from && wanted.to <= it.key().to) {
|
||||||
|
int offset = wanted.from - it.key().from;
|
||||||
|
int len = wanted.to - wanted.from;
|
||||||
|
QByteArray ba = it.value().mid(offset, len);
|
||||||
|
sendGdbServerMessage(ba.toHex(), memoryReadLogMessage(wanted.from, ba));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Happens when chunks are not comnbined
|
||||||
|
QTC_ASSERT(false, /**/);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
MEMORY_DEBUG("NEEDED AND UNSATISFIED: " << needed);
|
||||||
|
if (buffered) {
|
||||||
|
uint blockaddr = (needed.from / MemoryChunkSize) * MemoryChunkSize;
|
||||||
|
logMessage(_("Requesting buffered memory %1 bytes from 0x%2")
|
||||||
|
.arg(MemoryChunkSize).arg(blockaddr, 0, 16));
|
||||||
|
MemoryRange range(blockaddr, blockaddr + MemoryChunkSize);
|
||||||
|
MEMORY_DEBUGX(" FETCH MEMORY : " << range);
|
||||||
|
sendTrkMessage(0x10, TrkCB(handleReadMemoryBuffered),
|
||||||
|
trkReadMemoryMessage(range),
|
||||||
|
QVariant::fromValue(range));
|
||||||
|
} else { // Unbuffered, direct requests
|
||||||
|
int len = needed.to - needed.from;
|
||||||
|
logMessage(_("Requesting unbuffered memory %1 bytes from 0x%2")
|
||||||
|
.arg(len).arg(needed.from, 0, 16));
|
||||||
|
sendTrkMessage(0x10, TrkCB(handleReadMemoryUnbuffered),
|
||||||
|
trkReadMemoryMessage(needed),
|
||||||
|
QVariant::fromValue(needed));
|
||||||
|
MEMORY_DEBUGX(" FETCH MEMORY : " << needed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
void TrkGdbAdapter::reportReadMemoryBuffered(const TrkResult &result)
|
||||||
|
{
|
||||||
|
const MemoryRange range = result.cookie.value<MemoryRange>();
|
||||||
// Gdb accepts less memory according to documentation.
|
// Gdb accepts less memory according to documentation.
|
||||||
// Send E on complete failure.
|
// Send E on complete failure.
|
||||||
QByteArray ba;
|
QByteArray ba;
|
||||||
uint blockaddr = (addr / MemoryChunkSize) * MemoryChunkSize;
|
uint blockaddr = (range.from / MemoryChunkSize) * MemoryChunkSize;
|
||||||
for (; blockaddr < addr + len; blockaddr += MemoryChunkSize) {
|
for (; blockaddr < addr + len; blockaddr += MemoryChunkSize) {
|
||||||
const Snapshot::Memory::const_iterator it = m_snapshot.memory.constFind(blockaddr);
|
const Snapshot::Memory::const_iterator it = m_snapshot.memory.constFind(blockaddr);
|
||||||
if (it == m_snapshot.memory.constEnd())
|
if (it == m_snapshot.memory.constEnd())
|
||||||
@@ -1261,21 +1439,7 @@ void TrkGdbAdapter::reportReadMemoryBuffered(uint addr, uint len)
|
|||||||
sendGdbServerMessage(ba.toHex(), memoryReadLogMessage(addr, len, ba));
|
sendGdbServerMessage(ba.toHex(), memoryReadLogMessage(addr, len, ba));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
void TrkGdbAdapter::handleReadMemoryUnbuffered(const TrkResult &result)
|
|
||||||
{
|
|
||||||
//logMessage("UNBUFFERED MEMORY READ: " + stringFromArray(result.data));
|
|
||||||
const uint blockaddr = result.cookie.toUInt();
|
|
||||||
if (extractShort(result.data.data() + 1) + 3 != result.data.size())
|
|
||||||
logMessage("\n BAD MEMORY RESULT: " + result.data.toHex() + "\n");
|
|
||||||
if (const int errorCode = result.errorCode()) {
|
|
||||||
const QByteArray ba = "E20";
|
|
||||||
sendGdbServerMessage(ba, msgMemoryReadError(32, blockaddr).toLatin1());
|
|
||||||
} else {
|
|
||||||
const QByteArray ba = result.data.mid(3);
|
|
||||||
sendGdbServerMessage(ba.toHex(), memoryReadLogMessage(blockaddr, ba.size(), ba));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void TrkGdbAdapter::handleStepInto(const TrkResult &result)
|
void TrkGdbAdapter::handleStepInto(const TrkResult &result)
|
||||||
{
|
{
|
||||||
@@ -1398,7 +1562,7 @@ void TrkGdbAdapter::handleDisconnect(const TrkResult & /*result*/)
|
|||||||
logMessage(QLatin1String("Trk disconnected"));
|
logMessage(QLatin1String("Trk disconnected"));
|
||||||
}
|
}
|
||||||
|
|
||||||
void TrkGdbAdapter::readMemory(uint addr, uint len)
|
void TrkGdbAdapter::readMemory(uint addr, uint len, bool buffered)
|
||||||
{
|
{
|
||||||
Q_ASSERT(len < (2 << 16));
|
Q_ASSERT(len < (2 << 16));
|
||||||
|
|
||||||
@@ -1407,43 +1571,15 @@ void TrkGdbAdapter::readMemory(uint addr, uint len)
|
|||||||
logMessage(_("readMemory %1 bytes from 0x%2 blocksize=%3")
|
logMessage(_("readMemory %1 bytes from 0x%2 blocksize=%3")
|
||||||
.arg(len).arg(addr, 0, 16).arg(MemoryChunkSize));
|
.arg(len).arg(addr, 0, 16).arg(MemoryChunkSize));
|
||||||
|
|
||||||
if (m_bufferedMemoryRead) {
|
m_snapshot.wantedMemory = MemoryRange(addr, addr + len);
|
||||||
uint requests = 0;
|
tryAnswerGdbMemoryRequest(buffered);
|
||||||
uint blockaddr = (addr / MemoryChunkSize) * MemoryChunkSize;
|
|
||||||
for (; blockaddr < addr + len; blockaddr += MemoryChunkSize) {
|
|
||||||
if (!m_snapshot.memory.contains(blockaddr)) {
|
|
||||||
if (m_verbose)
|
|
||||||
logMessage(_("Requesting buffered "
|
|
||||||
"memory %1 bytes from 0x%2")
|
|
||||||
.arg(MemoryChunkSize).arg(blockaddr, 0, 16));
|
|
||||||
sendTrkMessage(0x10, TrkCB(handleReadMemoryBuffered),
|
|
||||||
trkReadMemoryMessage(blockaddr, MemoryChunkSize),
|
|
||||||
QVariant(blockaddr));
|
|
||||||
requests++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// If requests have been sent: Sync
|
|
||||||
if (requests) {
|
|
||||||
const qulonglong cookie = (qulonglong(addr) << 32) + len;
|
|
||||||
sendTrkMessage(TRK_WRITE_QUEUE_NOOP_CODE, TrkCB(reportReadMemoryBuffered),
|
|
||||||
QByteArray(), cookie);
|
|
||||||
} else {
|
|
||||||
// Everything is already buffered: invoke callback directly
|
|
||||||
reportReadMemoryBuffered(addr, len);
|
|
||||||
}
|
|
||||||
} else { // Unbuffered, direct requests
|
|
||||||
if (m_verbose)
|
|
||||||
logMessage(_("Requesting unbuffered memory %1 "
|
|
||||||
"bytes from 0x%2").arg(len).arg(addr, 0, 16));
|
|
||||||
sendTrkMessage(0x10, TrkCB(handleReadMemoryUnbuffered),
|
|
||||||
trkReadMemoryMessage(addr, len), QVariant(addr));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TrkGdbAdapter::interruptInferior()
|
void TrkGdbAdapter::interruptInferior()
|
||||||
{
|
{
|
||||||
QTC_ASSERT(state() == AdapterStarted, qDebug() << state());
|
QTC_ASSERT(state() == AdapterStarted, qDebug() << state());
|
||||||
qDebug() << "TRYING TO INTERRUPT INFERIOR";
|
logMessage("TRYING TO INTERRUPT INFERIOR");
|
||||||
sendTrkMessage(0x1a, TrkCallback(), trkInterruptMessage(), "Interrupting...");
|
sendTrkMessage(0x1a, TrkCallback(), trkInterruptMessage(), "Interrupting...");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -49,6 +49,67 @@
|
|||||||
namespace Debugger {
|
namespace Debugger {
|
||||||
namespace Internal {
|
namespace Internal {
|
||||||
|
|
||||||
|
enum CodeMode
|
||||||
|
{
|
||||||
|
ArmMode = 0,
|
||||||
|
ThumbMode,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum TargetConstants
|
||||||
|
{
|
||||||
|
|
||||||
|
RegisterCount = 17,
|
||||||
|
RegisterSP = 13, // Stack Pointer
|
||||||
|
RegisterLR = 14, // Return address
|
||||||
|
RegisterPC = 15, // Program counter
|
||||||
|
RegisterPSGdb = 25, // gdb's view of the world
|
||||||
|
RegisterPSTrk = 16, // TRK's view of the world
|
||||||
|
|
||||||
|
MemoryChunkSize = 256
|
||||||
|
};
|
||||||
|
|
||||||
|
struct MemoryRange
|
||||||
|
{
|
||||||
|
MemoryRange() : from(0), to(0) {}
|
||||||
|
MemoryRange(uint f, uint t) : from(f), to(t) {}
|
||||||
|
void operator-=(const MemoryRange &other);
|
||||||
|
bool intersects(const MemoryRange &other) const;
|
||||||
|
quint64 hash() const { return (quint64(from) << 32) + to; }
|
||||||
|
bool operator==(const MemoryRange &other) const { return hash() == other.hash(); }
|
||||||
|
bool operator<(const MemoryRange &other) const { return hash() < other.hash(); }
|
||||||
|
int size() const { return to - from; }
|
||||||
|
|
||||||
|
uint from; // Inclusive.
|
||||||
|
uint to; // Exclusive.
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Snapshot
|
||||||
|
{
|
||||||
|
void reset();
|
||||||
|
void insertMemory(const MemoryRange &range, const QByteArray &ba);
|
||||||
|
|
||||||
|
uint registers[RegisterCount];
|
||||||
|
typedef QMap<MemoryRange, QByteArray> Memory;
|
||||||
|
Memory memory;
|
||||||
|
|
||||||
|
// Current state.
|
||||||
|
MemoryRange wantedMemory;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct Breakpoint
|
||||||
|
{
|
||||||
|
Breakpoint(uint offset_ = 0)
|
||||||
|
{
|
||||||
|
number = 0;
|
||||||
|
offset = offset_;
|
||||||
|
mode = ArmMode;
|
||||||
|
}
|
||||||
|
uint offset;
|
||||||
|
ushort number;
|
||||||
|
CodeMode mode;
|
||||||
|
};
|
||||||
|
|
||||||
struct GdbResult
|
struct GdbResult
|
||||||
{
|
{
|
||||||
QByteArray data;
|
QByteArray data;
|
||||||
@@ -155,7 +216,7 @@ private:
|
|||||||
void handleAndReportCreateProcess(const TrkResult &result);
|
void handleAndReportCreateProcess(const TrkResult &result);
|
||||||
void handleAndReportReadRegistersAfterStop(const TrkResult &result);
|
void handleAndReportReadRegistersAfterStop(const TrkResult &result);
|
||||||
void reportRegisters();
|
void reportRegisters();
|
||||||
QByteArray memoryReadLogMessage(uint addr, uint len, const QByteArray &ba) const;
|
QByteArray memoryReadLogMessage(uint addr, const QByteArray &ba) const;
|
||||||
void handleAndReportSetBreakpoint(const TrkResult &result);
|
void handleAndReportSetBreakpoint(const TrkResult &result);
|
||||||
void handleReadMemoryBuffered(const TrkResult &result);
|
void handleReadMemoryBuffered(const TrkResult &result);
|
||||||
void handleReadMemoryUnbuffered(const TrkResult &result);
|
void handleReadMemoryUnbuffered(const TrkResult &result);
|
||||||
@@ -164,12 +225,12 @@ private:
|
|||||||
void handleStepOver(const TrkResult &result);
|
void handleStepOver(const TrkResult &result);
|
||||||
void handleStepOver2(const TrkResult &result);
|
void handleStepOver2(const TrkResult &result);
|
||||||
void handleReadRegisters(const TrkResult &result);
|
void handleReadRegisters(const TrkResult &result);
|
||||||
void reportReadMemoryBuffered(const TrkResult &result);
|
|
||||||
void reportReadMemoryBuffered(uint addr, uint len);
|
|
||||||
void handleWriteRegister(const TrkResult &result);
|
void handleWriteRegister(const TrkResult &result);
|
||||||
void reportToGdb(const TrkResult &result);
|
void reportToGdb(const TrkResult &result);
|
||||||
|
//void reportReadMemoryBuffered(const TrkResult &result);
|
||||||
|
//void reportReadMemoryUnbuffered(const TrkResult &result);
|
||||||
|
|
||||||
void readMemory(uint addr, uint len);
|
void readMemory(uint addr, uint len, bool buffered);
|
||||||
|
|
||||||
void handleDirectTrk(const TrkResult &response);
|
void handleDirectTrk(const TrkResult &response);
|
||||||
void directStep(uint addr);
|
void directStep(uint addr);
|
||||||
@@ -190,8 +251,9 @@ private:
|
|||||||
QByteArray trkContinueMessage();
|
QByteArray trkContinueMessage();
|
||||||
QByteArray trkReadRegistersMessage();
|
QByteArray trkReadRegistersMessage();
|
||||||
QByteArray trkWriteRegisterMessage(byte reg, uint value);
|
QByteArray trkWriteRegisterMessage(byte reg, uint value);
|
||||||
|
QByteArray trkReadMemoryMessage(const MemoryRange &range);
|
||||||
QByteArray trkReadMemoryMessage(uint addr, uint len);
|
QByteArray trkReadMemoryMessage(uint addr, uint len);
|
||||||
QByteArray trkWriteMemoryMessage(uint add, const QByteArray &date);
|
QByteArray trkWriteMemoryMessage(uint addr, const QByteArray &date);
|
||||||
QByteArray trkBreakpointMessage(uint addr, uint len, bool armMode = true);
|
QByteArray trkBreakpointMessage(uint addr, uint len, bool armMode = true);
|
||||||
QByteArray trkStepRangeMessage(byte option);
|
QByteArray trkStepRangeMessage(byte option);
|
||||||
QByteArray trkDeleteProcessMessage();
|
QByteArray trkDeleteProcessMessage();
|
||||||
@@ -228,6 +290,7 @@ private:
|
|||||||
const QByteArray &logNote = QByteArray());
|
const QByteArray &logNote = QByteArray());
|
||||||
void sendGdbServerAck();
|
void sendGdbServerAck();
|
||||||
bool sendGdbServerPacket(const QByteArray &packet, bool doFlush);
|
bool sendGdbServerPacket(const QByteArray &packet, bool doFlush);
|
||||||
|
void tryAnswerGdbMemoryRequest(bool buffered);
|
||||||
|
|
||||||
Q_SLOT void handleGdbError(QProcess::ProcessError error);
|
Q_SLOT void handleGdbError(QProcess::ProcessError error);
|
||||||
Q_SLOT void handleGdbFinished(int exitCode, QProcess::ExitStatus exitStatus);
|
Q_SLOT void handleGdbFinished(int exitCode, QProcess::ExitStatus exitStatus);
|
||||||
@@ -259,7 +322,7 @@ private:
|
|||||||
// Debuggee state
|
// Debuggee state
|
||||||
Q_SLOT void executeCommand(const QString &msg);
|
Q_SLOT void executeCommand(const QString &msg);
|
||||||
trk::Session m_session; // global-ish data (process id, target information)
|
trk::Session m_session; // global-ish data (process id, target information)
|
||||||
trk::Snapshot m_snapshot; // local-ish data (memory and registers)
|
Snapshot m_snapshot; // local-ish data (memory and registers)
|
||||||
QString m_remoteExecutable;
|
QString m_remoteExecutable;
|
||||||
QString m_symbolFile;
|
QString m_symbolFile;
|
||||||
int m_verbose;
|
int m_verbose;
|
||||||
@@ -270,4 +333,6 @@ private:
|
|||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
} // namespace Debugger
|
} // namespace Debugger
|
||||||
|
|
||||||
|
Q_DECLARE_METATYPE(Debugger::Internal::MemoryRange);
|
||||||
|
|
||||||
#endif // DEBUGGER_TRKGDBADAPTER_H
|
#endif // DEBUGGER_TRKGDBADAPTER_H
|
||||||
|
|||||||
@@ -65,8 +65,15 @@ struct TrkOptions
|
|||||||
QString cygwin; // ignored on Linux
|
QString cygwin; // ignored on Linux
|
||||||
};
|
};
|
||||||
|
|
||||||
inline bool operator==(const TrkOptions &o1, const TrkOptions &o2) { return o1.equals(o2); }
|
inline bool operator==(const TrkOptions &o1, const TrkOptions &o2)
|
||||||
inline bool operator!=(const TrkOptions &o1, const TrkOptions &o2) { return !o1.equals(o2); }
|
{
|
||||||
|
return o1.equals(o2);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool operator!=(const TrkOptions &o1, const TrkOptions &o2)
|
||||||
|
{
|
||||||
|
return !o1.equals(o2);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
} // namespace Debugger
|
} // namespace Debugger
|
||||||
|
|||||||
@@ -362,12 +362,5 @@ QString TrkResult::errorString() const
|
|||||||
return errorMessage(data.at(0));
|
return errorMessage(data.at(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Snapshot::reset()
|
|
||||||
{
|
|
||||||
memory.clear();
|
|
||||||
for (int i = 0; i < RegisterCount; ++i)
|
|
||||||
registers[i] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace trk
|
} // namespace trk
|
||||||
|
|
||||||
|
|||||||
@@ -95,25 +95,6 @@ void appendShort(QByteArray *ba, ushort s, Endianness = TargetByteOrder);
|
|||||||
void appendInt(QByteArray *ba, uint i, Endianness = TargetByteOrder);
|
void appendInt(QByteArray *ba, uint i, Endianness = TargetByteOrder);
|
||||||
void appendString(QByteArray *ba, const QByteArray &str, Endianness = TargetByteOrder, bool appendNullTerminator = true);
|
void appendString(QByteArray *ba, const QByteArray &str, Endianness = TargetByteOrder, bool appendNullTerminator = true);
|
||||||
|
|
||||||
enum CodeMode
|
|
||||||
{
|
|
||||||
ArmMode = 0,
|
|
||||||
ThumbMode,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum TargetConstants
|
|
||||||
{
|
|
||||||
|
|
||||||
RegisterCount = 17,
|
|
||||||
RegisterSP = 13, // Stack Pointer
|
|
||||||
RegisterLR = 14, // Return address
|
|
||||||
RegisterPC = 15, // Program counter
|
|
||||||
RegisterPSGdb = 25, // gdb's view of the world
|
|
||||||
RegisterPSTrk = 16, // TRK's view of the world
|
|
||||||
|
|
||||||
MemoryChunkSize = 256
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Library
|
struct Library
|
||||||
{
|
{
|
||||||
Library() {}
|
Library() {}
|
||||||
@@ -166,29 +147,6 @@ struct Session
|
|||||||
QStringList modules;
|
QStringList modules;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Snapshot
|
|
||||||
{
|
|
||||||
void reset();
|
|
||||||
|
|
||||||
uint registers[RegisterCount];
|
|
||||||
typedef QHash<uint, QByteArray> Memory;
|
|
||||||
Memory memory;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
struct Breakpoint
|
|
||||||
{
|
|
||||||
Breakpoint(uint offset_ = 0)
|
|
||||||
{
|
|
||||||
number = 0;
|
|
||||||
offset = offset_;
|
|
||||||
mode = ArmMode;
|
|
||||||
}
|
|
||||||
uint offset;
|
|
||||||
ushort number;
|
|
||||||
CodeMode mode;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct TrkResult
|
struct TrkResult
|
||||||
{
|
{
|
||||||
TrkResult();
|
TrkResult();
|
||||||
|
|||||||
Reference in New Issue
Block a user