Debugger: Consolidate code to enumerate shadowed variables

... in {ll,g}dbbridge.py and fix expansion of shadowed items.

Change-Id: Ide0c426416f2df85470fe851f265cf4835395680
Reviewed-by: hjk <hjk@qt.io>
This commit is contained in:
hjk
2016-09-20 11:52:06 +02:00
committed by hjk
parent 39555d3b86
commit b4251d6d24
3 changed files with 62 additions and 100 deletions
+27
View File
@@ -2193,11 +2193,38 @@ class DumperBase:
if numchild != self.currentChildNumChild:
self.put('numchild="%s",' % numchild)
def handleLocals(self, variables):
#warn("VARIABLES: %s" % variables)
self.preping("locals")
shadowed = {}
for value in variables:
self.anonNumber = 0
if value.name == "argv" and value.type.name == "char **":
self.putSpecialArgv(value)
else:
name = value.name
if name in shadowed:
level = shadowed[name]
shadowed[name] = level + 1
name += "@%d" % level
else:
shadowed[name] = 1
# A "normal" local variable or parameter.
iname = value.iname if hasattr(value, 'iname') else 'local.' + name
with TopLevelItem(self, iname):
self.preping("all-" + iname)
self.put('iname="%s",name="%s",' % (iname, name))
self.putItem(value)
self.ping("all-" + iname)
self.ping("locals")
def handleWatches(self, args):
self.preping("watches")
for watcher in args.get("watchers", []):
iname = watcher['iname']
exp = self.hexdecode(watcher['exp'])
self.handleWatch(exp, exp, iname)
self.ping("watches")
def handleWatch(self, origexp, exp, iname):
exp = str(exp).strip()
+12 -62
View File
@@ -457,7 +457,7 @@ class Dumper(DumperBase):
error("FIELD EXTARCTION FAILED: %s" % field)
return None
def listOfLocals(self):
def listOfLocals(self, partialVar):
frame = gdb.selected_frame()
try:
@@ -485,22 +485,16 @@ class Dumper(DumperBase):
if name == "__in_chrg" or name == "__PRETTY_FUNCTION__":
continue
if not partialVar is None and partialVar != name:
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))
try:
value = self.fromNativeDowncastableValue(frame.read_var(name, block))
#warn("READ 1: %s" % value)
value.name = name1
value.iname = "local." + name1
value.name = name
items.append(value)
continue
except:
@@ -509,8 +503,7 @@ class Dumper(DumperBase):
try:
#warn("READ 2: %s" % item.value)
value = self.fromNativeDowncastableValue(frame.read_var(name))
value.name = name1
value.iname = "local." + name1
value.name = name
items.append(value)
continue
except:
@@ -549,46 +542,20 @@ class Dumper(DumperBase):
def fetchVariables(self, args):
self.resetStats()
self.preping("locals")
self.prepare(args)
partialVariable = args.get("partialvar", "")
isPartial = len(partialVariable) > 0
(ok, res) = self.tryFetchInterpreterVariables(args)
if ok:
safePrint(res)
return
#
# Locals
#
self.output.append('data=[')
if isPartial:
parts = partialVariable.split('.')
name = parts[1]
try:
if parts[0] == 'local':
frame = gdb.selected_frame()
value = self.fromNativeDowncastableValue(frame.read_var(name))
else:
name = self.hexdecode(name)
value = self.fromNativeValue(gdb.parse_and_eval(name))
value.iname = parts[0] + '.' + name
value.name = name
variables = [value]
except RuntimeError as error:
warn("ERROR: %s" % error)
variables = []
except:
warn("ERROR")
variables = []
else:
variables = self.listOfLocals()
partialVar = args.get("partialvar", "")
isPartial = len(partialVar) > 0
partialName = partialVar.split('.')[1].split('@')[0] if isPartial else None
#warn("VARIABLES: %s" % variables)
self.ping("locals")
variables = self.listOfLocals(partialName)
# Take care of the return value of the last function call.
if len(self.resultVarName) > 0:
@@ -601,25 +568,8 @@ class Dumper(DumperBase):
# Don't bother. It's only supplementary information anyway.
pass
for value in variables:
with OutputSafer(self):
self.anonNumber = 0
if value.iname == "local.argv" and value.type.name == "char **":
self.putSpecialArgv(value)
else:
# A "normal" local variable or parameter.
with TopLevelItem(self, value.iname):
self.preping("all-" + value.iname)
self.put('iname="%s",' % value.iname)
self.put('name="%s",' % value.name)
self.putItem(value)
self.ping("all-" + value.iname)
self.preping("watches")
with OutputSafer(self):
self.handleWatches(args)
self.ping("watches")
self.handleLocals(variables)
self.handleWatches(args)
self.output.append('],typeinfo=[')
for name in self.typesToReport.keys():
+23 -38
View File
@@ -994,44 +994,6 @@ class Dumper(DumperBase):
self.currentIName = 'local'
self.put('data=[')
self.anonNumber = 0
shadowed = {}
#ids = {} # Filter out duplicates entries at the same address.
# FIXME: Implement shortcut for partial updates.
#if isPartial:
# values = [frame.FindVariable(partialVariable)]
#else:
if True:
values = list(frame.GetVariables(True, True, False, False))
values.reverse() # To get shadowed vars numbered backwards.
for val in values:
if not val.IsValid():
continue
self.currentContextValue = val
name = val.GetName()
#id = "%s:0x%x" % (name, val.GetLoadAddress())
#if id in ids:
# continue
#ids[id] = True
if name is None:
# This can happen for unnamed function parameters with
# default values: void foo(int = 0)
continue
value = self.fromNativeValue(val)
if name in shadowed:
level = shadowed[name]
shadowed[name] = level + 1
name += "@%s" % level
else:
shadowed[name] = 1
if name == "argv" and val.GetType().GetName() == "char **":
self.putSpecialArgv(value)
else:
with SubItem(self, name):
self.put('iname="%s",' % self.currentIName)
self.putItem(value)
with SubItem(self, '[statics]'):
self.put('iname="%s",' % self.currentIName)
@@ -1054,6 +1016,29 @@ class Dumper(DumperBase):
self.putEmptyValue()
self.putNumChild(0)
# FIXME: Implement shortcut for partial updates.
#if isPartial:
# values = [frame.FindVariable(partialVariable)]
#else:
if True:
values = list(frame.GetVariables(True, True, False, False))
values.reverse() # To get shadowed vars numbered backwards.
variables = []
for val in values:
if not val.IsValid():
continue
self.currentContextValue = val
name = val.GetName()
if name is None:
# This can happen for unnamed function parameters with
# default values: void foo(int = 0)
continue
value = self.fromNativeValue(val)
value.name = name
variables.append(value)
self.handleLocals(variables)
self.handleWatches(args)
self.put('],partial="%d"' % isPartial)