Ignore degenerate PT_LOAD segments
[deliverable/binutils-gdb.git] / bfd / elf.c
index 8cd67ad59bb8853ab915a2ba775556c32fe9b950..b069b592652dfd4d5c82478c71ba1b67538953fa 100644 (file)
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -1,6 +1,6 @@
 /* ELF executable support for BFD.
 
 /* ELF executable support for BFD.
 
-   Copyright (C) 1993-2017 Free Software Foundation, Inc.
+   Copyright (C) 1993-2018 Free Software Foundation, Inc.
 
    This file is part of BFD, the Binary File Descriptor library.
 
 
    This file is part of BFD, the Binary File Descriptor library.
 
@@ -52,9 +52,10 @@ static int elf_sort_sections (const void *, const void *);
 static bfd_boolean assign_file_positions_except_relocs (bfd *, struct bfd_link_info *);
 static bfd_boolean prep_headers (bfd *);
 static bfd_boolean swap_out_syms (bfd *, struct elf_strtab_hash **, int) ;
 static bfd_boolean assign_file_positions_except_relocs (bfd *, struct bfd_link_info *);
 static bfd_boolean prep_headers (bfd *);
 static bfd_boolean swap_out_syms (bfd *, struct elf_strtab_hash **, int) ;
-static bfd_boolean elf_read_notes (bfd *, file_ptr, bfd_size_type) ;
+static bfd_boolean elf_read_notes (bfd *, file_ptr, bfd_size_type,
+                                  size_t align) ;
 static bfd_boolean elf_parse_notes (bfd *abfd, char *buf, size_t size,
 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
 
 /* Swap version information in and out.  The version information is
    currently size independent.  If that ever changes, this code will
@@ -462,7 +463,7 @@ bfd_elf_get_elf_syms (bfd *ibfd,
       if (extshndx_buf == NULL)
        {
          alloc_extshndx = (Elf_External_Sym_Shndx *)
       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
          extshndx_buf = alloc_extshndx;
        }
       if (extshndx_buf == NULL
@@ -477,7 +478,7 @@ bfd_elf_get_elf_syms (bfd *ibfd,
   if (intsym_buf == NULL)
     {
       alloc_intsym = (Elf_Internal_Sym *)
   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;
       intsym_buf = alloc_intsym;
       if (intsym_buf == NULL)
        goto out;
@@ -486,7 +487,7 @@ 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,
   /* 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))
        isym < isymend;
        esym += extsym_size, isym++, shndx = shndx != NULL ? shndx + 1 : NULL)
     if (!(*bed->s->swap_symbol_in) (ibfd, esym, shndx, isym))
@@ -623,7 +624,7 @@ 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 **)
 
          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 *));
          if (elf_tdata (abfd)->group_sect_ptr == NULL)
            return FALSE;
          memset (elf_tdata (abfd)->group_sect_ptr, 0, num_group * sizeof (Elf_Internal_Shdr *));
@@ -638,11 +639,11 @@ setup_group (bfd *abfd, Elf_Internal_Shdr *hdr, asection *newsect)
                  unsigned char *src;
                  Elf_Internal_Group *dest;
 
                  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;
                  /* Add to list of sections.  */
                  elf_tdata (abfd)->group_sect_ptr[num_group] = shdr;
                  num_group += 1;
@@ -651,7 +652,7 @@ setup_group (bfd *abfd, Elf_Internal_Shdr *hdr, asection *newsect)
                  BFD_ASSERT (sizeof (*dest) >= 4);
                  amt = shdr->sh_size * sizeof (*dest) / 4;
                  shdr->contents = (unsigned char *)
                  BFD_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)
                    {
                  /* PR binutils/4110: Handle corrupt group headers.  */
                  if (shdr->contents == NULL)
                    {
@@ -736,10 +737,14 @@ setup_group (bfd *abfd, Elf_Internal_Shdr *hdr, asection *newsect)
 
   if (num_group != (unsigned) -1)
     {
 
   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;
          Elf_Internal_Shdr *shdr = elf_tdata (abfd)->group_sect_ptr[i];
          Elf_Internal_Group *idx;
          bfd_size_type n_elt;
@@ -802,7 +807,8 @@ setup_group (bfd *abfd, Elf_Internal_Shdr *hdr, asection *newsect)
                if (shdr->bfd_section != NULL)
                  elf_next_in_group (shdr->bfd_section) = 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;
              }
        }
                break;
              }
        }
@@ -1089,7 +1095,8 @@ _bfd_elf_make_section_from_shdr (bfd *abfd,
       if (!bfd_malloc_and_get_section (abfd, newsect, &contents))
        return FALSE;
 
       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);
     }
 
       free (contents);
     }
 
@@ -1277,7 +1284,7 @@ section_match (const Elf_Internal_Shdr * a,
               const Elf_Internal_Shdr * b)
 {
   return
               const Elf_Internal_Shdr * b)
 {
   return
-    a->sh_type         == b->sh_type
+    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_flags & ~ SHF_INFO_LINK)
     == (b->sh_flags & ~ SHF_INFO_LINK)
     && a->sh_addralign == b->sh_addralign
@@ -1325,7 +1332,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.  */
 /* 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,
 static bfd_boolean
 copy_special_section_fields (const bfd *ibfd,
                             bfd *obfd,
@@ -1428,7 +1435,7 @@ copy_special_section_fields (const bfd *ibfd,
 
   return changed;
 }
 
   return changed;
 }
-  
+
 /* Copy the program header and other data from one object module to
    another.  */
 
 /* Copy the program header and other data from one object module to
    another.  */
 
@@ -1460,7 +1467,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];
   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);
 
   /* Copy object attributes.  */
   _bfd_elf_copy_obj_attributes (ibfd, obfd);
 
@@ -1656,7 +1663,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.
        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;
       for (; extdyn <= (extdynend - extdynsize); extdyn += extdynsize)
        {
          Elf_Internal_Dyn dyn;
@@ -2220,7 +2227,7 @@ 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;
        for (entry = elf_symtab_shndx_list (abfd); entry != NULL; entry = entry->next)
          if (entry->ndx == shindex)
            goto success;
-       
+
        entry = bfd_alloc (abfd, sizeof * entry);
        if (entry == NULL)
          goto fail;
        entry = bfd_alloc (abfd, sizeof * entry);
        if (entry == NULL)
          goto fail;
@@ -2573,95 +2580,95 @@ 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 },
 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 },
 };
 
 static const struct bfd_elf_special_section special_sections_c[] =
 {
   { STRING_COMMA_LEN (".comment"), 0, SHT_PROGBITS, 0 },
-  { NULL,                       0, 0, 0,            0 }
+  { NULL,                      0, 0, 0,            0 }
 };
 
 static const struct bfd_elf_special_section special_sections_d[] =
 {
 };
 
 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.  */
   /* 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 (".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[] =
 {
 };
 
 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 },
   { 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 },
 };
 
 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.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[] =
 {
 };
 
 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[] =
 {
 };
 
 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 (".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 },
 };
 
 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 },
 };
 
 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 },
 };
 
 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 },
 };
 
 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[] =
 };
 
 static const struct bfd_elf_special_section special_sections_s[] =
@@ -2672,24 +2679,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 },
   /* 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[] =
 {
 };
 
 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 },
   { 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[] =
 {
 };
 
 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 },
   { 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[] =
 };
 
 static const struct bfd_elf_special_section * const special_sections[] =
@@ -2817,7 +2824,7 @@ _bfd_elf_new_section_hook (bfd *abfd, asection *sec)
   if (sdata == NULL)
     {
       sdata = (struct bfd_elf_section_data *) bfd_zalloc (abfd,
   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;
       if (sdata == NULL)
        return FALSE;
       sec->used_by_bfd = sdata;
@@ -2990,7 +2997,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;
     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;
 
        return FALSE;
       return TRUE;
 
@@ -3730,12 +3738,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,
   /* 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,
   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);
   if (i_shdrp[0] == NULL)
     {
       bfd_release (abfd, i_shdrp);
@@ -4107,7 +4115,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,
 
   /* 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;
 
   if (new_syms == NULL)
     return FALSE;
@@ -4472,7 +4480,7 @@ _bfd_elf_make_dynamic_segment (bfd *abfd, asection *dynsec)
   struct elf_segment_map *m;
 
   m = (struct elf_segment_map *) bfd_zalloc (abfd,
   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;
   if (m == NULL)
     return NULL;
   m->next = NULL;
@@ -4563,6 +4571,7 @@ _bfd_elf_map_sections_to_segments (bfd *abfd, struct bfd_link_info *info)
       asection **hdrpp;
       bfd_boolean phdr_in_segment = TRUE;
       bfd_boolean writable;
       asection **hdrpp;
       bfd_boolean phdr_in_segment = TRUE;
       bfd_boolean writable;
+      bfd_boolean executable;
       int tls_count = 0;
       asection *first_tls = NULL;
       asection *first_mbind = NULL;
       int tls_count = 0;
       asection *first_tls = NULL;
       asection *first_mbind = NULL;
@@ -4574,7 +4583,7 @@ _bfd_elf_map_sections_to_segments (bfd *abfd, struct bfd_link_info *info)
       /* Select the allocated sections, and sort them.  */
 
       sections = (asection **) bfd_malloc2 (bfd_count_sections (abfd),
       /* 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;
 
       if (sections == NULL)
        goto error_return;
 
@@ -4651,6 +4660,7 @@ _bfd_elf_map_sections_to_segments (bfd *abfd, struct bfd_link_info *info)
       if (maxpagesize == 0)
        maxpagesize = 1;
       writable = FALSE;
       if (maxpagesize == 0)
        maxpagesize = 1;
       writable = FALSE;
+      executable = FALSE;
       dynsec = bfd_get_section_by_name (abfd, ".dynamic");
       if (dynsec != NULL
          && (dynsec->flags & SEC_LOAD) == 0)
       dynsec = bfd_get_section_by_name (abfd, ".dynamic");
       if (dynsec != NULL
          && (dynsec->flags & SEC_LOAD) == 0)
@@ -4717,33 +4727,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;
            }
                 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.  */
          /* 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
            {
              /* 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.
            {
              /* 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)
              new_segment = TRUE;
            }
          else if ((abfd->flags & D_PAGED) == 0)
@@ -4753,18 +4765,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;
            }
                 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
          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
            {
              /* 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
              new_segment = TRUE;
            }
          else
@@ -4786,6 +4797,8 @@ _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_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))
              last_hdr = hdr;
              /* .tbss sections effectively have zero size.  */
              if ((hdr->flags & (SEC_THREAD_LOCAL | SEC_LOAD))
@@ -4811,6 +4824,11 @@ _bfd_elf_map_sections_to_segments (bfd *abfd, struct bfd_link_info *info)
          else
            writable = FALSE;
 
          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_hdr = hdr;
          /* .tbss sections effectively have zero size.  */
          if ((hdr->flags & (SEC_THREAD_LOCAL | SEC_LOAD)) != SEC_THREAD_LOCAL)
@@ -5274,8 +5292,8 @@ assign_file_positions_for_load_sections (bfd *abfd,
              == 0);
   phdrs = (Elf_Internal_Phdr *)
      bfd_zalloc2 (abfd,
              == 0);
   phdrs = (Elf_Internal_Phdr *)
      bfd_zalloc2 (abfd,
-                  (elf_program_header_size (abfd) / bed->s->sizeof_phdr),
-                  sizeof (Elf_Internal_Phdr));
+                 (elf_program_header_size (abfd) / bed->s->sizeof_phdr),
+                 sizeof (Elf_Internal_Phdr));
   elf_tdata (abfd)->phdr = phdrs;
   if (phdrs == NULL)
     return FALSE;
   elf_tdata (abfd)->phdr = phdrs;
   if (phdrs == NULL)
     return FALSE;
@@ -5557,7 +5575,7 @@ assign_file_positions_for_load_sections (bfd *abfd,
                  if (p->p_filesz + adjust < p->p_memsz)
                    {
                      /* We have a PROGBITS section following NOBITS ones.
                  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
+                        Allocate file space for the NOBITS section(s) and
                         zero it.  */
                      adjust = p->p_memsz - p->p_filesz;
                      if (!write_zeros (abfd, off, adjust))
                         zero it.  */
                      adjust = p->p_memsz - p->p_filesz;
                      if (!write_zeros (abfd, off, adjust))
@@ -5843,52 +5861,77 @@ assign_file_positions_for_non_load_sections (bfd *abfd,
     {
       if (p->p_type == PT_GNU_RELRO)
        {
     {
       if (p->p_type == PT_GNU_RELRO)
        {
-         const Elf_Internal_Phdr *lp;
-         struct elf_segment_map *lm;
+         bfd_vma start, end;
 
          if (link_info != NULL)
            {
              /* During linking the range of the RELRO segment is passed
 
          if (link_info != NULL)
            {
              /* During linking the range of the RELRO segment is passed
-                in link_info.  */
+                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;
+           }
+         else if (m->count != 0)
+           {
+             if (!m->p_size_valid)
+               abort ();
+             start = m->sections[0]->vma;
+             end = start + m->p_size;
+           }
+         else
+           {
+             start = 0;
+             end = 0;
+           }
+
+         if (start < end)
+           {
+             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
              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
+                     && lp->p_memsz != 0
                      && lm->count != 0
                      && lm->count != 0
-                     && lm->sections[0]->vma >= link_info->relro_start)
+                     && lm->sections[lm->count - 1]->vma >= start
+                     && lm->sections[0]->vma < end)
                    break;
                }
                    break;
                }
-
              BFD_ASSERT (lm != NULL);
              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)
+
+             /* Find the section starting the RELRO segment.  */
+             for (i = 0; i < lm->count; i++)
                {
                {
-                 if (lp->p_type == PT_LOAD
-                     && lp->p_paddr == p->p_paddr)
+                 asection *s = lm->sections[i];
+                 if (s->vma >= start
+                     && s->vma < end
+                     && s->size != 0)
                    break;
                }
                    break;
                }
-           }
+             BFD_ASSERT (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;
 
 
-         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
              /* Preserve the alignment and flags if they are valid. The
-                gold linker generates RW/4 for the PT_GNU_RELRO section.
+                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.
               */
                 It is better for objcopy/strip to honor these attributes
                 otherwise gdb will choke when using separate debug files.
               */
@@ -6093,10 +6136,12 @@ assign_file_positions_except_relocs (bfd *abfd,
         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
         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.  */
+        changed or the programs updated.  */
       if (alloc > 1
          && tdata->phdr[0].p_type == PT_PHDR
       if (alloc > 1
          && tdata->phdr[0].p_type == PT_PHDR
-         && ! bed->elf_backend_allow_non_load_phdr (abfd, tdata->phdr, alloc)
+         && (bed->elf_backend_allow_non_load_phdr == NULL
+             || !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[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)
@@ -6336,7 +6381,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)
        = _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;
       if (i_shdrp[count]->contents)
        {
          bfd_size_type amt = i_shdrp[count]->sh_size;
@@ -6785,7 +6831,7 @@ 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
          /* 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.  */
             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.  */
@@ -7561,7 +7607,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)
               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;
            s = elf_next_in_group (s);
            if (s == first)
              break;
@@ -7571,18 +7626,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
            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->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;
              }
            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;
+                 }
              }
          }
       }
              }
          }
       }
@@ -7718,7 +7781,7 @@ swap_out_syms (bfd *abfd,
     }
 
   outbound_syms = (bfd_byte *) bfd_alloc2 (abfd, 1 + symcount,
     }
 
   outbound_syms = (bfd_byte *) bfd_alloc2 (abfd, 1 + symcount,
-                                           bed->s->sizeof_sym);
+                                          bed->s->sizeof_sym);
   if (outbound_syms == NULL)
     {
 error_return:
   if (outbound_syms == NULL)
     {
 error_return:
@@ -8268,8 +8331,8 @@ error_return_verref:
          else
            {
              iverneed->vn_auxptr = (struct elf_internal_vernaux *)
          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;
            }
              if (iverneed->vn_auxptr == NULL)
                goto error_return_verref;
            }
@@ -8432,8 +8495,8 @@ error_return_verref:
          else
            {
              iverdef->vd_auxptr = (struct elf_internal_verdaux *)
          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;
            }
              if (iverdef->vd_auxptr == NULL)
                goto error_return_verdef;
            }
@@ -8497,7 +8560,7 @@ error_return_verref:
        freeidx++;
 
       elf_tdata (abfd)->verdef = (Elf_Internal_Verdef *)
        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;
 
       if (elf_tdata (abfd)->verdef == NULL)
        goto error_return;
 
@@ -8590,7 +8653,7 @@ _bfd_elf_is_local_label_name (bfd *abfd ATTRIBUTE_UNUSED,
      forward-backward labels (aka local labels) as locals.
      These labels have the form:
 
      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)
 
 
        [.]?L[0123456789]+{^A|^B}[0123456789]*  (local labels)
 
@@ -9631,73 +9694,73 @@ elfcore_grok_note (bfd *abfd, Elf_Internal_Note *note)
 
     case NT_PPC_VSX:
       if (note->namesz == 6
 
     case NT_PPC_VSX:
       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_vsx (abfd, note);
       else
       else
-        return TRUE;
+       return TRUE;
 
     case NT_S390_HIGH_GPRS:
       if (note->namesz == 6
 
     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
       else
-        return TRUE;
+       return TRUE;
 
     case NT_S390_TIMER:
       if (note->namesz == 6
 
     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
       else
-        return TRUE;
+       return TRUE;
 
     case NT_S390_TODCMP:
       if (note->namesz == 6
 
     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
       else
-        return TRUE;
+       return TRUE;
 
     case NT_S390_TODPREG:
       if (note->namesz == 6
 
     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
       else
-        return TRUE;
+       return TRUE;
 
     case NT_S390_CTRS:
       if (note->namesz == 6
 
     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
       else
-        return TRUE;
+       return TRUE;
 
     case NT_S390_PREFIX:
       if (note->namesz == 6
 
     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
       else
-        return TRUE;
+       return TRUE;
 
     case NT_S390_LAST_BREAK:
       if (note->namesz == 6
 
     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
       else
-        return TRUE;
+       return TRUE;
 
     case NT_S390_SYSTEM_CALL:
       if (note->namesz == 6
 
     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
       else
-        return TRUE;
+       return TRUE;
 
     case NT_S390_TDB:
       if (note->namesz == 6
 
     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
       else
-        return TRUE;
+       return TRUE;
 
     case NT_S390_VXRS_LOW:
       if (note->namesz == 6
 
     case NT_S390_VXRS_LOW:
       if (note->namesz == 6
@@ -10011,6 +10074,18 @@ elfcore_grok_freebsd_note (bfd *abfd, Elf_Internal_Note *note)
       else
        return TRUE;
 
       else
        return TRUE;
 
+    case NT_FREEBSD_PROCSTAT_PROC:
+      return elfcore_make_note_pseudosection (abfd, ".note.freebsdcore.proc",
+                                             note);
+
+    case NT_FREEBSD_PROCSTAT_FILES:
+      return elfcore_make_note_pseudosection (abfd, ".note.freebsdcore.files",
+                                             note);
+
+    case NT_FREEBSD_PROCSTAT_VMMAP:
+      return elfcore_make_note_pseudosection (abfd, ".note.freebsdcore.vmmap",
+                                             note);
+
     case NT_FREEBSD_PROCSTAT_AUXV:
       {
        asection *sect = bfd_make_section_anyway_with_flags (abfd, ".auxv",
     case NT_FREEBSD_PROCSTAT_AUXV:
       {
        asection *sect = bfd_make_section_anyway_with_flags (abfd, ".auxv",
@@ -10258,8 +10333,8 @@ elfcore_grok_nto_status (bfd *abfd, Elf_Internal_Note *note, long *tid)
   if (sect == NULL)
     return FALSE;
 
   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));
   sect->alignment_power = 2;
 
   return (elfcore_maybe_make_sect (abfd, ".qnx_core_status", sect));
@@ -10287,8 +10362,8 @@ elfcore_grok_nto_regs (bfd *abfd,
   if (sect == NULL)
     return FALSE;
 
   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.  */
   sect->alignment_power = 2;
 
   /* This is the current thread.  */
@@ -10345,8 +10420,8 @@ elfcore_grok_spu_note (bfd *abfd, Elf_Internal_Note *note)
   if (sect == NULL)
     return FALSE;
 
   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;
   sect->alignment_power = 1;
 
   return TRUE;
@@ -10694,14 +10769,14 @@ elfcore_write_ppc_vmx (bfd *abfd,
 
 char *
 elfcore_write_ppc_vsx (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,
 {
   char *note_name = "LINUX";
   return elfcore_write_note (abfd, buf, bufsiz,
-                             note_name, NT_PPC_VSX, ppc_vsx, size);
+                            note_name, NT_PPC_VSX, ppc_vsx, size);
 }
 
 static char *
 }
 
 static char *
@@ -10713,68 +10788,68 @@ elfcore_write_s390_high_gprs (bfd *abfd,
 {
   char *note_name = "LINUX";
   return elfcore_write_note (abfd, buf, bufsiz,
 {
   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,
                             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,
 {
   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 *
 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,
 {
   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 *
 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,
 {
   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 *
 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,
 {
   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 *
 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,
 {
   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 *
 }
 
 char *
@@ -10786,7 +10861,7 @@ elfcore_write_s390_last_break (bfd *abfd,
 {
   char *note_name = "LINUX";
   return elfcore_write_note (abfd, buf, bufsiz,
 {
   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);
 }
 
                             s390_last_break, size);
 }
 
@@ -10799,7 +10874,7 @@ elfcore_write_s390_system_call (bfd *abfd,
 {
   char *note_name = "LINUX";
   return elfcore_write_note (abfd, buf, bufsiz,
 {
   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);
 }
 
                             s390_system_call, size);
 }
 
@@ -10812,7 +10887,7 @@ elfcore_write_s390_tdb (bfd *abfd,
 {
   char *note_name = "LINUX";
   return elfcore_write_note (abfd, buf, bufsiz,
 {
   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 *
 }
 
 char *
@@ -10970,14 +11045,23 @@ elfcore_write_register_note (bfd *abfd,
 }
 
 static bfd_boolean
 }
 
 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;
 
 {
   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)
     {
   p = buf;
   while (p < buf + size)
     {
-      /* FIXME: bad alignment assumption.  */
       Elf_External_Note *xnp = (Elf_External_Note *) p;
       Elf_Internal_Note in;
 
       Elf_External_Note *xnp = (Elf_External_Note *) p;
       Elf_Internal_Note in;
 
@@ -10992,7 +11076,7 @@ elf_parse_notes (bfd *abfd, char *buf, size_t size, file_ptr offset)
        return FALSE;
 
       in.descsz = H_GET_32 (abfd, xnp->descsz);
        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
       in.descpos = offset + (in.descdata - buf);
       if (in.descsz != 0
          && (in.descdata >= buf + size
@@ -11000,7 +11084,7 @@ elf_parse_notes (bfd *abfd, char *buf, size_t size, file_ptr offset)
        return FALSE;
 
       switch (bfd_get_format (abfd))
        return FALSE;
 
       switch (bfd_get_format (abfd))
-        {
+       {
        default:
          return TRUE;
 
        default:
          return TRUE;
 
@@ -11054,14 +11138,15 @@ elf_parse_notes (bfd *abfd, char *buf, size_t size, file_ptr offset)
          break;
        }
 
          break;
        }
 
-      p = in.descdata + BFD_ALIGN (in.descsz, 4);
+      p += ELF_NOTE_NEXT_OFFSET (in.namesz, in.descsz, align);
     }
 
   return TRUE;
 }
 
 static bfd_boolean
     }
 
   return TRUE;
 }
 
 static bfd_boolean
-elf_read_notes (bfd *abfd, file_ptr offset, bfd_size_type size)
+elf_read_notes (bfd *abfd, file_ptr offset, bfd_size_type size,
+               size_t align)
 {
   char *buf;
 
 {
   char *buf;
 
@@ -11080,7 +11165,7 @@ elf_read_notes (bfd *abfd, file_ptr offset, bfd_size_type size)
   buf[size] = 0;
 
   if (bfd_bread (buf, size, abfd) != 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;
     {
       free (buf);
       return FALSE;
This page took 0.063597 seconds and 4 git commands to generate.