Automatic date update in version.in
[deliverable/binutils-gdb.git] / bfd / elf.c
index 6cbc389999d0c518379c20409333a55d1b0e10fc..e335ff7efbfd8d19f18dc0c6a44332907ad5ec97 100644 (file)
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -513,17 +513,14 @@ bfd_elf_get_elf_syms (bfd *ibfd,
        _bfd_error_handler (_("%pB symbol number %lu references"
                              " nonexistent SHT_SYMTAB_SHNDX section"),
                            ibfd, (unsigned long) symoffset);
-       if (alloc_intsym != NULL)
-         free (alloc_intsym);
+       free (alloc_intsym);
        intsym_buf = NULL;
        goto out;
       }
 
  out:
-  if (alloc_ext != NULL)
-    free (alloc_ext);
-  if (alloc_extshndx != NULL)
-    free (alloc_extshndx);
+  free (alloc_ext);
+  free (alloc_extshndx);
 
   return intsym_buf;
 }
@@ -857,11 +854,10 @@ _bfd_elf_setup_sections (bfd *abfd)
          if (elfsec == 0)
            {
              const struct elf_backend_data *bed = get_elf_backend_data (abfd);
-             if (bed->link_order_error_handler)
-               bed->link_order_error_handler
-                 /* xgettext:c-format */
-                 (_("%pB: warning: sh_link not set for section `%pA'"),
-                  abfd, s);
+             bed->link_order_error_handler
+               /* xgettext:c-format */
+               (_("%pB: warning: sh_link not set for section `%pA'"),
+                abfd, s);
            }
          else
            {
@@ -1424,9 +1420,8 @@ copy_special_section_fields (const bfd *ibfd,
     }
 
   /* Allow the target a chance to decide how these fields should be set.  */
-  if (bed->elf_backend_copy_special_section_fields != NULL
-      && bed->elf_backend_copy_special_section_fields
-      (ibfd, obfd, iheader, oheader))
+  if (bed->elf_backend_copy_special_section_fields (ibfd, obfd,
+                                                   iheader, oheader))
     return TRUE;
 
   /* We have an iheader which might match oheader, and which has non-zero
@@ -1610,8 +1605,8 @@ _bfd_elf_copy_private_bfd_data (bfd *ibfd, bfd *obfd)
        {
          /* Final attempt.  Call the backend copy function
             with a NULL input section.  */
-         if (bed->elf_backend_copy_special_section_fields != NULL)
-           (void) bed->elf_backend_copy_special_section_fields (ibfd, obfd, NULL, oheader);
+         (void) bed->elf_backend_copy_special_section_fields (ibfd, obfd,
+                                                              NULL, oheader);
        }
     }
 
@@ -1880,15 +1875,16 @@ _bfd_elf_print_private_bfd_data (bfd *abfd, void *farg)
   return TRUE;
 
  error_return:
-  if (dynbuf != NULL)
-    free (dynbuf);
+  free (dynbuf);
   return FALSE;
 }
 
-/* Get version string.  */
+/* Get version name.  If BASE_P is TRUE, return "Base" for VER_FLG_BASE
+   and return symbol version for symbol version itself.   */
 
 const char *
 _bfd_elf_get_symbol_version_string (bfd *abfd, asymbol *symbol,
+                                   bfd_boolean base_p,
                                    bfd_boolean *hidden)
 {
   const char *version_string = NULL;
@@ -1906,10 +1902,18 @@ _bfd_elf_get_symbol_version_string (bfd *abfd, asymbol *symbol,
               && (vernum > elf_tdata (abfd)->cverdefs
                   || (elf_tdata (abfd)->verdef[0].vd_flags
                       == VER_FLG_BASE)))
-       version_string = "Base";
+       version_string = base_p ? "Base" : "";
       else if (vernum <= elf_tdata (abfd)->cverdefs)
-       version_string =
-         elf_tdata (abfd)->verdef[vernum - 1].vd_nodename;
+       {
+         const char *nodename
+           = elf_tdata (abfd)->verdef[vernum - 1].vd_nodename;
+         version_string = "";
+         if (base_p
+             || nodename == NULL
+             || symbol->name == NULL
+             || strcmp (symbol->name, nodename) != 0)
+           version_string = nodename;
+       }
       else
        {
          Elf_Internal_Verneed *t;
@@ -1990,6 +1994,7 @@ bfd_elf_print_symbol (bfd *abfd,
        /* If we have version information, print it.  */
        version_string = _bfd_elf_get_symbol_version_string (abfd,
                                                             symbol,
+                                                            TRUE,
                                                             &hidden);
        if (version_string)
          {
@@ -2062,9 +2067,13 @@ bfd_section_from_shdr (bfd *abfd, unsigned int shindex)
       if (sections_being_created == NULL)
        {
          size_t amt = elf_numsections (abfd) * sizeof (bfd_boolean);
-         sections_being_created = (bfd_boolean *) bfd_zalloc (abfd, amt);
+
+         /* PR 26005: Do not use bfd_zalloc here as the memory might
+            be released before the bfd has been fully scanned.  */
+         sections_being_created = (bfd_boolean *) bfd_malloc (amt);
          if (sections_being_created == NULL)
            return FALSE;
+         memset (sections_being_created, FALSE, amt);
          sections_being_created_abfd = abfd;
        }
       if (sections_being_created [shindex])
@@ -2462,12 +2471,12 @@ bfd_section_from_shdr (bfd *abfd, unsigned int shindex)
           sections.  */
        if (*p_hdr != NULL)
          {
-           if (bed->init_secondary_reloc_section == NULL
-               || ! bed->init_secondary_reloc_section (abfd, hdr, name, shindex))
+           if (!bed->init_secondary_reloc_section (abfd, hdr, name, shindex))
              {
                _bfd_error_handler
                  /* xgettext:c-format */
-                 (_("%pB: warning: secondary relocation section '%s' for section %pA found - ignoring"),
+                 (_("%pB: warning: secondary relocation section '%s' "
+                    "for section %pA found - ignoring"),
                   abfd, name, target_sect);
              }
            goto success;
@@ -2602,8 +2611,9 @@ bfd_section_from_shdr (bfd *abfd, unsigned int shindex)
     sections_being_created [shindex] = FALSE;
   if (-- nesting == 0)
     {
+      free (sections_being_created);
       sections_being_created = NULL;
-      sections_being_created_abfd = abfd;
+      sections_being_created_abfd = NULL;
     }
   return ret;
 }
@@ -3940,11 +3950,10 @@ assign_section_numbers (bfd *abfd, struct bfd_link_info *link_info)
                 where s is NULL.  */
              const struct elf_backend_data *bed
                = get_elf_backend_data (abfd);
-             if (bed->link_order_error_handler)
-               bed->link_order_error_handler
-                 /* xgettext:c-format */
-                 (_("%pB: warning: sh_link not set for section `%pA'"),
-                  abfd, sec);
+             bed->link_order_error_handler
+               /* xgettext:c-format */
+               (_("%pB: warning: sh_link not set for section `%pA'"),
+                abfd, sec);
            }
        }
 
@@ -3994,9 +4003,7 @@ assign_section_numbers (bfd *abfd, struct bfd_link_info *link_info)
                  elf_section_data (s)->this_hdr.sh_link = d->this_idx;
 
                  /* This is a .stab section.  */
-                 if (elf_section_data (s)->this_hdr.sh_entsize == 0)
-                   elf_section_data (s)->this_hdr.sh_entsize
-                     = 4 + 2 * bfd_get_arch_size (abfd) / 8;
+                 elf_section_data (s)->this_hdr.sh_entsize = 12;
                }
            }
          break;
@@ -5201,9 +5208,12 @@ _bfd_elf_map_sections_to_segments (bfd *abfd, struct bfd_link_info *info)
                {
                  i = m->count;
                  while (--i != (unsigned) -1)
-                   if ((m->sections[i]->flags & (SEC_LOAD | SEC_HAS_CONTENTS))
-                       == (SEC_LOAD | SEC_HAS_CONTENTS))
-                     break;
+                   {
+                     if (m->sections[i]->size > 0
+                         && (m->sections[i]->flags & (SEC_LOAD | SEC_HAS_CONTENTS))
+                         == (SEC_LOAD | SEC_HAS_CONTENTS))
+                       break;
+                   }
 
                  if (i != (unsigned) -1)
                    break;
@@ -5238,8 +5248,7 @@ _bfd_elf_map_sections_to_segments (bfd *abfd, struct bfd_link_info *info)
   return TRUE;
 
  error_return:
-  if (sections != NULL)
-    free (sections);
+  free (sections);
   return FALSE;
 }
 
@@ -5826,10 +5835,11 @@ assign_file_positions_for_load_sections (bfd *abfd,
                }
              p->p_memsz += adjust;
 
-             if (this_hdr->sh_type != SHT_NOBITS)
+             if (p->p_type == PT_LOAD)
                {
-                 if (p->p_type == PT_LOAD)
+                 if (this_hdr->sh_type != SHT_NOBITS)
                    {
+                     off_adjust = 0;
                      if (p->p_filesz + adjust < p->p_memsz)
                        {
                          /* We have a PROGBITS section following NOBITS ones.
@@ -5839,10 +5849,25 @@ assign_file_positions_for_load_sections (bfd *abfd,
                          if (!write_zeros (abfd, off, adjust))
                            return FALSE;
                        }
+                   }
+                 /* We only adjust sh_offset in SHT_NOBITS sections
+                    as would seem proper for their address when the
+                    section is first in the segment.  sh_offset
+                    doesn't really have any significance for
+                    SHT_NOBITS anyway, apart from a notional position
+                    relative to other sections.  Historically we
+                    didn't bother with adjusting sh_offset and some
+                    programs depend on it not being adjusted.  See
+                    pr12921 and pr25662.  */
+                 if (this_hdr->sh_type != SHT_NOBITS || i == 0)
+                   {
                      off += adjust;
+                     if (this_hdr->sh_type == SHT_NOBITS)
+                       off_adjust += adjust;
                    }
-                 p->p_filesz += adjust;
                }
+             if (this_hdr->sh_type != SHT_NOBITS)
+               p->p_filesz += adjust;
            }
 
          if (p->p_type == PT_NOTE && bfd_get_format (abfd) == bfd_core)
@@ -7906,19 +7931,34 @@ _bfd_elf_fixup_group_sections (bfd *ibfd, asection *discarded)
                elf_section_flags (s->output_section) &= ~SHF_GROUP;
                elf_group_name (s->output_section) = NULL;
              }
-           /* Conversely, if the member section is not being output
-              but the SHT_GROUP section is, then adjust its size.  */
-           else if (s->output_section == discarded
-                    && isec->output_section != discarded)
+           else
              {
                struct bfd_elf_section_data *elf_sec = elf_section_data (s);
-               removed += 4;
-               if (elf_sec->rel.hdr != NULL
-                   && (elf_sec->rel.hdr->sh_flags & SHF_GROUP) != 0)
-                 removed += 4;
-               if (elf_sec->rela.hdr != NULL
-                   && (elf_sec->rela.hdr->sh_flags & SHF_GROUP) != 0)
-                 removed += 4;
+               if (s->output_section == discarded
+                   && isec->output_section != discarded)
+                 {
+                   /* Conversely, if the member section is not being
+                      output but the SHT_GROUP section is, then adjust
+                      its size.  */
+                   removed += 4;
+                   if (elf_sec->rel.hdr != NULL
+                       && (elf_sec->rel.hdr->sh_flags & SHF_GROUP) != 0)
+                     removed += 4;
+                   if (elf_sec->rela.hdr != NULL
+                       && (elf_sec->rela.hdr->sh_flags & SHF_GROUP) != 0)
+                     removed += 4;
+                 }
+               else
+                 {
+                   /* Also adjust for zero-sized relocation member
+                      section.  */
+                   if (elf_sec->rel.hdr != NULL
+                       && elf_sec->rel.hdr->sh_size == 0)
+                     removed += 4;
+                   if (elf_sec->rela.hdr != NULL
+                       && elf_sec->rela.hdr->sh_size == 0)
+                     removed += 4;
+                 }
              }
            s = elf_next_in_group (s);
            if (s == first)
@@ -8463,9 +8503,23 @@ _bfd_elf_get_dynamic_symtab_upper_bound (bfd *abfd)
 }
 
 long
-_bfd_elf_get_reloc_upper_bound (bfd *abfd ATTRIBUTE_UNUSED,
-                               sec_ptr asect)
+_bfd_elf_get_reloc_upper_bound (bfd *abfd, sec_ptr asect)
 {
+  if (asect->reloc_count != 0)
+    {
+      /* Sanity check reloc section size.  */
+      struct bfd_elf_section_data *d = elf_section_data (asect);
+      Elf_Internal_Shdr *rel_hdr = &d->this_hdr;
+      bfd_size_type ext_rel_size = rel_hdr->sh_size;
+      ufile_ptr filesize = bfd_get_file_size (abfd);
+
+      if (filesize != 0 && ext_rel_size > filesize)
+       {
+         bfd_set_error (bfd_error_file_truncated);
+         return -1;
+       }
+    }
+
 #if SIZEOF_LONG == SIZEOF_INT
   if (asect->reloc_count >= LONG_MAX / sizeof (arelent *))
     {
@@ -8531,7 +8585,7 @@ _bfd_elf_canonicalize_dynamic_symtab (bfd *abfd,
 long
 _bfd_elf_get_dynamic_reloc_upper_bound (bfd *abfd)
 {
-  bfd_size_type count;
+  bfd_size_type count, ext_rel_size;
   asection *s;
 
   if (elf_dynsymtab (abfd) == 0)
@@ -8541,11 +8595,18 @@ _bfd_elf_get_dynamic_reloc_upper_bound (bfd *abfd)
     }
 
   count = 1;
+  ext_rel_size = 0;
   for (s = abfd->sections; s != NULL; s = s->next)
     if (elf_section_data (s)->this_hdr.sh_link == elf_dynsymtab (abfd)
        && (elf_section_data (s)->this_hdr.sh_type == SHT_REL
            || elf_section_data (s)->this_hdr.sh_type == SHT_RELA))
       {
+       ext_rel_size += s->size;
+       if (ext_rel_size < s->size)
+         {
+           bfd_set_error (bfd_error_file_truncated);
+           return -1;
+         }
        count += s->size / elf_section_data (s)->this_hdr.sh_entsize;
        if (count > LONG_MAX / sizeof (arelent *))
          {
@@ -8553,6 +8614,16 @@ _bfd_elf_get_dynamic_reloc_upper_bound (bfd *abfd)
            return -1;
          }
       }
+  if (count > 1)
+    {
+      /* Sanity check reloc section sizes.  */
+      ufile_ptr filesize = bfd_get_file_size (abfd);
+      if (filesize != 0 && ext_rel_size > filesize)
+       {
+         bfd_set_error (bfd_error_file_truncated);
+         return -1;
+       }
+    }
   return count * sizeof (arelent *);
 }
 
@@ -8961,8 +9032,7 @@ _bfd_elf_slurp_version_tables (bfd *abfd, bfd_boolean default_imported_symver)
   return TRUE;
 
  error_return:
-  if (contents != NULL)
-    free (contents);
+  free (contents);
   return FALSE;
 }
 \f
@@ -9825,6 +9895,12 @@ elfcore_grok_aarch_pauth (bfd *abfd, Elf_Internal_Note *note)
   return elfcore_make_note_pseudosection (abfd, ".reg-aarch-pauth", note);
 }
 
+static bfd_boolean
+elfcore_grok_arc_v2 (bfd *abfd, Elf_Internal_Note *note)
+{
+  return elfcore_make_note_pseudosection (abfd, ".reg-arc-v2", note);
+}
+
 #if defined (HAVE_PRPSINFO_T)
 typedef prpsinfo_t   elfcore_psinfo_t;
 #if defined (HAVE_PRPSINFO32_T)                /* Sparc64 cross Sparc32 */
@@ -10384,6 +10460,13 @@ elfcore_grok_note (bfd *abfd, Elf_Internal_Note *note)
       else
        return TRUE;
 
+    case NT_ARC_V2:
+      if (note->namesz == 6
+         && strcmp (note->namedata, "LINUX") == 0)
+       return elfcore_grok_arc_v2 (abfd, note);
+      else
+       return TRUE;
+
     case NT_ARM_VFP:
       if (note->namesz == 6
          && strcmp (note->namedata, "LINUX") == 0)
@@ -11795,6 +11878,18 @@ elfcore_write_aarch_pauth (bfd *abfd,
                             note_name, NT_ARM_PAC_MASK, aarch_pauth, size);
 }
 
+char *
+elfcore_write_arc_v2 (bfd *abfd,
+                     char *buf,
+                     int *bufsiz,
+                     const void *arc_v2,
+                     int size)
+{
+  char *note_name = "LINUX";
+  return elfcore_write_note (abfd, buf, bufsiz,
+                            note_name, NT_ARC_V2, arc_v2, size);
+}
+
 char *
 elfcore_write_register_note (bfd *abfd,
                             char *buf,
@@ -11877,6 +11972,8 @@ elfcore_write_register_note (bfd *abfd,
     return elfcore_write_aarch_sve (abfd, buf, bufsiz, data, size);
   if (strcmp (section, ".reg-aarch-pauth") == 0)
     return elfcore_write_aarch_pauth (abfd, buf, bufsiz, data, size);
+  if (strcmp (section, ".reg-arc-v2") == 0)
+    return elfcore_write_arc_v2 (abfd, buf, bufsiz, data, size);
   return NULL;
 }
 
This page took 0.030518 seconds and 4 git commands to generate.