Make bfd_byte an int8_t, flagword a uint32_t
[binutils-gdb.git] / bfd / opncls.c
index f0ca9048f68e270f04b1df6a60fd536ac20e5136..81e124457e991f505ba56cafe8284155af52b8fe 100644 (file)
@@ -1,5 +1,5 @@
 /* opncls.c -- open and close a BFD.
-   Copyright (C) 1990-2022 Free Software Foundation, Inc.
+   Copyright (C) 1990-2023 Free Software Foundation, Inc.
 
    Written by Cygnus Support.
 
 #define S_IXOTH 0001   /* Execute by others.  */
 #endif
 
+/*
+SECTION
+       Opening and closing BFDs
+
+SUBSECTION
+       Functions for opening and closing
+*/
+
 /* Counters used to initialize the bfd identifier.  */
 
 static unsigned int bfd_id_counter = 0;
@@ -103,6 +111,12 @@ _bfd_new_bfd_contained_in (bfd *obfd)
 {
   bfd *nbfd;
 
+  /* Nested archives in bims are unsupported.  */
+  if ((obfd->flags & BFD_IN_MEMORY) != 0)
+    {
+      bfd_set_error (bfd_error_malformed_archive);
+      return NULL;
+    }
   nbfd = _bfd_new_bfd ();
   if (nbfd == NULL)
     return NULL;
@@ -179,14 +193,6 @@ _bfd_free_cached_info (bfd *abfd)
   return true;
 }
 
-/*
-SECTION
-       Opening and closing BFDs
-
-SUBSECTION
-       Functions for opening and closing
-*/
-
 /*
 FUNCTION
        bfd_fopen
@@ -798,20 +804,16 @@ DESCRIPTION
        The file descriptor associated with the BFD is closed (even
        if it was passed in to BFD by <<bfd_fdopenr>>).
 
-RETURNS
        <<TRUE>> is returned if all is ok, otherwise <<FALSE>>.
 */
 
 bool
 bfd_close (bfd *abfd)
 {
-  if (bfd_write_p (abfd))
-    {
-      if (! BFD_SEND_FMT (abfd, _bfd_write_contents, (abfd)))
-       return false;
-    }
+  bool ret = (!bfd_write_p (abfd)
+             || BFD_SEND_FMT (abfd, _bfd_write_contents, (abfd)));
 
-  return bfd_close_all_done (abfd);
+  return bfd_close_all_done (abfd) && ret;
 }
 
 /*
@@ -832,22 +834,21 @@ DESCRIPTION
 
        All memory attached to the BFD is released.
 
-RETURNS
        <<TRUE>> is returned if all is ok, otherwise <<FALSE>>.
 */
 
 bool
 bfd_close_all_done (bfd *abfd)
 {
-  bool ret;
-
-  if (! BFD_SEND (abfd, _close_and_cleanup, (abfd)))
-    return false;
+  bool ret = BFD_SEND (abfd, _close_and_cleanup, (abfd));
 
-  ret = abfd->iovec->bclose (abfd) == 0;
+  if (ret && abfd->iovec != NULL)
+    {
+      ret = abfd->iovec->bclose (abfd) == 0;
 
-  if (ret)
-    _maybe_make_executable (abfd);
+      if (ret)
+       _maybe_make_executable (abfd);
+    }
 
   _bfd_delete_bfd (abfd);
 
@@ -906,7 +907,6 @@ DESCRIPTION
        by converting the BFD to BFD_IN_MEMORY.  It's assumed that
        you will call <<bfd_make_readable>> on this bfd later.
 
-RETURNS
        <<TRUE>> is returned if all is ok, otherwise <<FALSE>>.
 */
 
@@ -952,7 +952,6 @@ DESCRIPTION
        contents out to the memory buffer, then reversing the
        direction.
 
-RETURNS
        <<TRUE>> is returned if all is ok, otherwise <<FALSE>>.  */
 
 bool
@@ -990,6 +989,7 @@ bfd_make_readable (bfd *abfd)
   abfd->symcount = 0;
   abfd->outsymbols = 0;
   abfd->tdata.any = 0;
+  abfd->size = 0;
 
   bfd_section_list_clear (abfd);
   bfd_check_format (abfd, bfd_object);
@@ -1099,7 +1099,6 @@ DESCRIPTION
        Advances the previously computed @var{crc} value by computing
        and adding in the crc32 for @var{len} bytes of @var{buf}.
 
-RETURNS
        Return the updated CRC32 value.
 */
 
@@ -1172,30 +1171,20 @@ bfd_calc_gnu_debuglink_crc32 (unsigned long crc,
 }
 
 
-/*
-INTERNAL_FUNCTION
-       bfd_get_debug_link_info_1
+/* Extracts the filename and CRC32 value for any separate debug
+   information file associated with @var{abfd}.
 
-SYNOPSIS
-       char *bfd_get_debug_link_info_1 (bfd *abfd, void *crc32_out);
+   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.
 
-DESCRIPTION
-       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.
 
-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.
-*/
+   The returned filename is allocated with @code{malloc}; freeing
+   it is the responsibility of the caller.  */
 
 static char *
 bfd_get_debug_link_info_1 (bfd *abfd, void *crc32_out)
@@ -1206,28 +1195,23 @@ bfd_get_debug_link_info_1 (bfd *abfd, void *crc32_out)
   unsigned int crc_offset;
   char *name;
   bfd_size_type size;
-  ufile_ptr file_size;
 
   BFD_ASSERT (abfd);
   BFD_ASSERT (crc32_out);
 
   sect = bfd_get_section_by_name (abfd, GNU_DEBUGLINK);
 
-  if (sect == NULL)
+  if (sect == NULL || (sect->flags & SEC_HAS_CONTENTS) == 0)
     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))
+  if (size < 8)
     return NULL;
 
   if (!bfd_malloc_and_get_section (abfd, sect, &contents))
-    {
-      free (contents);
-      return NULL;
-    }
+    return NULL;
 
   /* CRC value is stored after the filename, aligned up to 4 bytes.  */
   name = (char *) contents;
@@ -1235,7 +1219,10 @@ bfd_get_debug_link_info_1 (bfd *abfd, void *crc32_out)
   crc_offset = strnlen (name, size) + 1;
   crc_offset = (crc_offset + 3) & ~3;
   if (crc_offset + 4 > size)
-    return NULL;
+    {
+      free (name);
+      return NULL;
+    }
 
   *crc32 = bfd_get_32 (abfd, contents + crc_offset);
   return name;
@@ -1253,11 +1240,10 @@ 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.
+       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.
@@ -1296,7 +1282,6 @@ bfd_get_alt_debug_link_info (bfd * abfd, bfd_size_type *buildid_len,
   unsigned int buildid_offset;
   char *name;
   bfd_size_type size;
-  ufile_ptr file_size;
 
   BFD_ASSERT (abfd);
   BFD_ASSERT (buildid_len);
@@ -1304,19 +1289,15 @@ bfd_get_alt_debug_link_info (bfd * abfd, bfd_size_type *buildid_len,
 
   sect = bfd_get_section_by_name (abfd, GNU_DEBUGALTLINK);
 
-  if (sect == NULL)
+  if (sect == NULL || (sect->flags & SEC_HAS_CONTENTS) == 0)
     return NULL;
 
   size = bfd_section_size (sect);
-  file_size = bfd_get_size (abfd);
-  if (size < 8 || (file_size != 0 && size >= file_size))
+  if (size < 8)
     return NULL;
 
   if (!bfd_malloc_and_get_section (abfd, sect, & contents))
-    {
-      free (contents);
-      return NULL;
-    }
+    return NULL;
 
   /* BuildID value is stored after the filename.  */
   name = (char *) contents;
@@ -1331,22 +1312,12 @@ bfd_get_alt_debug_link_info (bfd * abfd, bfd_size_type *buildid_len,
   return name;
 }
 
-/*
-INTERNAL_FUNCTION
-       separate_debug_file_exists
-
-SYNOPSIS
-       bool separate_debug_file_exists
-         (char *name, void *crc32_p);
+/* Checks to see if @var{name} is a file and if its contents match
+   @var{crc32}, which is a pointer to an @code{unsigned long}
+   containing a CRC32.
 
-DESCRIPTION
-       Checks to see if @var{name} is a file and if its contents
-       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.
-*/
+   The @var{crc32_p} parameter is an untyped pointer because this
+   routine is used as a @code{check_func_type} function.  */
 
 static bool
 separate_debug_file_exists (const char *name, void *crc32_p)
@@ -1374,17 +1345,7 @@ separate_debug_file_exists (const char *name, void *crc32_p)
   return crc == file_crc;
 }
 
-/*
-INTERNAL_FUNCTION
-       separate_alt_debug_file_exists
-
-SYNOPSIS
-       bool separate_alt_debug_file_exists
-         (char *name, void *unused);
-
-DESCRIPTION
-       Checks to see if @var{name} is a file.
-*/
+/* Checks to see if @var{name} is a file.  */
 
 static bool
 separate_alt_debug_file_exists (const char *name, void *unused ATTRIBUTE_UNUSED)
@@ -1402,34 +1363,22 @@ separate_alt_debug_file_exists (const char *name, void *unused ATTRIBUTE_UNUSED)
   return true;
 }
 
-/*
-INTERNAL_FUNCTION
-       find_separate_debug_file
+/* Searches for a debug information file corresponding to @var{abfd}.
 
-SYNOPSIS
-       char *find_separate_debug_file
-         (bfd *abfd, const char *dir, bool include_dirs,
-          get_func_type get, check_func_type check, void *data);
+   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.
 
-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.
-
-       @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.
-*/
+   @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 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 *, void *);
 typedef bool (*check_func_type) (const char *, void *);
@@ -1609,10 +1558,10 @@ DESCRIPTION
        If @var{dir} is NULL, the search will take place starting at
        the current directory.
 
-RETURNS
-       <<NULL>> on any errors or failure to locate the .debug file,
-       otherwise a pointer to a heap-allocated string containing the
-       filename.  The caller is responsible for freeing this string.
+       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 *
@@ -1658,10 +1607,10 @@ DESCRIPTION
        If @var{dir} is NULL, the search will take place starting at
        the current directory.
 
-RETURNS
-       <<NULL>> on any errors or failure to locate the debug file,
-       otherwise a pointer to a heap-allocated string containing the
-       filename.  The caller is responsible for freeing this string.
+       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 *
@@ -1686,7 +1635,6 @@ DESCRIPTION
        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.
 */
@@ -1751,10 +1699,9 @@ SYNOPSIS
 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
-       current directory.
+       specified @var{filename}.  The filename should be absolute or
+       relative to the current directory.
 
-RETURNS
        <<TRUE>> is returned if all is ok.  Otherwise <<FALSE>> is returned
        and bfd_error is set.
 */
@@ -1779,12 +1726,7 @@ bfd_fill_in_gnu_debuglink_section (bfd *abfd,
       return false;
     }
 
-  /* Make sure that we can read the file.
-     XXX - Should we attempt to locate the debug info file using the same
-     algorithm as gdb ?  At the moment, since we are creating the
-     .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.  */
+  /* Open the linked file so that we can compute a CRC.  */
   handle = _bfd_real_fopen (filename, FOPEN_RB);
   if (handle == NULL)
     {
@@ -1830,24 +1772,14 @@ bfd_fill_in_gnu_debuglink_section (bfd *abfd,
   return true;
 }
 
-/*
-INTERNAL_FUNCTION
-       get_build_id
-
-SYNOPSIS
-       struct bfd_build_id * get_build_id (bfd *abfd);
+/* Finds the build-id associated with @var{abfd}.  If the build-id is
+   extracted from the note section then a build-id structure is built
+   for it, using memory allocated to @var{abfd}, and this is then
+   attached to the @var{abfd}.
 
-DESCRIPTION
-       Finds the build-id associated with @var{abfd}.  If the build-id is
-       extracted from the note section then a build-id structure is built
-       for it, using memory allocated to @var{abfd}, and this is then
-       attached to the @var{abfd}.
-
-RETURNS
-       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.
-*/
+   Returns a pointer to the build-id structure if a build-id could be
+   found.  If no build-id is found NULL is returned and error code is
+   set.  */
 
 static struct bfd_build_id *
 get_build_id (bfd *abfd)
@@ -1866,7 +1798,8 @@ get_build_id (bfd *abfd)
     return (struct bfd_build_id *) abfd->build_id;
 
   sect = bfd_get_section_by_name (abfd, ".note.gnu.build-id");
-  if (sect == NULL)
+  if (sect == NULL
+      || (sect->flags & SEC_HAS_CONTENTS) == 0)
     {
       bfd_set_error (bfd_error_no_debug_section);
       return NULL;
@@ -1881,10 +1814,7 @@ get_build_id (bfd *abfd)
     }
 
   if (!bfd_malloc_and_get_section (abfd, sect, & contents))
-    {
-      free (contents);
-      return NULL;
-    }
+    return NULL;
 
   /* FIXME: Paranoia - allow for compressed build-id sections.
      Maybe we should complain if this size is different from
@@ -1932,26 +1862,15 @@ get_build_id (bfd *abfd)
   return build_id;
 }
 
-/*
-INTERNAL_FUNCTION
-       get_build_id_name
+/* 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.
 
-SYNOPSIS
-       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_p}
-       parameter (which points to a @code{struct bfd_build_id}
-       pointer) is set to a pointer to the build_id structure.
-*/
+   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_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, void *build_id_out_p)
@@ -1995,22 +1914,12 @@ get_build_id_name (bfd *abfd, void *build_id_out_p)
   return name;
 }
 
-/*
-INTERNAL_FUNCTION
-       check_build_id_file
-
-SYNOPSIS
-       bool check_build_id_file (char *name, void *buildid_p);
+/* Checks to see if @var{name} is a readable file and if its build-id
+   matches @var{buildid}.
 
-DESCRIPTION
-       Checks to see if @var{name} is a readable file and if its build-id
-       matches @var{buildid}.
-
-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 **}).
-*/
+   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 bool
 check_build_id_file (const char *name, void *buildid_p)
@@ -2073,10 +1982,10 @@ DESCRIPTION
        If @var{dir} is NULL, the search will take place starting at
        the current directory.
 
-RETURNS
-       <<NULL>> on any errors or failure to locate the debug file,
-       otherwise a pointer to a heap-allocated string containing the
-       filename.  The caller is responsible for freeing this string.
+       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 *
@@ -2107,10 +2016,28 @@ bfd_set_filename (bfd *abfd, const char *filename)
 {
   size_t len = strlen (filename) + 1;
   char *n = bfd_alloc (abfd, len);
-  if (n)
+
+  if (n == NULL)
+    return NULL;
+
+  if (abfd->filename != NULL)
     {
-      memcpy (n, filename, len);
-      abfd->filename = n;
+      /* 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;
 }