This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
Improve separate debug file support for elfutils
- From: Daniel Jacobowitz <drow at false dot org>
- To: gdb-patches at sourceware dot org
- Date: Fri, 6 Oct 2006 16:25:50 -0400
- Subject: Improve separate debug file support for elfutils
It turns out that elfutils's eu-strip differs from objcopy --only-keep-debug
in one important respect: elfutils tends to leave .symtab in the original
file and put a NOBITS copy in the separate debug file, but objcopy moves the
whole symtab. This difference shows up a problem in GDB.
We search for the section containing the PC in a bunch of places, mostly for
overlay support (does this even still work? no idea). When we look up the
section for the PC, we might find either the copy in the separate debug file
or the original; they cover the same PC ranges. So we need to allow the
two sections to be treated as equal. That's what this patch implements.
I'm not sure how well it would work with overlays - but I don't see a way,
even in theory, to do better.
The change to "info sym" is a cosmetic improvement, which I made while
trying to find a way to test this portably. The original test was on ARM
with Thumb; we would try to look up the minsym to figure out whether to
set a 2-byte or 4-byte breakpoint, and by failing to find the minsym,
we set the wrong type.
I plan to commit this, probably next week, unless someone happens to have
an idea for another solution. Tested x86_64-pc-linux-gnu.
--
Daniel Jacobowitz
CodeSourcery
2006-10-06 Daniel Jacobowitz <dan@codesourcery.com>
* Makefile.in (symtab.o): Update.
* symtab.h (matching_bfd_section): New prototype.
* symtab.c (matching_bfd_section): New.
(find_pc_sect_psymbol, find_pc_sect_symtab): Use it.
* minsyms.c (lookup_minimal_symbol_by_pc_section): Likewise.
* printcmd.c (sym_info): Ignore separate debug objfiles.
2006-10-06 Daniel Jacobowitz <dan@codesourcery.com>
* gdb.base/sepdebug.exp: Remove debug format test.
* lib/gdb.exp (gdb_gnu_strip_debug): Perform debug format test.
Handle no-symtab.
* gdb.base/sepsymtab.c, gdb.base/sepsymtab.exp: New.
Index: Makefile.in
===================================================================
RCS file: /cvs/src/src/gdb/Makefile.in,v
retrieving revision 1.845
diff -u -p -r1.845 Makefile.in
--- Makefile.in 5 Oct 2006 19:42:31 -0000 1.845
+++ Makefile.in 6 Oct 2006 17:13:24 -0000
@@ -2754,7 +2754,7 @@ symtab.o: symtab.c $(defs_h) $(symtab_h)
$(language_h) $(demangle_h) $(inferior_h) $(linespec_h) $(source_h) \
$(filenames_h) $(objc_lang_h) $(ada_lang_h) $(hashtab_h) \
$(gdb_obstack_h) $(block_h) $(dictionary_h) $(gdb_string_h) \
- $(gdb_stat_h) $(cp_abi_h) $(observer_h)
+ $(gdb_stat_h) $(cp_abi_h) $(observer_h) $(gdb_assert_h)
target.o: target.c $(defs_h) $(gdb_string_h) $(target_h) $(gdbcmd_h) \
$(symtab_h) $(inferior_h) $(bfd_h) $(symfile_h) $(objfiles_h) \
$(gdb_wait_h) $(dcache_h) $(regcache_h) $(gdb_assert_h) $(gdbcore_h)
Index: minsyms.c
===================================================================
RCS file: /cvs/src/src/gdb/minsyms.c,v
retrieving revision 1.46
diff -u -p -r1.46 minsyms.c
--- minsyms.c 19 Jul 2006 02:17:23 -0000 1.46
+++ minsyms.c 6 Oct 2006 17:13:24 -0000
@@ -360,7 +360,6 @@ lookup_minimal_symbol_solib_trampoline (
return NULL;
}
-
/* Search through the minimal symbol table for each objfile and find
the symbol whose address is the largest address that is still less
than or equal to PC, and matches SECTION (if non-NULL). Returns a
@@ -491,7 +490,8 @@ lookup_minimal_symbol_by_pc_section (COR
don't fill the bfd_section member, so don't
throw away symbols on those platforms. */
&& SYMBOL_BFD_SECTION (&msymbol[hi]) != NULL
- && SYMBOL_BFD_SECTION (&msymbol[hi]) != section)
+ && (!matching_bfd_sections
+ (SYMBOL_BFD_SECTION (&msymbol[hi]), section)))
{
hi--;
continue;
Index: printcmd.c
===================================================================
RCS file: /cvs/src/src/gdb/printcmd.c,v
retrieving revision 1.98
diff -u -p -r1.98 printcmd.c
--- printcmd.c 17 Jul 2006 22:15:55 -0000 1.98
+++ printcmd.c 6 Oct 2006 17:13:24 -0000
@@ -983,6 +983,11 @@ sym_info (char *arg, int from_tty)
addr = parse_and_eval_address (arg);
ALL_OBJSECTIONS (objfile, osect)
{
+ /* Only process each object file once, even if there's a separate
+ debug file. */
+ if (objfile->separate_debug_objfile_backlink)
+ continue;
+
sect = osect->the_bfd_section;
sect_addr = overlay_mapped_address (addr, sect);
Index: symtab.c
===================================================================
RCS file: /cvs/src/src/gdb/symtab.c,v
retrieving revision 1.147
diff -u -p -r1.147 symtab.c
--- symtab.c 11 May 2006 09:29:52 -0000 1.147
+++ symtab.c 6 Oct 2006 17:13:25 -0000
@@ -56,6 +56,7 @@
#include <ctype.h>
#include "cp-abi.h"
#include "observer.h"
+#include "gdb_assert.h"
/* Prototypes for local functions */
@@ -706,6 +707,64 @@ init_sal (struct symtab_and_line *sal)
}
+/* Return 1 if the two sections are the same, or if they could
+ plausibly be copies of each other, one in an original object
+ file and another in a separated debug file. */
+
+int
+matching_bfd_sections (asection *first, asection *second)
+{
+ struct objfile *obj;
+
+ /* If they're the same section, then they match. */
+ if (first == second)
+ return 1;
+
+ /* If either is NULL, give up. */
+ if (first == NULL || second == NULL)
+ return 0;
+
+ /* This doesn't apply to absolute symbols. */
+ if (first->owner == NULL || second->owner == NULL)
+ return 0;
+
+ /* If they're in the same object file, they must be different sections. */
+ if (first->owner == second->owner)
+ return 0;
+
+ /* Check whether the two sections are potentially corresponding. They must
+ have the same size, address, and name. We can't compare section indexes,
+ which would be more reliable, because some sections may have been
+ stripped. */
+ if (bfd_get_section_size (first) != bfd_get_section_size (second))
+ return 0;
+
+ if (bfd_get_section_vma (first->owner, first)
+ != bfd_get_section_vma (second->owner, second))
+ return 0;
+
+ if (bfd_get_section_name (first->owner, first) == NULL
+ || bfd_get_section_name (second->owner, second) == NULL
+ || strcmp (bfd_get_section_name (first->owner, first),
+ bfd_get_section_name (second->owner, second)) != 0)
+ return 0;
+
+ /* Otherwise check that they are in corresponding objfiles. */
+
+ ALL_OBJFILES (obj)
+ if (obj->obfd == first->owner)
+ break;
+ gdb_assert (obj != NULL);
+
+ if (obj->separate_debug_objfile != NULL
+ && obj->separate_debug_objfile->obfd == second->owner)
+ return 1;
+ if (obj->separate_debug_objfile_backlink != NULL
+ && obj->separate_debug_objfile_backlink->obfd == second->owner)
+ return 1;
+
+ return 0;
+}
/* Find which partial symtab contains PC and SECTION. Return 0 if
none. We return the psymtab that contains a symbol whose address
@@ -845,7 +904,7 @@ find_pc_sect_psymbol (struct partial_sym
if (section) /* match on a specific section */
{
fixup_psymbol_section (p, psymtab->objfile);
- if (SYMBOL_BFD_SECTION (p) != section)
+ if (!matching_bfd_sections (SYMBOL_BFD_SECTION (p), section))
continue;
}
best_pc = SYMBOL_VALUE_ADDRESS (p);
@@ -869,7 +928,7 @@ find_pc_sect_psymbol (struct partial_sym
if (section) /* match on a specific section */
{
fixup_psymbol_section (p, psymtab->objfile);
- if (SYMBOL_BFD_SECTION (p) != section)
+ if (!matching_bfd_sections (SYMBOL_BFD_SECTION (p), section))
continue;
}
best_pc = SYMBOL_VALUE_ADDRESS (p);
@@ -1902,7 +1961,7 @@ find_pc_sect_symtab (CORE_ADDR pc, asect
ALL_BLOCK_SYMBOLS (b, iter, sym)
{
fixup_symbol_section (sym, objfile);
- if (section == SYMBOL_BFD_SECTION (sym))
+ if (matching_bfd_sections (SYMBOL_BFD_SECTION (sym), section))
break;
}
if (sym == NULL)
Index: symtab.h
===================================================================
RCS file: /cvs/src/src/gdb/symtab.h,v
retrieving revision 1.97
diff -u -p -r1.97 symtab.h
--- symtab.h 18 Mar 2006 18:40:04 -0000 1.97
+++ symtab.h 6 Oct 2006 17:13:25 -0000
@@ -1316,6 +1316,8 @@ extern char **make_source_files_completi
/* symtab.c */
+int matching_bfd_sections (asection *, asection *);
+
extern struct partial_symtab *find_main_psymtab (void);
extern struct symtab *find_line_symtab (struct symtab *, int, int *, int *);
Index: testsuite/gdb.base/sepdebug.exp
===================================================================
RCS file: /cvs/src/src/gdb/testsuite/gdb.base/sepdebug.exp,v
retrieving revision 1.4
diff -u -p -r1.4 sepdebug.exp
--- testsuite/gdb.base/sepdebug.exp 10 Aug 2006 05:27:20 -0000 1.4
+++ testsuite/gdb.base/sepdebug.exp 6 Oct 2006 17:13:25 -0000
@@ -47,39 +47,6 @@ if { [gdb_compile "${srcdir}/${subdir}/
return -1
}
-# FIXME: this is nasty. We need to check for the stabs debug format.
-# To do this we must run gdb on the unstripped executable, list 'main'
-# (as to have a default source file), use get_debug_format (which does
-# 'info source') and then see if the debug info is stabs. If so, we
-# bail out. We cannot do this any other way because get_debug_format
-# finds out the debug format using gdb itself, and in case of stabs we
-# get an error loading the program if it is already stripped. An
-# alternative would be to find out the debug info from the flags
-# passed to dejagnu when the test is run.
-
-gdb_exit
-gdb_start
-gdb_reinitialize_dir $srcdir/$subdir
-gdb_load ${binfile}
-gdb_test "list main" "" ""
-get_debug_format
-if { [test_debug_format "stabs"] } then {
- # the separate debug info feature doesn't work well in binutils with stabs.
- # It produces a corrupted debug info only file, and gdb chokes on it.
- # It is almost impossible to capture the failing message out of gdb,
- # because it happens inside gdb_load. At that point any error message
- # is intercepted by dejagnu itself, and, because of the error threshold,
- # any faulty test result is changed into an UNRESOLVED.
- # (see dejagnu/lib/framework.exp)
- unsupported "no separate debug info handling with stabs"
- return -1
-} elseif { [test_debug_format "unknown"] } then {
- # gdb doesn't know what the debug format is. We are out of luck here.
- unsupported "unknown debugging format"
- return -1
-}
-gdb_exit
-
# Note: the procedure gdb_gnu_strip_debug will produce an executable called
# ${binfile}, which is just like the executable ($binfile) but without
# the debuginfo. Instead $binfile has a .gnudebuglink section which contains
Index: testsuite/gdb.base/sepsymtab.c
===================================================================
RCS file: testsuite/gdb.base/sepsymtab.c
diff -N testsuite/gdb.base/sepsymtab.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ testsuite/gdb.base/sepsymtab.c 6 Oct 2006 17:13:25 -0000
@@ -0,0 +1,23 @@
+/* Copyright 2006
+ Free Software Foundation, Inc.
+
+ 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 2 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, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+
+int
+main (int argc, char **argv, char **envp)
+{
+ return 0;
+}
Index: testsuite/gdb.base/sepsymtab.exp
===================================================================
RCS file: testsuite/gdb.base/sepsymtab.exp
diff -N testsuite/gdb.base/sepsymtab.exp
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ testsuite/gdb.base/sepsymtab.exp 6 Oct 2006 17:13:25 -0000
@@ -0,0 +1,53 @@
+# Copyright 2006
+# Free Software Foundation, Inc.
+
+# 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 2 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, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+#
+# test running programs
+#
+
+set testfile "sepsymtab"
+set srcfile ${testfile}.c
+set binfile ${objdir}/${subdir}/${testfile}
+
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" \
+ executable {debug}] != "" } {
+ untested sepsymtab.exp
+ return -1
+}
+
+if [gdb_gnu_strip_debug $binfile no-main] {
+ # check that you have a recent version of strip and objcopy installed
+ unsupported "cannot produce separate debug info files"
+ return -1
+}
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+set command "info sym main"
+set command_regex [string_to_regexp $command]
+gdb_test_multiple "$command" "$command" {
+ -re "^${command_regex}\[\r\n\]+main in section \[^\r\n\]+\[\r\n\]+$gdb_prompt \$" {
+ pass "$command"
+ }
+}
Index: testsuite/lib/gdb.exp
===================================================================
RCS file: /cvs/src/src/gdb/testsuite/lib/gdb.exp,v
retrieving revision 1.70
diff -u -p -r1.70 gdb.exp
--- testsuite/lib/gdb.exp 18 Aug 2006 18:34:18 -0000 1.70
+++ testsuite/lib/gdb.exp 6 Oct 2006 17:13:25 -0000
@@ -2276,7 +2276,7 @@ proc gdb_skip_bogus_test { msg } {
# Note: the procedure gdb_gnu_strip_debug will produce an executable called
# ${binfile}.dbglnk, which is just like the executable ($binfile) but without
# the debuginfo. Instead $binfile has a .gnu_debuglink section which contains
-# the name of a idebuginfo only file. This file will be stored in the
+# the name of a debuginfo only file. This file will be stored in the
# gdb.base/.debug subdirectory.
# Functions for separate debug info testing
@@ -2307,8 +2307,45 @@ proc separate_debug_filename { exec } {
return $debug_file
}
-
-proc gdb_gnu_strip_debug { dest } {
+# Create stripped files for DEST, replacing it. If ARGS is passed, it is a
+# list of optional flags. The only currently supported flag is no-main,
+# which removes the symbol entry for main from the separate debug file.
+
+proc gdb_gnu_strip_debug { dest args } {
+
+ # First, make sure that we can do this. This is nasty. We need to
+ # check for the stabs debug format. To do this we must run gdb on
+ # the unstripped executable, list 'main' (as to have a default
+ # source file), use get_debug_format (which does 'info source')
+ # and then see if the debug info is stabs. If so, we bail out. We
+ # cannot do this any other way because get_debug_format finds out
+ # the debug format using gdb itself, and in case of stabs we get
+ # an error loading the program if it is already stripped. An
+ # alternative would be to find out the debug info from the flags
+ # passed to dejagnu when the test is run.
+
+ gdb_exit
+ gdb_start
+ gdb_load ${dest}
+ gdb_test "list main" "" ""
+ get_debug_format
+ if { [test_debug_format "stabs"] } then {
+ # The separate debug info feature doesn't work well in
+ # binutils with stabs. It produces a corrupted debug info
+ # only file, and gdb chokes on it. It is almost impossible to
+ # capture the failing message out of gdb, because it happens
+ # inside gdb_load. At that point any error message is
+ # intercepted by dejagnu itself, and, because of the error
+ # threshold, any faulty test result is changed into an
+ # UNRESOLVED. (see dejagnu/lib/framework.exp)
+ unsupported "no separate debug info handling with stabs"
+ return -1
+ } elseif { [test_debug_format "unknown"] } then {
+ # gdb doesn't know what the debug format is. We are out of luck here.
+ unsupported "unknown debugging format"
+ return -1
+ }
+ gdb_exit
set debug_file [separate_debug_filename $dest]
set strip_to_file_program strip
@@ -2342,6 +2379,22 @@ proc gdb_gnu_strip_debug { dest } {
return 1
}
+ # If no-main is passed, strip the symbol for main from the separate
+ # file. This is to simulate the behavior of elfutils's eu-strip, which
+ # leaves the symtab in the original file only. There's no way to get
+ # objcopy or strip to remove the symbol table without also removing the
+ # debugging sections, so this is as close as we can get.
+ if { [llength $args] == 1 && [lindex $args 0] == "no-main" } {
+ set result [catch "exec $objcopy_program -N main ${debug_file} ${debug_file}-tmp" output]
+ verbose "result is $result"
+ verbose "output is $output"
+ if {$result == 1} {
+ return 1
+ }
+ file delete "${debug_file}"
+ file rename "${debug_file}-tmp" "${debug_file}"
+ }
+
# Link the two previous output files together, adding the .gnu_debuglink
# section to the stripped_file, containing a pointer to the debug_file,
# save the new file in dest.