Skip to content

Commit

Permalink
Grow memory dump automatically when end of view is reached.
Browse files Browse the repository at this point in the history
When the users scrolls the memory dump view down to the end, new memory
dump is displayed automatically.
  • Loading branch information
Marc Font Freixa authored and j6t committed May 14, 2017
1 parent daf9b3d commit 331a4e1
Show file tree
Hide file tree
Showing 9 changed files with 225 additions and 106 deletions.
2 changes: 2 additions & 0 deletions kdbg/dbgdriver.h
Expand Up @@ -266,6 +266,7 @@ struct MemoryDump
DbgAddr address;
QString dump;
bool littleendian = true;
bool endOfDump = false;
};

/**
Expand Down Expand Up @@ -592,6 +593,7 @@ class DebuggerDriver : public QProcess
virtual QString makeCmdString(DbgCommand cmd, QString strArg, int intArg) = 0;
virtual QString makeCmdString(DbgCommand cmd, QString strArg1, QString strArg2) = 0;
virtual QString makeCmdString(DbgCommand cmd, int intArg1, int intArg2) = 0;
virtual QString makeCmdString(DbgCommand cmd, QString strArg, int intArg1, int intArg2) = 0;

protected:
void processOutput(const QByteArray& data);
Expand Down
32 changes: 22 additions & 10 deletions kdbg/debugger.cpp
Expand Up @@ -63,6 +63,7 @@ KDebugger::KDebugger(QWidget* parent,
QObject(parent),
m_ttyLevel(ttyFull),
m_memoryFormat(MDTword | MDThex),
m_memoryLength(16),
m_haveExecutable(false),
m_programActive(false),
m_programRunning(false),
Expand Down Expand Up @@ -1282,8 +1283,8 @@ void KDebugger::updateAllExprs()
m_d->queueCmd(DCinforegisters);

// get new memory dump
if (!m_memoryExpression.isEmpty()) {
queueMemoryDump(false);
if (!m_memoryStartExpression.isEmpty()) {
queueMemoryDump(false, true);
}

// update watch expressions
Expand Down Expand Up @@ -2157,25 +2158,36 @@ void KDebugger::setThread(int id)
m_d->queueCmdPrio(DCthread, id);
}

void KDebugger::setMemoryExpression(const QString& memexpr)
void KDebugger::setMemoryExpression(const QString& start_memexpr, unsigned total_length,
const QString& current_memexpr, unsigned current_length)
{
m_memoryExpression = memexpr;
m_memoryExpression = current_memexpr;
m_memoryLength = current_length;
m_memoryStartExpression = start_memexpr;
m_memoryTotalLength = total_length;

// queue the new expression
if (!m_memoryExpression.isEmpty() &&
isProgramActive() &&
!isProgramRunning())
{
queueMemoryDump(true);
queueMemoryDump(true, false);
}
}

void KDebugger::queueMemoryDump(bool immediate)
void KDebugger::queueMemoryDump(bool immediate, bool update)
{
if (immediate)
m_d->queueCmdPrio(DCexamine, m_memoryExpression, m_memoryFormat);
else
m_d->queueCmd(DCexamine, m_memoryExpression, m_memoryFormat);
if (update) {
if (immediate)
m_d->queueCmdPrio(DCexamine, m_memoryStartExpression, m_memoryFormat, m_memoryTotalLength);
else
m_d->queueCmd(DCexamine, m_memoryStartExpression, m_memoryFormat, m_memoryTotalLength);
} else {
if (immediate)
m_d->queueCmdPrio(DCexamine, m_memoryExpression, m_memoryFormat, m_memoryLength);
else
m_d->queueCmd(DCexamine, m_memoryExpression, m_memoryFormat, m_memoryLength);
}
}

void KDebugger::handleMemoryDump(const char* output)
Expand Down
10 changes: 8 additions & 2 deletions kdbg/debugger.h
Expand Up @@ -337,8 +337,11 @@ public slots:
/**
* The memory at that the expression evaluates to is watched. Can be
* empty. Triggers a redisplay even if the expression did not change.
* Memory expression start and total length is used to update all bytes of memory when
* is necessary, to request new parts of memory is used current_memexpr and current_length
*/
void setMemoryExpression(const QString& memexpr);
void setMemoryExpression(const QString& start_memexpr, unsigned total_length,
const QString& current_memexpr, unsigned current_length);

/**
* Sets how the watched memory location is displayed.
Expand All @@ -362,6 +365,9 @@ public slots:
std::list<Breakpoint> m_brkpts;
QString m_memoryExpression; /* memory location to watch */
unsigned m_memoryFormat; /* how that output should look */
unsigned m_memoryLength; /* memory length to watch */
QString m_memoryStartExpression; /* start memory location to watch */
unsigned m_memoryTotalLength; /* memory total length to watch */

protected slots:
void parse(CmdQueueItem* cmd, const char* output);
Expand Down Expand Up @@ -393,7 +399,7 @@ protected slots:
void evalStructExpression(VarTree* var, ExprWnd* wnd, bool immediate);
void dereferencePointer(ExprWnd* wnd, VarTree* var, bool immediate);
void determineType(ExprWnd* wnd, VarTree* var);
void queueMemoryDump(bool immediate);
void queueMemoryDump(bool immediate, bool update);
CmdQueueItem* loadCoreFile();
void openProgramConfig(const QString& name);

Expand Down
80 changes: 40 additions & 40 deletions kdbg/gdbdriver.cpp
Expand Up @@ -464,12 +464,44 @@ QString GdbDriver::makeCmdString(DbgCommand cmd, int intArg)
return cmdString;
}

QString GdbDriver::makeCmdString(DbgCommand cmd, QString strArg, int intArg1, int intArg2)
{
assert(cmd == DCexamine);

normalizeStringArg(strArg);

QString cmdString;

if (cmd == DCexamine) {
// make a format specifier from the intArg
static const char size[16] = {
'\0', 'b', 'h', 'w', 'g'
};
static const char format[16] = {
'\0', 'x', 'd', 'u', 'o', 't',
'a', 'c', 'f', 's', 'i'
};
assert(MDTsizemask == 0xf); /* lowest 4 bits */
assert(MDTformatmask == 0xf0); /* next 4 bits */
int count = intArg2; /* number of entities to print */
char sizeSpec = size[intArg1 & MDTsizemask];
char formatSpec = format[(intArg1 & MDTformatmask) >> 4];
assert(sizeSpec != '\0');
assert(formatSpec != '\0');

QString spec;
spec.sprintf("/%d%c%c", count, sizeSpec, formatSpec);
cmdString = makeCmdString(DCexamine, spec, strArg);
}

return cmdString;
}

QString GdbDriver::makeCmdString(DbgCommand cmd, QString strArg, int intArg)
{
assert(cmd >= 0 && cmd < NUM_CMDS);
assert(cmds[cmd].argsNeeded == GdbCmdInfo::argStringNum ||
cmds[cmd].argsNeeded == GdbCmdInfo::argNumString ||
cmd == DCexamine ||
cmd == DCtty);

normalizeStringArg(strArg);
Expand Down Expand Up @@ -504,45 +536,6 @@ QString GdbDriver::makeCmdString(DbgCommand cmd, QString strArg, int intArg)
return makeCmdString(DCtty, strArg); /* note: no problem if strArg empty */
}

if (cmd == DCexamine) {
// make a format specifier from the intArg
static const char size[16] = {
'\0', 'b', 'h', 'w', 'g'
};
static const char format[16] = {
'\0', 'x', 'd', 'u', 'o', 't',
'a', 'c', 'f', 's', 'i'
};
assert(MDTsizemask == 0xf); /* lowest 4 bits */
assert(MDTformatmask == 0xf0); /* next 4 bits */
int count = 16; /* number of entities to print */
char sizeSpec = size[intArg & MDTsizemask];
char formatSpec = format[(intArg & MDTformatmask) >> 4];
assert(sizeSpec != '\0');
assert(formatSpec != '\0');
// adjust count such that 16 lines are printed
switch (intArg & MDTformatmask) {
case MDTstring: case MDTinsn:
break; /* no modification needed */
default:
// all cases drop through:
switch (intArg & MDTsizemask) {
case MDTbyte:
case MDThalfword:
count *= 2;
case MDTword:
count *= 2;
case MDTgiantword:
count *= 2;
}
break;
}
QString spec;
spec.sprintf("/%d%c%c", count, sizeSpec, formatSpec);

return makeCmdString(DCexamine, spec, strArg);
}

if (cmds[cmd].argsNeeded == GdbCmdInfo::argStringNum)
{
// line numbers are zero-based
Expand Down Expand Up @@ -2683,10 +2676,14 @@ QString GdbDriver::parseMemoryDump(const char* output, std::list<MemoryDump>& me
MemoryDump md;

// the address
skipSpace(p); /* remove leading space, detected on instructions output format */

const char* start = p;

while (*p != '\0' && *p != ':' && !isspace(*p))
p++;
md.address = QString::fromLatin1(start, p-start);

if (*p != ':') {
// parse function offset
skipSpace(p);
Expand All @@ -2711,6 +2708,9 @@ QString GdbDriver::parseMemoryDump(const char* output, std::list<MemoryDump>& me
md.littleendian = m_littleendian;
memdump.push_back(md);
}

if (end_region && !memdump.empty())
memdump.back().endOfDump = true;

return QString();
}
Expand Down
1 change: 1 addition & 0 deletions kdbg/gdbdriver.h
Expand Up @@ -65,6 +65,7 @@ class GdbDriver : public DebuggerDriver
virtual QString makeCmdString(DbgCommand cmd, QString strArg, int intArg);
virtual QString makeCmdString(DbgCommand cmd, QString strArg1, QString strArg2);
virtual QString makeCmdString(DbgCommand cmd, int intArg1, int intArg2);
virtual QString makeCmdString(DbgCommand cmd, QString strArg, int intArg1, int intArg2);
virtual int findPrompt(const QByteArray& output) const;
void parseMarker(CmdQueueItem* cmd);
};
Expand Down

0 comments on commit 331a4e1

Please sign in to comment.