Debugger: Prepare assigning of values in LLDB interface

Change-Id: I722e78c352066ddd05e96199fd8ead088e3e9f59
Reviewed-by: hjk <hjk121@nokiamail.com>
This commit is contained in:
hjk
2013-05-30 15:35:52 +02:00
parent a7fa0dd4b9
commit 1dac4ba791
3 changed files with 82 additions and 81 deletions

View File

@@ -500,6 +500,7 @@ class Dumper:
self.currentPrintsAddress = None self.currentPrintsAddress = None
self.currentChildType = None self.currentChildType = None
self.currentChildNumChild = None self.currentChildNumChild = None
self.currentWatchers = {}
self.executable_ = None self.executable_ = None
self.charType_ = None self.charType_ = None
@@ -508,11 +509,12 @@ class Dumper:
self.charPtrType_ = None self.charPtrType_ = None
self.voidType_ = None self.voidType_ = None
self.isShuttingDown_ = False self.isShuttingDown_ = False
self.dummyValue = None
def extractTemplateArgument(self, typename, index): def extractTemplateArgument(self, typename, index):
level = 0 level = 0
skipSpace = False skipSpace = False
inner = "" inner = ''
for c in typename[typename.find('<') + 1 : -1]: for c in typename[typename.find('<') + 1 : -1]:
if c == '<': if c == '<':
inner += c inner += c
@@ -525,7 +527,7 @@ class Dumper:
if index == 0: if index == 0:
return inner return inner
index -= 1 index -= 1
inner = "" inner = ''
else: else:
inner += c inner += c
skipSpace = True skipSpace = True
@@ -736,11 +738,13 @@ class Dumper:
result = 'threads={threads=[' result = 'threads={threads=['
for i in xrange(0, self.process.GetNumThreads()): for i in xrange(0, self.process.GetNumThreads()):
thread = self.process.GetThreadAtIndex(i) thread = self.process.GetThreadAtIndex(i)
stopReason = thread.GetStopReason()
result += '{id="%d"' % thread.GetThreadID() result += '{id="%d"' % thread.GetThreadID()
result += ',index="%s"' % i result += ',index="%s"' % i
result += ',details="%s"' % thread.GetQueueName() result += ',details="%s"' % thread.GetQueueName()
result += ',state="%s"' % reasons[thread.GetStopReason()] result += ',stop-reason="%s"' % stopReason
result += ',stop-reason="%s"' % thread.GetStopReason() if stopReason >= 0 and stopReason < len(reasons):
result += ',state="%s"' % reasons[stopReason]
result += ',name="%s"' % thread.GetName() result += ',name="%s"' % thread.GetName()
result += ',frame={' result += ',frame={'
frame = thread.GetFrameAtIndex(0) frame = thread.GetFrameAtIndex(0)
@@ -931,12 +935,37 @@ class Dumper:
def reportVariables(self, _ = None): def reportVariables(self, _ = None):
frame = self.currentThread().GetSelectedFrame() frame = self.currentThread().GetSelectedFrame()
self.currentIName = "local" self.currentIName = 'local'
self.put('data=[') self.put('data=[')
for value in frame.GetVariables(True, True, False, False): for value in frame.GetVariables(True, True, False, False):
if self.dummyValue is None:
self.dummyValue = value
with SubItem(self, value): with SubItem(self, value):
self.put('iname="%s",' % self.currentIName) self.put('iname="%s",' % self.currentIName)
self.putItem(value) self.putItem(value)
# 'watchers':[{'id':'watch.0','exp':'23'},...]
if not self.dummyValue is None:
for watcher in self.currentWatchers:
iname = watcher['iname']
index = iname[iname.find('.') + 1:]
exp = binascii.unhexlify(watcher['exp'])
warn("EXP: %s" % exp)
warn("INDEX: %s" % index)
if exp == "":
self.put('type="",value="",exp=""')
continue
value = self.dummyValue.CreateValueFromExpression(iname, exp)
#value = self.dummyValue
warn("VALUE: %s" % value)
self.currentIName = 'watch'
with SubItem(self, index):
self.put('exp="%s",' % exp)
self.put('wname="%s",' % binascii.hexlify(exp))
self.put('iname="%s",' % self.currentIName)
self.putItem(value)
self.put(']') self.put(']')
self.report('') self.report('')
@@ -953,6 +982,7 @@ class Dumper:
self.reportVariables() self.reportVariables()
def reportRegisters(self, _ = None): def reportRegisters(self, _ = None):
return
if self.process is None: if self.process is None:
self.report('process="none"') self.report('process="none"')
else: else:
@@ -1225,13 +1255,19 @@ class Dumper:
def setOptions(self, args): def setOptions(self, args):
self.options = args self.options = args
def setWatchers(self, args):
self.currentWatchers = args['watchers']
warn("WATCHERS %s" % self.currentWatchers)
def updateData(self, args): def updateData(self, args):
self.expandedINames = set(args['expanded'].split(',')) self.expandedINames = set(args['expanded'].split(','))
self.autoDerefPointers = int(args['autoderef']) self.autoDerefPointers = int(args['autoderef'])
self.useDynamicType = int(args['dyntype']) self.useDynamicType = int(args['dyntype'])
# Keep always True for now. # Keep always True for now.
#self.passExceptions = args['pe'] #self.passExceptions = args['pe']
self.reportData() self.useDynamicType = int(args['dyntype'])
#self.reportData()
self.reportVariables(args)
def disassemble(self, args): def disassemble(self, args):
frame = self.currentFrame(); frame = self.currentFrame();
@@ -1263,6 +1299,18 @@ class Dumper:
result += ',contents="%s"}' % binascii.hexlify(contents) result += ',contents="%s"}' % binascii.hexlify(contents)
self.report(result) self.report(result)
def assignValue(self, args):
exp = binascii.unhexlify(args['exp'])
value = binascii.unhexlify(args['value'])
warn("EXP: %s" % exp)
warn("VALUE: %s" % value)
lhs = self.dummyValue.CreateValueFromExpression("$$lhs", exp)
rhs = self.dummyValue.CreateValueFromExpression("$$rhs", value)
warn("LHS: %s" % lhs)
warn("RHS: %s" % rhs)
#lhs.SetData(rhs.GetData())
self.reportVariables()
def importDumpers(self, _ = None): def importDumpers(self, _ = None):
result = lldb.SBCommandReturnObject() result = lldb.SBCommandReturnObject()
interpreter = self.debugger.GetCommandInterpreter() interpreter = self.debugger.GetCommandInterpreter()

View File

@@ -164,6 +164,8 @@ void LldbEngine::setupInferior()
{ {
QString executable = QFileInfo(startParameters().executable).absoluteFilePath(); QString executable = QFileInfo(startParameters().executable).absoluteFilePath();
runCommand(Command("setupInferior").arg("executable", executable)); runCommand(Command("setupInferior").arg("executable", executable));
requestUpdateWatchers();
} }
void LldbEngine::runEngine() void LldbEngine::runEngine()
@@ -676,18 +678,16 @@ void LldbEngine::updateAll()
// //
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
void LldbEngine::assignValueInDebugger(const Internal::WatchData *, const QString &expression, const QVariant &value) void LldbEngine::assignValueInDebugger(const Internal::WatchData *data,
const QString &expression, const QVariant &value)
{ {
Q_UNUSED(expression); Q_UNUSED(data);
Q_UNUSED(value); Command cmd("assignValue");
//SDEBUG("ASSIGNING: " << (expression + QLatin1Char('=') + value.toString())); cmd.arg("exp", expression.toLatin1().toHex());
#if 0 cmd.arg("value", value.toString().toLatin1().toHex());
m_scriptEngine->evaluate(expression + QLatin1Char('=') + value.toString()); runCommand(cmd);
updateLocals();
#endif
} }
void LldbEngine::updateWatchData(const WatchData &data, const WatchUpdateFlags &flags) void LldbEngine::updateWatchData(const WatchData &data, const WatchUpdateFlags &flags)
{ {
Q_UNUSED(data); Q_UNUSED(data);
@@ -699,12 +699,13 @@ void LldbEngine::updateLocals()
{ {
WatchHandler *handler = watchHandler(); WatchHandler *handler = watchHandler();
requestUpdateWatchers();
Command cmd("updateData"); Command cmd("updateData");
cmd.arg("expanded", handler->expansionRequests()); cmd.arg("expanded", handler->expansionRequests());
cmd.arg("typeformats", handler->typeFormatRequests()); cmd.arg("typeformats", handler->typeFormatRequests());
cmd.arg("formats", handler->individualFormatRequests()); cmd.arg("formats", handler->individualFormatRequests());
QList<QByteArray> watcherData;
// const QString fileName = stackHandler()->currentFrame().file; // const QString fileName = stackHandler()->currentFrame().file;
// if (!fileName.isEmpty()) { // if (!fileName.isEmpty()) {
// const QString function = stackHandler()->currentFrame().function; // const QString function = stackHandler()->currentFrame().function;
@@ -739,16 +740,6 @@ void LldbEngine::updateLocals()
// } // }
// } // }
QHashIterator<QByteArray, int> it(handler->watcherNames());
while (it.hasNext()) {
it.next();
QHash<QByteArray, QByteArray> hash;
hash["exp"] = '\'' + it.key() + '\'';
hash["id"] = "'watch." + QByteArray::number(it.value()) + '\'';
watcherData.append(Command::toData(hash));
}
cmd.args.append("'watchers':" + Command::toData(watcherData) + ',');
const static bool alwaysVerbose = !qgetenv("QTC_DEBUGGER_PYTHON_VERBOSE").isEmpty(); const static bool alwaysVerbose = !qgetenv("QTC_DEBUGGER_PYTHON_VERBOSE").isEmpty();
cmd.arg("passexeptions", alwaysVerbose); cmd.arg("passexeptions", alwaysVerbose);
cmd.arg("fancy", debuggerCore()->boolSetting(UseDebuggingHelpers)); cmd.arg("fancy", debuggerCore()->boolSetting(UseDebuggingHelpers));
@@ -839,58 +830,21 @@ void LldbEngine::readLldbStandardOutput()
} }
} }
QByteArray LldbEngine::currentOptions() const void LldbEngine::requestUpdateWatchers()
{ {
QByteArray localsOptions;
QByteArray stackOptions;
QByteArray threadsOptions;
{
QByteArray watchers;
//if (!m_toolTipExpression.isEmpty())
// watchers += m_toolTipExpression.toLatin1()
// + '#' + tooltipINameForExpression(m_toolTipExpression.toLatin1());
WatchHandler *handler = watchHandler(); WatchHandler *handler = watchHandler();
QHash<QByteArray, int> watcherNames = handler->watcherNames(); QHashIterator<QByteArray, int> it(handler->watcherNames());
QHashIterator<QByteArray, int> it(watcherNames); QList<QByteArray> watcherData;
while (it.hasNext()) { while (it.hasNext()) {
it.next(); it.next();
if (!watchers.isEmpty()) QHash<QByteArray, QByteArray> hash;
watchers += "##"; hash["iname"] = "'watch." + QByteArray::number(it.value()) + '\'';
watchers += it.key() + "#watch." + QByteArray::number(it.value()); hash["exp"] = '\'' + it.key().toHex() + '\'';
watcherData.append(Command::toData(hash));
} }
Command cmd("setWatchers");
QByteArray options; cmd.args.append("'watchers':" + Command::toData(watcherData) + ',');
if (debuggerCore()->boolSetting(UseDebuggingHelpers)) runCommand(cmd);
options += "fancy,";
if (debuggerCore()->boolSetting(AutoDerefPointers))
options += "autoderef,";
if (options.isEmpty())
options += "defaults,";
options.chop(1);
localsOptions = "options:" + options + " "
+ "vars: "
+ "expanded:" + handler->expansionRequests() + " "
+ "typeformats:" + handler->typeFormatRequests() + " "
+ "formats:" + handler->individualFormatRequests() + " "
+ "watcher:" + watchers.toHex();
}
{
int maxdepth = debuggerCore()->action(MaximalStackDepth)->value().toInt();
ThreadId curthread = threadsHandler()->currentThread();
stackOptions += "maxdepth:" + QByteArray::number(maxdepth);
stackOptions += ",curthread:" + QByteArray::number(curthread.raw());
}
QByteArray result;
result += "\"locals\":\"" + localsOptions + '"';
result += ",\"stack\":\"" + stackOptions + '"';
result += ",\"threads\":\"" + threadsOptions + '"';
return result;
} }
void LldbEngine::refreshLocals(const GdbMi &vars) void LldbEngine::refreshLocals(const GdbMi &vars)
@@ -911,10 +865,9 @@ void LldbEngine::refreshLocals(const GdbMi &vars)
dummy.iname = child["iname"].data(); dummy.iname = child["iname"].data();
GdbMi wname = child["wname"]; GdbMi wname = child["wname"];
if (wname.isValid()) { if (wname.isValid()) {
// Happens (only) for watched expressions. They are encoded as // Happens (only) for watched expressions.
// base64 encoded 8 bit data, without quotes dummy.exp = QByteArray::fromHex(wname.data());
dummy.name = decodeData(wname.data(), Base64Encoded8Bit); dummy.name = QString::fromUtf8(dummy.exp);
dummy.exp = dummy.name.toUtf8();
} else { } else {
dummy.name = child["name"].toUtf8(); dummy.name = child["name"].toUtf8();
} }

View File

@@ -134,6 +134,7 @@ private:
bool supportsThreads() const { return true; } bool supportsThreads() const { return true; }
bool isSynchronous() const { return true; } bool isSynchronous() const { return true; }
void updateWatchData(const WatchData &data, const WatchUpdateFlags &flags); void updateWatchData(const WatchData &data, const WatchUpdateFlags &flags);
void requestUpdateWatchers();
void setRegisterValue(int regnr, const QString &value); void setRegisterValue(int regnr, const QString &value);
void fetchMemory(Internal::MemoryAgent *, QObject *, quint64 addr, quint64 length); void fetchMemory(Internal::MemoryAgent *, QObject *, quint64 addr, quint64 length);
@@ -171,7 +172,6 @@ private:
typedef void (LldbEngine::*LldbCommandContinuation)(); typedef void (LldbEngine::*LldbCommandContinuation)();
QByteArray currentOptions() const;
void handleStop(const QByteArray &response); void handleStop(const QByteArray &response);
void handleListLocals(const QByteArray &response); void handleListLocals(const QByteArray &response);
void handleListModules(const QByteArray &response); void handleListModules(const QByteArray &response);