GDB (xrefs)

test_pubnames_and_indexes.py
Go to the documentation of this file.
1 #! /usr/bin/env python
2
3 # Copyright (C) 2011-2018 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__ = 'saugustine@google.com (Sterling Augustine)'
43
44 import os
45 import subprocess
46 import sys
47
48 OBJCOPY = None
49 READELF = None
50 GDB = None
51
52 def get_pub_info(filename, readelf_option):
53 """Parse and return all the pubnames or pubtypes produced by readelf with the
54 given option.
55 """
56 readelf = subprocess.Popen([READELF, '--debug-dump=' + readelf_option,
57 filename], stdout=subprocess.PIPE)
58 pubnames = []
59
60 in_list = False;
61 for line in readelf.stdout:
62 fields = line.split(None, 1)
63 if (len(fields) == 2 and fields[0] == 'Offset'
64 and fields[1].strip() == 'Name'):
65 in_list = True
66 # Either a blank-line or a new Length field terminates the current section.
67 elif (len(fields) == 0 or fields[0] == 'Length:'):
68 in_list = False;
69 elif (in_list):
70 pubnames.append(fields[1].strip())
71
72 readelf.wait()
73 return pubnames
74
75
76 def get_gdb_index(filename):
77 """Use readelf to dump the gdb index and collect the types and names"""
78 readelf = subprocess.Popen([READELF, '--debug-dump=gdb_index',
79 filename], stdout=subprocess.PIPE)
80 index_symbols = []
81 symbol_table_started = False
82 for line in readelf.stdout:
83 if (line == 'Symbol table:\n'):
84 symbol_table_started = True;
85 elif (symbol_table_started):
86 # Readelf prints gdb-index lines formatted like so:
87 # [ 4] two::c2<double>::c2: 0
88 # So take the string between the first close bracket and the last colon.
89 index_symbols.append(line[line.find(']') + 2: line.rfind(':')])
90
91 readelf.wait()
92 return index_symbols
93
94
95 def CheckSets(list0, list1, name0, name1):
96 """Report any setwise differences between the two lists"""
97
98 if len(list0) == 0 or len(list1) == 0:
99 return False
100
101 difference0 = set(list0) - set(list1)
102 if len(difference0) != 0:
103 print "Elements in " + name0 + " but not " + name1 + ": (",
104 print len(difference0),
105 print ")"
106 for element in difference0:
107 print " " + element
108
109 difference1 = set(list1) - set(list0)
110 if len(difference1) != 0:
111 print "Elements in " + name1 + " but not " + name0 + ": (",
112 print len(difference1),
113 print ")"
114 for element in difference1:
115 print " " + element
116
117 if (len(difference0) != 0 or len(difference1) != 0):
118 return True
119
120 print name0 + " and " + name1 + " are identical."
121 return False
122
123
124 def find_executables():
125 """Find the copies of readelf, objcopy and gdb to use."""
126 # Executable finding logic follows cc-with-index.sh
127 global READELF
128 READELF = os.getenv('READELF')
129 if READELF is None:
130 READELF = 'readelf'
131 global OBJCOPY
132 OBJCOPY = os.getenv('OBJCOPY')
133 if OBJCOPY is None:
134 OBJCOPY = 'objcopy'
135
136 global GDB
137 GDB = os.getenv('GDB')
138 if (GDB is None):
139 if os.path.isfile('./gdb') and os.access('./gdb', os.X_OK):
140 GDB = './gdb'
141 elif 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 else:
146 # Punt and use the gdb in the path.
147 GDB = 'gdb'
148
149
150 def main(argv):
151 """The main subprogram."""
152 if len(argv) != 2:
153 print "Usage: test_pubnames_and_indexes.py <filename>"
154 sys.exit(2)
155
156 find_executables();
157
158 # Get the index produced by Gold--It should have been built into the binary.
159 gold_index = get_gdb_index(argv[1])
160
161 # Collect the pubnames and types list
162 pubs_list = get_pub_info(argv[1], "pubnames")
163 pubs_list = pubs_list + get_pub_info(argv[1], "pubtypes")
164
165 # Generate a .gdb_index with gdb
166 gdb_index_file = argv[1] + '.gdb-generated-index'
167 subprocess.check_call([OBJCOPY, '--remove-section', '.gdb_index',
168 argv[1], gdb_index_file])
169 subprocess.check_call([GDB, '-batch', '-nx', gdb_index_file,
170 '-ex', 'save gdb-index ' + os.path.dirname(argv[1]),
171 '-ex', 'quit'])
172 subprocess.check_call([OBJCOPY, '--add-section',
173 '.gdb_index=' + gdb_index_file + '.gdb-index',
174 gdb_index_file])
175 gdb_index = get_gdb_index(gdb_index_file)
176 os.remove(gdb_index_file)
177 os.remove(gdb_index_file + '.gdb-index')
178
179 failed = False
180 gdb_index.sort()
181 gold_index.sort()
182 pubs_list.sort()
183
184 # Find the differences between the various indices.
185 if len(gold_index) == 0:
186 print "Gold index is empty"
187 failed |= True
188
189 if len(gdb_index) == 0:
190 print "Gdb index is empty"
191 failed |= True
192
193 if len(pubs_list) == 0:
194 print "Pubs list is empty"
195 failed |= True
196
197 failed |= CheckSets(gdb_index, gold_index, "gdb index", "gold index")
198 failed |= CheckSets(pubs_list, gold_index, "pubs list", "gold index")
199 failed |= CheckSets(pubs_list, gdb_index, "pubs list", "gdb index")
200
201 if failed:
202 print "Test failed"
203 sys.exit(1)
204
205
206 if __name__ == '__main__':
207 main(sys.argv)
test_pubnames_and_indexes.get_pub_info
def get_pub_info(filename, readelf_option)
Definition: test_pubnames_and_indexes.py:52
test_pubnames_and_indexes.CheckSets
def CheckSets(list0, list1, name0, name1)
Definition: test_pubnames_and_indexes.py:95
test_pubnames_and_indexes.main
def main(argv)
Definition: test_pubnames_and_indexes.py:150
test_pubnames_and_indexes.find_executables
def find_executables()
Definition: test_pubnames_and_indexes.py:124
test_pubnames_and_indexes.get_gdb_index
def get_gdb_index(filename)
Definition: test_pubnames_and_indexes.py:76