^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) #!/usr/bin/env python
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) # SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) # Usage: unwcheck.py FILE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) # This script checks the unwind info of each function in file FILE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) # and verifies that the sum of the region-lengths matches the total
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) # length of the function.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) # Based on a shell/awk script originally written by Harish Patil,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) # which was converted to Perl by Matthew Chapman, which was converted
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) # to Python by David Mosberger.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) import os
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) import re
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) import sys
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) if len(sys.argv) != 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) print("Usage: %s FILE" % sys.argv[0])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) sys.exit(2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) readelf = os.getenv("READELF", "readelf")
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) start_pattern = re.compile("<([^>]*)>: \[0x([0-9a-f]+)-0x([0-9a-f]+)\]")
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) rlen_pattern = re.compile(".*rlen=([0-9]+)")
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) def check_func (func, slots, rlen_sum):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) if slots != rlen_sum:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) global num_errors
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) num_errors += 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) if not func: func = "[%#x-%#x]" % (start, end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) print("ERROR: %s: %lu slots, total region length = %lu" % (func, slots, rlen_sum))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) return
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) num_funcs = 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) num_errors = 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) func = False
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) slots = 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) rlen_sum = 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) for line in os.popen("%s -u %s" % (readelf, sys.argv[1])):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) m = start_pattern.match(line)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) if m:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) check_func(func, slots, rlen_sum)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) func = m.group(1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) start = int(m.group(2), 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) end = int(m.group(3), 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) slots = 3 * (end - start) / 16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) rlen_sum = 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) num_funcs += 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) else:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) m = rlen_pattern.match(line)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) if m:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) rlen_sum += int(m.group(1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) check_func(func, slots, rlen_sum)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) if num_errors == 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) print("No errors detected in %u functions." % num_funcs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) else:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) if num_errors > 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) err="errors"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) else:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) err="error"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) print("%u %s detected in %u functions." % (num_errors, err, num_funcs))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) sys.exit(1)