forked from qt-creator/qt-creator
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:
@@ -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()
|
||||
|
||||
@@ -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():
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user