Update copyright years
[deliverable/binutils-gdb.git] / bfd / opncls.c
index c18d08af38844629df113a2e258ebbbaba25360b..a2a35f4e05847df2896067913ec1e42d412f1c72 100644 (file)
@@ -1,7 +1,5 @@
 /* opncls.c -- open and close a BFD.
-   Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 2000,
-   2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2012
-   Free Software Foundation, Inc.
+   Copyright (C) 1990-2014 Free Software Foundation, Inc.
 
    Written by Cygnus Support.
 
@@ -82,27 +80,12 @@ _bfd_new_bfd (void)
 
   nbfd->arch_info = &bfd_default_arch_struct;
 
-  nbfd->direction = no_direction;
-  nbfd->iostream = NULL;
-  nbfd->where = 0;
   if (!bfd_hash_table_init_n (& nbfd->section_htab, bfd_section_hash_newfunc,
-                             sizeof (struct section_hash_entry), 251))
+                             sizeof (struct section_hash_entry), 13))
     {
       free (nbfd);
       return NULL;
     }
-  nbfd->sections = NULL;
-  nbfd->section_last = NULL;
-  nbfd->format = bfd_unknown;
-  nbfd->my_archive = NULL;
-  nbfd->origin = 0;
-  nbfd->opened_once = FALSE;
-  nbfd->output_has_begun = FALSE;
-  nbfd->section_count = 0;
-  nbfd->usrdata = NULL;
-  nbfd->cacheable = FALSE;
-  nbfd->flags = BFD_NO_FLAGS;
-  nbfd->mtime_set = FALSE;
 
   return nbfd;
 }
@@ -140,6 +123,8 @@ _bfd_delete_bfd (bfd *abfd)
       objalloc_free ((struct objalloc *) abfd->memory);
     }
 
+  if (abfd->filename)
+    free ((char *) abfd->filename);
   free (abfd->arelt_data);
   free (abfd);
 }
@@ -198,6 +183,9 @@ DESCRIPTION
        <<system_call>> error.
 
        On error, @var{fd} is always closed.
+
+       A copy of the @var{filename} argument is stored in the newly created
+       BFD.  It can be accessed via the bfd_get_filename() macro.
 */
 
 bfd *
@@ -237,7 +225,10 @@ bfd_fopen (const char *filename, const char *target, const char *mode, int fd)
     }
 
   /* OK, put everything where it belongs.  */
-  nbfd->filename = filename;
+
+  /* PR 11983: Do not cache the original filename, but
+     rather make a copy - the original might go away.  */
+  nbfd->filename = xstrdup (filename);
 
   /* Figure out whether the user is opening the file for reading,
      writing, or both, by looking at the MODE argument.  */
@@ -255,12 +246,13 @@ bfd_fopen (const char *filename, const char *target, const char *mode, int fd)
       return NULL;
     }
   nbfd->opened_once = TRUE;
+
   /* If we opened the file by name, mark it cacheable; we can close it
      and reopen it later.  However, if a file descriptor was provided,
      then it may have been opened with special flags that make it
      unsafe to close and reopen the file.  */
   if (fd == -1)
-    bfd_set_cacheable (nbfd, TRUE);
+    (void) bfd_set_cacheable (nbfd, TRUE);
 
   return nbfd;
 }
@@ -282,6 +274,9 @@ DESCRIPTION
        If <<NULL>> is returned then an error has occured.   Possible errors
        are <<bfd_error_no_memory>>, <<bfd_error_invalid_target>> or
        <<system_call>> error.
+
+       A copy of the @var{filename} argument is stored in the newly created
+       BFD.  It can be accessed via the bfd_get_filename() macro.
 */
 
 bfd *
@@ -323,6 +318,9 @@ DESCRIPTION
        <<bfd_error_invalid_target>> and <<bfd_error_system_call>>.
 
        On error, @var{fd} is closed.
+
+       A copy of the @var{filename} argument is stored in the newly created
+       BFD.  It can be accessed via the bfd_get_filename() macro.
 */
 
 bfd *
@@ -365,12 +363,15 @@ FUNCTION
        bfd_openstreamr
 
 SYNOPSIS
-       bfd *bfd_openstreamr (const char *, const char *, void *);
+       bfd *bfd_openstreamr (const char * filename, const char * target, void * stream);
 
 DESCRIPTION
 
        Open a BFD for read access on an existing stdio stream.  When
        the BFD is passed to <<bfd_close>>, the stream will be closed.
+
+       A copy of the @var{filename} argument is stored in the newly created
+       BFD.  It can be accessed via the bfd_get_filename() macro.
 */
 
 bfd *
@@ -392,7 +393,9 @@ bfd_openstreamr (const char *filename, const char *target, void *streamarg)
     }
 
   nbfd->iostream = stream;
-  nbfd->filename = filename;
+  /* PR 11983: Do not cache the original filename, but
+     rather make a copy - the original might go away.  */
+  nbfd->filename = xstrdup (filename);
   nbfd->direction = read_direction;
 
   if (! bfd_cache_init (nbfd))
@@ -457,6 +460,8 @@ DESCRIPTION
        occurred.  Possible errors are <<bfd_error_no_memory>>,
        <<bfd_error_invalid_target>> and <<bfd_error_system_call>>.
 
+       A copy of the @var{filename} argument is stored in the newly created
+       BFD.  It can be accessed via the bfd_get_filename() macro.
 */
 
 struct opncls
@@ -582,7 +587,9 @@ bfd_openr_iovec (const char *filename, const char *target,
       return NULL;
     }
 
-  nbfd->filename = filename;
+  /* PR 11983: Do not cache the original filename, but
+     rather make a copy - the original might go away.  */
+  nbfd->filename = xstrdup (filename);
   nbfd->direction = read_direction;
 
   /* `open_p (...)' would get expanded by an the open(2) syscall macro.  */
@@ -623,6 +630,9 @@ DESCRIPTION
 
        Possible errors are <<bfd_error_system_call>>, <<bfd_error_no_memory>>,
        <<bfd_error_invalid_target>>.
+
+       A copy of the @var{filename} argument is stored in the newly created
+       BFD.  It can be accessed via the bfd_get_filename() macro.
 */
 
 bfd *
@@ -644,7 +654,9 @@ bfd_openw (const char *filename, const char *target)
       return NULL;
     }
 
-  nbfd->filename = filename;
+  /* PR 11983: Do not cache the original filename, but
+     rather make a copy - the original might go away.  */
+  nbfd->filename = xstrdup (filename);
   nbfd->direction = write_direction;
 
   if (bfd_open_file (nbfd) == NULL)
@@ -781,6 +793,9 @@ DESCRIPTION
        Create a new BFD in the manner of <<bfd_openw>>, but without
        opening a file. The new BFD takes the target from the target
        used by @var{templ}. The format is always set to <<bfd_object>>.
+
+       A copy of the @var{filename} argument is stored in the newly created
+       BFD.  It can be accessed via the bfd_get_filename() macro.
 */
 
 bfd *
@@ -791,7 +806,9 @@ bfd_create (const char *filename, bfd *templ)
   nbfd = _bfd_new_bfd ();
   if (nbfd == NULL)
     return NULL;
-  nbfd->filename = filename;
+  /* PR 11983: Do not cache the original filename, but
+     rather make a copy - the original might go away.  */
+  nbfd->filename = xstrdup (filename);
   if (templ)
     nbfd->xvec = templ->xvec;
   nbfd->direction = no_direction;
@@ -1049,10 +1066,11 @@ bfd_release (bfd *abfd, void *block)
 
    This facilitates "optional" provision of debugging information, without
    having to provide two complete copies of every binary object (with and
-   without debug symbols).
-*/
+   without debug symbols).  */
+
+#define GNU_DEBUGLINK          ".gnu_debuglink"
+#define GNU_DEBUGALTLINK       ".gnu_debugaltlink"
 
-#define GNU_DEBUGLINK  ".gnu_debuglink"
 /*
 FUNCTION
        bfd_calc_gnu_debuglink_crc32
@@ -1140,20 +1158,22 @@ bfd_calc_gnu_debuglink_crc32 (unsigned long crc,
 
 
 /*
-INTERNAL_FUNCTION
-       get_debug_link_info
+FUNCTION
+       bfd_get_debug_link_info
 
 SYNOPSIS
-       char *get_debug_link_info (bfd *abfd, unsigned long *crc32_out);
+       char *bfd_get_debug_link_info (bfd *abfd, unsigned long *crc32_out);
 
 DESCRIPTION
-       fetch the filename and CRC32 value for any separate debuginfo
-       associated with @var{abfd}. Return NULL if no such info found,
-       otherwise return filename and update @var{crc32_out}.
+       Fetch the filename and CRC32 value for any separate debuginfo
+       associated with @var{abfd}.  Return NULL if no such info found,
+       otherwise return filename and update @var{crc32_out}.  The
+       returned filename is allocated with @code{malloc}; freeing it
+       is the responsibility of the caller.
 */
 
-static char *
-get_debug_link_info (bfd *abfd, unsigned long *crc32_out)
+char *
+bfd_get_debug_link_info (bfd *abfd, unsigned long *crc32_out)
 {
   asection *sect;
   unsigned long crc32;
@@ -1187,6 +1207,60 @@ get_debug_link_info (bfd *abfd, unsigned long *crc32_out)
   return name;
 }
 
+/*
+FUNCTION
+       bfd_get_alt_debug_link_info
+
+SYNOPSIS
+       char *bfd_get_alt_debug_link_info (bfd * abfd,
+                                          bfd_size_type *buildid_len,
+                                          bfd_byte **buildid_out);
+
+DESCRIPTION
+       Fetch the filename and BuildID value for any alternate debuginfo
+       associated with @var{abfd}.  Return NULL if no such info found,
+       otherwise return filename and update @var{buildid_len} and
+       @var{buildid_out}.  The returned filename and build_id are
+       allocated with @code{malloc}; freeing them is the
+       responsibility of the caller.
+*/
+
+char *
+bfd_get_alt_debug_link_info (bfd * abfd, bfd_size_type *buildid_len,
+                            bfd_byte **buildid_out)
+{
+  asection *sect;
+  bfd_byte *contents;
+  int buildid_offset;
+  char *name;
+
+  BFD_ASSERT (abfd);
+  BFD_ASSERT (buildid_len);
+  BFD_ASSERT (buildid_out);
+
+  sect = bfd_get_section_by_name (abfd, GNU_DEBUGALTLINK);
+
+  if (sect == NULL)
+    return NULL;
+
+  if (!bfd_malloc_and_get_section (abfd, sect, & contents))
+    {
+      if (contents != NULL)
+       free (contents);
+      return NULL;
+    }
+
+  /* BuildID value is stored after the filename.  */
+  name = (char *) contents;
+  buildid_offset = strlen (name) + 1;
+
+  *buildid_len = bfd_get_section_size (sect) - buildid_offset;
+  *buildid_out = bfd_malloc (*buildid_len);
+  memcpy (*buildid_out, contents + buildid_offset, *buildid_len);
+
+  return name;
+}
+
 /*
 INTERNAL_FUNCTION
        separate_debug_file_exists
@@ -1222,6 +1296,37 @@ separate_debug_file_exists (const char *name, const unsigned long crc)
   return crc == file_crc;
 }
 
+/*
+INTERNAL_FUNCTION
+       separate_alt_debug_file_exists
+
+SYNOPSIS
+       bfd_boolean separate_alt_debug_file_exists
+         (char *name, unsigned long crc32);
+
+DESCRIPTION
+       Checks to see if @var{name} is a file and if its BuildID
+       matches @var{buildid}.
+*/
+
+static bfd_boolean
+separate_alt_debug_file_exists (const char *name,
+                               const unsigned long buildid ATTRIBUTE_UNUSED)
+{
+  FILE *f;
+
+  BFD_ASSERT (name);
+
+  f = real_fopen (name, FOPEN_RB);
+  if (f == NULL)
+    return FALSE;
+
+  /* FIXME: Add code to check buildid.  */
+
+  fclose (f);
+
+  return TRUE;
+}
 
 /*
 INTERNAL_FUNCTION
@@ -1231,16 +1336,24 @@ SYNOPSIS
        char *find_separate_debug_file (bfd *abfd);
 
 DESCRIPTION
-       Searches @var{abfd} for a reference to separate debugging
-       information, scans various locations in the filesystem, including
-       the file tree rooted at @var{debug_file_directory}, and returns a
-       filename of such debugging information if the file is found and has
-       matching CRC32.  Returns NULL if no reference to debugging file
-       exists, or file cannot be found.
+       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.
 */
 
+typedef char *      (* get_func_type) (bfd *, unsigned long *);
+typedef bfd_boolean (* check_func_type) (const char *, const unsigned long);
+
 static char *
-find_separate_debug_file (bfd *abfd, const char *debug_file_directory)
+find_separate_debug_file (bfd *           abfd,
+                         const char *    debug_file_directory,
+                         get_func_type   get_func,
+                         check_func_type check_func)
 {
   char *base;
   char *dir;
@@ -1261,7 +1374,8 @@ find_separate_debug_file (bfd *abfd, const char *debug_file_directory)
       return NULL;
     }
 
-  base = get_debug_link_info (abfd, & crc32);
+  base = get_func (abfd, & crc32);
+    
   if (base == NULL)
     return NULL;
 
@@ -1300,37 +1414,22 @@ find_separate_debug_file (bfd *abfd, const char *debug_file_directory)
                   + strlen (base)
                   + 1);
   if (debugfile == NULL)
-    {
-      free (base);
-      free (dir);
-      free (canon_dir);
-      return NULL;
-    }
+    goto found; /* Actually this returns NULL.  */
 
   /* First try in the same directory as the original file:  */
   strcpy (debugfile, dir);
   strcat (debugfile, base);
 
-  if (separate_debug_file_exists (debugfile, crc32))
-    {
-      free (base);
-      free (dir);
-      free (canon_dir);
-      return debugfile;
-    }
+  if (check_func (debugfile, crc32))
+    goto found;
 
   /* Then try in a subdirectory called .debug.  */
   strcpy (debugfile, dir);
   strcat (debugfile, ".debug/");
   strcat (debugfile, base);
 
-  if (separate_debug_file_exists (debugfile, crc32))
-    {
-      free (base);
-      free (dir);
-      free (canon_dir);
-      return debugfile;
-    }
+  if (check_func (debugfile, crc32))
+    goto found;
 
   /* Then try in the global debugfile directory.  */
   strcpy (debugfile, debug_file_directory);
@@ -1342,19 +1441,18 @@ find_separate_debug_file (bfd *abfd, const char *debug_file_directory)
   strcat (debugfile, canon_dir);
   strcat (debugfile, base);
 
-  if (separate_debug_file_exists (debugfile, crc32))
-    {
-      free (base);
-      free (dir);
-      free (canon_dir);
-      return debugfile;
-    }
+  if (check_func (debugfile, crc32))
+    goto found;
 
+  /* Failed to find the file.  */
   free (debugfile);
+  debugfile = NULL;
+
+ found:
   free (base);
   free (dir);
   free (canon_dir);
-  return NULL;
+  return debugfile;
 }
 
 
@@ -1387,7 +1485,61 @@ 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,
+                                  bfd_get_debug_link_info,
+                                  separate_debug_file_exists);
+}
+
+/* Helper for bfd_follow_gnu_debugaltlink.  It just pretends to return
+   a CRC.  .gnu_debugaltlink supplies a build-id, which is different,
+   but this is ok because separate_alt_debug_file_exists ignores the
+   CRC anyway.  */
+
+static char *
+get_alt_debug_link_info_shim (bfd * abfd, unsigned long *crc32_out)
+{
+  bfd_size_type len;
+  bfd_byte *buildid = NULL;
+  char *result = bfd_get_alt_debug_link_info (abfd, &len, &buildid);
+
+  *crc32_out = 0;
+  free (buildid);
+
+  return result;
+}
+
+/*
+FUNCTION
+       bfd_follow_gnu_debugaltlink
+
+SYNOPSIS
+       char *bfd_follow_gnu_debugaltlink (bfd *abfd, const char *dir);
+
+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
+       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].
+
+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_gnu_debugaltlink (bfd *abfd, const char *dir)
+{
+  return find_separate_debug_file (abfd, dir,
+                                  get_alt_debug_link_info_shim,
+                                  separate_alt_debug_file_exists);
 }
 
 /*
This page took 0.029464 seconds and 4 git commands to generate.