Commit eafde22e authored by hjk's avatar hjk
Browse files

Debugger: Handle extra dumpers with LLDB



This generalizes part of the previously GDB-only code paths

Change-Id: Id32798073e3c8bcb23bfedf463bebc866c8275e2
Reviewed-by: default avatarhjk <hjk@theqtcompany.com>
parent 39a1293e
......@@ -34,6 +34,8 @@ import sys
import base64
import re
import time
import importlib
try:
import subprocess
hasSubprocess = True
......@@ -1635,6 +1637,65 @@ class DumperBase:
self.currentNumChild = 0
self.putNumChild(0)
def registerDumper(self, funcname, function):
try:
#warn("FUNCTION: %s " % funcname)
#funcname = function.func_name
if funcname.startswith("qdump__"):
typename = funcname[7:]
self.qqDumpers[typename] = function
self.qqFormats[typename] = self.qqFormats.get(typename, "")
elif funcname.startswith("qform__"):
typename = funcname[7:]
formats = ""
try:
formats = function()
except:
pass
self.qqFormats[typename] = formats
elif funcname.startswith("qedit__"):
typename = funcname[7:]
try:
self.qqEditable[typename] = function
except:
pass
except:
pass
def findDumperFunctions(self):
self.qqDumpers = {}
self.qqFormats = {}
self.qqEditable = {}
self.typeCache = {}
for mod in dumpermodules:
m = importlib.import_module(mod)
dic = m.__dict__
for name in dic.keys():
item = dic[name]
self.registerDumper(name, item)
return self.reportDumpers()
def reportDumpers(self):
result = "dumpers=["
for key, value in self.qqFormats.items():
if key in self.qqEditable:
result += '{type="%s",formats="%s",editable="true"},' % (key, value)
else:
result += '{type="%s",formats="%s"},' % (key, value)
result += ']'
return result
def reloadDumper(self):
for mod in dumpermodules:
m = sys.modules[mod]
if sys.version_info[0] >= 3:
importlib.reload(m)
else:
reload(m)
findDumperFunctions()
# Some "Enums"
......@@ -1681,3 +1742,12 @@ DisplayUtf8String \
= range(6)
dumpermodules = [
"qttypes",
"stdtypes",
"misctypes",
"boosttypes",
"creatortypes",
"personaltypes",
]
......@@ -14,25 +14,11 @@ import sys
import struct
import types
import importlib
def warn(message):
print("XXX: %s\n" % message.encode("latin1"))
from dumper import *
dumpermodules = [
"qttypes",
"stdtypes",
"misctypes",
"boosttypes",
"creatortypes",
"personaltypes",
]
for mod in dumpermodules:
importlib.import_module(mod)
#######################################################################
#
......@@ -150,8 +136,7 @@ ScanStackCommand()
def bbsetup(args = ''):
theDumper.bbsetup()
print(theDumper.reportDumpers())
print(theDumper.findDumperFunctions())
registerCommand("bbsetup", bbsetup)
......@@ -1423,55 +1408,6 @@ class Dumper(DumperBase):
with Children(self, 1):
self.listAnonymous(value, name, field.type)
def registerDumper(self, funcname, function):
try:
#warn("FUNCTION: %s " % funcname)
#funcname = function.func_name
if funcname.startswith("qdump__"):
typename = funcname[7:]
self.qqDumpers[typename] = function
self.qqFormats[typename] = self.qqFormats.get(typename, "")
elif funcname.startswith("qform__"):
typename = funcname[7:]
formats = ""
try:
formats = function()
except:
pass
self.qqFormats[typename] = formats
elif funcname.startswith("qedit__"):
typename = funcname[7:]
try:
self.qqEditable[typename] = function
except:
pass
except:
pass
def bbsetup(self):
self.qqDumpers = {}
self.qqFormats = {}
self.qqEditable = {}
self.typeCache = {}
for mod in dumpermodules:
m = importlib.import_module(mod)
dic = m.__dict__
for name in dic.keys():
item = dic[name]
self.registerDumper(name, item)
def reportDumpers(self):
result = "dumpers=["
for key, value in self.qqFormats.items():
if key in self.qqEditable:
result += '{type="%s",formats="%s",editable="true"},' % (key, value)
else:
result += '{type="%s",formats="%s"},' % (key, value)
result += ']'
return result
#def threadname(self, maximalStackDepth, objectPrivateType):
# e = gdb.selected_frame()
# out = ""
......@@ -2044,15 +1980,8 @@ registerCommand("threadnames", threadnames)
#
#######################################################################
def reloadDumper(arg):
for mod in dumpermodules:
m = sys.modules[mod]
if sys.version_info[0] >= 3:
importlib.reload(m)
else:
reload(m)
bbsetup()
def reloadDumper(_):
theDumper.reloadDumper();
registerCommand("reload", reloadDumper)
......
......@@ -672,7 +672,6 @@ class Dumper(DumperBase):
self.target = self.debugger.CreateTarget(self.executable_, None, None, True, error)
else:
self.target = self.debugger.CreateTarget(None, None, None, True, error)
self.importDumpers()
state = "inferiorsetupok" if self.target.IsValid() else "inferiorsetupfailed"
self.report('state="%s",msg="%s",exe="%s"' % (state, error, self.executable_))
......@@ -1583,7 +1582,7 @@ class Dumper(DumperBase):
path = args['path']
(head, tail) = os.path.split(path)
sys.path.insert(1, head)
#dumpermodules.append(os.path.splitext(tail)[0])
dumpermodules.append(os.path.splitext(tail)[0])
self.report('ok')
def updateData(self, args):
......@@ -1642,6 +1641,10 @@ class Dumper(DumperBase):
result += ',offset="%s"},' % (addr - base)
self.report(result + ']')
def loadDumperFiles(self, _ = None):
result = self.findDumperFunctions()
self.report(result)
def fetchMemory(self, args):
address = args['address']
length = args['length']
......@@ -1668,35 +1671,6 @@ class Dumper(DumperBase):
self.reportError(error)
self.reportVariables()
def registerDumper(self, function):
if hasattr(function, 'func_name'):
funcname = function.func_name
if funcname.startswith("qdump__"):
type = funcname[7:]
self.qqDumpers[type] = function
self.qqFormats[type] = self.qqFormats.get(type, "")
elif funcname.startswith("qform__"):
type = funcname[7:]
formats = ""
try:
formats = function()
except:
pass
self.qqFormats[type] = formats
elif funcname.startswith("qedit__"):
type = funcname[7:]
try:
self.qqEditable[type] = function
except:
pass
def importDumpers(self, _ = None):
result = lldb.SBCommandReturnObject()
interpreter = self.debugger.GetCommandInterpreter()
items = globals()
for key in items:
self.registerDumper(items[key])
def execute(self, args):
getattr(self, args['cmd'])(args)
self.report('token="%s"' % args['token'])
......@@ -1754,7 +1728,7 @@ class Tester(Dumper):
self.expandedINames = set(sys.argv[3].split(','))
self.passExceptions = True
self.importDumpers()
self.loadDumperFiles()
error = lldb.SBError()
self.target = self.debugger.CreateTarget(sys.argv[2],
None, None, True, error)
......
......@@ -1737,22 +1737,7 @@ void GdbEngine::handlePythonSetup(const GdbResponse &response)
if (response.resultClass == GdbResultDone) {
GdbMi data;
data.fromStringMultiple(response.consoleStreamOutput);
const GdbMi dumpers = data["dumpers"];
foreach (const GdbMi &dumper, dumpers.children()) {
QByteArray type = dumper["type"].data();
QStringList formats(tr("Raw structure"));
foreach (const QByteArray &format,
dumper["formats"].data().split(',')) {
if (format == "Normal")
formats.append(tr("Normal"));
else if (format == "Displayed")
formats.append(tr("Displayed"));
else if (!format.isEmpty())
formats.append(_(format));
}
watchHandler()->addTypeFormats(type, formats);
}
watchHandler()->addDumpers(data["dumpers"]);
loadInitScript();
QTC_ASSERT(state() == EngineSetupRequested, qDebug() << state());
showMessage(_("ENGINE SUCCESSFULLY STARTED"));
......
......@@ -281,10 +281,13 @@ void LldbEngine::setupInferior()
const QString commands = stringSetting(ExtraDumperCommands);
if (!commands.isEmpty()) {
Command cmd("executeDebuggerCommand");
cmd.arg(commands.toUtf8());
cmd.arg("commands", commands.toUtf8());
runCommand(cmd);
}
Command cmd1("loadDumperFiles");
runCommand(cmd1);
QString executable;
QtcProcess::Arguments args;
QtcProcess::prepareCommand(QFileInfo(sp.executable).absoluteFilePath(),
......@@ -409,6 +412,8 @@ void LldbEngine::handleResponse(const QByteArray &response)
const QByteArray name = item.name();
if (name == "data")
refreshLocals(item);
else if (name == "dumpers")
watchHandler()->addDumpers(item);
else if (name == "stack")
refreshStack(item);
else if (name == "stack-position")
......
......@@ -1783,6 +1783,22 @@ QByteArray WatchHandler::individualFormatRequests() const
return ba;
}
void WatchHandler::addDumpers(const GdbMi &dumpers)
{
foreach (const GdbMi &dumper, dumpers.children()) {
QStringList formats(tr("Raw structure"));
foreach (const QByteArray &format, dumper["formats"].data().split(',')) {
if (format == "Normal")
formats.append(tr("Normal"));
else if (format == "Displayed")
formats.append(tr("Displayed"));
else if (!format.isEmpty())
formats.append(QString::fromLatin1(format));
}
addTypeFormats(dumper["type"].data(), formats);
}
}
void WatchHandler::addTypeFormats(const QByteArray &type, const QStringList &formats)
{
m_model->m_reportedTypeFormats.insert(QLatin1String(stripForFormat(type)), formats);
......
......@@ -217,6 +217,7 @@ public:
int format(const QByteArray &iname) const;
void addDumpers(const GdbMi &dumpers);
void addTypeFormats(const QByteArray &type, const QStringList &formats);
void setTypeFormats(const DumperTypeFormats &typeFormats);
DumperTypeFormats typeFormats() const;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment