Run DCE after a LoopFlatten test to reduce spurious output [nfc]
[llvm-project.git] / lld / test / MachO / tools / validate-unwind-info.py
blobac49f1ecb58899f1211a2f6713d416ddfcfe2d9a
1 #!/usr/bin/env python
3 """Validate compact unwind info by cross checking the llvm-objdump
4 reports of the input object file vs final linked output.
5 """
6 from __future__ import print_function
7 import sys
8 import argparse
9 import re
10 from pprint import pprint
13 def main():
14 hex = "[a-f\d]"
15 hex8 = hex + "{8}"
17 parser = argparse.ArgumentParser(description=__doc__)
18 parser.add_argument(
19 "files",
20 metavar="FILES",
21 nargs="*",
22 help="output of (llvm-objdump --unwind-info --syms) for object file(s) plus final linker output",
24 parser.add_argument("--debug", action="store_true")
25 args = parser.parse_args()
27 if args.files:
28 objdump_string = "".join([open(f).read() for f in args.files])
29 else:
30 objdump_string = sys.stdin.read()
32 object_encodings_list = [
33 (symbol, encoding, personality, lsda)
34 for symbol, encoding, personality, lsda in re.findall(
35 r"start:\s+0x%s+\s+(\w+)\s+" % hex
36 + r"length:\s+0x%s+\s+" % hex
37 + r"compact encoding:\s+0x(%s+)(?:\s+" % hex
38 + r"personality function:\s+0x(%s+)\s+\w+\s+" % hex
39 + r"LSDA:\s+0x(%s+)\s+\w+(?: \+ 0x%s+)?)?" % (hex, hex),
40 objdump_string,
41 re.DOTALL,
44 object_encodings_map = {
45 symbol: encoding for symbol, encoding, _, _ in object_encodings_list
47 if not object_encodings_map:
48 sys.exit("no object encodings found in input")
50 # generate-cfi-funcs.py doesn't generate unwind info for _main.
51 object_encodings_map["_main"] = "00000000"
53 program_symbols_map = {
54 address: symbol
55 for address, symbol in re.findall(
56 r"^%s(%s) g\s+F __TEXT,__text (x\1|_main)$" % (hex8, hex8),
57 objdump_string,
58 re.MULTILINE,
61 if not program_symbols_map:
62 sys.exit("no program symbols found in input")
64 program_common_encodings = re.findall(
65 r"^\s+encoding\[(?:\d|\d\d|1[01]\d|12[0-6])\]: 0x(%s+)$" % hex,
66 objdump_string,
67 re.MULTILINE,
69 if not program_common_encodings:
70 sys.exit("no common encodings found in input")
72 program_encodings_map = {
73 program_symbols_map[address]: encoding
74 for address, encoding in re.findall(
75 r"^\s+\[\d+\]: function offset=0x(%s+), " % hex
76 + r"encoding(?:\[\d+\])?=0x(%s+)$" % hex,
77 objdump_string,
78 re.MULTILINE,
81 if not object_encodings_map:
82 sys.exit("no program encodings found in input")
84 # Fold adjacent entries from the object file that have matching encodings
85 # TODO(gkm) add check for personality+lsda
86 encoding0 = 0
87 for symbol in sorted(object_encodings_map):
88 encoding = object_encodings_map[symbol]
89 fold = encoding == encoding0
90 if fold:
91 del object_encodings_map[symbol]
92 if args.debug:
93 print("%s %s with %s" % ("delete" if fold else "retain", symbol, encoding))
94 encoding0 = encoding
96 if program_encodings_map != object_encodings_map:
97 if args.debug:
98 print("program encodings map:")
99 pprint(program_encodings_map)
100 print("object encodings map:")
101 pprint(object_encodings_map)
102 sys.exit("encoding maps differ")
104 # Count frequency of object-file folded encodings
105 # and compare with the program-file common encodings table
106 encoding_frequency_map = {}
107 for _, encoding in object_encodings_map.items():
108 encoding_frequency_map[encoding] = 1 + encoding_frequency_map.get(encoding, 0)
109 encoding_frequencies = [
111 for x in sorted(
112 encoding_frequency_map,
113 key=lambda x: (encoding_frequency_map.get(x), x),
114 reverse=True,
117 del encoding_frequencies[127:]
119 if program_common_encodings != encoding_frequencies:
120 if args.debug:
121 pprint("program common encodings:\n" + str(program_common_encodings))
122 pprint("object encoding frequencies:\n" + str(encoding_frequencies))
123 sys.exit("encoding frequencies differ")
126 if __name__ == "__main__":
127 main()