forked from qt-creator/qt-creator
Debugger: Reorganize python dumper loading
- Split off GDB and LLDB specific parts into separate files, - Trigger loading of dumpers.py and qttypes.py from bridge.py - Read start up script at startup, not as part of dumper loading Change-Id: I7941ee535121fa0f43a466e5bb75a18c9bb19764 Reviewed-by: hjk <hjk121@nokiamail.com>
This commit is contained in:
@@ -1,5 +1,8 @@
|
|||||||
|
|
||||||
import binascii
|
import binascii
|
||||||
|
import inspect
|
||||||
|
import os
|
||||||
|
import traceback
|
||||||
|
|
||||||
cdbLoaded = False
|
cdbLoaded = False
|
||||||
lldbLoaded = False
|
lldbLoaded = False
|
||||||
@@ -11,14 +14,11 @@ gdbLoaded = False
|
|||||||
#
|
#
|
||||||
#######################################################################
|
#######################################################################
|
||||||
|
|
||||||
def showException(msg, exType, exValue, exTraceback):
|
currentDir = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))
|
||||||
warn("**** CAUGHT EXCEPTION: %s ****" % msg)
|
#print "DIR: %s " % currentDir
|
||||||
try:
|
|
||||||
import traceback
|
def warn(message):
|
||||||
for line in traceback.format_exception(exType, exValue, exTraceback):
|
print "XXX: %s\n" % message.encode("latin1")
|
||||||
warn("%s" % line)
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
|
|
||||||
PointerCode = None
|
PointerCode = None
|
||||||
ArrayCode = None
|
ArrayCode = None
|
||||||
@@ -46,688 +46,49 @@ TypedefCode = None
|
|||||||
NamespaceCode = None
|
NamespaceCode = None
|
||||||
SimpleValueCode = None # LLDB only
|
SimpleValueCode = None # LLDB only
|
||||||
|
|
||||||
|
failReasons = []
|
||||||
|
|
||||||
|
|
||||||
#######################################################################
|
|
||||||
#
|
|
||||||
# CDB
|
# CDB
|
||||||
#
|
if False:
|
||||||
#######################################################################
|
try:
|
||||||
|
import cdb_bridge
|
||||||
|
cdbLoaded = True
|
||||||
|
|
||||||
try:
|
except:
|
||||||
import cdb_bridge
|
failReasons.append(traceback.format_exc())
|
||||||
cdbLoaded = True
|
|
||||||
|
|
||||||
except:
|
|
||||||
#warn("LOADING CDB FAILED")
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
#######################################################################
|
|
||||||
#
|
|
||||||
# GDB
|
# GDB
|
||||||
#
|
if not cdbLoaded:
|
||||||
#######################################################################
|
try:
|
||||||
|
import gdb
|
||||||
try:
|
gdbLoaded = True
|
||||||
if cdbLoaded:
|
execfile(os.path.join(currentDir, "gbridge.py"))
|
||||||
raise "Not needed"
|
except:
|
||||||
|
failReasons.append(traceback.format_exc())
|
||||||
import gdb
|
|
||||||
gdbLoaded = True
|
|
||||||
|
|
||||||
def warn(message):
|
|
||||||
print "XXX: %s\n" % message.encode("latin1")
|
|
||||||
|
|
||||||
#warn("LOADING GDB")
|
|
||||||
|
|
||||||
#######################################################################
|
|
||||||
#
|
|
||||||
# Infrastructure
|
|
||||||
#
|
|
||||||
#######################################################################
|
|
||||||
|
|
||||||
def savePrint(output):
|
|
||||||
try:
|
|
||||||
print(output)
|
|
||||||
except:
|
|
||||||
out = ""
|
|
||||||
for c in output:
|
|
||||||
cc = ord(c)
|
|
||||||
if cc > 127:
|
|
||||||
out += "\\\\%d" % cc
|
|
||||||
elif cc < 0:
|
|
||||||
out += "\\\\%d" % (cc + 256)
|
|
||||||
else:
|
|
||||||
out += c
|
|
||||||
print(out)
|
|
||||||
|
|
||||||
def registerCommand(name, func):
|
|
||||||
|
|
||||||
class Command(gdb.Command):
|
|
||||||
def __init__(self):
|
|
||||||
super(Command, self).__init__(name, gdb.COMMAND_OBSCURE)
|
|
||||||
def invoke(self, args, from_tty):
|
|
||||||
savePrint(func(args))
|
|
||||||
|
|
||||||
Command()
|
|
||||||
|
|
||||||
def parseAndEvaluate(exp):
|
|
||||||
return gdb.parse_and_eval(exp)
|
|
||||||
|
|
||||||
def extractFields(value):
|
|
||||||
return value.type.fields()
|
|
||||||
## Insufficient, see http://sourceware.org/bugzilla/show_bug.cgi?id=10953:
|
|
||||||
##fields = type.fields()
|
|
||||||
## Insufficient, see http://sourceware.org/bugzilla/show_bug.cgi?id=11777:
|
|
||||||
##fields = defsype).fields()
|
|
||||||
## This seems to work.
|
|
||||||
##warn("TYPE 0: %s" % type)
|
|
||||||
#type = stripTypedefs(type)
|
|
||||||
#fields = type.fields()
|
|
||||||
#if len(fields):
|
|
||||||
# return fields
|
|
||||||
##warn("TYPE 1: %s" % type)
|
|
||||||
## This fails for arrays. See comment in lookupType.
|
|
||||||
#type0 = lookupType(str(type))
|
|
||||||
#if not type0 is None:
|
|
||||||
# type = type0
|
|
||||||
#if type.code == FunctionCode:
|
|
||||||
# return []
|
|
||||||
##warn("TYPE 2: %s" % type)
|
|
||||||
#fields = type.fields()
|
|
||||||
##warn("FIELDS: %s" % fields)
|
|
||||||
#return fields
|
|
||||||
|
|
||||||
def fieldCount(type):
|
|
||||||
return len(type.fields())
|
|
||||||
|
|
||||||
def listOfLocals(varList):
|
|
||||||
frame = gdb.selected_frame()
|
|
||||||
try:
|
|
||||||
frame = gdb.selected_frame()
|
|
||||||
#warn("FRAME %s: " % frame)
|
|
||||||
except RuntimeError, error:
|
|
||||||
warn("FRAME NOT ACCESSIBLE: %s" % error)
|
|
||||||
return []
|
|
||||||
except:
|
|
||||||
warn("FRAME NOT ACCESSIBLE FOR UNKNOWN REASONS")
|
|
||||||
return []
|
|
||||||
|
|
||||||
try:
|
|
||||||
block = frame.block()
|
|
||||||
#warn("BLOCK: %s " % block)
|
|
||||||
except RuntimeError, error:
|
|
||||||
warn("BLOCK IN FRAME NOT ACCESSIBLE: %s" % error)
|
|
||||||
return items
|
|
||||||
except:
|
|
||||||
warn("BLOCK NOT ACCESSIBLE FOR UNKNOWN REASONS")
|
|
||||||
return items
|
|
||||||
|
|
||||||
items = []
|
|
||||||
shadowed = {}
|
|
||||||
while True:
|
|
||||||
if block is None:
|
|
||||||
warn("UNEXPECTED 'None' BLOCK")
|
|
||||||
break
|
|
||||||
for symbol in block:
|
|
||||||
name = symbol.print_name
|
|
||||||
|
|
||||||
if name == "__in_chrg":
|
|
||||||
continue
|
|
||||||
|
|
||||||
# "NotImplementedError: Symbol type not yet supported in
|
|
||||||
# Python scripts."
|
|
||||||
#warn("SYMBOL %s (%s): " % (symbol, name))
|
|
||||||
if name in shadowed:
|
|
||||||
level = shadowed[name]
|
|
||||||
name1 = "%s@%s" % (name, level)
|
|
||||||
shadowed[name] = level + 1
|
|
||||||
else:
|
|
||||||
name1 = name
|
|
||||||
shadowed[name] = 1
|
|
||||||
#warn("SYMBOL %s (%s, %s)): " % (symbol, name, symbol.name))
|
|
||||||
item = LocalItem()
|
|
||||||
item.iname = "local." + name1
|
|
||||||
item.name = name1
|
|
||||||
try:
|
|
||||||
item.value = frame.read_var(name, block)
|
|
||||||
#warn("READ 1: %s" % item.value)
|
|
||||||
if not item.value.is_optimized_out:
|
|
||||||
#warn("ITEM 1: %s" % item.value)
|
|
||||||
items.append(item)
|
|
||||||
continue
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
|
|
||||||
try:
|
|
||||||
item.value = frame.read_var(name)
|
|
||||||
#warn("READ 2: %s" % item.value)
|
|
||||||
if not item.value.is_optimized_out:
|
|
||||||
#warn("ITEM 2: %s" % item.value)
|
|
||||||
items.append(item)
|
|
||||||
continue
|
|
||||||
except:
|
|
||||||
# RuntimeError: happens for
|
|
||||||
# void foo() { std::string s; std::wstring w; }
|
|
||||||
# ValueError: happens for (as of 2010/11/4)
|
|
||||||
# a local struct as found e.g. in
|
|
||||||
# gcc sources in gcc.c, int execute()
|
|
||||||
pass
|
|
||||||
|
|
||||||
try:
|
|
||||||
#warn("READ 3: %s %s" % (name, item.value))
|
|
||||||
item.value = gdb.parse_and_eval(name)
|
|
||||||
#warn("ITEM 3: %s" % item.value)
|
|
||||||
items.append(item)
|
|
||||||
except:
|
|
||||||
# Can happen in inlined code (see last line of
|
|
||||||
# RowPainter::paintChars(): "RuntimeError:
|
|
||||||
# No symbol \"__val\" in current context.\n"
|
|
||||||
pass
|
|
||||||
|
|
||||||
# The outermost block in a function has the function member
|
|
||||||
# FIXME: check whether this is guaranteed.
|
|
||||||
if not block.function is None:
|
|
||||||
break
|
|
||||||
|
|
||||||
block = block.superblock
|
|
||||||
|
|
||||||
return items
|
|
||||||
|
|
||||||
|
|
||||||
def catchCliOutput(command):
|
|
||||||
try:
|
|
||||||
return gdb.execute(command, to_string=True).split("\n")
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
filename = createTempFile()
|
|
||||||
gdb.execute("set logging off")
|
|
||||||
# gdb.execute("set logging redirect off")
|
|
||||||
gdb.execute("set logging file %s" % filename)
|
|
||||||
# gdb.execute("set logging redirect on")
|
|
||||||
gdb.execute("set logging on")
|
|
||||||
msg = ""
|
|
||||||
try:
|
|
||||||
gdb.execute(command)
|
|
||||||
except RuntimeError, error:
|
|
||||||
# For the first phase of core file loading this yield
|
|
||||||
# "No symbol table is loaded. Use the \"file\" command."
|
|
||||||
msg = str(error)
|
|
||||||
except:
|
|
||||||
msg = "Unknown error"
|
|
||||||
gdb.execute("set logging off")
|
|
||||||
# gdb.execute("set logging redirect off")
|
|
||||||
if len(msg):
|
|
||||||
# Having that might confuse result handlers in the gdbengine.
|
|
||||||
#warn("CLI ERROR: %s " % msg)
|
|
||||||
removeTempFile(filename)
|
|
||||||
return "CLI ERROR: %s " % msg
|
|
||||||
temp = open(filename, "r")
|
|
||||||
lines = []
|
|
||||||
for line in temp:
|
|
||||||
lines.append(line)
|
|
||||||
temp.close()
|
|
||||||
removeTempFile(filename)
|
|
||||||
return lines
|
|
||||||
|
|
||||||
def selectedInferior():
|
|
||||||
try:
|
|
||||||
# Does not exist in 7.3.
|
|
||||||
return gdb.selected_inferior()
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
# gdb.Inferior is new in gdb 7.2
|
|
||||||
return gdb.inferiors()[0]
|
|
||||||
|
|
||||||
def readRawMemory(base, size):
|
|
||||||
try:
|
|
||||||
inferior = selectedInferior()
|
|
||||||
return binascii.hexlify(inferior.read_memory(base, size))
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
s = ""
|
|
||||||
t = lookupType("unsigned char").pointer()
|
|
||||||
base = base.cast(t)
|
|
||||||
for i in xrange(size):
|
|
||||||
s += "%02x" % int(base.dereference())
|
|
||||||
base += 1
|
|
||||||
return s
|
|
||||||
|
|
||||||
|
|
||||||
#######################################################################
|
|
||||||
#
|
|
||||||
# Types
|
|
||||||
#
|
|
||||||
#######################################################################
|
|
||||||
|
|
||||||
PointerCode = gdb.TYPE_CODE_PTR
|
|
||||||
ArrayCode = gdb.TYPE_CODE_ARRAY
|
|
||||||
StructCode = gdb.TYPE_CODE_STRUCT
|
|
||||||
UnionCode = gdb.TYPE_CODE_UNION
|
|
||||||
EnumCode = gdb.TYPE_CODE_ENUM
|
|
||||||
FlagsCode = gdb.TYPE_CODE_FLAGS
|
|
||||||
FunctionCode = gdb.TYPE_CODE_FUNC
|
|
||||||
IntCode = gdb.TYPE_CODE_INT
|
|
||||||
FloatCode = gdb.TYPE_CODE_FLT # Parts of GDB assume that this means complex.
|
|
||||||
VoidCode = gdb.TYPE_CODE_VOID
|
|
||||||
#SetCode = gdb.TYPE_CODE_SET
|
|
||||||
RangeCode = gdb.TYPE_CODE_RANGE
|
|
||||||
StringCode = gdb.TYPE_CODE_STRING
|
|
||||||
#BitStringCode = gdb.TYPE_CODE_BITSTRING
|
|
||||||
#ErrorTypeCode = gdb.TYPE_CODE_ERROR
|
|
||||||
MethodCode = gdb.TYPE_CODE_METHOD
|
|
||||||
MethodPointerCode = gdb.TYPE_CODE_METHODPTR
|
|
||||||
MemberPointerCode = gdb.TYPE_CODE_MEMBERPTR
|
|
||||||
ReferenceCode = gdb.TYPE_CODE_REF
|
|
||||||
CharCode = gdb.TYPE_CODE_CHAR
|
|
||||||
BoolCode = gdb.TYPE_CODE_BOOL
|
|
||||||
ComplexCode = gdb.TYPE_CODE_COMPLEX
|
|
||||||
TypedefCode = gdb.TYPE_CODE_TYPEDEF
|
|
||||||
NamespaceCode = gdb.TYPE_CODE_NAMESPACE
|
|
||||||
#Code = gdb.TYPE_CODE_DECFLOAT # Decimal floating point.
|
|
||||||
#Code = gdb.TYPE_CODE_MODULE # Fortran
|
|
||||||
#Code = gdb.TYPE_CODE_INTERNAL_FUNCTION
|
|
||||||
|
|
||||||
#######################################################################
|
|
||||||
#
|
|
||||||
# Step Command
|
|
||||||
#
|
|
||||||
#######################################################################
|
|
||||||
|
|
||||||
def sal(args):
|
|
||||||
(cmd, addr) = args.split(",")
|
|
||||||
lines = catchCliOutput("info line *" + addr)
|
|
||||||
fromAddr = "0x0"
|
|
||||||
toAddr = "0x0"
|
|
||||||
for line in lines:
|
|
||||||
pos0from = line.find(" starts at address") + 19
|
|
||||||
pos1from = line.find(" ", pos0from)
|
|
||||||
pos0to = line.find(" ends at", pos1from) + 9
|
|
||||||
pos1to = line.find(" ", pos0to)
|
|
||||||
if pos1to > 0:
|
|
||||||
fromAddr = line[pos0from : pos1from]
|
|
||||||
toAddr = line[pos0to : pos1to]
|
|
||||||
gdb.execute("maint packet sal%s,%s,%s" % (cmd,fromAddr, toAddr))
|
|
||||||
|
|
||||||
registerCommand("sal", sal)
|
|
||||||
|
|
||||||
|
|
||||||
#######################################################################
|
|
||||||
#
|
|
||||||
# Convenience
|
|
||||||
#
|
|
||||||
#######################################################################
|
|
||||||
|
|
||||||
# Just convienience for 'python print ...'
|
|
||||||
class PPCommand(gdb.Command):
|
|
||||||
def __init__(self):
|
|
||||||
super(PPCommand, self).__init__("pp", gdb.COMMAND_OBSCURE)
|
|
||||||
def invoke(self, args, from_tty):
|
|
||||||
print(eval(args))
|
|
||||||
|
|
||||||
PPCommand()
|
|
||||||
|
|
||||||
# Just convienience for 'python print gdb.parse_and_eval(...)'
|
|
||||||
class PPPCommand(gdb.Command):
|
|
||||||
def __init__(self):
|
|
||||||
super(PPPCommand, self).__init__("ppp", gdb.COMMAND_OBSCURE)
|
|
||||||
def invoke(self, args, from_tty):
|
|
||||||
print(gdb.parse_and_eval(args))
|
|
||||||
|
|
||||||
PPPCommand()
|
|
||||||
|
|
||||||
|
|
||||||
def scanStack(p, n):
|
|
||||||
p = long(p)
|
|
||||||
r = []
|
|
||||||
for i in xrange(n):
|
|
||||||
f = gdb.parse_and_eval("{void*}%s" % p)
|
|
||||||
m = gdb.execute("info symbol %s" % f, to_string=True)
|
|
||||||
if not m.startswith("No symbol matches"):
|
|
||||||
r.append(m)
|
|
||||||
p += f.type.sizeof
|
|
||||||
return r
|
|
||||||
|
|
||||||
class ScanStackCommand(gdb.Command):
|
|
||||||
def __init__(self):
|
|
||||||
super(ScanStackCommand, self).__init__("scanStack", gdb.COMMAND_OBSCURE)
|
|
||||||
def invoke(self, args, from_tty):
|
|
||||||
if len(args) == 0:
|
|
||||||
args = 20
|
|
||||||
savePrint(scanStack(gdb.parse_and_eval("$sp"), int(args)))
|
|
||||||
|
|
||||||
ScanStackCommand()
|
|
||||||
|
|
||||||
|
|
||||||
except:
|
|
||||||
#warn("LOADING GDB FAILED")
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
#######################################################################
|
|
||||||
#
|
|
||||||
# LLDB
|
# LLDB
|
||||||
#
|
if not gdbLoaded and not cdbLoaded:
|
||||||
#######################################################################
|
try:
|
||||||
|
execfile(os.path.join(currentDir, "lbridge.py"))
|
||||||
|
lldbLoaded = True
|
||||||
|
except:
|
||||||
|
failReasons.append(traceback.format_exc())
|
||||||
|
|
||||||
|
|
||||||
|
# One is sufficient.
|
||||||
|
if cdbLoaded or gdbLoaded or lldbLoaded:
|
||||||
|
failReasons = []
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if gdbLoaded or cdbLoaded:
|
execfile(os.path.join(currentDir, "dumper.py"))
|
||||||
raise "Not needed"
|
execfile(os.path.join(currentDir, "qttypes.py"))
|
||||||
|
bbsetup()
|
||||||
lldbLoaded = True
|
|
||||||
|
|
||||||
def warn(message):
|
|
||||||
print "XXX: %s\n" % message.encode("latin1")
|
|
||||||
|
|
||||||
#warn("LOADING LLDB")
|
|
||||||
|
|
||||||
# Data members
|
|
||||||
SimpleValueCode, \
|
|
||||||
StructCode, \
|
|
||||||
PointerCode \
|
|
||||||
= range(3)
|
|
||||||
|
|
||||||
# Breakpoints. Keep synchronized with BreakpointType in breakpoint.h
|
|
||||||
UnknownType = 0
|
|
||||||
BreakpointByFileAndLine = 1
|
|
||||||
BreakpointByFunction = 2
|
|
||||||
BreakpointByAddress = 3
|
|
||||||
BreakpointAtThrow = 4
|
|
||||||
BreakpointAtCatch = 5
|
|
||||||
BreakpointAtMain = 6
|
|
||||||
BreakpointAtFork = 7
|
|
||||||
BreakpointAtExec = 8
|
|
||||||
BreakpointAtSysCall = 10
|
|
||||||
WatchpointAtAddress = 11
|
|
||||||
WatchpointAtExpression = 12
|
|
||||||
BreakpointOnQmlSignalEmit = 13
|
|
||||||
BreakpointAtJavaScriptThrow = 14
|
|
||||||
|
|
||||||
|
|
||||||
import json
|
|
||||||
|
|
||||||
def dumpJson(stuff):
|
|
||||||
warn("%s" % json.dumps(stuff, sort_keys=True, indent=4, separators=(',', ': ')))
|
|
||||||
|
|
||||||
def registerCommand(name, func):
|
|
||||||
pass
|
|
||||||
|
|
||||||
class Type:
|
|
||||||
def __init__(self, var):
|
|
||||||
self.raw = var
|
|
||||||
if var.num_children == 0:
|
|
||||||
self.code = SimpleValueCode
|
|
||||||
else:
|
|
||||||
self.code = StructCode
|
|
||||||
self.value_type = var.value_type
|
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
#try:
|
|
||||||
return self.raw.type.name
|
|
||||||
#except:
|
|
||||||
# return "<illegal type>"
|
|
||||||
|
|
||||||
def fieldCount(self):
|
|
||||||
return self.raw.num_children
|
|
||||||
|
|
||||||
def unqualified(self):
|
|
||||||
return self
|
|
||||||
|
|
||||||
class Value:
|
|
||||||
def __init__(self, var):
|
|
||||||
self.raw = var
|
|
||||||
self.is_optimized_out = False
|
|
||||||
self.address = var.addr
|
|
||||||
self.type = Type(var)
|
|
||||||
self.name = var.name
|
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
return str(self.raw.value)
|
|
||||||
|
|
||||||
def fields(self):
|
|
||||||
return [Value(self.raw.GetChildAtIndex(i)) for i in range(self.raw.num_children)]
|
|
||||||
|
|
||||||
currentThread = None
|
|
||||||
currentFrame = None
|
|
||||||
|
|
||||||
def listOfLocals(varList):
|
|
||||||
global currentThread
|
|
||||||
global currentFrame
|
|
||||||
|
|
||||||
items = []
|
|
||||||
currentThread = lldb.process.GetThreadAtIndex(0)
|
|
||||||
currentFrame = currentThread.GetFrameAtIndex(0)
|
|
||||||
for var in currentFrame.variables:
|
|
||||||
item = LocalItem()
|
|
||||||
item.iname = "local." + var.name
|
|
||||||
item.name = var.name
|
|
||||||
item.value = Value(var)
|
|
||||||
items.append(item)
|
|
||||||
return items
|
|
||||||
|
|
||||||
def extractFields(value):
|
|
||||||
return value.fields()
|
|
||||||
|
|
||||||
def fieldCount(type):
|
|
||||||
return type.fieldCount();
|
|
||||||
|
|
||||||
def threadsData(options):
|
|
||||||
result = "threads={threads=["
|
|
||||||
for thread in lldb.process.threads:
|
|
||||||
result += "{id=\"%d\"" % thread.id
|
|
||||||
result += ",target-id=\"%s\"" % thread.id
|
|
||||||
result += ",index=\"%s\"" % thread.idx
|
|
||||||
result += ",stop-reason=\"%s\"" % thread.stop_reason
|
|
||||||
|
|
||||||
if thread.IsSuspended():
|
|
||||||
result += ",state=\"stopped\""
|
|
||||||
else:
|
|
||||||
result += ",state=\"running\""
|
|
||||||
|
|
||||||
if not thread.name is None:
|
|
||||||
result += ",name=\"%s\"" % thread.name
|
|
||||||
|
|
||||||
result += ",frame={"
|
|
||||||
frame = thread.GetFrameAtIndex(0)
|
|
||||||
result += "pc=\"%s\"" % frame.pc
|
|
||||||
result += ",addr=\"%s\"" % frame.pc
|
|
||||||
result += ",fp=\"%s\"" % frame.fp
|
|
||||||
result += ",func=\"%s\"" % frame.function.name
|
|
||||||
result += ",line=\"%s\"" % frame.line_entry.line
|
|
||||||
result += ",fullname=\"%s\"" % frame.line_entry.file
|
|
||||||
result += ",file=\"%s\"" % frame.line_entry.file
|
|
||||||
result += "}},"
|
|
||||||
|
|
||||||
result += "],current-thread-id=\"%s\"}" % lldb.process.selected_thread.id
|
|
||||||
return result
|
|
||||||
|
|
||||||
def stackData(options):
|
|
||||||
try:
|
|
||||||
thread = lldb.process.GetThreadById(options["threadid"])
|
|
||||||
except:
|
|
||||||
thread = lldb.process.GetThreadAtIndex(0)
|
|
||||||
result = "stack={frames=["
|
|
||||||
for frame in thread.frames:
|
|
||||||
result += "{pc=\"%s\"" % frame.pc
|
|
||||||
result += ",level=\"%d\"" % frame.idx
|
|
||||||
result += ",addr=\"%s\"" % frame.pc
|
|
||||||
result += ",fp=\"%s\"" % frame.fp
|
|
||||||
result += ",func=\"%s\"" % frame.function.name
|
|
||||||
result += ",line=\"%s\"" % frame.line_entry.line
|
|
||||||
result += ",fullname=\"%s\"" % frame.line_entry.file
|
|
||||||
result += ",usable=\"1\""
|
|
||||||
result += ",file=\"%s\"}," % frame.line_entry.file
|
|
||||||
|
|
||||||
hasmore = "0"
|
|
||||||
result += "],hasmore=\"%s\"}, " % hasmore
|
|
||||||
return result
|
|
||||||
|
|
||||||
def parseOptions(optionstring):
|
|
||||||
options = {}
|
|
||||||
for opt in optionstring.split(","):
|
|
||||||
try:
|
|
||||||
key, value = opt.split(":")
|
|
||||||
options[key] = value
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
return options
|
|
||||||
|
|
||||||
def updateData(parts, localsOptions, stackOptions, threadOptions):
|
|
||||||
result = "";
|
|
||||||
if parts & 1:
|
|
||||||
result += bb(localsOptions) + ","
|
|
||||||
if parts & 2:
|
|
||||||
result += stackData(parseOptions(stackOptions))
|
|
||||||
if parts & 4:
|
|
||||||
result += threadsData(parseOptions(threadOptions))
|
|
||||||
return result
|
|
||||||
|
|
||||||
def listModules():
|
|
||||||
result = "modules={"
|
|
||||||
for module in lldb.target.modules:
|
|
||||||
result += "{file=\"%s\"" % module.file.fullpath
|
|
||||||
result += ",name=\"%s\"" % module.file.basename
|
|
||||||
#result += ",addrsize=\"%s\"" % module.addr_size
|
|
||||||
#result += ",triple=\"%s\"" % module.triple
|
|
||||||
#result += ",sections={"
|
|
||||||
#for section in module.sections:
|
|
||||||
# result += "[name=\"%s\"" % section.name
|
|
||||||
# result += ",addr=\"%s\"" % section.addr
|
|
||||||
# result += ",size=\"%s\"]," % section.size
|
|
||||||
#result += "}"
|
|
||||||
result += "},"
|
|
||||||
result += "]"
|
|
||||||
return result
|
|
||||||
|
|
||||||
|
|
||||||
def breakpoint_function_wrapper(baton, process, frame, bp_loc):
|
|
||||||
result = "*stopped"
|
|
||||||
result += ",line=\"%s\"" % frame.line_entry.line
|
|
||||||
result += ",file=\"%s\"" % frame.line_entry.file
|
|
||||||
warn("WRAPPER: %s " %result)
|
|
||||||
return result
|
|
||||||
|
|
||||||
def initLldb():
|
|
||||||
pass
|
|
||||||
|
|
||||||
def dumpBreakpoint(bp, modelId):
|
|
||||||
cond = bp.GetCondition()
|
|
||||||
result = "{lldbid=\"%s\"" % bp.GetID()
|
|
||||||
result += ",modelid=\"%s\"" % modelId
|
|
||||||
result += ",hitcount=\"%s\"" % bp.GetHitCount()
|
|
||||||
result += ",threadid=\"%s\"" % bp.GetThreadID()
|
|
||||||
result += ",oneshot=\"%s\"" % (1 if bp.IsOneShot() else 0)
|
|
||||||
result += ",enabled=\"%s\"" % (1 if bp.IsEnabled() else 0)
|
|
||||||
result += ",valid=\"%s\"" % (1 if bp.IsValid() else 0)
|
|
||||||
result += ",condition=\"%s\"" % ("" if cond is None else cond)
|
|
||||||
result += ",ignorecount=\"%s\"" % bp.GetIgnoreCount()
|
|
||||||
result += ",locations=["
|
|
||||||
for i in range(bp.GetNumLocations()):
|
|
||||||
loc = bp.GetLocationAtIndex(i)
|
|
||||||
addr = loc.GetAddress()
|
|
||||||
result += "{locid=\"%s\"" % loc.GetID()
|
|
||||||
result += ",func=\"%s\"" % addr.GetFunction().GetName()
|
|
||||||
result += ",enabled=\"%s\"" % (1 if loc.IsEnabled() else 0)
|
|
||||||
result += ",resolved=\"%s\"" % (1 if loc.IsResolved() else 0)
|
|
||||||
result += ",valid=\"%s\"" % (1 if loc.IsValid() else 0)
|
|
||||||
result += ",ignorecount=\"%s\"" % loc.GetIgnoreCount()
|
|
||||||
result += ",addr=\"%s\"}," % loc.GetLoadAddress()
|
|
||||||
result += "]},"
|
|
||||||
return result
|
|
||||||
|
|
||||||
def onBreak():
|
|
||||||
lldb.debugger.HandleCommand("settings set frame-format ''")
|
|
||||||
lldb.debugger.HandleCommand("settings set thread-format ''")
|
|
||||||
result = "*stopped,frame={....}"
|
|
||||||
print result
|
|
||||||
|
|
||||||
def handleBreakpoints(stuff):
|
|
||||||
todo = json.loads(stuff)
|
|
||||||
#dumpJson(todo)
|
|
||||||
#target = lldb.debugger.CreateTargetWithFileAndArch (exe, lldb.LLDB_ARCH_DEFAULT)
|
|
||||||
target = lldb.debugger.GetTargetAtIndex(0)
|
|
||||||
#target = lldb.target
|
|
||||||
|
|
||||||
result = "bkpts={added=["
|
|
||||||
|
|
||||||
for bp in todo["add"]:
|
|
||||||
bpType = bp["type"]
|
|
||||||
if bpType == BreakpointByFileAndLine:
|
|
||||||
bpNew = target.BreakpointCreateByLocation(str(bp["file"]), int(bp["line"]))
|
|
||||||
elif bpType == BreakpointByFunction:
|
|
||||||
bpNew = target.BreakpointCreateByName(bp["function"])
|
|
||||||
elif bpType == BreakpointAtMain:
|
|
||||||
bpNew = target.BreakpointCreateByName("main", target.GetExecutable().GetFilename())
|
|
||||||
bpNew.SetIgnoreCount(int(bp["ignorecount"]))
|
|
||||||
bpNew.SetCondition(str(bp["condition"]))
|
|
||||||
bpNew.SetEnabled(int(bp["enabled"]))
|
|
||||||
bpNew.SetOneShot(int(bp["oneshot"]))
|
|
||||||
#bpNew.SetCallback(breakpoint_function_wrapper, None)
|
|
||||||
#bpNew.SetCallback(breakpoint_function_wrapper, None)
|
|
||||||
#"breakpoint command add 1 -o \"import time; print time.asctime()\"
|
|
||||||
#cmd = "script print(11111111)"
|
|
||||||
cmd = "continue"
|
|
||||||
lldb.debugger.HandleCommand(
|
|
||||||
"breakpoint command add -o 'script onBreak()' %s" % bpNew.GetID())
|
|
||||||
|
|
||||||
result += dumpBreakpoint(bpNew, bp["modelid"])
|
|
||||||
|
|
||||||
result += "],changed=["
|
|
||||||
|
|
||||||
for bp in todo["change"]:
|
|
||||||
bpChange = target.FindBreakpointByID(int(bp["lldbid"]))
|
|
||||||
bpChange.SetIgnoreCount(int(bp["ignorecount"]))
|
|
||||||
bpChange.SetCondition(str(bp["condition"]))
|
|
||||||
bpChange.SetEnabled(int(bp["enabled"]))
|
|
||||||
bpChange.SetOneShot(int(bp["oneshot"]))
|
|
||||||
result += dumpBreakpoint(bpChange, bp["modelid"])
|
|
||||||
|
|
||||||
result += "],removed=["
|
|
||||||
|
|
||||||
for bp in todo["remove"]:
|
|
||||||
bpDead = target.BreakpointDelete(int(bp["lldbid"]))
|
|
||||||
result += "{modelid=\"%s\"}" % bp["modelid"]
|
|
||||||
|
|
||||||
result += "]}"
|
|
||||||
return result
|
|
||||||
|
|
||||||
def doStepOver():
|
|
||||||
lldb.debugger.SetAsync(False)
|
|
||||||
lldb.thread.StepOver()
|
|
||||||
lldb.debugger.SetAsync(True)
|
|
||||||
result = "result={"
|
|
||||||
result += "},"
|
|
||||||
result += stackData({'threadid': lldb.process.selected_thread.id})
|
|
||||||
result += threadsData({})
|
|
||||||
return result
|
|
||||||
|
|
||||||
def doInterrupt():
|
|
||||||
lldb.debugger.SetAsync(False)
|
|
||||||
lldb.process.Stop()
|
|
||||||
lldb.debugger.SetAsync(True)
|
|
||||||
result = "result={"
|
|
||||||
result += "}"
|
|
||||||
return result
|
|
||||||
|
|
||||||
except:
|
except:
|
||||||
#warn("LOADING LLDB FAILED")
|
failReasons.append(traceback.format_exc())
|
||||||
pass
|
|
||||||
|
|
||||||
#lldb.debugger.HandleCommand('command script add -f ls.ls ls')
|
if len(failReasons):
|
||||||
|
print "CANNOT ACCESS ANY DEBUGGER BACKEND:\n %s" % "\n".join(failReasons)
|
||||||
#
|
|
||||||
#SBEvent data;
|
|
||||||
#while (!stop) {
|
|
||||||
#if (self->m_listener.WaitForEvent(UINT32_MAX, data)) {
|
|
||||||
# if (data.getType() == SBProcess::eBroadcastBitStateChanged &&
|
|
||||||
#m_process.GetStateFromEvent (data) == eStateStopped) {
|
|
||||||
# SBThread th = m_process.GetSelectedThread();
|
|
||||||
# if (th.GetStopReason() == eStopReasonBreakpoint) {
|
|
||||||
# // th.GetStopReasonDataAtIndex(0) should have the breakpoint id
|
|
||||||
# }
|
|
||||||
# }
|
|
||||||
#}
|
|
||||||
#}
|
|
||||||
|
|
||||||
|
|
||||||
|
@@ -45,6 +45,15 @@ def removeTempFile(name):
|
|||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
def showException(msg, exType, exValue, exTraceback):
|
||||||
|
warn("**** CAUGHT EXCEPTION: %s ****" % msg)
|
||||||
|
try:
|
||||||
|
import traceback
|
||||||
|
for line in traceback.format_exception(exType, exValue, exTraceback):
|
||||||
|
warn("%s" % line)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
verbosity = 0
|
verbosity = 0
|
||||||
verbosity = 1
|
verbosity = 1
|
||||||
|
|
||||||
|
322
share/qtcreator/dumper/gbridge.py
Normal file
322
share/qtcreator/dumper/gbridge.py
Normal file
@@ -0,0 +1,322 @@
|
|||||||
|
def warn(message):
|
||||||
|
print "XXX: %s\n" % message.encode("latin1")
|
||||||
|
|
||||||
|
#######################################################################
|
||||||
|
#
|
||||||
|
# Infrastructure
|
||||||
|
#
|
||||||
|
#######################################################################
|
||||||
|
|
||||||
|
def savePrint(output):
|
||||||
|
try:
|
||||||
|
print(output)
|
||||||
|
except:
|
||||||
|
out = ""
|
||||||
|
for c in output:
|
||||||
|
cc = ord(c)
|
||||||
|
if cc > 127:
|
||||||
|
out += "\\\\%d" % cc
|
||||||
|
elif cc < 0:
|
||||||
|
out += "\\\\%d" % (cc + 256)
|
||||||
|
else:
|
||||||
|
out += c
|
||||||
|
print(out)
|
||||||
|
|
||||||
|
def registerCommand(name, func):
|
||||||
|
|
||||||
|
class Command(gdb.Command):
|
||||||
|
def __init__(self):
|
||||||
|
super(Command, self).__init__(name, gdb.COMMAND_OBSCURE)
|
||||||
|
def invoke(self, args, from_tty):
|
||||||
|
savePrint(func(args))
|
||||||
|
|
||||||
|
Command()
|
||||||
|
|
||||||
|
def parseAndEvaluate(exp):
|
||||||
|
return gdb.parse_and_eval(exp)
|
||||||
|
|
||||||
|
def extractFields(value):
|
||||||
|
return value.type.fields()
|
||||||
|
## Insufficient, see http://sourceware.org/bugzilla/show_bug.cgi?id=10953:
|
||||||
|
##fields = type.fields()
|
||||||
|
## Insufficient, see http://sourceware.org/bugzilla/show_bug.cgi?id=11777:
|
||||||
|
##fields = defsype).fields()
|
||||||
|
## This seems to work.
|
||||||
|
##warn("TYPE 0: %s" % type)
|
||||||
|
#type = stripTypedefs(type)
|
||||||
|
#fields = type.fields()
|
||||||
|
#if len(fields):
|
||||||
|
# return fields
|
||||||
|
##warn("TYPE 1: %s" % type)
|
||||||
|
## This fails for arrays. See comment in lookupType.
|
||||||
|
#type0 = lookupType(str(type))
|
||||||
|
#if not type0 is None:
|
||||||
|
# type = type0
|
||||||
|
#if type.code == FunctionCode:
|
||||||
|
# return []
|
||||||
|
##warn("TYPE 2: %s" % type)
|
||||||
|
#fields = type.fields()
|
||||||
|
##warn("FIELDS: %s" % fields)
|
||||||
|
#return fields
|
||||||
|
|
||||||
|
def fieldCount(type):
|
||||||
|
return len(type.fields())
|
||||||
|
|
||||||
|
def listOfLocals(varList):
|
||||||
|
frame = gdb.selected_frame()
|
||||||
|
try:
|
||||||
|
frame = gdb.selected_frame()
|
||||||
|
#warn("FRAME %s: " % frame)
|
||||||
|
except RuntimeError, error:
|
||||||
|
warn("FRAME NOT ACCESSIBLE: %s" % error)
|
||||||
|
return []
|
||||||
|
except:
|
||||||
|
warn("FRAME NOT ACCESSIBLE FOR UNKNOWN REASONS")
|
||||||
|
return []
|
||||||
|
|
||||||
|
try:
|
||||||
|
block = frame.block()
|
||||||
|
#warn("BLOCK: %s " % block)
|
||||||
|
except RuntimeError, error:
|
||||||
|
warn("BLOCK IN FRAME NOT ACCESSIBLE: %s" % error)
|
||||||
|
return items
|
||||||
|
except:
|
||||||
|
warn("BLOCK NOT ACCESSIBLE FOR UNKNOWN REASONS")
|
||||||
|
return items
|
||||||
|
|
||||||
|
items = []
|
||||||
|
shadowed = {}
|
||||||
|
while True:
|
||||||
|
if block is None:
|
||||||
|
warn("UNEXPECTED 'None' BLOCK")
|
||||||
|
break
|
||||||
|
for symbol in block:
|
||||||
|
name = symbol.print_name
|
||||||
|
|
||||||
|
if name == "__in_chrg":
|
||||||
|
continue
|
||||||
|
|
||||||
|
# "NotImplementedError: Symbol type not yet supported in
|
||||||
|
# Python scripts."
|
||||||
|
#warn("SYMBOL %s (%s): " % (symbol, name))
|
||||||
|
if name in shadowed:
|
||||||
|
level = shadowed[name]
|
||||||
|
name1 = "%s@%s" % (name, level)
|
||||||
|
shadowed[name] = level + 1
|
||||||
|
else:
|
||||||
|
name1 = name
|
||||||
|
shadowed[name] = 1
|
||||||
|
#warn("SYMBOL %s (%s, %s)): " % (symbol, name, symbol.name))
|
||||||
|
item = LocalItem()
|
||||||
|
item.iname = "local." + name1
|
||||||
|
item.name = name1
|
||||||
|
try:
|
||||||
|
item.value = frame.read_var(name, block)
|
||||||
|
#warn("READ 1: %s" % item.value)
|
||||||
|
if not item.value.is_optimized_out:
|
||||||
|
#warn("ITEM 1: %s" % item.value)
|
||||||
|
items.append(item)
|
||||||
|
continue
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
try:
|
||||||
|
item.value = frame.read_var(name)
|
||||||
|
#warn("READ 2: %s" % item.value)
|
||||||
|
if not item.value.is_optimized_out:
|
||||||
|
#warn("ITEM 2: %s" % item.value)
|
||||||
|
items.append(item)
|
||||||
|
continue
|
||||||
|
except:
|
||||||
|
# RuntimeError: happens for
|
||||||
|
# void foo() { std::string s; std::wstring w; }
|
||||||
|
# ValueError: happens for (as of 2010/11/4)
|
||||||
|
# a local struct as found e.g. in
|
||||||
|
# gcc sources in gcc.c, int execute()
|
||||||
|
pass
|
||||||
|
|
||||||
|
try:
|
||||||
|
#warn("READ 3: %s %s" % (name, item.value))
|
||||||
|
item.value = gdb.parse_and_eval(name)
|
||||||
|
#warn("ITEM 3: %s" % item.value)
|
||||||
|
items.append(item)
|
||||||
|
except:
|
||||||
|
# Can happen in inlined code (see last line of
|
||||||
|
# RowPainter::paintChars(): "RuntimeError:
|
||||||
|
# No symbol \"__val\" in current context.\n"
|
||||||
|
pass
|
||||||
|
|
||||||
|
# The outermost block in a function has the function member
|
||||||
|
# FIXME: check whether this is guaranteed.
|
||||||
|
if not block.function is None:
|
||||||
|
break
|
||||||
|
|
||||||
|
block = block.superblock
|
||||||
|
|
||||||
|
return items
|
||||||
|
|
||||||
|
|
||||||
|
def catchCliOutput(command):
|
||||||
|
try:
|
||||||
|
return gdb.execute(command, to_string=True).split("\n")
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
filename = createTempFile()
|
||||||
|
gdb.execute("set logging off")
|
||||||
|
# gdb.execute("set logging redirect off")
|
||||||
|
gdb.execute("set logging file %s" % filename)
|
||||||
|
# gdb.execute("set logging redirect on")
|
||||||
|
gdb.execute("set logging on")
|
||||||
|
msg = ""
|
||||||
|
try:
|
||||||
|
gdb.execute(command)
|
||||||
|
except RuntimeError, error:
|
||||||
|
# For the first phase of core file loading this yield
|
||||||
|
# "No symbol table is loaded. Use the \"file\" command."
|
||||||
|
msg = str(error)
|
||||||
|
except:
|
||||||
|
msg = "Unknown error"
|
||||||
|
gdb.execute("set logging off")
|
||||||
|
# gdb.execute("set logging redirect off")
|
||||||
|
if len(msg):
|
||||||
|
# Having that might confuse result handlers in the gdbengine.
|
||||||
|
#warn("CLI ERROR: %s " % msg)
|
||||||
|
removeTempFile(filename)
|
||||||
|
return "CLI ERROR: %s " % msg
|
||||||
|
temp = open(filename, "r")
|
||||||
|
lines = []
|
||||||
|
for line in temp:
|
||||||
|
lines.append(line)
|
||||||
|
temp.close()
|
||||||
|
removeTempFile(filename)
|
||||||
|
return lines
|
||||||
|
|
||||||
|
def selectedInferior():
|
||||||
|
try:
|
||||||
|
# Does not exist in 7.3.
|
||||||
|
return gdb.selected_inferior()
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
# gdb.Inferior is new in gdb 7.2
|
||||||
|
return gdb.inferiors()[0]
|
||||||
|
|
||||||
|
def readRawMemory(base, size):
|
||||||
|
try:
|
||||||
|
inferior = selectedInferior()
|
||||||
|
return binascii.hexlify(inferior.read_memory(base, size))
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
s = ""
|
||||||
|
t = lookupType("unsigned char").pointer()
|
||||||
|
base = base.cast(t)
|
||||||
|
for i in xrange(size):
|
||||||
|
s += "%02x" % int(base.dereference())
|
||||||
|
base += 1
|
||||||
|
return s
|
||||||
|
|
||||||
|
|
||||||
|
#######################################################################
|
||||||
|
#
|
||||||
|
# Types
|
||||||
|
#
|
||||||
|
#######################################################################
|
||||||
|
|
||||||
|
PointerCode = gdb.TYPE_CODE_PTR
|
||||||
|
ArrayCode = gdb.TYPE_CODE_ARRAY
|
||||||
|
StructCode = gdb.TYPE_CODE_STRUCT
|
||||||
|
UnionCode = gdb.TYPE_CODE_UNION
|
||||||
|
EnumCode = gdb.TYPE_CODE_ENUM
|
||||||
|
FlagsCode = gdb.TYPE_CODE_FLAGS
|
||||||
|
FunctionCode = gdb.TYPE_CODE_FUNC
|
||||||
|
IntCode = gdb.TYPE_CODE_INT
|
||||||
|
FloatCode = gdb.TYPE_CODE_FLT # Parts of GDB assume that this means complex.
|
||||||
|
VoidCode = gdb.TYPE_CODE_VOID
|
||||||
|
#SetCode = gdb.TYPE_CODE_SET
|
||||||
|
RangeCode = gdb.TYPE_CODE_RANGE
|
||||||
|
StringCode = gdb.TYPE_CODE_STRING
|
||||||
|
#BitStringCode = gdb.TYPE_CODE_BITSTRING
|
||||||
|
#ErrorTypeCode = gdb.TYPE_CODE_ERROR
|
||||||
|
MethodCode = gdb.TYPE_CODE_METHOD
|
||||||
|
MethodPointerCode = gdb.TYPE_CODE_METHODPTR
|
||||||
|
MemberPointerCode = gdb.TYPE_CODE_MEMBERPTR
|
||||||
|
ReferenceCode = gdb.TYPE_CODE_REF
|
||||||
|
CharCode = gdb.TYPE_CODE_CHAR
|
||||||
|
BoolCode = gdb.TYPE_CODE_BOOL
|
||||||
|
ComplexCode = gdb.TYPE_CODE_COMPLEX
|
||||||
|
TypedefCode = gdb.TYPE_CODE_TYPEDEF
|
||||||
|
NamespaceCode = gdb.TYPE_CODE_NAMESPACE
|
||||||
|
#Code = gdb.TYPE_CODE_DECFLOAT # Decimal floating point.
|
||||||
|
#Code = gdb.TYPE_CODE_MODULE # Fortran
|
||||||
|
#Code = gdb.TYPE_CODE_INTERNAL_FUNCTION
|
||||||
|
|
||||||
|
|
||||||
|
#######################################################################
|
||||||
|
#
|
||||||
|
# Step Command
|
||||||
|
#
|
||||||
|
#######################################################################
|
||||||
|
|
||||||
|
def sal(args):
|
||||||
|
(cmd, addr) = args.split(",")
|
||||||
|
lines = catchCliOutput("info line *" + addr)
|
||||||
|
fromAddr = "0x0"
|
||||||
|
toAddr = "0x0"
|
||||||
|
for line in lines:
|
||||||
|
pos0from = line.find(" starts at address") + 19
|
||||||
|
pos1from = line.find(" ", pos0from)
|
||||||
|
pos0to = line.find(" ends at", pos1from) + 9
|
||||||
|
pos1to = line.find(" ", pos0to)
|
||||||
|
if pos1to > 0:
|
||||||
|
fromAddr = line[pos0from : pos1from]
|
||||||
|
toAddr = line[pos0to : pos1to]
|
||||||
|
gdb.execute("maint packet sal%s,%s,%s" % (cmd,fromAddr, toAddr))
|
||||||
|
|
||||||
|
registerCommand("sal", sal)
|
||||||
|
|
||||||
|
|
||||||
|
#######################################################################
|
||||||
|
#
|
||||||
|
# Convenience
|
||||||
|
#
|
||||||
|
#######################################################################
|
||||||
|
|
||||||
|
# Just convienience for 'python print ...'
|
||||||
|
class PPCommand(gdb.Command):
|
||||||
|
def __init__(self):
|
||||||
|
super(PPCommand, self).__init__("pp", gdb.COMMAND_OBSCURE)
|
||||||
|
def invoke(self, args, from_tty):
|
||||||
|
print(eval(args))
|
||||||
|
|
||||||
|
PPCommand()
|
||||||
|
|
||||||
|
# Just convienience for 'python print gdb.parse_and_eval(...)'
|
||||||
|
class PPPCommand(gdb.Command):
|
||||||
|
def __init__(self):
|
||||||
|
super(PPPCommand, self).__init__("ppp", gdb.COMMAND_OBSCURE)
|
||||||
|
def invoke(self, args, from_tty):
|
||||||
|
print(gdb.parse_and_eval(args))
|
||||||
|
|
||||||
|
PPPCommand()
|
||||||
|
|
||||||
|
|
||||||
|
def scanStack(p, n):
|
||||||
|
p = long(p)
|
||||||
|
r = []
|
||||||
|
for i in xrange(n):
|
||||||
|
f = gdb.parse_and_eval("{void*}%s" % p)
|
||||||
|
m = gdb.execute("info symbol %s" % f, to_string=True)
|
||||||
|
if not m.startswith("No symbol matches"):
|
||||||
|
r.append(m)
|
||||||
|
p += f.type.sizeof
|
||||||
|
return r
|
||||||
|
|
||||||
|
class ScanStackCommand(gdb.Command):
|
||||||
|
def __init__(self):
|
||||||
|
super(ScanStackCommand, self).__init__("scanStack", gdb.COMMAND_OBSCURE)
|
||||||
|
def invoke(self, args, from_tty):
|
||||||
|
if len(args) == 0:
|
||||||
|
args = 20
|
||||||
|
savePrint(scanStack(gdb.parse_and_eval("$sp"), int(args)))
|
||||||
|
|
||||||
|
ScanStackCommand()
|
||||||
|
|
306
share/qtcreator/dumper/lbridge.py
Normal file
306
share/qtcreator/dumper/lbridge.py
Normal file
@@ -0,0 +1,306 @@
|
|||||||
|
import json
|
||||||
|
|
||||||
|
|
||||||
|
#warn("LOADING LLDB")
|
||||||
|
|
||||||
|
# Data members
|
||||||
|
SimpleValueCode, \
|
||||||
|
StructCode, \
|
||||||
|
PointerCode \
|
||||||
|
= range(3)
|
||||||
|
|
||||||
|
# Breakpoints. Keep synchronized with BreakpointType in breakpoint.h
|
||||||
|
UnknownType = 0
|
||||||
|
BreakpointByFileAndLine = 1
|
||||||
|
BreakpointByFunction = 2
|
||||||
|
BreakpointByAddress = 3
|
||||||
|
BreakpointAtThrow = 4
|
||||||
|
BreakpointAtCatch = 5
|
||||||
|
BreakpointAtMain = 6
|
||||||
|
BreakpointAtFork = 7
|
||||||
|
BreakpointAtExec = 8
|
||||||
|
BreakpointAtSysCall = 10
|
||||||
|
WatchpointAtAddress = 11
|
||||||
|
WatchpointAtExpression = 12
|
||||||
|
BreakpointOnQmlSignalEmit = 13
|
||||||
|
BreakpointAtJavaScriptThrow = 14
|
||||||
|
|
||||||
|
|
||||||
|
def dumpJson(stuff):
|
||||||
|
warn("%s" % json.dumps(stuff, sort_keys=True, indent=4, separators=(',', ': ')))
|
||||||
|
|
||||||
|
def registerCommand(name, func):
|
||||||
|
pass
|
||||||
|
|
||||||
|
class Type:
|
||||||
|
def __init__(self, var):
|
||||||
|
self.raw = var
|
||||||
|
if var.num_children == 0:
|
||||||
|
self.code = SimpleValueCode
|
||||||
|
else:
|
||||||
|
self.code = StructCode
|
||||||
|
self.value_type = var.value_type
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
#try:
|
||||||
|
return self.raw.type.name
|
||||||
|
#except:
|
||||||
|
# return "<illegal type>"
|
||||||
|
|
||||||
|
def fieldCount(self):
|
||||||
|
return self.raw.num_children
|
||||||
|
|
||||||
|
def unqualified(self):
|
||||||
|
return self
|
||||||
|
|
||||||
|
class Value:
|
||||||
|
def __init__(self, var):
|
||||||
|
self.raw = var
|
||||||
|
self.is_optimized_out = False
|
||||||
|
self.address = var.addr
|
||||||
|
self.type = Type(var)
|
||||||
|
self.name = var.name
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return str(self.raw.value)
|
||||||
|
|
||||||
|
def fields(self):
|
||||||
|
return [Value(self.raw.GetChildAtIndex(i)) for i in range(self.raw.num_children)]
|
||||||
|
|
||||||
|
currentThread = None
|
||||||
|
currentFrame = None
|
||||||
|
|
||||||
|
def listOfLocals(varList):
|
||||||
|
global currentThread
|
||||||
|
global currentFrame
|
||||||
|
|
||||||
|
items = []
|
||||||
|
currentThread = lldb.process.GetThreadAtIndex(0)
|
||||||
|
currentFrame = currentThread.GetFrameAtIndex(0)
|
||||||
|
for var in currentFrame.variables:
|
||||||
|
item = LocalItem()
|
||||||
|
item.iname = "local." + var.name
|
||||||
|
item.name = var.name
|
||||||
|
item.value = Value(var)
|
||||||
|
items.append(item)
|
||||||
|
return items
|
||||||
|
|
||||||
|
def extractFields(value):
|
||||||
|
return value.fields()
|
||||||
|
|
||||||
|
def fieldCount(type):
|
||||||
|
return type.fieldCount();
|
||||||
|
|
||||||
|
def threadsData(options):
|
||||||
|
result = "threads={threads=["
|
||||||
|
for thread in lldb.process.threads:
|
||||||
|
result += "{id=\"%d\"" % thread.id
|
||||||
|
result += ",target-id=\"%s\"" % thread.id
|
||||||
|
result += ",index=\"%s\"" % thread.idx
|
||||||
|
result += ",stop-reason=\"%s\"" % thread.stop_reason
|
||||||
|
|
||||||
|
if thread.IsSuspended():
|
||||||
|
result += ",state=\"stopped\""
|
||||||
|
else:
|
||||||
|
result += ",state=\"running\""
|
||||||
|
|
||||||
|
if not thread.name is None:
|
||||||
|
result += ",name=\"%s\"" % thread.name
|
||||||
|
|
||||||
|
result += ",frame={"
|
||||||
|
frame = thread.GetFrameAtIndex(0)
|
||||||
|
result += "pc=\"%s\"" % frame.pc
|
||||||
|
result += ",addr=\"%s\"" % frame.pc
|
||||||
|
result += ",fp=\"%s\"" % frame.fp
|
||||||
|
result += ",func=\"%s\"" % frame.function.name
|
||||||
|
result += ",line=\"%s\"" % frame.line_entry.line
|
||||||
|
result += ",fullname=\"%s\"" % frame.line_entry.file
|
||||||
|
result += ",file=\"%s\"" % frame.line_entry.file
|
||||||
|
result += "}},"
|
||||||
|
|
||||||
|
result += "],current-thread-id=\"%s\"}" % lldb.process.selected_thread.id
|
||||||
|
return result
|
||||||
|
|
||||||
|
def stackData(options):
|
||||||
|
try:
|
||||||
|
thread = lldb.process.GetThreadById(options["threadid"])
|
||||||
|
except:
|
||||||
|
thread = lldb.process.GetThreadAtIndex(0)
|
||||||
|
result = "stack={frames=["
|
||||||
|
for frame in thread.frames:
|
||||||
|
result += "{pc=\"%s\"" % frame.pc
|
||||||
|
result += ",level=\"%d\"" % frame.idx
|
||||||
|
result += ",addr=\"%s\"" % frame.pc
|
||||||
|
result += ",fp=\"%s\"" % frame.fp
|
||||||
|
result += ",func=\"%s\"" % frame.function.name
|
||||||
|
result += ",line=\"%s\"" % frame.line_entry.line
|
||||||
|
result += ",fullname=\"%s\"" % frame.line_entry.file
|
||||||
|
result += ",usable=\"1\""
|
||||||
|
result += ",file=\"%s\"}," % frame.line_entry.file
|
||||||
|
|
||||||
|
hasmore = "0"
|
||||||
|
result += "],hasmore=\"%s\"}, " % hasmore
|
||||||
|
return result
|
||||||
|
|
||||||
|
def parseOptions(optionstring):
|
||||||
|
options = {}
|
||||||
|
for opt in optionstring.split(","):
|
||||||
|
try:
|
||||||
|
key, value = opt.split(":")
|
||||||
|
options[key] = value
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
return options
|
||||||
|
|
||||||
|
def updateData(parts, localsOptions, stackOptions, threadOptions):
|
||||||
|
result = "";
|
||||||
|
if parts & 1:
|
||||||
|
result += bb(localsOptions) + ","
|
||||||
|
if parts & 2:
|
||||||
|
result += stackData(parseOptions(stackOptions))
|
||||||
|
if parts & 4:
|
||||||
|
result += threadsData(parseOptions(threadOptions))
|
||||||
|
return result
|
||||||
|
|
||||||
|
def listModules():
|
||||||
|
result = "modules={"
|
||||||
|
for module in lldb.target.modules:
|
||||||
|
result += "{file=\"%s\"" % module.file.fullpath
|
||||||
|
result += ",name=\"%s\"" % module.file.basename
|
||||||
|
#result += ",addrsize=\"%s\"" % module.addr_size
|
||||||
|
#result += ",triple=\"%s\"" % module.triple
|
||||||
|
#result += ",sections={"
|
||||||
|
#for section in module.sections:
|
||||||
|
# result += "[name=\"%s\"" % section.name
|
||||||
|
# result += ",addr=\"%s\"" % section.addr
|
||||||
|
# result += ",size=\"%s\"]," % section.size
|
||||||
|
#result += "}"
|
||||||
|
result += "},"
|
||||||
|
result += "]"
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
def breakpoint_function_wrapper(baton, process, frame, bp_loc):
|
||||||
|
result = "*stopped"
|
||||||
|
result += ",line=\"%s\"" % frame.line_entry.line
|
||||||
|
result += ",file=\"%s\"" % frame.line_entry.file
|
||||||
|
warn("WRAPPER: %s " %result)
|
||||||
|
return result
|
||||||
|
|
||||||
|
def initLldb():
|
||||||
|
pass
|
||||||
|
|
||||||
|
def dumpBreakpoint(bp, modelId):
|
||||||
|
cond = bp.GetCondition()
|
||||||
|
result = "{lldbid=\"%s\"" % bp.GetID()
|
||||||
|
result += ",modelid=\"%s\"" % modelId
|
||||||
|
result += ",hitcount=\"%s\"" % bp.GetHitCount()
|
||||||
|
result += ",threadid=\"%s\"" % bp.GetThreadID()
|
||||||
|
result += ",oneshot=\"%s\"" % (1 if bp.IsOneShot() else 0)
|
||||||
|
result += ",enabled=\"%s\"" % (1 if bp.IsEnabled() else 0)
|
||||||
|
result += ",valid=\"%s\"" % (1 if bp.IsValid() else 0)
|
||||||
|
result += ",condition=\"%s\"" % ("" if cond is None else cond)
|
||||||
|
result += ",ignorecount=\"%s\"" % bp.GetIgnoreCount()
|
||||||
|
result += ",locations=["
|
||||||
|
for i in range(bp.GetNumLocations()):
|
||||||
|
loc = bp.GetLocationAtIndex(i)
|
||||||
|
addr = loc.GetAddress()
|
||||||
|
result += "{locid=\"%s\"" % loc.GetID()
|
||||||
|
result += ",func=\"%s\"" % addr.GetFunction().GetName()
|
||||||
|
result += ",enabled=\"%s\"" % (1 if loc.IsEnabled() else 0)
|
||||||
|
result += ",resolved=\"%s\"" % (1 if loc.IsResolved() else 0)
|
||||||
|
result += ",valid=\"%s\"" % (1 if loc.IsValid() else 0)
|
||||||
|
result += ",ignorecount=\"%s\"" % loc.GetIgnoreCount()
|
||||||
|
result += ",addr=\"%s\"}," % loc.GetLoadAddress()
|
||||||
|
result += "]},"
|
||||||
|
return result
|
||||||
|
|
||||||
|
def onBreak():
|
||||||
|
lldb.debugger.HandleCommand("settings set frame-format ''")
|
||||||
|
lldb.debugger.HandleCommand("settings set thread-format ''")
|
||||||
|
result = "*stopped,frame={....}"
|
||||||
|
print result
|
||||||
|
|
||||||
|
def handleBreakpoints(stuff):
|
||||||
|
todo = json.loads(stuff)
|
||||||
|
#dumpJson(todo)
|
||||||
|
#target = lldb.debugger.CreateTargetWithFileAndArch (exe, lldb.LLDB_ARCH_DEFAULT)
|
||||||
|
target = lldb.debugger.GetTargetAtIndex(0)
|
||||||
|
#target = lldb.target
|
||||||
|
|
||||||
|
result = "bkpts={added=["
|
||||||
|
|
||||||
|
for bp in todo["add"]:
|
||||||
|
bpType = bp["type"]
|
||||||
|
if bpType == BreakpointByFileAndLine:
|
||||||
|
bpNew = target.BreakpointCreateByLocation(str(bp["file"]), int(bp["line"]))
|
||||||
|
elif bpType == BreakpointByFunction:
|
||||||
|
bpNew = target.BreakpointCreateByName(bp["function"])
|
||||||
|
elif bpType == BreakpointAtMain:
|
||||||
|
bpNew = target.BreakpointCreateByName("main", target.GetExecutable().GetFilename())
|
||||||
|
bpNew.SetIgnoreCount(int(bp["ignorecount"]))
|
||||||
|
bpNew.SetCondition(str(bp["condition"]))
|
||||||
|
bpNew.SetEnabled(int(bp["enabled"]))
|
||||||
|
bpNew.SetOneShot(int(bp["oneshot"]))
|
||||||
|
#bpNew.SetCallback(breakpoint_function_wrapper, None)
|
||||||
|
#bpNew.SetCallback(breakpoint_function_wrapper, None)
|
||||||
|
#"breakpoint command add 1 -o \"import time; print time.asctime()\"
|
||||||
|
#cmd = "script print(11111111)"
|
||||||
|
cmd = "continue"
|
||||||
|
lldb.debugger.HandleCommand(
|
||||||
|
"breakpoint command add -o 'script onBreak()' %s" % bpNew.GetID())
|
||||||
|
|
||||||
|
result += dumpBreakpoint(bpNew, bp["modelid"])
|
||||||
|
|
||||||
|
result += "],changed=["
|
||||||
|
|
||||||
|
for bp in todo["change"]:
|
||||||
|
bpChange = target.FindBreakpointByID(int(bp["lldbid"]))
|
||||||
|
bpChange.SetIgnoreCount(int(bp["ignorecount"]))
|
||||||
|
bpChange.SetCondition(str(bp["condition"]))
|
||||||
|
bpChange.SetEnabled(int(bp["enabled"]))
|
||||||
|
bpChange.SetOneShot(int(bp["oneshot"]))
|
||||||
|
result += dumpBreakpoint(bpChange, bp["modelid"])
|
||||||
|
|
||||||
|
result += "],removed=["
|
||||||
|
|
||||||
|
for bp in todo["remove"]:
|
||||||
|
bpDead = target.BreakpointDelete(int(bp["lldbid"]))
|
||||||
|
result += "{modelid=\"%s\"}" % bp["modelid"]
|
||||||
|
|
||||||
|
result += "]}"
|
||||||
|
return result
|
||||||
|
|
||||||
|
def doStepOver():
|
||||||
|
lldb.debugger.SetAsync(False)
|
||||||
|
lldb.thread.StepOver()
|
||||||
|
lldb.debugger.SetAsync(True)
|
||||||
|
result = "result={"
|
||||||
|
result += "},"
|
||||||
|
result += stackData({'threadid': lldb.process.selected_thread.id})
|
||||||
|
result += threadsData({})
|
||||||
|
return result
|
||||||
|
|
||||||
|
def doInterrupt():
|
||||||
|
lldb.debugger.SetAsync(False)
|
||||||
|
lldb.process.Stop()
|
||||||
|
lldb.debugger.SetAsync(True)
|
||||||
|
result = "result={"
|
||||||
|
result += "}"
|
||||||
|
return result
|
||||||
|
|
||||||
|
#lldb.debugger.HandleCommand('command script add -f ls.ls ls')
|
||||||
|
|
||||||
|
#
|
||||||
|
#SBEvent data;
|
||||||
|
#while (!stop) {
|
||||||
|
#if (self->m_listener.WaitForEvent(UINT32_MAX, data)) {
|
||||||
|
# if (data.getType() == SBProcess::eBroadcastBitStateChanged &&
|
||||||
|
#m_process.GetStateFromEvent (data) == eStateStopped) {
|
||||||
|
# SBThread th = m_process.GetSelectedThread();
|
||||||
|
# if (th.GetStopReason() == eStopReasonBreakpoint) {
|
||||||
|
# // th.GetStopReasonDataAtIndex(0) should have the breakpoint id
|
||||||
|
# }
|
||||||
|
# }
|
||||||
|
#}
|
||||||
|
#}
|
@@ -1840,6 +1840,10 @@ void GdbEngine::handleHasPython(const GdbResponse &response)
|
|||||||
void GdbEngine::handlePythonSetup(const GdbResponse &response)
|
void GdbEngine::handlePythonSetup(const GdbResponse &response)
|
||||||
{
|
{
|
||||||
if (response.resultClass == GdbResultDone) {
|
if (response.resultClass == GdbResultDone) {
|
||||||
|
postCommand("python qqStringCutOff = "
|
||||||
|
+ debuggerCore()->action(MaximalStringLength)->value().toByteArray(),
|
||||||
|
ConsoleCommand|NonCriticalResponse);
|
||||||
|
|
||||||
m_hasPython = true;
|
m_hasPython = true;
|
||||||
GdbMi data;
|
GdbMi data;
|
||||||
data.fromStringMultiple(response.consoleStreamOutput);
|
data.fromStringMultiple(response.consoleStreamOutput);
|
||||||
@@ -4902,6 +4906,7 @@ void GdbEngine::startGdb(const QStringList &args)
|
|||||||
|
|
||||||
void GdbEngine::reportEngineSetupOk(const GdbResponse &response)
|
void GdbEngine::reportEngineSetupOk(const GdbResponse &response)
|
||||||
{
|
{
|
||||||
|
loadInitScript();
|
||||||
Q_UNUSED(response);
|
Q_UNUSED(response);
|
||||||
QTC_ASSERT(state() == EngineSetupRequested, qDebug() << state());
|
QTC_ASSERT(state() == EngineSetupRequested, qDebug() << state());
|
||||||
showMessage(_("ENGINE SUCCESSFULLY STARTED"));
|
showMessage(_("ENGINE SUCCESSFULLY STARTED"));
|
||||||
@@ -4948,19 +4953,7 @@ void GdbEngine::tryLoadPythonDumpers()
|
|||||||
Core::ICore::resourcePath().toLocal8Bit() + "/dumper/";
|
Core::ICore::resourcePath().toLocal8Bit() + "/dumper/";
|
||||||
|
|
||||||
postCommand("python execfile('" + dumperSourcePath + "bridge.py')",
|
postCommand("python execfile('" + dumperSourcePath + "bridge.py')",
|
||||||
ConsoleCommand|NonCriticalResponse);
|
ConsoleCommand, CB(handlePythonSetup));
|
||||||
postCommand("python execfile('" + dumperSourcePath + "dumper.py')",
|
|
||||||
ConsoleCommand|NonCriticalResponse);
|
|
||||||
postCommand("python execfile('" + dumperSourcePath + "qttypes.py')",
|
|
||||||
ConsoleCommand|NonCriticalResponse);
|
|
||||||
|
|
||||||
postCommand("python qqStringCutOff = "
|
|
||||||
+ debuggerCore()->action(MaximalStringLength)->value().toByteArray(),
|
|
||||||
ConsoleCommand|NonCriticalResponse);
|
|
||||||
|
|
||||||
loadInitScript();
|
|
||||||
|
|
||||||
postCommand("bbsetup", ConsoleCommand, CB(handlePythonSetup));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GdbEngine::reloadDebuggingHelpers()
|
void GdbEngine::reloadDebuggingHelpers()
|
||||||
|
@@ -1113,9 +1113,6 @@ void LldbEngine::loadPythonDumpers()
|
|||||||
Core::ICore::resourcePath().toLocal8Bit() + "/dumper/";
|
Core::ICore::resourcePath().toLocal8Bit() + "/dumper/";
|
||||||
|
|
||||||
postCommand("script execfile('" + dumperSourcePath + "bridge.py')");
|
postCommand("script execfile('" + dumperSourcePath + "bridge.py')");
|
||||||
postCommand("script execfile('" + dumperSourcePath + "dumper.py')");
|
|
||||||
postCommand("script execfile('" + dumperSourcePath + "qttypes.py')");
|
|
||||||
postCommand("script bbsetup('')");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool LldbEngine::hasCapability(unsigned cap) const
|
bool LldbEngine::hasCapability(unsigned cap) const
|
||||||
|
Reference in New Issue
Block a user