Index: gdb/contrib/test_pubnames_and_indexes.py |
diff --git a/gdb/contrib/test_pubnames_and_indexes.py b/gdb/contrib/test_pubnames_and_indexes.py |
new file mode 100644 |
index 0000000000000000000000000000000000000000..12d6d6d8f246ee41b4a5fb0df269b83f05ab7cd2 |
--- /dev/null |
+++ b/gdb/contrib/test_pubnames_and_indexes.py |
@@ -0,0 +1,207 @@ |
+#! /usr/bin/env python |
+ |
+# Copyright (C) 2011-2012 Free Software Foundation, Inc. |
+# |
+# This file is part of GDB. |
+# |
+# This program is free software; you can redistribute it and/or modify |
+# it under the terms of the GNU General Public License as published by |
+# the Free Software Foundation; either version 3 of the License, or |
+# (at your option) any later version. |
+# |
+# This program is distributed in the hope that it will be useful, |
+# but WITHOUT ANY WARRANTY; without even the implied warranty of |
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
+# GNU General Public License for more details. |
+# |
+# You should have received a copy of the GNU General Public License |
+# along with this program. If not, see <http://www.gnu.org/licenses/>. |
+ |
+# This program requires readelf, gdb and objcopy. The default values are gdb |
+# from the build tree and objcopy and readelf from $PATH. They may be |
+# overridden by setting environment variables GDB, READELF and OBJCOPY |
+# respectively. We assume the current directory is either $obj/gdb or |
+# $obj/gdb/testsuite. |
+# |
+# Example usage: |
+# |
+# bash$ cd $objdir/gdb/testsuite |
+# bash$ python test_pubnames_and_indexes.py <binary_name> |
+ |
+"""test_pubnames_and_indexes.py |
+ |
+Test that the gdb_index produced by gold is identical to the gdb_index |
+produced by gdb itself. |
+ |
+Further check that the pubnames and pubtypes produced by gcc are identical |
+to those that gdb produces. |
+ |
+Finally, check that all strings are canonicalized identically. |
+""" |
+ |
+__author__ = 'saugustine@google.com (Sterling Augustine)' |
+ |
+import os |
+import subprocess |
+import sys |
+ |
+OBJCOPY = None |
+READELF = None |
+GDB = None |
+ |
+def get_pub_info(filename, readelf_option): |
+ """Parse and return all the pubnames or pubtypes produced by readelf with the |
+ given option. |
+ """ |
+ readelf = subprocess.Popen([READELF, '--debug-dump=' + readelf_option, |
+ filename], stdout=subprocess.PIPE) |
+ pubnames = [] |
+ |
+ in_list = False; |
+ for line in readelf.stdout: |
+ fields = line.split(None, 1) |
+ if (len(fields) == 2 and fields[0] == 'Offset' |
+ and fields[1].strip() == 'Name'): |
+ in_list = True |
+ # Either a blank-line or a new Length field terminates the current section. |
+ elif (len(fields) == 0 or fields[0] == 'Length:'): |
+ in_list = False; |
+ elif (in_list): |
+ pubnames.append(fields[1].strip()) |
+ |
+ readelf.wait() |
+ return pubnames |
+ |
+ |
+def get_gdb_index(filename): |
+ """Use readelf to dump the gdb index and collect the types and names""" |
+ readelf = subprocess.Popen([READELF, '--debug-dump=gdb_index', |
+ filename], stdout=subprocess.PIPE) |
+ index_symbols = [] |
+ symbol_table_started = False |
+ for line in readelf.stdout: |
+ if (line == 'Symbol table:\n'): |
+ symbol_table_started = True; |
+ elif (symbol_table_started): |
+ # Readelf prints gdb-index lines formatted like so: |
+ # [ 4] two::c2<double>::c2: 0 |
+ # So take the string between the first close bracket and the last colon. |
+ index_symbols.append(line[line.find(']') + 2: line.rfind(':')]) |
+ |
+ readelf.wait() |
+ return index_symbols |
+ |
+ |
+def CheckSets(list0, list1, name0, name1): |
+ """Report any setwise differences between the two lists""" |
+ |
+ if len(list0) == 0 or len(list1) == 0: |
+ return False |
+ |
+ difference0 = set(list0) - set(list1) |
+ if len(difference0) != 0: |
+ print "Elements in " + name0 + " but not " + name1 + ": (", |
+ print len(difference0), |
+ print ")" |
+ for element in difference0: |
+ print " " + element |
+ |
+ difference1 = set(list1) - set(list0) |
+ if len(difference1) != 0: |
+ print "Elements in " + name1 + " but not " + name0 + ": (", |
+ print len(difference1), |
+ print ")" |
+ for element in difference1: |
+ print " " + element |
+ |
+ if (len(difference0) != 0 or len(difference1) != 0): |
+ return True |
+ |
+ print name0 + " and " + name1 + " are identical." |
+ return False |
+ |
+ |
+def find_executables(): |
+ """Find the copies of readelf, objcopy and gdb to use.""" |
+ # Executable finding logic follows cc-with-index.sh |
+ global READELF |
+ READELF = os.getenv('READELF') |
+ if READELF is None: |
+ READELF = 'readelf' |
+ global OBJCOPY |
+ OBJCOPY = os.getenv('OBJCOPY') |
+ if OBJCOPY is None: |
+ OBJCOPY = 'objcopy' |
+ |
+ global GDB |
+ GDB = os.getenv('GDB') |
+ if (GDB is None): |
+ if os.path.isfile('./gdb') and os.access('./gdb', os.X_OK): |
+ GDB = './gdb' |
+ elif os.path.isfile('../gdb') and os.access('../gdb', os.X_OK): |
+ GDB = '../gdb' |
+ elif os.path.isfile('../../gdb') and os.access('../../gdb', os.X_OK): |
+ GDB = '../../gdb' |
+ else: |
+ # Punt and use the gdb in the path. |
+ GDB = 'gdb' |
+ |
+ |
+def main(argv): |
+ """The main subprogram.""" |
+ if len(argv) != 2: |
+ print "Usage: test_pubnames_and_indexes.py <filename>" |
+ sys.exit(2) |
+ |
+ find_executables(); |
+ |
+ # Get the index produced by Gold--It should have been built into the binary. |
+ gold_index = get_gdb_index(argv[1]) |
+ |
+ # Collect the pubnames and types list |
+ pubs_list = get_pub_info(argv[1], "pubnames") |
+ pubs_list = pubs_list + get_pub_info(argv[1], "pubtypes") |
+ |
+ # Generate a .gdb_index with gdb |
+ gdb_index_file = argv[1] + '.gdb-generated-index' |
+ subprocess.check_call([OBJCOPY, '--remove-section', '.gdb_index', |
+ argv[1], gdb_index_file]) |
+ subprocess.check_call([GDB, '-batch', '-nx', gdb_index_file, |
+ '-ex', 'save gdb-index ' + os.path.dirname(argv[1]), |
+ '-ex', 'quit']) |
+ subprocess.check_call([OBJCOPY, '--add-section', |
+ '.gdb_index=' + gdb_index_file + '.gdb-index', |
+ gdb_index_file]) |
+ gdb_index = get_gdb_index(gdb_index_file) |
+ os.remove(gdb_index_file) |
+ os.remove(gdb_index_file + '.gdb-index') |
+ |
+ failed = False |
+ gdb_index.sort() |
+ gold_index.sort() |
+ pubs_list.sort() |
+ |
+ # Find the differences between the various indices. |
+ if len(gold_index) == 0: |
+ print "Gold index is empty" |
+ failed |= True |
+ |
+ if len(gdb_index) == 0: |
+ print "Gdb index is empty" |
+ failed |= True |
+ |
+ if len(pubs_list) == 0: |
+ print "Pubs list is empty" |
+ failed |= True |
+ |
+ failed |= CheckSets(gdb_index, gold_index, "gdb index", "gold index") |
+ failed |= CheckSets(pubs_list, gold_index, "pubs list", "gold index") |
+ failed |= CheckSets(pubs_list, gdb_index, "pubs list", "gdb index") |
+ |
+ if failed: |
+ print "Test failed" |
+ sys.exit(1) |
+ |
+ |
+if __name__ == '__main__': |
+ main(sys.argv) |