]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blobdiff - bfd/coffgen.c
HPPA64 linker: Do not force the generation of DT_FLAGS for Linux targets.
[thirdparty/binutils-gdb.git] / bfd / coffgen.c
index 1ec9a5185c729366b5357dbea5fe5d5e11d0243d..cc1c655738b3bb990ee879a5044aae7900e82bf8 100644 (file)
@@ -1,5 +1,5 @@
 /* Support for the generic parts of COFF, for BFD.
-   Copyright (C) 1990-2023 Free Software Foundation, Inc.
+   Copyright (C) 1990-2024 Free Software Foundation, Inc.
    Written by Cygnus Support.
 
    This file is part of BFD, the Binary File Descriptor library.
@@ -284,16 +284,15 @@ make_a_section_from_file (bfd *abfd,
 void
 coff_object_cleanup (bfd *abfd)
 {
-  if (bfd_family_coff (abfd) && bfd_get_format (abfd) == bfd_object)
+  struct coff_tdata *td = coff_data (abfd);
+  if (td != NULL)
     {
-      struct coff_tdata *td = coff_data (abfd);
-      if (td != NULL)
-       {
-         if (td->section_by_index)
-           htab_delete (td->section_by_index);
-         if (td->section_by_target_index)
-           htab_delete (td->section_by_target_index);
-       }
+      if (td->section_by_index)
+       htab_delete (td->section_by_index);
+      if (td->section_by_target_index)
+       htab_delete (td->section_by_target_index);
+      if (obj_pe (abfd) && pe_data (abfd)->comdat_hash)
+       htab_delete (pe_data (abfd)->comdat_hash);
     }
 }
 
@@ -1844,8 +1843,6 @@ coff_get_normalized_symtab (bfd *abfd)
 {
   combined_entry_type *internal;
   combined_entry_type *internal_ptr;
-  combined_entry_type *symbol_ptr;
-  combined_entry_type *internal_end;
   size_t symesz;
   char *raw_src;
   char *raw_end;
@@ -1868,7 +1865,6 @@ coff_get_normalized_symtab (bfd *abfd)
   internal = (combined_entry_type *) bfd_zalloc (abfd, size);
   if (internal == NULL && size != 0)
     return NULL;
-  internal_end = internal + obj_raw_syment_count (abfd);
 
   raw_src = (char *) obj_coff_external_syms (abfd);
 
@@ -1888,48 +1884,32 @@ coff_get_normalized_symtab (bfd *abfd)
 
       bfd_coff_swap_sym_in (abfd, (void *) raw_src,
                            (void *) & internal_ptr->u.syment);
-      symbol_ptr = internal_ptr;
       internal_ptr->is_sym = true;
+      combined_entry_type *sym = internal_ptr;
 
       /* PR 17512: Prevent buffer overrun.  */
-      if (symbol_ptr->u.syment.n_numaux > ((raw_end - 1) - raw_src) / symesz)
+      if (sym->u.syment.n_numaux > ((raw_end - 1) - raw_src) / symesz)
        return NULL;
 
-      for (i = 0;
-          i < symbol_ptr->u.syment.n_numaux;
-          i++)
+      for (i = 0; i < sym->u.syment.n_numaux; i++)
        {
          internal_ptr++;
          raw_src += symesz;
 
          bfd_coff_swap_aux_in (abfd, (void *) raw_src,
-                               symbol_ptr->u.syment.n_type,
-                               symbol_ptr->u.syment.n_sclass,
-                               (int) i, symbol_ptr->u.syment.n_numaux,
+                               sym->u.syment.n_type,
+                               sym->u.syment.n_sclass,
+                               (int) i, sym->u.syment.n_numaux,
                                &(internal_ptr->u.auxent));
 
          internal_ptr->is_sym = false;
-         coff_pointerize_aux (abfd, internal, symbol_ptr, i, internal_ptr);
+         coff_pointerize_aux (abfd, internal, sym, i, internal_ptr);
        }
-    }
-
-  /* Free the raw symbols.  */
-  if (obj_coff_external_syms (abfd) != NULL
-      && ! obj_coff_keep_syms (abfd))
-    {
-      free (obj_coff_external_syms (abfd));
-      obj_coff_external_syms (abfd) = NULL;
-    }
-
-  for (internal_ptr = internal; internal_ptr < internal_end;
-       internal_ptr++)
-    {
-      BFD_ASSERT (internal_ptr->is_sym);
 
-      if (internal_ptr->u.syment.n_sclass == C_FILE
-         && internal_ptr->u.syment.n_numaux > 0)
+      if (sym->u.syment.n_sclass == C_FILE
+         && sym->u.syment.n_numaux > 0)
        {
-         combined_entry_type * aux = internal_ptr + 1;
+         combined_entry_type * aux = sym + 1;
 
          /* Make a file symbol point to the name in the auxent, since
             the text ".file" is redundant.  */
@@ -1945,12 +1925,12 @@ coff_get_normalized_symtab (bfd *abfd)
                    return NULL;
                }
 
-             if ((bfd_size_type)(aux->u.auxent.x_file.x_n.x_n.x_offset)
+             if ((bfd_size_type) aux->u.auxent.x_file.x_n.x_n.x_offset
                  >= obj_coff_strings_len (abfd))
-               internal_ptr->u.syment._n._n_n._n_offset =
+               sym->u.syment._n._n_n._n_offset =
                  (uintptr_t) _("<corrupt>");
              else
-               internal_ptr->u.syment._n._n_n._n_offset =
+               sym->u.syment._n._n_n._n_offset =
                  (uintptr_t) (string_table
                               + aux->u.auxent.x_file.x_n.x_n.x_offset);
            }
@@ -1959,30 +1939,35 @@ coff_get_normalized_symtab (bfd *abfd)
              /* Ordinary short filename, put into memory anyway.  The
                 Microsoft PE tools sometimes store a filename in
                 multiple AUX entries.  */
-             if (internal_ptr->u.syment.n_numaux > 1 && obj_pe (abfd))
-               internal_ptr->u.syment._n._n_n._n_offset =
-                 ((uintptr_t)
-                  copy_name (abfd,
-                             aux->u.auxent.x_file.x_n.x_fname,
-                             internal_ptr->u.syment.n_numaux * symesz));
+             size_t len;
+             char *src;
+             if (sym->u.syment.n_numaux > 1 && obj_pe (abfd))
+               {
+                 len = sym->u.syment.n_numaux * symesz;
+                 src = raw_src - (len - symesz);
+               }
              else
-               internal_ptr->u.syment._n._n_n._n_offset =
-                 ((uintptr_t)
-                  copy_name (abfd,
-                             aux->u.auxent.x_file.x_n.x_fname,
-                             (size_t) bfd_coff_filnmlen (abfd)));
+               {
+                 len = bfd_coff_filnmlen (abfd);
+                 src = aux->u.auxent.x_file.x_n.x_fname;
+               }
+             sym->u.syment._n._n_n._n_offset =
+               (uintptr_t) copy_name (abfd, src, len);
            }
 
          /* Normalize other strings available in C_FILE aux entries.  */
          if (!obj_pe (abfd))
-           for (int numaux = 1; numaux < internal_ptr->u.syment.n_numaux; numaux++)
+           for (int numaux = 1;
+                numaux < sym->u.syment.n_numaux;
+                numaux++)
              {
-               aux = internal_ptr + numaux + 1;
+               aux = sym + numaux + 1;
                BFD_ASSERT (! aux->is_sym);
 
                if (aux->u.auxent.x_file.x_n.x_n.x_zeroes == 0)
                  {
-                   /* The string information is a long one, point into the string table.  */
+                   /* The string information is a long one, point
+                      into the string table.  */
                    if (string_table == NULL)
                      {
                        string_table = _bfd_coff_read_string_table (abfd);
@@ -1990,48 +1975,48 @@ coff_get_normalized_symtab (bfd *abfd)
                          return NULL;
                      }
 
-                   if ((bfd_size_type)(aux->u.auxent.x_file.x_n.x_n.x_offset)
+                   if ((bfd_size_type) aux->u.auxent.x_file.x_n.x_n.x_offset
                        >= obj_coff_strings_len (abfd))
                      aux->u.auxent.x_file.x_n.x_n.x_offset =
                        (uintptr_t) _("<corrupt>");
                    else
                      aux->u.auxent.x_file.x_n.x_n.x_offset =
                        (uintptr_t) (string_table
-                                    + (aux->u.auxent.x_file.x_n.x_n.x_offset));
+                                    + aux->u.auxent.x_file.x_n.x_n.x_offset);
                  }
                else
                  aux->u.auxent.x_file.x_n.x_n.x_offset =
                    ((uintptr_t)
                     copy_name (abfd,
                                aux->u.auxent.x_file.x_n.x_fname,
-                               (size_t) bfd_coff_filnmlen (abfd)));
+                               bfd_coff_filnmlen (abfd)));
              }
 
        }
       else
        {
-         if (internal_ptr->u.syment._n._n_n._n_zeroes != 0)
+         if (sym->u.syment._n._n_n._n_zeroes != 0)
            {
              /* This is a "short" name.  Make it long.  */
-             size_t i;
              char *newstring;
 
              /* Find the length of this string without walking into memory
                 that isn't ours.  */
-             for (i = 0; i < 8; ++i)
-               if (internal_ptr->u.syment._n._n_name[i] == '\0')
+             for (i = 0; i < SYMNMLEN; ++i)
+               if (sym->u.syment._n._n_name[i] == '\0')
                  break;
 
-             newstring = (char *) bfd_zalloc (abfd, (bfd_size_type) (i + 1));
+             newstring = bfd_alloc (abfd, i + 1);
              if (newstring == NULL)
                return NULL;
-             strncpy (newstring, internal_ptr->u.syment._n._n_name, i);
-             internal_ptr->u.syment._n._n_n._n_offset = (uintptr_t) newstring;
-             internal_ptr->u.syment._n._n_n._n_zeroes = 0;
+             memcpy (newstring, sym->u.syment._n._n_name, i);
+             newstring[i] = 0;
+             sym->u.syment._n._n_n._n_offset = (uintptr_t) newstring;
+             sym->u.syment._n._n_n._n_zeroes = 0;
            }
-         else if (internal_ptr->u.syment._n._n_n._n_offset == 0)
-           internal_ptr->u.syment._n._n_n._n_offset = (uintptr_t) "";
-         else if (!bfd_coff_symname_in_debug (abfd, &internal_ptr->u.syment))
+         else if (sym->u.syment._n._n_n._n_offset == 0)
+           sym->u.syment._n._n_n._n_offset = (uintptr_t) "";
+         else if (!bfd_coff_symname_in_debug (abfd, &sym->u.syment))
            {
              /* Long name already.  Point symbol at the string in the
                 table.  */
@@ -2041,43 +2026,47 @@ coff_get_normalized_symtab (bfd *abfd)
                  if (string_table == NULL)
                    return NULL;
                }
-             if (internal_ptr->u.syment._n._n_n._n_offset >= obj_coff_strings_len (abfd)
-                 || string_table + internal_ptr->u.syment._n._n_n._n_offset < string_table)
-               internal_ptr->u.syment._n._n_n._n_offset =
+             if (sym->u.syment._n._n_n._n_offset >= obj_coff_strings_len (abfd))
+               sym->u.syment._n._n_n._n_offset =
                  (uintptr_t) _("<corrupt>");
              else
-               internal_ptr->u.syment._n._n_n._n_offset =
-                 ((uintptr_t) (string_table
-                               + internal_ptr->u.syment._n._n_n._n_offset));
+               sym->u.syment._n._n_n._n_offset =
+                 (uintptr_t) (string_table
+                              + sym->u.syment._n._n_n._n_offset);
            }
          else
            {
              /* Long name in debug section.  Very similar.  */
              if (debug_sec_data == NULL)
-               debug_sec_data = build_debug_section (abfd, & debug_sec);
-             if (debug_sec_data != NULL)
                {
-                 BFD_ASSERT (debug_sec != NULL);
-                 /* PR binutils/17512: Catch out of range offsets into the debug data.  */
-                 if (internal_ptr->u.syment._n._n_n._n_offset > debug_sec->size
-                     || debug_sec_data + internal_ptr->u.syment._n._n_n._n_offset < debug_sec_data)
-                   internal_ptr->u.syment._n._n_n._n_offset =
-                     (uintptr_t) _("<corrupt>");
-                 else
-                   internal_ptr->u.syment._n._n_n._n_offset =
-                     (uintptr_t) (debug_sec_data
-                                  + internal_ptr->u.syment._n._n_n._n_offset);
+                 debug_sec_data = build_debug_section (abfd, &debug_sec);
+                 if (debug_sec_data == NULL)
+                   return NULL;
                }
+             /* PR binutils/17512: Catch out of range offsets into
+                the debug data.  */
+             if (sym->u.syment._n._n_n._n_offset >= debug_sec->size)
+               sym->u.syment._n._n_n._n_offset =
+                 (uintptr_t) _("<corrupt>");
              else
-               internal_ptr->u.syment._n._n_n._n_offset = (uintptr_t) "";
+               sym->u.syment._n._n_n._n_offset =
+                 (uintptr_t) (debug_sec_data
+                              + sym->u.syment._n._n_n._n_offset);
            }
        }
-      internal_ptr += internal_ptr->u.syment.n_numaux;
+    }
+
+  /* Free the raw symbols.  */
+  if (obj_coff_external_syms (abfd) != NULL
+      && ! obj_coff_keep_syms (abfd))
+    {
+      free (obj_coff_external_syms (abfd));
+      obj_coff_external_syms (abfd) = NULL;
     }
 
   obj_raw_syments (abfd) = internal;
   BFD_ASSERT (obj_raw_syment_count (abfd)
-             == (unsigned int) (internal_ptr - internal));
+             == (size_t) (internal_ptr - internal));
 
   return internal;
 }
@@ -3292,6 +3281,12 @@ _bfd_coff_free_cached_info (bfd *abfd)
          tdata->section_by_target_index = NULL;
        }
 
+      if (obj_pe (abfd) && pe_data (abfd)->comdat_hash)
+       {
+         htab_delete (pe_data (abfd)->comdat_hash);
+         pe_data (abfd)->comdat_hash = NULL;
+       }
+
       _bfd_dwarf2_cleanup_debug_info (abfd, &tdata->dwarf2_find_line_info);
       _bfd_stab_cleanup (abfd, &tdata->line_info);