forked from qt-creator/qt-creator
Debugger: Split memory reads if big reads fail
Task-number: QTCREATORBUG-10396 Change-Id: I2083e493329fa287446f3c48b4ef8d08fadd9827 Reviewed-by: Christian Stenger <christian.stenger@digia.com> Reviewed-by: hjk <hjk121@nokiamail.com>
This commit is contained in:
@@ -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);
|
||||
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;
|
||||
}
|
||||
ac.agent->addLazyData(ac.token, ac.address, ba);
|
||||
}
|
||||
|
||||
class DisassemblerAgentCookie
|
||||
|
||||
Reference in New Issue
Block a user