This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [patch] build-id .debug files load (like .gnu_debuglink)


On Fri, 24 Aug 2007 20:20:28 +0200, Daniel Jacobowitz wrote:
> On Fri, Aug 24, 2007 at 08:04:50PM +0200, Jan Kratochvil wrote:
...
> > This part may be questionable:
> > -  debugfile = find_separate_debug_file (objfile); 
> > +  /* If the file has its own symbol tables it has no separate debug info.  */
> > +  if (objfile->psymtabs == NULL)
> > +    debugfile = find_separate_debug_file (objfile);
...
> > Not sure if `PSYMTABS == NULL' is the right condition.  According to my
> > experiments on GNU/Linux it should be correct.
> 
> In some cases a library will be left with .symtab but not .debug_info;
> sometimes elfutils does this, also sometimes it is done deliberately
> for ld.so / libpthread.so so that the separate debug file is not
> necessary for minimal debugging to work.

You are right about the content of `/lib64/ld-linux-x86-64.so.2'.
Still in such case both `.dynsym' and `.symtab' gets read into MSYMBOLS but
PSYMTABS and SYMTABS are left forever NULL for the main executable (as there is
no .debug_info).

While I would still expect the former patch was right I changed it according to
your advice.  It is definitely the safe way but with a tiny performance hit:

The reason of my check was that build-id (contrary to the debug-link) is always
present there, even for locally built unsplit files.  With the patch attached
below GDB will try to open a separate debug file in /usr/lib/debug/.debug-id/
even for the unsplit files.  This step did not happen with my former patch.


> We should either pass a flag down so that we know we're already
> looking at the separate debug file (more efficient, saves us the
> second search, more work to implement)

Chose this way as the intention of the whole patch is performance.
(Aware OBJF_DEBUG_FILE is not an OBJFILE flag - just an additional
SYMBOL_FILE_ADD_WITH_ADDRS_OR_OFFSETS parameter - but it may get one day useful
for later retrieval from OBJFILE.)


> > +/* Locate NT_GNU_BUILD_ID and return its content.
> > +   Separate debuginfo files have corrupted PHDR but SHDR is correct there.  */
> > +
> > +static struct build_id *
> > +build_id_bfd_shdr_get (bfd *abfd)
> > +{
> > +  struct build_id *retval;
> > +
> > +  if (!bfd_check_format (abfd, bfd_object)
> > +      || bfd_get_flavour (abfd) != bfd_target_elf_flavour
> > +      || elf_tdata (abfd)->build_id == NULL)
> > +    return NULL;
> > +
> > +  retval = xmalloc (sizeof *retval - 1 + elf_tdata (abfd)->build_id_size);
> > +  retval->size = elf_tdata (abfd)->build_id_size;
> > +  memcpy (retval->data, elf_tdata (abfd)->build_id, retval->size);
> > +
> > +  return retval;
> > +}
> 
> This function isn't doing anything with program headers or section
> headers now, maybe it should be renamed (and the comment doesn't need
> to talk about corrupted phdrs in that case).

Not agreed as the PHDR<->SHDR difference is important (there are issues about
it for readelf/eu-readelf - whether PHDR or SHDR should be chosen there).
But changed according to your advice.


> I believe the manual needs an update to mention the new search path.

I see now, sorry, implemented.



Thanks,
Jan
2007-08-25  Jan Kratochvil  <jan.kratochvil@redhat.com>

	* Makefile.in (symfile.o): Update dependencies.
	* objfiles.h (OBJF_DEBUG_FILE): New definition.
	* symfile.c (symbol_file_add_with_addrs_or_offsets): Initialize the
	DEBUGFILE variable.  FIND_SEPARATE_DEBUG_FILE protected against loop by
	setting OBJF_DEBUG_FILE for the first call.
	(struct build_id): New structure.
	(build_id_bfd_get, build_id_verify, build_id_to_debug_filename): New.
	(find_separate_debug_file): New variable BUILD_ID.
	Call BUILD_ID_BFD_GET with BUILD_ID_TO_DEBUG_FILENAME as the first try.

2007-08-25  Jan Kratochvil  <jan.kratochvil@redhat.com>

	* lib/gdb.exp (build_id_debug_filename_get): New function.
	* gdb.base/sepdebug.exp: Reflect the changes in the heading comment.
	Remove the generate DEBUG file for the future testcase runs.
	New testcase for the NT_GNU_BUILD_ID retrieval.
	Move the final testing step to ...
	(test_different_dir): ... a new function.
	New parameter XFAIL to XFAIL all the tests performed.
	New parameter TEST_DIFFERENT_DIR parametrizing the directory.
	New parameter TYPE to PF_PREFIX all the tests performed.

2007-08-25  Jan Kratochvil  <jan.kratochvil@redhat.com>

	* gdb.texinfo (Separate Debug Files): Included a BUILD ID description.
	Enlisted BUILD ID to the debug file searching example.
	Included a BUILD ID `.note.gnu.build-id' section description.
	Updated/added the debug files splitting instructions for OBJCOPY.

--- gdb/Makefile.in	23 Aug 2007 20:33:48 -0000	1.929
+++ gdb/Makefile.in	25 Aug 2007 22:43:21 -0000
@@ -2731,7 +2731,7 @@ symfile.o: symfile.c $(defs_h) $(bfdlink
 	$(gdb_stabs_h) $(gdb_obstack_h) $(completer_h) $(bcache_h) \
 	$(hashtab_h) $(readline_h) $(gdb_assert_h) $(block_h) \
 	$(gdb_string_h) $(gdb_stat_h) $(observer_h) $(exec_h) \
-	$(parser_defs_h) $(varobj_h)
+	$(parser_defs_h) $(varobj_h) $(elf_bfd_h)
 symfile-mem.o: symfile-mem.c $(defs_h) $(symtab_h) $(gdbcore_h) \
 	$(objfiles_h) $(exceptions_h) $(gdbcmd_h) $(target_h) $(value_h) \
 	$(symfile_h) $(observer_h) $(auxv_h) $(elf_common_h)
--- gdb/objfiles.h	23 Aug 2007 18:08:36 -0000	1.46
+++ gdb/objfiles.h	25 Aug 2007 22:43:21 -0000
@@ -448,6 +448,11 @@ struct objfile
 
 #define OBJF_USERLOADED	(1 << 5)	/* User loaded */
 
+/* We should not try to find by build-id the separate debug info file for the
+   same separate debug info file itself.  */
+
+#define OBJF_DEBUG_FILE	(1 << 6)	/* Separate debug file */
+
 /* The object file that the main symbol table was loaded from (e.g. the
    argument to the "symbol-file" or "file" command).  */
 
--- gdb/symfile.c	23 Aug 2007 18:08:39 -0000	1.190
+++ gdb/symfile.c	25 Aug 2007 22:43:21 -0000
@@ -51,6 +51,7 @@
 #include "exec.h"
 #include "parser-defs.h"
 #include "varobj.h"
+#include "elf-bfd.h"
 
 #include <sys/types.h>
 #include <fcntl.h>
@@ -1017,7 +1018,7 @@ symbol_file_add_with_addrs_or_offsets (b
 {
   struct objfile *objfile;
   struct partial_symtab *psymtab;
-  char *debugfile;
+  char *debugfile = NULL;
   struct section_addr_info *orig_addrs = NULL;
   struct cleanup *my_cleanups;
   const char *name = bfd_get_filename (abfd);
@@ -1081,18 +1082,21 @@ symbol_file_add_with_addrs_or_offsets (b
 	}
     }
 
-  debugfile = find_separate_debug_file (objfile);
+  if (!(flags & OBJF_DEBUG_FILE))
+    debugfile = find_separate_debug_file (objfile);
   if (debugfile)
     {
       if (addrs != NULL)
 	{
 	  objfile->separate_debug_objfile
-            = symbol_file_add (debugfile, from_tty, orig_addrs, 0, flags);
+            = symbol_file_add (debugfile, from_tty, orig_addrs, 0,
+			       flags | OBJF_DEBUG_FILE);
 	}
       else
 	{
 	  objfile->separate_debug_objfile
-            = symbol_file_add (debugfile, from_tty, NULL, 0, flags);
+            = symbol_file_add (debugfile, from_tty, NULL, 0,
+			       flags | OBJF_DEBUG_FILE);
 	}
       objfile->separate_debug_objfile->separate_debug_objfile_backlink
         = objfile;
@@ -1223,6 +1227,97 @@ symbol_file_clear (int from_tty)
       printf_unfiltered (_("No symbol file now.\n"));
 }
 
+struct build_id
+  {
+    size_t size;
+    gdb_byte data[1];
+  };
+
+/* Locate NT_GNU_BUILD_ID from ABFD and return its content.  */
+
+static struct build_id *
+build_id_bfd_get (bfd *abfd)
+{
+  struct build_id *retval;
+
+  if (!bfd_check_format (abfd, bfd_object)
+      || bfd_get_flavour (abfd) != bfd_target_elf_flavour
+      || elf_tdata (abfd)->build_id == NULL)
+    return NULL;
+
+  retval = xmalloc (sizeof *retval - 1 + elf_tdata (abfd)->build_id_size);
+  retval->size = elf_tdata (abfd)->build_id_size;
+  memcpy (retval->data, elf_tdata (abfd)->build_id, retval->size);
+
+  return retval;
+}
+
+/* Return if FILENAME has NT_GNU_BUILD_ID matching the CHECK value.  */
+
+static int
+build_id_verify (const char *filename, struct build_id *check)
+{
+  bfd *abfd;
+  struct build_id *found = NULL;
+  int retval = 0;
+
+  /* We expect to be silent on the non-existing files.  */
+  abfd = bfd_openr (filename, gnutarget);
+  if (abfd == NULL)
+    return 0;
+
+  found = build_id_bfd_get (abfd);
+
+  if (found == NULL)
+    warning (_("File \"%s\" has no build-id, file skipped"), filename);
+  else if (found->size != check->size
+           || memcmp (found->data, check->data, found->size) != 0)
+    warning (_("File \"%s\" has a different build-id, file skipped"), filename);
+  else
+    retval = 1;
+
+  if (!bfd_close (abfd))
+    warning (_("cannot close \"%s\": %s"), filename,
+	     bfd_errmsg (bfd_get_error ()));
+  return retval;
+}
+
+static char *
+build_id_to_debug_filename (struct build_id *build_id)
+{
+  char *link, *s, *retval = NULL;
+  gdb_byte *data = build_id->data;
+  size_t size = build_id->size;
+
+  /* DEBUG_FILE_DIRECTORY/.build-id/ab/cdef */
+  link = xmalloc (strlen (debug_file_directory) + (sizeof "/.build-id/" - 1) + 1
+		  + 2 * size + (sizeof ".debug" - 1) + 1);
+  s = link + sprintf (link, "%s/.build-id/", debug_file_directory);
+  if (size > 0)
+    {
+      size--;
+      s += sprintf (s, "%02x", (unsigned) *data++);
+    }
+  if (size > 0)
+    *s++ = '/';
+  while (size-- > 0)
+    s += sprintf (s, "%02x", (unsigned) *data++);
+  strcpy (s, ".debug");
+
+  /* lrealpath() is expensive even for the usually non-existent files.  */
+  if (access (link, F_OK) == 0)
+    retval = lrealpath (link);
+  xfree (link);
+
+  if (retval != NULL && !build_id_verify (retval, build_id))
+    {
+      xfree (retval);
+      retval = NULL;
+    }
+
+  return retval;
+}
+
 static char *
 get_debug_link_info (struct objfile *objfile, unsigned long *crc32_out)
 {
@@ -1300,6 +1395,18 @@ find_separate_debug_file (struct objfile
   bfd_size_type debuglink_size;
   unsigned long crc32;
   int i;
+  struct build_id *build_id;
+
+  build_id = build_id_bfd_get (objfile->obfd);
+  if (build_id != NULL)
+    {
+      char *build_id_name;
+
+      build_id_name = build_id_to_debug_filename (build_id);
+      free (build_id);
+      if (build_id_name != NULL)
+        return build_id_name;
+    }
 
   basename = get_debug_link_info (objfile, &crc32);
 
--- gdb/doc/gdb.texinfo	21 Aug 2007 15:09:59 -0000	1.423
+++ gdb/doc/gdb.texinfo	25 Aug 2007 22:43:31 -0000
@@ -11902,18 +11902,32 @@ than the executable code itself --- some
 information for their executables in separate files, which users can
 install only when they need to debug a problem.
 
-If an executable's debugging information has been extracted to a
-separate file, the executable should contain a @dfn{debug link} giving
-the name of the debugging information file (with no directory
-components), and a checksum of its contents.  (The exact form of a
-debug link is described below.)  If the full name of the directory
-containing the executable is @var{execdir}, and the executable has a
-debug link that specifies the name @var{debugfile}, then @value{GDBN}
-will automatically search for the debugging information file in three
-places:
+There are two identificators how the separate debug file may be found:
 
 @itemize @bullet
 @item
+@dfn{debug link} is present only in the executable if its debug information has
+been split out.  It is not present in the separate debug file.  It provides the
+separate debug file filename, usually as @file{executable.debug}.
+@item
+@dfn{build id} is present in all the files (if the operating system supports
+it).  The executable file and its separate debug file have the same unique
+@dfn{build id} content.
+@end itemize
+
+If the full name of the directory containing the executable is @var{execdir},
+the executable has a debug link that specifies the name @var{debugfile},
+@var{bu} is the first byte (two hexadecimal characters) of the build id
+content, @var{ild-id} are the remaining bytes / hexadecimal characters and
+@var{globaldebugdir} is the global debug file directory then @value{GDBN} will
+automatically search for the debugging information file in four places:
+
+@itemize @bullet
+@item
+a specific file in the subdirectory of the global debug file directory
+according to the @dfn{build id} content (if present), the file tried is
+@file{@var{globaldebugdir}/.debug-id/@var{bu}/@var{ild-id}.debug}.
+@item
 the directory containing the executable file (that is, it will look
 for a file named @file{@var{execdir}/@var{debugfile}},
 @item
@@ -11928,15 +11942,17 @@ executable's full path, and the name fro
 @end itemize
 @noindent
 @value{GDBN} checks under each of these names for a debugging
-information file whose checksum matches that given in the link, and
-reads the debugging information from the first one it finds.
-
-So, for example, if you ask @value{GDBN} to debug @file{/usr/bin/ls},
-which has a link containing the name @file{ls.debug}, and the global
-debug directory is @file{/usr/lib/debug}, then @value{GDBN} will look
-for debug information in @file{/usr/bin/ls.debug},
-@file{/usr/bin/.debug/ls.debug}, and
-@file{/usr/lib/debug/usr/bin/ls.debug}.
+information file with build id content matching the build id content of the
+executable file - or - whose checksum matches the one given in the link in the
+debug link case.  In each case @value{GDBN} reads the debugging information
+from the first debug file it finds.
+
+So, for example, if you ask @value{GDBN} to debug @file{/usr/bin/ls}, which has
+a @dfn{debug link} containing the name @file{ls.debug}, its @dfn{build id}
+value in hexadecimal is @code{abcdef} and the global debug directory is
+@file{/usr/lib/debug}, then @value{GDBN} will look for debug information in
+@file{/usr/lib/debug/.build-id/ab/cdef.debug}, @file{/usr/bin/ls.debug},
+@file{/usr/bin/.debug/ls.debug}, and @file{/usr/lib/debug/usr/bin/ls.debug}.
 
 You can set the global debugging info directory's name, and view the
 name @value{GDBN} is currently using.
@@ -11978,6 +11994,16 @@ Any executable file format can carry a d
 contain a section named @code{.gnu_debuglink} with the contents
 described above.
 
+@cindex @code{.note.gnu.build-id} sections
+@cindex build id
+Build id is a special section of the executable file named
+@code{.note.gnu.build-id}.  The section contains unique identification hash
+derived from the built files - it remains the same across multiple builds of
+the same build tree.  The default algorithm SHA1 produces 160 bits (40
+hexadecimal characters) of the content.  The same section and value is present
+in the original built binary with symbols, in its stripped variant and in the
+separate debug information file.
+
 The debugging information file itself should be an ordinary
 executable, containing a full set of linker symbols, sections, and
 debugging information.  The sections of the debugging information file
@@ -11985,18 +12011,21 @@ should have the same names, addresses an
 but they need not contain any data --- much like a @code{.bss} section
 in an ordinary executable.
 
-As of December 2002, there is no standard GNU utility to produce
-separated executable / debugging information file pairs.  Ulrich
-Drepper's @file{elfutils} package, starting with version 0.53,
-contains a version of the @code{strip} command such that the command
-@kbd{strip foo -f foo.debug} removes the debugging information from
-the executable file @file{foo}, places it in the file
-@file{foo.debug}, and leaves behind a debug link in @file{foo}.
-
-Since there are many different ways to compute CRC's (different
-polynomials, reversals, byte ordering, etc.), the simplest way to
-describe the CRC used in @code{.gnu_debuglink} sections is to give the
-complete code for a function that computes it:
+@sc{gnu} binary utilities contain the @samp{objcopy} utility able to produce
+the separated executable / debugging information file pairs by commands
+@kbd{objcopy --only-keep-debug foo foo.debug; strip -g foo; objcopy
+--add-gnu-debuglink="foo.debug" "foo"}.  These commands remove the debugging
+information from the executable file @file{foo}, place it in the file
+@file{foo.debug}, and leave behind a debug link in @file{foo}.  Ulrich
+Drepper's @file{elfutils} package, starting with version 0.53, contains
+a version of the @code{strip} command such that the command @kbd{strip foo -f
+foo.debug} has the same functionality as the three commands above.
+
+Since there are many different ways to compute CRC's for the debug link
+(different polynomials, reversals, byte ordering, etc.).  This computation does
+not apply to the build id section.  The simplest way to describe the CRC used
+in @code{.gnu_debuglink} sections is to give the complete code for a function
+that computes it:
 
 @kindex gnu_debuglink_crc32
 @smallexample
--- gdb/testsuite/gdb.base/sepdebug.exp	23 Aug 2007 18:14:17 -0000	1.8
+++ gdb/testsuite/gdb.base/sepdebug.exp	25 Aug 2007 22:43:31 -0000
@@ -19,11 +19,14 @@
 
 # Based on break.exp, written by Rob Savoye. (rob@cygnus.com)
 # Modified to test gdb's handling of separate debug info files.
+# Modified to test gdb's handling of a debug-id retrieval.
 
 # This file has two parts. The first is testing that gdb behaves
 # normally after reading in an executable and its corresponding
 # separate debug file. The second moves the .debug file to a different
 # location and tests the "set debug-file-directory" command.
+# The third is for testing build-id retrievel by finding the separate
+# ".debug-id/ab/cdef.debug" file.
 
 
 if $tracelevel then {
@@ -828,93 +831,152 @@ test_next_with_recursion
 
 #********
 
-# now move the .debug file to a different location so that we can test
-# the "set debug-file-directory" command.
-  
-remote_exec build "mv ${objdir}/${subdir}/.debug/${testfile}.debug ${objdir}/${subdir}"
-gdb_exit
-gdb_start
-gdb_reinitialize_dir $srcdir/$subdir
-gdb_test "set debug-file-directory ${objdir}/${subdir}" ".*" "set separate debug location"
-gdb_load ${binfile}
+proc test_different_dir {type test_different_dir xfail} {
+    global srcdir subdir objdir binfile srcfile timeout gdb_prompt
+    global pf_prefix
+    global bp_location6 decimal hex
+
+    set pf_prefix "$type:"
+
+    gdb_exit
+    gdb_start
+    gdb_reinitialize_dir $srcdir/$subdir
+    gdb_test "set debug-file-directory ${test_different_dir}" ".*" "set separate debug location"
+    gdb_load ${binfile}
 
-if [target_info exists gdb_stub] {
-    gdb_step_for_stub;
-}
+    if [target_info exists gdb_stub] {
+	gdb_step_for_stub;
+    }
 
-#
-# test break at function
-#
-gdb_test "break main" \
-    "Breakpoint.*at.* file .*$srcfile, line.*" \
-    "breakpoint function, optimized file"
+    #
+    # test break at function
+    #
+    if {$xfail} {
+	setup_xfail "*-*-*"
+    }
+    gdb_test "break main" \
+	"Breakpoint.*at.* file .*$srcfile, line.*" \
+	"breakpoint function, optimized file"
 
-#
-# test break at function
-#
-gdb_test "break marker4" \
-    "Breakpoint.*at.* file .*$srcfile, line.*" \
-    "breakpoint small function, optimized file"
+    #
+    # test break at function
+    #
+    if {$xfail} {
+	setup_xfail "*-*-*"
+    }
+    gdb_test "break marker4" \
+	"Breakpoint.*at.* file .*$srcfile, line.*" \
+	"breakpoint small function, optimized file"
 
-#
-# run until the breakpoint at main is hit. For non-stubs-using targets.
-#
-gdb_run_cmd
-gdb_expect {
-    -re "Breakpoint \[0-9\]+,.*main .*argc.*argv.* at .*$srcfile:$bp_location6.*$bp_location6\[\t \]+if .argc.* \{.*$gdb_prompt $" {
-	pass "run until function breakpoint, optimized file"
+    #
+    # run until the breakpoint at main is hit. For non-stubs-using targets.
+    #
+    gdb_run_cmd
+    if {$xfail} {
+	setup_xfail "*-*-*"
     }
-    -re "Breakpoint \[0-9\]+,.*main .*argc.*argv.* at .*$gdb_prompt $" {
-	pass "run until function breakpoint, optimized file (code motion)"
+    gdb_expect {
+	-re "Breakpoint \[0-9\]+,.*main .*argc.*argv.* at .*$srcfile:$bp_location6.*$bp_location6\[\t \]+if .argc.* \{.*$gdb_prompt $" {
+	    pass "run until function breakpoint, optimized file"
+	}
+	-re "Breakpoint \[0-9\]+,.*main .*argc.*argv.* at .*$gdb_prompt $" {
+	    pass "run until function breakpoint, optimized file (code motion)"
+	}
+	-re "$gdb_prompt $" {
+	    fail "run until function breakpoint, optimized file"
+	}
+	timeout {
+	    fail "run until function breakpoint, optimized file (timeout)"
+	}
     }
-    -re "$gdb_prompt $" {
-	fail "run until function breakpoint, optimized file"
+
+    #
+    # run until the breakpoint at a small function
+    #
+
+    #
+    # Add a second pass pattern.  The behavior differs here between stabs
+    # and dwarf for one-line functions.  Stabs preserves two line symbols
+    # (one before the prologue and one after) with the same line number, 
+    # but dwarf regards these as duplicates and discards one of them.
+    # Therefore the address after the prologue (where the breakpoint is)
+    # has no exactly matching line symbol, and GDB reports the breakpoint
+    # as if it were in the middle of a line rather than at the beginning.
+
+    set bp_location13 [gdb_get_line_number "set breakpoint 13 here"]
+    set bp_location14 [gdb_get_line_number "set breakpoint 14 here"]
+    send_gdb "continue\n"
+    if {$xfail} {
+	setup_xfail "*-*-*"
     }
-    timeout {
-	fail "run until function breakpoint, optimized file (timeout)"
+    gdb_expect {
+	-re "Breakpoint $decimal, marker4 \\(d=177601976\\) at .*$srcfile:$bp_location13\[\r\n\]+$bp_location13\[\t \]+void marker4.*" {
+	    pass "run until breakpoint set at small function, optimized file"
+	}
+	-re "Breakpoint $decimal, $hex in marker4 \\(d=177601976\\) at .*$srcfile:$bp_location13\[\r\n\]+$bp_location13\[\t \]+void marker4.*" {
+	    pass "run until breakpoint set at small function, optimized file"
+	}
+	-re "Breakpoint $decimal, marker4 \\(d=177601976\\) at .*$srcfile:$bp_location14\[\r\n\]+$bp_location14\[\t \]+void marker4.*" {
+	    # marker4() is defined at line 46 when compiled with -DPROTOTYPES
+	    pass "run until breakpoint set at small function, optimized file (line bp_location14)"
+	}
+	-re ".*$gdb_prompt " {
+	    fail "run until breakpoint set at small function, optimized file"
+	}
+	timeout {
+	    fail "run until breakpoint set at small function, optimized file (timeout)"
+	}
+    }
+
+
+    # Reset the default arguments for VxWorks
+    if [istarget "*-*-vxworks*"] {
+	set timeout 10
+	verbose "Timeout is now $timeout seconds" 2
+	send_gdb "set args main\n"
+	gdb_expect -re ".*$gdb_prompt $" {}
     }
+
+    unset pf_prefix
+# proc test_different_dir
 }
 
-#
-# run until the breakpoint at a small function
-#
 
-#
-# Add a second pass pattern.  The behavior differs here between stabs
-# and dwarf for one-line functions.  Stabs preserves two line symbols
-# (one before the prologue and one after) with the same line number, 
-# but dwarf regards these as duplicates and discards one of them.
-# Therefore the address after the prologue (where the breakpoint is)
-# has no exactly matching line symbol, and GDB reports the breakpoint
-# as if it were in the middle of a line rather than at the beginning.
+# now move the .debug file to a different location so that we can test
+# the "set debug-file-directory" command.
+  
+remote_exec build "mv ${objdir}/${subdir}/.debug/${testfile}.debug ${objdir}/${subdir}"
+set debugfile "${objdir}/${subdir}/${testfile}.debug"
 
-set bp_location13 [gdb_get_line_number "set breakpoint 13 here"]
-set bp_location14 [gdb_get_line_number "set breakpoint 14 here"]
-send_gdb "continue\n"
-gdb_expect {
-    -re "Breakpoint $decimal, marker4 \\(d=177601976\\) at .*$srcfile:$bp_location13\[\r\n\]+$bp_location13\[\t \]+void marker4.*" {
-	pass "run until breakpoint set at small function, optimized file"
-    }
-    -re "Breakpoint $decimal, $hex in marker4 \\(d=177601976\\) at .*$srcfile:$bp_location13\[\r\n\]+$bp_location13\[\t \]+void marker4.*" {
-	pass "run until breakpoint set at small function, optimized file"
-    }
-    -re "Breakpoint $decimal, marker4 \\(d=177601976\\) at .*$srcfile:$bp_location14\[\r\n\]+$bp_location14\[\t \]+void marker4.*" {
-        # marker4() is defined at line 46 when compiled with -DPROTOTYPES
-	pass "run until breakpoint set at small function, optimized file (line bp_location14)"
-    }
-    -re ".*$gdb_prompt " {
-	fail "run until breakpoint set at small function, optimized file"
-    }
-    timeout {
-	fail "run until breakpoint set at small function, optimized file (timeout)"
+test_different_dir debuglink "${objdir}/${subdir}" 0
+
+
+# NT_GNU_BUILD_ID / .note.gnu.build-id test:
+
+set build_id_debug_filename [build_id_debug_filename_get $binfile]
+if {$build_id_debug_filename eq ""} {
+    unsupported "build-id is not supported by the compiler"
+
+    # Spare debug files may confuse testsuite runs in the future.
+    remote_exec build "rm -f $debugfile"
+} else {
+    set build_id_debugself_filename [build_id_debug_filename_get $debugfile]
+    set test "build-id support by binutils"
+    set xfail 0
+    if {$build_id_debugself_filename eq ""} {
+	unsupported $test
+	set xfail 1
+    } elseif {$build_id_debugself_filename ne $build_id_debug_filename} {
+	fail $test
+    } else {
+	pass $test
     }
-}
 
+    file mkdir [file dirname ${objdir}/${subdir}/${build_id_debug_filename}]
+    remote_exec build "mv $debugfile ${objdir}/${subdir}/${build_id_debug_filename}"
+
+    test_different_dir build-id "${objdir}/${subdir}" $xfail
 
-# Reset the default arguments for VxWorks
-if [istarget "*-*-vxworks*"] {
-    set timeout 10
-    verbose "Timeout is now $timeout seconds" 2
-    send_gdb "set args main\n"
-    gdb_expect -re ".*$gdb_prompt $" {}
+    # Spare debug files may confuse testsuite runs in the future.
+    remote_exec build "rm -f ${objdir}/${subdir}/${build_id_debug_filename}"
 }
--- gdb/testsuite/lib/gdb.exp	23 Aug 2007 20:10:04 -0000	1.86
+++ gdb/testsuite/lib/gdb.exp	25 Aug 2007 22:43:32 -0000
@@ -2482,6 +2482,27 @@ proc separate_debug_filename { exec } {
     return $debug_file
 }
 
+# Return the build-id hex string (usually 160 bits as 40 hex characters)
+# converted to the form: .build-id/ab/cdef1234...89.debug
+# Return "" if no build-id found.
+proc build_id_debug_filename_get { exec } {
+    set tmp "${exec}-tmp"
+    exec objcopy -j .note.gnu.build-id -O binary $exec $tmp
+    set fi [open $tmp]
+    # Skip the NOTE header.
+    read $fi 16
+    set data [read $fi]
+    close $fi
+    file delete $tmp
+    if {$data eq ""} {
+	return ""
+    }
+    # Convert it to hex.
+    binary scan $data H* data
+    set data [regsub {^..} $data {\0/}]
+    return ".build-id/${data}.debug";
+}
+
 # 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.

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]