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.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()
|
||||||
|
|||||||
@@ -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;
|
WatchHandler *handler = watchHandler();
|
||||||
QByteArray stackOptions;
|
QHashIterator<QByteArray, int> it(handler->watcherNames());
|
||||||
QByteArray threadsOptions;
|
QList<QByteArray> watcherData;
|
||||||
|
while (it.hasNext()) {
|
||||||
{
|
it.next();
|
||||||
QByteArray watchers;
|
QHash<QByteArray, QByteArray> hash;
|
||||||
//if (!m_toolTipExpression.isEmpty())
|
hash["iname"] = "'watch." + QByteArray::number(it.value()) + '\'';
|
||||||
// watchers += m_toolTipExpression.toLatin1()
|
hash["exp"] = '\'' + it.key().toHex() + '\'';
|
||||||
// + '#' + tooltipINameForExpression(m_toolTipExpression.toLatin1());
|
watcherData.append(Command::toData(hash));
|
||||||
|
|
||||||
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();
|
|
||||||
}
|
}
|
||||||
|
Command cmd("setWatchers");
|
||||||
{
|
cmd.args.append("'watchers':" + Command::toData(watcherData) + ',');
|
||||||
int maxdepth = debuggerCore()->action(MaximalStackDepth)->value().toInt();
|
runCommand(cmd);
|
||||||
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();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
Reference in New Issue
Block a user