forked from qt-creator/qt-creator
debugger: refactor the dumper class to make it work with gdb 7.0
This is an attempt to make it work with released gdb 7.0. It uses some ugly workarounds to compensate for the missing gdb.Block and gdb.Symbol structures.
This commit is contained in:
@@ -9,6 +9,10 @@ import gdb
|
||||
import base64
|
||||
import curses.ascii
|
||||
|
||||
# only needed for gdb 7.0
|
||||
import os
|
||||
import tempfile
|
||||
|
||||
verbosity = 0
|
||||
verbosity = 1
|
||||
|
||||
@@ -22,13 +26,95 @@ def qmin(n, m):
|
||||
return n
|
||||
return m
|
||||
|
||||
def parseAndEvaluate(exp):
|
||||
if gdb.VERSION.startswith("6.8.50.2009"):
|
||||
return gdb.parse_and_eval(exp)
|
||||
# Work around non-existing gdb.parse_and_eval as in released 7.0
|
||||
gdb.execute("set logging redirect on")
|
||||
gdb.execute("set logging on")
|
||||
gdb.execute("print %s" % exp)
|
||||
gdb.execute("set logging off")
|
||||
return gdb.history(0)
|
||||
|
||||
def listOfLocals():
|
||||
try:
|
||||
frame = gdb.selected_frame()
|
||||
#warn("FRAME %s: " % frame)
|
||||
except RuntimeError:
|
||||
return ""
|
||||
|
||||
items = []
|
||||
if gdb.VERSION.startswith("6.8.50.2009"):
|
||||
# archer-tromey-python
|
||||
block = frame.block()
|
||||
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: " % symbol.value)
|
||||
#warn("SYMBOL %s (%s): " % (symbol, name))
|
||||
item = Item(0, "local", name, name)
|
||||
try:
|
||||
item.value = frame.read_var(name) # this is a gdb value
|
||||
except RuntimeError:
|
||||
# happens for void foo() { std::string s; std::wstring w; }
|
||||
#warn(" FRAME READ VAR ERROR: %s (%s): " % (symbol, name))
|
||||
continue
|
||||
#warn("ITEM %s: " % item.value)
|
||||
items.append(item)
|
||||
# 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
|
||||
else:
|
||||
# Assuming gdb 7.0 release.
|
||||
file = tempfile.mkstemp(prefix="gdbpy_")
|
||||
filename = file[1]
|
||||
gdb.execute("set logging file %s" % filename)
|
||||
gdb.execute("set logging redirect on")
|
||||
gdb.execute("set logging on")
|
||||
gdb.execute("info locals")
|
||||
gdb.execute("info args")
|
||||
gdb.execute("set logging off")
|
||||
gdb.execute("set logging redirect off")
|
||||
file = open(filename, "r")
|
||||
for line in file:
|
||||
if len(line) == 0 or line.startswith(" "):
|
||||
continue
|
||||
pos = line.find(" = ")
|
||||
if pos < 0:
|
||||
continue
|
||||
name = line[0:pos]
|
||||
item = Item(0, "local", name, name)
|
||||
try:
|
||||
item.value = frame.read_var(name) # this is a gdb value
|
||||
except RuntimeError:
|
||||
continue
|
||||
items.append(item)
|
||||
file.close()
|
||||
os.remove(filename)
|
||||
|
||||
return items
|
||||
|
||||
|
||||
def value(expr):
|
||||
value = gdb.parse_and_eval(expr)
|
||||
value = parseAndEvaluate(expr)
|
||||
try:
|
||||
return int(value)
|
||||
except:
|
||||
return str(value)
|
||||
|
||||
|
||||
def isSimpleType(typeobj):
|
||||
type = str(typeobj)
|
||||
return type == "bool" \
|
||||
@@ -41,6 +127,7 @@ def isSimpleType(typeobj):
|
||||
or type == "signed" or type.startswith("signed ") \
|
||||
or type == "unsigned" or type.startswith("unsigned ")
|
||||
|
||||
|
||||
def isStringType(d, typeobj):
|
||||
type = str(typeobj)
|
||||
return type == d.ns + "QString" \
|
||||
@@ -114,17 +201,17 @@ def checkPointerRange(p, n):
|
||||
def call(value, func):
|
||||
#warn("CALL: %s -> %s" % (value, func))
|
||||
type = stripClassTag(str(value.type))
|
||||
if type.find(':') >= 0:
|
||||
if type.find(":") >= 0:
|
||||
type = "'" + type + "'"
|
||||
exp = "((%s*)%s)->%s" % (type, value.address, func)
|
||||
#warn("CALL: %s" % exp)
|
||||
result = gdb.parse_and_eval(exp)
|
||||
result = parseAndEvaluate(exp)
|
||||
#warn(" -> %s" % result)
|
||||
return result
|
||||
|
||||
def qtNamespace():
|
||||
try:
|
||||
type = str(gdb.parse_and_eval("&QString::null").type.target().unqualified())
|
||||
type = str(parseAndEvaluate("&QString::null").type.target().unqualified())
|
||||
return type[0:len(type) - len("QString::null")]
|
||||
except RuntimeError:
|
||||
return ""
|
||||
@@ -247,39 +334,12 @@ class FrameCommand(gdb.Command):
|
||||
#
|
||||
# Locals
|
||||
#
|
||||
try:
|
||||
frame = gdb.selected_frame()
|
||||
#warn("FRAME %s: " % frame)
|
||||
except RuntimeError:
|
||||
return ""
|
||||
|
||||
block = frame.block()
|
||||
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: " % symbol.value)
|
||||
#warn("SYMBOL %s (%s): " % (symbol, name))
|
||||
item = Item(0, "local", name, name)
|
||||
try:
|
||||
item.value = frame.read_var(name) # this is a gdb value
|
||||
except RuntimeError:
|
||||
# happens for void foo() { std::string s; std::wstring w; }
|
||||
#warn(" FRAME READ VAR ERROR: %s (%s): " % (symbol, name))
|
||||
continue
|
||||
for item in listOfLocals():
|
||||
#warn("ITEM %s: " % item.value)
|
||||
|
||||
type = item.value.type
|
||||
if type.code == gdb.TYPE_CODE_PTR \
|
||||
and name == "argv" and str(type) == "char **":
|
||||
and item.name == "argv" and str(type) == "char **":
|
||||
# Special handling for char** argv:
|
||||
n = 0
|
||||
p = item.value
|
||||
@@ -289,7 +349,7 @@ class FrameCommand(gdb.Command):
|
||||
|
||||
d.beginHash()
|
||||
d.put('iname="%s",' % item.iname)
|
||||
d.putName(name)
|
||||
d.putName(item.name)
|
||||
d.putItemCount(select(n <= 100, n, "> 100"))
|
||||
d.putType(type)
|
||||
d.putNumChild(n)
|
||||
@@ -313,14 +373,6 @@ class FrameCommand(gdb.Command):
|
||||
d.safePutItemHelper(item)
|
||||
d.endHash()
|
||||
|
||||
# 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
|
||||
#warn("BLOCK %s: " % block)
|
||||
|
||||
d.pushOutput()
|
||||
locals = d.safeoutput
|
||||
|
||||
@@ -386,7 +438,7 @@ class FrameCommand(gdb.Command):
|
||||
d.put('type=" ",numchild="0"')
|
||||
else:
|
||||
try:
|
||||
value = gdb.parse_and_eval(exp)
|
||||
value = parseAndEvaluate(exp)
|
||||
item = Item(value, "watch", name, name)
|
||||
d.safePutItemHelper(item)
|
||||
except RuntimeError:
|
||||
|
@@ -613,7 +613,6 @@ def qdump__QObject(d, item):
|
||||
# % (d.ns, item.value.address, propertyName)
|
||||
#exp = '"((\'%sQObject\'*)%s)"' % (d.ns, item.value.address,)
|
||||
#warn("EXPRESSION: %s" % exp)
|
||||
#value = gdb.parse_and_eval(exp)
|
||||
value = call(item.value, 'property("%s")' % propertyName)
|
||||
warn("VALUE: %s" % value)
|
||||
warn("TYPE: %s" % value.type)
|
||||
|
@@ -4365,8 +4365,8 @@ bool GdbEngine::startGdb(const QStringList &args, const QString &gdb, const QStr
|
||||
|
||||
postCommand(_("show version"), CB(handleShowVersion));
|
||||
|
||||
postCommand(_("source -p ") + dumperSourcePath + _("dumper.py"));
|
||||
postCommand(_("source -p ") + dumperSourcePath + _("gdbmacros.py"));
|
||||
postCommand(_("python execfile('%1dumper.py')").arg(dumperSourcePath));
|
||||
postCommand(_("python execfile('%1gdbmacros.py')").arg(dumperSourcePath));
|
||||
|
||||
postCommand(_("-interpreter-exec console \"help bb\""),
|
||||
CB(handleIsSynchroneous));
|
||||
|
Reference in New Issue
Block a user