18c2ecf20Sopenharmony_ci#!/usr/bin/env python 28c2ecf20Sopenharmony_ci# SPDX-License-Identifier: GPL-2.0 38c2ecf20Sopenharmony_ci# 48c2ecf20Sopenharmony_ci# Usage: unwcheck.py FILE 58c2ecf20Sopenharmony_ci# 68c2ecf20Sopenharmony_ci# This script checks the unwind info of each function in file FILE 78c2ecf20Sopenharmony_ci# and verifies that the sum of the region-lengths matches the total 88c2ecf20Sopenharmony_ci# length of the function. 98c2ecf20Sopenharmony_ci# 108c2ecf20Sopenharmony_ci# Based on a shell/awk script originally written by Harish Patil, 118c2ecf20Sopenharmony_ci# which was converted to Perl by Matthew Chapman, which was converted 128c2ecf20Sopenharmony_ci# to Python by David Mosberger. 138c2ecf20Sopenharmony_ci# 148c2ecf20Sopenharmony_ciimport os 158c2ecf20Sopenharmony_ciimport re 168c2ecf20Sopenharmony_ciimport sys 178c2ecf20Sopenharmony_ci 188c2ecf20Sopenharmony_ciif len(sys.argv) != 2: 198c2ecf20Sopenharmony_ci print("Usage: %s FILE" % sys.argv[0]) 208c2ecf20Sopenharmony_ci sys.exit(2) 218c2ecf20Sopenharmony_ci 228c2ecf20Sopenharmony_cireadelf = os.getenv("READELF", "readelf") 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_cistart_pattern = re.compile("<([^>]*)>: \[0x([0-9a-f]+)-0x([0-9a-f]+)\]") 258c2ecf20Sopenharmony_cirlen_pattern = re.compile(".*rlen=([0-9]+)") 268c2ecf20Sopenharmony_ci 278c2ecf20Sopenharmony_cidef check_func (func, slots, rlen_sum): 288c2ecf20Sopenharmony_ci if slots != rlen_sum: 298c2ecf20Sopenharmony_ci global num_errors 308c2ecf20Sopenharmony_ci num_errors += 1 318c2ecf20Sopenharmony_ci if not func: func = "[%#x-%#x]" % (start, end) 328c2ecf20Sopenharmony_ci print("ERROR: %s: %lu slots, total region length = %lu" % (func, slots, rlen_sum)) 338c2ecf20Sopenharmony_ci return 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_cinum_funcs = 0 368c2ecf20Sopenharmony_cinum_errors = 0 378c2ecf20Sopenharmony_cifunc = False 388c2ecf20Sopenharmony_cislots = 0 398c2ecf20Sopenharmony_cirlen_sum = 0 408c2ecf20Sopenharmony_cifor line in os.popen("%s -u %s" % (readelf, sys.argv[1])): 418c2ecf20Sopenharmony_ci m = start_pattern.match(line) 428c2ecf20Sopenharmony_ci if m: 438c2ecf20Sopenharmony_ci check_func(func, slots, rlen_sum) 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_ci func = m.group(1) 468c2ecf20Sopenharmony_ci start = int(m.group(2), 16) 478c2ecf20Sopenharmony_ci end = int(m.group(3), 16) 488c2ecf20Sopenharmony_ci slots = 3 * (end - start) / 16 498c2ecf20Sopenharmony_ci rlen_sum = 0 508c2ecf20Sopenharmony_ci num_funcs += 1 518c2ecf20Sopenharmony_ci else: 528c2ecf20Sopenharmony_ci m = rlen_pattern.match(line) 538c2ecf20Sopenharmony_ci if m: 548c2ecf20Sopenharmony_ci rlen_sum += int(m.group(1)) 558c2ecf20Sopenharmony_cicheck_func(func, slots, rlen_sum) 568c2ecf20Sopenharmony_ci 578c2ecf20Sopenharmony_ciif num_errors == 0: 588c2ecf20Sopenharmony_ci print("No errors detected in %u functions." % num_funcs) 598c2ecf20Sopenharmony_cielse: 608c2ecf20Sopenharmony_ci if num_errors > 1: 618c2ecf20Sopenharmony_ci err="errors" 628c2ecf20Sopenharmony_ci else: 638c2ecf20Sopenharmony_ci err="error" 648c2ecf20Sopenharmony_ci print("%u %s detected in %u functions." % (num_errors, err, num_funcs)) 658c2ecf20Sopenharmony_ci sys.exit(1) 66