x86: consistently convert to byte registers for TEST w/ imm optimization
[deliverable/binutils-gdb.git] / bfd / elf.c
index 9b61f06a84c9b5c5783bab86b64bd289b8f86496..08aaab644a821b75c984fa6c9f01345a0d0afb0a 100644 (file)
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -1,6 +1,6 @@
 /* ELF executable support for BFD.
 
-   Copyright (C) 1993-2017 Free Software Foundation, Inc.
+   Copyright (C) 1993-2020 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"
@@ -50,11 +51,9 @@ SECTION
 
 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_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
@@ -273,7 +272,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;
@@ -297,6 +296,7 @@ bfd_elf_get_str_section (bfd *abfd, unsigned int shindex)
       /* Allocate and clear an extra byte at the end, to prevent crashes
         in case the string table is not terminated.  */
       if (shstrtabsize + 1 <= 1
+         || shstrtabsize > bfd_get_file_size (abfd)
          || bfd_seek (abfd, offset, SEEK_SET) != 0
          || (shstrtab = (bfd_byte *) bfd_alloc (abfd, shstrtabsize + 1)) == NULL)
        shstrtab = NULL;
@@ -339,7 +339,7 @@ bfd_elf_string_from_elf_section (bfd *abfd,
        {
          /* PR 17512: file: f057ec89.  */
          /* xgettext:c-format */
-         _bfd_error_handler (_("%B: attempt to load strings from"
+         _bfd_error_handler (_("%pB: attempt to load strings from"
                                " a non-string section (number %d)"),
                              abfd, shindex);
          return NULL;
@@ -348,14 +348,24 @@ 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)
     {
       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, hdr->sh_size,
+       (_("%pB: invalid string offset %u >= %" PRIu64 " for section `%s'"),
+        abfd, strindex, (uint64_t) hdr->sh_size,
         (shindex == shstrndx && strindex == hdr->sh_name
          ? ".shstrtab"
          : bfd_elf_string_from_elf_section (abfd, shstrndx, hdr->sh_name)));
@@ -462,7 +472,7 @@ bfd_elf_get_elf_syms (bfd *ibfd,
       if (extshndx_buf == NULL)
        {
          alloc_extshndx = (Elf_External_Sym_Shndx *)
-              bfd_malloc2 (symcount, sizeof (Elf_External_Sym_Shndx));
+             bfd_malloc2 (symcount, sizeof (Elf_External_Sym_Shndx));
          extshndx_buf = alloc_extshndx;
        }
       if (extshndx_buf == NULL
@@ -477,7 +487,7 @@ bfd_elf_get_elf_syms (bfd *ibfd,
   if (intsym_buf == NULL)
     {
       alloc_intsym = (Elf_Internal_Sym *)
-          bfd_malloc2 (symcount, sizeof (Elf_Internal_Sym));
+         bfd_malloc2 (symcount, sizeof (Elf_Internal_Sym));
       intsym_buf = alloc_intsym;
       if (intsym_buf == NULL)
        goto out;
@@ -486,14 +496,14 @@ bfd_elf_get_elf_syms (bfd *ibfd,
   /* Convert the symbols to internal form.  */
   isymend = intsym_buf + symcount;
   for (esym = (const bfd_byte *) extsym_buf, isym = intsym_buf,
-           shndx = extshndx_buf;
+          shndx = extshndx_buf;
        isym < isymend;
        esym += extsym_size, isym++, shndx = shndx != NULL ? shndx + 1 : NULL)
     if (!(*bed->s->swap_symbol_in) (ibfd, esym, shndx, isym))
       {
        symoffset += (esym - (bfd_byte *) extsym_buf) / extsym_size;
        /* xgettext:c-format */
-       _bfd_error_handler (_("%B symbol number %lu references"
+       _bfd_error_handler (_("%pB symbol number %lu references"
                              " nonexistent SHT_SYMTAB_SHNDX section"),
                            ibfd, (unsigned long) symoffset);
        if (alloc_intsym != NULL)
@@ -534,7 +544,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;
 }
@@ -623,10 +633,11 @@ setup_group (bfd *abfd, Elf_Internal_Shdr *hdr, asection *newsect)
 
          elf_tdata (abfd)->num_group = num_group;
          elf_tdata (abfd)->group_sect_ptr = (Elf_Internal_Shdr **)
-              bfd_alloc2 (abfd, num_group, sizeof (Elf_Internal_Shdr *));
+             bfd_alloc2 (abfd, num_group, sizeof (Elf_Internal_Shdr *));
          if (elf_tdata (abfd)->group_sect_ptr == NULL)
            return FALSE;
-         memset (elf_tdata (abfd)->group_sect_ptr, 0, num_group * sizeof (Elf_Internal_Shdr *));
+         memset (elf_tdata (abfd)->group_sect_ptr, 0,
+                 num_group * sizeof (Elf_Internal_Shdr *));
          num_group = 0;
 
          for (i = 0; i < shnum; i++)
@@ -638,11 +649,11 @@ setup_group (bfd *abfd, Elf_Internal_Shdr *hdr, asection *newsect)
                  unsigned char *src;
                  Elf_Internal_Group *dest;
 
-                  /* Make sure the group section has a BFD section
-                     attached to it.  */
-                  if (!bfd_section_from_shdr (abfd, i))
-                    return FALSE;
-                  
+                 /* Make sure the group section has a BFD section
+                    attached to it.  */
+                 if (!bfd_section_from_shdr (abfd, i))
+                   return FALSE;
+
                  /* Add to list of sections.  */
                  elf_tdata (abfd)->group_sect_ptr[num_group] = shdr;
                  num_group += 1;
@@ -651,14 +662,15 @@ 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)
                    {
                      _bfd_error_handler
                        /* xgettext:c-format */
-                       (_("%B: corrupt size field in group section"
-                          " header: %#Lx"), abfd, shdr->sh_size);
+                       (_("%pB: corrupt size field in group section"
+                          " header: %#" PRIx64),
+                        abfd, (uint64_t) shdr->sh_size);
                      bfd_set_error (bfd_error_bad_value);
                      -- num_group;
                      continue;
@@ -672,8 +684,9 @@ setup_group (bfd *abfd, Elf_Internal_Shdr *hdr, asection *newsect)
                    {
                      _bfd_error_handler
                        /* xgettext:c-format */
-                       (_("%B: invalid size field in group section"
-                          " header: %#Lx"), abfd, shdr->sh_size);
+                       (_("%pB: invalid size field in group section"
+                          " header: %#" PRIx64 ""),
+                        abfd, (uint64_t) shdr->sh_size);
                      bfd_set_error (bfd_error_bad_value);
                      -- num_group;
                      /* PR 17510: If the group contents are even
@@ -705,13 +718,24 @@ setup_group (bfd *abfd, Elf_Internal_Shdr *hdr, asection *newsect)
                              |= SEC_LINK_ONCE | SEC_LINK_DUPLICATES_DISCARD;
                          break;
                        }
-                     if (idx >= shnum)
+                     if (idx < shnum)
+                       {
+                         dest->shdr = elf_elfsections (abfd)[idx];
+                         /* PR binutils/23199: All sections in a
+                            section group should be marked with
+                            SHF_GROUP.  But some tools generate
+                            broken objects without SHF_GROUP.  Fix
+                            them up here.  */
+                         dest->shdr->sh_flags |= SHF_GROUP;
+                       }
+                     if (idx >= shnum
+                         || dest->shdr->sh_type == SHT_GROUP)
                        {
                          _bfd_error_handler
-                           (_("%B: invalid SHT_GROUP entry"), abfd);
-                         idx = 0;
+                           (_("%pB: invalid entry in SHT_GROUP section [%u]"),
+                              abfd, i);
+                         dest->shdr = NULL;
                        }
-                     dest->shdr = elf_elfsections (abfd)[idx];
                    }
                }
            }
@@ -727,7 +751,7 @@ setup_group (bfd *abfd, Elf_Internal_Shdr *hdr, asection *newsect)
                  elf_tdata (abfd)->group_sect_ptr = NULL;
                  elf_tdata (abfd)->num_group = num_group = -1;
                  _bfd_error_handler
-                   (_("%B: no valid group sections found"), abfd);
+                   (_("%pB: no valid group sections found"), abfd);
                  bfd_set_error (bfd_error_bad_value);
                }
            }
@@ -736,10 +760,14 @@ setup_group (bfd *abfd, Elf_Internal_Shdr *hdr, asection *newsect)
 
   if (num_group != (unsigned) -1)
     {
-      unsigned int i;
+      unsigned int search_offset = elf_tdata (abfd)->group_search_offset;
+      unsigned int j;
 
-      for (i = 0; i < num_group; i++)
+      for (j = 0; j < num_group; j++)
        {
+         /* Begin search from previous found group.  */
+         unsigned i = (j + search_offset) % num_group;
+
          Elf_Internal_Shdr *shdr = elf_tdata (abfd)->group_sect_ptr[i];
          Elf_Internal_Group *idx;
          bfd_size_type n_elt;
@@ -752,7 +780,7 @@ setup_group (bfd *abfd, Elf_Internal_Shdr *hdr, asection *newsect)
            {
              /* See PR 21957 for a reproducer.  */
              /* xgettext:c-format */
-             _bfd_error_handler (_("%B: group section '%A' has no contents"),
+             _bfd_error_handler (_("%pB: group section '%pA' has no contents"),
                                  abfd, shdr->bfd_section);
              elf_tdata (abfd)->group_sect_ptr[i] = NULL;
              bfd_set_error (bfd_error_bad_value);
@@ -773,7 +801,8 @@ setup_group (bfd *abfd, Elf_Internal_Shdr *hdr, asection *newsect)
                idx = (Elf_Internal_Group *) shdr->contents;
                n_elt = shdr->sh_size / 4;
                while (--n_elt != 0)
-                 if ((s = (++idx)->shdr->bfd_section) != NULL
+                 if ((++idx)->shdr != NULL
+                     && (s = idx->shdr->bfd_section) != NULL
                      && elf_next_in_group (s) != NULL)
                    break;
                if (n_elt != 0)
@@ -802,7 +831,8 @@ setup_group (bfd *abfd, Elf_Internal_Shdr *hdr, asection *newsect)
                if (shdr->bfd_section != NULL)
                  elf_next_in_group (shdr->bfd_section) = newsect;
 
-               i = num_group - 1;
+               elf_tdata (abfd)->group_search_offset = i;
+               j = num_group - 1;
                break;
              }
        }
@@ -811,7 +841,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 (_("%pB: no group info for section '%pA'"),
                          abfd, newsect);
       return FALSE;
     }
@@ -842,7 +872,7 @@ _bfd_elf_setup_sections (bfd *abfd)
              if (bed->link_order_error_handler)
                bed->link_order_error_handler
                  /* xgettext:c-format */
-                 (_("%B: warning: sh_link not set for section `%A'"),
+                 (_("%pB: warning: sh_link not set for section `%pA'"),
                   abfd, s);
            }
          else
@@ -862,7 +892,7 @@ _bfd_elf_setup_sections (bfd *abfd)
                {
                  _bfd_error_handler
                    /* xgettext:c-format */
-                   (_("%B: sh_link [%d] in section `%A' is incorrect"),
+                   (_("%pB: sh_link [%d] in section `%pA' is incorrect"),
                     s->owner, elfsec, s);
                  result = FALSE;
                }
@@ -875,7 +905,7 @@ _bfd_elf_setup_sections (bfd *abfd)
        {
          _bfd_error_handler
            /* xgettext:c-format */
-           (_("%B: SHT_GROUP section [index %d] has no SHF_GROUP sections"),
+           (_("%pB: SHT_GROUP section [index %d] has no SHF_GROUP sections"),
             abfd, elf_section_data (s)->this_idx);
          result = FALSE;
        }
@@ -896,7 +926,7 @@ _bfd_elf_setup_sections (bfd *abfd)
        {
          _bfd_error_handler
            /* xgettext:c-format */
-           (_("%B: section group entry number %u is corrupt"),
+           (_("%pB: section group entry number %u is corrupt"),
             abfd, i);
          result = FALSE;
          continue;
@@ -913,20 +943,13 @@ _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
                /* xgettext:c-format */
-               (_("%B: unknown type [%#x] section `%s' in group [%A]"),
+               (_("%pB: unknown type [%#x] section `%s' in group [%pA]"),
                 abfd,
                 idx->shdr->sh_type,
                 bfd_elf_string_from_elf_section (abfd,
@@ -948,6 +971,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)
 {
@@ -973,6 +1004,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.  */
 
@@ -1003,10 +1046,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;
@@ -1041,29 +1083,35 @@ _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,
         not any sort of flag.  Their SEC_ALLOC bits are cleared.  */
       if (name [0] == '.')
        {
-         const char *p;
-         int n;
-         if (name[1] == 'd')
-           p = ".debug", n = 6;
-         else if (name[1] == 'g' && name[2] == 'n')
-           p = ".gnu.linkonce.wi.", n = 17;
-         else if (name[1] == 'g' && name[2] == 'd')
-           p = ".gdb_index", n = 11; /* yes we really do mean 11.  */
-         else if (name[1] == 'l')
-           p = ".line", n = 5;
-         else if (name[1] == 's')
-           p = ".stab", n = 5;
-         else if (name[1] == 'z')
-           p = ".zdebug", n = 7;
-         else
-           p = NULL, n = 0;
-         if (p != NULL && strncmp (name, p, n) == 0)
+         if (strncmp (name, ".debug", 6) == 0
+             || strncmp (name, ".gnu.linkonce.wi.", 17) == 0
+             || strncmp (name, ".zdebug", 7) == 0)
+           flags |= SEC_DEBUGGING | SEC_ELF_OCTETS;
+         else if (strncmp (name, GNU_BUILD_ATTRS_SECTION_NAME, 21) == 0
+                  || strncmp (name, ".note.gnu", 9) == 0)
+           flags |= SEC_ELF_OCTETS;
+         else if (strncmp (name, ".line", 5) == 0
+                  || strncmp (name, ".stab", 5) == 0
+                  || strcmp (name, ".gdb_index") == 0)
            flags |= SEC_DEBUGGING;
        }
     }
@@ -1083,7 +1131,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
@@ -1096,7 +1144,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);
     }
 
@@ -1161,11 +1210,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.  */
@@ -1195,7 +1245,7 @@ _bfd_elf_make_section_from_shdr (bfd *abfd,
            {
              _bfd_error_handler
                /* xgettext:c-format */
-               (_("%B: unable to initialize compress status for section %s"),
+               (_("%pB: unable to initialize compress status for section %s"),
                 abfd, name);
              return FALSE;
            }
@@ -1206,7 +1256,7 @@ _bfd_elf_make_section_from_shdr (bfd *abfd,
            {
              _bfd_error_handler
                /* xgettext:c-format */
-               (_("%B: unable to initialize decompress status for section %s"),
+               (_("%pB: unable to initialize decompress status for section %s"),
                 abfd, name);
              return FALSE;
            }
@@ -1225,7 +1275,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
@@ -1234,6 +1284,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;
 }
 
@@ -1283,15 +1344,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
@@ -1332,7 +1393,7 @@ find_link (const bfd *obfd, const Elf_Internal_Shdr *iheader,
 /* PR 19938: Attempt to set the ELF section header fields of an OS or
    Processor specific section, based upon a matching input section.
    Returns TRUE upon success, FALSE otherwise.  */
-   
+
 static bfd_boolean
 copy_special_section_fields (const bfd *ibfd,
                             bfd *obfd,
@@ -1387,7 +1448,7 @@ copy_special_section_fields (const bfd *ibfd,
        {
          _bfd_error_handler
            /* xgettext:c-format */
-           (_("%B: Invalid sh_link field (%d) in section number %d"),
+           (_("%pB: invalid sh_link field (%d) in section number %d"),
             ibfd, iheader->sh_link, secnum);
          return FALSE;
        }
@@ -1403,7 +1464,7 @@ copy_special_section_fields (const bfd *ibfd,
           if we could not find a match ?  */
        _bfd_error_handler
          /* xgettext:c-format */
-         (_("%B: Failed to find link section for section %d"), obfd, secnum);
+         (_("%pB: failed to find link section for section %d"), obfd, secnum);
     }
 
   if (iheader->sh_info)
@@ -1430,12 +1491,12 @@ copy_special_section_fields (const bfd *ibfd,
       else
        _bfd_error_handler
          /* xgettext:c-format */
-         (_("%B: Failed to find info section for section %d"), obfd, secnum);
+         (_("%pB: failed to find info section for section %d"), obfd, secnum);
     }
 
   return changed;
 }
-  
+
 /* Copy the program header and other data from one object module to
    another.  */
 
@@ -1467,7 +1528,7 @@ _bfd_elf_copy_private_bfd_data (bfd *ibfd, bfd *obfd)
   if (elf_elfheader (ibfd)->e_ident[EI_ABIVERSION])
     elf_elfheader (obfd)->e_ident[EI_ABIVERSION]
       = elf_elfheader (ibfd)->e_ident[EI_ABIVERSION];
-  
+
   /* Copy object attributes.  */
   _bfd_elf_copy_obj_attributes (ibfd, obfd);
 
@@ -1663,7 +1724,7 @@ _bfd_elf_print_private_bfd_data (bfd *abfd, void *farg)
        goto error_return;
       extdynend = extdyn + s->size;
       /* PR 17512: file: id:000006,sig:06,src:000000,op:flip4,pos:5664.
-         Fix range check.  */
+        Fix range check.  */
       for (; extdyn <= (extdynend - extdynsize); extdyn += extdynsize)
        {
          Elf_Internal_Dyn dyn;
@@ -1849,7 +1910,10 @@ _bfd_elf_get_symbol_version_string (bfd *abfd, asymbol *symbol,
 
       if (vernum == 0)
        version_string = "";
-      else if (vernum == 1)
+      else if (vernum == 1
+              && (vernum > elf_tdata (abfd)->cverdefs
+                  || (elf_tdata (abfd)->verdef[0].vd_flags
+                      == VER_FLG_BASE)))
        version_string = "Base";
       else if (vernum <= elf_tdata (abfd)->cverdefs)
        version_string =
@@ -1858,7 +1922,7 @@ _bfd_elf_get_symbol_version_string (bfd *abfd, asymbol *symbol,
        {
          Elf_Internal_Verneed *t;
 
-         version_string = "";
+         version_string = _("<corrupt>");
          for (t = elf_tdata (abfd)->verref;
               t != NULL;
               t = t->vn_nextref)
@@ -1992,7 +2056,7 @@ bfd_section_from_shdr (bfd *abfd, unsigned int shindex)
   if (++ nesting > 3)
     {
       /* PR17512: A corrupt ELF binary might contain a recursive group of
-        sections, with each the string indicies pointing to the next in the
+        sections, with each the string indices pointing to the next in the
         loop.  Detect this here, by refusing to load a section that we are
         already in the process of loading.  We only trigger this test if
         we have nested at least three sections deep as normal ELF binaries
@@ -2005,15 +2069,14 @@ 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])
        {
          _bfd_error_handler
-           (_("%B: warning: loop in section dependencies detected"), abfd);
+           (_("%pB: warning: loop in section dependencies detected"), abfd);
          return FALSE;
        }
       sections_being_created [shindex] = TRUE;
@@ -2121,7 +2184,7 @@ bfd_section_from_shdr (bfd *abfd, unsigned int shindex)
        {
          _bfd_error_handler
            /* xgettext:c-format */
-           (_("%B: warning: multiple symbol tables detected"
+           (_("%pB: warning: multiple symbol tables detected"
               " - ignoring the table in section %u"),
             abfd, shindex);
          goto success;
@@ -2205,7 +2268,7 @@ bfd_section_from_shdr (bfd *abfd, unsigned int shindex)
        {
          _bfd_error_handler
            /* xgettext:c-format */
-           (_("%B: warning: multiple dynamic symbol tables detected"
+           (_("%pB: warning: multiple dynamic symbol tables detected"
               " - ignoring the table in section %u"),
             abfd, shindex);
          goto success;
@@ -2227,8 +2290,8 @@ bfd_section_from_shdr (bfd *abfd, unsigned int shindex)
        for (entry = elf_symtab_shndx_list (abfd); entry != NULL; entry = entry->next)
          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;
@@ -2318,7 +2381,7 @@ bfd_section_from_shdr (bfd *abfd, unsigned int shindex)
          {
            _bfd_error_handler
              /* xgettext:c-format */
-             (_("%B: invalid link %u for reloc section %s (index %u)"),
+             (_("%pB: 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);
@@ -2365,15 +2428,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
@@ -2397,9 +2463,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;
@@ -2477,7 +2552,7 @@ bfd_section_from_shdr (bfd *abfd, unsigned int shindex)
               for applications?  */
            _bfd_error_handler
              /* xgettext:c-format */
-             (_("%B: unknown type [%#x] section `%s'"),
+             (_("%pB: unknown type [%#x] section `%s'"),
               abfd, hdr->sh_type, name);
          else
            {
@@ -2492,7 +2567,7 @@ bfd_section_from_shdr (bfd *abfd, unsigned int shindex)
        /* FIXME: We should handle this section.  */
        _bfd_error_handler
          /* xgettext:c-format */
-         (_("%B: unknown type [%#x] section `%s'"),
+         (_("%pB: unknown type [%#x] section `%s'"),
           abfd, hdr->sh_type, name);
       else if (hdr->sh_type >= SHT_LOOS && hdr->sh_type <= SHT_HIOS)
        {
@@ -2503,7 +2578,7 @@ bfd_section_from_shdr (bfd *abfd, unsigned int shindex)
               be rejected with an error message.  */
            _bfd_error_handler
              /* xgettext:c-format */
-             (_("%B: unknown type [%#x] section `%s'"),
+             (_("%pB: unknown type [%#x] section `%s'"),
               abfd, hdr->sh_type, name);
          else
            {
@@ -2516,7 +2591,7 @@ bfd_section_from_shdr (bfd *abfd, unsigned int shindex)
        /* FIXME: We should handle this section.  */
        _bfd_error_handler
          /* xgettext:c-format */
-         (_("%B: unknown type [%#x] section `%s'"),
+         (_("%pB: unknown type [%#x] section `%s'"),
           abfd, hdr->sh_type, name);
 
       goto fail;
@@ -2580,95 +2655,96 @@ bfd_section_from_elf_index (bfd *abfd, unsigned int sec_index)
 static const struct bfd_elf_special_section special_sections_b[] =
 {
   { STRING_COMMA_LEN (".bss"), -2, SHT_NOBITS,   SHF_ALLOC + SHF_WRITE },
-  { NULL,                   0,  0, 0,            0 }
+  { NULL,                  0,  0, 0,            0 }
 };
 
 static const struct bfd_elf_special_section special_sections_c[] =
 {
   { STRING_COMMA_LEN (".comment"), 0, SHT_PROGBITS, 0 },
-  { NULL,                       0, 0, 0,            0 }
+  { STRING_COMMA_LEN (".ctf"), 0, SHT_PROGBITS,    0 },
+  { NULL,                      0, 0, 0,            0 }
 };
 
 static const struct bfd_elf_special_section special_sections_d[] =
 {
-  { STRING_COMMA_LEN (".data"),         -2, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE },
-  { STRING_COMMA_LEN (".data1"),         0, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE },
+  { STRING_COMMA_LEN (".data"),                -2, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE },
+  { STRING_COMMA_LEN (".data1"),        0, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE },
   /* There are more DWARF sections than these, but they needn't be added here
      unless you have to cope with broken compilers that don't emit section
      attributes or you want to help the user writing assembler.  */
-  { STRING_COMMA_LEN (".debug"),         0, SHT_PROGBITS, 0 },
-  { STRING_COMMA_LEN (".debug_line"),    0, SHT_PROGBITS, 0 },
-  { STRING_COMMA_LEN (".debug_info"),    0, SHT_PROGBITS, 0 },
-  { STRING_COMMA_LEN (".debug_abbrev"),  0, SHT_PROGBITS, 0 },
+  { STRING_COMMA_LEN (".debug"),        0, SHT_PROGBITS, 0 },
+  { STRING_COMMA_LEN (".debug_line"),   0, SHT_PROGBITS, 0 },
+  { STRING_COMMA_LEN (".debug_info"),   0, SHT_PROGBITS, 0 },
+  { STRING_COMMA_LEN (".debug_abbrev"),         0, SHT_PROGBITS, 0 },
   { STRING_COMMA_LEN (".debug_aranges"), 0, SHT_PROGBITS, 0 },
-  { STRING_COMMA_LEN (".dynamic"),       0, SHT_DYNAMIC,  SHF_ALLOC },
-  { STRING_COMMA_LEN (".dynstr"),        0, SHT_STRTAB,   SHF_ALLOC },
-  { STRING_COMMA_LEN (".dynsym"),        0, SHT_DYNSYM,   SHF_ALLOC },
-  { NULL,                      0,        0, 0,            0 }
+  { STRING_COMMA_LEN (".dynamic"),      0, SHT_DYNAMIC,  SHF_ALLOC },
+  { STRING_COMMA_LEN (".dynstr"),       0, SHT_STRTAB,   SHF_ALLOC },
+  { STRING_COMMA_LEN (".dynsym"),       0, SHT_DYNSYM,   SHF_ALLOC },
+  { NULL,                     0,        0, 0,            0 }
 };
 
 static const struct bfd_elf_special_section special_sections_f[] =
 {
-  { STRING_COMMA_LEN (".fini"),        0, SHT_PROGBITS,   SHF_ALLOC + SHF_EXECINSTR },
+  { STRING_COMMA_LEN (".fini"),               0, SHT_PROGBITS,   SHF_ALLOC + SHF_EXECINSTR },
   { STRING_COMMA_LEN (".fini_array"), -2, SHT_FINI_ARRAY, SHF_ALLOC + SHF_WRITE },
-  { NULL,                          0 , 0, 0,              0 }
+  { NULL,                         0 , 0, 0,              0 }
 };
 
 static const struct bfd_elf_special_section special_sections_g[] =
 {
   { STRING_COMMA_LEN (".gnu.linkonce.b"), -2, SHT_NOBITS,      SHF_ALLOC + SHF_WRITE },
-  { STRING_COMMA_LEN (".gnu.lto_"),       -1, SHT_PROGBITS,    SHF_EXCLUDE },
-  { STRING_COMMA_LEN (".got"),             0, SHT_PROGBITS,    SHF_ALLOC + SHF_WRITE },
-  { STRING_COMMA_LEN (".gnu.version"),     0, SHT_GNU_versym,  0 },
+  { STRING_COMMA_LEN (".gnu.lto_"),      -1, SHT_PROGBITS,    SHF_EXCLUDE },
+  { STRING_COMMA_LEN (".got"),            0, SHT_PROGBITS,    SHF_ALLOC + SHF_WRITE },
+  { STRING_COMMA_LEN (".gnu.version"),    0, SHT_GNU_versym,  0 },
   { STRING_COMMA_LEN (".gnu.version_d"),   0, SHT_GNU_verdef,  0 },
   { STRING_COMMA_LEN (".gnu.version_r"),   0, SHT_GNU_verneed, 0 },
-  { STRING_COMMA_LEN (".gnu.liblist"),     0, SHT_GNU_LIBLIST, SHF_ALLOC },
-  { STRING_COMMA_LEN (".gnu.conflict"),    0, SHT_RELA,        SHF_ALLOC },
-  { STRING_COMMA_LEN (".gnu.hash"),        0, SHT_GNU_HASH,    SHF_ALLOC },
-  { NULL,                        0,        0, 0,               0 }
+  { STRING_COMMA_LEN (".gnu.liblist"),    0, SHT_GNU_LIBLIST, SHF_ALLOC },
+  { STRING_COMMA_LEN (".gnu.conflict"),           0, SHT_RELA,        SHF_ALLOC },
+  { STRING_COMMA_LEN (".gnu.hash"),       0, SHT_GNU_HASH,    SHF_ALLOC },
+  { NULL,                       0,        0, 0,               0 }
 };
 
 static const struct bfd_elf_special_section special_sections_h[] =
 {
-  { STRING_COMMA_LEN (".hash"), 0, SHT_HASH,     SHF_ALLOC },
-  { NULL,                    0, 0, 0,            0 }
+  { STRING_COMMA_LEN (".hash"), 0, SHT_HASH,    SHF_ALLOC },
+  { NULL,                   0, 0, 0,            0 }
 };
 
 static const struct bfd_elf_special_section special_sections_i[] =
 {
-  { STRING_COMMA_LEN (".init"),        0, SHT_PROGBITS,   SHF_ALLOC + SHF_EXECINSTR },
+  { STRING_COMMA_LEN (".init"),               0, SHT_PROGBITS,   SHF_ALLOC + SHF_EXECINSTR },
   { STRING_COMMA_LEN (".init_array"), -2, SHT_INIT_ARRAY, SHF_ALLOC + SHF_WRITE },
-  { STRING_COMMA_LEN (".interp"),      0, SHT_PROGBITS,   0 },
-  { NULL,                      0,      0, 0,              0 }
+  { STRING_COMMA_LEN (".interp"),      0, SHT_PROGBITS,          0 },
+  { NULL,                     0,      0, 0,              0 }
 };
 
 static const struct bfd_elf_special_section special_sections_l[] =
 {
   { STRING_COMMA_LEN (".line"), 0, SHT_PROGBITS, 0 },
-  { NULL,                    0, 0, 0,            0 }
+  { NULL,                   0, 0, 0,            0 }
 };
 
 static const struct bfd_elf_special_section special_sections_n[] =
 {
   { STRING_COMMA_LEN (".note.GNU-stack"), 0, SHT_PROGBITS, 0 },
-  { STRING_COMMA_LEN (".note"),          -1, SHT_NOTE,     0 },
-  { NULL,                    0,           0, 0,            0 }
+  { STRING_COMMA_LEN (".note"),                 -1, SHT_NOTE,     0 },
+  { NULL,                   0,           0, 0,            0 }
 };
 
 static const struct bfd_elf_special_section special_sections_p[] =
 {
   { STRING_COMMA_LEN (".preinit_array"), -2, SHT_PREINIT_ARRAY, SHF_ALLOC + SHF_WRITE },
-  { STRING_COMMA_LEN (".plt"),            0, SHT_PROGBITS,      SHF_ALLOC + SHF_EXECINSTR },
-  { NULL,                   0,            0, 0,                 0 }
+  { STRING_COMMA_LEN (".plt"),           0, SHT_PROGBITS,      SHF_ALLOC + SHF_EXECINSTR },
+  { NULL,                  0,            0, 0,                 0 }
 };
 
 static const struct bfd_elf_special_section special_sections_r[] =
 {
   { STRING_COMMA_LEN (".rodata"), -2, SHT_PROGBITS, SHF_ALLOC },
   { STRING_COMMA_LEN (".rodata1"), 0, SHT_PROGBITS, SHF_ALLOC },
-  { STRING_COMMA_LEN (".rela"),   -1, SHT_RELA,     0 },
-  { STRING_COMMA_LEN (".rel"),    -1, SHT_REL,      0 },
-  { NULL,                   0,     0, 0,            0 }
+  { STRING_COMMA_LEN (".rela"),          -1, SHT_RELA,     0 },
+  { STRING_COMMA_LEN (".rel"),   -1, SHT_REL,      0 },
+  { NULL,                  0,     0, 0,            0 }
 };
 
 static const struct bfd_elf_special_section special_sections_s[] =
@@ -2679,24 +2755,24 @@ static const struct bfd_elf_special_section special_sections_s[] =
   /* See struct bfd_elf_special_section declaration for the semantics of
      this special case where .prefix_length != strlen (.prefix).  */
   { ".stabstr",                        5,  3, SHT_STRTAB, 0 },
-  { NULL,                       0,  0, 0,          0 }
+  { NULL,                      0,  0, 0,          0 }
 };
 
 static const struct bfd_elf_special_section special_sections_t[] =
 {
-  { STRING_COMMA_LEN (".text"),  -2, SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR },
-  { STRING_COMMA_LEN (".tbss"),  -2, SHT_NOBITS,   SHF_ALLOC + SHF_WRITE + SHF_TLS },
+  { STRING_COMMA_LEN (".text"),         -2, SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR },
+  { STRING_COMMA_LEN (".tbss"),         -2, SHT_NOBITS,   SHF_ALLOC + SHF_WRITE + SHF_TLS },
   { STRING_COMMA_LEN (".tdata"), -2, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE + SHF_TLS },
-  { NULL,                     0,  0, 0,            0 }
+  { NULL,                    0,  0, 0,            0 }
 };
 
 static const struct bfd_elf_special_section special_sections_z[] =
 {
-  { STRING_COMMA_LEN (".zdebug_line"),    0, SHT_PROGBITS, 0 },
-  { STRING_COMMA_LEN (".zdebug_info"),    0, SHT_PROGBITS, 0 },
+  { STRING_COMMA_LEN (".zdebug_line"),   0, SHT_PROGBITS, 0 },
+  { STRING_COMMA_LEN (".zdebug_info"),   0, SHT_PROGBITS, 0 },
   { STRING_COMMA_LEN (".zdebug_abbrev"),  0, SHT_PROGBITS, 0 },
   { STRING_COMMA_LEN (".zdebug_aranges"), 0, SHT_PROGBITS, 0 },
-  { NULL,                     0,  0, 0,            0 }
+  { NULL,                    0,  0, 0,            0 }
 };
 
 static const struct bfd_elf_special_section * const special_sections[] =
@@ -2824,7 +2900,7 @@ _bfd_elf_new_section_hook (bfd *abfd, asection *sec)
   if (sdata == NULL)
     {
       sdata = (struct bfd_elf_section_data *) bfd_zalloc (abfd,
-                                                          sizeof (*sdata));
+                                                         sizeof (*sdata));
       if (sdata == NULL)
        return FALSE;
       sec->used_by_bfd = sdata;
@@ -2975,6 +3051,16 @@ _bfd_elf_make_section_from_phdr (bfd *abfd,
   return TRUE;
 }
 
+static bfd_boolean
+_bfd_elf_core_find_build_id (bfd *templ, bfd_vma offset)
+{
+  /* The return value is ignored.  Build-ids are considered optional.  */
+  if (templ->xvec->flavour == bfd_target_elf_flavour)
+    return (*get_elf_backend_data (templ)->elf_backend_core_find_build_id)
+      (templ, offset);
+  return FALSE;
+}
+
 bfd_boolean
 bfd_section_from_phdr (bfd *abfd, Elf_Internal_Phdr *hdr, int hdr_index)
 {
@@ -2986,7 +3072,11 @@ bfd_section_from_phdr (bfd *abfd, Elf_Internal_Phdr *hdr, int hdr_index)
       return _bfd_elf_make_section_from_phdr (abfd, hdr, hdr_index, "null");
 
     case PT_LOAD:
-      return _bfd_elf_make_section_from_phdr (abfd, hdr, hdr_index, "load");
+      if (! _bfd_elf_make_section_from_phdr (abfd, hdr, hdr_index, "load"))
+       return FALSE;
+      if (bfd_get_format (abfd) == bfd_core && abfd->build_id == NULL)
+       _bfd_elf_core_find_build_id (abfd, hdr->p_offset);
+      return TRUE;
 
     case PT_DYNAMIC:
       return _bfd_elf_make_section_from_phdr (abfd, hdr, hdr_index, "dynamic");
@@ -2997,7 +3087,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;
 
@@ -3102,7 +3193,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;
@@ -3220,7 +3311,7 @@ elf_fake_sections (bfd *abfd, asection *asect, void *fsarg)
     {
       _bfd_error_handler
        /* xgettext:c-format */
-       (_("%B: error: Alignment power %d of section `%A' is too big"),
+       (_("%pB: error: alignment power %d of section `%pA' is too big"),
         abfd, asect->alignment_power, asect);
       arg->failed = TRUE;
       return;
@@ -3250,7 +3341,7 @@ elf_fake_sections (bfd *abfd, asection *asect, void *fsarg)
         non-bss input sections to bss output sections, or emit data
         to a bss output section via a linker script.  */
       _bfd_error_handler
-       (_("warning: section `%A' type changed to PROGBITS"), asect);
+       (_("warning: section `%pA' type changed to PROGBITS"), asect);
       this_hdr->sh_type = sh_type;
     }
 
@@ -3380,15 +3471,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;
@@ -3400,14 +3491,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)
     {
@@ -3432,7 +3529,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;
 
@@ -3524,10 +3622,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)
@@ -3677,11 +3794,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
@@ -3701,7 +3818,7 @@ assign_section_numbers (bfd *abfd, struct bfd_link_info *link_info)
   if (section_number >= SHN_LORESERVE)
     {
       /* xgettext:c-format */
-      _bfd_error_handler (_("%B: too many sections: %u"),
+      _bfd_error_handler (_("%pB: too many sections: %u"),
                          abfd, section_number);
       return FALSE;
     }
@@ -3712,12 +3829,12 @@ assign_section_numbers (bfd *abfd, struct bfd_link_info *link_info)
   /* Set up the list of section header pointers, in agreement with the
      indices.  */
   i_shdrp = (Elf_Internal_Shdr **) bfd_zalloc2 (abfd, section_number,
-                                                sizeof (Elf_Internal_Shdr *));
+                                               sizeof (Elf_Internal_Shdr *));
   if (i_shdrp == NULL)
     return FALSE;
 
   i_shdrp[0] = (Elf_Internal_Shdr *) bfd_zalloc (abfd,
-                                                 sizeof (Elf_Internal_Shdr));
+                                                sizeof (Elf_Internal_Shdr));
   if (i_shdrp[0] == NULL)
     {
       bfd_release (abfd, i_shdrp);
@@ -3786,8 +3903,8 @@ assign_section_numbers (bfd *abfd, struct bfd_link_info *link_info)
                      asection *kept;
                      _bfd_error_handler
                        /* xgettext:c-format */
-                       (_("%B: sh_link of section `%A' points to"
-                          " discarded section `%A' of `%B'"),
+                       (_("%pB: sh_link of section `%pA' points to"
+                          " discarded section `%pA' of `%pB'"),
                         abfd, d->this_hdr.bfd_section,
                         s, s->owner);
                      /* Point to the kept section if it has the same
@@ -3811,8 +3928,8 @@ assign_section_numbers (bfd *abfd, struct bfd_link_info *link_info)
                    {
                      _bfd_error_handler
                        /* xgettext:c-format */
-                       (_("%B: sh_link of section `%A' points to"
-                          " removed section `%A' of `%B'"),
+                       (_("%pB: sh_link of section `%pA' points to"
+                          " removed section `%pA' of `%pB'"),
                         abfd, d->this_hdr.bfd_section, s, s->owner);
                      bfd_set_error (bfd_error_bad_value);
                      return FALSE;
@@ -3833,7 +3950,7 @@ assign_section_numbers (bfd *abfd, struct bfd_link_info *link_info)
              if (bed->link_order_error_handler)
                bed->link_order_error_handler
                  /* xgettext:c-format */
-                 (_("%B: warning: sh_link not set for section `%A'"),
+                 (_("%pB: warning: sh_link not set for section `%pA'"),
                   abfd, sec);
            }
        }
@@ -3944,8 +4061,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
@@ -3994,15 +4111,22 @@ ignore_section_sym (bfd *abfd, asymbol *sym)
 {
   elf_symbol_type *type_ptr;
 
+  if (sym == NULL)
+    return FALSE;
+
   if ((sym->flags & BSF_SECTION_SYM) == 0)
     return FALSE;
 
+  if (sym->section == NULL)
+    return TRUE;
+
   type_ptr = elf_symbol_from (abfd, sym);
   return ((type_ptr != NULL
           && type_ptr->internal_elf_sym.st_shndx != 0
           && bfd_is_abs_section (sym->section))
          || !(sym->section->owner == abfd
-              || (sym->section->output_section->owner == abfd
+              || (sym->section->output_section != NULL
+                  && sym->section->output_section->owner == abfd
                   && sym->section->output_offset == 0)
               || bfd_is_abs_section (sym->section)));
 }
@@ -4089,7 +4213,7 @@ elf_map_symbols (bfd *abfd, unsigned int *pnum_locals)
 
   /* Now sort the symbols so the local symbols are first.  */
   new_syms = (asymbol **) bfd_alloc2 (abfd, num_locals + num_globals,
-                                      sizeof (asymbol *));
+                                     sizeof (asymbol *));
 
   if (new_syms == NULL)
     return FALSE;
@@ -4180,12 +4304,9 @@ _bfd_elf_compute_section_file_positions (bfd *abfd,
   if (bed->elf_backend_begin_write_processing)
     (*bed->elf_backend_begin_write_processing) (abfd, link_info);
 
-  if (! prep_headers (abfd))
+  if (!(*bed->elf_backend_init_file_header) (abfd, link_info))
     return FALSE;
 
-  /* Post process the headers if necessary.  */
-  (*bed->elf_backend_post_process_headers) (abfd, link_info);
-
   fsargs.failed = FALSE;
   fsargs.link_info = link_info;
   bfd_map_over_sections (abfd, elf_fake_sections, &fsargs);
@@ -4218,7 +4339,7 @@ _bfd_elf_compute_section_file_positions (bfd *abfd,
     }
 
   shstrtab_hdr = &elf_tdata (abfd)->shstrtab_hdr;
-  /* sh_name was set in prep_headers.  */
+  /* sh_name was set in init_file_header.  */
   shstrtab_hdr->sh_type = SHT_STRTAB;
   shstrtab_hdr->sh_flags = bed->elf_strtab_flags;
   shstrtab_hdr->sh_addr = 0;
@@ -4283,7 +4404,7 @@ get_program_header_size (bfd *abfd, struct bfd_link_info *info)
   segs = 2;
 
   s = bfd_get_section_by_name (abfd, ".interp");
-  if (s != NULL && (s->flags & SEC_LOAD) != 0)
+  if (s != NULL && (s->flags & SEC_LOAD) != 0 && s->size != 0)
     {
       /* If we have a loadable interpreter section, we need a
         PT_INTERP segment.  In this case, assume we also need a
@@ -4316,26 +4437,33 @@ 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
-         && CONST_STRNEQ (s->name, ".note"))
+         && elf_section_type (s) == SHT_NOTE)
        {
+         unsigned int alignment_power;
          /* We need a PT_NOTE segment.  */
          ++segs;
-         /* Try to create just one PT_NOTE segment
-            for all adjacent loadable .note* sections.
-            gABI requires that within a PT_NOTE segment
-            (and also inside of each SHT_NOTE section)
-            each note is padded to a multiple of 4 size,
-            so we check whether the sections are correctly
-            aligned.  */
-         if (s->alignment_power == 2)
-           while (s->next != NULL
-                  && s->next->alignment_power == 2
-                  && (s->next->flags & SEC_LOAD) != 0
-                  && CONST_STRNEQ (s->next->name, ".note"))
-             s = s->next;
+         /* Try to create just one PT_NOTE segment for all adjacent
+            loadable SHT_NOTE sections.  gABI requires that within a
+            PT_NOTE segment (and also inside of each SHT_NOTE section)
+            each note should have the same alignment.  So we check
+            whether the sections are correctly aligned.  */
+         alignment_power = s->alignment_power;
+         while (s->next != NULL
+                && s->next->alignment_power == alignment_power
+                && (s->next->flags & SEC_LOAD) != 0
+                && elf_section_type (s->next) == SHT_NOTE)
+           s = s->next;
        }
     }
 
@@ -4351,31 +4479,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 */
-                (_("%B: GNU_MBIN section `%A' 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;
 
@@ -4424,8 +4553,8 @@ make_mapping (bfd *abfd,
   asection **hdrpp;
   bfd_size_type amt;
 
-  amt = sizeof (struct elf_segment_map);
-  amt += (to - from - 1) * sizeof (asection *);
+  amt = sizeof (struct elf_segment_map) - sizeof (asection *);
+  amt += (to - from) * sizeof (asection *);
   m = (struct elf_segment_map *) bfd_zalloc (abfd, amt);
   if (m == NULL)
     return NULL;
@@ -4454,7 +4583,7 @@ _bfd_elf_make_dynamic_segment (bfd *abfd, asection *dynsec)
   struct elf_segment_map *m;
 
   m = (struct elf_segment_map *) bfd_zalloc (abfd,
-                                             sizeof (struct elf_segment_map));
+                                            sizeof (struct elf_segment_map));
   if (m == NULL)
     return NULL;
   m->next = NULL;
@@ -4516,6 +4645,9 @@ elf_modify_segment_map (bfd *abfd,
   return TRUE;
 }
 
+#define IS_TBSS(s) \
+  ((s->flags & (SEC_THREAD_LOCAL | SEC_LOAD)) == SEC_THREAD_LOCAL)
+
 /* Set up a mapping from BFD sections to program segments.  */
 
 bfd_boolean
@@ -4540,23 +4672,24 @@ _bfd_elf_map_sections_to_segments (bfd *abfd, struct bfd_link_info *info)
       struct elf_segment_map **pm;
       asection *last_hdr;
       bfd_vma last_size;
-      unsigned int phdr_index;
+      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;
       asection *first_tls = NULL;
       asection *first_mbind = NULL;
       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.  */
 
       sections = (asection **) bfd_malloc2 (bfd_count_sections (abfd),
-                                            sizeof (asection *));
+                                           sizeof (asection *));
       if (sections == NULL)
        goto error_return;
 
@@ -4571,6 +4704,10 @@ _bfd_elf_map_sections_to_segments (bfd *abfd, struct bfd_link_info *info)
        {
          if ((s->flags & SEC_ALLOC) != 0)
            {
+             /* target_index is unused until bfd_elf_final_link
+                starts output of section symbols.  Use it to make
+                qsort stable.  */
+             s->target_index = i;
              sections[i] = s;
              ++i;
              /* A wrapping section potentially clashes with header.  */
@@ -4583,8 +4720,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;
 
@@ -4592,7 +4744,7 @@ _bfd_elf_map_sections_to_segments (bfd *abfd, struct bfd_link_info *info)
         the program headers and a PT_INTERP segment for the .interp
         section.  */
       s = bfd_get_section_by_name (abfd, ".interp");
-      if (s != NULL && (s->flags & SEC_LOAD) != 0)
+      if (s != NULL && (s->flags & SEC_LOAD) != 0 && s->size != 0)
        {
          amt = sizeof (struct elf_segment_map);
          m = (struct elf_segment_map *) bfd_zalloc (abfd, amt);
@@ -4600,11 +4752,10 @@ _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;
+         phdr_in_segment = TRUE;
          *pm = m;
          pm = &m->next;
 
@@ -4626,47 +4777,70 @@ _bfd_elf_map_sections_to_segments (bfd *abfd, struct bfd_link_info *info)
         a few bytes of the end of the first section.  */
       last_hdr = NULL;
       last_size = 0;
-      phdr_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;
+      hdr_index = 0;
       writable = FALSE;
+      executable = FALSE;
       dynsec = bfd_get_section_by_name (abfd, ".dynamic");
       if (dynsec != NULL
          && (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;
            }
        }
 
@@ -4700,33 +4874,35 @@ _bfd_elf_map_sections_to_segments (bfd *abfd, struct bfd_link_info *info)
                 the previous section, then we need a new segment.  */
              new_segment = TRUE;
            }
+         else if ((abfd->flags & D_PAGED) != 0
+                  && (((last_hdr->lma + last_size - 1) & -maxpagesize)
+                      == (hdr->lma & -maxpagesize)))
+           {
+             /* If we are demand paged then we can't map two disk
+                pages onto the same memory page.  */
+             new_segment = FALSE;
+           }
          /* In the next test we have to be careful when last_hdr->lma is close
             to the end of the address space.  If the aligned address wraps
             around to the start of the address space, then there are no more
             pages left in memory and it is OK to assume that the current
             section can be included in the current segment.  */
-         else if ((BFD_ALIGN (last_hdr->lma + last_size, maxpagesize) + maxpagesize
-                   > last_hdr->lma)
-                  && (BFD_ALIGN (last_hdr->lma + last_size, maxpagesize) + maxpagesize
-                      <= hdr->lma))
+         else if ((BFD_ALIGN (last_hdr->lma + last_size, maxpagesize)
+                   + maxpagesize > last_hdr->lma)
+                  && (BFD_ALIGN (last_hdr->lma + last_size, maxpagesize)
+                      + maxpagesize <= hdr->lma))
            {
              /* If putting this section in this segment would force us to
                 skip a page in the segment, then we need a new segment.  */
              new_segment = TRUE;
            }
          else if ((last_hdr->flags & (SEC_LOAD | SEC_THREAD_LOCAL)) == 0
-                  && (hdr->flags & (SEC_LOAD | SEC_THREAD_LOCAL)) != 0
-                  && ((abfd->flags & D_PAGED) == 0
-                      || (((last_hdr->lma + last_size - 1) & -maxpagesize)
-                          != (hdr->lma & -maxpagesize))))
+                  && (hdr->flags & (SEC_LOAD | SEC_THREAD_LOCAL)) != 0)
            {
              /* We don't want to put a loaded section after a
                 nonloaded (ie. bss style) section in the same segment
                 as that will force the non-loaded section to be loaded.
-                Consider .tbss sections as loaded for this purpose.
-                However, like the writable/non-writable case below,
-                if they are on the same page then they must be put
-                in the same segment.  */
+                Consider .tbss sections as loaded for this purpose.  */
              new_segment = TRUE;
            }
          else if ((abfd->flags & D_PAGED) == 0)
@@ -4736,18 +4912,17 @@ _bfd_elf_map_sections_to_segments (bfd *abfd, struct bfd_link_info *info)
                 file, then there is no other reason for a new segment.  */
              new_segment = FALSE;
            }
+         else if (info != NULL
+                  && info->separate_code
+                  && executable != ((hdr->flags & SEC_CODE) != 0))
+           {
+             new_segment = TRUE;
+           }
          else if (! writable
-                  && (hdr->flags & SEC_READONLY) == 0
-                  && (((last_hdr->lma + last_size - 1) & -maxpagesize)
-                      != (hdr->lma & -maxpagesize)))
+                  && (hdr->flags & SEC_READONLY) == 0)
            {
              /* We don't want to put a writable section in a read only
-                segment, unless they are on the same page in memory
-                anyhow.  We already know that the last section does not
-                bring us past the current section on the page, so the
-                only case in which the new section is not on the same
-                page as the previous section is when the previous section
-                ends precisely on a page boundary.  */
+                segment.  */
              new_segment = TRUE;
            }
          else
@@ -4769,20 +4944,18 @@ _bfd_elf_map_sections_to_segments (bfd *abfd, struct bfd_link_info *info)
            {
              if ((hdr->flags & SEC_READONLY) == 0)
                writable = TRUE;
+             if ((hdr->flags & SEC_CODE) != 0)
+               executable = TRUE;
              last_hdr = hdr;
              /* .tbss sections effectively have zero size.  */
-             if ((hdr->flags & (SEC_THREAD_LOCAL | SEC_LOAD))
-                 != SEC_THREAD_LOCAL)
-               last_size = hdr->size;
-             else
-               last_size = 0;
+             last_size = !IS_TBSS (hdr) ? hdr->size : 0;
              continue;
            }
 
          /* We need a new program segment.  We must create a new program
-            header holding all the sections from phdr_index until hdr.  */
+            header holding all the sections from hdr_index until hdr.  */
 
-         m = make_mapping (abfd, sections, phdr_index, i, phdr_in_segment);
+         m = make_mapping (abfd, sections, hdr_index, i, phdr_in_segment);
          if (m == NULL)
            goto error_return;
 
@@ -4794,24 +4967,25 @@ _bfd_elf_map_sections_to_segments (bfd *abfd, struct bfd_link_info *info)
          else
            writable = FALSE;
 
+         if ((hdr->flags & SEC_CODE) == 0)
+           executable = FALSE;
+         else
+           executable = TRUE;
+
          last_hdr = hdr;
          /* .tbss sections effectively have zero size.  */
-         if ((hdr->flags & (SEC_THREAD_LOCAL | SEC_LOAD)) != SEC_THREAD_LOCAL)
-           last_size = hdr->size;
-         else
-           last_size = 0;
-         phdr_index = i;
+         last_size = !IS_TBSS (hdr) ? hdr->size : 0;
+         hdr_index = i;
          phdr_in_segment = FALSE;
        }
 
       /* Create a final PT_LOAD program segment, but not if it's just
         for .tbss.  */
       if (last_hdr != NULL
-         && (i - phdr_index != 1
-             || ((last_hdr->flags & (SEC_THREAD_LOCAL | SEC_LOAD))
-                 != SEC_THREAD_LOCAL)))
+         && (i - hdr_index != 1
+             || !IS_TBSS (last_hdr)))
        {
-         m = make_mapping (abfd, sections, phdr_index, i, phdr_in_segment);
+         m = make_mapping (abfd, sections, hdr_index, i, phdr_in_segment);
          if (m == NULL)
            goto error_return;
 
@@ -4829,34 +5003,34 @@ _bfd_elf_map_sections_to_segments (bfd *abfd, struct bfd_link_info *info)
          pm = &m->next;
        }
 
-      /* For each batch of consecutive loadable .note sections,
+      /* For each batch of consecutive loadable SHT_NOTE  sections,
         add a PT_NOTE segment.  We don't use bfd_get_section_by_name,
         because if we link together nonloadable .note sections and
         loadable .note sections, we will generate two .note sections
-        in the output file.  FIXME: Using names for section types is
-        bogus anyhow.  */
+        in the output file.  */
       for (s = abfd->sections; s != NULL; s = s->next)
        {
          if ((s->flags & SEC_LOAD) != 0
-             && CONST_STRNEQ (s->name, ".note"))
+             && elf_section_type (s) == SHT_NOTE)
            {
              asection *s2;
+             unsigned int alignment_power = s->alignment_power;
 
              count = 1;
-             amt = sizeof (struct elf_segment_map);
-             if (s->alignment_power == 2)
-               for (s2 = s; s2->next != NULL; s2 = s2->next)
-                 {
-                   if (s2->next->alignment_power == 2
-                       && (s2->next->flags & SEC_LOAD) != 0
-                       && CONST_STRNEQ (s2->next->name, ".note")
-                       && align_power (s2->lma + s2->size, 2)
-                          == s2->next->lma)
-                     count++;
-                   else
-                     break;
-                 }
-             amt += (count - 1) * sizeof (asection *);
+             for (s2 = s; s2->next != NULL; s2 = s2->next)
+               {
+                 if (s2->next->alignment_power == alignment_power
+                     && (s2->next->flags & SEC_LOAD) != 0
+                     && elf_section_type (s2->next) == SHT_NOTE
+                     && align_power (s2->lma + s2->size,
+                                     alignment_power)
+                     == s2->next->lma)
+                   count++;
+                 else
+                   break;
+               }
+             amt = sizeof (struct elf_segment_map) - sizeof (asection *);
+             amt += count * sizeof (asection *);
              m = (struct elf_segment_map *) bfd_zalloc (abfd, amt);
              if (m == NULL)
                goto error_return;
@@ -4888,8 +5062,8 @@ _bfd_elf_map_sections_to_segments (bfd *abfd, struct bfd_link_info *info)
       /* If there are any SHF_TLS output sections, add PT_TLS segment.  */
       if (tls_count > 0)
        {
-         amt = sizeof (struct elf_segment_map);
-         amt += (tls_count - 1) * sizeof (asection *);
+         amt = sizeof (struct elf_segment_map) - sizeof (asection *);
+         amt += tls_count * sizeof (asection *);
          m = (struct elf_segment_map *) bfd_zalloc (abfd, amt);
          if (m == NULL)
            goto error_return;
@@ -4905,18 +5079,18 @@ _bfd_elf_map_sections_to_segments (bfd *abfd, struct bfd_link_info *info)
              if ((s->flags & SEC_THREAD_LOCAL) == 0)
                {
                  _bfd_error_handler
-                   (_("%B: TLS sections are not adjacent:"), abfd);
+                   (_("%pB: TLS sections are not adjacent:"), abfd);
                  s = first_tls;
                  i = 0;
                  while (i < (unsigned int) tls_count)
                    {
                      if ((s->flags & SEC_THREAD_LOCAL) != 0)
                        {
-                         _bfd_error_handler (_("           TLS: %A"), s);
+                         _bfd_error_handler (_("           TLS: %pA"), s);
                          i++;
                        }
                      else
-                       _bfd_error_handler (_(" non-TLS: %A"), s);
+                       _bfd_error_handler (_(" non-TLS: %pA"), s);
                      s = s->next;
                    }
                  bfd_set_error (bfd_error_bad_value);
@@ -4930,11 +5104,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;
@@ -4959,6 +5134,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);
@@ -5082,14 +5275,7 @@ elf_sort_sections (const void *arg1, const void *arg2)
 
   if (TOEND (sec1))
     {
-      if (TOEND (sec2))
-       {
-         /* If the indicies are the same, do not return 0
-            here, but continue to try the next comparison.  */
-         if (sec1->target_index - sec2->target_index != 0)
-           return sec1->target_index - sec2->target_index;
-       }
-      else
+      if (!TOEND (sec2))
        return 1;
     }
   else if (TOEND (sec2))
@@ -5111,6 +5297,48 @@ elf_sort_sections (const void *arg1, const void *arg2)
   return sec1->target_index - sec2->target_index;
 }
 
+/* This qsort comparison functions sorts PT_LOAD segments first and
+   by p_paddr, for assign_file_positions_for_load_sections.  */
+
+static int
+elf_sort_segments (const void *arg1, const void *arg2)
+{
+  const struct elf_segment_map *m1 = *(const struct elf_segment_map **) arg1;
+  const struct elf_segment_map *m2 = *(const struct elf_segment_map **) arg2;
+
+  if (m1->p_type != m2->p_type)
+    {
+      if (m1->p_type == PT_NULL)
+       return 1;
+      if (m2->p_type == PT_NULL)
+       return -1;
+      return m1->p_type < m2->p_type ? -1 : 1;
+    }
+  if (m1->includes_filehdr != m2->includes_filehdr)
+    return m1->includes_filehdr ? -1 : 1;
+  if (m1->no_sort_lma != m2->no_sort_lma)
+    return m1->no_sort_lma ? -1 : 1;
+  if (m1->p_type == PT_LOAD && !m1->no_sort_lma)
+    {
+      bfd_vma lma1, lma2;
+      lma1 = 0;
+      if (m1->p_paddr_valid)
+       lma1 = m1->p_paddr;
+      else if (m1->count != 0)
+       lma1 = m1->sections[0]->lma + m1->p_vaddr_offset;
+      lma2 = 0;
+      if (m2->p_paddr_valid)
+       lma2 = m2->p_paddr;
+      else if (m2->count != 0)
+       lma2 = m2->sections[0]->lma + m2->p_vaddr_offset;
+      if (lma1 != lma2)
+       return lma1 < lma2 ? -1 : 1;
+    }
+  if (m1->idx != m2->idx)
+    return m1->idx < m2->idx ? -1 : 1;
+  return 0;
+}
+
 /* Ian Lance Taylor writes:
 
    We shouldn't be using % with a negative signed number.  That's just
@@ -5197,14 +5425,14 @@ assign_file_positions_for_load_sections (bfd *abfd,
 {
   const struct elf_backend_data *bed = get_elf_backend_data (abfd);
   struct elf_segment_map *m;
+  struct elf_segment_map *phdr_load_seg;
   Elf_Internal_Phdr *phdrs;
   Elf_Internal_Phdr *p;
   file_ptr off;
   bfd_size_type maxpagesize;
-  unsigned int pt_load_count = 0;
-  unsigned int alloc;
+  unsigned int alloc, actual;
   unsigned int i, j;
-  bfd_vma header_pad = 0;
+  struct elf_segment_map **sorted_seg_map;
 
   if (link_info == NULL
       && !_bfd_elf_map_sections_to_segments (abfd, link_info))
@@ -5212,11 +5440,7 @@ assign_file_positions_for_load_sections (bfd *abfd,
 
   alloc = 0;
   for (m = elf_seg_map (abfd); m != NULL; m = m->next)
-    {
-      ++alloc;
-      if (m->header_size)
-       header_pad = m->header_size;
-    }
+    m->idx = alloc++;
 
   if (alloc)
     {
@@ -5233,10 +5457,17 @@ assign_file_positions_for_load_sections (bfd *abfd,
   elf_elfheader (abfd)->e_phnum = alloc;
 
   if (elf_program_header_size (abfd) == (bfd_size_type) -1)
-    elf_program_header_size (abfd) = alloc * bed->s->sizeof_phdr;
+    {
+      actual = alloc;
+      elf_program_header_size (abfd) = alloc * bed->s->sizeof_phdr;
+    }
   else
-    BFD_ASSERT (elf_program_header_size (abfd)
-               >= alloc * bed->s->sizeof_phdr);
+    {
+      actual = elf_program_header_size (abfd) / bed->s->sizeof_phdr;
+      BFD_ASSERT (elf_program_header_size (abfd)
+                 == actual * bed->s->sizeof_phdr);
+      BFD_ASSERT (actual >= alloc);
+    }
 
   if (alloc == 0)
     {
@@ -5253,66 +5484,86 @@ assign_file_positions_for_load_sections (bfd *abfd,
      See ld/emultempl/elf-generic.em:gld${EMULATION_NAME}_map_segments
      where the layout is forced to according to a larger size in the
      last iterations for the testcase ld-elf/header.  */
-  BFD_ASSERT (elf_program_header_size (abfd) % bed->s->sizeof_phdr
-             == 0);
-  phdrs = (Elf_Internal_Phdr *)
-     bfd_zalloc2 (abfd,
-                  (elf_program_header_size (abfd) / bed->s->sizeof_phdr),
-                  sizeof (Elf_Internal_Phdr));
+  phdrs = bfd_zalloc (abfd, (actual * sizeof (*phdrs)
+                            + alloc * sizeof (*sorted_seg_map)));
+  sorted_seg_map = (struct elf_segment_map **) (phdrs + actual);
   elf_tdata (abfd)->phdr = phdrs;
   if (phdrs == NULL)
     return FALSE;
 
+  for (m = elf_seg_map (abfd), j = 0; m != NULL; m = m->next, j++)
+    {
+      sorted_seg_map[j] = m;
+      /* If elf_segment_map is not from map_sections_to_segments, the
+        sections may not be correctly ordered.  NOTE: sorting should
+        not be done to the PT_NOTE section of a corefile, which may
+        contain several pseudo-sections artificially created by bfd.
+        Sorting these pseudo-sections breaks things badly.  */
+      if (m->count > 1
+         && !(elf_elfheader (abfd)->e_type == ET_CORE
+              && m->p_type == PT_NOTE))
+       {
+         for (i = 0; i < m->count; i++)
+           m->sections[i]->target_index = i;
+         qsort (m->sections, (size_t) m->count, sizeof (asection *),
+                elf_sort_sections);
+       }
+    }
+  if (alloc > 1)
+    qsort (sorted_seg_map, alloc, sizeof (*sorted_seg_map),
+          elf_sort_segments);
+
   maxpagesize = 1;
   if ((abfd->flags & D_PAGED) != 0)
     maxpagesize = bed->maxpagesize;
 
+  /* Sections must map to file offsets past the ELF file header.  */
   off = bed->s->sizeof_ehdr;
-  off += alloc * bed->s->sizeof_phdr;
-  if (header_pad < (bfd_vma) off)
-    header_pad = 0;
-  else
-    header_pad -= off;
-  off += header_pad;
+  /* And if one of the PT_LOAD headers doesn't include the program
+     headers then we'll be mapping program headers in the usual
+     position after the ELF file header.  */
+  phdr_load_seg = NULL;
+  for (j = 0; j < alloc; j++)
+    {
+      m = sorted_seg_map[j];
+      if (m->p_type != PT_LOAD)
+       break;
+      if (m->includes_phdrs)
+       {
+         phdr_load_seg = m;
+         break;
+       }
+    }
+  if (phdr_load_seg == NULL)
+    off += actual * bed->s->sizeof_phdr;
 
-  for (m = elf_seg_map (abfd), p = phdrs, j = 0;
-       m != NULL;
-       m = m->next, p++, j++)
+  for (j = 0; j < alloc; j++)
     {
       asection **secpp;
       bfd_vma off_adjust;
       bfd_boolean no_contents;
 
-      /* If elf_segment_map is not from map_sections_to_segments, the
-        sections may not be correctly ordered.  NOTE: sorting should
-        not be done to the PT_NOTE section of a corefile, which may
-        contain several pseudo-sections artificially created by bfd.
-        Sorting these pseudo-sections breaks things badly.  */
-      if (m->count > 1
-         && !(elf_elfheader (abfd)->e_type == ET_CORE
-              && m->p_type == PT_NOTE))
-       qsort (m->sections, (size_t) m->count, sizeof (asection *),
-              elf_sort_sections);
-
       /* An ELF segment (described by Elf_Internal_Phdr) may contain a
         number of sections with contents contributing to both p_filesz
         and p_memsz, followed by a number of sections with no contents
         that just contribute to p_memsz.  In this loop, OFF tracks next
         available file offset for PT_LOAD and PT_NOTE segments.  */
+      m = sorted_seg_map[j];
+      p = phdrs + m->idx;
       p->p_type = m->p_type;
       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)
@@ -5329,14 +5580,18 @@ assign_file_positions_for_load_sections (bfd *abfd,
            maxpagesize = m->p_align;
 
          p->p_align = maxpagesize;
-         pt_load_count += 1;
        }
       else if (m->p_align_valid)
        p->p_align = m->p_align;
       else if (m->count == 0)
        p->p_align = 1 << bed->s->log_file_align;
-      else
-       p->p_align = 0;
+
+      if (m == phdr_load_seg)
+       {
+         if (!m->includes_filehdr)
+           p->p_offset = off;
+         off += actual * bed->s->sizeof_phdr;
+       }
 
       no_contents = FALSE;
       off_adjust = 0;
@@ -5354,7 +5609,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;
                }
@@ -5385,7 +5640,8 @@ assign_file_positions_for_load_sections (bfd *abfd,
          /* Broken hardware and/or kernel require that files do not
             map the same page with different permissions on some hppa
             processors.  */
-         if (pt_load_count > 1
+         if (j != 0
+             && (abfd->flags & D_PAGED) != 0
              && bed->no_page_alias
              && (off & (maxpagesize - 1)) != 0
              && (off & -maxpagesize) == ((off + off_adjust) & -maxpagesize))
@@ -5412,7 +5668,7 @@ assign_file_positions_for_load_sections (bfd *abfd,
               && strcmp (m->sections[0]->name, ".dynamic") != 0)
        {
          _bfd_error_handler
-           (_("%B: The first section in the PT_DYNAMIC segment"
+           (_("%pB: The first section in the PT_DYNAMIC segment"
               " is not the .dynamic section"),
             abfd);
          bfd_set_error (bfd_error_bad_value);
@@ -5423,33 +5679,38 @@ assign_file_positions_for_load_sections (bfd *abfd,
        for (i = 0; i < m->count; i++)
          elf_section_type (m->sections[i]) = SHT_NOTE;
 
-      p->p_offset = 0;
-      p->p_filesz = 0;
-      p->p_memsz = 0;
-
       if (m->includes_filehdr)
        {
          if (!m->p_flags_valid)
            p->p_flags |= PF_R;
          p->p_filesz = bed->s->sizeof_ehdr;
          p->p_memsz = bed->s->sizeof_ehdr;
-         if (m->count > 0)
+         if (p->p_type == PT_LOAD)
            {
-             if (p->p_vaddr < (bfd_vma) off
-                 || (!m->p_paddr_valid
-                     && p->p_paddr < (bfd_vma) off))
+             if (m->count > 0)
                {
-                 _bfd_error_handler
-                   (_("%B: Not enough room for program headers,"
-                      " try linking with -N"),
-                    abfd);
-                 bfd_set_error (bfd_error_bad_value);
-                 return FALSE;
+                 if (p->p_vaddr < (bfd_vma) off
+                     || (!m->p_paddr_valid
+                         && p->p_paddr < (bfd_vma) off))
+                   {
+                     _bfd_error_handler
+                       (_("%pB: not enough room for program headers,"
+                          " try linking with -N"),
+                        abfd);
+                     bfd_set_error (bfd_error_bad_value);
+                     return FALSE;
+                   }
+                 p->p_vaddr -= off;
+                 if (!m->p_paddr_valid)
+                   p->p_paddr -= off;
                }
-
-             p->p_vaddr -= off;
+           }
+         else if (sorted_seg_map[0]->includes_filehdr)
+           {
+             Elf_Internal_Phdr *filehdr = phdrs + sorted_seg_map[0]->idx;
+             p->p_vaddr = filehdr->p_vaddr;
              if (!m->p_paddr_valid)
-               p->p_paddr -= off;
+               p->p_paddr = filehdr->p_paddr;
            }
        }
 
@@ -5457,25 +5718,33 @@ assign_file_positions_for_load_sections (bfd *abfd,
        {
          if (!m->p_flags_valid)
            p->p_flags |= PF_R;
-
+         p->p_filesz += actual * bed->s->sizeof_phdr;
+         p->p_memsz += actual * bed->s->sizeof_phdr;
          if (!m->includes_filehdr)
            {
-             p->p_offset = bed->s->sizeof_ehdr;
-
-             if (m->count > 0)
+             if (p->p_type == PT_LOAD)
+               {
+                 elf_elfheader (abfd)->e_phoff = p->p_offset;
+                 if (m->count > 0)
+                   {
+                     p->p_vaddr -= off - p->p_offset;
+                     if (!m->p_paddr_valid)
+                       p->p_paddr -= off - p->p_offset;
+                   }
+               }
+             else if (phdr_load_seg != NULL)
                {
-                 p->p_vaddr -= off - p->p_offset;
+                 Elf_Internal_Phdr *phdr = phdrs + phdr_load_seg->idx;
+                 bfd_vma phdr_off = 0;
+                 if (phdr_load_seg->includes_filehdr)
+                   phdr_off = bed->s->sizeof_ehdr;
+                 p->p_vaddr = phdr->p_vaddr + phdr_off;
                  if (!m->p_paddr_valid)
-                   p->p_paddr -= off - p->p_offset;
+                   p->p_paddr = phdr->p_paddr + phdr_off;
+                 p->p_offset = phdr->p_offset + phdr_off;
                }
-           }
-
-         p->p_filesz += alloc * bed->s->sizeof_phdr;
-         p->p_memsz += alloc * bed->s->sizeof_phdr;
-         if (m->count)
-           {
-             p->p_filesz += header_pad;
-             p->p_memsz += header_pad;
+             else
+               p->p_offset = bed->s->sizeof_ehdr;
            }
        }
 
@@ -5483,7 +5752,15 @@ assign_file_positions_for_load_sections (bfd *abfd,
          || (p->p_type == PT_NOTE && bfd_get_format (abfd) == bfd_core))
        {
          if (!m->includes_filehdr && !m->includes_phdrs)
-           p->p_offset = off;
+           {
+             p->p_offset = off;
+             if (no_contents)
+               /* Put meaningless p_offset for PT_LOAD segments
+                  without file contents somewhere within the first
+                  page, in an attempt to not point past EOF.  */
+               p->p_offset = off % (p->p_align > maxpagesize
+                                    ? p->p_align : maxpagesize);
+           }
          else
            {
              file_ptr adjust;
@@ -5508,7 +5785,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)
@@ -5528,8 +5805,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, s_start, p_end);
+                   (_("%pB: section %pA lma %#" PRIx64 " adjusted to %#" PRIx64),
+                    abfd, sec, (uint64_t) s_start, (uint64_t) p_end);
                  adjust = 0;
                  sec->lma = p_end;
                }
@@ -5537,16 +5814,19 @@ assign_file_positions_for_load_sections (bfd *abfd,
 
              if (this_hdr->sh_type != SHT_NOBITS)
                {
-                 if (p->p_filesz + adjust < p->p_memsz)
+                 if (p->p_type == PT_LOAD)
                    {
-                     /* We have a PROGBITS section following NOBITS ones.
-                        Allocate file space for the NOBITS section(s) and
-                        zero it.  */
-                     adjust = p->p_memsz - p->p_filesz;
-                     if (!write_zeros (abfd, off, adjust))
-                       return FALSE;
+                     if (p->p_filesz + adjust < p->p_memsz)
+                       {
+                         /* We have a PROGBITS section following NOBITS ones.
+                            Allocate file space for the NOBITS section(s) and
+                            zero it.  */
+                         adjust = p->p_memsz - p->p_filesz;
+                         if (!write_zeros (abfd, off, adjust))
+                           return FALSE;
+                       }
+                     off += adjust;
                    }
-                 off += adjust;
                  p->p_filesz += adjust;
                }
            }
@@ -5635,6 +5915,22 @@ assign_file_positions_for_load_sections (bfd *abfd,
 
       off -= off_adjust;
 
+      /* PR ld/20815 - Check that the program header segment, if
+        present, will be loaded into memory.  */
+      if (p->p_type == PT_PHDR
+         && phdr_load_seg == NULL
+         && !(bed->elf_backend_allow_non_load_phdr != NULL
+              && bed->elf_backend_allow_non_load_phdr (abfd, phdrs, alloc)))
+       {
+         /* The fix for this error is usually to edit the linker script being
+            used and set up the program headers manually.  Either that or
+            leave room for the headers at the start of the SECTIONS.  */
+         _bfd_error_handler (_("%pB: error: PHDR segment not covered"
+                               " by LOAD segment"),
+                             abfd);
+         return FALSE;
+       }
+
       /* Check that all sections are in a PT_LOAD segment.
         Don't check funky gdb generated core files.  */
       if (p->p_type == PT_LOAD && bfd_get_format (abfd) != bfd_core)
@@ -5665,7 +5961,7 @@ assign_file_positions_for_load_sections (bfd *abfd,
                {
                  _bfd_error_handler
                    /* xgettext:c-format */
-                   (_("%B: section `%A' can't be allocated in segment %d"),
+                   (_("%pB: section `%pA' can't be allocated in segment %d"),
                     abfd, sec, j);
                  print_segment_map (m);
                }
@@ -5674,33 +5970,110 @@ assign_file_positions_for_load_sections (bfd *abfd,
     }
 
   elf_next_file_pos (abfd) = off;
-  return TRUE;
-}
-
-/* Assign file positions for the other sections.  */
-
-static bfd_boolean
-assign_file_positions_for_non_load_sections (bfd *abfd,
-                                            struct bfd_link_info *link_info)
-{
-  const struct elf_backend_data *bed = get_elf_backend_data (abfd);
-  Elf_Internal_Shdr **i_shdrpp;
-  Elf_Internal_Shdr **hdrpp, **end_hdrpp;
-  Elf_Internal_Phdr *phdrs;
-  Elf_Internal_Phdr *p;
-  struct elf_segment_map *m;
-  struct elf_segment_map *hdrs_segment;
-  bfd_vma filehdr_vaddr, filehdr_paddr;
-  bfd_vma phdrs_vaddr, phdrs_paddr;
-  file_ptr off;
-  unsigned int count;
 
-  i_shdrpp = elf_elfsections (abfd);
-  end_hdrpp = i_shdrpp + elf_numsections (abfd);
-  off = elf_next_file_pos (abfd);
-  for (hdrpp = i_shdrpp + 1; hdrpp < end_hdrpp; hdrpp++)
+  if (link_info != NULL
+      && phdr_load_seg != NULL
+      && phdr_load_seg->includes_filehdr)
     {
-      Elf_Internal_Shdr *hdr;
+      /* There is a segment that contains both the file headers and the
+        program headers, so provide a symbol __ehdr_start pointing there.
+        A program can use this to examine itself robustly.  */
+
+      struct elf_link_hash_entry *hash
+       = elf_link_hash_lookup (elf_hash_table (link_info), "__ehdr_start",
+                               FALSE, FALSE, TRUE);
+      /* If the symbol was referenced and not defined, define it.  */
+      if (hash != NULL
+         && (hash->root.type == bfd_link_hash_new
+             || hash->root.type == bfd_link_hash_undefined
+             || hash->root.type == bfd_link_hash_undefweak
+             || hash->root.type == bfd_link_hash_common))
+       {
+         asection *s = NULL;
+         bfd_vma filehdr_vaddr = phdrs[phdr_load_seg->idx].p_vaddr;
+
+         if (phdr_load_seg->count != 0)
+           /* The segment contains sections, so use the first one.  */
+           s = phdr_load_seg->sections[0];
+         else
+           /* Use the first (i.e. lowest-addressed) section in any segment.  */
+           for (m = elf_seg_map (abfd); m != NULL; m = m->next)
+             if (m->p_type == PT_LOAD && m->count != 0)
+               {
+                 s = m->sections[0];
+                 break;
+               }
+
+         if (s != NULL)
+           {
+             hash->root.u.def.value = filehdr_vaddr - s->vma;
+             hash->root.u.def.section = s;
+           }
+         else
+           {
+             hash->root.u.def.value = filehdr_vaddr;
+             hash->root.u.def.section = bfd_abs_section_ptr;
+           }
+
+         hash->root.type = bfd_link_hash_defined;
+         hash->def_regular = 1;
+         hash->non_elf = 0;
+       }
+    }
+
+  return TRUE;
+}
+
+/* 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,
+                                            struct bfd_link_info *link_info)
+{
+  const struct elf_backend_data *bed = get_elf_backend_data (abfd);
+  Elf_Internal_Shdr **i_shdrpp;
+  Elf_Internal_Shdr **hdrpp, **end_hdrpp;
+  Elf_Internal_Phdr *phdrs;
+  Elf_Internal_Phdr *p;
+  struct elf_segment_map *m;
+  file_ptr off;
+
+  i_shdrpp = elf_elfsections (abfd);
+  end_hdrpp = i_shdrpp + elf_numsections (abfd);
+  off = elf_next_file_pos (abfd);
+  for (hdrpp = i_shdrpp + 1; hdrpp < end_hdrpp; hdrpp++)
+    {
+      Elf_Internal_Shdr *hdr;
 
       hdr = *hdrpp;
       if (hdr->bfd_section != NULL
@@ -5710,10 +6083,16 @@ 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 */
-             (_("%B: warning: allocated section `%s' not in segment"),
+             (_("%pB: warning: allocated section `%s' not in segment"),
               abfd,
               (hdr->bfd_section == NULL
                ? "*unknown*"
@@ -5730,9 +6109,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])
@@ -5742,149 +6124,109 @@ assign_file_positions_for_non_load_sections (bfd *abfd,
       else
        off = _bfd_elf_assign_file_position_for_section (hdr, off, TRUE);
     }
+  elf_next_file_pos (abfd) = off;
 
   /* Now that we have set the section file positions, we can set up
      the file positions for the non PT_LOAD segments.  */
-  count = 0;
-  filehdr_vaddr = 0;
-  filehdr_paddr = 0;
-  phdrs_vaddr = bed->maxpagesize + bed->s->sizeof_ehdr;
-  phdrs_paddr = 0;
-  hdrs_segment = NULL;
   phdrs = elf_tdata (abfd)->phdr;
   for (m = elf_seg_map (abfd), p = phdrs; m != NULL; m = m->next, p++)
     {
-      ++count;
-      if (p->p_type != PT_LOAD)
-       continue;
-
-      if (m->includes_filehdr)
-       {
-         filehdr_vaddr = p->p_vaddr;
-         filehdr_paddr = p->p_paddr;
-       }
-      if (m->includes_phdrs)
+      if (p->p_type == PT_GNU_RELRO)
        {
-         phdrs_vaddr = p->p_vaddr;
-         phdrs_paddr = p->p_paddr;
-         if (m->includes_filehdr)
+         bfd_vma start, end;
+         bfd_boolean ok;
+
+         if (link_info != NULL)
            {
-             hdrs_segment = m;
-             phdrs_vaddr += bed->s->sizeof_ehdr;
-             phdrs_paddr += bed->s->sizeof_ehdr;
+             /* During linking the range of the RELRO segment is passed
+                in link_info.  Note that there may be padding between
+                relro_start and the first RELRO section.  */
+             start = link_info->relro_start;
+             end = link_info->relro_end;
            }
-       }
-    }
-
-  if (hdrs_segment != NULL && link_info != NULL)
-    {
-      /* There is a segment that contains both the file headers and the
-        program headers, so provide a symbol __ehdr_start pointing there.
-        A program can use this to examine itself robustly.  */
-
-      struct elf_link_hash_entry *hash
-       = elf_link_hash_lookup (elf_hash_table (link_info), "__ehdr_start",
-                               FALSE, FALSE, TRUE);
-      /* If the symbol was referenced and not defined, define it.  */
-      if (hash != NULL
-         && (hash->root.type == bfd_link_hash_new
-             || hash->root.type == bfd_link_hash_undefined
-             || hash->root.type == bfd_link_hash_undefweak
-             || hash->root.type == bfd_link_hash_common))
-       {
-         asection *s = NULL;
-         if (hdrs_segment->count != 0)
-           /* The segment contains sections, so use the first one.  */
-           s = hdrs_segment->sections[0];
-         else
-           /* Use the first (i.e. lowest-addressed) section in any segment.  */
-           for (m = elf_seg_map (abfd); m != NULL; m = m->next)
-             if (m->count != 0)
-               {
-                 s = m->sections[0];
-                 break;
-               }
-
-         if (s != NULL)
+         else if (m->count != 0)
            {
-             hash->root.u.def.value = filehdr_vaddr - s->vma;
-             hash->root.u.def.section = s;
+             if (!m->p_size_valid)
+               abort ();
+             start = m->sections[0]->vma;
+             end = start + m->p_size;
            }
          else
            {
-             hash->root.u.def.value = filehdr_vaddr;
-             hash->root.u.def.section = bfd_abs_section_ptr;
+             start = 0;
+             end = 0;
            }
 
-         hash->root.type = bfd_link_hash_defined;
-         hash->def_regular = 1;
-         hash->non_elf = 0;
-       }
-    }
-
-  for (m = elf_seg_map (abfd), p = phdrs; m != NULL; m = m->next, p++)
-    {
-      if (p->p_type == PT_GNU_RELRO)
-       {
-         const Elf_Internal_Phdr *lp;
-         struct elf_segment_map *lm;
-
-         if (link_info != NULL)
+         ok = FALSE;
+         if (start < end)
            {
-             /* During linking the range of the RELRO segment is passed
-                in link_info.  */
+             struct elf_segment_map *lm;
+             const Elf_Internal_Phdr *lp;
+             unsigned int i;
+
+             /* Find a LOAD segment containing a section in the RELRO
+                segment.  */
              for (lm = elf_seg_map (abfd), lp = phdrs;
                   lm != NULL;
                   lm = lm->next, lp++)
                {
                  if (lp->p_type == PT_LOAD
-                     && lp->p_vaddr < link_info->relro_end
                      && lm->count != 0
-                     && lm->sections[0]->vma >= link_info->relro_start)
+                     && (lm->sections[lm->count - 1]->vma
+                         + (!IS_TBSS (lm->sections[lm->count - 1])
+                            ? lm->sections[lm->count - 1]->size
+                            : 0)) > start
+                     && lm->sections[0]->vma < end)
                    break;
                }
 
-             BFD_ASSERT (lm != NULL);
-           }
-         else
-           {
-             /* Otherwise we are copying an executable or shared
-                library, but we need to use the same linker logic.  */
-             for (lp = phdrs; lp < phdrs + count; ++lp)
+             if (lm != NULL)
                {
-                 if (lp->p_type == PT_LOAD
-                     && lp->p_paddr == p->p_paddr)
-                   break;
-               }
-           }
+                 /* Find the section starting the RELRO segment.  */
+                 for (i = 0; i < lm->count; i++)
+                   {
+                     asection *s = lm->sections[i];
+                     if (s->vma >= start
+                         && s->vma < end
+                         && s->size != 0)
+                       break;
+                   }
 
-         if (lp < phdrs + count)
-           {
-             p->p_vaddr = lp->p_vaddr;
-             p->p_paddr = lp->p_paddr;
-             p->p_offset = lp->p_offset;
-             if (link_info != NULL)
-               p->p_filesz = link_info->relro_end - lp->p_vaddr;
-             else if (m->p_size_valid)
-               p->p_filesz = m->p_size;
-             else
-               abort ();
-             p->p_memsz = p->p_filesz;
-             /* Preserve the alignment and flags if they are valid. The
-                gold linker generates RW/4 for the PT_GNU_RELRO section.
-                It is better for objcopy/strip to honor these attributes
-                otherwise gdb will choke when using separate debug files.
-              */
-             if (!m->p_align_valid)
-               p->p_align = 1;
-             if (!m->p_flags_valid)
-               p->p_flags = PF_R;
-           }
-         else
-           {
-             memset (p, 0, sizeof *p);
-             p->p_type = PT_NULL;
+                 if (i < lm->count)
+                   {
+                     p->p_vaddr = lm->sections[i]->vma;
+                     p->p_paddr = lm->sections[i]->lma;
+                     p->p_offset = lm->sections[i]->filepos;
+                     p->p_memsz = end - p->p_vaddr;
+                     p->p_filesz = p->p_memsz;
+
+                     /* The RELRO segment typically ends a few bytes
+                        into .got.plt but other layouts are possible.
+                        In cases where the end does not match any
+                        loaded section (for instance is in file
+                        padding), trim p_filesz back to correspond to
+                        the end of loaded section contents.  */
+                     if (p->p_filesz > lp->p_vaddr + lp->p_filesz - p->p_vaddr)
+                       p->p_filesz = lp->p_vaddr + lp->p_filesz - p->p_vaddr;
+
+                     /* Preserve the alignment and flags if they are
+                        valid.  The gold linker generates RW/4 for
+                        the PT_GNU_RELRO section.  It is better for
+                        objcopy/strip to honor these attributes
+                        otherwise gdb will choke when using separate
+                        debug files.  */
+                     if (!m->p_align_valid)
+                       p->p_align = 1;
+                     if (!m->p_flags_valid)
+                       p->p_flags = PF_R;
+                     ok = TRUE;
+                   }
+               }
            }
+         if (link_info != NULL)
+           BFD_ASSERT (ok);
+         if (!ok)
+           memset (p, 0, sizeof *p);
        }
       else if (p->p_type == PT_GNU_STACK)
        {
@@ -5911,7 +6253,7 @@ 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 "
+                   (_("%pB: error: non-load segment %d includes file header "
                       "and/or program header"),
                     abfd, (int) (p - phdrs));
                  return FALSE;
@@ -5932,22 +6274,8 @@ assign_file_positions_for_non_load_sections (bfd *abfd,
                }
            }
        }
-      else if (m->includes_filehdr)
-       {
-         p->p_vaddr = filehdr_vaddr;
-         if (! m->p_paddr_valid)
-           p->p_paddr = filehdr_paddr;
-       }
-      else if (m->includes_phdrs)
-       {
-         p->p_vaddr = phdrs_vaddr;
-         if (! m->p_paddr_valid)
-           p->p_paddr = phdrs_paddr;
-       }
     }
 
-  elf_next_file_pos (abfd) = off;
-
   return TRUE;
 }
 
@@ -5965,11 +6293,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.  */
@@ -5981,6 +6310,7 @@ assign_file_positions_except_relocs (bfd *abfd,
   struct elf_obj_tdata *tdata = elf_tdata (abfd);
   Elf_Internal_Ehdr *i_ehdrp = elf_elfheader (abfd);
   const struct elf_backend_data *bed = get_elf_backend_data (abfd);
+  unsigned int alloc;
 
   if ((abfd->flags & (EXEC_P | DYNAMIC)) == 0
       && bfd_get_format (abfd) != bfd_core)
@@ -6004,9 +6334,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])
@@ -6020,11 +6353,10 @@ assign_file_positions_except_relocs (bfd *abfd,
        }
 
       elf_next_file_pos (abfd) = off;
+      elf_program_header_size (abfd) = 0;
     }
   else
     {
-      unsigned int alloc;
-
       /* Assign file positions for the loaded sections based on the
         assignment of sections to segments.  */
       if (!assign_file_positions_for_load_sections (abfd, link_info))
@@ -6033,68 +6365,16 @@ assign_file_positions_except_relocs (bfd *abfd,
       /* And for non-load sections.  */
       if (!assign_file_positions_for_non_load_sections (abfd, link_info))
        return FALSE;
+    }
 
-      if (bed->elf_backend_modify_program_headers != NULL)
-       {
-         if (!(*bed->elf_backend_modify_program_headers) (abfd, link_info))
-           return FALSE;
-       }
-
-      /* Set e_type in ELF header to ET_EXEC for -pie -Ttext-segment=.  */
-      if (link_info != NULL && bfd_link_pie (link_info))
-       {
-         unsigned int num_segments = elf_elfheader (abfd)->e_phnum;
-         Elf_Internal_Phdr *segment = elf_tdata (abfd)->phdr;
-         Elf_Internal_Phdr *end_segment = &segment[num_segments];
-
-         /* Find the lowest p_vaddr in PT_LOAD segments.  */
-         bfd_vma p_vaddr = (bfd_vma) -1;
-         for (; segment < end_segment; segment++)
-           if (segment->p_type == PT_LOAD && p_vaddr > segment->p_vaddr)
-             p_vaddr = segment->p_vaddr;
-
-         /* Set e_type to ET_EXEC if the lowest p_vaddr in PT_LOAD
-            segments is non-zero.  */
-         if (p_vaddr)
-           i_ehdrp->e_type = ET_EXEC;
-       }
-
-      /* Write out the program headers.  */
-      alloc = elf_program_header_size (abfd) / bed->s->sizeof_phdr;
-
-      /* Sort the program headers into the ordering required by the ELF standard.  */
-      if (alloc == 0)
-       return TRUE;
-
-      /* PR ld/20815 - Check that the program header segment, if present, will
-        be loaded into memory.  FIXME: The check below is not sufficient as
-        really all PT_LOAD segments should be checked before issuing an error
-        message.  Plus the PHDR segment does not have to be the first segment
-        in the program header table.  But this version of the check should
-        catch all real world use cases.
-
-        FIXME: We used to have code here to sort the PT_LOAD segments into
-        ascending order, as per the ELF spec.  But this breaks some programs,
-        including the Linux kernel.  But really either the spec should be
-         changed or the programs updated.  */
-      if (alloc > 1
-         && tdata->phdr[0].p_type == PT_PHDR
-         && ! bed->elf_backend_allow_non_load_phdr (abfd, tdata->phdr, alloc)
-         && tdata->phdr[1].p_type == PT_LOAD
-         && (tdata->phdr[1].p_vaddr > tdata->phdr[0].p_vaddr
-             || (tdata->phdr[1].p_vaddr + tdata->phdr[1].p_memsz)
-             <  (tdata->phdr[0].p_vaddr + tdata->phdr[0].p_memsz)))
-       {
-         /* The fix for this error is usually to edit the linker script being
-            used and set up the program headers manually.  Either that or
-            leave room for the headers at the start of the SECTIONS.  */
-         _bfd_error_handler (_("\
-%B: error: PHDR segment not covered by LOAD segment"),
-                             abfd);
-         return FALSE;
-       }
+  if (!(*bed->elf_backend_modify_headers) (abfd, link_info))
+    return FALSE;
 
-      if (bfd_seek (abfd, (bfd_signed_vma) bed->s->sizeof_ehdr, SEEK_SET) != 0
+  /* Write out the program headers.  */
+  alloc = i_ehdrp->e_phnum;
+  if (alloc != 0)
+    {
+      if (bfd_seek (abfd, i_ehdrp->e_phoff, SEEK_SET) != 0
          || bed->s->write_out_phdrs (abfd, tdata->phdr, alloc) != 0)
        return FALSE;
     }
@@ -6102,8 +6382,9 @@ assign_file_positions_except_relocs (bfd *abfd,
   return TRUE;
 }
 
-static bfd_boolean
-prep_headers (bfd *abfd)
+bfd_boolean
+_bfd_elf_init_file_header (bfd *abfd,
+                          struct bfd_link_info *info ATTRIBUTE_UNUSED)
 {
   Elf_Internal_Ehdr *i_ehdrp;  /* Elf file header, internal form.  */
   struct elf_strtab_hash *shstrtab;
@@ -6166,16 +6447,6 @@ prep_headers (bfd *abfd)
   i_ehdrp->e_entry = bfd_get_start_address (abfd);
   i_ehdrp->e_shentsize = bed->s->sizeof_shdr;
 
-  /* If we're building an executable, we'll need a program header table.  */
-  if (abfd->flags & EXEC_P)
-    /* It all happens later.  */
-    ;
-  else
-    {
-      i_ehdrp->e_phentsize = 0;
-      i_ehdrp->e_phoff = 0;
-    }
-
   elf_tdata (abfd)->symtab_hdr.sh_name =
     (unsigned int) _bfd_elf_strtab_add (shstrtab, ".symtab", FALSE);
   elf_tdata (abfd)->strtab_hdr.sh_name =
@@ -6190,6 +6461,38 @@ prep_headers (bfd *abfd)
   return TRUE;
 }
 
+/* Set e_type in ELF header to ET_EXEC for -pie -Ttext-segment=.
+
+   FIXME: We used to have code here to sort the PT_LOAD segments into
+   ascending order, as per the ELF spec.  But this breaks some programs,
+   including the Linux kernel.  But really either the spec should be
+   changed or the programs updated.  */
+
+bfd_boolean
+_bfd_elf_modify_headers (bfd *obfd, struct bfd_link_info *link_info)
+{
+  if (link_info != NULL && bfd_link_pie (link_info))
+    {
+      Elf_Internal_Ehdr *i_ehdrp = elf_elfheader (obfd);
+      unsigned int num_segments = i_ehdrp->e_phnum;
+      struct elf_obj_tdata *tdata = elf_tdata (obfd);
+      Elf_Internal_Phdr *segment = tdata->phdr;
+      Elf_Internal_Phdr *end_segment = &segment[num_segments];
+
+      /* Find the lowest p_vaddr in PT_LOAD segments.  */
+      bfd_vma p_vaddr = (bfd_vma) -1;
+      for (; segment < end_segment; segment++)
+       if (segment->p_type == PT_LOAD && p_vaddr > segment->p_vaddr)
+         p_vaddr = segment->p_vaddr;
+
+      /* Set e_type to ET_EXEC if the lowest p_vaddr in PT_LOAD
+        segments is non-zero.  */
+      if (p_vaddr)
+       i_ehdrp->e_type = ET_EXEC;
+    }
+  return TRUE;
+}
+
 /* Assign file positions for all the reloc sections which are not part
    of the loadable file image, and the file position of section headers.  */
 
@@ -6214,10 +6517,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;
@@ -6263,6 +6568,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);
@@ -6300,6 +6612,18 @@ _bfd_elf_write_object_contents (bfd *abfd)
   if (! abfd->output_has_begun
       && ! _bfd_elf_compute_section_file_positions (abfd, NULL))
     return FALSE;
+  /* Do not rewrite ELF data when the BFD has been opened for update.
+     abfd->output_has_begun was set to TRUE on opening, so creation of new
+     sections, and modification of existing section sizes was restricted.
+     This means the ELF header, program headers and section headers can't have
+     changed.
+     If the contents of any sections has been modified, then those changes have
+     already been written to the BFD.  */
+  else if (abfd->direction == both_direction)
+    {
+      BFD_ASSERT (abfd->output_has_begun);
+      return TRUE;
+    }
 
   i_shdrp = elf_elfsections (abfd);
 
@@ -6319,7 +6643,8 @@ _bfd_elf_write_object_contents (bfd *abfd)
        = _bfd_elf_strtab_offset (elf_shstrtab (abfd),
                                  i_shdrp[count]->sh_name);
       if (bed->elf_backend_section_processing)
-       (*bed->elf_backend_section_processing) (abfd, i_shdrp[count]);
+       if (!(*bed->elf_backend_section_processing) (abfd, i_shdrp[count]))
+         return FALSE;
       if (i_shdrp[count]->contents)
        {
          bfd_size_type amt = i_shdrp[count]->sh_size;
@@ -6337,8 +6662,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;
@@ -6432,7 +6757,7 @@ _bfd_elf_symbol_from_bfd_symbol (bfd *abfd, asymbol **asym_ptr_ptr)
         which is used in a relocation entry.  */
       _bfd_error_handler
        /* xgettext:c-format */
-       (_("%B: symbol `%s' required but not present"),
+       (_("%pB: symbol `%s' required but not present"),
         abfd, bfd_asymbol_name (asym_ptr));
       bfd_set_error (bfd_error_no_symbols);
       return -1;
@@ -6500,6 +6825,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)))
 
@@ -6563,9 +6889,8 @@ 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))                                                       \
-   && !section->segment_mark)
+       || (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,
    it is removed from the corresponding output segment.   */
@@ -6693,13 +7018,11 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd)
       asection **sections;
       asection *output_section;
       unsigned int isec;
-      bfd_vma matching_lma;
-      bfd_vma suggested_lma;
+      asection *matching_lma;
+      asection *suggested_lma;
       unsigned int j;
       bfd_size_type amt;
       asection *first_section;
-      bfd_boolean first_matching_lma;
-      bfd_boolean first_suggested_lma;
 
       if (segment->p_type == PT_NULL)
        continue;
@@ -6723,8 +7046,8 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd)
 
       /* Allocate a segment map big enough to contain
         all of the sections we have selected.  */
-      amt = sizeof (struct elf_segment_map);
-      amt += ((bfd_size_type) section_count - 1) * sizeof (asection *);
+      amt = sizeof (struct elf_segment_map) - sizeof (asection *);
+      amt += (bfd_size_type) section_count * sizeof (asection *);
       map = (struct elf_segment_map *) bfd_zalloc (obfd, amt);
       if (map == NULL)
        return FALSE;
@@ -6768,17 +7091,19 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd)
          /* Special segments, such as the PT_PHDR segment, may contain
             no sections, but ordinary, loadable segments should contain
             something.  They are allowed by the ELF spec however, so only
-            a warning is produced.  
+            a warning is produced.
             There is however the valid use case of embedded systems which
             have segments with p_filesz of 0 and a p_memsz > 0 to initialize
             flash memory with zeros.  No warning is shown for that case.  */
          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=%#Lx, is this intentional?"),
-                               ibfd, segment->p_vaddr);
+           _bfd_error_handler
+             (_("%pB: warning: empty loadable segment detected"
+                " 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;
@@ -6825,10 +7150,8 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd)
         we have completely filled the segment, and there is nothing
         more to do.  */
       isec = 0;
-      matching_lma = 0;
-      suggested_lma = 0;
-      first_matching_lma = TRUE;
-      first_suggested_lma = TRUE;
+      matching_lma = NULL;
+      suggested_lma = NULL;
 
       for (section = first_section, j = 0;
           section != NULL;
@@ -6849,14 +7172,14 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd)
                  && !bed->want_p_paddr_set_to_zero
                  && isec == 0
                  && output_section->lma != 0
-                 && output_section->vma == (segment->p_vaddr
-                                            + (map->includes_filehdr
-                                               ? iehdr->e_ehsize
-                                               : 0)
-                                            + (map->includes_phdrs
-                                               ? (iehdr->e_phnum
-                                                  * iehdr->e_phentsize)
-                                               : 0)))
+                 && (align_power (segment->p_vaddr
+                                  + (map->includes_filehdr
+                                     ? iehdr->e_ehsize : 0)
+                                  + (map->includes_phdrs
+                                     ? iehdr->e_phnum * iehdr->e_phentsize
+                                     : 0),
+                                  output_section->alignment_power)
+                     == output_section->vma))
                map->p_paddr = segment->p_vaddr;
 
              /* Match up the physical address of the segment with the
@@ -6866,22 +7189,17 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd)
                  || (bed->want_p_paddr_set_to_zero
                      && IS_CONTAINED_BY_VMA (output_section, segment)))
                {
-                 if (first_matching_lma || output_section->lma < matching_lma)
-                   {
-                     matching_lma = output_section->lma;
-                     first_matching_lma = FALSE;
-                   }
+                 if (matching_lma == NULL
+                     || output_section->lma < matching_lma->lma)
+                   matching_lma = output_section;
 
                  /* We assume that if the section fits within the segment
                     then it does not overlap any other section within that
                     segment.  */
                  map->sections[isec++] = output_section;
                }
-             else if (first_suggested_lma)
-               {
-                 suggested_lma = output_section->lma;
-                 first_suggested_lma = FALSE;
-               }
+             else if (suggested_lma == NULL)
+               suggested_lma = output_section;
 
              if (j == section_count)
                break;
@@ -6903,64 +7221,59 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd)
          pointer_to_map = &map->next;
 
          if (p_paddr_valid
-             && !bed->want_p_paddr_set_to_zero
-             && matching_lma != map->p_paddr
-             && !map->includes_filehdr
-             && !map->includes_phdrs)
-           /* 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 - map->p_paddr;
+             && !bed->want_p_paddr_set_to_zero)
+           {
+             bfd_vma hdr_size = 0;
+             if (map->includes_filehdr)
+               hdr_size = iehdr->e_ehsize;
+             if (map->includes_phdrs)
+               hdr_size += iehdr->e_phnum * iehdr->e_phentsize;
+
+             /* Account for padding before the first section in the
+                segment.  */
+             map->p_vaddr_offset = map->p_paddr + hdr_size - matching_lma->lma;
+           }
 
          free (sections);
          continue;
        }
       else
        {
-         if (!first_matching_lma)
-           {
-             /* At least one section fits inside the current segment.
-                Keep it, but modify its physical address to match the
-                LMA of the first section that fitted.  */
-             map->p_paddr = matching_lma;
-           }
-         else
-           {
-             /* None of the sections fitted inside the current segment.
-                Change the current segment's physical address to match
-                the LMA of the first section.  */
-             map->p_paddr = suggested_lma;
-           }
+         /* Change the current segment's physical address to match
+            the LMA of the first section that fitted, or if no
+            section fitted, the first section.  */
+         if (matching_lma == NULL)
+           matching_lma = suggested_lma;
+
+         map->p_paddr = matching_lma->lma;
 
          /* Offset the segment physical address from the lma
             to allow for space taken up by elf headers.  */
-         if (map->includes_filehdr)
+         if (map->includes_phdrs)
            {
-             if (map->p_paddr >= iehdr->e_ehsize)
-               map->p_paddr -= iehdr->e_ehsize;
-             else
-               {
-                 map->includes_filehdr = FALSE;
-                 map->includes_phdrs = FALSE;
-               }
+             map->p_paddr -= iehdr->e_phnum * iehdr->e_phentsize;
+
+             /* iehdr->e_phnum is just an estimate of the number
+                of program headers that we will need.  Make a note
+                here of the number we used and the segment we chose
+                to hold these headers, so that we can adjust the
+                offset when we know the correct value.  */
+             phdr_adjust_num = iehdr->e_phnum;
+             phdr_adjust_seg = map;
            }
 
-         if (map->includes_phdrs)
+         if (map->includes_filehdr)
            {
-             if (map->p_paddr >= iehdr->e_phnum * iehdr->e_phentsize)
-               {
-                 map->p_paddr -= iehdr->e_phnum * iehdr->e_phentsize;
-
-                 /* iehdr->e_phnum is just an estimate of the number
-                    of program headers that we will need.  Make a note
-                    here of the number we used and the segment we chose
-                    to hold these headers, so that we can adjust the
-                    offset when we know the correct value.  */
-                 phdr_adjust_num = iehdr->e_phnum;
-                 phdr_adjust_seg = map;
-               }
-             else
-               map->includes_phdrs = FALSE;
+             bfd_vma align = (bfd_vma) 1 << matching_lma->alignment_power;
+             map->p_paddr -= iehdr->e_ehsize;
+             /* We've subtracted off the size of headers from the
+                first section lma, but there may have been some
+                alignment padding before that section too.  Try to
+                account for that by adjusting the segment lma down to
+                the same alignment.  */
+             if (segment->p_align != 0 && segment->p_align < align)
+               align = segment->p_align;
+             map->p_paddr &= -align;
            }
        }
 
@@ -6975,8 +7288,7 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd)
       do
        {
          map->count = 0;
-         suggested_lma = 0;
-         first_suggested_lma = TRUE;
+         suggested_lma = NULL;
 
          /* Fill the current segment with sections that fit.  */
          for (j = 0; j < section_count; j++)
@@ -6998,13 +7310,15 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd)
                      /* If the first section in a segment does not start at
                         the beginning of the segment, then something is
                         wrong.  */
-                     if (output_section->lma
-                         != (map->p_paddr
-                             + (map->includes_filehdr ? iehdr->e_ehsize : 0)
-                             + (map->includes_phdrs
-                                ? iehdr->e_phnum * iehdr->e_phentsize
-                                : 0)))
-                       abort ();
+                     if (align_power (map->p_paddr
+                                      + (map->includes_filehdr
+                                         ? iehdr->e_ehsize : 0)
+                                      + (map->includes_phdrs
+                                         ? iehdr->e_phnum * iehdr->e_phentsize
+                                         : 0),
+                                      output_section->alignment_power)
+                         != output_section->lma)
+                       goto sorry;
                    }
                  else
                    {
@@ -7021,11 +7335,8 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd)
                          || (prev_sec->lma + prev_sec->size
                              > output_section->lma))
                        {
-                         if (first_suggested_lma)
-                           {
-                             suggested_lma = output_section->lma;
-                             first_suggested_lma = FALSE;
-                           }
+                         if (suggested_lma == NULL)
+                           suggested_lma = output_section;
 
                          continue;
                        }
@@ -7034,16 +7345,23 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd)
                  map->sections[map->count++] = output_section;
                  ++isec;
                  sections[j] = NULL;
-                 section->segment_mark = TRUE;
-               }
-             else if (first_suggested_lma)
-               {
-                 suggested_lma = output_section->lma;
-                 first_suggested_lma = FALSE;
+                 if (segment->p_type == PT_LOAD)
+                   section->segment_mark = TRUE;
                }
+             else if (suggested_lma == NULL)
+               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)
+           {
+           sorry:
+             bfd_set_error (bfd_error_sorry);
+             free (sections);
+             return FALSE;
+           }
 
          /* Add the current segment to the list of built segments.  */
          *pointer_to_map = map;
@@ -7054,8 +7372,8 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd)
              /* We still have not allocated all of the sections to
                 segments.  Create a new segment here, initialise it
                 and carry on looping.  */
-             amt = sizeof (struct elf_segment_map);
-             amt += ((bfd_size_type) section_count - 1) * sizeof (asection *);
+             amt = sizeof (struct elf_segment_map) - sizeof (asection *);
+             amt += (bfd_size_type) section_count * sizeof (asection *);
              map = (struct elf_segment_map *) bfd_zalloc (obfd, amt);
              if (map == NULL)
                {
@@ -7070,7 +7388,7 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd)
              map->p_type = segment->p_type;
              map->p_flags = segment->p_flags;
              map->p_flags_valid = 1;
-             map->p_paddr = suggested_lma;
+             map->p_paddr = suggested_lma->lma;
              map->p_paddr_valid = p_paddr_valid;
              map->includes_filehdr = 0;
              map->includes_phdrs = 0;
@@ -7096,6 +7414,15 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd)
       if (count > phdr_adjust_num)
        phdr_adjust_seg->p_paddr
          -= (count - phdr_adjust_num) * iehdr->e_phentsize;
+
+      for (map = map_first; map != NULL; map = map->next)
+       if (map->p_type == PT_PHDR)
+         {
+           bfd_vma adjust
+             = phdr_adjust_seg->includes_filehdr ? iehdr->e_ehsize : 0;
+           map->p_paddr = phdr_adjust_seg->p_paddr + adjust;
+           break;
+         }
     }
 
 #undef SEGMENT_END
@@ -7172,9 +7499,8 @@ copy_elf_program_header (bfd *ibfd, bfd *obfd)
 
       /* Allocate a segment map big enough to contain
         all of the sections we have selected.  */
-      amt = sizeof (struct elf_segment_map);
-      if (section_count != 0)
-       amt += ((bfd_size_type) section_count - 1) * sizeof (asection *);
+      amt = sizeof (struct elf_segment_map) - sizeof (asection *);
+      amt += (bfd_size_type) section_count * sizeof (asection *);
       map = (struct elf_segment_map *) bfd_zalloc (obfd, amt);
       if (map == NULL)
        return FALSE;
@@ -7261,16 +7587,20 @@ copy_elf_program_header (bfd *ibfd, bfd *obfd)
            }
        }
 
-      if (map->includes_filehdr && lowest_section != NULL)
-       /* We need to keep the space used by the headers fixed.  */
-       map->header_size = lowest_section->vma - segment->p_vaddr;
+      if (section_count == 0)
+       map->p_vaddr_offset = segment->p_vaddr;
+      else if (map->p_paddr_valid)
+       {
+         /* Account for padding before the first section in the segment.  */
+         bfd_vma hdr_size = 0;
+         if (map->includes_filehdr)
+           hdr_size = iehdr->e_ehsize;
+         if (map->includes_phdrs)
+           hdr_size += iehdr->e_phnum * iehdr->e_phentsize;
 
-      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);
+         map->p_vaddr_offset = (map->p_paddr + hdr_size
+                                - (lowest_section ? lowest_section->lma : 0));
+       }
 
       map->count = section_count;
       *pointer_to_map = map;
@@ -7389,9 +7719,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 %#Lx"
-                                   " is too large"),
-                                 ibfd, segment->p_align);
+             _bfd_error_handler (_("%pB: warning: segment alignment of %#"
+                                   PRIx64 " is too large"),
+                                 ibfd, (uint64_t) segment->p_align);
            else
              maxpagesize = segment->p_align;
          }
@@ -7439,7 +7769,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;
 
@@ -7544,7 +7875,16 @@ _bfd_elf_fixup_group_sections (bfd *ibfd, asection *discarded)
               but the SHT_GROUP section is, then adjust its size.  */
            else if (s->output_section == discarded
                     && isec->output_section != discarded)
-             removed += 4;
+             {
+               struct bfd_elf_section_data *elf_sec = elf_section_data (s);
+               removed += 4;
+               if (elf_sec->rel.hdr != NULL
+                   && (elf_sec->rel.hdr->sh_flags & SHF_GROUP) != 0)
+                 removed += 4;
+               if (elf_sec->rela.hdr != NULL
+                   && (elf_sec->rela.hdr->sh_flags & SHF_GROUP) != 0)
+                 removed += 4;
+             }
            s = elf_next_in_group (s);
            if (s == first)
              break;
@@ -7554,18 +7894,26 @@ _bfd_elf_fixup_group_sections (bfd *ibfd, asection *discarded)
            if (discarded != NULL)
              {
                /* If we've been called for ld -r, then we need to
-                  adjust the input section size.  This function may
-                  be called multiple times, so save the original
-                  size.  */
+                  adjust the input section size.  */
                if (isec->rawsize == 0)
                  isec->rawsize = isec->size;
                isec->size = isec->rawsize - removed;
+               if (isec->size <= 4)
+                 {
+                   isec->size = 0;
+                   isec->flags |= SEC_EXCLUDE;
+                 }
              }
            else
              {
                /* Adjust the output section size when called from
                   objcopy. */
                isec->output_section->size -= removed;
+               if (isec->output_section->size <= 4)
+                 {
+                   isec->output_section->size = 0;
+                   isec->output_section->flags |= SEC_EXCLUDE;
+                 }
              }
          }
       }
@@ -7692,8 +8040,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);
@@ -7701,7 +8049,7 @@ swap_out_syms (bfd *abfd,
     }
 
   outbound_syms = (bfd_byte *) bfd_alloc2 (abfd, 1 + symcount,
-                                           bed->s->sizeof_sym);
+                                          bed->s->sizeof_sym);
   if (outbound_syms == NULL)
     {
 error_return:
@@ -7870,10 +8218,11 @@ error_return:
                  if (shndx == SHN_BAD)
                    {
                      /* xgettext:c-format */
-                     _bfd_error_handler (_("\
-Unable to find equivalent output section for symbol '%s' from section '%s'"),
-                                         syms[idx]->name ? syms[idx]->name : "<Local sym>",
-                                         sec->name);
+                     _bfd_error_handler
+                       (_("unable to find equivalent output section"
+                          " for symbol '%s' from section '%s'"),
+                        syms[idx]->name ? syms[idx]->name : "<Local sym>",
+                        sec->name);
                      bfd_set_error (bfd_error_invalid_operation);
                      goto error_return;
                    }
@@ -8016,11 +8365,16 @@ Unable to find equivalent output section for symbol '%s' from section '%s'"),
 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 *);
@@ -8031,7 +8385,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;
 
@@ -8042,6 +8396,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 *);
@@ -8053,6 +8412,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 *);
 }
 
@@ -8087,7 +8453,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;
 }
 
@@ -8099,7 +8465,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;
 }
 
@@ -8111,7 +8477,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)
@@ -8120,15 +8486,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
@@ -8198,11 +8569,12 @@ _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
-           (_("%B: .gnu.version_r invalid entry"), abfd);
+           (_("%pB: .gnu.version_r invalid entry"), abfd);
          bfd_set_error (bfd_error_bad_value);
 error_return_verref:
          elf_tdata (abfd)->verref = NULL;
@@ -8210,6 +8582,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;
@@ -8219,7 +8603,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;
@@ -8250,8 +8634,8 @@ error_return_verref:
          else
            {
              iverneed->vn_auxptr = (struct elf_internal_vernaux *)
-                  bfd_alloc2 (abfd, iverneed->vn_cnt,
-                              sizeof (Elf_Internal_Vernaux));
+                 bfd_alloc2 (abfd, iverneed->vn_cnt,
+                             sizeof (Elf_Internal_Vernaux));
              if (iverneed->vn_auxptr == NULL)
                goto error_return_verref;
            }
@@ -8329,7 +8713,7 @@ error_return_verref:
        {
        error_return_bad_verdef:
          _bfd_error_handler
-           (_("%B: .gnu.version_d invalid entry"), abfd);
+           (_("%pB: .gnu.version_d invalid entry"), abfd);
          bfd_set_error (bfd_error_bad_value);
        error_return_verdef:
          elf_tdata (abfd)->verdef = NULL;
@@ -8414,8 +8798,8 @@ error_return_verref:
          else
            {
              iverdef->vd_auxptr = (struct elf_internal_verdaux *)
-                  bfd_alloc2 (abfd, iverdef->vd_cnt,
-                              sizeof (Elf_Internal_Verdaux));
+                 bfd_alloc2 (abfd, iverdef->vd_cnt,
+                             sizeof (Elf_Internal_Verdaux));
              if (iverdef->vd_auxptr == NULL)
                goto error_return_verdef;
            }
@@ -8479,7 +8863,7 @@ error_return_verref:
        freeidx++;
 
       elf_tdata (abfd)->verdef = (Elf_Internal_Verdef *)
-          bfd_zalloc2 (abfd, freeidx, sizeof (Elf_Internal_Verdef));
+         bfd_zalloc2 (abfd, freeidx, sizeof (Elf_Internal_Verdef));
       if (elf_tdata (abfd)->verdef == NULL)
        goto error_return;
 
@@ -8527,7 +8911,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;
@@ -8572,7 +8956,7 @@ _bfd_elf_is_local_label_name (bfd *abfd ATTRIBUTE_UNUSED,
      forward-backward labels (aka local labels) as locals.
      These labels have the form:
 
-       L0^A.*                                  (fake symbols)
+       L0^A.*                                 (fake symbols)
 
        [.]?L[0123456789]+{^A|^B}[0123456789]*  (local labels)
 
@@ -8653,11 +9037,12 @@ _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,
-                                    &elf_tdata (abfd)->dwarf2_find_line_info)
-      || _bfd_dwarf1_find_nearest_line (abfd, symbols, section, offset,
-                                       filename_ptr, functionname_ptr,
-                                       line_ptr))
+                                    dwarf_debug_sections,
+                                    &elf_tdata (abfd)->dwarf2_find_line_info))
+    return TRUE;
+
+  if (_bfd_dwarf1_find_nearest_line (abfd, symbols, section, offset,
+                                    filename_ptr, functionname_ptr, line_ptr))
     {
       if (!*functionname_ptr)
        _bfd_elf_find_function (abfd, symbols, section, offset,
@@ -8693,7 +9078,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);
 }
 
@@ -8765,6 +9150,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
@@ -8782,12 +9172,13 @@ _bfd_elf_set_section_contents (bfd *abfd,
   return TRUE;
 }
 
-void
+bfd_boolean
 _bfd_elf_no_info_to_howto (bfd *abfd ATTRIBUTE_UNUSED,
                           arelent *cache_ptr ATTRIBUTE_UNUSED,
                           Elf_Internal_Rela *dst ATTRIBUTE_UNUSED)
 {
   abort ();
+  return FALSE;
 }
 
 /* Try to convert a non-ELF reloc into an ELF one.  */
@@ -8833,7 +9224,7 @@ _bfd_elf_validate_reloc (bfd *abfd, arelent *areloc)
 
          howto = bfd_reloc_type_lookup (abfd, code);
 
-         if (areloc->howto->pcrel_offset != howto->pcrel_offset)
+         if (howto && areloc->howto->pcrel_offset != howto->pcrel_offset)
            {
              if (howto->pcrel_offset)
                areloc->addend += areloc->address;
@@ -8879,11 +9270,10 @@ _bfd_elf_validate_reloc (bfd *abfd, arelent *areloc)
   return TRUE;
 
  fail:
-  _bfd_error_handler
-    /* xgettext:c-format */
-    (_("%B: unsupported relocation type %s"),
-     abfd, areloc->howto->name);
-  bfd_set_error (bfd_error_bad_value);
+  /* xgettext:c-format */
+  _bfd_error_handler (_("%pB: %s unsupported"),
+                     abfd, areloc->howto->name);
+  bfd_set_error (bfd_error_sorry);
   return FALSE;
 }
 
@@ -9003,6 +9393,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
@@ -9139,6 +9546,84 @@ elfcore_grok_ppc_vsx (bfd *abfd, Elf_Internal_Note *note)
   return elfcore_make_note_pseudosection (abfd, ".reg-ppc-vsx", note);
 }
 
+static bfd_boolean
+elfcore_grok_ppc_tar (bfd *abfd, Elf_Internal_Note *note)
+{
+  return elfcore_make_note_pseudosection (abfd, ".reg-ppc-tar", note);
+}
+
+static bfd_boolean
+elfcore_grok_ppc_ppr (bfd *abfd, Elf_Internal_Note *note)
+{
+  return elfcore_make_note_pseudosection (abfd, ".reg-ppc-ppr", note);
+}
+
+static bfd_boolean
+elfcore_grok_ppc_dscr (bfd *abfd, Elf_Internal_Note *note)
+{
+  return elfcore_make_note_pseudosection (abfd, ".reg-ppc-dscr", note);
+}
+
+static bfd_boolean
+elfcore_grok_ppc_ebb (bfd *abfd, Elf_Internal_Note *note)
+{
+  return elfcore_make_note_pseudosection (abfd, ".reg-ppc-ebb", note);
+}
+
+static bfd_boolean
+elfcore_grok_ppc_pmu (bfd *abfd, Elf_Internal_Note *note)
+{
+  return elfcore_make_note_pseudosection (abfd, ".reg-ppc-pmu", note);
+}
+
+static bfd_boolean
+elfcore_grok_ppc_tm_cgpr (bfd *abfd, Elf_Internal_Note *note)
+{
+  return elfcore_make_note_pseudosection (abfd, ".reg-ppc-tm-cgpr", note);
+}
+
+static bfd_boolean
+elfcore_grok_ppc_tm_cfpr (bfd *abfd, Elf_Internal_Note *note)
+{
+  return elfcore_make_note_pseudosection (abfd, ".reg-ppc-tm-cfpr", note);
+}
+
+static bfd_boolean
+elfcore_grok_ppc_tm_cvmx (bfd *abfd, Elf_Internal_Note *note)
+{
+  return elfcore_make_note_pseudosection (abfd, ".reg-ppc-tm-cvmx", note);
+}
+
+static bfd_boolean
+elfcore_grok_ppc_tm_cvsx (bfd *abfd, Elf_Internal_Note *note)
+{
+  return elfcore_make_note_pseudosection (abfd, ".reg-ppc-tm-cvsx", note);
+}
+
+static bfd_boolean
+elfcore_grok_ppc_tm_spr (bfd *abfd, Elf_Internal_Note *note)
+{
+  return elfcore_make_note_pseudosection (abfd, ".reg-ppc-tm-spr", note);
+}
+
+static bfd_boolean
+elfcore_grok_ppc_tm_ctar (bfd *abfd, Elf_Internal_Note *note)
+{
+  return elfcore_make_note_pseudosection (abfd, ".reg-ppc-tm-ctar", note);
+}
+
+static bfd_boolean
+elfcore_grok_ppc_tm_cppr (bfd *abfd, Elf_Internal_Note *note)
+{
+  return elfcore_make_note_pseudosection (abfd, ".reg-ppc-tm-cppr", note);
+}
+
+static bfd_boolean
+elfcore_grok_ppc_tm_cdscr (bfd *abfd, Elf_Internal_Note *note)
+{
+  return elfcore_make_note_pseudosection (abfd, ".reg-ppc-tm-cdscr", note);
+}
+
 static bfd_boolean
 elfcore_grok_s390_high_gprs (bfd *abfd, Elf_Internal_Note *note)
 {
@@ -9241,6 +9726,18 @@ elfcore_grok_aarch_hw_watch (bfd *abfd, Elf_Internal_Note *note)
   return elfcore_make_note_pseudosection (abfd, ".reg-aarch-hw-watch", note);
 }
 
+static bfd_boolean
+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 */
@@ -9590,96 +10087,187 @@ elfcore_grok_note (bfd *abfd, Elf_Internal_Note *note)
     case NT_WIN32PSTATUS:
       return elfcore_grok_win32pstatus (abfd, note);
 
-    case NT_PRXFPREG:          /* Linux SSE extension */
+    case NT_PRXFPREG:          /* Linux SSE extension */
+      if (note->namesz == 6
+         && strcmp (note->namedata, "LINUX") == 0)
+       return elfcore_grok_prxfpreg (abfd, note);
+      else
+       return TRUE;
+
+    case NT_X86_XSTATE:                /* Linux XSAVE extension */
+      if (note->namesz == 6
+         && strcmp (note->namedata, "LINUX") == 0)
+       return elfcore_grok_xstatereg (abfd, note);
+      else
+       return TRUE;
+
+    case NT_PPC_VMX:
+      if (note->namesz == 6
+         && strcmp (note->namedata, "LINUX") == 0)
+       return elfcore_grok_ppc_vmx (abfd, note);
+      else
+       return TRUE;
+
+    case NT_PPC_VSX:
+      if (note->namesz == 6
+         && strcmp (note->namedata, "LINUX") == 0)
+       return elfcore_grok_ppc_vsx (abfd, note);
+      else
+       return TRUE;
+
+    case NT_PPC_TAR:
+      if (note->namesz == 6
+         && strcmp (note->namedata, "LINUX") == 0)
+       return elfcore_grok_ppc_tar (abfd, note);
+      else
+       return TRUE;
+
+    case NT_PPC_PPR:
+      if (note->namesz == 6
+         && strcmp (note->namedata, "LINUX") == 0)
+       return elfcore_grok_ppc_ppr (abfd, note);
+      else
+       return TRUE;
+
+    case NT_PPC_DSCR:
+      if (note->namesz == 6
+         && strcmp (note->namedata, "LINUX") == 0)
+       return elfcore_grok_ppc_dscr (abfd, note);
+      else
+       return TRUE;
+
+    case NT_PPC_EBB:
+      if (note->namesz == 6
+         && strcmp (note->namedata, "LINUX") == 0)
+       return elfcore_grok_ppc_ebb (abfd, note);
+      else
+       return TRUE;
+
+    case NT_PPC_PMU:
+      if (note->namesz == 6
+         && strcmp (note->namedata, "LINUX") == 0)
+       return elfcore_grok_ppc_pmu (abfd, note);
+      else
+       return TRUE;
+
+    case NT_PPC_TM_CGPR:
+      if (note->namesz == 6
+         && strcmp (note->namedata, "LINUX") == 0)
+       return elfcore_grok_ppc_tm_cgpr (abfd, note);
+      else
+       return TRUE;
+
+    case NT_PPC_TM_CFPR:
+      if (note->namesz == 6
+         && strcmp (note->namedata, "LINUX") == 0)
+       return elfcore_grok_ppc_tm_cfpr (abfd, note);
+      else
+       return TRUE;
+
+    case NT_PPC_TM_CVMX:
+      if (note->namesz == 6
+         && strcmp (note->namedata, "LINUX") == 0)
+       return elfcore_grok_ppc_tm_cvmx (abfd, note);
+      else
+       return TRUE;
+
+    case NT_PPC_TM_CVSX:
+      if (note->namesz == 6
+         && strcmp (note->namedata, "LINUX") == 0)
+       return elfcore_grok_ppc_tm_cvsx (abfd, note);
+      else
+       return TRUE;
+
+    case NT_PPC_TM_SPR:
       if (note->namesz == 6
          && strcmp (note->namedata, "LINUX") == 0)
-       return elfcore_grok_prxfpreg (abfd, note);
+       return elfcore_grok_ppc_tm_spr (abfd, note);
       else
        return TRUE;
 
-    case NT_X86_XSTATE:                /* Linux XSAVE extension */
+    case NT_PPC_TM_CTAR:
       if (note->namesz == 6
          && strcmp (note->namedata, "LINUX") == 0)
-       return elfcore_grok_xstatereg (abfd, note);
+       return elfcore_grok_ppc_tm_ctar (abfd, note);
       else
        return TRUE;
 
-    case NT_PPC_VMX:
+    case NT_PPC_TM_CPPR:
       if (note->namesz == 6
          && strcmp (note->namedata, "LINUX") == 0)
-       return elfcore_grok_ppc_vmx (abfd, note);
+       return elfcore_grok_ppc_tm_cppr (abfd, note);
       else
        return TRUE;
 
-    case NT_PPC_VSX:
+    case NT_PPC_TM_CDSCR:
       if (note->namesz == 6
-          && strcmp (note->namedata, "LINUX") == 0)
-        return elfcore_grok_ppc_vsx (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
-          && strcmp (note->namedata, "LINUX") == 0)
-        return elfcore_grok_s390_high_gprs (abfd, note);
+         && strcmp (note->namedata, "LINUX") == 0)
+       return elfcore_grok_s390_high_gprs (abfd, note);
       else
-        return TRUE;
+       return TRUE;
 
     case NT_S390_TIMER:
       if (note->namesz == 6
-          && strcmp (note->namedata, "LINUX") == 0)
-        return elfcore_grok_s390_timer (abfd, note);
+         && strcmp (note->namedata, "LINUX") == 0)
+       return elfcore_grok_s390_timer (abfd, note);
       else
-        return TRUE;
+       return TRUE;
 
     case NT_S390_TODCMP:
       if (note->namesz == 6
-          && strcmp (note->namedata, "LINUX") == 0)
-        return elfcore_grok_s390_todcmp (abfd, note);
+         && strcmp (note->namedata, "LINUX") == 0)
+       return elfcore_grok_s390_todcmp (abfd, note);
       else
-        return TRUE;
+       return TRUE;
 
     case NT_S390_TODPREG:
       if (note->namesz == 6
-          && strcmp (note->namedata, "LINUX") == 0)
-        return elfcore_grok_s390_todpreg (abfd, note);
+         && strcmp (note->namedata, "LINUX") == 0)
+       return elfcore_grok_s390_todpreg (abfd, note);
       else
-        return TRUE;
+       return TRUE;
 
     case NT_S390_CTRS:
       if (note->namesz == 6
-          && strcmp (note->namedata, "LINUX") == 0)
-        return elfcore_grok_s390_ctrs (abfd, note);
+         && strcmp (note->namedata, "LINUX") == 0)
+       return elfcore_grok_s390_ctrs (abfd, note);
       else
-        return TRUE;
+       return TRUE;
 
     case NT_S390_PREFIX:
       if (note->namesz == 6
-          && strcmp (note->namedata, "LINUX") == 0)
-        return elfcore_grok_s390_prefix (abfd, note);
+         && strcmp (note->namedata, "LINUX") == 0)
+       return elfcore_grok_s390_prefix (abfd, note);
       else
-        return TRUE;
+       return TRUE;
 
     case NT_S390_LAST_BREAK:
       if (note->namesz == 6
-          && strcmp (note->namedata, "LINUX") == 0)
-        return elfcore_grok_s390_last_break (abfd, note);
+         && strcmp (note->namedata, "LINUX") == 0)
+       return elfcore_grok_s390_last_break (abfd, note);
       else
-        return TRUE;
+       return TRUE;
 
     case NT_S390_SYSTEM_CALL:
       if (note->namesz == 6
-          && strcmp (note->namedata, "LINUX") == 0)
-        return elfcore_grok_s390_system_call (abfd, note);
+         && strcmp (note->namedata, "LINUX") == 0)
+       return elfcore_grok_s390_system_call (abfd, note);
       else
-        return TRUE;
+       return TRUE;
 
     case NT_S390_TDB:
       if (note->namesz == 6
-          && strcmp (note->namedata, "LINUX") == 0)
-        return elfcore_grok_s390_tdb (abfd, note);
+         && strcmp (note->namedata, "LINUX") == 0)
+       return elfcore_grok_s390_tdb (abfd, note);
       else
-        return TRUE;
+       return TRUE;
 
     case NT_S390_VXRS_LOW:
       if (note->namesz == 6
@@ -9737,6 +10325,20 @@ elfcore_grok_note (bfd *abfd, Elf_Internal_Note *note)
       else
        return TRUE;
 
+    case NT_ARM_SVE:
+      if (note->namesz == 6
+         && strcmp (note->namedata, "LINUX") == 0)
+       return elfcore_grok_aarch_sve (abfd, 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)
@@ -9749,18 +10351,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",
@@ -9812,8 +10403,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;
@@ -9861,6 +10452,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. */
@@ -9970,9 +10562,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:
@@ -9987,19 +10584,20 @@ elfcore_grok_freebsd_note (bfd *abfd, Elf_Internal_Note *note)
       else
        return TRUE;
 
-    case NT_FREEBSD_PROCSTAT_AUXV:
-      {
-       asection *sect = bfd_make_section_anyway_with_flags (abfd, ".auxv",
-                                                            SEC_HAS_CONTENTS);
+    case NT_FREEBSD_PROCSTAT_PROC:
+      return elfcore_make_note_pseudosection (abfd, ".note.freebsdcore.proc",
+                                             note);
 
-       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;
+    case NT_FREEBSD_PROCSTAT_FILES:
+      return elfcore_make_note_pseudosection (abfd, ".note.freebsdcore.files",
+                                             note);
 
-       return TRUE;
-      }
+    case NT_FREEBSD_PROCSTAT_VMMAP:
+      return elfcore_make_note_pseudosection (abfd, ".note.freebsdcore.vmmap",
+                                             note);
+
+    case NT_FREEBSD_PROCSTAT_AUXV:
+      return elfcore_make_auxv_note_section (abfd, note, 4);
 
     case NT_X86_XSTATE:
       if (note->namesz == 8)
@@ -10011,6 +10609,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;
     }
@@ -10033,6 +10634,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);
@@ -10057,17 +10661,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.  */
@@ -10095,6 +10706,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.  */
 
@@ -10117,6 +10745,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);
@@ -10148,18 +10779,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)
     {
@@ -10188,6 +10808,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);
 
@@ -10222,8 +10845,8 @@ elfcore_grok_nto_status (bfd *abfd, Elf_Internal_Note *note, long *tid)
   if (sect == NULL)
     return FALSE;
 
-  sect->size            = note->descsz;
-  sect->filepos         = note->descpos;
+  sect->size           = note->descsz;
+  sect->filepos                = note->descpos;
   sect->alignment_power = 2;
 
   return (elfcore_maybe_make_sect (abfd, ".qnx_core_status", sect));
@@ -10251,8 +10874,8 @@ elfcore_grok_nto_regs (bfd *abfd,
   if (sect == NULL)
     return FALSE;
 
-  sect->size            = note->descsz;
-  sect->filepos         = note->descpos;
+  sect->size           = note->descsz;
+  sect->filepos                = note->descpos;
   sect->alignment_power = 2;
 
   /* This is the current thread.  */
@@ -10309,8 +10932,8 @@ elfcore_grok_spu_note (bfd *abfd, Elf_Internal_Note *note)
   if (sect == NULL)
     return FALSE;
 
-  sect->size            = note->descsz;
-  sect->filepos         = note->descpos;
+  sect->size           = note->descsz;
+  sect->filepos                = note->descpos;
   sect->alignment_power = 1;
 
   return TRUE;
@@ -10383,6 +11006,23 @@ elfcore_write_note (bfd *abfd,
   return buf;
 }
 
+/* gcc-8 warns (*) on all the strncpy calls in this function about
+   possible string truncation.  The "truncation" is not a bug.  We
+   have an external representation of structs with fields that are not
+   necessarily NULL terminated and corresponding internal
+   representation fields that are one larger so that they can always
+   be NULL terminated.
+   gcc versions between 4.2 and 4.6 do not allow pragma control of
+   diagnostics inside functions, giving a hard error if you try to use
+   the finer control available with later versions.
+   gcc prior to 4.2 warns about diagnostic push and pop.
+   gcc-5, gcc-6 and gcc-7 warn that -Wstringop-truncation is unknown,
+   unless you also add #pragma GCC diagnostic ignored "-Wpragma".
+   (*) Depending on your system header files!  */
+#if GCC_VERSION >= 8000
+# pragma GCC diagnostic push
+# pragma GCC diagnostic ignored "-Wstringop-truncation"
+#endif
 char *
 elfcore_write_prpsinfo (bfd  *abfd,
                        char *buf,
@@ -10402,16 +11042,16 @@ elfcore_write_prpsinfo (bfd  *abfd,
     }
 
 #if defined (HAVE_PRPSINFO_T) || defined (HAVE_PSINFO_T)
-#if defined (HAVE_PRPSINFO32_T) || defined (HAVE_PSINFO32_T)
+# if defined (HAVE_PRPSINFO32_T) || defined (HAVE_PSINFO32_T)
   if (bed->s->elfclass == ELFCLASS32)
     {
-#if defined (HAVE_PSINFO32_T)
+#  if defined (HAVE_PSINFO32_T)
       psinfo32_t data;
       int note_type = NT_PSINFO;
-#else
+#  else
       prpsinfo32_t data;
       int note_type = NT_PRPSINFO;
-#endif
+#  endif
 
       memset (&data, 0, sizeof (data));
       strncpy (data.pr_fname, fname, sizeof (data.pr_fname));
@@ -10420,15 +11060,15 @@ elfcore_write_prpsinfo (bfd  *abfd,
                                 "CORE", note_type, &data, sizeof (data));
     }
   else
-#endif
+# endif
     {
-#if defined (HAVE_PSINFO_T)
+# if defined (HAVE_PSINFO_T)
       psinfo_t data;
       int note_type = NT_PSINFO;
-#else
+# else
       prpsinfo_t data;
       int note_type = NT_PRPSINFO;
-#endif
+# endif
 
       memset (&data, 0, sizeof (data));
       strncpy (data.pr_fname, fname, sizeof (data.pr_fname));
@@ -10441,17 +11081,31 @@ elfcore_write_prpsinfo (bfd  *abfd,
   free (buf);
   return NULL;
 }
+#if GCC_VERSION >= 8000
+# pragma GCC diagnostic pop
+#endif
 
 char *
 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 *
@@ -10459,11 +11113,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 *
@@ -10636,14 +11301,170 @@ elfcore_write_ppc_vmx (bfd *abfd,
 
 char *
 elfcore_write_ppc_vsx (bfd *abfd,
-                       char *buf,
-                       int *bufsiz,
-                       const void *ppc_vsx,
-                       int size)
+                      char *buf,
+                      int *bufsiz,
+                      const void *ppc_vsx,
+                      int size)
+{
+  char *note_name = "LINUX";
+  return elfcore_write_note (abfd, buf, bufsiz,
+                            note_name, NT_PPC_VSX, ppc_vsx, size);
+}
+
+char *
+elfcore_write_ppc_tar (bfd *abfd,
+                      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);
+}
+
+char *
+elfcore_write_ppc_ppr (bfd *abfd,
+                      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);
+}
+
+char *
+elfcore_write_ppc_dscr (bfd *abfd,
+                       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);
+}
+
+char *
+elfcore_write_ppc_ebb (bfd *abfd,
+                      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);
+}
+
+char *
+elfcore_write_ppc_pmu (bfd *abfd,
+                      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);
+}
+
+char *
+elfcore_write_ppc_tm_cgpr (bfd *abfd,
+                          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);
+}
+
+char *
+elfcore_write_ppc_tm_cfpr (bfd *abfd,
+                          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);
+}
+
+char *
+elfcore_write_ppc_tm_cvmx (bfd *abfd,
+                          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);
+}
+
+char *
+elfcore_write_ppc_tm_cvsx (bfd *abfd,
+                          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_VSX, ppc_vsx, 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 *note_name = "LINUX";
+  return elfcore_write_note (abfd, buf, bufsiz,
+                            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 *note_name = "LINUX";
+  return elfcore_write_note (abfd, buf, bufsiz,
+                            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 *note_name = "LINUX";
+  return elfcore_write_note (abfd, buf, bufsiz,
+                            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 *note_name = "LINUX";
+  return elfcore_write_note (abfd, buf, bufsiz,
+                            note_name, NT_PPC_TM_CDSCR, ppc_tm_cdscr, size);
 }
 
 static char *
@@ -10655,68 +11476,68 @@ elfcore_write_s390_high_gprs (bfd *abfd,
 {
   char *note_name = "LINUX";
   return elfcore_write_note (abfd, buf, bufsiz,
-                             note_name, NT_S390_HIGH_GPRS,
+                            note_name, NT_S390_HIGH_GPRS,
                             s390_high_gprs, size);
 }
 
 char *
 elfcore_write_s390_timer (bfd *abfd,
-                          char *buf,
-                          int *bufsiz,
-                          const void *s390_timer,
-                          int size)
+                         char *buf,
+                         int *bufsiz,
+                         const void *s390_timer,
+                         int size)
 {
   char *note_name = "LINUX";
   return elfcore_write_note (abfd, buf, bufsiz,
-                             note_name, NT_S390_TIMER, s390_timer, size);
+                            note_name, NT_S390_TIMER, s390_timer, size);
 }
 
 char *
 elfcore_write_s390_todcmp (bfd *abfd,
-                           char *buf,
-                           int *bufsiz,
-                           const void *s390_todcmp,
-                           int size)
+                          char *buf,
+                          int *bufsiz,
+                          const void *s390_todcmp,
+                          int size)
 {
   char *note_name = "LINUX";
   return elfcore_write_note (abfd, buf, bufsiz,
-                             note_name, NT_S390_TODCMP, s390_todcmp, size);
+                            note_name, NT_S390_TODCMP, s390_todcmp, size);
 }
 
 char *
 elfcore_write_s390_todpreg (bfd *abfd,
-                            char *buf,
-                            int *bufsiz,
-                            const void *s390_todpreg,
-                            int size)
+                           char *buf,
+                           int *bufsiz,
+                           const void *s390_todpreg,
+                           int size)
 {
   char *note_name = "LINUX";
   return elfcore_write_note (abfd, buf, bufsiz,
-                             note_name, NT_S390_TODPREG, s390_todpreg, size);
+                            note_name, NT_S390_TODPREG, s390_todpreg, size);
 }
 
 char *
 elfcore_write_s390_ctrs (bfd *abfd,
-                         char *buf,
-                         int *bufsiz,
-                         const void *s390_ctrs,
-                         int size)
+                        char *buf,
+                        int *bufsiz,
+                        const void *s390_ctrs,
+                        int size)
 {
   char *note_name = "LINUX";
   return elfcore_write_note (abfd, buf, bufsiz,
-                             note_name, NT_S390_CTRS, s390_ctrs, size);
+                            note_name, NT_S390_CTRS, s390_ctrs, size);
 }
 
 char *
 elfcore_write_s390_prefix (bfd *abfd,
-                           char *buf,
-                           int *bufsiz,
-                           const void *s390_prefix,
-                           int size)
+                          char *buf,
+                          int *bufsiz,
+                          const void *s390_prefix,
+                          int size)
 {
   char *note_name = "LINUX";
   return elfcore_write_note (abfd, buf, bufsiz,
-                             note_name, NT_S390_PREFIX, s390_prefix, size);
+                            note_name, NT_S390_PREFIX, s390_prefix, size);
 }
 
 char *
@@ -10728,7 +11549,7 @@ elfcore_write_s390_last_break (bfd *abfd,
 {
   char *note_name = "LINUX";
   return elfcore_write_note (abfd, buf, bufsiz,
-                             note_name, NT_S390_LAST_BREAK,
+                            note_name, NT_S390_LAST_BREAK,
                             s390_last_break, size);
 }
 
@@ -10741,7 +11562,7 @@ elfcore_write_s390_system_call (bfd *abfd,
 {
   char *note_name = "LINUX";
   return elfcore_write_note (abfd, buf, bufsiz,
-                             note_name, NT_S390_SYSTEM_CALL,
+                            note_name, NT_S390_SYSTEM_CALL,
                             s390_system_call, size);
 }
 
@@ -10754,7 +11575,7 @@ elfcore_write_s390_tdb (bfd *abfd,
 {
   char *note_name = "LINUX";
   return elfcore_write_note (abfd, buf, bufsiz,
-                             note_name, NT_S390_TDB, s390_tdb, size);
+                            note_name, NT_S390_TDB, s390_tdb, size);
 }
 
 char *
@@ -10856,6 +11677,30 @@ elfcore_write_aarch_hw_watch (bfd *abfd,
                             note_name, NT_ARM_HW_WATCH, aarch_hw_watch, size);
 }
 
+char *
+elfcore_write_aarch_sve (bfd *abfd,
+                        char *buf,
+                        int *bufsiz,
+                        const void *aarch_sve,
+                        int size)
+{
+  char *note_name = "LINUX";
+  return elfcore_write_note (abfd, buf, bufsiz,
+                            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,
@@ -10874,6 +11719,32 @@ elfcore_write_register_note (bfd *abfd,
     return elfcore_write_ppc_vmx (abfd, buf, bufsiz, data, size);
   if (strcmp (section, ".reg-ppc-vsx") == 0)
     return elfcore_write_ppc_vsx (abfd, buf, bufsiz, data, size);
+  if (strcmp (section, ".reg-ppc-tar") == 0)
+    return elfcore_write_ppc_tar (abfd, buf, bufsiz, data, size);
+  if (strcmp (section, ".reg-ppc-ppr") == 0)
+    return elfcore_write_ppc_ppr (abfd, buf, bufsiz, data, size);
+  if (strcmp (section, ".reg-ppc-dscr") == 0)
+    return elfcore_write_ppc_dscr (abfd, buf, bufsiz, data, size);
+  if (strcmp (section, ".reg-ppc-ebb") == 0)
+    return elfcore_write_ppc_ebb (abfd, buf, bufsiz, data, size);
+  if (strcmp (section, ".reg-ppc-pmu") == 0)
+    return elfcore_write_ppc_pmu (abfd, buf, bufsiz, data, size);
+  if (strcmp (section, ".reg-ppc-tm-cgpr") == 0)
+    return elfcore_write_ppc_tm_cgpr (abfd, buf, bufsiz, data, size);
+  if (strcmp (section, ".reg-ppc-tm-cfpr") == 0)
+    return elfcore_write_ppc_tm_cfpr (abfd, buf, bufsiz, data, size);
+  if (strcmp (section, ".reg-ppc-tm-cvmx") == 0)
+    return elfcore_write_ppc_tm_cvmx (abfd, buf, bufsiz, data, size);
+  if (strcmp (section, ".reg-ppc-tm-cvsx") == 0)
+    return elfcore_write_ppc_tm_cvsx (abfd, buf, bufsiz, data, size);
+  if (strcmp (section, ".reg-ppc-tm-spr") == 0)
+    return elfcore_write_ppc_tm_spr (abfd, buf, bufsiz, data, size);
+  if (strcmp (section, ".reg-ppc-tm-ctar") == 0)
+    return elfcore_write_ppc_tm_ctar (abfd, buf, bufsiz, data, size);
+  if (strcmp (section, ".reg-ppc-tm-cppr") == 0)
+    return elfcore_write_ppc_tm_cppr (abfd, buf, bufsiz, data, size);
+  if (strcmp (section, ".reg-ppc-tm-cdscr") == 0)
+    return elfcore_write_ppc_tm_cdscr (abfd, buf, bufsiz, data, size);
   if (strcmp (section, ".reg-s390-high-gprs") == 0)
     return elfcore_write_s390_high_gprs (abfd, buf, bufsiz, data, size);
   if (strcmp (section, ".reg-s390-timer") == 0)
@@ -10908,18 +11779,31 @@ elfcore_write_register_note (bfd *abfd,
     return elfcore_write_aarch_hw_break (abfd, buf, bufsiz, data, size);
   if (strcmp (section, ".reg-aarch-hw-watch") == 0)
     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;
 }
 
 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;
+  if (align != 4 && align != 8)
+    return FALSE;
+
   p = buf;
   while (p < buf + size)
     {
-      /* FIXME: bad alignment assumption.  */
       Elf_External_Note *xnp = (Elf_External_Note *) p;
       Elf_Internal_Note in;
 
@@ -10934,7 +11818,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
@@ -10942,7 +11826,7 @@ elf_parse_notes (bfd *abfd, char *buf, size_t size, file_ptr offset)
        return FALSE;
 
       switch (bfd_get_format (abfd))
-        {
+       {
        default:
          return TRUE;
 
@@ -10962,7 +11846,8 @@ elf_parse_notes (bfd *abfd, char *buf, size_t size, file_ptr offset)
              GROKER_ELEMENT ("NetBSD-CORE", elfcore_grok_netbsd_note),
              GROKER_ELEMENT ( "OpenBSD", elfcore_grok_openbsd_note),
              GROKER_ELEMENT ("QNX", elfcore_grok_nto_note),
-             GROKER_ELEMENT ("SPU/", elfcore_grok_spu_note)
+             GROKER_ELEMENT ("SPU/", elfcore_grok_spu_note),
+             GROKER_ELEMENT ("GNU", elfobj_grok_gnu_note)
            };
 #undef GROKER_ELEMENT
            int i;
@@ -10996,14 +11881,15 @@ 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)
+bfd_boolean
+elf_read_notes (bfd *abfd, file_ptr offset, bfd_size_type size,
+               size_t align)
 {
   char *buf;
 
@@ -11022,7 +11908,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;
@@ -11070,8 +11956,9 @@ bfd_get_elf_phdrs (bfd *abfd, void *phdrs)
     }
 
   num_phdrs = elf_elfheader (abfd)->e_phnum;
-  memcpy (phdrs, elf_tdata (abfd)->phdr,
-         num_phdrs * sizeof (Elf_Internal_Phdr));
+  if (num_phdrs != 0)
+    memcpy (phdrs, elf_tdata (abfd)->phdr,
+           num_phdrs * sizeof (Elf_Internal_Phdr));
 
   return num_phdrs;
 }
@@ -11169,7 +12056,8 @@ _bfd_elf_section_offset (bfd *abfd,
 
          /* address_size and sec->size are in octets.  Convert
             to bytes before subtracting the original offset.  */
-         offset = (sec->size - address_size) / bfd_octets_per_byte (abfd) - offset;
+         offset = ((sec->size - address_size)
+                   / bfd_octets_per_byte (abfd, sec) - offset);
        }
       return offset;
     }
@@ -11326,22 +12214,37 @@ asection _bfd_elf_large_com_section
   = BFD_FAKE_SECTION (_bfd_elf_large_com_section, &lcomm_sym,
                      "LARGE_COMMON", 0, SEC_IS_COMMON);
 
-void
-_bfd_elf_post_process_headers (bfd * abfd,
-                              struct bfd_link_info * link_info ATTRIBUTE_UNUSED)
+bfd_boolean
+_bfd_elf_final_write_processing (bfd *abfd)
 {
-  Elf_Internal_Ehdr * i_ehdrp; /* ELF file header, internal form.  */
+  Elf_Internal_Ehdr *i_ehdrp;  /* ELF file header, internal form.  */
 
   i_ehdrp = elf_elfheader (abfd);
 
-  i_ehdrp->e_ident[EI_OSABI] = get_elf_backend_data (abfd)->elf_osabi;
-
-  /* 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_sorry);
+         return FALSE;
+       }
+    }
+  return TRUE;
 }
 
 
This page took 0.098549 seconds and 4 git commands to generate.