3 """Validate compact unwind info by cross checking the llvm-objdump
4 reports of the input object file vs final linked output.
6 from __future__
import print_function
10 from pprint
import pprint
17 parser
= argparse
.ArgumentParser(description
=__doc__
)
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()
28 objdump_string
= "".join([open(f
).read() for f
in args
.files
])
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),
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
= {
55 for address
, symbol
in re
.findall(
56 r
"^%s(%s) g\s+F __TEXT,__text (x\1|_main)$" % (hex8
, hex8
),
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,
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,
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
87 for symbol
in sorted(object_encodings_map
):
88 encoding
= object_encodings_map
[symbol
]
89 fold
= encoding
== encoding0
91 del object_encodings_map
[symbol
]
93 print("%s %s with %s" % ("delete" if fold
else "retain", symbol
, encoding
))
96 if program_encodings_map
!= object_encodings_map
:
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
= [
112 encoding_frequency_map
,
113 key
=lambda x
: (encoding_frequency_map
.get(x
), x
),
117 del encoding_frequencies
[127:]
119 if program_common_encodings
!= encoding_frequencies
:
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__":