[v3,0/7] Fix some libm static issues
[platform/upstream/glibc.git] / scripts / check-wx-segment.py
1 #!/usr/bin/python3
2 # Check ELF program headers for WX segments.
3 # Copyright (C) 2020-2024 Free Software Foundation, Inc.
4 # This file is part of the GNU C Library.
5 #
6 # The GNU C Library is free software; you can redistribute it and/or
7 # modify it under the terms of the GNU Lesser General Public
8 # License as published by the Free Software Foundation; either
9 # version 2.1 of the License, or (at your option) any later version.
10 #
11 # The GNU C Library is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 # Lesser General Public License for more details.
15 #
16 # You should have received a copy of the GNU Lesser General Public
17 # License along with the GNU C Library; if not, see
18 # <https://www.gnu.org/licenses/>.
19
20 """Check that the program headers do not contain write-exec segments."""
21
22 import argparse
23 import os.path
24 import re
25 import sys
26
27 # Regular expression to extract the RWE flags field.  The
28 # address/offset columns have varying width.
29 RE_LOAD = re.compile(
30     r'^  LOAD +(?:0x[0-9a-fA-F]+ +){5}([R ][W ][ E]) +0x[0-9a-fA-F]+\n\Z')
31
32 def process_file(path, inp, xfail):
33     """Analyze one input file."""
34
35     errors = 0
36     for line in inp:
37         error = None
38         if line.startswith('  LOAD '):
39             match = RE_LOAD.match(line)
40             if match is None:
41                 error = 'Invalid LOAD line'
42             else:
43                 flags, = match.groups()
44                 if 'W' in flags and 'E' in flags:
45                     if xfail:
46                         print('{}: warning: WX segment (as expected)'.format(
47                             path))
48                     else:
49                         error = 'WX segment'
50
51         if error is not None:
52             print('{}: error: {}: {!r}'.format(path, error, line.strip()))
53             errors += 1
54
55     if xfail and errors == 0:
56         print('{}: warning: missing expected WX segment'.format(path))
57     return errors
58
59
60 def main():
61     """The main entry point."""
62     parser = argparse.ArgumentParser(description=__doc__)
63     parser.add_argument('--xfail',
64                         help='Mark input files as XFAILed ("*" for all)',
65                         type=str, default='')
66     parser.add_argument('phdrs',
67                         help='Files containing readelf -Wl output',
68                         nargs='*')
69     opts = parser.parse_args(sys.argv)
70
71     xfails = set(opts.xfail.split(' '))
72     xfails_all = opts.xfail.strip() == '*'
73
74     errors = 0
75     for path in opts.phdrs:
76         xfail = ((os.path.basename(path) + '.phdrs') in xfails
77                  or xfails_all)
78         with open(path) as inp:
79             errors += process_file(path, inp, xfail)
80     if errors > 0:
81         sys.exit(1)
82
83
84 if __name__ == '__main__':
85     main()