scripts: Adopted better input file handling in result scripts

- Error on no/insufficient files.

  Instead of just returning no results. This is more useful when
  debugging complicated bash scripts.

- Use elf magic to allow any file order in perfbd.py/stack.py.

  This was already implemented in stack.py, now also adopted in
  perfbd.py.

  Elf files always start with the magic string "\x7fELF", so we can use
  this to figure out the types of input files without needing to rely on
  argument order.

  This is just one less thing to worry about when invoking these
  scripts.
This commit is contained in:
Christopher Haster
2024-12-10 14:45:46 -06:00
parent 4325a06277
commit 3e03c2ee7f
9 changed files with 117 additions and 11 deletions
+8
View File
@@ -1015,7 +1015,15 @@ def main(obj_paths, *,
**args):
# find sizes
if not args.get('use', None):
# not enough info?
if not obj_paths:
print("error: no *.o files?",
file=sys.stderr)
sys.exit(1)
# collect info
results = collect(obj_paths, **args)
else:
results = []
with openio(args['use']) as f:
+8
View File
@@ -833,7 +833,15 @@ def main(gcda_paths, *,
# find sizes
if not args.get('use', None):
# not enough info?
if not gcda_paths:
print("error: no *.gcda files?",
file=sys.stderr)
sys.exit(1)
# collect info
results = collect(gcda_paths, **args)
else:
results = []
with openio(args['use']) as f:
+7 -1
View File
@@ -1789,7 +1789,13 @@ def main(csv_paths, *,
if args.get('use'):
csv_paths = csv_paths + [args['use']]
# find CSV files
# not enough info?
if not csv_paths:
print("error: no *.csv files?",
file=sys.stderr)
sys.exit(1)
# collect info
fields_, results = collect(csv_paths, defines)
# homogenize
+8
View File
@@ -1230,7 +1230,15 @@ def main(obj_paths, *,
# find sizes
if not args.get('use', None):
# not enough info?
if not obj_paths:
print("error: no *.o files?",
file=sys.stderr)
sys.exit(1)
# collect info
results = collect(obj_paths, **args)
else:
results = []
with openio(args['use']) as f:
+8
View File
@@ -1015,7 +1015,15 @@ def main(obj_paths, *,
**args):
# find sizes
if not args.get('use', None):
# not enough info?
if not obj_paths:
print("error: no *.o files?",
file=sys.stderr)
sys.exit(1)
# collect info
results = collect(obj_paths, **args)
else:
results = []
with openio(args['use']) as f:
+8
View File
@@ -1310,7 +1310,15 @@ def report(perf_paths, *,
# find sizes
if not args.get('use', None):
# not enough info?
if not perf_paths:
print("error: no *.perf files?",
file=sys.stderr)
sys.exit(1)
# collect info
results = collect(perf_paths, **args)
else:
results = []
with openio(args['use']) as f:
+48 -6
View File
@@ -170,6 +170,11 @@ def openio(path, mode='r', buffering=-1):
else:
return open(path, mode, buffering)
def iself(path):
# check for an elf file's magic string (\x7fELF)
with open(path, 'rb') as f:
return f.read(4) == b'\x7fELF'
class Sym(co.namedtuple('Sym', [
'name', 'global_', 'section', 'addr', 'size'])):
__slots__ = ()
@@ -714,7 +719,7 @@ def starapply(args):
f, args, kwargs = args
return f(*args, **kwargs)
def collect(obj_path, trace_paths, *,
def collect(elf_path, trace_paths, *,
jobs=None,
**args):
# automatic job detection?
@@ -722,10 +727,10 @@ def collect(obj_path, trace_paths, *,
jobs = len(os.sched_getaffinity(0))
# find sym/line info to reverse ASLR
syms = collect_syms(obj_path,
syms = collect_syms(elf_path,
sections=['.text'],
**args)
lines = collect_dwarf_lines(obj_path, **args)
lines = collect_dwarf_lines(elf_path, **args)
if jobs is not None:
# try to split up files so that even single files can be processed
@@ -1265,7 +1270,7 @@ def annotate(Result, results, *,
print(line)
def report(obj_path='', trace_paths=[], *,
def report(paths, *,
by=None,
fields=None,
defines=[],
@@ -1287,7 +1292,32 @@ def report(obj_path='', trace_paths=[], *,
# find sizes
if not args.get('use', None):
results = collect(obj_path, trace_paths, **args)
# figure out paths
elf_paths = []
trace_paths = []
for path in paths:
if iself(path):
elf_paths.append(path)
else:
trace_paths.append(path)
# not enough info?
if not elf_paths:
print("error: no elf file?",
file=sys.stderr)
sys.exit(1)
if not trace_paths:
print("error: no *.trace files?",
file=sys.stderr)
sys.exit(1)
# too much info?
if len(elf_paths) != 1:
print("error: multiple elf files?",
file=sys.stderr)
sys.exit(1)
# collect info
results = collect(elf_paths[0], trace_paths, **args)
else:
results = []
with openio(args['use']) as f:
@@ -1400,13 +1430,25 @@ if __name__ == "__main__":
description="Aggregate and report call-stack propagated "
"block-device operations from trace output.",
allow_abbrev=False)
class AppendPath(argparse.Action):
def __call__(self, parser, namespace, value, option):
if getattr(namespace, 'paths', None) is None:
namespace.paths = []
if value is None:
pass
elif isinstance(value, str):
namespace.paths.append(value)
else:
namespace.paths.extend(value)
parser.add_argument(
'obj_path',
'elf_path',
nargs='?',
action=AppendPath,
help="Input executable for mapping addresses to symbols.")
parser.add_argument(
'trace_paths',
nargs='*',
action=AppendPath,
help="Input *.trace files.")
parser.add_argument(
'-v', '--verbose',
+14 -4
View File
@@ -1383,15 +1383,25 @@ if __name__ == "__main__":
parser = argparse.ArgumentParser(
description="Find stack usage at the function level.",
allow_abbrev=False)
class AppendPath(argparse.Action):
def __call__(self, parser, namespace, value, option):
if getattr(namespace, 'paths', None) is None:
namespace.paths = []
if value is None:
pass
elif isinstance(value, str):
namespace.paths.append(value)
else:
namespace.paths.extend(value)
parser.add_argument(
'paths',
metavar='obj_paths',
'obj_paths',
nargs='*',
action=AppendPath,
help="Input *.o files.")
parser.add_argument(
'paths_',
metavar='ci_paths',
'ci_paths',
nargs='*',
action=AppendPath,
help="Input *.ci files.")
parser.add_argument(
'-v', '--verbose',
+8
View File
@@ -1043,7 +1043,15 @@ def main(obj_paths, *,
# find sizes
if not args.get('use', None):
# not enough info?
if not obj_paths:
print("error: no *.o files?",
file=sys.stderr)
sys.exit(1)
# collect info
results = collect(obj_paths, **args)
else:
results = []
with openio(args['use']) as f: