* Script to compare pubnames, gdb index as produced by gold and gdb index as produced by gdb
@ 2012-04-27 0:37 Sterling Augustine
2012-04-27 2:06 ` Doug Evans
0 siblings, 1 reply; 7+ messages in thread
From: Sterling Augustine @ 2012-04-27 0:37 UTC (permalink / raw)
To: gdb-patches
[-- Attachment #1: Type: text/plain, Size: 891 bytes --]
Enclosed is patch with a python script which takes a binary and
performs a three-way comparison between the elements in:
1. The pubnames and pubtypes sections as generated by gcc
2. The .gdb_index section as generated by gold
3. The .gdb_index section as generated by gdb
I have found it very useful in working on the fission project and I
suspect anyone else who is working on gdb_index would also find it
useful. I'm very open to moving it to a different location--is there
no "contrib" directory?--or not checking it in at all.
In a perfect world, this script would be included in the testsuite and
run against a wide variety of programs, but the configury associated
with determining whether the right versions of gdb, gold and gcc are
available is beyond my ken.
Thanks,
Sterling
012-04-26 Sterling Augustine <saugustine@google.com>
* test_pubnames_and_indexes.py: New file.
[-- Attachment #2: test_pubnames.patch --]
[-- Type: application/octet-stream, Size: 6873 bytes --]
Index: test_pubnames_and_indexes.py
===================================================================
RCS file: test_pubnames_and_indexes.py
diff -N test_pubnames_and_indexes.py
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ test_pubnames_and_indexes.py 26 Apr 2012 23:31:49 -0000
@@ -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)
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: Script to compare pubnames, gdb index as produced by gold and gdb index as produced by gdb
2012-04-27 0:37 Script to compare pubnames, gdb index as produced by gold and gdb index as produced by gdb Sterling Augustine
@ 2012-04-27 2:06 ` Doug Evans
2012-04-27 16:01 ` Tom Tromey
0 siblings, 1 reply; 7+ messages in thread
From: Doug Evans @ 2012-04-27 2:06 UTC (permalink / raw)
To: Sterling Augustine; +Cc: gdb-patches
On Thu, Apr 26, 2012 at 4:40 PM, Sterling Augustine
<saugustine@google.com> wrote:
> Enclosed is patch with a python script which takes a binary and
> performs a three-way comparison between the elements in:
>
> 1. The pubnames and pubtypes sections as generated by gcc
> 2. The .gdb_index section as generated by gold
> 3. The .gdb_index section as generated by gdb
>
> I have found it very useful in working on the fission project and I
> suspect anyone else who is working on gdb_index would also find it
> useful. I'm very open to moving it to a different location--is there
> no "contrib" directory?--or not checking it in at all.
>
> In a perfect world, this script would be included in the testsuite and
> run against a wide variety of programs, but the configury associated
> with determining whether the right versions of gdb, gold and gcc are
> available is beyond my ken.
There is/was a src/contrib directory, but setting aside a possibility
of separating gdb and binutils trees src/contrib would be shared by a
lot of packages.
Since we have a few outstanding requests for where to put similar things,
I propose creating src/gdb/contrib.
>
> Thanks,
>
> Sterling
>
>
> 012-04-26 Sterling Augustine <saugustine@google.com>
>
> * test_pubnames_and_indexes.py: New file.
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: Script to compare pubnames, gdb index as produced by gold and gdb index as produced by gdb
2012-04-27 2:06 ` Doug Evans
@ 2012-04-27 16:01 ` Tom Tromey
2012-04-27 18:48 ` Doug Evans
0 siblings, 1 reply; 7+ messages in thread
From: Tom Tromey @ 2012-04-27 16:01 UTC (permalink / raw)
To: Doug Evans; +Cc: Sterling Augustine, gdb-patches
>>>>> "Doug" == Doug Evans <dje@google.com> writes:
Doug> Since we have a few outstanding requests for where to put similar things,
Doug> I propose creating src/gdb/contrib.
Works for me.
Tom
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: Script to compare pubnames, gdb index as produced by gold and gdb index as produced by gdb
2012-04-27 16:01 ` Tom Tromey
@ 2012-04-27 18:48 ` Doug Evans
2012-04-27 19:44 ` Joel Brobecker
0 siblings, 1 reply; 7+ messages in thread
From: Doug Evans @ 2012-04-27 18:48 UTC (permalink / raw)
To: Tom Tromey; +Cc: Sterling Augustine, gdb-patches
On Fri, Apr 27, 2012 at 8:54 AM, Tom Tromey <tromey@redhat.com> wrote:
>>>>>> "Doug" == Doug Evans <dje@google.com> writes:
>
> Doug> Since we have a few outstanding requests for where to put similar things,
> Doug> I propose creating src/gdb/contrib.
>
> Works for me.
Cool. Next fun question.
gdb/contrib/ChangeLog? 1/2 :-)
/me ducks
I don't have a preference on this. There is gdb/doc/ChangeLog and
gdb/testsuite/ChangeLog, but for this I'd be inclined to stick with
gdb/ChangeLog.
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: Script to compare pubnames, gdb index as produced by gold and gdb index as produced by gdb
2012-04-27 18:48 ` Doug Evans
@ 2012-04-27 19:44 ` Joel Brobecker
2012-04-27 20:17 ` Tom Tromey
0 siblings, 1 reply; 7+ messages in thread
From: Joel Brobecker @ 2012-04-27 19:44 UTC (permalink / raw)
To: Doug Evans; +Cc: Tom Tromey, Sterling Augustine, gdb-patches
> gdb/contrib/ChangeLog? 1/2 :-)
> /me ducks
/me throws a pillow :-).
> I don't have a preference on this. There is gdb/doc/ChangeLog and
> gdb/testsuite/ChangeLog, but for this I'd be inclined to stick with
> gdb/ChangeLog.
I don't have a preference, but ISTR that we were generally in favor
of fewer ChangeLog files. If anything, it helps me get an idea of
the list of changes that were made in the past without having to
use the VCS (and filter out this $!#$#% daily version update commits).
--
Joel
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: Script to compare pubnames, gdb index as produced by gold and gdb index as produced by gdb
2012-04-27 19:44 ` Joel Brobecker
@ 2012-04-27 20:17 ` Tom Tromey
2012-04-30 18:43 ` Sterling Augustine
0 siblings, 1 reply; 7+ messages in thread
From: Tom Tromey @ 2012-04-27 20:17 UTC (permalink / raw)
To: Joel Brobecker; +Cc: Doug Evans, Sterling Augustine, gdb-patches
Joel> I don't have a preference, but ISTR that we were generally in favor
Joel> of fewer ChangeLog files.
Yes, please, I'd prefer no new ones.
They are a pain to deal with and I don't think separate ones add much value.
Tom
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: Script to compare pubnames, gdb index as produced by gold and gdb index as produced by gdb
2012-04-27 20:17 ` Tom Tromey
@ 2012-04-30 18:43 ` Sterling Augustine
0 siblings, 0 replies; 7+ messages in thread
From: Sterling Augustine @ 2012-04-30 18:43 UTC (permalink / raw)
To: Tom Tromey; +Cc: Joel Brobecker, Doug Evans, gdb-patches
[-- Attachment #1: Type: text/plain, Size: 595 bytes --]
On Fri, Apr 27, 2012 at 12:58 PM, Tom Tromey <tromey@redhat.com> wrote:
> Joel> I don't have a preference, but ISTR that we were generally in favor
> Joel> of fewer ChangeLog files.
>
> Yes, please, I'd prefer no new ones.
> They are a pain to deal with and I don't think separate ones add much value.
Alright then. I have committed the following patch which creates a new
gdb/contrib directory and populates it with
test_pubnames_and_indexes.py.
Sterling
2012-04-26 Sterling Augustine <saugustine@google.com>
* contrib: New directory.
* contrib/test_pubnames_and_indexes.py: New file.
[-- Attachment #2: test_pubnames.patch --]
[-- Type: application/octet-stream, Size: 6905 bytes --]
Index: contrib/test_pubnames_and_indexes.py
===================================================================
RCS file: contrib/test_pubnames_and_indexes.py
diff -N contrib/test_pubnames_and_indexes.py
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ contrib/test_pubnames_and_indexes.py 30 Apr 2012 18:04:06 -0000
@@ -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)
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2012-04-30 18:09 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-04-27 0:37 Script to compare pubnames, gdb index as produced by gold and gdb index as produced by gdb Sterling Augustine
2012-04-27 2:06 ` Doug Evans
2012-04-27 16:01 ` Tom Tromey
2012-04-27 18:48 ` Doug Evans
2012-04-27 19:44 ` Joel Brobecker
2012-04-27 20:17 ` Tom Tromey
2012-04-30 18:43 ` Sterling Augustine
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox