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 base64
|
||||||
import curses.ascii
|
import curses.ascii
|
||||||
|
|
||||||
|
# only needed for gdb 7.0
|
||||||
|
import os
|
||||||
|
import tempfile
|
||||||
|
|
||||||
verbosity = 0
|
verbosity = 0
|
||||||
verbosity = 1
|
verbosity = 1
|
||||||
|
|
||||||
@@ -22,13 +26,95 @@ def qmin(n, m):
|
|||||||
return n
|
return n
|
||||||
return m
|
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):
|
def value(expr):
|
||||||
value = gdb.parse_and_eval(expr)
|
value = parseAndEvaluate(expr)
|
||||||
try:
|
try:
|
||||||
return int(value)
|
return int(value)
|
||||||
except:
|
except:
|
||||||
return str(value)
|
return str(value)
|
||||||
|
|
||||||
|
|
||||||
def isSimpleType(typeobj):
|
def isSimpleType(typeobj):
|
||||||
type = str(typeobj)
|
type = str(typeobj)
|
||||||
return type == "bool" \
|
return type == "bool" \
|
||||||
@@ -41,6 +127,7 @@ def isSimpleType(typeobj):
|
|||||||
or type == "signed" or type.startswith("signed ") \
|
or type == "signed" or type.startswith("signed ") \
|
||||||
or type == "unsigned" or type.startswith("unsigned ")
|
or type == "unsigned" or type.startswith("unsigned ")
|
||||||
|
|
||||||
|
|
||||||
def isStringType(d, typeobj):
|
def isStringType(d, typeobj):
|
||||||
type = str(typeobj)
|
type = str(typeobj)
|
||||||
return type == d.ns + "QString" \
|
return type == d.ns + "QString" \
|
||||||
@@ -114,17 +201,17 @@ def checkPointerRange(p, n):
|
|||||||
def call(value, func):
|
def call(value, func):
|
||||||
#warn("CALL: %s -> %s" % (value, func))
|
#warn("CALL: %s -> %s" % (value, func))
|
||||||
type = stripClassTag(str(value.type))
|
type = stripClassTag(str(value.type))
|
||||||
if type.find(':') >= 0:
|
if type.find(":") >= 0:
|
||||||
type = "'" + type + "'"
|
type = "'" + type + "'"
|
||||||
exp = "((%s*)%s)->%s" % (type, value.address, func)
|
exp = "((%s*)%s)->%s" % (type, value.address, func)
|
||||||
#warn("CALL: %s" % exp)
|
#warn("CALL: %s" % exp)
|
||||||
result = gdb.parse_and_eval(exp)
|
result = parseAndEvaluate(exp)
|
||||||
#warn(" -> %s" % result)
|
#warn(" -> %s" % result)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def qtNamespace():
|
def qtNamespace():
|
||||||
try:
|
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")]
|
return type[0:len(type) - len("QString::null")]
|
||||||
except RuntimeError:
|
except RuntimeError:
|
||||||
return ""
|
return ""
|
||||||
@@ -247,39 +334,12 @@ class FrameCommand(gdb.Command):
|
|||||||
#
|
#
|
||||||
# Locals
|
# Locals
|
||||||
#
|
#
|
||||||
try:
|
for item in listOfLocals():
|
||||||
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
|
|
||||||
#warn("ITEM %s: " % item.value)
|
#warn("ITEM %s: " % item.value)
|
||||||
|
|
||||||
type = item.value.type
|
type = item.value.type
|
||||||
if type.code == gdb.TYPE_CODE_PTR \
|
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:
|
# Special handling for char** argv:
|
||||||
n = 0
|
n = 0
|
||||||
p = item.value
|
p = item.value
|
||||||
@@ -289,7 +349,7 @@ class FrameCommand(gdb.Command):
|
|||||||
|
|
||||||
d.beginHash()
|
d.beginHash()
|
||||||
d.put('iname="%s",' % item.iname)
|
d.put('iname="%s",' % item.iname)
|
||||||
d.putName(name)
|
d.putName(item.name)
|
||||||
d.putItemCount(select(n <= 100, n, "> 100"))
|
d.putItemCount(select(n <= 100, n, "> 100"))
|
||||||
d.putType(type)
|
d.putType(type)
|
||||||
d.putNumChild(n)
|
d.putNumChild(n)
|
||||||
@@ -313,14 +373,6 @@ class FrameCommand(gdb.Command):
|
|||||||
d.safePutItemHelper(item)
|
d.safePutItemHelper(item)
|
||||||
d.endHash()
|
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()
|
d.pushOutput()
|
||||||
locals = d.safeoutput
|
locals = d.safeoutput
|
||||||
|
|
||||||
@@ -386,7 +438,7 @@ class FrameCommand(gdb.Command):
|
|||||||
d.put('type=" ",numchild="0"')
|
d.put('type=" ",numchild="0"')
|
||||||
else:
|
else:
|
||||||
try:
|
try:
|
||||||
value = gdb.parse_and_eval(exp)
|
value = parseAndEvaluate(exp)
|
||||||
item = Item(value, "watch", name, name)
|
item = Item(value, "watch", name, name)
|
||||||
d.safePutItemHelper(item)
|
d.safePutItemHelper(item)
|
||||||
except RuntimeError:
|
except RuntimeError:
|
||||||
|
@@ -613,7 +613,6 @@ def qdump__QObject(d, item):
|
|||||||
# % (d.ns, item.value.address, propertyName)
|
# % (d.ns, item.value.address, propertyName)
|
||||||
#exp = '"((\'%sQObject\'*)%s)"' % (d.ns, item.value.address,)
|
#exp = '"((\'%sQObject\'*)%s)"' % (d.ns, item.value.address,)
|
||||||
#warn("EXPRESSION: %s" % exp)
|
#warn("EXPRESSION: %s" % exp)
|
||||||
#value = gdb.parse_and_eval(exp)
|
|
||||||
value = call(item.value, 'property("%s")' % propertyName)
|
value = call(item.value, 'property("%s")' % propertyName)
|
||||||
warn("VALUE: %s" % value)
|
warn("VALUE: %s" % value)
|
||||||
warn("TYPE: %s" % value.type)
|
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(_("show version"), CB(handleShowVersion));
|
||||||
|
|
||||||
postCommand(_("source -p ") + dumperSourcePath + _("dumper.py"));
|
postCommand(_("python execfile('%1dumper.py')").arg(dumperSourcePath));
|
||||||
postCommand(_("source -p ") + dumperSourcePath + _("gdbmacros.py"));
|
postCommand(_("python execfile('%1gdbmacros.py')").arg(dumperSourcePath));
|
||||||
|
|
||||||
postCommand(_("-interpreter-exec console \"help bb\""),
|
postCommand(_("-interpreter-exec console \"help bb\""),
|
||||||
CB(handleIsSynchroneous));
|
CB(handleIsSynchroneous));
|
||||||
|
Reference in New Issue
Block a user