forked from qt-creator/qt-creator
Debugger: Claim a few more capabilities for LLDB engine
This will need further fine tuning. Change-Id: Ia8926a73adfdf3de313cd379c4d6452b0af56ca0 Reviewed-by: hjk <hjk121@nokiamail.com>
This commit is contained in:
@@ -841,6 +841,7 @@ qqEditable = {}
|
||||
qqStripForFormat = {}
|
||||
|
||||
def stripForFormat(typeName):
|
||||
global qqStripForFormat
|
||||
if typeName in qqStripForFormat:
|
||||
return qqStripForFormat[typeName]
|
||||
stripped = ""
|
||||
@@ -860,42 +861,31 @@ def stripForFormat(typeName):
|
||||
qqStripForFormat[typeName] = stripped
|
||||
return stripped
|
||||
|
||||
def bbsetup(args = ''):
|
||||
typeCache = {}
|
||||
module = sys.modules[__name__]
|
||||
for key, value in module.__dict__.items():
|
||||
if key.startswith("qdump__"):
|
||||
name = key[7:]
|
||||
qqDumpers[name] = value
|
||||
qqFormats[name] = qqFormats.get(name, "")
|
||||
elif key.startswith("qform__"):
|
||||
name = key[7:]
|
||||
|
||||
def registerDumper(function):
|
||||
global qqDumpers, qqFormats, qqEditable
|
||||
try:
|
||||
funcname = function.func_name
|
||||
if funcname.startswith("qdump__"):
|
||||
type = funcname[7:]
|
||||
qqDumpers[type] = function
|
||||
qqFormats[type] = qqFormats.get(type, "")
|
||||
elif funcname.startswith("qform__"):
|
||||
type = funcname[7:]
|
||||
formats = ""
|
||||
try:
|
||||
formats = value()
|
||||
formats = function()
|
||||
except:
|
||||
pass
|
||||
qqFormats[name] = formats
|
||||
elif key.startswith("qedit__"):
|
||||
name = key[7:]
|
||||
qqFormats[type] = formats
|
||||
elif funcname.startswith("qedit__"):
|
||||
type = funcname[7:]
|
||||
try:
|
||||
qqEditable[name] = value
|
||||
qqEditable[type] = function
|
||||
except:
|
||||
pass
|
||||
result = "dumpers=["
|
||||
#qqNs = qtNamespace() # This is too early
|
||||
for key, value in qqFormats.items():
|
||||
if qqEditable.has_key(key):
|
||||
result += '{type="%s",formats="%s",editable="true"},' % (key, value)
|
||||
else:
|
||||
result += '{type="%s",formats="%s"},' % (key, value)
|
||||
result += ']'
|
||||
#result += ',namespace="%s"' % qqNs
|
||||
result += ',hasInferiorThreadList="%s"' % int(hasInferiorThreadList())
|
||||
return result
|
||||
|
||||
registerCommand("bbsetup", bbsetup)
|
||||
|
||||
except:
|
||||
pass
|
||||
|
||||
#######################################################################
|
||||
#
|
||||
@@ -904,6 +894,7 @@ registerCommand("bbsetup", bbsetup)
|
||||
#######################################################################
|
||||
|
||||
def bbedit(args):
|
||||
global qqEditable
|
||||
(type, expr, value) = args.split(",")
|
||||
type = base64.b16decode(type, True)
|
||||
ns = qtNamespace()
|
||||
@@ -1431,6 +1422,8 @@ class Dumper:
|
||||
self.putNumChild(0)
|
||||
return
|
||||
|
||||
global qqDumpers, qqFormats
|
||||
|
||||
type = value.type.unqualified()
|
||||
typeName = str(type)
|
||||
tryDynamic &= self.useDynamicType
|
||||
@@ -1666,8 +1659,8 @@ class Dumper:
|
||||
return
|
||||
|
||||
# Fall back to plain pointer printing.
|
||||
warn("GENERIC PLAIN POINTER: %s" % value.type)
|
||||
warn("ADDR PLAIN POINTER: %s" % value.address)
|
||||
#warn("GENERIC PLAIN POINTER: %s" % value.type)
|
||||
#warn("ADDR PLAIN POINTER: %s" % value.address)
|
||||
self.putType(typeName)
|
||||
self.putField("aaa", "1")
|
||||
#self.put('addr="0x%x",' % long(value.address))
|
||||
@@ -1733,6 +1726,7 @@ class Dumper:
|
||||
return
|
||||
|
||||
#warn(" STRIPPED: %s" % nsStrippedType)
|
||||
#warn(" DUMPERS: %s" % qqDumpers)
|
||||
#warn(" DUMPERS: %s" % (nsStrippedType in qqDumpers))
|
||||
dumper = qqDumpers.get(nsStrippedType, None)
|
||||
if not dumper is None:
|
||||
@@ -1942,44 +1936,6 @@ def threadnames(arg):
|
||||
registerCommand("threadnames", threadnames)
|
||||
|
||||
|
||||
#######################################################################
|
||||
#
|
||||
# Import plain gdb pretty printers
|
||||
#
|
||||
#######################################################################
|
||||
|
||||
class PlainDumper:
|
||||
def __init__(self, printer):
|
||||
self.printer = printer
|
||||
|
||||
def __call__(self, d, value):
|
||||
printer = self.printer.gen_printer(value)
|
||||
lister = getattr(printer, "children", None)
|
||||
children = [] if lister is None else list(lister())
|
||||
d.putType(self.printer.name)
|
||||
val = printer.to_string().encode("hex")
|
||||
d.putValue(val, Hex2EncodedLatin1)
|
||||
d.putValue(printer.to_string())
|
||||
d.putNumChild(len(children))
|
||||
if d.isExpanded():
|
||||
with Children(d):
|
||||
for child in children:
|
||||
d.putSubItem(child[0], child[1])
|
||||
|
||||
def importPlainDumper(printer):
|
||||
name = printer.name.replace("::", "__")
|
||||
qqDumpers[name] = PlainDumper(printer)
|
||||
qqFormats[name] = ""
|
||||
|
||||
def importPlainDumpers(args):
|
||||
for obj in gdb.objfiles():
|
||||
for printers in obj.pretty_printers + gdb.pretty_printers:
|
||||
for printer in printers.subprinters:
|
||||
importPlainDumper(printer)
|
||||
|
||||
registerCommand("importPlainDumpers", importPlainDumpers)
|
||||
|
||||
|
||||
#######################################################################
|
||||
#
|
||||
# Mixed C++/Qml debugging
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
|
||||
import binascii
|
||||
import gdb
|
||||
import inspect
|
||||
import os
|
||||
import sys
|
||||
import traceback
|
||||
import gdb
|
||||
|
||||
cdbLoaded = False
|
||||
lldbLoaded = False
|
||||
@@ -333,8 +334,72 @@ class ScanStackCommand(gdb.Command):
|
||||
ScanStackCommand()
|
||||
|
||||
|
||||
def bbsetup(args = ''):
|
||||
global qqDumpers, qqFormats, qqEditable, typeCache
|
||||
typeCache = {}
|
||||
module = sys.modules[__name__]
|
||||
|
||||
for key, value in module.__dict__.items():
|
||||
registerDumper(value)
|
||||
|
||||
result = "dumpers=["
|
||||
#qqNs = qtNamespace() # This is too early
|
||||
for key, value in qqFormats.items():
|
||||
if qqEditable.has_key(key):
|
||||
result += '{type="%s",formats="%s",editable="true"},' % (key, value)
|
||||
else:
|
||||
result += '{type="%s",formats="%s"},' % (key, value)
|
||||
result += ']'
|
||||
#result += ',namespace="%s"' % qqNs
|
||||
result += ',hasInferiorThreadList="%s"' % int(hasInferiorThreadList())
|
||||
return result
|
||||
|
||||
registerCommand("bbsetup", bbsetup)
|
||||
|
||||
|
||||
#######################################################################
|
||||
#
|
||||
# Import plain gdb pretty printers
|
||||
#
|
||||
#######################################################################
|
||||
|
||||
class PlainDumper:
|
||||
def __init__(self, printer):
|
||||
self.printer = printer
|
||||
|
||||
def __call__(self, d, value):
|
||||
printer = self.printer.gen_printer(value)
|
||||
lister = getattr(printer, "children", None)
|
||||
children = [] if lister is None else list(lister())
|
||||
d.putType(self.printer.name)
|
||||
val = printer.to_string().encode("hex")
|
||||
d.putValue(val, Hex2EncodedLatin1)
|
||||
d.putValue(printer.to_string())
|
||||
d.putNumChild(len(children))
|
||||
if d.isExpanded():
|
||||
with Children(d):
|
||||
for child in children:
|
||||
d.putSubItem(child[0], child[1])
|
||||
|
||||
def importPlainDumper(printer):
|
||||
global qqDumpers, qqFormats
|
||||
name = printer.name.replace("::", "__")
|
||||
qqDumpers[name] = PlainDumper(printer)
|
||||
qqFormats[name] = ""
|
||||
|
||||
def importPlainDumpers(args):
|
||||
return
|
||||
for obj in gdb.objfiles():
|
||||
for printers in obj.pretty_printers + gdb.pretty_printers:
|
||||
for printer in printers.subprinters:
|
||||
importPlainDumper(printer)
|
||||
|
||||
registerCommand("importPlainDumpers", importPlainDumpers)
|
||||
|
||||
|
||||
gdbLoaded = True
|
||||
currentDir = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))
|
||||
execfile(os.path.join(currentDir, "dumper.py"))
|
||||
execfile(os.path.join(currentDir, "qttypes.py"))
|
||||
|
||||
bbsetup()
|
||||
|
||||
@@ -49,10 +49,9 @@ SimpleValueCode = None # LLDB only
|
||||
#warn("LOADING LLDB")
|
||||
|
||||
# Data members
|
||||
SimpleValueCode, \
|
||||
StructCode, \
|
||||
PointerCode \
|
||||
= range(3)
|
||||
SimpleValueCode = 100
|
||||
StructCode = 101
|
||||
PointerCode = 102
|
||||
|
||||
# Breakpoints. Keep synchronized with BreakpointType in breakpoint.h
|
||||
UnknownType = 0
|
||||
@@ -95,6 +94,9 @@ class Type:
|
||||
def unqualified(self):
|
||||
return self
|
||||
|
||||
def strip_typedefs(self):
|
||||
return self
|
||||
|
||||
class Value:
|
||||
def __init__(self, var):
|
||||
self.raw = var
|
||||
@@ -106,6 +108,9 @@ class Value:
|
||||
def __str__(self):
|
||||
return str(self.raw.value)
|
||||
|
||||
def __getitem__(self, name):
|
||||
return None if self.raw is None else self.raw.GetChildMemberWithName(name)
|
||||
|
||||
def fields(self):
|
||||
return [Value(self.raw.GetChildAtIndex(i)) for i in range(self.raw.num_children)]
|
||||
|
||||
@@ -397,10 +402,22 @@ lldb.debugger.HandleCommand("settings set interpreter.prompt-on-quit off")
|
||||
lldb.debugger.HandleCommand("settings set frame-format ''")
|
||||
lldb.debugger.HandleCommand("settings set thread-format ''")
|
||||
|
||||
lldbLoaded = True
|
||||
|
||||
execfile(os.path.join(currentDir, "dumper.py"))
|
||||
execfile(os.path.join(currentDir, "qttypes.py"))
|
||||
|
||||
def importPlainDumpers(args):
|
||||
pass
|
||||
|
||||
def bbsetup(args = ''):
|
||||
global qqDumpers, qqFormats, qqEditable
|
||||
typeCache = {}
|
||||
|
||||
items = globals()
|
||||
for key in items:
|
||||
registerDumper(items[key])
|
||||
|
||||
bbsetup()
|
||||
|
||||
print "result={state=\"enginesetupok\"}"
|
||||
lldbLoaded = True
|
||||
|
||||
print "result={state=\"enginesetupok\",dumpers=\"%s\"}" % qqDumpers.keys()
|
||||
|
||||
@@ -1033,7 +1033,37 @@ void LldbEngine::refreshLocation(const GdbMi &reportedLocation)
|
||||
|
||||
bool LldbEngine::hasCapability(unsigned cap) const
|
||||
{
|
||||
return cap & (ReloadModuleCapability|BreakConditionCapability);
|
||||
if (cap & (ReverseSteppingCapability
|
||||
| AutoDerefPointersCapability
|
||||
| DisassemblerCapability
|
||||
| RegisterCapability
|
||||
| ShowMemoryCapability
|
||||
| JumpToLineCapability
|
||||
| ReloadModuleCapability
|
||||
| ReloadModuleSymbolsCapability
|
||||
| BreakOnThrowAndCatchCapability
|
||||
| BreakConditionCapability
|
||||
| TracePointCapability
|
||||
| ReturnFromFunctionCapability
|
||||
| CreateFullBacktraceCapability
|
||||
| WatchpointByAddressCapability
|
||||
| WatchpointByExpressionCapability
|
||||
| AddWatcherCapability
|
||||
| WatchWidgetsCapability
|
||||
| ShowModuleSymbolsCapability
|
||||
| ShowModuleSectionsCapability
|
||||
| CatchCapability
|
||||
| OperateByInstructionCapability
|
||||
| RunToLineCapability
|
||||
| WatchComplexExpressionsCapability
|
||||
| MemoryAddressCapability))
|
||||
return true;
|
||||
|
||||
if (startParameters().startMode == AttachCore)
|
||||
return false;
|
||||
|
||||
//return cap == SnapshotCapability;
|
||||
return false;
|
||||
}
|
||||
|
||||
DebuggerEngine *createLldbEngine(const DebuggerStartParameters &startParameters)
|
||||
|
||||
Reference in New Issue
Block a user