diff options
author | Sterling Augustine <saugustine@google.com> | 2012-04-30 18:06:50 +0000 |
---|---|---|
committer | Sterling Augustine <saugustine@google.com> | 2012-04-30 18:06:50 +0000 |
commit | be36f02d8a3729c9429487a678153c4705cc92c6 (patch) | |
tree | 7e01a18526d58740d929c627a6ab768757c3654f /gdb/contrib | |
parent | fceca5159fe3cc09e4cfe8fb495397ceb0b4a91a (diff) | |
download | gdb-be36f02d8a3729c9429487a678153c4705cc92c6.zip gdb-be36f02d8a3729c9429487a678153c4705cc92c6.tar.gz gdb-be36f02d8a3729c9429487a678153c4705cc92c6.tar.bz2 |
2012-04-26 Sterling Augustine <saugustine@google.com>
* contrib: New directory.
* contrib/test_pubnames_and_indexes.py: New file.
Diffstat (limited to 'gdb/contrib')
-rw-r--r-- | gdb/contrib/test_pubnames_and_indexes.py | 207 |
1 files changed, 207 insertions, 0 deletions
diff --git a/gdb/contrib/test_pubnames_and_indexes.py b/gdb/contrib/test_pubnames_and_indexes.py new file mode 100644 index 0000000..12d6d6d --- /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) |