3 # Copyright (C) 2011-2020 Free Software Foundation, Inc.
5 # This file is part of GDB.
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.
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.
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/>.
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
28 # bash$ cd $objdir/gdb/testsuite
29 # bash$ python test_pubnames_and_indexes.py <binary_name>
31 """test_pubnames_and_indexes.py
33 Test that the gdb_index produced by gold is identical to the gdb_index
34 produced by gdb itself.
36 Further check that the pubnames and pubtypes produced by gcc are identical
37 to those that gdb produces.
39 Finally, check that all strings are canonicalized identically.
42 __author__
= 'saugustine@google.com (Sterling Augustine)'
52 def get_pub_info(filename
, readelf_option
):
53 """Parse and return all the pubnames or pubtypes produced by readelf with the
56 readelf
= subprocess
.Popen([READELF
, '--debug-dump=' + readelf_option
,
57 filename
], stdout
=subprocess
.PIPE
)
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'):
66 # Either a blank-line or a new Length field terminates the current section.
67 elif (len(fields
) == 0 or fields
[0] == 'Length:'):
70 pubnames
.append(fields
[1].strip())
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
)
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(':')])
95 def CheckSets(list0
, list1
, name0
, name1
):
96 """Report any setwise differences between the two lists"""
98 if len(list0
) == 0 or len(list1
) == 0:
101 difference0
= set(list0
) - set(list1
)
102 if len(difference0
) != 0:
103 print "Elements in " + name0
+ " but not " + name1
+ ": (",
104 print len(difference0
),
106 for element
in difference0
:
109 difference1
= set(list1
) - set(list0
)
110 if len(difference1
) != 0:
111 print "Elements in " + name1
+ " but not " + name0
+ ": (",
112 print len(difference1
),
114 for element
in difference1
:
117 if (len(difference0
) != 0 or len(difference1
) != 0):
120 print name0
+ " and " + name1
+ " are identical."
124 def find_executables():
125 """Find the copies of readelf, objcopy and gdb to use."""
126 # Executable finding logic follows cc-with-index.sh
128 READELF
= os
.getenv('READELF')
132 OBJCOPY
= os
.getenv('OBJCOPY')
137 GDB
= os
.getenv('GDB')
139 if os
.path
.isfile('./gdb') and os
.access('./gdb', os
.X_OK
):
141 elif os
.path
.isfile('../gdb') and os
.access('../gdb', os
.X_OK
):
143 elif os
.path
.isfile('../../gdb') and os
.access('../../gdb', os
.X_OK
):
146 # Punt and use the gdb in the path.
151 """The main subprogram."""
153 print "Usage: test_pubnames_and_indexes.py <filename>"
158 # Get the index produced by Gold--It should have been built into the binary.
159 gold_index
= get_gdb_index(argv
[1])
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")
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]),
172 subprocess
.check_call([OBJCOPY
, '--add-section',
173 '.gdb_index=' + gdb_index_file
+ '.gdb-index',
175 gdb_index
= get_gdb_index(gdb_index_file
)
176 os
.remove(gdb_index_file
)
177 os
.remove(gdb_index_file
+ '.gdb-index')
184 # Find the differences between the various indices.
185 if len(gold_index
) == 0:
186 print "Gold index is empty"
189 if len(gdb_index
) == 0:
190 print "Gdb index is empty"
193 if len(pubs_list
) == 0:
194 print "Pubs list is empty"
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")
206 if __name__
== '__main__':