c6dd967
diff -rcp ../binutils-2.23.2.orig/bfd/bfd-in2.h bfd/bfd-in2.h
c6dd967
*** ../binutils-2.23.2.orig/bfd/bfd-in2.h	2013-05-29 15:56:00.512051112 +0100
c6dd967
--- bfd/bfd-in2.h	2013-05-29 15:58:54.994055949 +0100
c6dd967
*************** void *bfd_zalloc (bfd *abfd, bfd_size_ty
c6dd967
*** 1042,1049 ****
c6dd967
--- 1042,1053 ----
c6dd967
  unsigned long bfd_calc_gnu_debuglink_crc32
c6dd967
     (unsigned long crc, const unsigned char *buf, bfd_size_type len);
c6dd967
  
c6dd967
+ char *bfd_get_alt_debug_link_info (bfd *abfd, unsigned long *crc32_out);
c6dd967
+ 
c6dd967
  char *bfd_follow_gnu_debuglink (bfd *abfd, const char *dir);
c6dd967
  
c6dd967
+ char *bfd_follow_gnu_debugaltlink (bfd *abfd, const char *dir);
c6dd967
+ 
c6dd967
  struct bfd_section *bfd_create_gnu_debuglink_section
c6dd967
     (bfd *abfd, const char *filename);
c6dd967
  
c6dd967
diff -rcp ../binutils-2.23.2.orig/bfd/dwarf2.c bfd/dwarf2.c
c6dd967
*** ../binutils-2.23.2.orig/bfd/dwarf2.c	2013-05-29 15:56:00.296051106 +0100
c6dd967
--- bfd/dwarf2.c	2013-05-29 16:00:03.490057848 +0100
c6dd967
*************** struct dwarf2_debug
c6dd967
*** 108,113 ****
c6dd967
--- 108,123 ----
c6dd967
    asection *sec;
c6dd967
    bfd_byte *sec_info_ptr;
c6dd967
  
c6dd967
+   /* Support for alternate debug info sections created by the DWZ utility:
c6dd967
+      This includes a pointer to an alternate bfd which contains *extra*,
c6dd967
+      possibly duplicate debug sections, and pointers to the loaded
c6dd967
+      .debug_str and .debug_info sections from this bfd.  */
c6dd967
+   bfd *          alt_bfd_ptr;
c6dd967
+   bfd_byte *     alt_dwarf_str_buffer;
c6dd967
+   bfd_size_type  alt_dwarf_str_size;
c6dd967
+   bfd_byte *     alt_dwarf_info_buffer;
c6dd967
+   bfd_size_type  alt_dwarf_info_size;
c6dd967
+ 
c6dd967
    /* A pointer to the memory block allocated for info_ptr.  Neither
c6dd967
       info_ptr nor sec_info_ptr are guaranteed to stay pointing to the
c6dd967
       beginning of the malloc block.  This is used only to free the
c6dd967
*************** const struct dwarf_debug_section dwarf_d
c6dd967
*** 287,292 ****
c6dd967
--- 297,303 ----
c6dd967
    { ".debug_aranges",		".zdebug_aranges" },
c6dd967
    { ".debug_frame",		".zdebug_frame" },
c6dd967
    { ".debug_info",		".zdebug_info" },
c6dd967
+   { ".debug_info",		".zdebug_info" },
c6dd967
    { ".debug_line",		".zdebug_line" },
c6dd967
    { ".debug_loc",		".zdebug_loc" },
c6dd967
    { ".debug_macinfo",		".zdebug_macinfo" },
c6dd967
*************** const struct dwarf_debug_section dwarf_d
c6dd967
*** 297,302 ****
c6dd967
--- 308,314 ----
c6dd967
    { ".debug_static_func",	".zdebug_static_func" },
c6dd967
    { ".debug_static_vars",	".zdebug_static_vars" },
c6dd967
    { ".debug_str",		".zdebug_str", },
c6dd967
+   { ".debug_str",		".zdebug_str", },
c6dd967
    { ".debug_types",		".zdebug_types" },
c6dd967
    /* GNU DWARF 1 extensions */
c6dd967
    { ".debug_sfnames",		".zdebug_sfnames" },
c6dd967
*************** const struct dwarf_debug_section dwarf_d
c6dd967
*** 309,320 ****
c6dd967
--- 321,335 ----
c6dd967
    { NULL,			NULL },
c6dd967
  };
c6dd967
  
c6dd967
+ /* NB/ Numbers in this enum must match up with indicies
c6dd967
+    into the dwarf_debug_sections[] array above.  */
c6dd967
  enum dwarf_debug_section_enum
c6dd967
  {
c6dd967
    debug_abbrev = 0,
c6dd967
    debug_aranges,
c6dd967
    debug_frame,
c6dd967
    debug_info,
c6dd967
+   debug_info_alt,
c6dd967
    debug_line,
c6dd967
    debug_loc,
c6dd967
    debug_macinfo,
c6dd967
*************** enum dwarf_debug_section_enum
c6dd967
*** 325,330 ****
c6dd967
--- 340,346 ----
c6dd967
    debug_static_func,
c6dd967
    debug_static_vars,
c6dd967
    debug_str,
c6dd967
+   debug_str_alt,
c6dd967
    debug_types,
c6dd967
    debug_sfnames,
c6dd967
    debug_srcinfo,
c6dd967
*************** read_section (bfd *           abfd,
c6dd967
*** 481,488 ****
c6dd967
    asection *msec;
c6dd967
    const char *section_name = sec->uncompressed_name;
c6dd967
  
c6dd967
!   /* read_section is a noop if the section has already been read.  */
c6dd967
!   if (!*section_buffer)
c6dd967
      {
c6dd967
        msec = bfd_get_section_by_name (abfd, section_name);
c6dd967
        if (! msec)
c6dd967
--- 497,504 ----
c6dd967
    asection *msec;
c6dd967
    const char *section_name = sec->uncompressed_name;
c6dd967
  
c6dd967
!   /* The section may have already been read.  */
c6dd967
!   if (*section_buffer == NULL)
c6dd967
      {
c6dd967
        msec = bfd_get_section_by_name (abfd, section_name);
c6dd967
        if (! msec)
c6dd967
*************** read_indirect_string (struct comp_unit *
c6dd967
*** 623,628 ****
c6dd967
--- 639,742 ----
c6dd967
    return str;
c6dd967
  }
c6dd967
  
c6dd967
+ /* Like read_indirect_string but uses a .debug_str located in
c6dd967
+    an alternate filepointed to by the .gnu_debuglink section.
c6dd967
+    Used to impement DW_FORM_GNU_strp_alt.  */
c6dd967
+ 
c6dd967
+ static char *
c6dd967
+ read_alt_indirect_string (struct comp_unit * unit,
c6dd967
+ 			  bfd_byte *         buf,
c6dd967
+ 			  unsigned int *     bytes_read_ptr)
c6dd967
+ {
c6dd967
+   bfd_uint64_t offset;
c6dd967
+   struct dwarf2_debug *stash = unit->stash;
c6dd967
+   char *str;
c6dd967
+ 
c6dd967
+   if (unit->offset_size == 4)
c6dd967
+     offset = read_4_bytes (unit->abfd, buf);
c6dd967
+   else
c6dd967
+     offset = read_8_bytes (unit->abfd, buf);
c6dd967
+ 
c6dd967
+   *bytes_read_ptr = unit->offset_size;
c6dd967
+ 
c6dd967
+   if (stash->alt_bfd_ptr == NULL)
c6dd967
+     {
c6dd967
+       bfd *  debug_bfd;
c6dd967
+       char * debug_filename = bfd_follow_gnu_debugaltlink (unit->abfd, DEBUGDIR);
c6dd967
+ 
c6dd967
+       if (debug_filename == NULL)
c6dd967
+ 	return NULL;
c6dd967
+ 
c6dd967
+       if ((debug_bfd = bfd_openr (debug_filename, NULL)) == NULL
c6dd967
+ 	  || ! bfd_check_format (debug_bfd, bfd_object))
c6dd967
+ 	{
c6dd967
+ 	  if (debug_bfd)
c6dd967
+ 	    bfd_close (debug_bfd);
c6dd967
+ 
c6dd967
+ 	  /* FIXME: Should we report our failure to follow the debuglink ?  */
c6dd967
+ 	  free (debug_filename);
c6dd967
+ 	  return NULL;
c6dd967
+ 	}
c6dd967
+       stash->alt_bfd_ptr = debug_bfd;
c6dd967
+     }
c6dd967
+   
c6dd967
+   if (! read_section (unit->stash->alt_bfd_ptr,
c6dd967
+ 		      stash->debug_sections + debug_str_alt,
c6dd967
+ 		      NULL, /* FIXME: Do we need to load alternate symbols ?  */
c6dd967
+ 		      offset,
c6dd967
+ 		      &stash->alt_dwarf_str_buffer,
c6dd967
+ 		      &stash->alt_dwarf_str_size))
c6dd967
+     return NULL;
c6dd967
+ 
c6dd967
+   str = (char *) stash->alt_dwarf_str_buffer + offset;
c6dd967
+   if (*str == '\0')
c6dd967
+     return NULL;
c6dd967
+ 
c6dd967
+   return str;
c6dd967
+ }
c6dd967
+ 
c6dd967
+ /* Resolve an alternate reference from UNIT at OFFSET.
c6dd967
+    Returns a pointer into the loaded alternate CU upon success
c6dd967
+    or NULL upon failure.  */
c6dd967
+ 
c6dd967
+ static bfd_byte *
c6dd967
+ read_alt_indirect_ref (struct comp_unit * unit,
c6dd967
+ 		       bfd_uint64_t       offset)
c6dd967
+ {
c6dd967
+   struct dwarf2_debug *stash = unit->stash;
c6dd967
+ 
c6dd967
+   if (stash->alt_bfd_ptr == NULL)
c6dd967
+     {
c6dd967
+       bfd *  debug_bfd;
c6dd967
+       char * debug_filename = bfd_follow_gnu_debugaltlink (unit->abfd, DEBUGDIR);
c6dd967
+ 
c6dd967
+       if (debug_filename == NULL)
c6dd967
+ 	return FALSE;
c6dd967
+ 
c6dd967
+       if ((debug_bfd = bfd_openr (debug_filename, NULL)) == NULL
c6dd967
+ 	  || ! bfd_check_format (debug_bfd, bfd_object))
c6dd967
+ 	{
c6dd967
+ 	  if (debug_bfd)
c6dd967
+ 	    bfd_close (debug_bfd);
c6dd967
+ 
c6dd967
+ 	  /* FIXME: Should we report our failure to follow the debuglink ?  */
c6dd967
+ 	  free (debug_filename);
c6dd967
+ 	  return NULL;
c6dd967
+ 	}
c6dd967
+       stash->alt_bfd_ptr = debug_bfd;
c6dd967
+     }
c6dd967
+   
c6dd967
+   if (! read_section (unit->stash->alt_bfd_ptr,
c6dd967
+ 		      stash->debug_sections + debug_info_alt,
c6dd967
+ 		      NULL, /* FIXME: Do we need to load alternate symbols ?  */
c6dd967
+ 		      offset,
c6dd967
+ 		      &stash->alt_dwarf_info_buffer,
c6dd967
+ 		      &stash->alt_dwarf_info_size))
c6dd967
+     return NULL;
c6dd967
+ 
c6dd967
+   return stash->alt_dwarf_info_buffer + offset;
c6dd967
+ }
c6dd967
+ 
c6dd967
  static bfd_uint64_t
c6dd967
  read_address (struct comp_unit *unit, bfd_byte *buf)
c6dd967
  {
c6dd967
*************** read_attribute_value (struct attribute *
c6dd967
*** 826,831 ****
c6dd967
--- 940,946 ----
c6dd967
        attr->u.val = read_address (unit, info_ptr);
c6dd967
        info_ptr += unit->addr_size;
c6dd967
        break;
c6dd967
+     case DW_FORM_GNU_ref_alt:
c6dd967
      case DW_FORM_sec_offset:
c6dd967
        if (unit->offset_size == 4)
c6dd967
  	attr->u.val = read_4_bytes (unit->abfd, info_ptr);
c6dd967
*************** read_attribute_value (struct attribute *
c6dd967
*** 875,880 ****
c6dd967
--- 990,999 ----
c6dd967
        attr->u.str = read_indirect_string (unit, info_ptr, &bytes_read);
c6dd967
        info_ptr += bytes_read;
c6dd967
        break;
c6dd967
+     case DW_FORM_GNU_strp_alt:
c6dd967
+       attr->u.str = read_alt_indirect_string (unit, info_ptr, &bytes_read);
c6dd967
+       info_ptr += bytes_read;
c6dd967
+       break;
c6dd967
      case DW_FORM_exprloc:
c6dd967
      case DW_FORM_block:
c6dd967
        amt = sizeof (struct dwarf_block);
c6dd967
*************** find_abstract_instance_name (struct comp
c6dd967
*** 2006,2011 ****
c6dd967
--- 2125,2141 ----
c6dd967
  
c6dd967
        info_ptr = unit->sec_info_ptr + die_ref;
c6dd967
      }
c6dd967
+   else if (attr_ptr->form == DW_FORM_GNU_ref_alt)
c6dd967
+     {
c6dd967
+       info_ptr = read_alt_indirect_ref (unit, die_ref);
c6dd967
+       if (info_ptr == NULL)
c6dd967
+ 	{
c6dd967
+ 	  (*_bfd_error_handler)
c6dd967
+ 	    (_("Dwarf Error: Unable to read alt ref %u."), die_ref);
c6dd967
+ 	  bfd_set_error (bfd_error_bad_value);
c6dd967
+ 	  return name;
c6dd967
+ 	}
c6dd967
+     }
c6dd967
    else 
c6dd967
      info_ptr = unit->info_ptr_unit + die_ref;
c6dd967
    abbrev_number = read_unsigned_leb128 (abfd, info_ptr, &bytes_read);
c6dd967
*************** _bfd_dwarf2_cleanup_debug_info (bfd *abf
c6dd967
*** 3720,3723 ****
c6dd967
--- 3850,3859 ----
c6dd967
      free (stash->dwarf_ranges_buffer);
c6dd967
    if (stash->info_ptr_memory)
c6dd967
      free (stash->info_ptr_memory);
c6dd967
+   if (stash->alt_dwarf_str_buffer)
c6dd967
+     free (stash->alt_dwarf_str_buffer);
c6dd967
+   if (stash->alt_dwarf_info_buffer)
c6dd967
+     free (stash->alt_dwarf_info_buffer);
c6dd967
+   if (stash->alt_bfd_ptr)
c6dd967
+     bfd_close (stash->alt_bfd_ptr);
c6dd967
  }
c6dd967
diff -rcp ../binutils-2.23.2.orig/bfd/opncls.c bfd/opncls.c
c6dd967
*** ../binutils-2.23.2.orig/bfd/opncls.c	2013-05-29 15:55:59.990051098 +0100
c6dd967
--- bfd/opncls.c	2013-05-29 16:01:00.052059415 +0100
c6dd967
*************** bfd_release (bfd *abfd, void *block)
c6dd967
*** 1056,1065 ****
c6dd967
  
c6dd967
     This facilitates "optional" provision of debugging information, without
c6dd967
     having to provide two complete copies of every binary object (with and
c6dd967
!    without debug symbols).
c6dd967
! */
c6dd967
  
c6dd967
- #define GNU_DEBUGLINK	".gnu_debuglink"
c6dd967
  /*
c6dd967
  FUNCTION
c6dd967
  	bfd_calc_gnu_debuglink_crc32
c6dd967
--- 1056,1066 ----
c6dd967
  
c6dd967
     This facilitates "optional" provision of debugging information, without
c6dd967
     having to provide two complete copies of every binary object (with and
c6dd967
!    without debug symbols).  */
c6dd967
! 
c6dd967
! #define GNU_DEBUGLINK		".gnu_debuglink"
c6dd967
! #define GNU_DEBUGALTLINK	".gnu_debugaltlink"
c6dd967
  
c6dd967
  /*
c6dd967
  FUNCTION
c6dd967
  	bfd_calc_gnu_debuglink_crc32
c6dd967
*************** get_debug_link_info (bfd *abfd, unsigned
c6dd967
*** 1195,1200 ****
c6dd967
--- 1196,1249 ----
c6dd967
  }
c6dd967
  
c6dd967
  /*
c6dd967
+ FUNCTION
c6dd967
+ 	bfd_get_alt_debug_link_info
c6dd967
+ 
c6dd967
+ SYNOPSIS
c6dd967
+ 	char *bfd_get_alt_debug_link_info (bfd *abfd, unsigned long *crc32_out);
c6dd967
+ 
c6dd967
+ DESCRIPTION
c6dd967
+ 	Fetch the filename and BuildID value for any alternate debuginfo
c6dd967
+ 	associated with @var{abfd}.  Return NULL if no such info found,
c6dd967
+ 	otherwise return filename and update @var{buildid_out}.  The
c6dd967
+ 	returned filename is allocated with @code{malloc}; freeing it
c6dd967
+ 	is the responsibility of the caller.
c6dd967
+ */
c6dd967
+ 
c6dd967
+ char *
c6dd967
+ bfd_get_alt_debug_link_info (bfd * abfd, unsigned long * buildid_out)
c6dd967
+ {
c6dd967
+   asection *sect;
c6dd967
+   bfd_byte *contents;
c6dd967
+   int buildid_offset;
c6dd967
+   char *name;
c6dd967
+ 
c6dd967
+   BFD_ASSERT (abfd);
c6dd967
+   BFD_ASSERT (buildid_out);
c6dd967
+ 
c6dd967
+   sect = bfd_get_section_by_name (abfd, GNU_DEBUGALTLINK);
c6dd967
+ 
c6dd967
+   if (sect == NULL)
c6dd967
+     return NULL;
c6dd967
+ 
c6dd967
+   if (!bfd_malloc_and_get_section (abfd, sect, & contents))
c6dd967
+     {
c6dd967
+       if (contents != NULL)
c6dd967
+ 	free (contents);
c6dd967
+       return NULL;
c6dd967
+     }
c6dd967
+ 
c6dd967
+   /* BuildID value is stored after the filename, aligned up to 4 bytes.  */
c6dd967
+   name = (char *) contents;
c6dd967
+   buildid_offset = strlen (name) + 1;
c6dd967
+   buildid_offset = (buildid_offset + 3) & ~3;
c6dd967
+ 
c6dd967
+   * buildid_out = bfd_get_32 (abfd, contents + buildid_offset);
c6dd967
+ 
c6dd967
+   return name;
c6dd967
+ }
c6dd967
+ 
c6dd967
+ /*
c6dd967
  INTERNAL_FUNCTION
c6dd967
  	separate_debug_file_exists
c6dd967
  
c6dd967
*************** separate_debug_file_exists (const char *
c6dd967
*** 1229,1234 ****
c6dd967
--- 1278,1314 ----
c6dd967
    return crc == file_crc;
c6dd967
  }
c6dd967
  
c6dd967
+ /*
c6dd967
+ INTERNAL_FUNCTION
c6dd967
+ 	separate_alt_debug_file_exists
c6dd967
+ 
c6dd967
+ SYNOPSIS
c6dd967
+ 	bfd_boolean separate_alt_debug_file_exists
c6dd967
+ 	  (char *name, unsigned long crc32);
c6dd967
+ 
c6dd967
+ DESCRIPTION
c6dd967
+ 	Checks to see if @var{name} is a file and if its BuildID
c6dd967
+ 	matches @var{buildid}.
c6dd967
+ */
c6dd967
+ 
c6dd967
+ static bfd_boolean
c6dd967
+ separate_alt_debug_file_exists (const char *name,
c6dd967
+ 				const unsigned long buildid ATTRIBUTE_UNUSED)
c6dd967
+ {
c6dd967
+   FILE *f;
c6dd967
+ 
c6dd967
+   BFD_ASSERT (name);
c6dd967
+ 
c6dd967
+   f = real_fopen (name, FOPEN_RB);
c6dd967
+   if (f == NULL)
c6dd967
+     return FALSE;
c6dd967
+ 
c6dd967
+   /* FIXME: Add code to check buildid.  */
c6dd967
+ 
c6dd967
+   fclose (f);
c6dd967
+ 
c6dd967
+   return TRUE;
c6dd967
+ }
c6dd967
  
c6dd967
  /*
c6dd967
  INTERNAL_FUNCTION
c6dd967
*************** SYNOPSIS
c6dd967
*** 1238,1253 ****
c6dd967
  	char *find_separate_debug_file (bfd *abfd);
c6dd967
  
c6dd967
  DESCRIPTION
c6dd967
! 	Searches @var{abfd} for a reference to separate debugging
c6dd967
! 	information, scans various locations in the filesystem, including
c6dd967
! 	the file tree rooted at @var{debug_file_directory}, and returns a
c6dd967
! 	filename of such debugging information if the file is found and has
c6dd967
! 	matching CRC32.  Returns NULL if no reference to debugging file
c6dd967
! 	exists, or file cannot be found.
c6dd967
  */
c6dd967
  
c6dd967
  static char *
c6dd967
! find_separate_debug_file (bfd *abfd, const char *debug_file_directory)
c6dd967
  {
c6dd967
    char *base;
c6dd967
    char *dir;
c6dd967
--- 1318,1341 ----
c6dd967
  	char *find_separate_debug_file (bfd *abfd);
c6dd967
  
c6dd967
  DESCRIPTION
c6dd967
! 	Searches @var{abfd} for a section called @var{section_name} which
c6dd967
! 	is expected to contain a reference to a file containing separate
c6dd967
! 	debugging information.  The function scans various locations in
c6dd967
! 	the filesystem, including the file tree rooted at
c6dd967
! 	@var{debug_file_directory}, and returns the first matching
c6dd967
! 	filename that it finds.  If @var{check_crc} is TRUE then the
c6dd967
! 	contents of the file must also match the CRC value contained in
c6dd967
! 	@var{section_name}.  Returns NULL if no valid file could be found.
c6dd967
  */
c6dd967
  
c6dd967
+ typedef char *      (* get_func_type) (bfd *, unsigned long *);
c6dd967
+ typedef bfd_boolean (* check_func_type) (const char *, const unsigned long);
c6dd967
+ 
c6dd967
  static char *
c6dd967
! find_separate_debug_file (bfd *           abfd,
c6dd967
! 			  const char *    debug_file_directory,
c6dd967
! 			  get_func_type   get_func,
c6dd967
! 			  check_func_type check_func)
c6dd967
  {
c6dd967
    char *base;
c6dd967
    char *dir;
c6dd967
*************** find_separate_debug_file (bfd *abfd, con
c6dd967
*** 1268,1274 ****
c6dd967
        return NULL;
c6dd967
      }
c6dd967
  
c6dd967
!   base = get_debug_link_info (abfd, & crc32);
c6dd967
    if (base == NULL)
c6dd967
      return NULL;
c6dd967
  
c6dd967
--- 1356,1362 ----
c6dd967
        return NULL;
c6dd967
      }
c6dd967
  
c6dd967
!   base = get_func (abfd, & crc32);
c6dd967
    if (base == NULL)
c6dd967
      return NULL;
c6dd967
  
c6dd967
*************** find_separate_debug_file (bfd *abfd, con
c6dd967
*** 1309,1345 ****
c6dd967
                    + strlen (base)
c6dd967
                    + 1);
c6dd967
    if (debugfile == NULL)
c6dd967
!     {
c6dd967
!       free (base);
c6dd967
!       free (dir);
c6dd967
!       free (canon_dir);
c6dd967
!       return NULL;
c6dd967
!     }
c6dd967
  
c6dd967
    /* First try in the same directory as the original file:  */
c6dd967
    strcpy (debugfile, dir);
c6dd967
    strcat (debugfile, base);
c6dd967
  
c6dd967
!   if (separate_debug_file_exists (debugfile, crc32))
c6dd967
!     {
c6dd967
!       free (base);
c6dd967
!       free (dir);
c6dd967
!       free (canon_dir);
c6dd967
!       return debugfile;
c6dd967
!     }
c6dd967
  
c6dd967
    /* Then try in a subdirectory called .debug.  */
c6dd967
    strcpy (debugfile, dir);
c6dd967
    strcat (debugfile, ".debug/");
c6dd967
    strcat (debugfile, base);
c6dd967
  
c6dd967
!   if (separate_debug_file_exists (debugfile, crc32))
c6dd967
!     {
c6dd967
!       free (base);
c6dd967
!       free (dir);
c6dd967
!       free (canon_dir);
c6dd967
!       return debugfile;
c6dd967
!     }
c6dd967
  
c6dd967
    /* Then try in the global debug dir for Fedora libraries.  */
c6dd967
    sprintf (debugfile, "%s%s%s", FEDORA_LIB_DEBUG_DIR, dir, base);
c6dd967
--- 1397,1418 ----
c6dd967
                    + strlen (base)
c6dd967
                    + 1);
c6dd967
    if (debugfile == NULL)
c6dd967
!     goto found; /* Actually this returns NULL.  */
c6dd967
  
c6dd967
    /* First try in the same directory as the original file:  */
c6dd967
    strcpy (debugfile, dir);
c6dd967
    strcat (debugfile, base);
c6dd967
  
c6dd967
!   if (check_func (debugfile, crc32))
c6dd967
!     goto found;
c6dd967
  
c6dd967
    /* Then try in a subdirectory called .debug.  */
c6dd967
    strcpy (debugfile, dir);
c6dd967
    strcat (debugfile, ".debug/");
c6dd967
    strcat (debugfile, base);
c6dd967
  
c6dd967
!   if (check_func (debugfile, crc32))
c6dd967
!     goto found;
c6dd967
  
c6dd967
    /* Then try in the global debug dir for Fedora libraries.  */
c6dd967
    sprintf (debugfile, "%s%s%s", FEDORA_LIB_DEBUG_DIR, dir, base);
c6dd967
*************** find_separate_debug_file (bfd *abfd, con
c6dd967
*** 1371,1389 ****
c6dd967
    strcat (debugfile, canon_dir);
c6dd967
    strcat (debugfile, base);
c6dd967
  
c6dd967
!   if (separate_debug_file_exists (debugfile, crc32))
c6dd967
!     {
c6dd967
!       free (base);
c6dd967
!       free (dir);
c6dd967
!       free (canon_dir);
c6dd967
!       return debugfile;
c6dd967
!     }
c6dd967
  
c6dd967
    free (debugfile);
c6dd967
    free (base);
c6dd967
    free (dir);
c6dd967
    free (canon_dir);
c6dd967
!   return NULL;
c6dd967
  }
c6dd967
  
c6dd967
  
c6dd967
--- 1444,1461 ----
c6dd967
    strcat (debugfile, canon_dir);
c6dd967
    strcat (debugfile, base);
c6dd967
  
c6dd967
!   if (check_func (debugfile, crc32))
c6dd967
!     goto found;
c6dd967
  
c6dd967
+   /* Failed to find the file.  */
c6dd967
    free (debugfile);
c6dd967
+   debugfile = NULL;
c6dd967
+ 
c6dd967
+  found:
c6dd967
    free (base);
c6dd967
    free (dir);
c6dd967
    free (canon_dir);
c6dd967
!   return debugfile;
c6dd967
  }
c6dd967
  
c6dd967
  
c6dd967
*************** RETURNS
c6dd967
*** 1416,1422 ****
c6dd967
  char *
c6dd967
  bfd_follow_gnu_debuglink (bfd *abfd, const char *dir)
c6dd967
  {
c6dd967
!   return find_separate_debug_file (abfd, dir);
c6dd967
  }
c6dd967
  
c6dd967
  /*
c6dd967
--- 1488,1530 ----
c6dd967
  char *
c6dd967
  bfd_follow_gnu_debuglink (bfd *abfd, const char *dir)
c6dd967
  {
c6dd967
!   return find_separate_debug_file (abfd, dir,
c6dd967
! 				   get_debug_link_info,
c6dd967
! 				   separate_debug_file_exists);
c6dd967
! }
c6dd967
! 
c6dd967
! /*
c6dd967
! FUNCTION
c6dd967
! 	bfd_follow_gnu_debugaltlink
c6dd967
! 
c6dd967
! SYNOPSIS
c6dd967
! 	char *bfd_follow_gnu_debugaltlink (bfd *abfd, const char *dir);
c6dd967
! 
c6dd967
! DESCRIPTION
c6dd967
! 
c6dd967
! 	Takes a BFD and searches it for a .gnu_debugaltlink section.  If this
c6dd967
! 	section is found, it examines the section for the name of a file
c6dd967
! 	containing auxiliary debugging information.  It	then searches the
c6dd967
! 	filesystem for this file in a set of standard locations, including
c6dd967
! 	the directory tree rooted at @var{dir}, and if found returns the
c6dd967
! 	full filename.
c6dd967
! 
c6dd967
! 	If @var{dir} is NULL, it will search a default path configured into
c6dd967
! 	libbfd at build time.  [FIXME: This feature is not currently
c6dd967
! 	implemented].
c6dd967
! 
c6dd967
! RETURNS
c6dd967
! 	<<NULL>> on any errors or failure to locate the debug file,
c6dd967
! 	otherwise a pointer to a heap-allocated string containing the
c6dd967
! 	filename.  The caller is responsible for freeing this string.
c6dd967
! */
c6dd967
! 
c6dd967
! char *
c6dd967
! bfd_follow_gnu_debugaltlink (bfd *abfd, const char *dir)
c6dd967
! {
c6dd967
!   return find_separate_debug_file (abfd, dir,
c6dd967
! 				   bfd_get_alt_debug_link_info,
c6dd967
! 				   separate_alt_debug_file_exists);
c6dd967
  }
c6dd967
  
c6dd967
  /*
c6dd967