scripts: Fixed incorrect files on recursive results
It's been a while since I've been hurt by Python's late-binding variables. In this case the scope-creep of the "file" variable hid that we didn't actually know which recursive result belonged to which file. Instead we were just assigning whatever the most recent top-level result was. This is fixed by looking up the correct file in childrenof. Though this unfortunately does add quite a bit of noise.
This commit is contained in:
+19
-3
@@ -701,11 +701,16 @@ def collect(obj_paths, *,
|
||||
type = info[int(type['DW_AT_type'].strip('<>'), 0)]
|
||||
if (type.name is not None
|
||||
and type.tag != 'DW_TAG_subroutine_type'):
|
||||
# if we have no file guess from obj path
|
||||
if 'DW_AT_decl_file' in type:
|
||||
file_ = files.get(int(type['DW_AT_decl_file']), '?')
|
||||
else:
|
||||
file_ = re.sub('(\.o)?$', '.c', obj_path, 1)
|
||||
name_ = type.name
|
||||
size_ = sizeof(type, seen | {entry.off})
|
||||
children_, notes_, dirty_ = childrenof(
|
||||
type, seen | {entry.off})
|
||||
children.append(CtxResult(file, name_, size_,
|
||||
children.append(CtxResult(file_, name_, size_,
|
||||
children=children_,
|
||||
notes=notes_))
|
||||
dirty = dirty or dirty_
|
||||
@@ -717,11 +722,16 @@ def collect(obj_paths, *,
|
||||
for child in entry.children:
|
||||
if child.tag != 'DW_TAG_member':
|
||||
continue
|
||||
# if we have no file guess from obj path
|
||||
if 'DW_AT_decl_file' in child:
|
||||
file_ = files.get(int(child['DW_AT_decl_file']), '?')
|
||||
else:
|
||||
file_ = re.sub('(\.o)?$', '.c', obj_path, 1)
|
||||
name_ = child.name
|
||||
size_ = sizeof(child, seen | {entry.off})
|
||||
children_, notes_, dirty_ = childrenof(
|
||||
child, seen | {entry.off})
|
||||
children.append(CtxResult(file, name_, size_,
|
||||
children.append(CtxResult(file_, name_, size_,
|
||||
i=child.off,
|
||||
children=children_,
|
||||
notes=notes_))
|
||||
@@ -793,6 +803,12 @@ def collect(obj_paths, *,
|
||||
if param.tag != 'DW_TAG_formal_parameter':
|
||||
continue
|
||||
|
||||
# if we have no file guess from obj path
|
||||
if 'DW_AT_decl_file' in param:
|
||||
file_ = files.get(int(param['DW_AT_decl_file']), '?')
|
||||
else:
|
||||
file_ = re.sub('(\.o)?$', '.c', obj_path, 1)
|
||||
|
||||
# find name, if there is one
|
||||
name_ = param.name if param.name is not None else '(unnamed)'
|
||||
|
||||
@@ -802,7 +818,7 @@ def collect(obj_paths, *,
|
||||
# find children, recursing if necessary
|
||||
children_, notes_, _ = childrenof(param)
|
||||
|
||||
params.append(CtxResult(file, name_, size_,
|
||||
params.append(CtxResult(file_, name_, size_,
|
||||
i=param.off,
|
||||
children=children_,
|
||||
notes=notes_))
|
||||
|
||||
+13
-10
@@ -633,16 +633,17 @@ class Parser:
|
||||
self.data[self.i:self.i+32]))
|
||||
|
||||
class CGNode(co.namedtuple('CGNode', [
|
||||
'name', 'size', 'qualifiers', 'calls'])):
|
||||
'name', 'file', 'size', 'qualifiers', 'calls'])):
|
||||
__slots__ = ()
|
||||
def __new__(cls, name, size, qualifiers, calls=None):
|
||||
return super().__new__(cls, name, size, qualifiers,
|
||||
def __new__(cls, name, file, size, qualifiers, calls=None):
|
||||
return super().__new__(cls, name, file, size, qualifiers,
|
||||
calls if calls is not None else set())
|
||||
|
||||
def __repr__(self):
|
||||
return '%s(%r, %r, %r, %r)' % (
|
||||
return '%s(%r, %r, %r, %r, %r)' % (
|
||||
self.__class__.__name__,
|
||||
self.name,
|
||||
self.file,
|
||||
self.size,
|
||||
self.qualifiers,
|
||||
self.calls)
|
||||
@@ -699,13 +700,15 @@ def collect_callgraph(ci_path,
|
||||
|
||||
cg_ = {}
|
||||
for node in cg['graph'][0].get('node') or []:
|
||||
m = re.search('([0-9]+) bytes \((.*)\)', node['label'][0])
|
||||
if not m:
|
||||
continue
|
||||
name = cg_key(node['title'][0])
|
||||
label = node['label'][0].split('\\n')
|
||||
if len(label) < 3:
|
||||
continue
|
||||
file = cg_key(label[1]+':').split(':', 1)[0]
|
||||
m = re.match('([0-9]+) bytes \((.*)\)', label[2])
|
||||
size = int(m.group(1))
|
||||
qualifiers = [q.strip() for q in m.group(2).split(',')]
|
||||
cg_[name] = CGNode(name, size, qualifiers)
|
||||
cg_[name] = CGNode(name, file, size, qualifiers)
|
||||
|
||||
for edge in cg['graph'][0].get('edge') or []:
|
||||
cg_[cg_key(edge['sourcename'][0])].calls.add(
|
||||
@@ -777,12 +780,12 @@ def collect(obj_paths, ci_paths, *,
|
||||
if call not in cg:
|
||||
continue
|
||||
node_ = cg[call]
|
||||
file_ = node_.file
|
||||
name_ = node_.name.split(':', 1)[-1]
|
||||
frame_ = frameof(node_)
|
||||
limit_ = limitof(node_, seen | {node.name})
|
||||
children_, notes_, dirty_ = childrenof(node_, seen | {node.name})
|
||||
# TODO this file is a hack... how do we find the correct file?
|
||||
children.append(StackResult(file, name_, frame_, limit_,
|
||||
children.append(StackResult(file_, name_, frame_, limit_,
|
||||
children=children_,
|
||||
notes=notes_))
|
||||
dirty = dirty or dirty_
|
||||
|
||||
+6
-1
@@ -546,12 +546,17 @@ def collect(obj_paths, *,
|
||||
'DW_TAG_union_type'}:
|
||||
children = []
|
||||
for child in entry.children:
|
||||
# if we have no file guess from obj path
|
||||
if 'DW_AT_decl_file' in child:
|
||||
file_ = files.get(int(child['DW_AT_decl_file']), '?')
|
||||
else:
|
||||
file_ = re.sub('(\.o)?$', '.c', obj_path, 1)
|
||||
name_ = child.name
|
||||
size_ = sizeof(child)
|
||||
align_ = alignof(child)
|
||||
children_ = childrenof(child)
|
||||
children.append(StructResult(
|
||||
file, name_, size_, align_,
|
||||
file_, name_, size_, align_,
|
||||
i=child.off,
|
||||
children=children_))
|
||||
# indirect type?
|
||||
|
||||
Reference in New Issue
Block a user