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:
Christopher Haster
2024-12-10 12:23:17 -06:00
parent c8c12ffae8
commit 4325a06277
3 changed files with 38 additions and 14 deletions
+19 -3
View File
@@ -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
View File
@@ -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
View File
@@ -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?