Fix invalid escape sequence in build-many-glibcs.py
[glibc.git] / scripts / tst-ld-trace.py
blob66953ab01ff6458172ef697d9f9e6c01983874af
1 #!/usr/bin/python3
2 # Dump the output of LD_TRACE_LOADED_OBJECTS in architecture neutral format.
3 # Copyright (C) 2022-2024 Free Software Foundation, Inc.
4 # Copyright The GNU Toolchain Authors.
5 # This file is part of the GNU C Library.
7 # The GNU C Library is free software; you can redistribute it and/or
8 # modify it under the terms of the GNU Lesser General Public
9 # License as published by the Free Software Foundation; either
10 # version 2.1 of the License, or (at your option) any later version.
12 # The GNU C Library is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 # Lesser General Public License for more details.
17 # You should have received a copy of the GNU Lesser General Public
18 # License along with the GNU C Library; if not, see
19 # <https://www.gnu.org/licenses/>.
21 import argparse
22 import os
23 import subprocess
24 import sys
26 try:
27 subprocess.run
28 except:
29 class _CompletedProcess:
30 def __init__(self, args, returncode, stdout=None, stderr=None):
31 self.args = args
32 self.returncode = returncode
33 self.stdout = stdout
34 self.stderr = stderr
36 def _run(*popenargs, input=None, timeout=None, check=False, **kwargs):
37 assert(timeout is None)
38 with subprocess.Popen(*popenargs, **kwargs) as process:
39 try:
40 stdout, stderr = process.communicate(input)
41 except:
42 process.kill()
43 process.wait()
44 raise
45 returncode = process.poll()
46 if check and returncode:
47 raise subprocess.CalledProcessError(returncode, popenargs)
48 return _CompletedProcess(popenargs, returncode, stdout, stderr)
50 subprocess.run = _run
52 def is_vdso(lib):
53 return lib.startswith('linux-gate') or lib.startswith('linux-vdso')
56 def parse_trace(cmd, fref):
57 new_env = os.environ.copy()
58 new_env['LD_TRACE_LOADED_OBJECTS'] = '1'
59 trace_out = subprocess.run(cmd, stdout=subprocess.PIPE, check=True,
60 universal_newlines=True, env=new_env).stdout
61 trace = []
62 for line in trace_out.splitlines():
63 line = line.strip()
64 if is_vdso(line):
65 continue
66 fields = line.split('=>' if '=>' in line else ' ')
67 lib = os.path.basename(fields[0].strip())
68 if lib.startswith('ld'):
69 lib = 'ld'
70 elif lib.startswith('libc'):
71 lib = 'libc'
72 found = 1 if fields[1].strip() != 'not found' else 0
73 trace += ['{} {}'.format(lib, found)]
74 trace = sorted(trace)
76 reference = sorted(line.replace('\n','') for line in fref.readlines())
78 ret = 0 if trace == reference else 1
79 if ret != 0:
80 for i in reference:
81 if i not in trace:
82 print("Only in {}: {}".format(fref.name, i))
83 for i in trace:
84 if i not in reference:
85 print("Only in trace: {}".format(i))
87 sys.exit(ret)
90 def get_parser():
91 parser = argparse.ArgumentParser(description=__doc__)
92 parser.add_argument('command',
93 help='comand to run')
94 parser.add_argument('reference',
95 help='reference file to compare')
96 return parser
99 def main(argv):
100 parser = get_parser()
101 opts = parser.parse_args(argv)
102 with open(opts.reference, 'r') as fref:
103 # Remove the initial 'env' command.
104 parse_trace(opts.command.split()[1:], fref)
107 if __name__ == '__main__':
108 main(sys.argv[1:])