[PR ld/22263] aarch64: Avoid dynamic TLS relocs in PIE
[deliverable/binutils-gdb.git] / bfd / elf.c
index a238d392b4cc477218e074a3f6b46de238d6d898..8f6aa53b5c98b59bc0aa21c1db352d05ba77b6bb 100644 (file)
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -52,9 +52,10 @@ static int elf_sort_sections (const void *, const void *);
 static bfd_boolean assign_file_positions_except_relocs (bfd *, struct bfd_link_info *);
 static bfd_boolean prep_headers (bfd *);
 static bfd_boolean swap_out_syms (bfd *, struct elf_strtab_hash **, int) ;
-static bfd_boolean elf_read_notes (bfd *, file_ptr, bfd_size_type) ;
+static bfd_boolean elf_read_notes (bfd *, file_ptr, bfd_size_type,
+                                  size_t align) ;
 static bfd_boolean elf_parse_notes (bfd *abfd, char *buf, size_t size,
-                                   file_ptr offset);
+                                   file_ptr offset, size_t align);
 
 /* Swap version information in and out.  The version information is
    currently size independent.  If that ever changes, this code will
@@ -354,8 +355,8 @@ bfd_elf_string_from_elf_section (bfd *abfd,
       unsigned int shstrndx = elf_elfheader(abfd)->e_shstrndx;
       _bfd_error_handler
        /* xgettext:c-format */
-       (_("%B: invalid string offset %u >= %lu for section `%s'"),
-        abfd, strindex, (unsigned long) hdr->sh_size,
+       (_("%B: invalid string offset %u >= %Lu for section `%s'"),
+        abfd, strindex, hdr->sh_size,
         (shindex == shstrndx && strindex == hdr->sh_name
          ? ".shstrtab"
          : bfd_elf_string_from_elf_section (abfd, shstrndx, hdr->sh_name)));
@@ -658,7 +659,7 @@ setup_group (bfd *abfd, Elf_Internal_Shdr *hdr, asection *newsect)
                      _bfd_error_handler
                        /* xgettext:c-format */
                        (_("%B: corrupt size field in group section"
-                          " header: 0x%lx"), abfd, shdr->sh_size);
+                          " header: %#Lx"), abfd, shdr->sh_size);
                      bfd_set_error (bfd_error_bad_value);
                      -- num_group;
                      continue;
@@ -673,7 +674,7 @@ setup_group (bfd *abfd, Elf_Internal_Shdr *hdr, asection *newsect)
                      _bfd_error_handler
                        /* xgettext:c-format */
                        (_("%B: invalid size field in group section"
-                          " header: 0x%lx"), abfd, shdr->sh_size);
+                          " header: %#Lx"), abfd, shdr->sh_size);
                      bfd_set_error (bfd_error_bad_value);
                      -- num_group;
                      /* PR 17510: If the group contents are even
@@ -742,12 +743,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 +812,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;
     }
@@ -896,32 +907,32 @@ _bfd_elf_setup_sections (bfd *abfd)
       n_elt = shdr->sh_size / 4;
 
       while (--n_elt != 0)
-       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
-         {
-           /* There are some unknown sections in the group.  */
-           _bfd_error_handler
-             /* xgettext:c-format */
-             (_("%B: unknown [%d] section `%s' in group [%A]"),
-              abfd,
-              (unsigned int) idx->shdr->sh_type,
-              bfd_elf_string_from_elf_section (abfd,
-                                               (elf_elfheader (abfd)
-                                                ->e_shstrndx),
-                                               idx->shdr->sh_name),
-              shdr->bfd_section);
-           result = FALSE;
-         }
+       {
+         ++ idx;
+
+         if (idx->shdr == NULL)
+           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)
+           {
+             /* There are some unknown sections in the group.  */
+             _bfd_error_handler
+               /* xgettext:c-format */
+               (_("%B: unknown type [%#x] section `%s' in group [%A]"),
+                abfd,
+                idx->shdr->sh_type,
+                bfd_elf_string_from_elf_section (abfd,
+                                                 (elf_elfheader (abfd)
+                                                  ->e_shstrndx),
+                                                 idx->shdr->sh_name),
+                shdr->bfd_section);
+             result = FALSE;
+           }
+       }
     }
+
   return result;
 }
 
@@ -1079,7 +1090,8 @@ _bfd_elf_make_section_from_shdr (bfd *abfd,
       if (!bfd_malloc_and_get_section (abfd, newsect, &contents))
        return FALSE;
 
-      elf_parse_notes (abfd, (char *) contents, hdr->sh_size, hdr->sh_offset);
+      elf_parse_notes (abfd, (char *) contents, hdr->sh_size,
+                      hdr->sh_offset, hdr->sh_addralign);
       free (contents);
     }
 
@@ -1368,7 +1380,7 @@ copy_special_section_fields (const bfd *ibfd,
       /* See PR 20931 for a reproducer.  */
       if (iheader->sh_link >= elf_numsections (ibfd))
        {
-         (* _bfd_error_handler)
+         _bfd_error_handler
            /* xgettext:c-format */
            (_("%B: Invalid sh_link field (%d) in section number %d"),
             ibfd, iheader->sh_link, secnum);
@@ -1384,7 +1396,7 @@ copy_special_section_fields (const bfd *ibfd,
       else
        /* FIXME: Should we install iheader->sh_link
           if we could not find a match ?  */
-       (* _bfd_error_handler)
+       _bfd_error_handler
          /* xgettext:c-format */
          (_("%B: Failed to find link section for section %d"), obfd, secnum);
     }
@@ -1411,7 +1423,7 @@ copy_special_section_fields (const bfd *ibfd,
          changed = TRUE;
        }
       else
-       (* _bfd_error_handler)
+       _bfd_error_handler
          /* xgettext:c-format */
          (_("%B: Failed to find info section for section %d"), obfd, secnum);
     }
@@ -1669,7 +1681,7 @@ _bfd_elf_print_private_bfd_data (bfd *abfd, void *farg)
 
              if (!strcmp (name, ""))
                {
-                 sprintf (ab, "0x%lx", (unsigned long) dyn.d_tag);
+                 sprintf (ab, "%#" BFD_VMA_FMT "x", dyn.d_tag);
                  name = ab;
                }
              break;
@@ -1879,7 +1891,7 @@ bfd_elf_print_symbol (bfd *abfd,
     case bfd_print_symbol_more:
       fprintf (file, "elf ");
       bfd_fprintf_vma (abfd, file, symbol->value);
-      fprintf (file, " %lx", (unsigned long) symbol->flags);
+      fprintf (file, " %x", symbol->flags);
       break;
     case bfd_print_symbol_all:
       {
@@ -2301,7 +2313,7 @@ bfd_section_from_shdr (bfd *abfd, unsigned int shindex)
          {
            _bfd_error_handler
              /* xgettext:c-format */
-             (_("%B: invalid link %lu for reloc section %s (index %u)"),
+             (_("%B: invalid link %u for reloc section %s (index %u)"),
               abfd, hdr->sh_link, name, shindex);
            ret = _bfd_elf_make_section_from_shdr (abfd, hdr, name,
                                                   shindex);
@@ -2460,9 +2472,8 @@ bfd_section_from_shdr (bfd *abfd, unsigned int shindex)
               for applications?  */
            _bfd_error_handler
              /* xgettext:c-format */
-             (_("%B: don't know how to handle allocated, application "
-                "specific section `%s' [0x%8x]"),
-              abfd, name, hdr->sh_type);
+             (_("%B: unknown type [%#x] section `%s'"),
+              abfd, hdr->sh_type, name);
          else
            {
              /* Allow sections reserved for applications.  */
@@ -2476,9 +2487,8 @@ bfd_section_from_shdr (bfd *abfd, unsigned int shindex)
        /* FIXME: We should handle this section.  */
        _bfd_error_handler
          /* xgettext:c-format */
-         (_("%B: don't know how to handle processor specific section "
-            "`%s' [0x%8x]"),
-          abfd, name, hdr->sh_type);
+         (_("%B: unknown type [%#x] section `%s'"),
+          abfd, hdr->sh_type, name);
       else if (hdr->sh_type >= SHT_LOOS && hdr->sh_type <= SHT_HIOS)
        {
          /* Unrecognised OS-specific sections.  */
@@ -2488,9 +2498,8 @@ bfd_section_from_shdr (bfd *abfd, unsigned int shindex)
               be rejected with an error message.  */
            _bfd_error_handler
              /* xgettext:c-format */
-             (_("%B: don't know how to handle OS specific section "
-                "`%s' [0x%8x]"),
-              abfd, name, hdr->sh_type);
+             (_("%B: unknown type [%#x] section `%s'"),
+              abfd, hdr->sh_type, name);
          else
            {
              /* Otherwise it should be processed.  */
@@ -2502,8 +2511,8 @@ bfd_section_from_shdr (bfd *abfd, unsigned int shindex)
        /* FIXME: We should handle this section.  */
        _bfd_error_handler
          /* xgettext:c-format */
-         (_("%B: don't know how to handle section `%s' [0x%8x]"),
-          abfd, name, hdr->sh_type);
+         (_("%B: unknown type [%#x] section `%s'"),
+          abfd, hdr->sh_type, name);
 
       goto fail;
     }
@@ -2983,7 +2992,8 @@ bfd_section_from_phdr (bfd *abfd, Elf_Internal_Phdr *hdr, int hdr_index)
     case PT_NOTE:
       if (! _bfd_elf_make_section_from_phdr (abfd, hdr, hdr_index, "note"))
        return FALSE;
-      if (! elf_read_notes (abfd, hdr->p_offset, hdr->p_filesz))
+      if (! elf_read_notes (abfd, hdr->p_offset, hdr->p_filesz,
+                           hdr->p_align))
        return FALSE;
       return TRUE;
 
@@ -3366,15 +3376,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, 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, name,
+                                           TRUE, delay_st_name_p))
            {
              arg->failed = TRUE;
              return;
@@ -3386,14 +3396,20 @@ elf_fake_sections (bfd *abfd, asection *asect, void *fsarg)
                                          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)
     {
@@ -3510,10 +3526,29 @@ 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);
+         struct bfd_elf_section_data *input_elf_sec = elf_section_data (elt);
 
+         if (elf_sec->rel.hdr != NULL
+             && (gas
+                 || (input_elf_sec->rel.hdr != NULL
+                     && input_elf_sec->rel.hdr->sh_flags & SHF_GROUP) != 0))
+           {
+             elf_sec->rel.hdr->sh_flags |= SHF_GROUP;
+             loc -= 4;
+             H_PUT_32 (abfd, elf_sec->rel.idx, loc);
+           }
+         if (elf_sec->rela.hdr != NULL
+             && (gas
+                 || (input_elf_sec->rela.hdr != NULL
+                     && input_elf_sec->rela.hdr->sh_flags & SHF_GROUP) != 0))
+           {
+             elf_sec->rela.hdr->sh_flags |= SHF_GROUP;
+             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)
@@ -4586,8 +4621,7 @@ _bfd_elf_map_sections_to_segments (bfd *abfd, struct bfd_link_info *info)
            goto error_return;
          m->next = NULL;
          m->p_type = PT_PHDR;
-         /* FIXME: UnixWare and Solaris set PF_X, Irix 5 does not.  */
-         m->p_flags = PF_R | PF_X;
+         m->p_flags = PF_R;
          m->p_flags_valid = 1;
          m->includes_phdrs = 1;
          linker_created_pt_phdr_segment = TRUE;
@@ -5118,7 +5152,7 @@ elf_sort_sections (const void *arg1, const void *arg2)
    else
      adjustment = vma_offset - off_offset;
 
-   which can can be collapsed into the expression below.  */
+   which can be collapsed into the expression below.  */
 
 static file_ptr
 vma_page_aligned_bias (bfd_vma vma, ufile_ptr off, bfd_vma maxpagesize)
@@ -5514,8 +5548,8 @@ assign_file_positions_for_load_sections (bfd *abfd,
                {
                  _bfd_error_handler
                    /* xgettext:c-format */
-                   (_("%B: section %A lma %#lx adjusted to %#lx"), abfd, sec,
-                    (unsigned long) s_start, (unsigned long) p_end);
+                   (_("%B: section %A lma %#Lx adjusted to %#Lx"),
+                    abfd, sec, s_start, p_end);
                  adjust = 0;
                  sec->lma = p_end;
                }
@@ -5897,8 +5931,9 @@ assign_file_positions_for_non_load_sections (bfd *abfd,
                {
                  /* PR 17512: file: 2195325e.  */
                  _bfd_error_handler
-                   (_("%B: error: non-load segment %d includes file header and/or program header"),
-                    abfd, (int)(p - phdrs));
+                   (_("%B: error: non-load segment %d includes file header "
+                      "and/or program header"),
+                    abfd, (int) (p - phdrs));
                  return FALSE;
                }
 
@@ -6426,8 +6461,8 @@ _bfd_elf_symbol_from_bfd_symbol (bfd *abfd, asymbol **asym_ptr_ptr)
 #if DEBUG & 4
   {
     fprintf (stderr,
-            "elf_symbol_from_bfd_symbol 0x%.8lx, name = %s, sym num = %d, flags = 0x%.8lx\n",
-            (long) asym_ptr, asym_ptr->name, idx, (long) flags);
+            "elf_symbol_from_bfd_symbol 0x%.8lx, name = %s, sym num = %d, flags = 0x%.8x\n",
+            (long) asym_ptr, asym_ptr->name, idx, flags);
     fflush (stderr);
   }
 #endif
@@ -6760,8 +6795,8 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd)
          if (segment->p_type == PT_LOAD
              && (segment->p_filesz > 0 || segment->p_memsz == 0))
            /* xgettext:c-format */
-           _bfd_error_handler (_("\
-%B: warning: Empty loadable segment detected at vaddr=0x%.8x, is this intentional ?"),
+           _bfd_error_handler (_("%B: warning: Empty loadable segment detected"
+                                 " at vaddr=%#Lx, is this intentional?"),
                                ibfd, segment->p_vaddr);
 
          map->count = 0;
@@ -7374,9 +7409,9 @@ rewrite:
            /* PR 17512: file: f17299af.  */
            if (segment->p_align > (bfd_vma) 1 << ((sizeof (bfd_vma) * 8) - 2))
              /* xgettext:c-format */
-             _bfd_error_handler (_("\
-%B: warning: segment alignment of 0x%llx is too large"),
-                                 ibfd, (long long) segment->p_align);
+             _bfd_error_handler (_("%B: warning: segment alignment of %#Lx"
+                                   " is too large"),
+                                 ibfd, segment->p_align);
            else
              maxpagesize = segment->p_align;
          }
@@ -8183,7 +8218,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
@@ -8204,7 +8240,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;
@@ -8956,7 +8992,7 @@ elfcore_maybe_make_sect (bfd *abfd, char *name, asection *sect)
      such a section already exists.
    - For the multi-threaded case, a section named "NAME/PID", where
      PID is elfcore_make_pid (abfd).
-   Both pseudosections have identical contents. */
+   Both pseudosections have identical contents.  */
 bfd_boolean
 _bfd_elfcore_make_pseudosection (bfd *abfd,
                                 char *name,
@@ -9683,14 +9719,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;
 
@@ -9846,6 +9882,7 @@ elfcore_grok_freebsd_psinfo (bfd *abfd, Elf_Internal_Note *note)
   /* Check for version 1 in pr_version.  */
   if (bfd_h_get_32 (abfd, (bfd_byte *) note->descdata) != 1)
     return FALSE;
+
   offset = 4;
 
   /* Skip over pr_psinfosz. */
@@ -9885,58 +9922,68 @@ elfcore_grok_freebsd_prstatus (bfd *abfd, Elf_Internal_Note *note)
 {
   size_t offset;
   size_t size;
+  size_t min_size;
 
-  /* Check for version 1 in pr_version. */
-  if (bfd_h_get_32 (abfd, (bfd_byte *) note->descdata) != 1)
-    return FALSE;
-  offset = 4;
-
-  /* Skip over pr_statussz.  */
+  /* Compute offset of pr_getregsz, skipping over pr_statussz.
+     Also compute minimum size of this note.  */
   switch (elf_elfheader (abfd)->e_ident[EI_CLASS])
     {
     case ELFCLASS32:
-      offset += 4;
+      offset = 4 + 4;
+      min_size = offset + (4 * 2) + 4 + 4 + 4;
       break;
 
     case ELFCLASS64:
-      offset += 4;     /* Padding before pr_statussz. */
-      offset += 8;
+      offset = 4 + 4 + 8;      /* Includes padding before pr_statussz.  */
+      min_size = offset + (8 * 2) + 4 + 4 + 4 + 4;
       break;
 
     default:
       return FALSE;
     }
 
-  /* Extract size of pr_reg from pr_gregsetsz.  */
-  if (elf_elfheader (abfd)->e_ident[EI_CLASS] == ELFCLASS32)
-    size = bfd_h_get_32 (abfd, (bfd_byte *) note->descdata + offset);
-  else
-    size = bfd_h_get_64 (abfd, (bfd_byte *) note->descdata + offset);
+  if (note->descsz < min_size)
+    return FALSE;
 
-  /* Skip over pr_gregsetsz and pr_fpregsetsz. */
+  /* Check for version 1 in pr_version.  */
+  if (bfd_h_get_32 (abfd, (bfd_byte *) note->descdata) != 1)
+    return FALSE;
+
+  /* Extract size of pr_reg from pr_gregsetsz.  */
+  /* Skip over pr_gregsetsz and pr_fpregsetsz.  */
   if (elf_elfheader (abfd)->e_ident[EI_CLASS] == ELFCLASS32)
-    offset += 4 * 2;
+    {
+      size = bfd_h_get_32 (abfd, (bfd_byte *) note->descdata + offset);
+      offset += 4 * 2;
+    }
   else
-    offset += 8 * 2;
+    {
+      size = bfd_h_get_64 (abfd, (bfd_byte *) note->descdata + offset);
+      offset += 8 * 2;
+    }
 
-  /* Skip over pr_osreldate. */
+  /* Skip over pr_osreldate.  */
   offset += 4;
 
-  /* Read signal from pr_cursig. */
+  /* Read signal from pr_cursig.  */
   if (elf_tdata (abfd)->core->signal == 0)
     elf_tdata (abfd)->core->signal
       = bfd_h_get_32 (abfd, (bfd_byte *) note->descdata + offset);
   offset += 4;
 
-  /* Read TID from pr_pid. */
+  /* Read TID from pr_pid.  */
   elf_tdata (abfd)->core->lwpid
       = bfd_h_get_32 (abfd, (bfd_byte *) note->descdata + offset);
   offset += 4;
 
-  /* Padding before pr_reg. */
+  /* Padding before pr_reg.  */
   if (elf_elfheader (abfd)->e_ident[EI_CLASS] == ELFCLASS64)
     offset += 4;
 
+  /* Make sure that there is enough data remaining in the note.  */
+  if ((note->descsz - offset) < size)
+    return FALSE;
+
   /* Make a ".reg/999" section and a ".reg" section.  */
   return _bfd_elfcore_make_pseudosection (abfd, ".reg",
                                          size, note->descpos + offset);
@@ -9945,9 +9992,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:
@@ -9982,6 +10034,13 @@ elfcore_grok_freebsd_note (bfd *abfd, Elf_Internal_Note *note)
       else
        return TRUE;
 
+    case NT_FREEBSD_PTLWPINFO:
+      return elfcore_make_note_pseudosection (abfd, ".note.freebsdcore.lwpinfo",
+                                             note);
+
+    case NT_ARM_VFP:
+      return elfcore_grok_arm_vfp (abfd, note);
+
     default:
       return TRUE;
     }
@@ -10004,6 +10063,9 @@ elfcore_netbsd_get_lwpid (Elf_Internal_Note *note, int *lwpidp)
 static bfd_boolean
 elfcore_grok_netbsd_procinfo (bfd *abfd, Elf_Internal_Note *note)
 {
+  if (note->descsz <= 0x7c + 31)
+    return FALSE;
+
   /* Signal number at offset 0x08. */
   elf_tdata (abfd)->core->signal
     = bfd_h_get_32 (abfd, (bfd_byte *) note->descdata + 0x08);
@@ -10088,6 +10150,9 @@ elfcore_grok_netbsd_note (bfd *abfd, Elf_Internal_Note *note)
 static bfd_boolean
 elfcore_grok_openbsd_procinfo (bfd *abfd, Elf_Internal_Note *note)
 {
+  if (note->descsz <= 0x48 + 31)
+    return FALSE;
+
   /* Signal number at offset 0x08. */
   elf_tdata (abfd)->core->signal
     = bfd_h_get_32 (abfd, (bfd_byte *) note->descdata + 0x08);
@@ -10159,6 +10224,9 @@ elfcore_grok_nto_status (bfd *abfd, Elf_Internal_Note *note, long *tid)
   short sig;
   unsigned flags;
 
+  if (note->descsz < 16)
+    return FALSE;
+
   /* nto_procfs_status 'pid' field is at offset 0.  */
   elf_tdata (abfd)->core->pid = bfd_get_32 (abfd, (bfd_byte *) ddata);
 
@@ -10418,11 +10486,22 @@ elfcore_write_linux_prpsinfo32
   (bfd *abfd, char *buf, int *bufsiz,
    const struct elf_internal_linux_prpsinfo *prpsinfo)
 {
-  struct elf_external_linux_prpsinfo32 data;
+  if (get_elf_backend_data (abfd)->linux_prpsinfo32_ugid16)
+    {
+      struct elf_external_linux_prpsinfo32_ugid16 data;
+
+      swap_linux_prpsinfo32_ugid16_out (abfd, prpsinfo, &data);
+      return elfcore_write_note (abfd, buf, bufsiz, "CORE", NT_PRPSINFO,
+                                &data, sizeof (data));
+    }
+  else
+    {
+      struct elf_external_linux_prpsinfo32_ugid32 data;
 
-  swap_linux_prpsinfo32_out (abfd, prpsinfo, &data);
-  return elfcore_write_note (abfd, buf, bufsiz, "CORE", NT_PRPSINFO,
-                            &data, sizeof (data));
+      swap_linux_prpsinfo32_ugid32_out (abfd, prpsinfo, &data);
+      return elfcore_write_note (abfd, buf, bufsiz, "CORE", NT_PRPSINFO,
+                                &data, sizeof (data));
+    }
 }
 
 char *
@@ -10430,11 +10509,22 @@ elfcore_write_linux_prpsinfo64
   (bfd *abfd, char *buf, int *bufsiz,
    const struct elf_internal_linux_prpsinfo *prpsinfo)
 {
-  struct elf_external_linux_prpsinfo64 data;
+  if (get_elf_backend_data (abfd)->linux_prpsinfo64_ugid16)
+    {
+      struct elf_external_linux_prpsinfo64_ugid16 data;
 
-  swap_linux_prpsinfo64_out (abfd, prpsinfo, &data);
-  return elfcore_write_note (abfd, buf, bufsiz,
-                            "CORE", NT_PRPSINFO, &data, sizeof (data));
+      swap_linux_prpsinfo64_ugid16_out (abfd, prpsinfo, &data);
+      return elfcore_write_note (abfd, buf, bufsiz,
+                                "CORE", NT_PRPSINFO, &data, sizeof (data));
+    }
+  else
+    {
+      struct elf_external_linux_prpsinfo64_ugid32 data;
+
+      swap_linux_prpsinfo64_ugid32_out (abfd, prpsinfo, &data);
+      return elfcore_write_note (abfd, buf, bufsiz,
+                                "CORE", NT_PRPSINFO, &data, sizeof (data));
+    }
 }
 
 char *
@@ -10883,14 +10973,21 @@ elfcore_write_register_note (bfd *abfd,
 }
 
 static bfd_boolean
-elf_parse_notes (bfd *abfd, char *buf, size_t size, file_ptr offset)
+elf_parse_notes (bfd *abfd, char *buf, size_t size, file_ptr offset,
+                size_t align)
 {
   char *p;
 
+  /* NB: CORE PT_NOTE segments may have p_align values of 0 or 1.
+     gABI specifies that PT_NOTE alignment should be aligned to 4
+     bytes for 32-bit objects and to 8 bytes for 64-bit objects.  If
+     align is less than 4, we use 4 byte alignment.   */
+  if (align < 4)
+    align = 4;
+
   p = buf;
   while (p < buf + size)
     {
-      /* FIXME: bad alignment assumption.  */
       Elf_External_Note *xnp = (Elf_External_Note *) p;
       Elf_Internal_Note in;
 
@@ -10905,7 +11002,7 @@ elf_parse_notes (bfd *abfd, char *buf, size_t size, file_ptr offset)
        return FALSE;
 
       in.descsz = H_GET_32 (abfd, xnp->descsz);
-      in.descdata = in.namedata + BFD_ALIGN (in.namesz, 4);
+      in.descdata = p + ELF_NOTE_DESC_OFFSET (in.namesz, align);
       in.descpos = offset + (in.descdata - buf);
       if (in.descsz != 0
          && (in.descdata >= buf + size
@@ -10967,18 +11064,19 @@ elf_parse_notes (bfd *abfd, char *buf, size_t size, file_ptr offset)
          break;
        }
 
-      p = in.descdata + BFD_ALIGN (in.descsz, 4);
+      p += ELF_NOTE_NEXT_OFFSET (in.namesz, in.descsz, align);
     }
 
   return TRUE;
 }
 
 static bfd_boolean
-elf_read_notes (bfd *abfd, file_ptr offset, bfd_size_type size)
+elf_read_notes (bfd *abfd, file_ptr offset, bfd_size_type size,
+               size_t align)
 {
   char *buf;
 
-  if (size <= 0)
+  if (size == 0 || (size + 1) == 0)
     return TRUE;
 
   if (bfd_seek (abfd, offset, SEEK_SET) != 0)
@@ -10993,7 +11091,7 @@ elf_read_notes (bfd *abfd, file_ptr offset, bfd_size_type size)
   buf[size] = 0;
 
   if (bfd_bread (buf, size, abfd) != size
-      || !elf_parse_notes (abfd, buf, size, offset))
+      || !elf_parse_notes (abfd, buf, size, offset, align))
     {
       free (buf);
       return FALSE;
This page took 0.036748 seconds and 4 git commands to generate.