bfd, ld: add CTF section linking
[deliverable/binutils-gdb.git] / bfd / elf.c
index fe43c9ffe726328b85ab9e87434260b8ecf2127d..cbec4269cf0788431a6a0dc799bc92132673f5ce 100644 (file)
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -1,6 +1,6 @@
 /* ELF executable support for BFD.
 
-   Copyright (C) 1993-2018 Free Software Foundation, Inc.
+   Copyright (C) 1993-2019 Free Software Foundation, Inc.
 
    This file is part of BFD, the Binary File Descriptor library.
 
@@ -35,6 +35,7 @@ SECTION
 /* For sparc64-cross-sparc32.  */
 #define _SYSCALL32
 #include "sysdep.h"
+#include <limits.h>
 #include "bfd.h"
 #include "bfdlink.h"
 #include "libbfd.h"
@@ -274,7 +275,7 @@ bfd_elf_mkcorefile (bfd *abfd)
   return elf_tdata (abfd)->core != NULL;
 }
 
-static char *
+char *
 bfd_elf_get_str_section (bfd *abfd, unsigned int shindex)
 {
   Elf_Internal_Shdr **i_shdrp;
@@ -350,6 +351,16 @@ bfd_elf_string_from_elf_section (bfd *abfd,
       if (bfd_elf_get_str_section (abfd, shindex) == NULL)
        return NULL;
     }
+  else
+    {
+      /* PR 24273: The string section's contents may have already
+        been loaded elsewhere, eg because a corrupt file has the
+        string section index in the ELF header pointing at a group
+        section.  So be paranoid, and test that the last byte of
+        the section is zero.  */
+      if (hdr->sh_size == 0 || hdr->contents[hdr->sh_size - 1] != 0)
+       return NULL;
+    }
 
   if (strindex >= hdr->sh_size)
     {
@@ -536,7 +547,7 @@ bfd_elf_sym_name (bfd *abfd,
   if (name == NULL)
     name = "(null)";
   else if (sym_sec && *name == '\0')
-    name = bfd_section_name (abfd, sym_sec);
+    name = bfd_section_name (sym_sec);
 
   return name;
 }
@@ -654,7 +665,7 @@ setup_group (bfd *abfd, Elf_Internal_Shdr *hdr, asection *newsect)
                  BFD_ASSERT (sizeof (*dest) >= 4);
                  amt = shdr->sh_size * sizeof (*dest) / 4;
                  shdr->contents = (unsigned char *)
-                     bfd_alloc2 (abfd, shdr->sh_size, sizeof (*dest) / 4);
+                   bfd_alloc2 (abfd, shdr->sh_size, sizeof (*dest) / 4);
                  /* PR binutils/4110: Handle corrupt group headers.  */
                  if (shdr->contents == NULL)
                    {
@@ -963,6 +974,14 @@ bfd_elf_is_group_section (bfd *abfd ATTRIBUTE_UNUSED, const asection *sec)
   return elf_next_in_group (sec) != NULL;
 }
 
+const char *
+bfd_elf_group_name (bfd *abfd ATTRIBUTE_UNUSED, const asection *sec)
+{
+  if (elf_sec_group (sec) != NULL)
+    return elf_group_name (sec);
+  return NULL;
+}
+
 static char *
 convert_debug_to_zdebug (bfd *abfd, const char *name)
 {
@@ -988,6 +1007,18 @@ convert_zdebug_to_debug (bfd *abfd, const char *name)
   return new_name;
 }
 
+/* This a copy of lto_section defined in GCC (lto-streamer.h).  */
+
+struct lto_section
+{
+  int16_t major_version;
+  int16_t minor_version;
+  unsigned char slim_object;
+
+  /* Flags is a private field that is not defined publicly.  */
+  uint16_t flags;
+};
+
 /* Make a BFD section from an ELF section.  We store a pointer to the
    BFD section in the bfd_section field of the header.  */
 
@@ -1018,10 +1049,9 @@ _bfd_elf_make_section_from_shdr (bfd *abfd,
 
   newsect->filepos = hdr->sh_offset;
 
-  if (! bfd_set_section_vma (abfd, newsect, hdr->sh_addr)
-      || ! bfd_set_section_size (abfd, newsect, hdr->sh_size)
-      || ! bfd_set_section_alignment (abfd, newsect,
-                                     bfd_log2 (hdr->sh_addralign)))
+  if (!bfd_set_section_vma (newsect, hdr->sh_addr)
+      || !bfd_set_section_size (newsect, hdr->sh_size)
+      || !bfd_set_section_alignment (newsect, bfd_log2 (hdr->sh_addralign)))
     return FALSE;
 
   flags = SEC_NO_FLAGS;
@@ -1056,6 +1086,19 @@ _bfd_elf_make_section_from_shdr (bfd *abfd,
   if ((hdr->sh_flags & SHF_EXCLUDE) != 0)
     flags |= SEC_EXCLUDE;
 
+  switch (elf_elfheader (abfd)->e_ident[EI_OSABI])
+    {
+      /* FIXME: We should not recognize SHF_GNU_MBIND for ELFOSABI_NONE,
+        but binutils as of 2019-07-23 did not set the EI_OSABI header
+        byte.  */
+    case ELFOSABI_NONE:
+    case ELFOSABI_GNU:
+    case ELFOSABI_FREEBSD:
+      if ((hdr->sh_flags & SHF_GNU_MBIND) != 0)
+       elf_tdata (abfd)->has_gnu_osabi |= elf_gnu_osabi_mbind;
+      break;
+    }
+
   if ((flags & SEC_ALLOC) == 0)
     {
       /* The debugging sections appear to be recognized only by name,
@@ -1098,7 +1141,7 @@ _bfd_elf_make_section_from_shdr (bfd *abfd,
     if (! bed->elf_backend_section_flags (&flags, hdr))
       return FALSE;
 
-  if (! bfd_set_section_flags (abfd, newsect, flags))
+  if (!bfd_set_section_flags (newsect, flags))
     return FALSE;
 
   /* We do not parse the PT_NOTE segments as we are interested even in the
@@ -1177,11 +1220,12 @@ _bfd_elf_make_section_from_shdr (bfd *abfd,
       enum { nothing, compress, decompress } action = nothing;
       int compression_header_size;
       bfd_size_type uncompressed_size;
+      unsigned int uncompressed_align_power;
       bfd_boolean compressed
        = bfd_is_section_compressed_with_header (abfd, newsect,
                                                 &compression_header_size,
-                                                &uncompressed_size);
-
+                                                &uncompressed_size,
+                                                &uncompressed_align_power);
       if (compressed)
        {
          /* Compressed section.  Check if we should decompress.  */
@@ -1241,7 +1285,7 @@ _bfd_elf_make_section_from_shdr (bfd *abfd,
              char *new_name = convert_zdebug_to_debug (abfd, name);
              if (new_name == NULL)
                return FALSE;
-             bfd_rename_section (abfd, newsect, new_name);
+             bfd_rename_section (newsect, new_name);
            }
        }
       else
@@ -1250,6 +1294,17 @@ _bfd_elf_make_section_from_shdr (bfd *abfd,
        newsect->flags |= SEC_ELF_RENAME;
     }
 
+  /* GCC uses .gnu.lto_.lto.<some_hash> as a LTO bytecode information
+     section.  */
+  const char *lto_section_name = ".gnu.lto_.lto.";
+  if (strncmp (name, lto_section_name, strlen (lto_section_name)) == 0)
+    {
+      struct lto_section lsection;
+      if (bfd_get_section_contents (abfd, newsect, &lsection, 0,
+                                   sizeof (struct lto_section)))
+       abfd->lto_slim_object = lsection.slim_object;
+    }
+
   return TRUE;
 }
 
@@ -1299,15 +1354,15 @@ static bfd_boolean
 section_match (const Elf_Internal_Shdr * a,
               const Elf_Internal_Shdr * b)
 {
-  return
-    a->sh_type        == b->sh_type
-    && (a->sh_flags & ~ SHF_INFO_LINK)
-    == (b->sh_flags & ~ SHF_INFO_LINK)
-    && a->sh_addralign == b->sh_addralign
-    && a->sh_size      == b->sh_size
-    && a->sh_entsize   == b->sh_entsize
-    /* FIXME: Check sh_addr ?  */
-    ;
+  if (a->sh_type != b->sh_type
+      || ((a->sh_flags ^ b->sh_flags) & ~SHF_INFO_LINK) != 0
+      || a->sh_addralign != b->sh_addralign
+      || a->sh_entsize != b->sh_entsize)
+    return FALSE;
+  if (a->sh_type == SHT_SYMTAB
+      || a->sh_type == SHT_STRTAB)
+    return TRUE;
+  return a->sh_size == b->sh_size;
 }
 
 /* Find a section in OBFD that has the same characteristics
@@ -2024,9 +2079,8 @@ bfd_section_from_shdr (bfd *abfd, unsigned int shindex)
        sections_being_created = NULL;
       if (sections_being_created == NULL)
        {
-         /* FIXME: It would be more efficient to attach this array to the bfd somehow.  */
          sections_being_created = (bfd_boolean *)
-           bfd_zalloc (abfd, elf_numsections (abfd) * sizeof (bfd_boolean));
+           bfd_zalloc2 (abfd, elf_numsections (abfd), sizeof (bfd_boolean));
          sections_being_created_abfd = abfd;
        }
       if (sections_being_created [shindex])
@@ -2247,7 +2301,7 @@ bfd_section_from_shdr (bfd *abfd, unsigned int shindex)
          if (entry->ndx == shindex)
            goto success;
 
-       entry = bfd_alloc (abfd, sizeof * entry);
+       entry = bfd_alloc (abfd, sizeof (*entry));
        if (entry == NULL)
          goto fail;
        entry->ndx = shindex;
@@ -2384,15 +2438,18 @@ bfd_section_from_shdr (bfd *abfd, unsigned int shindex)
            && ! bfd_section_from_shdr (abfd, hdr->sh_link))
          goto fail;
 
-       /* If this reloc section does not use the main symbol table we
-          don't treat it as a reloc section.  BFD can't adequately
-          represent such a section, so at least for now, we don't
-          try.  We just present it as a normal section.  We also
-          can't use it as a reloc section if it points to the null
-          section, an invalid section, another reloc section, or its
-          sh_link points to the null section.  */
-       if (hdr->sh_link != elf_onesymtab (abfd)
+       /* If this is an alloc section in an executable or shared
+          library, or the reloc section does not use the main symbol
+          table we don't treat it as a reloc section.  BFD can't
+          adequately represent such a section, so at least for now,
+          we don't try.  We just present it as a normal section.  We
+          also can't use it as a reloc section if it points to the
+          null section, an invalid section, another reloc section, or
+          its sh_link points to the null section.  */
+       if (((abfd->flags & (DYNAMIC | EXEC_P)) != 0
+            && (hdr->sh_flags & SHF_ALLOC) != 0)
            || hdr->sh_link == SHN_UNDEF
+           || hdr->sh_link != elf_onesymtab (abfd)
            || hdr->sh_info == SHN_UNDEF
            || hdr->sh_info >= num_sec
            || elf_elfsections (abfd)[hdr->sh_info]->sh_type == SHT_REL
@@ -2416,9 +2473,18 @@ bfd_section_from_shdr (bfd *abfd, unsigned int shindex)
        else
          p_hdr = &esdt->rel.hdr;
 
-       /* PR 17512: file: 0b4f81b7.  */
+       /* PR 17512: file: 0b4f81b7.
+          Also see PR 24456, for a file which deliberately has two reloc
+          sections.  */
        if (*p_hdr != NULL)
-         goto fail;
+         {
+           _bfd_error_handler
+             /* xgettext:c-format */
+             (_("%pB: warning: multiple relocation sections for section %pA \
+found - ignoring all but the first"),
+              abfd, target_sect);
+           goto success;
+         }
        hdr2 = (Elf_Internal_Shdr *) bfd_alloc (abfd, sizeof (*hdr2));
        if (hdr2 == NULL)
          goto fail;
@@ -2605,6 +2671,7 @@ static const struct bfd_elf_special_section special_sections_b[] =
 static const struct bfd_elf_special_section special_sections_c[] =
 {
   { STRING_COMMA_LEN (".comment"), 0, SHT_PROGBITS, 0 },
+  { STRING_COMMA_LEN (".ctf"), 0, SHT_PROGBITS,    0 },
   { NULL,                      0, 0, 0,            0 }
 };
 
@@ -3122,7 +3189,7 @@ _bfd_elf_init_reloc_shdr (bfd *abfd,
 int
 bfd_elf_get_default_section_type (flagword flags)
 {
-  if ((flags & SEC_ALLOC) != 0
+  if ((flags & (SEC_ALLOC | SEC_IS_COMMON)) != 0
       && (flags & (SEC_LOAD | SEC_HAS_CONTENTS)) == 0)
     return SHT_NOBITS;
   return SHT_PROGBITS;
@@ -3458,7 +3525,8 @@ bfd_elf_set_group_contents (bfd *abfd, asection *sec, void *failedptrarg)
 
   /* Ignore linker created group section.  See elfNN_ia64_object_p in
      elfxx-ia64.c.  */
-  if (((sec->flags & (SEC_GROUP | SEC_LINKER_CREATED)) != SEC_GROUP)
+  if ((sec->flags & (SEC_GROUP | SEC_LINKER_CREATED)) != SEC_GROUP
+      || sec->size == 0
       || *failedptr)
     return;
 
@@ -3722,11 +3790,11 @@ assign_section_numbers (bfd *abfd, struct bfd_link_info *link_info)
       _bfd_elf_strtab_addref (elf_shstrtab (abfd), t->symtab_hdr.sh_name);
       if (section_number > ((SHN_LORESERVE - 2) & 0xFFFF))
        {
-         elf_section_list * entry;
+         elf_section_list *entry;
 
          BFD_ASSERT (elf_symtab_shndx_list (abfd) == NULL);
 
-         entry = bfd_zalloc (abfd, sizeof * entry);
+         entry = bfd_zalloc (abfd, sizeof (*entry));
          entry->ndx = section_number++;
          elf_symtab_shndx_list (abfd) = entry;
          entry->hdr.sh_name
@@ -3989,8 +4057,8 @@ sym_is_global (bfd *abfd, asymbol *sym)
     return (*bed->elf_backend_sym_is_global) (abfd, sym);
 
   return ((sym->flags & (BSF_GLOBAL | BSF_WEAK | BSF_GNU_UNIQUE)) != 0
-         || bfd_is_und_section (bfd_get_section (sym))
-         || bfd_is_com_section (bfd_get_section (sym)));
+         || bfd_is_und_section (bfd_asymbol_section (sym))
+         || bfd_is_com_section (bfd_asymbol_section (sym)));
 }
 
 /* Filter global symbols of ABFD to include in the import library.  All
@@ -4368,6 +4436,14 @@ get_program_header_size (bfd *abfd, struct bfd_link_info *info)
       ++segs;
     }
 
+  s = bfd_get_section_by_name (abfd,
+                              NOTE_GNU_PROPERTY_SECTION_NAME);
+  if (s != NULL && s->size != 0)
+    {
+      /* We need a PT_GNU_PROPERTY segment.  */
+      ++segs;
+    }
+
   for (s = abfd->sections; s != NULL; s = s->next)
     {
       if ((s->flags & SEC_LOAD) != 0
@@ -4402,31 +4478,32 @@ get_program_header_size (bfd *abfd, struct bfd_link_info *info)
 
   bed = get_elf_backend_data (abfd);
 
- if ((abfd->flags & D_PAGED) != 0)
-   {
-     /* Add a PT_GNU_MBIND segment for each mbind section.  */
-     unsigned int page_align_power = bfd_log2 (bed->commonpagesize);
-     for (s = abfd->sections; s != NULL; s = s->next)
-       if (elf_section_flags (s) & SHF_GNU_MBIND)
-        {
-          if (elf_section_data (s)->this_hdr.sh_info
-              > PT_GNU_MBIND_NUM)
-            {
-              _bfd_error_handler
-                /* xgettext:c-format */
-                (_("%pB: GNU_MBIN section `%pA' has invalid sh_info field: %d"),
-                    abfd, s, elf_section_data (s)->this_hdr.sh_info);
-              continue;
-            }
-          /* Align mbind section to page size.  */
-          if (s->alignment_power < page_align_power)
-            s->alignment_power = page_align_power;
-          segs ++;
-        }
-   }
-
- /* Let the backend count up any program headers it might need.  */
- if (bed->elf_backend_additional_program_headers)
+  if ((abfd->flags & D_PAGED) != 0
+      && (elf_tdata (abfd)->has_gnu_osabi & elf_gnu_osabi_mbind) != 0)
+    {
+      /* Add a PT_GNU_MBIND segment for each mbind section.  */
+      unsigned int page_align_power = bfd_log2 (bed->commonpagesize);
+      for (s = abfd->sections; s != NULL; s = s->next)
+       if (elf_section_flags (s) & SHF_GNU_MBIND)
+         {
+           if (elf_section_data (s)->this_hdr.sh_info > PT_GNU_MBIND_NUM)
+             {
+               _bfd_error_handler
+                 /* xgettext:c-format */
+                 (_("%pB: GNU_MBIND section `%pA' has invalid "
+                    "sh_info field: %d"),
+                  abfd, s, elf_section_data (s)->this_hdr.sh_info);
+               continue;
+             }
+           /* Align mbind section to page size.  */
+           if (s->alignment_power < page_align_power)
+             s->alignment_power = page_align_power;
+           segs ++;
+         }
+    }
+
+  /* Let the backend count up any program headers it might need.  */
+  if (bed->elf_backend_additional_program_headers)
     {
       int a;
 
@@ -4597,7 +4674,7 @@ _bfd_elf_map_sections_to_segments (bfd *abfd, struct bfd_link_info *info)
       unsigned int hdr_index;
       bfd_vma maxpagesize;
       asection **hdrpp;
-      bfd_boolean phdr_in_segment = TRUE;
+      bfd_boolean phdr_in_segment;
       bfd_boolean writable;
       bfd_boolean executable;
       int tls_count = 0;
@@ -4606,7 +4683,7 @@ _bfd_elf_map_sections_to_segments (bfd *abfd, struct bfd_link_info *info)
       asection *dynsec, *eh_frame_hdr;
       bfd_size_type amt;
       bfd_vma addr_mask, wrap_to = 0;
-      bfd_boolean linker_created_pt_phdr_segment = FALSE;
+      bfd_size_type phdr_size;
 
       /* Select the allocated sections, and sort them.  */
 
@@ -4638,8 +4715,23 @@ _bfd_elf_map_sections_to_segments (bfd *abfd, struct bfd_link_info *info)
 
       qsort (sections, (size_t) count, sizeof (asection *), elf_sort_sections);
 
-      /* Build the mapping.  */
+      phdr_size = elf_program_header_size (abfd);
+      if (phdr_size == (bfd_size_type) -1)
+       phdr_size = get_program_header_size (abfd, info);
+      phdr_size += bed->s->sizeof_ehdr;
+      maxpagesize = bed->maxpagesize;
+      if (maxpagesize == 0)
+       maxpagesize = 1;
+      phdr_in_segment = info != NULL && info->load_phdrs;
+      if (count != 0
+         && (((sections[0]->lma & addr_mask) & (maxpagesize - 1))
+             >= (phdr_size & (maxpagesize - 1))))
+       /* For compatibility with old scripts that may not be using
+          SIZEOF_HEADERS, add headers when it looks like space has
+          been left for them.  */
+       phdr_in_segment = TRUE;
 
+      /* Build the mapping.  */
       mfirst = NULL;
       pm = &mfirst;
 
@@ -4658,7 +4750,7 @@ _bfd_elf_map_sections_to_segments (bfd *abfd, struct bfd_link_info *info)
          m->p_flags = PF_R;
          m->p_flags_valid = 1;
          m->includes_phdrs = 1;
-         linker_created_pt_phdr_segment = TRUE;
+         phdr_in_segment = TRUE;
          *pm = m;
          pm = &m->next;
 
@@ -4681,12 +4773,6 @@ _bfd_elf_map_sections_to_segments (bfd *abfd, struct bfd_link_info *info)
       last_hdr = NULL;
       last_size = 0;
       hdr_index = 0;
-      maxpagesize = bed->maxpagesize;
-      /* PR 17512: file: c8455299.
-        Avoid divide-by-zero errors later on.
-        FIXME: Should we abort if the maxpagesize is zero ?  */
-      if (maxpagesize == 0)
-       maxpagesize = 1;
       writable = FALSE;
       executable = FALSE;
       dynsec = bfd_get_section_by_name (abfd, ".dynamic");
@@ -4694,34 +4780,62 @@ _bfd_elf_map_sections_to_segments (bfd *abfd, struct bfd_link_info *info)
          && (dynsec->flags & SEC_LOAD) == 0)
        dynsec = NULL;
 
+      if ((abfd->flags & D_PAGED) == 0)
+       phdr_in_segment = FALSE;
+
       /* Deal with -Ttext or something similar such that the first section
         is not adjacent to the program headers.  This is an
         approximation, since at this point we don't know exactly how many
         program headers we will need.  */
-      if (count > 0)
+      if (phdr_in_segment && count > 0)
        {
-         bfd_size_type phdr_size = elf_program_header_size (abfd);
+         bfd_vma phdr_lma;
+         bfd_boolean separate_phdr = FALSE;
 
-         if (phdr_size == (bfd_size_type) -1)
-           phdr_size = get_program_header_size (abfd, info);
-         phdr_size += bed->s->sizeof_ehdr;
-         if ((abfd->flags & D_PAGED) == 0
-             || (sections[0]->lma & addr_mask) < phdr_size
-             || ((sections[0]->lma & addr_mask) % maxpagesize
-                 < phdr_size % maxpagesize)
-             || (sections[0]->lma & addr_mask & -maxpagesize) < wrap_to)
+         phdr_lma = (sections[0]->lma - phdr_size) & addr_mask & -maxpagesize;
+         if (info != NULL
+             && info->separate_code
+             && (sections[0]->flags & SEC_CODE) != 0)
            {
-             /* PR 20815: The ELF standard says that a PT_PHDR segment, if
-                present, must be included as part of the memory image of the
-                program.  Ie it must be part of a PT_LOAD segment as well.
-                If we have had to create our own PT_PHDR segment, but it is
-                not going to be covered by the first PT_LOAD segment, then
-                force the inclusion if we can...  */
-             if ((abfd->flags & D_PAGED) != 0
-                 && linker_created_pt_phdr_segment)
-               phdr_in_segment = TRUE;
-             else
-               phdr_in_segment = FALSE;
+             /* If data sections should be separate from code and
+                thus not executable, and the first section is
+                executable then put the file and program headers in
+                their own PT_LOAD.  */
+             separate_phdr = TRUE;
+             if ((((phdr_lma + phdr_size - 1) & addr_mask & -maxpagesize)
+                  == (sections[0]->lma & addr_mask & -maxpagesize)))
+               {
+                 /* The file and program headers are currently on the
+                    same page as the first section.  Put them on the
+                    previous page if we can.  */
+                 if (phdr_lma >= maxpagesize)
+                   phdr_lma -= maxpagesize;
+                 else
+                   separate_phdr = FALSE;
+               }
+           }
+         if ((sections[0]->lma & addr_mask) < phdr_lma
+             || (sections[0]->lma & addr_mask) < phdr_size)
+           /* If file and program headers would be placed at the end
+              of memory then it's probably better to omit them.  */
+           phdr_in_segment = FALSE;
+         else if (phdr_lma < wrap_to)
+           /* If a section wraps around to where we'll be placing
+              file and program headers, then the headers will be
+              overwritten.  */
+           phdr_in_segment = FALSE;
+         else if (separate_phdr)
+           {
+             m = make_mapping (abfd, sections, 0, 0, phdr_in_segment);
+             if (m == NULL)
+               goto error_return;
+             m->p_paddr = phdr_lma;
+             m->p_vaddr_offset
+               = (sections[0]->vma - phdr_size) & addr_mask & -maxpagesize;
+             m->p_paddr_valid = 1;
+             *pm = m;
+             pm = &m->next;
+             phdr_in_segment = FALSE;
            }
        }
 
@@ -4985,11 +5099,12 @@ _bfd_elf_map_sections_to_segments (bfd *abfd, struct bfd_link_info *info)
          pm = &m->next;
        }
 
-      if (first_mbind && (abfd->flags & D_PAGED) != 0)
+      if (first_mbind
+         && (abfd->flags & D_PAGED) != 0
+         && (elf_tdata (abfd)->has_gnu_osabi & elf_gnu_osabi_mbind) != 0)
        for (s = first_mbind; s != NULL; s = s->next)
          if ((elf_section_flags (s) & SHF_GNU_MBIND) != 0
-             && (elf_section_data (s)->this_hdr.sh_info
-                 <= PT_GNU_MBIND_NUM))
+             && elf_section_data (s)->this_hdr.sh_info <= PT_GNU_MBIND_NUM)
            {
              /* Mandated PF_R.  */
              unsigned long p_flags = PF_R;
@@ -5014,6 +5129,24 @@ _bfd_elf_map_sections_to_segments (bfd *abfd, struct bfd_link_info *info)
              pm = &m->next;
            }
 
+      s = bfd_get_section_by_name (abfd,
+                                  NOTE_GNU_PROPERTY_SECTION_NAME);
+      if (s != NULL && s->size != 0)
+       {
+         amt = sizeof (struct elf_segment_map) + sizeof (asection *);
+         m = bfd_zalloc (abfd, amt);
+         if (m == NULL)
+           goto error_return;
+         m->next = NULL;
+         m->p_type = PT_GNU_PROPERTY;
+         m->count = 1;
+         m->p_flags_valid = 1;
+         m->sections[0] = s;
+         m->p_flags = PF_R;
+         *pm = m;
+         pm = &m->next;
+       }
+
       /* If there is a .eh_frame_hdr section, throw in a PT_GNU_EH_FRAME
         segment.  */
       eh_frame_hdr = elf_eh_frame_hdr (abfd);
@@ -5358,16 +5491,16 @@ assign_file_positions_for_load_sections (bfd *abfd,
       p->p_flags = m->p_flags;
 
       if (m->count == 0)
-       p->p_vaddr = 0;
+       p->p_vaddr = m->p_vaddr_offset;
       else
-       p->p_vaddr = m->sections[0]->vma - m->p_vaddr_offset;
+       p->p_vaddr = m->sections[0]->vma + m->p_vaddr_offset;
 
       if (m->p_paddr_valid)
        p->p_paddr = m->p_paddr;
       else if (m->count == 0)
        p->p_paddr = 0;
       else
-       p->p_paddr = m->sections[0]->lma - m->p_vaddr_offset;
+       p->p_paddr = m->sections[0]->lma + m->p_vaddr_offset;
 
       if (p->p_type == PT_LOAD
          && (abfd->flags & D_PAGED) != 0)
@@ -5409,7 +5542,7 @@ assign_file_positions_for_load_sections (bfd *abfd,
                {
                  unsigned int secalign;
 
-                 secalign = bfd_get_section_alignment (abfd, *secpp);
+                 secalign = bfd_section_alignment (*secpp);
                  if (secalign > align_power)
                    align_power = secalign;
                }
@@ -5563,7 +5696,7 @@ assign_file_positions_for_load_sections (bfd *abfd,
 
          sec = *secpp;
          this_hdr = &elf_section_data (sec)->this_hdr;
-         align = (bfd_size_type) 1 << bfd_get_section_alignment (abfd, sec);
+         align = (bfd_size_type) 1 << bfd_section_alignment (sec);
 
          if ((p->p_type == PT_LOAD
               || p->p_type == PT_TLS)
@@ -5732,7 +5865,37 @@ assign_file_positions_for_load_sections (bfd *abfd,
   return TRUE;
 }
 
-/* Assign file positions for the other sections.  */
+/* Determine if a bfd is a debuginfo file.  Unfortunately there
+   is no defined method for detecting such files, so we have to
+   use heuristics instead.  */
+
+bfd_boolean
+is_debuginfo_file (bfd *abfd)
+{
+  if (abfd == NULL || bfd_get_flavour (abfd) != bfd_target_elf_flavour)
+    return FALSE;
+
+  Elf_Internal_Shdr **start_headers = elf_elfsections (abfd);
+  Elf_Internal_Shdr **end_headers = start_headers + elf_numsections (abfd);
+  Elf_Internal_Shdr **headerp;
+
+  for (headerp = start_headers; headerp < end_headers; headerp ++)
+    {
+      Elf_Internal_Shdr *header = * headerp;
+
+      /* Debuginfo files do not have any allocated SHT_PROGBITS sections.
+        The only allocated sections are SHT_NOBITS or SHT_NOTES.  */
+      if ((header->sh_flags & SHF_ALLOC) == SHF_ALLOC
+         && header->sh_type != SHT_NOBITS
+         && header->sh_type != SHT_NOTE)
+       return FALSE;
+    }
+
+  return TRUE;
+}
+
+/* Assign file positions for the other sections, except for compressed debugging
+   and other sections assigned in _bfd_elf_assign_file_positions_for_non_load().  */
 
 static bfd_boolean
 assign_file_positions_for_non_load_sections (bfd *abfd,
@@ -5765,7 +5928,13 @@ assign_file_positions_for_non_load_sections (bfd *abfd,
        BFD_ASSERT (hdr->sh_offset == hdr->bfd_section->filepos);
       else if ((hdr->sh_flags & SHF_ALLOC) != 0)
        {
-         if (hdr->sh_size != 0)
+         if (hdr->sh_size != 0
+             /* PR 24717 - debuginfo files are known to be not strictly
+                compliant with the ELF standard.  In particular they often
+                have .note.gnu.property sections that are outside of any
+                loadable segment.  This is not a problem for such files,
+                so do not warn about them.  */
+             && ! is_debuginfo_file (abfd))
            _bfd_error_handler
              /* xgettext:c-format */
              (_("%pB: warning: allocated section `%s' not in segment"),
@@ -5785,9 +5954,12 @@ assign_file_positions_for_non_load_sections (bfd *abfd,
        }
       else if (((hdr->sh_type == SHT_REL || hdr->sh_type == SHT_RELA)
                && hdr->bfd_section == NULL)
+              /* We don't know the offset of these sections yet: their size has
+                 not been decided.  */
               || (hdr->bfd_section != NULL
-                  && (hdr->bfd_section->flags & SEC_ELF_COMPRESS))
-                  /* Compress DWARF debug sections.  */
+                  && (hdr->bfd_section->flags & SEC_ELF_COMPRESS
+                      || (bfd_section_is_ctf (hdr->bfd_section)
+                          && abfd->is_linker_output)))
               || hdr == i_shdrpp[elf_onesymtab (abfd)]
               || (elf_symtab_shndx_list (abfd) != NULL
                   && hdr == i_shdrpp[elf_symtab_shndx_list (abfd)->ndx])
@@ -6055,11 +6227,12 @@ find_section_in_list (unsigned int i, elf_section_list * list)
    VMAs must be known before this is called.
 
    Reloc sections come in two flavours: Those processed specially as
-   "side-channel" data attached to a section to which they apply, and
-   those that bfd doesn't process as relocations.  The latter sort are
-   stored in a normal bfd section by bfd_section_from_shdr.   We don't
-   consider the former sort here, unless they form part of the loadable
-   image.  Reloc sections not assigned here will be handled later by
+   "side-channel" data attached to a section to which they apply, and those that
+   bfd doesn't process as relocations.  The latter sort are stored in a normal
+   bfd section by bfd_section_from_shdr.  We don't consider the former sort
+   here, unless they form part of the loadable image.  Reloc sections not
+   assigned here (and compressed debugging sections and CTF sections which
+   nothing else in the file can rely upon) will be handled later by
    assign_file_positions_for_relocs.
 
    We also don't set the positions of the .symtab and .strtab here.  */
@@ -6094,9 +6267,12 @@ assign_file_positions_except_relocs (bfd *abfd,
          hdr = *hdrpp;
          if (((hdr->sh_type == SHT_REL || hdr->sh_type == SHT_RELA)
               && hdr->bfd_section == NULL)
+             /* Do not assign offsets for these sections yet: we don't know
+                their sizes.  */
              || (hdr->bfd_section != NULL
-                 && (hdr->bfd_section->flags & SEC_ELF_COMPRESS))
-                 /* Compress DWARF debug sections.  */
+                 && (hdr->bfd_section->flags & SEC_ELF_COMPRESS
+                     || (bfd_section_is_ctf (hdr->bfd_section)
+                         && abfd->is_linker_output)))
              || i == elf_onesymtab (abfd)
              || (elf_symtab_shndx_list (abfd) != NULL
                  && hdr == i_shdrpp[elf_symtab_shndx_list (abfd)->ndx])
@@ -6304,10 +6480,12 @@ _bfd_elf_assign_file_positions_for_non_load (bfd *abfd)
          asection *sec = shdrp->bfd_section;
          bfd_boolean is_rel = (shdrp->sh_type == SHT_REL
                                || shdrp->sh_type == SHT_RELA);
+         bfd_boolean is_ctf = sec && bfd_section_is_ctf (sec);
          if (is_rel
+             || is_ctf
              || (sec != NULL && (sec->flags & SEC_ELF_COMPRESS)))
            {
-             if (!is_rel)
+             if (!is_rel && !is_ctf)
                {
                  const char *name = sec->name;
                  struct bfd_elf_section_data *d;
@@ -6353,6 +6531,13 @@ _bfd_elf_assign_file_positions_for_non_load (bfd *abfd)
                  shdrp->contents = sec->contents;
                  shdrp->bfd_section->contents = NULL;
                }
+             else if (is_ctf)
+               {
+                 /* Update section size and contents.  */
+                 shdrp->sh_size = sec->size;
+                 shdrp->contents = sec->contents;
+               }
+
              off = _bfd_elf_assign_file_position_for_section (shdrp,
                                                               off,
                                                               TRUE);
@@ -6440,8 +6625,8 @@ _bfd_elf_write_object_contents (bfd *abfd)
          || !_bfd_elf_strtab_emit (abfd, elf_shstrtab (abfd))))
     return FALSE;
 
-  if (bed->elf_backend_final_write_processing)
-    (*bed->elf_backend_final_write_processing) (abfd, elf_linker (abfd));
+  if (!(*bed->elf_backend_final_write_processing) (abfd))
+    return FALSE;
 
   if (!bed->s->write_shdrs_and_ehdr (abfd))
     return FALSE;
@@ -6603,6 +6788,7 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd)
      the given segment.  LMA addresses are compared.  */
 #define IS_CONTAINED_BY_LMA(section, segment, base)                    \
   (section->lma >= base                                                        \
+   && (section->lma + SECTION_SIZE (section, segment) >= section->lma) \
    && (section->lma + SECTION_SIZE (section, segment)                  \
        <= SEGMENT_END (segment, base)))
 
@@ -6666,8 +6852,7 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd)
        || (segment->p_paddr                                            \
           ? segment->p_paddr != section->lma                           \
           : segment->p_vaddr != section->vma)                          \
-       || (strcmp (bfd_get_section_name (ibfd, section), ".dynamic")   \
-          == 0))                                                       \
+       || (strcmp (bfd_section_name (section), ".dynamic") == 0))      \
    && (segment->p_type != PT_LOAD || !section->segment_mark))
 
 /* If the output section of a section in the input segment is NULL,
@@ -6881,6 +7066,7 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd)
                 " at vaddr=%#" PRIx64 ", is this intentional?"),
               ibfd, (uint64_t) segment->p_vaddr);
 
+         map->p_vaddr_offset = segment->p_vaddr;
          map->count = 0;
          *pointer_to_map = map;
          pointer_to_map = &map->next;
@@ -7005,7 +7191,7 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd)
            /* There is some padding before the first section in the
               segment.  So, we must account for that in the output
               segment's vma.  */
-           map->p_vaddr_offset = matching_lma->lma - map->p_paddr;
+           map->p_vaddr_offset = map->p_paddr - matching_lma->lma;
 
          free (sections);
          continue;
@@ -7125,7 +7311,15 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd)
                suggested_lma = output_section;
            }
 
-         BFD_ASSERT (map->count > 0);
+         /* PR 23932.  A corrupt input file may contain sections that cannot
+            be assigned to any segment - because for example they have a
+            negative size - or segments that do not contain any sections.  */
+         if (map->count == 0)
+           {
+             bfd_set_error (bfd_error_bad_value);
+             free (sections);
+             return FALSE;
+           }
 
          /* Add the current segment to the list of built segments.  */
          *pointer_to_map = map;
@@ -7367,12 +7561,14 @@ copy_elf_program_header (bfd *ibfd, bfd *obfd)
            map->header_size = lowest_section->filepos;
        }
 
-      if (!map->includes_phdrs
-         && !map->includes_filehdr
-         && map->p_paddr_valid)
-       /* There is some other padding before the first section.  */
-       map->p_vaddr_offset = ((lowest_section ? lowest_section->lma : 0)
-                              - segment->p_paddr);
+      if (section_count == 0)
+       map->p_vaddr_offset = segment->p_vaddr;
+      else if (!map->includes_phdrs
+              && !map->includes_filehdr
+              && map->p_paddr_valid)
+       /* Account for padding before the first section.  */
+       map->p_vaddr_offset = (segment->p_paddr
+                              - (lowest_section ? lowest_section->lma : 0));
 
       map->count = section_count;
       *pointer_to_map = map;
@@ -7541,7 +7737,8 @@ _bfd_elf_init_private_section_data (bfd *ibfd,
                               & (SHF_MASKOS | SHF_MASKPROC));
 
   /* Copy sh_info from input for mbind section.  */
-  if (elf_section_flags (isec) & SHF_GNU_MBIND)
+  if ((elf_tdata (ibfd)->has_gnu_osabi & elf_gnu_osabi_mbind) != 0
+      && elf_section_flags (isec) & SHF_GNU_MBIND)
     elf_section_data (osec)->this_hdr.sh_info
       = elf_section_data (isec)->this_hdr.sh_info;
 
@@ -7811,8 +8008,8 @@ swap_out_syms (bfd *abfd,
   symstrtab_hdr->sh_type = SHT_STRTAB;
 
   /* Allocate buffer to swap out the .strtab section.  */
-  symstrtab = (struct elf_sym_strtab *) bfd_malloc ((symcount + 1)
-                                                   * sizeof (*symstrtab));
+  symstrtab = (struct elf_sym_strtab *) bfd_malloc2 (symcount + 1,
+                                                    sizeof (*symstrtab));
   if (symstrtab == NULL)
     {
       _bfd_elf_strtab_free (stt);
@@ -8136,11 +8333,16 @@ error_return:
 long
 _bfd_elf_get_symtab_upper_bound (bfd *abfd)
 {
-  long symcount;
+  bfd_size_type symcount;
   long symtab_size;
   Elf_Internal_Shdr *hdr = &elf_tdata (abfd)->symtab_hdr;
 
   symcount = hdr->sh_size / get_elf_backend_data (abfd)->s->sizeof_sym;
+  if (symcount >= LONG_MAX / sizeof (asymbol *))
+    {
+      bfd_set_error (bfd_error_file_too_big);
+      return -1;
+    }
   symtab_size = (symcount + 1) * (sizeof (asymbol *));
   if (symcount > 0)
     symtab_size -= sizeof (asymbol *);
@@ -8151,7 +8353,7 @@ _bfd_elf_get_symtab_upper_bound (bfd *abfd)
 long
 _bfd_elf_get_dynamic_symtab_upper_bound (bfd *abfd)
 {
-  long symcount;
+  bfd_size_type symcount;
   long symtab_size;
   Elf_Internal_Shdr *hdr = &elf_tdata (abfd)->dynsymtab_hdr;
 
@@ -8162,6 +8364,11 @@ _bfd_elf_get_dynamic_symtab_upper_bound (bfd *abfd)
     }
 
   symcount = hdr->sh_size / get_elf_backend_data (abfd)->s->sizeof_sym;
+  if (symcount >= LONG_MAX / sizeof (asymbol *))
+    {
+      bfd_set_error (bfd_error_file_too_big);
+      return -1;
+    }
   symtab_size = (symcount + 1) * (sizeof (asymbol *));
   if (symcount > 0)
     symtab_size -= sizeof (asymbol *);
@@ -8173,6 +8380,13 @@ long
 _bfd_elf_get_reloc_upper_bound (bfd *abfd ATTRIBUTE_UNUSED,
                                sec_ptr asect)
 {
+#if SIZEOF_LONG == SIZEOF_INT
+  if (asect->reloc_count >= LONG_MAX / sizeof (arelent *))
+    {
+      bfd_set_error (bfd_error_file_too_big);
+      return -1;
+    }
+#endif
   return (asect->reloc_count + 1) * sizeof (arelent *);
 }
 
@@ -8207,7 +8421,7 @@ _bfd_elf_canonicalize_symtab (bfd *abfd, asymbol **allocation)
   long symcount = bed->s->slurp_symbol_table (abfd, allocation, FALSE);
 
   if (symcount >= 0)
-    bfd_get_symcount (abfd) = symcount;
+    abfd->symcount = symcount;
   return symcount;
 }
 
@@ -8219,7 +8433,7 @@ _bfd_elf_canonicalize_dynamic_symtab (bfd *abfd,
   long symcount = bed->s->slurp_symbol_table (abfd, allocation, TRUE);
 
   if (symcount >= 0)
-    bfd_get_dynamic_symcount (abfd) = symcount;
+    abfd->dynsymcount = symcount;
   return symcount;
 }
 
@@ -8231,7 +8445,7 @@ _bfd_elf_canonicalize_dynamic_symtab (bfd *abfd,
 long
 _bfd_elf_get_dynamic_reloc_upper_bound (bfd *abfd)
 {
-  long ret;
+  bfd_size_type count;
   asection *s;
 
   if (elf_dynsymtab (abfd) == 0)
@@ -8240,15 +8454,20 @@ _bfd_elf_get_dynamic_reloc_upper_bound (bfd *abfd)
       return -1;
     }
 
-  ret = sizeof (arelent *);
+  count = 1;
   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))
-      ret += ((s->size / elf_section_data (s)->this_hdr.sh_entsize)
-             * sizeof (arelent *));
-
-  return ret;
+      {
+       count += s->size / elf_section_data (s)->this_hdr.sh_entsize;
+       if (count > LONG_MAX / sizeof (arelent *))
+         {
+           bfd_set_error (bfd_error_file_too_big);
+           return -1;
+         }
+      }
+  return count * sizeof (arelent *);
 }
 
 /* Canonicalize the dynamic relocation entries.  Note that we return the
@@ -8331,6 +8550,18 @@ error_return_verref:
          goto error_return;
        }
 
+      ufile_ptr filesize = bfd_get_file_size (abfd);
+      if (filesize > 0 && filesize < hdr->sh_size)
+       {
+         /* PR 24708: Avoid attempts to allocate a ridiculous amount
+            of memory.  */
+         bfd_set_error (bfd_error_no_memory);
+         _bfd_error_handler
+           /* xgettext:c-format */
+           (_("error: %pB version reference section is too large (%#" PRIx64 " bytes)"),
+            abfd, (uint64_t) hdr->sh_size);
+         goto error_return_verref;
+       }
       contents = (bfd_byte *) bfd_malloc (hdr->sh_size);
       if (contents == NULL)
        goto error_return_verref;
@@ -8648,7 +8879,7 @@ _bfd_elf_make_empty_symbol (bfd *abfd)
 {
   elf_symbol_type *newsym;
 
-  newsym = (elf_symbol_type *) bfd_zalloc (abfd, sizeof * newsym);
+  newsym = (elf_symbol_type *) bfd_zalloc (abfd, sizeof (*newsym));
   if (!newsym)
     return NULL;
   newsym->symbol.the_bfd = abfd;
@@ -8774,7 +9005,7 @@ _bfd_elf_find_nearest_line (bfd *abfd,
   if (_bfd_dwarf2_find_nearest_line (abfd, symbols, NULL, section, offset,
                                     filename_ptr, functionname_ptr,
                                     line_ptr, discriminator_ptr,
-                                    dwarf_debug_sections, 0,
+                                    dwarf_debug_sections,
                                     &elf_tdata (abfd)->dwarf2_find_line_info)
       || _bfd_dwarf1_find_nearest_line (abfd, symbols, section, offset,
                                        filename_ptr, functionname_ptr,
@@ -8814,7 +9045,7 @@ _bfd_elf_find_line (bfd *abfd, asymbol **symbols, asymbol *symbol,
 {
   return _bfd_dwarf2_find_nearest_line (abfd, symbols, symbol, NULL, 0,
                                        filename_ptr, NULL, line_ptr, NULL,
-                                       dwarf_debug_sections, 0,
+                                       dwarf_debug_sections,
                                        &elf_tdata (abfd)->dwarf2_find_line_info);
 }
 
@@ -8886,6 +9117,11 @@ _bfd_elf_set_section_contents (bfd *abfd,
   hdr = &elf_section_data (section)->this_hdr;
   if (hdr->sh_offset == (file_ptr) -1)
     {
+      if (bfd_section_is_ctf (section))
+       /* Nothing to do with this section: the contents are generated
+          later.  */
+       return TRUE;
+
       /* We must compress this section.  Write output to the buffer.  */
       unsigned char *contents = hdr->contents;
       if ((offset + count) > hdr->sh_size
@@ -9124,6 +9360,23 @@ _bfd_elfcore_make_pseudosection (bfd *abfd,
   return elfcore_maybe_make_sect (abfd, name, sect);
 }
 
+static bfd_boolean
+elfcore_make_auxv_note_section (bfd *abfd, Elf_Internal_Note *note,
+                               size_t offs)
+{
+  asection *sect = bfd_make_section_anyway_with_flags (abfd, ".auxv",
+                                                      SEC_HAS_CONTENTS);
+
+  if (sect == NULL)
+    return FALSE;
+
+  sect->size = note->descsz - offs;
+  sect->filepos = note->descpos + offs;
+  sect->alignment_power = 1 + bfd_get_arch_size (abfd) / 32;
+
+  return TRUE;
+}
+
 /* prstatus_t exists on:
      solaris 2.5+
      linux 2.[01] + glibc
@@ -9446,6 +9699,12 @@ elfcore_grok_aarch_sve (bfd *abfd, Elf_Internal_Note *note)
   return elfcore_make_note_pseudosection (abfd, ".reg-aarch-sve", note);
 }
 
+static bfd_boolean
+elfcore_grok_aarch_pauth (bfd *abfd, Elf_Internal_Note *note)
+{
+  return elfcore_make_note_pseudosection (abfd, ".reg-aarch-pauth", note);
+}
+
 #if defined (HAVE_PRPSINFO_T)
 typedef prpsinfo_t   elfcore_psinfo_t;
 #if defined (HAVE_PRPSINFO32_T)                /* Sparc64 cross Sparc32 */
@@ -9825,94 +10084,94 @@ elfcore_grok_note (bfd *abfd, Elf_Internal_Note *note)
 
     case NT_PPC_TAR:
       if (note->namesz == 6
-          && strcmp (note->namedata, "LINUX") == 0)
-        return elfcore_grok_ppc_tar (abfd, note);
+         && strcmp (note->namedata, "LINUX") == 0)
+       return elfcore_grok_ppc_tar (abfd, note);
       else
-        return TRUE;
+       return TRUE;
 
     case NT_PPC_PPR:
       if (note->namesz == 6
-          && strcmp (note->namedata, "LINUX") == 0)
-        return elfcore_grok_ppc_ppr (abfd, note);
+         && strcmp (note->namedata, "LINUX") == 0)
+       return elfcore_grok_ppc_ppr (abfd, note);
       else
-        return TRUE;
+       return TRUE;
 
     case NT_PPC_DSCR:
       if (note->namesz == 6
-          && strcmp (note->namedata, "LINUX") == 0)
-        return elfcore_grok_ppc_dscr (abfd, note);
+         && strcmp (note->namedata, "LINUX") == 0)
+       return elfcore_grok_ppc_dscr (abfd, note);
       else
-        return TRUE;
+       return TRUE;
 
     case NT_PPC_EBB:
       if (note->namesz == 6
-          && strcmp (note->namedata, "LINUX") == 0)
-        return elfcore_grok_ppc_ebb (abfd, note);
+         && strcmp (note->namedata, "LINUX") == 0)
+       return elfcore_grok_ppc_ebb (abfd, note);
       else
-        return TRUE;
+       return TRUE;
 
     case NT_PPC_PMU:
       if (note->namesz == 6
-          && strcmp (note->namedata, "LINUX") == 0)
-        return elfcore_grok_ppc_pmu (abfd, note);
+         && strcmp (note->namedata, "LINUX") == 0)
+       return elfcore_grok_ppc_pmu (abfd, note);
       else
-        return TRUE;
+       return TRUE;
 
     case NT_PPC_TM_CGPR:
       if (note->namesz == 6
-          && strcmp (note->namedata, "LINUX") == 0)
-        return elfcore_grok_ppc_tm_cgpr (abfd, note);
+         && strcmp (note->namedata, "LINUX") == 0)
+       return elfcore_grok_ppc_tm_cgpr (abfd, note);
       else
-        return TRUE;
+       return TRUE;
 
     case NT_PPC_TM_CFPR:
       if (note->namesz == 6
-          && strcmp (note->namedata, "LINUX") == 0)
-        return elfcore_grok_ppc_tm_cfpr (abfd, note);
+         && strcmp (note->namedata, "LINUX") == 0)
+       return elfcore_grok_ppc_tm_cfpr (abfd, note);
       else
-        return TRUE;
+       return TRUE;
 
     case NT_PPC_TM_CVMX:
       if (note->namesz == 6
-          && strcmp (note->namedata, "LINUX") == 0)
-        return elfcore_grok_ppc_tm_cvmx (abfd, note);
+         && strcmp (note->namedata, "LINUX") == 0)
+       return elfcore_grok_ppc_tm_cvmx (abfd, note);
       else
-        return TRUE;
+       return TRUE;
 
     case NT_PPC_TM_CVSX:
       if (note->namesz == 6
-          && strcmp (note->namedata, "LINUX") == 0)
-        return elfcore_grok_ppc_tm_cvsx (abfd, note);
+         && strcmp (note->namedata, "LINUX") == 0)
+       return elfcore_grok_ppc_tm_cvsx (abfd, note);
       else
-        return TRUE;
+       return TRUE;
 
     case NT_PPC_TM_SPR:
       if (note->namesz == 6
-          && strcmp (note->namedata, "LINUX") == 0)
-        return elfcore_grok_ppc_tm_spr (abfd, note);
+         && strcmp (note->namedata, "LINUX") == 0)
+       return elfcore_grok_ppc_tm_spr (abfd, note);
       else
-        return TRUE;
+       return TRUE;
 
     case NT_PPC_TM_CTAR:
       if (note->namesz == 6
-          && strcmp (note->namedata, "LINUX") == 0)
-        return elfcore_grok_ppc_tm_ctar (abfd, note);
+         && strcmp (note->namedata, "LINUX") == 0)
+       return elfcore_grok_ppc_tm_ctar (abfd, note);
       else
-        return TRUE;
+       return TRUE;
 
     case NT_PPC_TM_CPPR:
       if (note->namesz == 6
-          && strcmp (note->namedata, "LINUX") == 0)
-        return elfcore_grok_ppc_tm_cppr (abfd, note);
+         && strcmp (note->namedata, "LINUX") == 0)
+       return elfcore_grok_ppc_tm_cppr (abfd, note);
       else
-        return TRUE;
+       return TRUE;
 
     case NT_PPC_TM_CDSCR:
       if (note->namesz == 6
-          && strcmp (note->namedata, "LINUX") == 0)
-        return elfcore_grok_ppc_tm_cdscr (abfd, note);
+         && strcmp (note->namedata, "LINUX") == 0)
+       return elfcore_grok_ppc_tm_cdscr (abfd, note);
       else
-        return TRUE;
+       return TRUE;
 
     case NT_S390_HIGH_GPRS:
       if (note->namesz == 6
@@ -10040,6 +10299,13 @@ elfcore_grok_note (bfd *abfd, Elf_Internal_Note *note)
       else
        return TRUE;
 
+    case NT_ARM_PAC_MASK:
+      if (note->namesz == 6
+         && strcmp (note->namedata, "LINUX") == 0)
+       return elfcore_grok_aarch_pauth (abfd, note);
+      else
+       return TRUE;
+
     case NT_PRPSINFO:
     case NT_PSINFO:
       if (bed->elf_backend_grok_psinfo)
@@ -10052,18 +10318,7 @@ elfcore_grok_note (bfd *abfd, Elf_Internal_Note *note)
 #endif
 
     case NT_AUXV:
-      {
-       asection *sect = bfd_make_section_anyway_with_flags (abfd, ".auxv",
-                                                            SEC_HAS_CONTENTS);
-
-       if (sect == NULL)
-         return FALSE;
-       sect->size = note->descsz;
-       sect->filepos = note->descpos;
-       sect->alignment_power = 1 + bfd_get_arch_size (abfd) / 32;
-
-       return TRUE;
-      }
+      return elfcore_make_auxv_note_section (abfd, note, 0);
 
     case NT_FILE:
       return elfcore_make_note_pseudosection (abfd, ".note.linuxcore.file",
@@ -10115,8 +10370,8 @@ static bfd_boolean
 elfobj_grok_stapsdt_note_1 (bfd *abfd, Elf_Internal_Note *note)
 {
   struct sdt_note *cur =
-    (struct sdt_note *) bfd_alloc (abfd, sizeof (struct sdt_note)
-                                  + note->descsz);
+    (struct sdt_note *) bfd_alloc (abfd,
+                                  sizeof (struct sdt_note) + note->descsz);
 
   cur->next = (struct sdt_note *) (elf_tdata (abfd))->sdt_note_head;
   cur->size = (bfd_size_type) note->descsz;
@@ -10309,18 +10564,7 @@ elfcore_grok_freebsd_note (bfd *abfd, Elf_Internal_Note *note)
                                              note);
 
     case NT_FREEBSD_PROCSTAT_AUXV:
-      {
-       asection *sect = bfd_make_section_anyway_with_flags (abfd, ".auxv",
-                                                            SEC_HAS_CONTENTS);
-
-       if (sect == NULL)
-         return FALSE;
-       sect->size = note->descsz - 4;
-       sect->filepos = note->descpos + 4;
-       sect->alignment_power = 1 + bfd_get_arch_size (abfd) / 32;
-
-       return TRUE;
-      }
+      return elfcore_make_auxv_note_section (abfd, note, 4);
 
     case NT_X86_XSTATE:
       if (note->namesz == 8)
@@ -10384,17 +10628,24 @@ elfcore_grok_netbsd_note (bfd *abfd, Elf_Internal_Note *note)
   if (elfcore_netbsd_get_lwpid (note, &lwp))
     elf_tdata (abfd)->core->lwpid = lwp;
 
-  if (note->type == NT_NETBSDCORE_PROCINFO)
+  switch (note->type)
     {
+    case NT_NETBSDCORE_PROCINFO:
       /* NetBSD-specific core "procinfo".  Note that we expect to
         find this note before any of the others, which is fine,
         since the kernel writes this note out first when it
         creates a core file.  */
-
       return elfcore_grok_netbsd_procinfo (abfd, note);
+#ifdef NT_NETBSDCORE_AUXV
+    case NT_NETBSDCORE_AUXV:
+      /* NetBSD-specific Elf Auxiliary Vector data. */
+      return elfcore_make_auxv_note_section (abfd, note, 4);
+#endif
+    default:
+      break;
     }
 
-  /* As of Jan 2002 there are no other machine-independent notes
+  /* As of March 2017 there are no other machine-independent notes
      defined for NetBSD core files.  If the note type is less
      than the start of the machine-dependent note types, we don't
      understand it.  */
@@ -10422,6 +10673,23 @@ elfcore_grok_netbsd_note (bfd *abfd, Elf_Internal_Note *note)
          return TRUE;
        }
 
+      /* On SuperH, PT_GETREGS == mach+3 and PT_GETFPREGS == mach+5.
+        There's also old PT___GETREGS40 == mach + 1 for old reg
+        structure which lacks GBR.  */
+
+    case bfd_arch_sh:
+      switch (note->type)
+       {
+       case NT_NETBSDCORE_FIRSTMACH+3:
+         return elfcore_make_note_pseudosection (abfd, ".reg", note);
+
+       case NT_NETBSDCORE_FIRSTMACH+5:
+         return elfcore_make_note_pseudosection (abfd, ".reg2", note);
+
+       default:
+         return TRUE;
+       }
+
       /* On all other arch's, PT_GETREGS == mach+1 and
         PT_GETFPREGS == mach+3.  */
 
@@ -10478,18 +10746,7 @@ elfcore_grok_openbsd_note (bfd *abfd, Elf_Internal_Note *note)
     return elfcore_make_note_pseudosection (abfd, ".reg-xfp", note);
 
   if (note->type == NT_OPENBSD_AUXV)
-    {
-      asection *sect = bfd_make_section_anyway_with_flags (abfd, ".auxv",
-                                                          SEC_HAS_CONTENTS);
-
-      if (sect == NULL)
-       return FALSE;
-      sect->size = note->descsz;
-      sect->filepos = note->descpos;
-      sect->alignment_power = 1 + bfd_get_arch_size (abfd) / 32;
-
-      return TRUE;
-    }
+    return elfcore_make_auxv_note_section (abfd, note, 0);
 
   if (note->type == NT_OPENBSD_WCOOKIE)
     {
@@ -11023,158 +11280,158 @@ elfcore_write_ppc_vsx (bfd *abfd,
 
 char *
 elfcore_write_ppc_tar (bfd *abfd,
-                       char *buf,
-                       int *bufsiz,
-                       const void *ppc_tar,
-                       int size)
+                      char *buf,
+                      int *bufsiz,
+                      const void *ppc_tar,
+                      int size)
 {
   char *note_name = "LINUX";
   return elfcore_write_note (abfd, buf, bufsiz,
-                             note_name, NT_PPC_TAR, ppc_tar, size);
+                            note_name, NT_PPC_TAR, ppc_tar, size);
 }
 
 char *
 elfcore_write_ppc_ppr (bfd *abfd,
-                       char *buf,
-                       int *bufsiz,
-                       const void *ppc_ppr,
-                       int size)
+                      char *buf,
+                      int *bufsiz,
+                      const void *ppc_ppr,
+                      int size)
 {
   char *note_name = "LINUX";
   return elfcore_write_note (abfd, buf, bufsiz,
-                             note_name, NT_PPC_PPR, ppc_ppr, size);
+                            note_name, NT_PPC_PPR, ppc_ppr, size);
 }
 
 char *
 elfcore_write_ppc_dscr (bfd *abfd,
-                        char *buf,
-                        int *bufsiz,
-                        const void *ppc_dscr,
-                        int size)
+                       char *buf,
+                       int *bufsiz,
+                       const void *ppc_dscr,
+                       int size)
 {
   char *note_name = "LINUX";
   return elfcore_write_note (abfd, buf, bufsiz,
-                             note_name, NT_PPC_DSCR, ppc_dscr, size);
+                            note_name, NT_PPC_DSCR, ppc_dscr, size);
 }
 
 char *
 elfcore_write_ppc_ebb (bfd *abfd,
-                       char *buf,
-                       int *bufsiz,
-                       const void *ppc_ebb,
-                       int size)
+                      char *buf,
+                      int *bufsiz,
+                      const void *ppc_ebb,
+                      int size)
 {
   char *note_name = "LINUX";
   return elfcore_write_note (abfd, buf, bufsiz,
-                             note_name, NT_PPC_EBB, ppc_ebb, size);
+                            note_name, NT_PPC_EBB, ppc_ebb, size);
 }
 
 char *
 elfcore_write_ppc_pmu (bfd *abfd,
-                       char *buf,
-                       int *bufsiz,
-                       const void *ppc_pmu,
-                       int size)
+                      char *buf,
+                      int *bufsiz,
+                      const void *ppc_pmu,
+                      int size)
 {
   char *note_name = "LINUX";
   return elfcore_write_note (abfd, buf, bufsiz,
-                             note_name, NT_PPC_PMU, ppc_pmu, size);
+                            note_name, NT_PPC_PMU, ppc_pmu, size);
 }
 
 char *
 elfcore_write_ppc_tm_cgpr (bfd *abfd,
-                           char *buf,
-                           int *bufsiz,
-                           const void *ppc_tm_cgpr,
-                           int size)
+                          char *buf,
+                          int *bufsiz,
+                          const void *ppc_tm_cgpr,
+                          int size)
 {
   char *note_name = "LINUX";
   return elfcore_write_note (abfd, buf, bufsiz,
-                             note_name, NT_PPC_TM_CGPR, ppc_tm_cgpr, size);
+                            note_name, NT_PPC_TM_CGPR, ppc_tm_cgpr, size);
 }
 
 char *
 elfcore_write_ppc_tm_cfpr (bfd *abfd,
-                           char *buf,
-                           int *bufsiz,
-                           const void *ppc_tm_cfpr,
-                           int size)
+                          char *buf,
+                          int *bufsiz,
+                          const void *ppc_tm_cfpr,
+                          int size)
 {
   char *note_name = "LINUX";
   return elfcore_write_note (abfd, buf, bufsiz,
-                             note_name, NT_PPC_TM_CFPR, ppc_tm_cfpr, size);
+                            note_name, NT_PPC_TM_CFPR, ppc_tm_cfpr, size);
 }
 
 char *
 elfcore_write_ppc_tm_cvmx (bfd *abfd,
-                           char *buf,
-                           int *bufsiz,
-                           const void *ppc_tm_cvmx,
-                           int size)
+                          char *buf,
+                          int *bufsiz,
+                          const void *ppc_tm_cvmx,
+                          int size)
 {
   char *note_name = "LINUX";
   return elfcore_write_note (abfd, buf, bufsiz,
-                             note_name, NT_PPC_TM_CVMX, ppc_tm_cvmx, size);
+                            note_name, NT_PPC_TM_CVMX, ppc_tm_cvmx, size);
 }
 
 char *
 elfcore_write_ppc_tm_cvsx (bfd *abfd,
-                           char *buf,
-                           int *bufsiz,
-                           const void *ppc_tm_cvsx,
-                           int size)
+                          char *buf,
+                          int *bufsiz,
+                          const void *ppc_tm_cvsx,
+                          int size)
 {
   char *note_name = "LINUX";
   return elfcore_write_note (abfd, buf, bufsiz,
-                             note_name, NT_PPC_TM_CVSX, ppc_tm_cvsx, size);
+                            note_name, NT_PPC_TM_CVSX, ppc_tm_cvsx, size);
 }
 
 char *
 elfcore_write_ppc_tm_spr (bfd *abfd,
-                          char *buf,
-                          int *bufsiz,
-                          const void *ppc_tm_spr,
-                          int size)
+                         char *buf,
+                         int *bufsiz,
+                         const void *ppc_tm_spr,
+                         int size)
 {
   char *note_name = "LINUX";
   return elfcore_write_note (abfd, buf, bufsiz,
-                             note_name, NT_PPC_TM_SPR, ppc_tm_spr, size);
+                            note_name, NT_PPC_TM_SPR, ppc_tm_spr, size);
 }
 
 char *
 elfcore_write_ppc_tm_ctar (bfd *abfd,
-                           char *buf,
-                           int *bufsiz,
-                           const void *ppc_tm_ctar,
-                           int size)
+                          char *buf,
+                          int *bufsiz,
+                          const void *ppc_tm_ctar,
+                          int size)
 {
   char *note_name = "LINUX";
   return elfcore_write_note (abfd, buf, bufsiz,
-                             note_name, NT_PPC_TM_CTAR, ppc_tm_ctar, size);
+                            note_name, NT_PPC_TM_CTAR, ppc_tm_ctar, size);
 }
 
 char *
 elfcore_write_ppc_tm_cppr (bfd *abfd,
-                           char *buf,
-                           int *bufsiz,
-                           const void *ppc_tm_cppr,
-                           int size)
+                          char *buf,
+                          int *bufsiz,
+                          const void *ppc_tm_cppr,
+                          int size)
 {
   char *note_name = "LINUX";
   return elfcore_write_note (abfd, buf, bufsiz,
-                             note_name, NT_PPC_TM_CPPR, ppc_tm_cppr, size);
+                            note_name, NT_PPC_TM_CPPR, ppc_tm_cppr, size);
 }
 
 char *
 elfcore_write_ppc_tm_cdscr (bfd *abfd,
-                            char *buf,
-                            int *bufsiz,
-                            const void *ppc_tm_cdscr,
-                            int size)
+                           char *buf,
+                           int *bufsiz,
+                           const void *ppc_tm_cdscr,
+                           int size)
 {
   char *note_name = "LINUX";
   return elfcore_write_note (abfd, buf, bufsiz,
-                             note_name, NT_PPC_TM_CDSCR, ppc_tm_cdscr, size);
+                            note_name, NT_PPC_TM_CDSCR, ppc_tm_cdscr, size);
 }
 
 static char *
@@ -11399,6 +11656,18 @@ elfcore_write_aarch_sve (bfd *abfd,
                             note_name, NT_ARM_SVE, aarch_sve, size);
 }
 
+char *
+elfcore_write_aarch_pauth (bfd *abfd,
+                          char *buf,
+                          int *bufsiz,
+                          const void *aarch_pauth,
+                          int size)
+{
+  char *note_name = "LINUX";
+  return elfcore_write_note (abfd, buf, bufsiz,
+                            note_name, NT_ARM_PAC_MASK, aarch_pauth, size);
+}
+
 char *
 elfcore_write_register_note (bfd *abfd,
                             char *buf,
@@ -11479,6 +11748,8 @@ elfcore_write_register_note (bfd *abfd,
     return elfcore_write_aarch_hw_watch (abfd, buf, bufsiz, data, size);
   if (strcmp (section, ".reg-aarch-sve") == 0)
     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);
   return NULL;
 }
 
@@ -11909,21 +12180,42 @@ asection _bfd_elf_large_com_section
                      "LARGE_COMMON", 0, SEC_IS_COMMON);
 
 void
-_bfd_elf_post_process_headers (bfd * abfd,
-                              struct bfd_link_info * link_info ATTRIBUTE_UNUSED)
+_bfd_elf_post_process_headers (bfd *abfd ATTRIBUTE_UNUSED,
+                              struct bfd_link_info *info ATTRIBUTE_UNUSED)
 {
-  Elf_Internal_Ehdr * i_ehdrp; /* ELF file header, internal form.  */
+}
 
-  i_ehdrp = elf_elfheader (abfd);
+bfd_boolean
+_bfd_elf_final_write_processing (bfd *abfd)
+{
+  Elf_Internal_Ehdr *i_ehdrp;  /* ELF file header, internal form.  */
 
-  i_ehdrp->e_ident[EI_OSABI] = get_elf_backend_data (abfd)->elf_osabi;
+  i_ehdrp = elf_elfheader (abfd);
 
-  /* To make things simpler for the loader on Linux systems we set the
-     osabi field to ELFOSABI_GNU if the binary contains symbols of
-     the STT_GNU_IFUNC type or STB_GNU_UNIQUE binding.  */
-  if (i_ehdrp->e_ident[EI_OSABI] == ELFOSABI_NONE
-      && elf_tdata (abfd)->has_gnu_symbols)
-    i_ehdrp->e_ident[EI_OSABI] = ELFOSABI_GNU;
+  if (i_ehdrp->e_ident[EI_OSABI] == ELFOSABI_NONE)
+    i_ehdrp->e_ident[EI_OSABI] = get_elf_backend_data (abfd)->elf_osabi;
+
+  /* Set the osabi field to ELFOSABI_GNU if the binary contains
+     SHF_GNU_MBIND sections or symbols of STT_GNU_IFUNC type or
+     STB_GNU_UNIQUE binding.  */
+  if (elf_tdata (abfd)->has_gnu_osabi != 0)
+    {
+      if (i_ehdrp->e_ident[EI_OSABI] == ELFOSABI_NONE)
+       i_ehdrp->e_ident[EI_OSABI] = ELFOSABI_GNU;
+      else if (i_ehdrp->e_ident[EI_OSABI] != ELFOSABI_GNU
+              && i_ehdrp->e_ident[EI_OSABI] != ELFOSABI_FREEBSD)
+       {
+         if (elf_tdata (abfd)->has_gnu_osabi & elf_gnu_osabi_mbind)
+           _bfd_error_handler (_("GNU_MBIND section is unsupported"));
+         if (elf_tdata (abfd)->has_gnu_osabi & elf_gnu_osabi_ifunc)
+           _bfd_error_handler (_("symbol type STT_GNU_IFUNC is unsupported"));
+         if (elf_tdata (abfd)->has_gnu_osabi & elf_gnu_osabi_unique)
+           _bfd_error_handler (_("symbol binding STB_GNU_UNIQUE is unsupported"));
+         bfd_set_error (bfd_error_bad_value);
+         return FALSE;
+       }
+    }
+  return TRUE;
 }
 
 
This page took 0.048291 seconds and 4 git commands to generate.