forked from qt-creator/qt-creator
Debugger: Prepare assigning of values in LLDB interface
Change-Id: I722e78c352066ddd05e96199fd8ead088e3e9f59 Reviewed-by: hjk <hjk121@nokiamail.com>
This commit is contained in:
@@ -500,6 +500,7 @@ class Dumper:
|
||||
self.currentPrintsAddress = None
|
||||
self.currentChildType = None
|
||||
self.currentChildNumChild = None
|
||||
self.currentWatchers = {}
|
||||
|
||||
self.executable_ = None
|
||||
self.charType_ = None
|
||||
@@ -508,11 +509,12 @@ class Dumper:
|
||||
self.charPtrType_ = None
|
||||
self.voidType_ = None
|
||||
self.isShuttingDown_ = False
|
||||
self.dummyValue = None
|
||||
|
||||
def extractTemplateArgument(self, typename, index):
|
||||
level = 0
|
||||
skipSpace = False
|
||||
inner = ""
|
||||
inner = ''
|
||||
for c in typename[typename.find('<') + 1 : -1]:
|
||||
if c == '<':
|
||||
inner += c
|
||||
@@ -525,7 +527,7 @@ class Dumper:
|
||||
if index == 0:
|
||||
return inner
|
||||
index -= 1
|
||||
inner = ""
|
||||
inner = ''
|
||||
else:
|
||||
inner += c
|
||||
skipSpace = True
|
||||
@@ -736,11 +738,13 @@ class Dumper:
|
||||
result = 'threads={threads=['
|
||||
for i in xrange(0, self.process.GetNumThreads()):
|
||||
thread = self.process.GetThreadAtIndex(i)
|
||||
stopReason = thread.GetStopReason()
|
||||
result += '{id="%d"' % thread.GetThreadID()
|
||||
result += ',index="%s"' % i
|
||||
result += ',details="%s"' % thread.GetQueueName()
|
||||
result += ',state="%s"' % reasons[thread.GetStopReason()]
|
||||
result += ',stop-reason="%s"' % thread.GetStopReason()
|
||||
result += ',stop-reason="%s"' % stopReason
|
||||
if stopReason >= 0 and stopReason < len(reasons):
|
||||
result += ',state="%s"' % reasons[stopReason]
|
||||
result += ',name="%s"' % thread.GetName()
|
||||
result += ',frame={'
|
||||
frame = thread.GetFrameAtIndex(0)
|
||||
@@ -931,12 +935,37 @@ class Dumper:
|
||||
|
||||
def reportVariables(self, _ = None):
|
||||
frame = self.currentThread().GetSelectedFrame()
|
||||
self.currentIName = "local"
|
||||
self.currentIName = 'local'
|
||||
self.put('data=[')
|
||||
for value in frame.GetVariables(True, True, False, False):
|
||||
if self.dummyValue is None:
|
||||
self.dummyValue = value
|
||||
with SubItem(self, value):
|
||||
self.put('iname="%s",' % self.currentIName)
|
||||
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.report('')
|
||||
|
||||
@@ -953,6 +982,7 @@ class Dumper:
|
||||
self.reportVariables()
|
||||
|
||||
def reportRegisters(self, _ = None):
|
||||
return
|
||||
if self.process is None:
|
||||
self.report('process="none"')
|
||||
else:
|
||||
@@ -1225,13 +1255,19 @@ class Dumper:
|
||||
def setOptions(self, args):
|
||||
self.options = args
|
||||
|
||||
def setWatchers(self, args):
|
||||
self.currentWatchers = args['watchers']
|
||||
warn("WATCHERS %s" % self.currentWatchers)
|
||||
|
||||
def updateData(self, args):
|
||||
self.expandedINames = set(args['expanded'].split(','))
|
||||
self.autoDerefPointers = int(args['autoderef'])
|
||||
self.useDynamicType = int(args['dyntype'])
|
||||
# Keep always True for now.
|
||||
#self.passExceptions = args['pe']
|
||||
self.reportData()
|
||||
self.useDynamicType = int(args['dyntype'])
|
||||
#self.reportData()
|
||||
self.reportVariables(args)
|
||||
|
||||
def disassemble(self, args):
|
||||
frame = self.currentFrame();
|
||||
@@ -1263,6 +1299,18 @@ class Dumper:
|
||||
result += ',contents="%s"}' % binascii.hexlify(contents)
|
||||
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):
|
||||
result = lldb.SBCommandReturnObject()
|
||||
interpreter = self.debugger.GetCommandInterpreter()
|
||||
|
||||
@@ -164,6 +164,8 @@ void LldbEngine::setupInferior()
|
||||
{
|
||||
QString executable = QFileInfo(startParameters().executable).absoluteFilePath();
|
||||
runCommand(Command("setupInferior").arg("executable", executable));
|
||||
|
||||
requestUpdateWatchers();
|
||||
}
|
||||
|
||||
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(value);
|
||||
//SDEBUG("ASSIGNING: " << (expression + QLatin1Char('=') + value.toString()));
|
||||
#if 0
|
||||
m_scriptEngine->evaluate(expression + QLatin1Char('=') + value.toString());
|
||||
updateLocals();
|
||||
#endif
|
||||
Q_UNUSED(data);
|
||||
Command cmd("assignValue");
|
||||
cmd.arg("exp", expression.toLatin1().toHex());
|
||||
cmd.arg("value", value.toString().toLatin1().toHex());
|
||||
runCommand(cmd);
|
||||
}
|
||||
|
||||
|
||||
void LldbEngine::updateWatchData(const WatchData &data, const WatchUpdateFlags &flags)
|
||||
{
|
||||
Q_UNUSED(data);
|
||||
@@ -699,12 +699,13 @@ void LldbEngine::updateLocals()
|
||||
{
|
||||
WatchHandler *handler = watchHandler();
|
||||
|
||||
requestUpdateWatchers();
|
||||
|
||||
Command cmd("updateData");
|
||||
cmd.arg("expanded", handler->expansionRequests());
|
||||
cmd.arg("typeformats", handler->typeFormatRequests());
|
||||
cmd.arg("formats", handler->individualFormatRequests());
|
||||
|
||||
QList<QByteArray> watcherData;
|
||||
// const QString fileName = stackHandler()->currentFrame().file;
|
||||
// if (!fileName.isEmpty()) {
|
||||
// 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();
|
||||
cmd.arg("passexeptions", alwaysVerbose);
|
||||
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();
|
||||
QHash<QByteArray, int> watcherNames = handler->watcherNames();
|
||||
QHashIterator<QByteArray, int> it(watcherNames);
|
||||
while (it.hasNext()) {
|
||||
it.next();
|
||||
if (!watchers.isEmpty())
|
||||
watchers += "##";
|
||||
watchers += it.key() + "#watch." + QByteArray::number(it.value());
|
||||
}
|
||||
|
||||
QByteArray options;
|
||||
if (debuggerCore()->boolSetting(UseDebuggingHelpers))
|
||||
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();
|
||||
WatchHandler *handler = watchHandler();
|
||||
QHashIterator<QByteArray, int> it(handler->watcherNames());
|
||||
QList<QByteArray> watcherData;
|
||||
while (it.hasNext()) {
|
||||
it.next();
|
||||
QHash<QByteArray, QByteArray> hash;
|
||||
hash["iname"] = "'watch." + QByteArray::number(it.value()) + '\'';
|
||||
hash["exp"] = '\'' + it.key().toHex() + '\'';
|
||||
watcherData.append(Command::toData(hash));
|
||||
}
|
||||
|
||||
{
|
||||
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;
|
||||
Command cmd("setWatchers");
|
||||
cmd.args.append("'watchers':" + Command::toData(watcherData) + ',');
|
||||
runCommand(cmd);
|
||||
}
|
||||
|
||||
void LldbEngine::refreshLocals(const GdbMi &vars)
|
||||
@@ -911,10 +865,9 @@ void LldbEngine::refreshLocals(const GdbMi &vars)
|
||||
dummy.iname = child["iname"].data();
|
||||
GdbMi wname = child["wname"];
|
||||
if (wname.isValid()) {
|
||||
// Happens (only) for watched expressions. They are encoded as
|
||||
// base64 encoded 8 bit data, without quotes
|
||||
dummy.name = decodeData(wname.data(), Base64Encoded8Bit);
|
||||
dummy.exp = dummy.name.toUtf8();
|
||||
// Happens (only) for watched expressions.
|
||||
dummy.exp = QByteArray::fromHex(wname.data());
|
||||
dummy.name = QString::fromUtf8(dummy.exp);
|
||||
} else {
|
||||
dummy.name = child["name"].toUtf8();
|
||||
}
|
||||
|
||||
@@ -134,6 +134,7 @@ private:
|
||||
bool supportsThreads() const { return true; }
|
||||
bool isSynchronous() const { return true; }
|
||||
void updateWatchData(const WatchData &data, const WatchUpdateFlags &flags);
|
||||
void requestUpdateWatchers();
|
||||
void setRegisterValue(int regnr, const QString &value);
|
||||
|
||||
void fetchMemory(Internal::MemoryAgent *, QObject *, quint64 addr, quint64 length);
|
||||
@@ -171,7 +172,6 @@ private:
|
||||
|
||||
typedef void (LldbEngine::*LldbCommandContinuation)();
|
||||
|
||||
QByteArray currentOptions() const;
|
||||
void handleStop(const QByteArray &response);
|
||||
void handleListLocals(const QByteArray &response);
|
||||
void handleListModules(const QByteArray &response);
|
||||
|
||||
Reference in New Issue
Block a user