]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blobdiff - bfd/opncls.c
Fix a conflict between the linker's need to rename some PE format input libraries...
[thirdparty/binutils-gdb.git] / bfd / opncls.c
index 073a37f8d4557dfd3206b2a363fbb064c42f1c95..a5bc2de3648135e2a304041b169c7c1d827f1b87 100644 (file)
@@ -1,5 +1,5 @@
 /* opncls.c -- open and close a BFD.
-   Copyright (C) 1990-2017 Free Software Foundation, Inc.
+   Copyright (C) 1990-2022 Free Software Foundation, Inc.
 
    Written by Cygnus Support.
 
@@ -84,10 +84,13 @@ _bfd_new_bfd (void)
   if (!bfd_hash_table_init_n (& nbfd->section_htab, bfd_section_hash_newfunc,
                              sizeof (struct section_hash_entry), 13))
     {
+      objalloc_free ((struct objalloc *) nbfd->memory);
       free (nbfd);
       return NULL;
     }
 
+  nbfd->archive_plugin_fd = -1;
+
   return nbfd;
 }
 
@@ -125,20 +128,43 @@ _bfd_delete_bfd (bfd *abfd)
       bfd_hash_table_free (&abfd->section_htab);
       objalloc_free ((struct objalloc *) abfd->memory);
     }
+  else
+    free ((char *) bfd_get_filename (abfd));
 
-  if (abfd->filename)
-    free ((char *) abfd->filename);
   free (abfd->arelt_data);
   free (abfd);
 }
 
 /* Free objalloc memory.  */
 
-bfd_boolean
+bool
 _bfd_free_cached_info (bfd *abfd)
 {
   if (abfd->memory)
     {
+      const char *filename = bfd_get_filename (abfd);
+      if (filename)
+       {
+         /* We can't afford to lose the bfd filename when freeing
+            abfd->memory, because that would kill the cache.c scheme
+            of closing and reopening files in order to limit the
+            number of open files.  To reopen, you need the filename.
+            And indeed _bfd_compute_and_write_armap calls
+            _bfd_free_cached_info to free up space used by symbols
+            and by check_format_matches.  Which we want to continue
+            doing to handle very large archives.  Later the archive
+            elements are copied, which might require reopening files.
+            We also want to keep using objalloc memory for the
+            filename since that allows the name to be updated
+            without either leaking memory or implementing some sort
+            of reference counted string for copies of the filename.  */
+         size_t len = strlen (filename) + 1;
+         char *copy = bfd_malloc (len);
+         if (copy == NULL)
+           return false;
+         memcpy (copy, filename, len);
+         abfd->filename = copy;
+       }
       bfd_hash_table_free (&abfd->section_htab);
       objalloc_free ((struct objalloc *) abfd->memory);
 
@@ -150,7 +176,7 @@ _bfd_free_cached_info (bfd *abfd)
       abfd->memory = NULL;
     }
 
-  return TRUE;
+  return true;
 }
 
 /*
@@ -223,6 +249,8 @@ bfd_fopen (const char *filename, const char *target, const char *mode, int fd)
   if (nbfd->iostream == NULL)
     {
       bfd_set_error (bfd_error_system_call);
+      if (fd != -1)
+       close (fd);
       _bfd_delete_bfd (nbfd);
       return NULL;
     }
@@ -231,7 +259,12 @@ 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);
+  if (!bfd_set_filename (nbfd, filename))
+    {
+      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,19 +276,20 @@ 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;
     }
-  nbfd->opened_once = TRUE;
+  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)
-    (void) bfd_set_cacheable (nbfd, TRUE);
+    (void) bfd_set_cacheable (nbfd, true);
 
   return nbfd;
 }
@@ -361,6 +395,39 @@ bfd_fdopenr (const char *filename, const char *target, int fd)
   return bfd_fopen (filename, target, mode, fd);
 }
 
+/*
+FUNCTION
+       bfd_fdopenw
+
+SYNOPSIS
+       bfd *bfd_fdopenw (const char *filename, const char *target, int fd);
+
+DESCRIPTION
+       <<bfd_fdopenw>> is exactly like <<bfd_fdopenr>> with the exception that
+       the resulting BFD is suitable for output.
+*/
+
+bfd *
+bfd_fdopenw (const char *filename, const char *target, int fd)
+{
+  bfd *out = bfd_fdopenr (filename, target, fd);
+
+  if (out != NULL)
+    {
+      if (!bfd_write_p (out))
+       {
+         close (fd);
+         _bfd_delete_bfd (out);
+         out = NULL;
+         bfd_set_error (bfd_error_invalid_operation);
+       }
+      else
+       out->direction = write_direction;
+    }
+
+  return out;
+}
+
 /*
 FUNCTION
        bfd_openstreamr
@@ -398,7 +465,11 @@ 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);
+  if (!bfd_set_filename (nbfd, filename))
+    {
+      _bfd_delete_bfd (nbfd);
+      return NULL;
+    }
   nbfd->direction = read_direction;
 
   if (! bfd_cache_init (nbfd))
@@ -594,7 +665,11 @@ 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);
+  if (!bfd_set_filename (nbfd, filename))
+    {
+      _bfd_delete_bfd (nbfd);
+      return NULL;
+    }
   nbfd->direction = read_direction;
 
   /* `open_p (...)' would get expanded by an the open(2) syscall macro.  */
@@ -661,7 +736,11 @@ 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);
+  if (!bfd_set_filename (nbfd, filename))
+    {
+      _bfd_delete_bfd (nbfd);
+      return NULL;
+    }
   nbfd->direction = write_direction;
 
   if (bfd_open_file (nbfd) == NULL)
@@ -685,7 +764,7 @@ _maybe_make_executable (bfd * abfd)
     {
       struct stat buf;
 
-      if (stat (abfd->filename, &buf) == 0
+      if (stat (bfd_get_filename (abfd), &buf) == 0
          /* Do not attempt to change non-regular files.  This is
             here especially for configure scripts and kernel builds
             which run tests with "ld [...] -o /dev/null".  */
@@ -694,7 +773,7 @@ _maybe_make_executable (bfd * abfd)
          unsigned int mask = umask (0);
 
          umask (mask);
-         chmod (abfd->filename,
+         chmod (bfd_get_filename (abfd),
                 (0777
                  & (buf.st_mode | ((S_IXUSR | S_IXGRP | S_IXOTH) &~ mask))));
        }
@@ -706,7 +785,7 @@ FUNCTION
        bfd_close
 
 SYNOPSIS
-       bfd_boolean bfd_close (bfd *abfd);
+       bool bfd_close (bfd *abfd);
 
 DESCRIPTION
        Close a BFD. If the BFD was open for writing, then pending
@@ -723,13 +802,13 @@ RETURNS
        <<TRUE>> is returned if all is ok, otherwise <<FALSE>>.
 */
 
-bfd_boolean
+bool
 bfd_close (bfd *abfd)
 {
   if (bfd_write_p (abfd))
     {
       if (! BFD_SEND_FMT (abfd, _bfd_write_contents, (abfd)))
-       return FALSE;
+       return false;
     }
 
   return bfd_close_all_done (abfd);
@@ -740,7 +819,7 @@ FUNCTION
        bfd_close_all_done
 
 SYNOPSIS
-       bfd_boolean bfd_close_all_done (bfd *);
+       bool bfd_close_all_done (bfd *);
 
 DESCRIPTION
        Close a BFD.  Differs from <<bfd_close>> since it does not
@@ -757,13 +836,13 @@ RETURNS
        <<TRUE>> is returned if all is ok, otherwise <<FALSE>>.
 */
 
-bfd_boolean
+bool
 bfd_close_all_done (bfd *abfd)
 {
-  bfd_boolean ret;
+  bool ret;
 
   if (! BFD_SEND (abfd, _close_and_cleanup, (abfd)))
-    return FALSE;
+    return false;
 
   ret = abfd->iovec->bclose (abfd) == 0;
 
@@ -801,7 +880,11 @@ 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);
+  if (!bfd_set_filename (nbfd, filename))
+    {
+      _bfd_delete_bfd (nbfd);
+      return NULL;
+    }
   if (templ)
     nbfd->xvec = templ->xvec;
   nbfd->direction = no_direction;
@@ -815,7 +898,7 @@ FUNCTION
        bfd_make_writable
 
 SYNOPSIS
-       bfd_boolean bfd_make_writable (bfd *abfd);
+       bool bfd_make_writable (bfd *abfd);
 
 DESCRIPTION
        Takes a BFD as created by <<bfd_create>> and converts it
@@ -827,7 +910,7 @@ RETURNS
        <<TRUE>> is returned if all is ok, otherwise <<FALSE>>.
 */
 
-bfd_boolean
+bool
 bfd_make_writable (bfd *abfd)
 {
   struct bfd_in_memory *bim;
@@ -835,12 +918,12 @@ bfd_make_writable (bfd *abfd)
   if (abfd->direction != no_direction)
     {
       bfd_set_error (bfd_error_invalid_operation);
-      return FALSE;
+      return false;
     }
 
   bim = (struct bfd_in_memory *) bfd_malloc (sizeof (struct bfd_in_memory));
   if (bim == NULL)
-    return FALSE;      /* bfd_error already set.  */
+    return false;      /* bfd_error already set.  */
   abfd->iostream = bim;
   /* bfd_bwrite will grow these as needed.  */
   bim->size = 0;
@@ -852,7 +935,7 @@ bfd_make_writable (bfd *abfd)
   abfd->direction = write_direction;
   abfd->where = 0;
 
-  return TRUE;
+  return true;
 }
 
 /*
@@ -860,7 +943,7 @@ FUNCTION
        bfd_make_readable
 
 SYNOPSIS
-       bfd_boolean bfd_make_readable (bfd *abfd);
+       bool bfd_make_readable (bfd *abfd);
 
 DESCRIPTION
        Takes a BFD as created by <<bfd_create>> and
@@ -872,20 +955,20 @@ DESCRIPTION
 RETURNS
        <<TRUE>> is returned if all is ok, otherwise <<FALSE>>.  */
 
-bfd_boolean
+bool
 bfd_make_readable (bfd *abfd)
 {
   if (abfd->direction != write_direction || !(abfd->flags & BFD_IN_MEMORY))
     {
       bfd_set_error (bfd_error_invalid_operation);
-      return FALSE;
+      return false;
     }
 
   if (! BFD_SEND_FMT (abfd, _bfd_write_contents, (abfd)))
-    return FALSE;
+    return false;
 
   if (! BFD_SEND (abfd, _close_and_cleanup, (abfd)))
-    return FALSE;
+    return false;
 
   abfd->arch_info = &bfd_default_arch_struct;
 
@@ -893,15 +976,15 @@ bfd_make_readable (bfd *abfd)
   abfd->format = bfd_unknown;
   abfd->my_archive = NULL;
   abfd->origin = 0;
-  abfd->opened_once = FALSE;
-  abfd->output_has_begun = FALSE;
+  abfd->opened_once = false;
+  abfd->output_has_begun = false;
   abfd->section_count = 0;
   abfd->usrdata = NULL;
-  abfd->cacheable = FALSE;
+  abfd->cacheable = false;
   abfd->flags |= BFD_IN_MEMORY;
-  abfd->mtime_set = FALSE;
+  abfd->mtime_set = false;
 
-  abfd->target_defaulted = TRUE;
+  abfd->target_defaulted = true;
   abfd->direction = read_direction;
   abfd->sections = 0;
   abfd->symcount = 0;
@@ -911,7 +994,7 @@ bfd_make_readable (bfd *abfd)
   bfd_section_list_clear (abfd);
   bfd_check_format (abfd, bfd_object);
 
-  return TRUE;
+  return true;
 }
 
 /*
@@ -949,35 +1032,11 @@ bfd_alloc (bfd *abfd, bfd_size_type size)
   ret = objalloc_alloc ((struct objalloc *) abfd->memory, ul_size);
   if (ret == NULL)
     bfd_set_error (bfd_error_no_memory);
+  else
+    abfd->alloc_size += 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
@@ -1001,39 +1060,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!  */
 
@@ -1179,6 +1205,8 @@ bfd_get_debug_link_info_1 (bfd *abfd, void *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,19 +1216,25 @@ bfd_get_debug_link_info_1 (bfd *abfd, void *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)
-       free (contents);
+      free (contents);
       return NULL;
     }
 
   /* 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 + 4 > bfd_get_section_size (sect))
+  if (crc_offset + 4 > size)
     return NULL;
 
   *crc32 = bfd_get_32 (abfd, contents + crc_offset);
@@ -1261,6 +1295,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);
@@ -1271,20 +1307,24 @@ 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)
-       free (contents);
+      free (contents);
       return NULL;
     }
 
   /* 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);
 
@@ -1296,7 +1336,7 @@ INTERNAL_FUNCTION
        separate_debug_file_exists
 
 SYNOPSIS
-       bfd_boolean separate_debug_file_exists
+       bool separate_debug_file_exists
          (char *name, void *crc32_p);
 
 DESCRIPTION
@@ -1308,10 +1348,10 @@ DESCRIPTION
        this routine is used as a @code{check_func_type} function.
 */
 
-static bfd_boolean
+static bool
 separate_debug_file_exists (const char *name, void *crc32_p)
 {
-  static unsigned char buffer [8 * 1024];
+  unsigned char buffer[8 * 1024];
   unsigned long file_crc = 0;
   FILE *f;
   bfd_size_type count;
@@ -1324,7 +1364,7 @@ separate_debug_file_exists (const char *name, void *crc32_p)
 
   f = _bfd_real_fopen (name, FOPEN_RB);
   if (f == NULL)
-    return FALSE;
+    return false;
 
   while ((count = fread (buffer, 1, sizeof (buffer), f)) > 0)
     file_crc = bfd_calc_gnu_debuglink_crc32 (file_crc, buffer, count);
@@ -1339,14 +1379,14 @@ INTERNAL_FUNCTION
        separate_alt_debug_file_exists
 
 SYNOPSIS
-       bfd_boolean separate_alt_debug_file_exists
+       bool separate_alt_debug_file_exists
          (char *name, void *unused);
 
 DESCRIPTION
        Checks to see if @var{name} is a file.
 */
 
-static bfd_boolean
+static bool
 separate_alt_debug_file_exists (const char *name, void *unused ATTRIBUTE_UNUSED)
 {
   FILE *f;
@@ -1355,11 +1395,11 @@ separate_alt_debug_file_exists (const char *name, void *unused ATTRIBUTE_UNUSED)
 
   f = _bfd_real_fopen (name, FOPEN_RB);
   if (f == NULL)
-    return FALSE;
+    return false;
 
   fclose (f);
 
-  return TRUE;
+  return true;
 }
 
 /*
@@ -1368,7 +1408,7 @@ INTERNAL_FUNCTION
 
 SYNOPSIS
        char *find_separate_debug_file
-         (bfd *abfd, const char *dir, bfd_boolean include_dirs,
+         (bfd *abfd, const char *dir, bool include_dirs,
           get_func_type get, check_func_type check, void *data);
 
 DESCRIPTION
@@ -1391,16 +1431,16 @@ RETURNS
        Returns NULL if no valid file could be found.
 */
 
-typedef char *      (* get_func_type) (bfd *, void *);
-typedef bfd_boolean (* check_func_type) (const char *, void *);
+typedef char * (*get_func_type) (bfd *, void *);
+typedef bool (*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,
+find_separate_debug_file (bfd *abfd,
+                         const char *debug_file_directory,
+                         bool include_dirs,
+                         get_func_type get_func,
                          check_func_type check_func,
-                         void *          func_data)
+                         void *func_data)
 {
   char *base;
   char *dir;
@@ -1414,7 +1454,7 @@ find_separate_debug_file (bfd *             abfd,
     debug_file_directory = ".";
 
   /* BFD may have been opened from a stream.  */
-  if (abfd->filename == NULL)
+  if (bfd_get_filename (abfd) == NULL)
     {
       bfd_set_error (bfd_error_invalid_operation);
       return NULL;
@@ -1434,8 +1474,9 @@ find_separate_debug_file (bfd *             abfd,
 
   if (include_dirs)
     {
-      for (dirlen = strlen (abfd->filename); dirlen > 0; dirlen--)
-       if (IS_DIR_SEPARATOR (abfd->filename[dirlen - 1]))
+      const char *fname = bfd_get_filename (abfd);
+      for (dirlen = strlen (fname); dirlen > 0; dirlen--)
+       if (IS_DIR_SEPARATOR (fname[dirlen - 1]))
          break;
 
       dir = (char *) bfd_malloc (dirlen + 1);
@@ -1444,7 +1485,7 @@ find_separate_debug_file (bfd *             abfd,
          free (base);
          return NULL;
        }
-      memcpy (dir, abfd->filename, dirlen);
+      memcpy (dir, fname, dirlen);
       dir[dirlen] = '\0';
     }
   else
@@ -1456,7 +1497,7 @@ find_separate_debug_file (bfd *             abfd,
 
   /* Compute the canonical name of the bfd object with all symbolic links
      resolved, for use in the global debugfile directory.  */
-  canon_dir = lrealpath (abfd->filename);
+  canon_dir = lrealpath (bfd_get_filename (abfd));
   for (canon_dirlen = strlen (canon_dir); canon_dirlen > 0; canon_dirlen--)
     if (IS_DIR_SEPARATOR (canon_dir[canon_dirlen - 1]))
       break;
@@ -1579,7 +1620,7 @@ bfd_follow_gnu_debuglink (bfd *abfd, const char *dir)
 {
   unsigned long crc32;
 
-  return find_separate_debug_file (abfd, dir, TRUE,
+  return find_separate_debug_file (abfd, dir, true,
                                   bfd_get_debug_link_info_1,
                                   separate_debug_file_exists, &crc32);
 }
@@ -1626,7 +1667,7 @@ RETURNS
 char *
 bfd_follow_gnu_debugaltlink (bfd *abfd, const char *dir)
 {
-  return find_separate_debug_file (abfd, dir, TRUE,
+  return find_separate_debug_file (abfd, dir, true,
                                   get_alt_debug_link_info_shim,
                                   separate_alt_debug_file_exists,
                                   NULL);
@@ -1686,14 +1727,14 @@ bfd_create_gnu_debuglink_section (bfd *abfd, const char *filename)
   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 (abfd, sect, 2);
+  bfd_set_section_alignment (sect, 2);
 
   return sect;
 }
@@ -1704,7 +1745,7 @@ FUNCTION
        bfd_fill_in_gnu_debuglink_section
 
 SYNOPSIS
-       bfd_boolean bfd_fill_in_gnu_debuglink_section
+       bool bfd_fill_in_gnu_debuglink_section
          (bfd *abfd, struct bfd_section *sect, const char *filename);
 
 DESCRIPTION
@@ -1718,7 +1759,7 @@ RETURNS
        and bfd_error is set.
 */
 
-bfd_boolean
+bool
 bfd_fill_in_gnu_debuglink_section (bfd *abfd,
                                   struct bfd_section *sect,
                                   const char *filename)
@@ -1728,14 +1769,14 @@ bfd_fill_in_gnu_debuglink_section (bfd *abfd,
   char * contents;
   bfd_size_type crc_offset;
   FILE * handle;
-  static unsigned char buffer[8 * 1024];
+  unsigned char buffer[8 * 1024];
   size_t count;
   size_t filelen;
 
   if (abfd == NULL || sect == NULL || filename == NULL)
     {
       bfd_set_error (bfd_error_invalid_operation);
-      return FALSE;
+      return false;
     }
 
   /* Make sure that we can read the file.
@@ -1748,7 +1789,7 @@ bfd_fill_in_gnu_debuglink_section (bfd *abfd,
   if (handle == NULL)
     {
       bfd_set_error (bfd_error_system_call);
-      return FALSE;
+      return false;
     }
 
   crc32 = 0;
@@ -1770,7 +1811,7 @@ bfd_fill_in_gnu_debuglink_section (bfd *abfd,
   if (contents == NULL)
     {
       /* XXX Should we delete the section from the bfd ?  */
-      return FALSE;
+      return false;
     }
 
   crc_offset = debuglink_size - 4;
@@ -1783,10 +1824,10 @@ bfd_fill_in_gnu_debuglink_section (bfd *abfd,
     {
       /* XXX Should we delete the section from the bfd ?  */
       free (contents);
-      return FALSE;
+      return false;
     }
 
-  return TRUE;
+  return true;
 }
 
 /*
@@ -1831,7 +1872,7 @@ get_build_id (bfd *abfd)
       return NULL;
     }
 
-  size = bfd_get_section_size (sect);
+  size = bfd_section_size (sect);
   /* FIXME: Should we support smaller build-id notes ?  */
   if (size < 0x24)
     {
@@ -1841,15 +1882,14 @@ get_build_id (bfd *abfd)
 
   if (!bfd_malloc_and_get_section (abfd, sect, & contents))
     {
-      if (contents != NULL)
-       free (contents);
+      free (contents);
       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_get_section_size (sect);
+  size = bfd_section_size (sect);
   if (size < sizeof (Elf_External_Note))
     {
       bfd_set_error (bfd_error_invalid_operation);
@@ -1865,10 +1905,11 @@ get_build_id (bfd *abfd)
   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"  */
-      || strncmp (inote.namedata, "GNU", 4) != 0
+      || !startswith (inote.namedata, "GNU")
+      || inote.descsz > 0x7ffffffe
       || size < (12 + BFD_ALIGN (inote.namesz, 4) + inote.descsz))
     {
       free (contents);
@@ -1922,7 +1963,7 @@ get_build_id_name (bfd *abfd, void *build_id_out_p)
   bfd_size_type s;
   bfd_byte *d;
 
-  if (abfd == NULL || abfd->filename == NULL || build_id_out == NULL)
+  if (abfd == NULL || bfd_get_filename (abfd) == NULL || build_id_out == NULL)
     {
       bfd_set_error (bfd_error_invalid_operation);
       return NULL;
@@ -1959,7 +2000,7 @@ INTERNAL_FUNCTION
        check_build_id_file
 
 SYNOPSIS
-       bfd_boolean check_build_id_file (char *name, void *buildid_p);
+       bool 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
@@ -1971,33 +2012,33 @@ RETURNS
        @var{build_id_p} (which is really a @code{struct bfd_build_id **}).
 */
 
-static bfd_boolean
+static bool
 check_build_id_file (const char *name, void *buildid_p)
 {
   struct bfd_build_id *orig_build_id;
   struct bfd_build_id *build_id;
   bfd * file;
-  bfd_boolean result;
+  bool result;
 
   BFD_ASSERT (name);
   BFD_ASSERT (buildid_p);
 
   file = bfd_openr (name, NULL);
   if (file == NULL)
-    return FALSE;
+    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;
+      return false;
     }
 
   build_id = get_build_id (file);
   if (build_id == NULL)
     {
       bfd_close (file);
-      return FALSE;
+      return false;
     }
 
   orig_build_id = *(struct bfd_build_id **) buildid_p;
@@ -2043,7 +2084,51 @@ bfd_follow_build_id_debuglink (bfd *abfd, const char *dir)
 {
   struct bfd_build_id *build_id;
 
-  return find_separate_debug_file (abfd, dir, FALSE,
+  return find_separate_debug_file (abfd, dir, false,
                                   get_build_id_name,
                                   check_build_id_file, &build_id);
 }
+
+/*
+FUNCTION
+       bfd_set_filename
+
+SYNOPSIS
+       const char *bfd_set_filename (bfd *abfd, const char *filename);
+
+DESCRIPTION
+       Set the filename of @var{abfd}, copying the FILENAME parameter to
+       bfd_alloc'd memory owned by @var{abfd}.  Returns a pointer the
+       newly allocated name, or NULL if the allocation failed.
+*/
+
+const char *
+bfd_set_filename (bfd *abfd, const char *filename)
+{
+  size_t len = strlen (filename) + 1;
+  char *n = bfd_alloc (abfd, len);
+
+  if (n == NULL)
+    return NULL;
+
+  if (abfd->filename != NULL)
+    {
+      /* PR 29389.  If we attempt to rename a file that has been closed due
+        to caching, then we will not be able to reopen it later on.  */
+      if (abfd->iostream == NULL && (abfd->flags & BFD_CLOSED_BY_CACHE))
+       {
+         bfd_set_error (bfd_error_invalid_operation);
+         return NULL;
+       }
+
+      /* Similarly if we attempt to close a renamed file because the
+        cache is now full, we will not be able to reopen it later on.  */
+      if (abfd->iostream != NULL)
+       abfd->cacheable = 0;
+    }
+
+  memcpy (n, filename, len);
+  abfd->filename = n;
+
+  return n;
+}