Account for padding in FreeBSD/mipsn32 NT_PRSTATUS notes.
[binutils-gdb.git] / bfd / elf.c
index d702474bff7c24f42b7b9cd1d69f7760e7e43b11..c6de70d6b57808a5e8f56c0caab06fa3d2c4d095 100644 (file)
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -742,12 +742,22 @@ setup_group (bfd *abfd, Elf_Internal_Shdr *hdr, asection *newsect)
        {
          Elf_Internal_Shdr *shdr = elf_tdata (abfd)->group_sect_ptr[i];
          Elf_Internal_Group *idx;
-         unsigned int n_elt;
+         bfd_size_type n_elt;
 
          if (shdr == NULL)
            continue;
 
          idx = (Elf_Internal_Group *) shdr->contents;
+         if (idx == NULL || shdr->sh_size < 4)
+           {
+             /* See PR 21957 for a reproducer.  */
+             /* xgettext:c-format */
+             _bfd_error_handler (_("%B: group section '%A' has no contents"),
+                                 abfd, shdr->bfd_section);
+             elf_tdata (abfd)->group_sect_ptr[i] = NULL;
+             bfd_set_error (bfd_error_bad_value);
+             return FALSE;
+           }
          n_elt = shdr->sh_size / 4;
 
          /* Look through this group's sections to see if current
@@ -801,7 +811,7 @@ setup_group (bfd *abfd, Elf_Internal_Shdr *hdr, asection *newsect)
   if (elf_group_name (newsect) == NULL)
     {
       /* xgettext:c-format */
-      _bfd_error_handler (_("%B: no group info for section %A"),
+      _bfd_error_handler (_("%B: no group info for section '%A'"),
                          abfd, newsect);
       return FALSE;
     }
@@ -903,15 +913,8 @@ _bfd_elf_setup_sections (bfd *abfd)
            continue;
          else if (idx->shdr->bfd_section)
            elf_sec_group (idx->shdr->bfd_section) = shdr->bfd_section;
-         else if (idx->shdr->sh_type == SHT_RELA
-                  || idx->shdr->sh_type == SHT_REL)
-           /* We won't include relocation sections in section groups in
-              output object files. We adjust the group section size here
-              so that relocatable link will work correctly when
-              relocation sections are in section group in input object
-              files.  */
-           shdr->bfd_section->size -= 4;
-         else
+         else if (idx->shdr->sh_type != SHT_RELA
+                  && idx->shdr->sh_type != SHT_REL)
            {
              /* There are some unknown sections in the group.  */
              _bfd_error_handler
@@ -3058,6 +3061,7 @@ _bfd_elf_set_reloc_sh_name (bfd *abfd,
 static bfd_boolean
 _bfd_elf_init_reloc_shdr (bfd *abfd,
                          struct bfd_elf_section_reloc_data *reldata,
+                         const Elf_Internal_Shdr *sec_hdr,
                          const char *sec_name,
                          bfd_boolean use_rela_p,
                          bfd_boolean delay_st_name_p)
@@ -3079,7 +3083,7 @@ _bfd_elf_init_reloc_shdr (bfd *abfd,
                         ? bed->s->sizeof_rela
                         : bed->s->sizeof_rel);
   rel_hdr->sh_addralign = (bfd_vma) 1 << bed->s->log_file_align;
-  rel_hdr->sh_flags = 0;
+  rel_hdr->sh_flags = sec_hdr->sh_flags & SHF_GROUP;
   rel_hdr->sh_addr = 0;
   rel_hdr->sh_size = 0;
   rel_hdr->sh_offset = 0;
@@ -3370,15 +3374,15 @@ elf_fake_sections (bfd *abfd, asection *asect, void *fsarg)
              || arg->link_info->emitrelocations))
        {
          if (esd->rel.count && esd->rel.hdr == NULL
-             && !_bfd_elf_init_reloc_shdr (abfd, &esd->rel, name, FALSE,
-                                           delay_st_name_p))
+             && !_bfd_elf_init_reloc_shdr (abfd, &esd->rel, this_hdr, name,
+                                           FALSE, delay_st_name_p))
            {
              arg->failed = TRUE;
              return;
            }
          if (esd->rela.count && esd->rela.hdr == NULL
-             && !_bfd_elf_init_reloc_shdr (abfd, &esd->rela, name, TRUE,
-                                           delay_st_name_p))
+             && !_bfd_elf_init_reloc_shdr (abfd, &esd->rela, this_hdr, name,
+                                           TRUE, delay_st_name_p))
            {
              arg->failed = TRUE;
              return;
@@ -3387,17 +3391,24 @@ elf_fake_sections (bfd *abfd, asection *asect, void *fsarg)
       else if (!_bfd_elf_init_reloc_shdr (abfd,
                                          (asect->use_rela_p
                                           ? &esd->rela : &esd->rel),
+                                         this_hdr,
                                          name,
                                          asect->use_rela_p,
                                          delay_st_name_p))
+       {
          arg->failed = TRUE;
+         return;
+       }
     }
 
   /* Check for processor-specific section types.  */
   sh_type = this_hdr->sh_type;
   if (bed->elf_backend_fake_sections
       && !(*bed->elf_backend_fake_sections) (abfd, this_hdr, asect))
-    arg->failed = TRUE;
+    {
+      arg->failed = TRUE;
+      return;
+    }
 
   if (sh_type == SHT_NOBITS && asect->size != 0)
     {
@@ -3514,10 +3525,19 @@ bfd_elf_set_group_contents (bfd *abfd, asection *sec, void *failedptrarg)
       if (s != NULL
          && !bfd_is_abs_section (s))
        {
-         unsigned int idx = elf_section_data (s)->this_idx;
-
+         struct bfd_elf_section_data *elf_sec = elf_section_data (s);
+         if (elf_sec->rel.hdr != NULL)
+           {
+             loc -= 4;
+             H_PUT_32 (abfd, elf_sec->rel.idx, loc);
+           }
+         if (elf_sec->rela.hdr != NULL)
+           {
+             loc -= 4;
+             H_PUT_32 (abfd, elf_sec->rela.idx, loc);
+           }
          loc -= 4;
-         H_PUT_32 (abfd, idx, loc);
+         H_PUT_32 (abfd, elf_sec->this_idx, loc);
        }
       elt = elf_next_in_group (elt);
       if (elt == first)
@@ -8188,7 +8208,8 @@ _bfd_elf_slurp_version_tables (bfd *abfd, bfd_boolean default_imported_symver)
 
       hdr = &elf_tdata (abfd)->dynverref_hdr;
 
-      if (hdr->sh_info == 0 || hdr->sh_size < sizeof (Elf_External_Verneed))
+      if (hdr->sh_info == 0
+         || hdr->sh_info > hdr->sh_size / sizeof (Elf_External_Verneed))
        {
 error_return_bad_verref:
          _bfd_error_handler
@@ -8209,7 +8230,7 @@ error_return_verref:
        goto error_return_verref;
 
       elf_tdata (abfd)->verref = (Elf_Internal_Verneed *)
-       bfd_zalloc2 (abfd, hdr->sh_info, sizeof (Elf_Internal_Verneed));
+       bfd_alloc2 (abfd, hdr->sh_info, sizeof (Elf_Internal_Verneed));
 
       if (elf_tdata (abfd)->verref == NULL)
        goto error_return_verref;
@@ -9688,14 +9709,14 @@ elfcore_grok_note (bfd *abfd, Elf_Internal_Note *note)
     case NT_S390_GS_CB:
       if (note->namesz == 6
          && strcmp (note->namedata, "LINUX") == 0)
-       return elfcore_grok_s390_gs_bc (abfd, note);
+       return elfcore_grok_s390_gs_cb (abfd, note);
       else
        return TRUE;
 
     case NT_S390_GS_BC:
       if (note->namesz == 6
          && strcmp (note->namedata, "LINUX") == 0)
-       return elfcore_grok_s390_gs_cb (abfd, note);
+       return elfcore_grok_s390_gs_bc (abfd, note);
       else
        return TRUE;
 
@@ -9960,9 +9981,14 @@ elfcore_grok_freebsd_prstatus (bfd *abfd, Elf_Internal_Note *note)
 static bfd_boolean
 elfcore_grok_freebsd_note (bfd *abfd, Elf_Internal_Note *note)
 {
+  const struct elf_backend_data *bed = get_elf_backend_data (abfd);
+
   switch (note->type)
     {
     case NT_PRSTATUS:
+      if (bed->elf_backend_grok_freebsd_prstatus)
+       if ((*bed->elf_backend_grok_freebsd_prstatus) (abfd, note))
+         return TRUE;
       return elfcore_grok_freebsd_prstatus (abfd, note);
 
     case NT_FPREGSET:
@@ -10001,6 +10027,9 @@ elfcore_grok_freebsd_note (bfd *abfd, Elf_Internal_Note *note)
       return elfcore_make_note_pseudosection (abfd, ".note.freebsdcore.lwpinfo",
                                              note);
 
+    case NT_ARM_VFP:
+      return elfcore_grok_arm_vfp (abfd, note);
+
     default:
       return TRUE;
     }