This is the mail archive of the binutils-cvs@sourceware.org mailing list for the binutils 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]

[binutils-gdb] Add support for locating separate debug info files via the build-id method.


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=2425a30e406a0523020b7e70abb864a06a45bb97

commit 2425a30e406a0523020b7e70abb864a06a45bb97
Author: Nick Clifton <nickc@redhat.com>
Date:   Thu Jan 12 16:56:54 2017 +0000

    Add support for locating separate debug info files via the build-id method.
    
    	PR binutils/20876
    bfd	* opncls.c (find_separate_debug_file): Add include_dirs
    	parameter.  Only include the directory part of the bfd's filename
    	in search paths if include_dirs is true.  Add a couple of extra
    	locations for looking for debug files.
    	( bfd_follow_gnu_debuglink): Update invocation of
    	find_separate_debug_file.
    	(bfd_follow_gnu_debugaltlink): Likewise.
    	(get_build_id): New function: Finds the build-id of the given bfd.
    	(get_build_id_name): New function: Computes the name of the
    	separate debug info file for a bfd, based upon its build-id.
    	(check_build_id_file): New function: Checks to see if a separate
    	debug info file exists at the given location, and that its
    	build-id matches that of the original bfd.
    	(bfd_follow_build_id_debuglink): New function: Finds a separate
    	debug info file for a given bfd by using the build-id method.
    	* dwarf2.c (_bfd_dwarf2_slurp_debug_info): Try using the build-id
    	method of locating a separate debug info file before using the
    	debuglink method.
    	* bfd-in2.h: Regenerate.
    
    binutils * NEWS: Mention the new feature.
    	* testsuite/binutils-all/objdump.exp (test_build_id_debuglink):
    	New proc to test the location of separate debug info files using
    	the build-id method.

Diff:
---
 bfd/ChangeLog                               |  23 ++
 bfd/bfd-in2.h                               |   2 +
 bfd/dwarf2.c                                |   6 +-
 bfd/opncls.c                                | 373 +++++++++++++++++++++++++---
 binutils/ChangeLog                          |   8 +
 binutils/NEWS                               |   4 +
 binutils/testsuite/binutils-all/objdump.exp |  80 ++++++
 7 files changed, 456 insertions(+), 40 deletions(-)

diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 252e57b..6705ae4 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,3 +1,26 @@
+2017-01-12  Nick Clifton  <nickc@redhat.com>
+
+	PR binutils/20876
+	* opncls.c (find_separate_debug_file): Add include_dirs
+	parameter.  Only include the directory part of the bfd's filename
+	in search paths if include_dirs is true.  Add a couple of extra
+	locations for looking for debug files.
+	( bfd_follow_gnu_debuglink): Update invocation of
+	find_separate_debug_file.
+	(bfd_follow_gnu_debugaltlink): Likewise.
+	(get_build_id): New function: Finds the build-id of the given bfd.
+	(get_build_id_name): New function: Computes the name of the
+	separate debug info file for a bfd, based upon its build-id.
+	(check_build_id_file): New function: Checks to see if a separate
+	debug info file exists at the given location, and that its
+	build-id matches that of the original bfd.
+	(bfd_follow_build_id_debuglink): New function: Finds a separate
+	debug info file for a given bfd by using the build-id method.
+	* dwarf2.c (_bfd_dwarf2_slurp_debug_info): Try using the build-id
+	method of locating a separate debug info file before using the
+	debuglink method.
+	* bfd-in2.h: Regenerate.
+
 2017-01-11  H.J. Lu  <hongjiu.lu@intel.com>
 
 	PR ld/21038
diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h
index 2930089..80d60cb 100644
--- a/bfd/bfd-in2.h
+++ b/bfd/bfd-in2.h
@@ -1121,6 +1121,8 @@ struct bfd_section *bfd_create_gnu_debuglink_section
 bfd_boolean bfd_fill_in_gnu_debuglink_section
    (bfd *abfd, struct bfd_section *sect, const char *filename);
 
+char *bfd_follow_build_id_debuglink (bfd *abfd, const char *dir);
+
 /* Extracted from libbfd.c.  */
 
 /* Byte swapping macros for user section data.  */
diff --git a/bfd/dwarf2.c b/bfd/dwarf2.c
index 40edd91..3699587 100644
--- a/bfd/dwarf2.c
+++ b/bfd/dwarf2.c
@@ -3921,7 +3921,11 @@ _bfd_dwarf2_slurp_debug_info (bfd *abfd, bfd *debug_bfd,
   msec = find_debug_info (debug_bfd, debug_sections, NULL);
   if (msec == NULL && abfd == debug_bfd)
     {
-      char * debug_filename = bfd_follow_gnu_debuglink (abfd, DEBUGDIR);
+      char * debug_filename;
+
+      debug_filename = bfd_follow_build_id_debuglink (abfd, DEBUGDIR);
+      if (debug_filename == NULL)
+	debug_filename = bfd_follow_gnu_debuglink (abfd, DEBUGDIR);
 
       if (debug_filename == NULL)
 	/* No dwarf2 info, and no gnu_debuglink to follow.
diff --git a/bfd/opncls.c b/bfd/opncls.c
index 10684d2..b4d4dcf 100644
--- a/bfd/opncls.c
+++ b/bfd/opncls.c
@@ -25,6 +25,7 @@
 #include "objalloc.h"
 #include "libbfd.h"
 #include "libiberty.h"
+#include "elf-bfd.h"
 
 #ifndef S_IXUSR
 #define S_IXUSR 0100	/* Execute by owner.  */
@@ -1305,7 +1306,7 @@ INTERNAL_FUNCTION
 
 SYNOPSIS
 	bfd_boolean separate_alt_debug_file_exists
-	  (char *name, unsigned long crc32);
+	  (char *name, unsigned long buildid);
 
 DESCRIPTION
 	Checks to see if @var{name} is a file and if its BuildID
@@ -1336,17 +1337,21 @@ INTERNAL_FUNCTION
 	find_separate_debug_file
 
 SYNOPSIS
-	char *find_separate_debug_file (bfd *abfd);
+	char *find_separate_debug_file
+	  (bfd *abfd, const char *dir, bfd_boolean include_dirs,
+	   get_func_type get, check_func_type check);
 
 DESCRIPTION
-	Searches @var{abfd} for a section called @var{section_name} which
-	is expected to contain a reference to a file containing separate
-	debugging information.  The function scans various locations in
-	the filesystem, including the file tree rooted at
-	@var{debug_file_directory}, and returns the first matching
-	filename that it finds.  If @var{check_crc} is TRUE then the
-	contents of the file must also match the CRC value contained in
-	@var{section_name}.  Returns NULL if no valid file could be found.
+	Searches for a debug information file corresponding to @var{abfd}.
+	The name of the separate debug info file is returned by the @var{get}
+	function.  This function scans various fixed locations in the
+	filesystem, including the file tree rooted at @var{dir}.  If the
+	@var{include_dirs} parameter is true then the directory components of
+	@var{abfd}'s filename will be included in the searched locations.
+
+	Returns the filename of the first file to be found which receives a
+	TRUE result from the @var{check} function.  Returns NULL if no valid
+	file could be found.
 */
 
 typedef char *      (* get_func_type) (bfd *, unsigned long *);
@@ -1355,6 +1360,7 @@ typedef bfd_boolean (* check_func_type) (const char *, const unsigned long);
 static char *
 find_separate_debug_file (bfd *           abfd,
 			  const char *    debug_file_directory,
+			  bfd_boolean     include_dirs,
 			  get_func_type   get_func,
 			  check_func_type check_func)
 {
@@ -1389,18 +1395,27 @@ find_separate_debug_file (bfd *           abfd,
       return NULL;
     }
 
-  for (dirlen = strlen (abfd->filename); dirlen > 0; dirlen--)
-    if (IS_DIR_SEPARATOR (abfd->filename[dirlen - 1]))
-      break;
+  if (include_dirs)
+    {
+      for (dirlen = strlen (abfd->filename); dirlen > 0; dirlen--)
+	if (IS_DIR_SEPARATOR (abfd->filename[dirlen - 1]))
+	  break;
 
-  dir = (char *) bfd_malloc (dirlen + 1);
-  if (dir == NULL)
+      dir = (char *) bfd_malloc (dirlen + 1);
+      if (dir == NULL)
+	{
+	  free (base);
+	  return NULL;
+	}
+      memcpy (dir, abfd->filename, dirlen);
+      dir[dirlen] = '\0';
+    }
+  else
     {
-      free (base);
-      return NULL;
+      dir = (char *) bfd_malloc (1);
+      * dir = 0;
+      dirlen = 0;
     }
-  memcpy (dir, abfd->filename, dirlen);
-  dir[dirlen] = '\0';
 
   /* Compute the canonical name of the bfd object with all symbolic links
      resolved, for use in the global debugfile directory.  */
@@ -1410,38 +1425,78 @@ find_separate_debug_file (bfd *           abfd,
       break;
   canon_dir[canon_dirlen] = '\0';
 
+#ifndef EXTRA_DEBUG_ROOT1
+#define EXTRA_DEBUG_ROOT1 "/usr/lib/debug"
+#endif
+#ifndef EXTRA_DEBUG_ROOT2
+#define EXTRA_DEBUG_ROOT2 "/usr/lib/debug/usr"
+#endif  
+
   debugfile = (char *)
       bfd_malloc (strlen (debug_file_directory) + 1
                   + (canon_dirlen > dirlen ? canon_dirlen : dirlen)
                   + strlen (".debug/")
+#ifdef EXTRA_DEBUG_ROOT1
+		  + strlen (EXTRA_DEBUG_ROOT1)
+#endif
+#ifdef EXTRA_DEBUG_ROOT2
+		  + strlen (EXTRA_DEBUG_ROOT2)
+#endif
                   + strlen (base)
                   + 1);
   if (debugfile == NULL)
     goto found; /* Actually this returns NULL.  */
 
-  /* First try in the same directory as the original file:  */
-  strcpy (debugfile, dir);
-  strcat (debugfile, base);
+  /* First try in the same directory as the original file.
 
+     FIXME: Strictly speaking if we are using the build-id method,
+     (ie include_dirs == FALSE) then we should only check absolute
+     paths, not relative ones like this one (and the next one).
+     The check is left in however as this allows the binutils
+     testsuite to exercise this feature without having to install
+     a file into the root filesystem.  (See binutils/testsuite/
+     binutils-all/objdump.exp for the test).  */
+  sprintf (debugfile, "%s%s", dir, base);
   if (check_func (debugfile, crc32))
     goto found;
 
   /* Then try in a subdirectory called .debug.  */
-  strcpy (debugfile, dir);
-  strcat (debugfile, ".debug/");
-  strcat (debugfile, base);
+  sprintf (debugfile, "%s.debug/%s", dir, base);
+  if (check_func (debugfile, crc32))
+    goto found;
 
+#ifdef EXTRA_DEBUG_ROOT1
+  /* Try the first extra debug file root.  */
+  sprintf (debugfile, "%s%s%s", EXTRA_DEBUG_ROOT1,
+	   include_dirs ? canon_dir : "/", base);
   if (check_func (debugfile, crc32))
     goto found;
+#endif
 
+#ifdef EXTRA_DEBUG_ROOT2
+  /* Try the second extra debug file root.  */
+  sprintf (debugfile, "%s%s%s", EXTRA_DEBUG_ROOT2,
+	   include_dirs ? canon_dir : "/", base);
+  if (check_func (debugfile, crc32))
+    goto found;
+#endif
+  
   /* Then try in the global debugfile directory.  */
   strcpy (debugfile, debug_file_directory);
   dirlen = strlen (debug_file_directory) - 1;
-  if (dirlen > 0
-      && debug_file_directory[dirlen] != '/'
-      && canon_dir[0] != '/')
-    strcat (debugfile, "/");
-  strcat (debugfile, canon_dir);
+  if (include_dirs)
+    {
+      if (dirlen > 0
+	  && debug_file_directory[dirlen] != '/'
+	  && canon_dir[0] != '/')
+	strcat (debugfile, "/");
+      strcat (debugfile, canon_dir);
+    }
+  else
+    {
+      if (dirlen > 0 && debug_file_directory[dirlen] != '/')
+	strcat (debugfile, "/");
+    }
   strcat (debugfile, base);
 
   if (check_func (debugfile, crc32))
@@ -1475,9 +1530,8 @@ DESCRIPTION
 	locations, including the directory tree rooted at @var{dir}, and if
 	found returns the full filename.
 
-	If @var{dir} is NULL, it will search a default path configured into
-	libbfd at build time.  [XXX this feature is not currently
-	implemented].
+	If @var{dir} is NULL, the search will take place starting at
+	the current directory.
 
 RETURNS
 	<<NULL>> on any errors or failure to locate the .debug file,
@@ -1488,7 +1542,7 @@ RETURNS
 char *
 bfd_follow_gnu_debuglink (bfd *abfd, const char *dir)
 {
-  return find_separate_debug_file (abfd, dir,
+  return find_separate_debug_file (abfd, dir, TRUE,
 				   bfd_get_debug_link_info,
 				   separate_debug_file_exists);
 }
@@ -1522,14 +1576,13 @@ DESCRIPTION
 
 	Takes a BFD and searches it for a .gnu_debugaltlink section.  If this
 	section is found, it examines the section for the name of a file
-	containing auxiliary debugging information.  It	then searches the
+	containing auxiliary debugging information.  It then searches the
 	filesystem for this file in a set of standard locations, including
 	the directory tree rooted at @var{dir}, and if found returns the
 	full filename.
 
-	If @var{dir} is NULL, it will search a default path configured into
-	libbfd at build time.  [FIXME: This feature is not currently
-	implemented].
+	If @var{dir} is NULL, the search will take place starting at
+	the current directory.
 
 RETURNS
 	<<NULL>> on any errors or failure to locate the debug file,
@@ -1540,7 +1593,7 @@ RETURNS
 char *
 bfd_follow_gnu_debugaltlink (bfd *abfd, const char *dir)
 {
-  return find_separate_debug_file (abfd, dir,
+  return find_separate_debug_file (abfd, dir, TRUE,
 				   get_alt_debug_link_info_shim,
 				   separate_alt_debug_file_exists);
 }
@@ -1695,3 +1748,245 @@ bfd_fill_in_gnu_debuglink_section (bfd *abfd,
 
   return TRUE;
 }
+
+/*
+INTERNAL_FUNCTION
+	get_build_id
+
+SYNOPSIS
+	struct bfd_build_id * get_build_id
+	  (bfd *abfd);
+
+DESCRIPTION
+	Finds the build-id associated with @var{abfd}.  If the build-id is
+	extracted from the note section then a build-id structure is built
+	for it, using memory allocated to @var{abfd}, and this is then
+	attached to the @var{abfd}.
+
+	Returns a pointer to the build-id structure if a build-id could be
+	found.  If no build-id is found NULL is returned and error code is
+	set.
+*/
+
+static struct bfd_build_id *
+get_build_id (bfd *abfd)
+{
+  struct bfd_build_id *build_id;
+  Elf_Internal_Note inote;
+  Elf_External_Note *enote;
+  bfd_byte *contents;
+  asection *sect;
+
+  BFD_ASSERT (abfd);
+
+  if (abfd->build_id && abfd->build_id->size > 0)
+    /* Save some time by using the already computed build-id.  */
+    return (struct bfd_build_id *) abfd->build_id;
+
+  sect = bfd_get_section_by_name (abfd, ".note.gnu.build-id");
+  if (sect == NULL)
+    {
+      bfd_set_error (bfd_error_no_debug_section);
+      return NULL;
+    }
+
+  /* FIXME: Should we support smaller build-id notes ?  */
+  if (bfd_get_section_size (sect) < 0x24)
+    {
+      bfd_set_error (bfd_error_invalid_operation);
+      return NULL;
+    }
+
+  if (!bfd_malloc_and_get_section (abfd, sect, & contents))
+    {
+      if (contents != NULL)
+	free (contents);
+      return NULL;
+    }
+
+  enote = (Elf_External_Note *) contents;
+  inote.type = H_GET_32 (abfd, enote->type);
+  inote.namesz = H_GET_32 (abfd, enote->namesz);
+  inote.namedata = enote->name;
+  inote.descsz = H_GET_32 (abfd, enote->descsz);
+  inote.descdata = inote.namedata + BFD_ALIGN (inote.namesz, 4);
+  /* FIXME: Should we check for extra notes in this section ?  */
+	  
+  if (inote.descsz == 0
+      || inote.type != NT_GNU_BUILD_ID
+      || inote.namesz != 4 /* sizeof "GNU"  */
+      || strcmp (inote.namedata, "GNU") != 0)
+    {
+      free (contents);
+      bfd_set_error (bfd_error_invalid_operation);
+      return NULL;
+    }
+
+  build_id = bfd_alloc (abfd, sizeof (struct bfd_build_id) + inote.descsz);
+  if (build_id == NULL)
+    {
+      free (contents);
+      return NULL;
+    }
+
+  build_id->size = inote.descsz;
+  memcpy (build_id->data, inote.descdata, inote.descsz);
+  abfd->build_id = build_id;
+  free (contents);
+
+  return build_id;
+}
+
+/*
+INTERNAL_FUNCTION
+	get_build_id_name
+
+SYNOPSIS
+	char * get_build_id_name
+	  (bfd *abfd, unsigned long *build_id_out)
+
+DESCRIPTION
+	Searches @var{abfd} for a build-id, and then constructs a pathname
+	from it.  The path is computed as .build-id/NN/NN+NN.debug where
+	NNNN+NN is the build-id value as a hexadecimal string.
+
+	Returns the constructed filename or NULL upon error.
+	It is the caller's responsibility to free the memory used to hold the
+	filename.
+	If a filename is returned then the @var{build_id_out} parameter is
+	set to a pointer to the build_id structure.
+*/
+
+static char *
+get_build_id_name (bfd *abfd, unsigned long *build_id_out)
+{
+  struct bfd_build_id *build_id;
+  char *name;
+  char *n;
+  bfd_size_type s;
+  bfd_byte *d;
+
+  if (abfd == NULL || abfd->filename == NULL || build_id_out == NULL)
+    {
+      bfd_set_error (bfd_error_invalid_operation);
+      return NULL;
+    }
+
+  build_id = get_build_id (abfd);
+  if (build_id == NULL)
+    return NULL;
+
+  /* Compute the debug pathname corresponding to the build-id.  */
+  name = bfd_malloc (strlen (".build-id/") + build_id->size * 2 + 2 + strlen (".debug"));
+  if (name == NULL)
+    {
+      bfd_set_error (bfd_error_no_memory);
+      return NULL;
+    }
+  n = name;
+  d = build_id->data;
+  s = build_id->size;
+
+  n += sprintf (n, ".build-id/");
+  n += sprintf (n, "%02x", (unsigned) *d++); s--;
+  n += sprintf (n, "/");
+  while (s--)
+    n += sprintf (n, "%02x", (unsigned) *d++);
+  n += sprintf (n, ".debug");
+
+  * build_id_out = (unsigned long) build_id;
+  return name;
+}
+
+/*
+INTERNAL_FUNCTION
+	check_build_id_file
+
+SYNOPSIS
+	bfd_boolean check_build_id_file
+	  (char *name, unsigned long buildid);
+
+DESCRIPTION
+	Checks to see if @var{name} is a readable file and if its build-id
+	matches @var{buildid}.
+
+	Returns TRUE if the file exists, is readable, and contains a build-id
+	which matches @var{build-id}.
+*/
+
+static bfd_boolean
+check_build_id_file (const char *name,
+		     const unsigned long buildid)
+{
+  struct bfd_build_id *orig_build_id;
+  struct bfd_build_id *build_id;
+  bfd * file;
+  bfd_boolean result;
+
+  BFD_ASSERT (name);
+  BFD_ASSERT (buildid);
+
+  file = bfd_openr (name, NULL);
+  if (file == NULL)
+    return FALSE;
+
+  /* If the file is an archive, process all of its elements.  */
+  if (! bfd_check_format (file, bfd_object))
+    {
+      bfd_close (file);
+      return FALSE;
+    }
+  
+  build_id = get_build_id (file);
+  if (build_id == NULL)
+    {
+      bfd_close (file);
+      return FALSE;
+    }
+
+  orig_build_id = (struct bfd_build_id *) buildid;
+
+  result = build_id->size == orig_build_id->size
+    && memcmp (build_id->data, orig_build_id->data, build_id->size) == 0;
+
+  (void) bfd_close (file);
+
+  return result;
+}
+
+/*
+FUNCTION
+	bfd_follow_build_id_debuglink
+
+SYNOPSIS
+	char *bfd_follow_build_id_debuglink (bfd *abfd, const char *dir);
+
+DESCRIPTION
+
+	Takes @var{abfd} and searches it for a .note.gnu.build-id section.
+	If this section is found, it extracts the value of the NT_GNU_BUILD_ID
+	note, which should be a hexadecimal value @var{NNNN+NN} (for
+	32+ hex digits).  It then searches the filesystem for a file named
+	@var{.build-id/NN/NN+NN.debug} in a set of standard locations,
+	including the directory tree rooted at @var{dir}.  The filename
+	of the first matching file to be found is returned.  A matching
+	file should contain a .note.gnu.build-id section with the same
+	@var{NNNN+NN} note as @var{abfd}, although this check is currently
+	not implemented.
+
+	If @var{dir} is NULL, the search will take place starting at
+	the current directory.
+
+RETURNS
+	<<NULL>> on any errors or failure to locate the debug file,
+	otherwise a pointer to a heap-allocated string containing the
+	filename.  The caller is responsible for freeing this string.
+*/
+
+char *
+bfd_follow_build_id_debuglink (bfd *abfd, const char *dir)
+{
+  return find_separate_debug_file (abfd, dir, FALSE,
+				   get_build_id_name,
+				   check_build_id_file);
+}
diff --git a/binutils/ChangeLog b/binutils/ChangeLog
index 38d033e..16e9c60 100644
--- a/binutils/ChangeLog
+++ b/binutils/ChangeLog
@@ -1,3 +1,11 @@
+2017-01-12  Nick Clifton  <nickc@redhat.com>
+
+	PR binutils/20876
+	* NEWS: Mention the new feature.
+	* testsuite/binutils-all/objdump.exp (test_build_id_debuglink):
+	New proc to test the location of separate debug info files using
+	the build-id method.
+
 2017-01-10  Nick Clifton  <nickc@redhat.com>
 
 	PR 21034
diff --git a/binutils/NEWS b/binutils/NEWS
index 00675f7..b425901 100644
--- a/binutils/NEWS
+++ b/binutils/NEWS
@@ -1,5 +1,9 @@
 -*- text -*-
 
+* Add support for locating separate debug info files using the build-id
+  method, where the separate file has a name based upon the build-id of
+  the original file.
+
 Changes in 2.28:
 
 * This version of binutils fixes a problem with PowerPC VLE 16A and 16D
diff --git a/binutils/testsuite/binutils-all/objdump.exp b/binutils/testsuite/binutils-all/objdump.exp
index 67fc8aa..c29965b 100644
--- a/binutils/testsuite/binutils-all/objdump.exp
+++ b/binutils/testsuite/binutils-all/objdump.exp
@@ -273,6 +273,86 @@ if { ![is_elf_format] } then {
     }
 }
 
+proc test_build_id_debuglink {} {
+    global srcdir
+    global subdir
+    global env
+    global CC_FOR_TARGET
+    global STRIP
+    global OBJCOPY
+    global OBJDUMP
+    global CFLAGS_FOR_TARGET
+    
+    set test "build-id-debuglink"
+    if {![info exists CC_FOR_TARGET]} {
+	set CC_FOR_TARGET $env(CC)
+    }
+    if { $CC_FOR_TARGET == "" } {
+	unsupported $test
+	return
+    }
+
+    # Use a fixed build-id.
+    set CFLAGS_FOR_TARGET "-g -Wl,--build-id=0x12345678abcdef01"
+
+    if { [target_compile $srcdir/$subdir/testprog.c tmpdir/testprog exectuable debug] != "" } {
+	fail "$test (build)"
+	return
+    }
+
+    # FIXME: Do we need to restore CFLAGS_FOR_TARGET to its old value ?
+
+    if { [binutils_run $STRIP "--strip-debug --remove-section=.comment tmpdir/testprog -o tmpdir/testprog.strip"] != "" } {
+	fail "$test (strip debug info)"
+	return
+    }
+
+    if { [binutils_run $OBJCOPY "--only-keep-debug tmpdir/testprog tmpdir/testprog.debug"] != "" } {
+	fail "$test (create separate debug info file)"
+	return
+    }
+
+    set got [remote_exec host "mkdir -p .build-id/12" ]
+    if { [lindex $got 0] != 0 || ![string match "" [lindex $got 1]] } then {
+	fail "$test (make debug directory)"
+	return
+    }
+
+    set got [remote_exec host "cp tmpdir/testprog.debug .build-id/12/345678abcdef01.debug"]
+    if { [lindex $got 0] != 0 || ![string match "" [lindex $got 1]] } then {
+	fail "$test (copy debug info into debug directory)"
+	return
+    }
+    
+    set got [remote_exec host "$OBJDUMP -Sl tmpdir/testprog.strip" "" "/dev/null" "tmpdir/testprog.strip.dump"]
+    if { [lindex $got 0] != 0 || ![string match "" [lindex $got 1]] } then {
+	fail "$test (post strip dump)"
+	return
+    }
+
+    set src2 tmpdir/testprog.strip.dump
+    verbose " grep -e testprog.c ${src2}"
+    set status [remote_exec build grep "-e testprog.c ${src2}"]
+    set exec_output [lindex $status 1]
+    set exec_output [prune_warnings $exec_output]
+    if [string match "" $exec_output] then {
+	send_log "$exec_output\n"
+	verbose "$exec_output" 1
+	fail "$test (grepping for source file name in disassembly output)"
+    } else {
+	pass "$test"
+	# Cleanup...
+	set got [remote_exec host "rm .build-id/12/345678abcdef01.debug"]
+	set got [remote_exec host "rmdir -p .build-id/12" ]
+	set got [remote_exec host "rm tmpdir/testprog.strip.dump"]
+	set got [remote_exec host "rm tmpdir/testprog.debug"]
+	set got [remote_exec host "rm tmpdir/testprog.strip"]
+    }
+}
+
+if {[isnative] && [is_elf_format]} then {
+    test_build_id_debuglink
+}
 
 # Options which are not tested: -a -d -D -R -T -x -l --stabs
 # I don't see any generic way to test any of these other than -a.


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