Automatic date update in version.in
[deliverable/binutils-gdb.git] / bfd / opncls.c
index b4d4dcf64643145e71e70dba29cd8208c945ddec..99097a9e39989e377af70e9450a970b009439e70 100644 (file)
@@ -1,5 +1,5 @@
 /* opncls.c -- open and close a BFD.
-   Copyright (C) 1990-2017 Free Software Foundation, Inc.
+   Copyright (C) 1990-2020 Free Software Foundation, Inc.
 
    Written by Cygnus Support.
 
@@ -167,7 +167,7 @@ FUNCTION
 
 SYNOPSIS
        bfd *bfd_fopen (const char *filename, const char *target,
-                        const char *mode, int fd);
+                       const char *mode, int fd);
 
 DESCRIPTION
        Open the file @var{filename} with the target @var{target}.
@@ -219,10 +219,12 @@ bfd_fopen (const char *filename, const char *target, const char *mode, int fd)
     nbfd->iostream = fdopen (fd, mode);
   else
 #endif
-    nbfd->iostream = real_fopen (filename, mode);
+    nbfd->iostream = _bfd_real_fopen (filename, mode);
   if (nbfd->iostream == NULL)
     {
       bfd_set_error (bfd_error_system_call);
+      if (fd != -1)
+       close (fd);
       _bfd_delete_bfd (nbfd);
       return NULL;
     }
@@ -231,7 +233,13 @@ bfd_fopen (const char *filename, const char *target, const char *mode, int fd)
 
   /* PR 11983: Do not cache the original filename, but
      rather make a copy - the original might go away.  */
-  nbfd->filename = xstrdup (filename);
+  nbfd->filename = bfd_strdup (filename);
+  if (nbfd->filename == NULL)
+    {
+      fclose (nbfd->iostream);
+      _bfd_delete_bfd (nbfd);
+      return NULL;
+    }
 
   /* Figure out whether the user is opening the file for reading,
      writing, or both, by looking at the MODE argument.  */
@@ -243,8 +251,9 @@ bfd_fopen (const char *filename, const char *target, const char *mode, int fd)
   else
     nbfd->direction = write_direction;
 
-  if (! bfd_cache_init (nbfd))
+  if (!bfd_cache_init (nbfd))
     {
+      fclose (nbfd->iostream);
       _bfd_delete_bfd (nbfd);
       return NULL;
     }
@@ -366,10 +375,10 @@ FUNCTION
        bfd_openstreamr
 
 SYNOPSIS
-       bfd *bfd_openstreamr (const char * filename, const char * target, void * stream);
+       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.
 
@@ -398,7 +407,12 @@ bfd_openstreamr (const char *filename, const char *target, void *streamarg)
   nbfd->iostream = stream;
   /* PR 11983: Do not cache the original filename, but
      rather make a copy - the original might go away.  */
-  nbfd->filename = xstrdup (filename);
+  nbfd->filename = bfd_strdup (filename);
+  if (nbfd->filename == NULL)
+    {
+      _bfd_delete_bfd (nbfd);
+      return NULL;
+    }
   nbfd->direction = read_direction;
 
   if (! bfd_cache_init (nbfd))
@@ -415,26 +429,25 @@ FUNCTION
        bfd_openr_iovec
 
 SYNOPSIS
-        bfd *bfd_openr_iovec (const char *filename, const char *target,
-                              void *(*open_func) (struct bfd *nbfd,
-                                                  void *open_closure),
-                              void *open_closure,
-                              file_ptr (*pread_func) (struct bfd *nbfd,
-                                                      void *stream,
-                                                      void *buf,
-                                                      file_ptr nbytes,
-                                                      file_ptr offset),
-                              int (*close_func) (struct bfd *nbfd,
-                                                 void *stream),
+       bfd *bfd_openr_iovec (const char *filename, const char *target,
+                             void *(*open_func) (struct bfd *nbfd,
+                                                 void *open_closure),
+                             void *open_closure,
+                             file_ptr (*pread_func) (struct bfd *nbfd,
+                                                     void *stream,
+                                                     void *buf,
+                                                     file_ptr nbytes,
+                                                     file_ptr offset),
+                             int (*close_func) (struct bfd *nbfd,
+                                                void *stream),
                              int (*stat_func) (struct bfd *abfd,
-                                               void *stream,
-                                               struct stat *sb));
+                                               void *stream,
+                                               struct stat *sb));
 
 DESCRIPTION
-
-        Create and return a BFD backed by a read-only @var{stream}.
-        The @var{stream} is created using @var{open_func}, accessed using
-        @var{pread_func} and destroyed using @var{close_func}.
+       Create and return a BFD backed by a read-only @var{stream}.
+       The @var{stream} is created using @var{open_func}, accessed using
+       @var{pread_func} and destroyed using @var{close_func}.
 
        Calls <<bfd_find_target>>, so @var{target} is interpreted as by
        that function.
@@ -502,6 +515,7 @@ opncls_bread (struct bfd *abfd, void *buf, file_ptr nbytes)
 {
   struct opncls *vec = (struct opncls *) abfd->iostream;
   file_ptr nread = (vec->pread) (abfd, vec->stream, buf, nbytes, vec->where);
+
   if (nread < 0)
     return nread;
   vec->where += nread;
@@ -523,6 +537,7 @@ opncls_bclose (struct bfd *abfd)
   /* Since the VEC's memory is bound to the bfd deleting the bfd will
      free it.  */
   int status = 0;
+
   if (vec->close != NULL)
     status = (vec->close) (abfd, vec->stream);
   abfd->iostream = NULL;
@@ -554,13 +569,14 @@ opncls_bmmap (struct bfd *abfd ATTRIBUTE_UNUSED,
              int prot ATTRIBUTE_UNUSED,
              int flags ATTRIBUTE_UNUSED,
              file_ptr offset ATTRIBUTE_UNUSED,
-              void **map_addr ATTRIBUTE_UNUSED,
-              bfd_size_type *map_len ATTRIBUTE_UNUSED)
+             void **map_addr ATTRIBUTE_UNUSED,
+             bfd_size_type *map_len ATTRIBUTE_UNUSED)
 {
   return (void *) -1;
 }
 
-static const struct bfd_iovec opncls_iovec = {
+static const struct bfd_iovec opncls_iovec =
+{
   &opncls_bread, &opncls_bwrite, &opncls_btell, &opncls_bseek,
   &opncls_bclose, &opncls_bflush, &opncls_bstat, &opncls_bmmap
 };
@@ -592,7 +608,12 @@ bfd_openr_iovec (const char *filename, const char *target,
 
   /* PR 11983: Do not cache the original filename, but
      rather make a copy - the original might go away.  */
-  nbfd->filename = xstrdup (filename);
+  nbfd->filename = bfd_strdup (filename);
+  if (nbfd->filename == NULL)
+    {
+      _bfd_delete_bfd (nbfd);
+      return NULL;
+    }
   nbfd->direction = read_direction;
 
   /* `open_p (...)' would get expanded by an the open(2) syscall macro.  */
@@ -659,7 +680,12 @@ bfd_openw (const char *filename, const char *target)
 
   /* PR 11983: Do not cache the original filename, but
      rather make a copy - the original might go away.  */
-  nbfd->filename = xstrdup (filename);
+  nbfd->filename = bfd_strdup (filename);
+  if (nbfd->filename == NULL)
+    {
+      _bfd_delete_bfd (nbfd);
+      return NULL;
+    }
   nbfd->direction = write_direction;
 
   if (bfd_open_file (nbfd) == NULL)
@@ -700,7 +726,6 @@ _maybe_make_executable (bfd * abfd)
 }
 
 /*
-
 FUNCTION
        bfd_close
 
@@ -708,7 +733,6 @@ SYNOPSIS
        bfd_boolean bfd_close (bfd *abfd);
 
 DESCRIPTION
-
        Close a BFD. If the BFD was open for writing, then pending
        operations are completed and the file written out and closed.
        If the created file is executable, then <<chmod>> is called
@@ -723,29 +747,16 @@ RETURNS
        <<TRUE>> is returned if all is ok, otherwise <<FALSE>>.
 */
 
-
 bfd_boolean
 bfd_close (bfd *abfd)
 {
-  bfd_boolean ret;
-
   if (bfd_write_p (abfd))
     {
       if (! BFD_SEND_FMT (abfd, _bfd_write_contents, (abfd)))
        return FALSE;
     }
 
-  if (! BFD_SEND (abfd, _close_and_cleanup, (abfd)))
-    return FALSE;
-
-  ret = abfd->iovec->bclose (abfd) == 0;
-
-  if (ret)
-    _maybe_make_executable (abfd);
-
-  _bfd_delete_bfd (abfd);
-
-  return ret;
+  return bfd_close_all_done (abfd);
 }
 
 /*
@@ -775,7 +786,10 @@ bfd_close_all_done (bfd *abfd)
 {
   bfd_boolean ret;
 
-  ret = bfd_cache_close (abfd);
+  if (! BFD_SEND (abfd, _close_and_cleanup, (abfd)))
+    return FALSE;
+
+  ret = abfd->iovec->bclose (abfd) == 0;
 
   if (ret)
     _maybe_make_executable (abfd);
@@ -811,7 +825,12 @@ bfd_create (const char *filename, bfd *templ)
     return NULL;
   /* PR 11983: Do not cache the original filename, but
      rather make a copy - the original might go away.  */
-  nbfd->filename = xstrdup (filename);
+  nbfd->filename = bfd_strdup (filename);
+  if (nbfd->filename == NULL)
+    {
+      _bfd_delete_bfd (nbfd);
+      return NULL;
+    }
   if (templ)
     nbfd->xvec = templ->xvec;
   nbfd->direction = no_direction;
@@ -962,32 +981,6 @@ bfd_alloc (bfd *abfd, bfd_size_type size)
   return ret;
 }
 
-/*
-INTERNAL_FUNCTION
-       bfd_alloc2
-
-SYNOPSIS
-       void *bfd_alloc2 (bfd *abfd, bfd_size_type nmemb, bfd_size_type size);
-
-DESCRIPTION
-       Allocate a block of @var{nmemb} elements of @var{size} bytes each
-       of memory attached to <<abfd>> and return a pointer to it.
-*/
-
-void *
-bfd_alloc2 (bfd *abfd, bfd_size_type nmemb, bfd_size_type size)
-{
-  if ((nmemb | size) >= HALF_BFD_SIZE_TYPE
-      && size != 0
-      && nmemb > ~(bfd_size_type) 0 / size)
-    {
-      bfd_set_error (bfd_error_no_memory);
-      return NULL;
-    }
-
-  return bfd_alloc (abfd, size * nmemb);
-}
-
 /*
 FUNCTION
        bfd_zalloc
@@ -1011,39 +1004,6 @@ bfd_zalloc (bfd *abfd, bfd_size_type size)
   return res;
 }
 
-/*
-INTERNAL_FUNCTION
-       bfd_zalloc2
-
-SYNOPSIS
-       void *bfd_zalloc2 (bfd *abfd, bfd_size_type nmemb, bfd_size_type size);
-
-DESCRIPTION
-       Allocate a block of @var{nmemb} elements of @var{size} bytes each
-       of zeroed memory attached to <<abfd>> and return a pointer to it.
-*/
-
-void *
-bfd_zalloc2 (bfd *abfd, bfd_size_type nmemb, bfd_size_type size)
-{
-  void *res;
-
-  if ((nmemb | size) >= HALF_BFD_SIZE_TYPE
-      && size != 0
-      && nmemb > ~(bfd_size_type) 0 / size)
-    {
-      bfd_set_error (bfd_error_no_memory);
-      return NULL;
-    }
-
-  size *= nmemb;
-
-  res = bfd_alloc (abfd, size);
-  if (res)
-    memset (res, 0, (size_t) size);
-  return res;
-}
-
 /* Free a block allocated for a BFD.
    Note:  Also frees all more recently allocated blocks!  */
 
@@ -1157,28 +1117,40 @@ bfd_calc_gnu_debuglink_crc32 (unsigned long crc,
 
 
 /*
-FUNCTION
-       bfd_get_debug_link_info
+INTERNAL_FUNCTION
+       bfd_get_debug_link_info_1
 
 SYNOPSIS
-       char *bfd_get_debug_link_info (bfd *abfd, unsigned long *crc32_out);
+       char *bfd_get_debug_link_info_1 (bfd *abfd, void *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}.  The
-       returned filename is allocated with @code{malloc}; freeing it
-       is the responsibility of the caller.
+       Extracts the filename and CRC32 value for any separate debug
+       information file associated with @var{abfd}.
+
+       The @var{crc32_out} parameter is an untyped pointer because
+       this routine is used as a @code{get_func_type} function, but it
+       is expected to be an unsigned long pointer.
+
+RETURNS
+       The filename of the associated debug information file, or NULL
+       if there is no such file.  If the filename was found then the
+       contents of @var{crc32_out} are updated to hold the corresponding
+       CRC32 value for the file.
+
+       The returned filename is allocated with @code{malloc}; freeing
+       it is the responsibility of the caller.
 */
 
-char *
-bfd_get_debug_link_info (bfd *abfd, unsigned long *crc32_out)
+static char *
+bfd_get_debug_link_info_1 (bfd *abfd, void *crc32_out)
 {
   asection *sect;
-  unsigned long crc32;
+  unsigned long *crc32 = (unsigned long *) crc32_out;
   bfd_byte *contents;
   unsigned int crc_offset;
   char *name;
+  bfd_size_type size;
+  ufile_ptr file_size;
 
   BFD_ASSERT (abfd);
   BFD_ASSERT (crc32_out);
@@ -1188,6 +1160,13 @@ bfd_get_debug_link_info (bfd *abfd, unsigned long *crc32_out)
   if (sect == NULL)
     return NULL;
 
+  size = bfd_section_size (sect);
+  file_size = bfd_get_size (abfd);
+
+  /* PR 22794: Make sure that the section has a reasonable size.  */
+  if (size < 8 || (file_size != 0 && size >= file_size))
+    return NULL;
+
   if (!bfd_malloc_and_get_section (abfd, sect, &contents))
     {
       if (contents != NULL)
@@ -1197,18 +1176,44 @@ bfd_get_debug_link_info (bfd *abfd, unsigned long *crc32_out)
 
   /* CRC value is stored after the filename, aligned up to 4 bytes.  */
   name = (char *) contents;
-  /* PR 17597: avoid reading off the end of the buffer.  */
-  crc_offset = strnlen (name, bfd_get_section_size (sect)) + 1;
+  /* PR 17597: Avoid reading off the end of the buffer.  */
+  crc_offset = strnlen (name, size) + 1;
   crc_offset = (crc_offset + 3) & ~3;
-  if (crc_offset >= bfd_get_section_size (sect))
+  if (crc_offset + 4 > size)
     return NULL;
 
-  crc32 = bfd_get_32 (abfd, contents + crc_offset);
-
-  *crc32_out = crc32;
+  *crc32 = bfd_get_32 (abfd, contents + crc_offset);
   return name;
 }
 
+
+/*
+FUNCTION
+       bfd_get_debug_link_info
+
+SYNOPSIS
+       char *bfd_get_debug_link_info (bfd *abfd, unsigned long *crc32_out);
+
+DESCRIPTION
+       Extracts the filename and CRC32 value for any separate debug
+       information file associated with @var{abfd}.
+
+RETURNS
+       The filename of the associated debug information file, or NULL
+       if there is no such file.  If the filename was found then the
+       contents of @var{crc32_out} are updated to hold the corresponding
+       CRC32 value for the file.
+
+       The returned filename is allocated with @code{malloc}; freeing
+       it is the responsibility of the caller.
+*/
+
+char *
+bfd_get_debug_link_info (bfd *abfd, unsigned long *crc32_out)
+{
+  return bfd_get_debug_link_info_1 (abfd, crc32_out);
+}
+
 /*
 FUNCTION
        bfd_get_alt_debug_link_info
@@ -1216,15 +1221,15 @@ FUNCTION
 SYNOPSIS
        char *bfd_get_alt_debug_link_info (bfd * abfd,
                                           bfd_size_type *buildid_len,
-                                          bfd_byte **buildid_out);
+                                          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.
+       allocated with @code{malloc}; freeing them is the responsibility
+       of the caller.
 */
 
 char *
@@ -1235,6 +1240,8 @@ bfd_get_alt_debug_link_info (bfd * abfd, bfd_size_type *buildid_len,
   bfd_byte *contents;
   unsigned int buildid_offset;
   char *name;
+  bfd_size_type size;
+  ufile_ptr file_size;
 
   BFD_ASSERT (abfd);
   BFD_ASSERT (buildid_len);
@@ -1245,6 +1252,11 @@ bfd_get_alt_debug_link_info (bfd * abfd, bfd_size_type *buildid_len,
   if (sect == NULL)
     return NULL;
 
+  size = bfd_section_size (sect);
+  file_size = bfd_get_size (abfd);
+  if (size < 8 || (file_size != 0 && size >= file_size))
+    return NULL;
+
   if (!bfd_malloc_and_get_section (abfd, sect, & contents))
     {
       if (contents != NULL)
@@ -1254,11 +1266,11 @@ bfd_get_alt_debug_link_info (bfd * abfd, bfd_size_type *buildid_len,
 
   /* BuildID value is stored after the filename.  */
   name = (char *) contents;
-  buildid_offset = strnlen (name, bfd_get_section_size (sect)) + 1;
-  if (buildid_offset >= bfd_get_section_size (sect))
+  buildid_offset = strnlen (name, size) + 1;
+  if (buildid_offset >= bfd_section_size (sect))
     return NULL;
 
-  *buildid_len = bfd_get_section_size (sect) - buildid_offset;
+  *buildid_len = size - buildid_offset;
   *buildid_out = bfd_malloc (*buildid_len);
   memcpy (*buildid_out, contents + buildid_offset, *buildid_len);
 
@@ -1271,24 +1283,32 @@ INTERNAL_FUNCTION
 
 SYNOPSIS
        bfd_boolean separate_debug_file_exists
-         (char *name, unsigned long crc32);
+         (char *name, void *crc32_p);
 
 DESCRIPTION
        Checks to see if @var{name} is a file and if its contents
-       match @var{crc32}.
+       match @var{crc32}, which is a pointer to an @code{unsigned
+       long} containing a CRC32.
+
+       The @var{crc32_p} parameter is an untyped pointer because
+       this routine is used as a @code{check_func_type} function.
 */
 
 static bfd_boolean
-separate_debug_file_exists (const char *name, const unsigned long crc)
+separate_debug_file_exists (const char *name, void *crc32_p)
 {
   static unsigned char buffer [8 * 1024];
   unsigned long file_crc = 0;
   FILE *f;
   bfd_size_type count;
+  unsigned long crc;
 
   BFD_ASSERT (name);
+  BFD_ASSERT (crc32_p);
+
+  crc = *(unsigned long *) crc32_p;
 
-  f = real_fopen (name, FOPEN_RB);
+  f = _bfd_real_fopen (name, FOPEN_RB);
   if (f == NULL)
     return FALSE;
 
@@ -1306,27 +1326,23 @@ INTERNAL_FUNCTION
 
 SYNOPSIS
        bfd_boolean separate_alt_debug_file_exists
-         (char *name, unsigned long buildid);
+         (char *name, void *unused);
 
 DESCRIPTION
-       Checks to see if @var{name} is a file and if its BuildID
-       matches @var{buildid}.
+       Checks to see if @var{name} is a file.
 */
 
 static bfd_boolean
-separate_alt_debug_file_exists (const char *name,
-                               const unsigned long buildid ATTRIBUTE_UNUSED)
+separate_alt_debug_file_exists (const char *name, void *unused ATTRIBUTE_UNUSED)
 {
   FILE *f;
 
   BFD_ASSERT (name);
 
-  f = real_fopen (name, FOPEN_RB);
+  f = _bfd_real_fopen (name, FOPEN_RB);
   if (f == NULL)
     return FALSE;
 
-  /* FIXME: Add code to check buildid.  */
-
   fclose (f);
 
   return TRUE;
@@ -1339,36 +1355,43 @@ INTERNAL_FUNCTION
 SYNOPSIS
        char *find_separate_debug_file
          (bfd *abfd, const char *dir, bfd_boolean include_dirs,
-          get_func_type get, check_func_type check);
+          get_func_type get, check_func_type check, void *data);
 
 DESCRIPTION
        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.
+
+       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.
+
+       @var{data} is passed unmodified to the @var{get} and @var{check}
+       functions.  It is generally used to implement build-id-like
+       matching in the callback functions.
+
+RETURNS
+       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 *);
-typedef bfd_boolean (* check_func_type) (const char *, const unsigned long);
+typedef char *      (* get_func_type) (bfd *, void *);
+typedef bfd_boolean (* check_func_type) (const char *, void *);
 
 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)
+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,
+                         void *          func_data)
 {
   char *base;
   char *dir;
   char *debugfile;
   char *canon_dir;
-  unsigned long crc32;
   size_t dirlen;
   size_t canon_dirlen;
 
@@ -1383,7 +1406,7 @@ find_separate_debug_file (bfd *           abfd,
       return NULL;
     }
 
-  base = get_func (abfd, & crc32);
+  base = get_func (abfd, func_data);
 
   if (base == NULL)
     return NULL;
@@ -1430,20 +1453,20 @@ find_separate_debug_file (bfd *           abfd,
 #endif
 #ifndef EXTRA_DEBUG_ROOT2
 #define EXTRA_DEBUG_ROOT2 "/usr/lib/debug/usr"
-#endif  
+#endif
 
   debugfile = (char *)
       bfd_malloc (strlen (debug_file_directory) + 1
-                  + (canon_dirlen > dirlen ? canon_dirlen : dirlen)
-                  + strlen (".debug/")
+                 + (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);
+                 + strlen (base)
+                 + 1);
   if (debugfile == NULL)
     goto found; /* Actually this returns NULL.  */
 
@@ -1457,19 +1480,19 @@ find_separate_debug_file (bfd *           abfd,
      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))
+  if (check_func (debugfile, func_data))
     goto found;
 
   /* Then try in a subdirectory called .debug.  */
   sprintf (debugfile, "%s.debug/%s", dir, base);
-  if (check_func (debugfile, crc32))
+  if (check_func (debugfile, func_data))
     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))
+  if (check_func (debugfile, func_data))
     goto found;
 #endif
 
@@ -1477,10 +1500,10 @@ find_separate_debug_file (bfd *           abfd,
   /* 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))
+  if (check_func (debugfile, func_data))
     goto found;
 #endif
-  
+
   /* Then try in the global debugfile directory.  */
   strcpy (debugfile, debug_file_directory);
   dirlen = strlen (debug_file_directory) - 1;
@@ -1499,7 +1522,7 @@ find_separate_debug_file (bfd *           abfd,
     }
   strcat (debugfile, base);
 
-  if (check_func (debugfile, crc32))
+  if (check_func (debugfile, func_data))
     goto found;
 
   /* Failed to find the file.  */
@@ -1513,7 +1536,6 @@ find_separate_debug_file (bfd *           abfd,
   return debugfile;
 }
 
-
 /*
 FUNCTION
        bfd_follow_gnu_debuglink
@@ -1522,7 +1544,6 @@ SYNOPSIS
        char *bfd_follow_gnu_debuglink (bfd *abfd, const char *dir);
 
 DESCRIPTION
-
        Takes a BFD and searches it for a .gnu_debuglink section.  If this
        section is found, it examines the section for the name and checksum
        of a '.debug' file containing auxiliary debugging information.  It
@@ -1542,24 +1563,23 @@ RETURNS
 char *
 bfd_follow_gnu_debuglink (bfd *abfd, const char *dir)
 {
+  unsigned long crc32;
+
   return find_separate_debug_file (abfd, dir, TRUE,
-                                  bfd_get_debug_link_info,
-                                  separate_debug_file_exists);
+                                  bfd_get_debug_link_info_1,
+                                  separate_debug_file_exists, &crc32);
 }
 
-/* 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.  */
+/* Helper for bfd_follow_gnu_debugaltlink.  It just returns the name
+   of the separate debug file.  */
 
 static char *
-get_alt_debug_link_info_shim (bfd * abfd, unsigned long *crc32_out)
+get_alt_debug_link_info_shim (bfd * abfd, void *unused ATTRIBUTE_UNUSED)
 {
   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;
@@ -1573,7 +1593,6 @@ 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
@@ -1595,7 +1614,8 @@ bfd_follow_gnu_debugaltlink (bfd *abfd, const char *dir)
 {
   return find_separate_debug_file (abfd, dir, TRUE,
                                   get_alt_debug_link_info_shim,
-                                  separate_alt_debug_file_exists);
+                                  separate_alt_debug_file_exists,
+                                  NULL);
 }
 
 /*
@@ -1607,13 +1627,13 @@ SYNOPSIS
          (bfd *abfd, const char *filename);
 
 DESCRIPTION
-
-       Takes a @var{BFD} and adds a .gnu_debuglink section to it.  The section is sized
-       to be big enough to contain a link to the specified @var{filename}.
+       Takes a @var{BFD} and adds a .gnu_debuglink section to it.  The
+       section is sized to be big enough to contain a link to the specified
+       @var{filename}.
 
 RETURNS
-       A pointer to the new section is returned if all is ok.  Otherwise <<NULL>> is
-       returned and bfd_error is set.
+       A pointer to the new section is returned if all is ok.  Otherwise
+       <<NULL>> is returned and bfd_error is set.
 */
 
 asection *
@@ -1645,15 +1665,22 @@ bfd_create_gnu_debuglink_section (bfd *abfd, const char *filename)
   if (sect == NULL)
     return NULL;
 
+  /* Compute the size of the section.  Allow for the CRC after the filename,
+     and padding so that it will start on a 4-byte boundary.  */
   debuglink_size = strlen (filename) + 1;
   debuglink_size += 3;
   debuglink_size &= ~3;
   debuglink_size += 4;
 
-  if (! bfd_set_section_size (abfd, sect, debuglink_size))
+  if (!bfd_set_section_size (sect, debuglink_size))
     /* XXX Should we delete the section from the bfd ?  */
     return NULL;
 
+  /* PR 21193: Ensure that the section has 4-byte alignment for the CRC.
+     Note - despite the name of the function being called, we are
+     setting an alignment power, not a byte alignment value.  */
+  bfd_set_section_alignment (sect, 2);
+
   return sect;
 }
 
@@ -1667,7 +1694,6 @@ SYNOPSIS
          (bfd *abfd, struct bfd_section *sect, const char *filename);
 
 DESCRIPTION
-
        Takes a @var{BFD} and containing a .gnu_debuglink section @var{SECT}
        and fills in the contents of the section to contain a link to the
        specified @var{filename}.  The filename should be relative to the
@@ -1704,7 +1730,7 @@ bfd_fill_in_gnu_debuglink_section (bfd *abfd,
      .gnu_debuglink section, we insist upon the user providing us with a
      correct-for-section-creation-time path, but this need not conform to
      the gdb location algorithm.  */
-  handle = real_fopen (filename, FOPEN_RB);
+  handle = _bfd_real_fopen (filename, FOPEN_RB);
   if (handle == NULL)
     {
       bfd_set_error (bfd_error_system_call);
@@ -1754,8 +1780,7 @@ INTERNAL_FUNCTION
        get_build_id
 
 SYNOPSIS
-       struct bfd_build_id * get_build_id
-         (bfd *abfd);
+       struct bfd_build_id * get_build_id (bfd *abfd);
 
 DESCRIPTION
        Finds the build-id associated with @var{abfd}.  If the build-id is
@@ -1763,6 +1788,7 @@ DESCRIPTION
        for it, using memory allocated to @var{abfd}, and this is then
        attached to the @var{abfd}.
 
+RETURNS
        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.
@@ -1776,6 +1802,7 @@ get_build_id (bfd *abfd)
   Elf_External_Note *enote;
   bfd_byte *contents;
   asection *sect;
+  bfd_size_type size;
 
   BFD_ASSERT (abfd);
 
@@ -1790,8 +1817,9 @@ get_build_id (bfd *abfd)
       return NULL;
     }
 
+  size = bfd_section_size (sect);
   /* FIXME: Should we support smaller build-id notes ?  */
-  if (bfd_get_section_size (sect) < 0x24)
+  if (size < 0x24)
     {
       bfd_set_error (bfd_error_invalid_operation);
       return NULL;
@@ -1804,6 +1832,17 @@ get_build_id (bfd *abfd)
       return NULL;
     }
 
+  /* FIXME: Paranoia - allow for compressed build-id sections.
+     Maybe we should complain if this size is different from
+     the one obtained above...  */
+  size = bfd_section_size (sect);
+  if (size < sizeof (Elf_External_Note))
+    {
+      bfd_set_error (bfd_error_invalid_operation);
+      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);
@@ -1811,11 +1850,13 @@ get_build_id (bfd *abfd)
   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
+
+  if (inote.descsz <= 0
       || inote.type != NT_GNU_BUILD_ID
       || inote.namesz != 4 /* sizeof "GNU"  */
-      || strcmp (inote.namedata, "GNU") != 0)
+      || strncmp (inote.namedata, "GNU", 4) != 0
+      || inote.descsz > 0x7ffffffe
+      || size < (12 + BFD_ALIGN (inote.namesz, 4) + inote.descsz))
     {
       free (contents);
       bfd_set_error (bfd_error_invalid_operation);
@@ -1842,24 +1883,26 @@ INTERNAL_FUNCTION
        get_build_id_name
 
 SYNOPSIS
-       char * get_build_id_name
-         (bfd *abfd, unsigned long *build_id_out)
+       char * get_build_id_name (bfd *abfd, void *build_id_out_p)
 
 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
        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.
+       If a filename is returned then the @var{build_id_out_p}
+       parameter (which points to a @code{struct bfd_build_id}
+       pointer) is set to a pointer to the build_id structure.
 */
 
 static char *
-get_build_id_name (bfd *abfd, unsigned long *build_id_out)
+get_build_id_name (bfd *abfd, void *build_id_out_p)
 {
+  struct bfd_build_id **build_id_out = build_id_out_p;
   struct bfd_build_id *build_id;
   char *name;
   char *n;
@@ -1894,7 +1937,7 @@ get_build_id_name (bfd *abfd, unsigned long *build_id_out)
     n += sprintf (n, "%02x", (unsigned) *d++);
   n += sprintf (n, ".debug");
 
-  * build_id_out = (unsigned long) build_id;
+  *build_id_out = build_id;
   return name;
 }
 
@@ -1903,20 +1946,20 @@ INTERNAL_FUNCTION
        check_build_id_file
 
 SYNOPSIS
-       bfd_boolean check_build_id_file
-         (char *name, unsigned long buildid);
+       bfd_boolean check_build_id_file (char *name, void *buildid_p);
 
 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}.
+RETURNS
+       Returns TRUE if the file exists, is readable, and contains a
+       build-id which matches the build-id pointed at by
+       @var{build_id_p} (which is really a @code{struct bfd_build_id **}).
 */
 
 static bfd_boolean
-check_build_id_file (const char *name,
-                    const unsigned long buildid)
+check_build_id_file (const char *name, void *buildid_p)
 {
   struct bfd_build_id *orig_build_id;
   struct bfd_build_id *build_id;
@@ -1924,7 +1967,7 @@ check_build_id_file (const char *name,
   bfd_boolean result;
 
   BFD_ASSERT (name);
-  BFD_ASSERT (buildid);
+  BFD_ASSERT (buildid_p);
 
   file = bfd_openr (name, NULL);
   if (file == NULL)
@@ -1936,7 +1979,7 @@ check_build_id_file (const char *name,
       bfd_close (file);
       return FALSE;
     }
-  
+
   build_id = get_build_id (file);
   if (build_id == NULL)
     {
@@ -1944,7 +1987,7 @@ check_build_id_file (const char *name,
       return FALSE;
     }
 
-  orig_build_id = (struct bfd_build_id *) buildid;
+  orig_build_id = *(struct bfd_build_id **) buildid_p;
 
   result = build_id->size == orig_build_id->size
     && memcmp (build_id->data, orig_build_id->data, build_id->size) == 0;
@@ -1962,7 +2005,6 @@ 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
@@ -1986,7 +2028,29 @@ RETURNS
 char *
 bfd_follow_build_id_debuglink (bfd *abfd, const char *dir)
 {
+  struct bfd_build_id *build_id;
+
   return find_separate_debug_file (abfd, dir, FALSE,
                                   get_build_id_name,
-                                  check_build_id_file);
+                                  check_build_id_file, &build_id);
+}
+
+/*
+FUNCTION
+       bfd_set_filename
+
+SYNOPSIS
+       void bfd_set_filename (bfd *abfd, char *filename);
+
+DESCRIPTION
+       Set the filename of @var{abfd}.  The old filename, if any, is freed.
+       @var{filename} must be allocated using @code{xmalloc}.  After
+       this call, it is owned @var{abfd}.
+*/
+
+void
+bfd_set_filename (bfd *abfd, char *filename)
+{
+  free ((char *) abfd->filename);
+  abfd->filename = filename;
 }
This page took 0.035672 seconds and 4 git commands to generate.