GDB (xrefs)
test_pubnames_and_indexes.py
Go to the documentation of this file.
1 #! /usr/bin/env python
2 
3 # Copyright (C) 2011-2015 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 
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 
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)
def get_pub_info(filename, readelf_option)
def CheckSets(list0, list1, name0, name1)
const ULONGEST const LONGEST len
Definition: target.h:309