]> Git Repo - binutils.git/blob - gdb/contrib/test_pubnames_and_indexes.py
Automatic date update in version.in
[binutils.git] / gdb / contrib / test_pubnames_and_indexes.py
1 #! /usr/bin/env python3
2
3 # Copyright (C) 2011-2022 Free Software Foundation, Inc.
4 #
5 # This file is part of GDB.
6 #
7 # This program is free software; you can redistribute it and/or modify
8 # it under the terms of the GNU General Public License as published by
9 # the Free Software Foundation; either version 3 of the License, or
10 # (at your option) any later version.
11 #
12 # This program is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 # GNU General Public License for more details.
16 #
17 # You should have received a copy of the GNU General Public License
18 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
19
20 # This program requires readelf, gdb and objcopy.  The default values are gdb
21 # from the build tree and objcopy and readelf from $PATH.  They may be
22 # overridden by setting environment variables GDB, READELF and OBJCOPY
23 # respectively.  We assume the current directory is either $obj/gdb or
24 # $obj/gdb/testsuite.
25 #
26 # Example usage:
27 #
28 # bash$ cd $objdir/gdb/testsuite
29 # bash$ python test_pubnames_and_indexes.py <binary_name>
30
31 """test_pubnames_and_indexes.py
32
33 Test that the gdb_index produced by gold is identical to the gdb_index
34 produced by gdb itself.
35
36 Further check that the pubnames and pubtypes produced by gcc are identical
37 to those that gdb produces.
38
39 Finally, check that all strings are canonicalized identically.
40 """
41
42 __author__ = "[email protected] (Sterling Augustine)"
43
44 import os
45 import subprocess
46 import sys
47
48 OBJCOPY = None
49 READELF = None
50 GDB = None
51
52
53 def get_pub_info(filename, readelf_option):
54     """Parse and return all the pubnames or pubtypes produced by readelf with the
55     given option.
56     """
57     readelf = subprocess.Popen(
58         [READELF, "--debug-dump=" + readelf_option, filename], stdout=subprocess.PIPE
59     )
60     pubnames = []
61
62     in_list = False
63     for line in readelf.stdout:
64         fields = line.split(None, 1)
65         if len(fields) == 2 and fields[0] == "Offset" and fields[1].strip() == "Name":
66             in_list = True
67         # Either a blank-line or a new Length field terminates the current section.
68         elif len(fields) == 0 or fields[0] == "Length:":
69             in_list = False
70         elif in_list:
71             pubnames.append(fields[1].strip())
72
73     readelf.wait()
74     return pubnames
75
76
77 def get_gdb_index(filename):
78     """Use readelf to dump the gdb index and collect the types and names"""
79     readelf = subprocess.Popen(
80         [READELF, "--debug-dump=gdb_index", filename], stdout=subprocess.PIPE
81     )
82     index_symbols = []
83     symbol_table_started = False
84     for line in readelf.stdout:
85         if line == "Symbol table:\n":
86             symbol_table_started = True
87         elif symbol_table_started:
88             # Readelf prints gdb-index lines formatted like so:
89             # [  4] two::c2<double>::c2: 0
90             # So take the string between the first close bracket and the last colon.
91             index_symbols.append(line[line.find("]") + 2 : line.rfind(":")])
92
93     readelf.wait()
94     return index_symbols
95
96
97 def CheckSets(list0, list1, name0, name1):
98     """Report any setwise differences between the two lists"""
99
100     if len(list0) == 0 or len(list1) == 0:
101         return False
102
103     difference0 = set(list0) - set(list1)
104     if len(difference0) != 0:
105         print("Elements in " + name0 + " but not " + name1 + ": (", end=" ")
106         print(len(difference0), end=" ")
107         print(")")
108         for element in difference0:
109             print("  " + element)
110
111     difference1 = set(list1) - set(list0)
112     if len(difference1) != 0:
113         print("Elements in " + name1 + " but not " + name0 + ": (", end=" ")
114         print(len(difference1), end=" ")
115         print(")")
116         for element in difference1:
117             print("  " + element)
118
119     if len(difference0) != 0 or len(difference1) != 0:
120         return True
121
122     print(name0 + " and " + name1 + " are identical.")
123     return False
124
125
126 def find_executables():
127     """Find the copies of readelf, objcopy and gdb to use."""
128     # Executable finding logic follows cc-with-index.sh
129     global READELF
130     READELF = os.getenv("READELF")
131     if READELF is None:
132         READELF = "readelf"
133     global OBJCOPY
134     OBJCOPY = os.getenv("OBJCOPY")
135     if OBJCOPY is None:
136         OBJCOPY = "objcopy"
137
138     global GDB
139     GDB = os.getenv("GDB")
140     if GDB is None:
141         if os.path.isfile("./gdb") and os.access("./gdb", os.X_OK):
142             GDB = "./gdb"
143         elif os.path.isfile("../gdb") and os.access("../gdb", os.X_OK):
144             GDB = "../gdb"
145         elif os.path.isfile("../../gdb") and os.access("../../gdb", os.X_OK):
146             GDB = "../../gdb"
147         else:
148             # Punt and use the gdb in the path.
149             GDB = "gdb"
150
151
152 def main(argv):
153     """The main subprogram."""
154     if len(argv) != 2:
155         print("Usage: test_pubnames_and_indexes.py <filename>")
156         sys.exit(2)
157
158     find_executables()
159
160     # Get the index produced by Gold--It should have been built into the binary.
161     gold_index = get_gdb_index(argv[1])
162
163     # Collect the pubnames and types list
164     pubs_list = get_pub_info(argv[1], "pubnames")
165     pubs_list = pubs_list + get_pub_info(argv[1], "pubtypes")
166
167     # Generate a .gdb_index with gdb
168     gdb_index_file = argv[1] + ".gdb-generated-index"
169     subprocess.check_call(
170         [OBJCOPY, "--remove-section", ".gdb_index", argv[1], gdb_index_file]
171     )
172     subprocess.check_call(
173         [
174             GDB,
175             "-batch",
176             "-nx",
177             gdb_index_file,
178             "-ex",
179             "save gdb-index " + os.path.dirname(argv[1]),
180             "-ex",
181             "quit",
182         ]
183     )
184     subprocess.check_call(
185         [
186             OBJCOPY,
187             "--add-section",
188             ".gdb_index=" + gdb_index_file + ".gdb-index",
189             gdb_index_file,
190         ]
191     )
192     gdb_index = get_gdb_index(gdb_index_file)
193     os.remove(gdb_index_file)
194     os.remove(gdb_index_file + ".gdb-index")
195
196     failed = False
197     gdb_index.sort()
198     gold_index.sort()
199     pubs_list.sort()
200
201     # Find the differences between the various indices.
202     if len(gold_index) == 0:
203         print("Gold index is empty")
204         failed |= True
205
206     if len(gdb_index) == 0:
207         print("Gdb index is empty")
208         failed |= True
209
210     if len(pubs_list) == 0:
211         print("Pubs list is empty")
212         failed |= True
213
214     failed |= CheckSets(gdb_index, gold_index, "gdb index", "gold index")
215     failed |= CheckSets(pubs_list, gold_index, "pubs list", "gold index")
216     failed |= CheckSets(pubs_list, gdb_index, "pubs list", "gdb index")
217
218     if failed:
219         print("Test failed")
220         sys.exit(1)
221
222
223 if __name__ == "__main__":
224     main(sys.argv)
This page took 0.037862 seconds and 4 git commands to generate.