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:
hjk
2009-12-09 09:53:43 +01:00
parent c311ab0a4f
commit 68bd4d2b95
3 changed files with 127 additions and 76 deletions

View File

@@ -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:

View File

@@ -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)

View File

@@ -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));