Commit 949fb733 authored by hjk's avatar hjk

Debugger: Split memory reads if big reads fail

Task-number: QTCREATORBUG-10396
Change-Id: I2083e493329fa287446f3c48b4ef8d08fadd9827
Reviewed-by: default avatarChristian Stenger <christian.stenger@digia.com>
Reviewed-by: default avatarhjk <hjk121@nokiamail.com>
parent bd685bde
......@@ -4357,28 +4357,36 @@ void GdbEngine::handleWatchPoint(const GdbResponse &response)
class MemoryAgentCookie
{
public:
MemoryAgentCookie() : agent(0), token(0), address(0) {}
MemoryAgentCookie(MemoryAgent *agent_, QObject *token_, quint64 address_)
: agent(agent_), token(token_), address(address_)
MemoryAgentCookie()
: accumulator(0), pendingRequests(0), agent(0), token(0), base(0), offset(0), length(0)
{}
public:
QByteArray *accumulator; // Shared between split request. Last one cleans up.
uint *pendingRequests; // Shared between split request. Last one cleans up.
QPointer<MemoryAgent> agent;
QPointer<QObject> token;
quint64 address;
quint64 base; // base address.
uint offset; // offset to base, and in accumulator
uint length; //
};
void GdbEngine::changeMemory(MemoryAgent *agent, QObject *token,
quint64 addr, const QByteArray &data)
{
QByteArray cmd = "-data-write-memory " + QByteArray::number(addr) + " d 1";
QByteArray cmd = "-data-write-memory 0x" + QByteArray::number(addr, 16) + " d 1";
foreach (unsigned char c, data) {
cmd.append(' ');
cmd.append(QByteArray::number(uint(c)));
}
postCommand(cmd, NeedsStop, CB(handleChangeMemory),
QVariant::fromValue(MemoryAgentCookie(agent, token, addr)));
MemoryAgentCookie ac;
ac.agent = agent;
ac.token = token;
ac.base = addr;
ac.length = data.size();
postCommand(cmd, NeedsStop, CB(handleChangeMemory), QVariant::fromValue(ac));
}
void GdbEngine::handleChangeMemory(const GdbResponse &response)
......@@ -4389,10 +4397,21 @@ void GdbEngine::handleChangeMemory(const GdbResponse &response)
void GdbEngine::fetchMemory(MemoryAgent *agent, QObject *token, quint64 addr,
quint64 length)
{
postCommand("-data-read-memory " + QByteArray::number(addr) + " x 1 1 "
+ QByteArray::number(length),
NeedsStop, CB(handleFetchMemory),
QVariant::fromValue(MemoryAgentCookie(agent, token, addr)));
MemoryAgentCookie ac;
ac.accumulator = new QByteArray(length, char());
ac.pendingRequests = new uint(1);
ac.agent = agent;
ac.token = token;
ac.base = addr;
ac.length = length;
fetchMemoryHelper(ac);
}
void GdbEngine::fetchMemoryHelper(const MemoryAgentCookie &ac)
{
postCommand("-data-read-memory 0x" + QByteArray::number(ac.base + ac.offset, 16) + " x 1 1 "
+ QByteArray::number(ac.length),
NeedsStop, CB(handleFetchMemory), QVariant::fromValue(ac));
}
void GdbEngine::handleFetchMemory(const GdbResponse &response)
......@@ -4402,22 +4421,46 @@ void GdbEngine::handleFetchMemory(const GdbResponse &response)
// prev-page="0x08910c78",memory=[{addr="0x08910c88",
// data=["1","0","0","0","5","0","0","0","0","0","0","0","0","0","0","0"]}]
MemoryAgentCookie ac = response.cookie.value<MemoryAgentCookie>();
--*ac.pendingRequests;
showMessage(QString::fromLatin1("PENDING: %1").arg(*ac.pendingRequests));
QTC_ASSERT(ac.agent, return);
QByteArray ba;
GdbMi memory = response.data["memory"];
QTC_ASSERT(memory.children().size() <= 1, return);
if (memory.children().isEmpty())
return;
GdbMi memory0 = memory.children().at(0); // we asked for only one 'row'
GdbMi data = memory0["data"];
foreach (const GdbMi &child, data.children()) {
bool ok = true;
unsigned char c = '?';
c = child.data().toUInt(&ok, 0);
QTC_ASSERT(ok, return);
ba.append(c);
}
ac.agent->addLazyData(ac.token, ac.address, ba);
if (response.resultClass == GdbResultDone) {
GdbMi memory = response.data["memory"];
QTC_ASSERT(memory.children().size() <= 1, return);
if (memory.children().isEmpty())
return;
GdbMi memory0 = memory.children().at(0); // we asked for only one 'row'
GdbMi data = memory0["data"];
for (int i = 0, n = data.children().size(); i != n; ++i) {
const GdbMi &child = data.children().at(i);
bool ok = true;
unsigned char c = '?';
c = child.data().toUInt(&ok, 0);
QTC_ASSERT(ok, return);
(*ac.accumulator)[ac.offset + i] = c;
}
} else {
// We have an error
if (ac.length > 1) {
// ... and size > 1, split the load and re-try.
*ac.pendingRequests += 2;
uint hunk = ac.length / 2;
MemoryAgentCookie ac1 = ac;
ac1.length = hunk;
ac1.offset = ac.offset;
MemoryAgentCookie ac2 = ac;
ac2.length = ac.length - hunk;
ac2.offset = ac.offset + hunk;
fetchMemoryHelper(ac1);
fetchMemoryHelper(ac2);
}
}
if (*ac.pendingRequests <= 0) {
ac.agent->addLazyData(ac.token, ac.base, *ac.accumulator);
delete ac.pendingRequests;
delete ac.accumulator;
}
}
class DisassemblerAgentCookie
......
......@@ -52,6 +52,7 @@ class DebugInfoTask;
class DebugInfoTaskHandler;
class GdbResponse;
class GdbMi;
class MemoryAgentCookie;
class WatchData;
class DisassemblerAgentCookie;
......@@ -571,6 +572,7 @@ protected:
virtual void fetchMemory(MemoryAgent *agent, QObject *token,
quint64 addr, quint64 length);
void fetchMemoryHelper(const MemoryAgentCookie &cookie);
void handleChangeMemory(const GdbResponse &response);
virtual void changeMemory(MemoryAgent *agent, QObject *token,
quint64 addr, const QByteArray &data);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment