Fix the linker so that it will not silently generate ELF binaries with invalid progra...
authorNick Clifton <nickc@redhat.com>
Wed, 23 Nov 2016 11:10:39 +0000 (11:10 +0000)
committerNick Clifton <nickc@redhat.com>
Wed, 23 Nov 2016 11:10:39 +0000 (11:10 +0000)
PR ld/20815
bfd * elf.c (elf_modify_segment_map): Allow empty LOAD segments if
they contain the program headers.
(_bfd_elf_map_sections_to_segments): If the linker created the
PHDR segment then always attempt to include it in a LOAD segment.
(assign_file_positions_for_non_load_sections): Allow LOAD segments
to overlap PHDR segments.
(phdr_sorter): New function.  Sorts program headers.
(assign_file_positions_except_relocs): Sort the program headers
before writing them out.  Issue an error if the PHDR segment is
not covered by a LOAD segment, unless the backend allows it.
* elf-bfd.h (struct elf_backend_data): Add
elf_backend_allow_non_load_phdr.
* elfxx-target.h (elf_backend_allow_non_load_phdr): Provide
default definition that returns FALSE.
(elfNN_bed): Initialise the elf_backend_allow_non_load_phdr
field.
* elf64-hppa.c (elf64_hppa_allow_non_load_phdr): New function.
Returns TRUE.
(elf_backend_allow_non_load_phdr): Define.
* elf-m10300.c (_bfd_mn10300_elf_size_dynamic_sections): Do not
place the interpreter string into the .interp section if the
nointerp flag is set in the link info structure.
* elf32-arc.c (elf_arc_size_dynamic_sections): Likewise.
* elf32-score7.c (score_elf_final_link_relocate): Allow for the
_gp symbol not being part of the output.

binutils* readelf.c (process_program_headers): Check PT_LOAD and PT_PHDR
segments for validity.

ld * ld.texinfo: Note that PT_TLS can be used as a segment type.
* testsuite/ld-discard/discard.ld: Add space for program headers.
* testsuite/ld-elf/flags1.ld: Likewise.
* testsuite/ld-elf/maxpage3.t: Likewise.
* testsuite/ld-elf/noload-1.t: Likewise.
* testsuite/ld-elf/orphan.ld: Likewise.
* testsuite/ld-elf/overlay.t: Likewise.
* testsuite/ld-elf/pr14052.t: Likewise.
* testsuite/ld-elf/pr19539.t: Likewise.
* testsuite/ld-elf/provide-hidden-1.ld: Likewise.
* testsuite/ld-elf/provide-hidden-s.ld: Likewise.
* testsuite/ld-elf/weak-dyn-1.ld: Likewise.
* testsuite/ld-i386/pr19539.t: Likewise.
* testsuite/ld-scripts/defined.t: Likewise.
* testsuite/ld-scripts/defined6.t: Likewise.
* testsuite/ld-scripts/dynamic-sections.t: Likewise.
* testsuite/ld-scripts/empty-aligned.t: Likewise.
* testsuite/ld-scripts/provide-2.t: Likewise.
* testsuite/ld-scripts/provide-4.t: Likewise.
* testsuite/ld-vax-elf/plt-local.ld: Likewise.
* testsuite/ld-x86-64/pr19539.t: Likewise.
* testsuite/ld-elf/ehdr_start-missing.d: Do not initialise the
dynamic linker.
* testsuite/ld-elf/ehdr_start-weak.d: Likewise.
* testsuite/ld-elf/elf.exp (pr14170, pr17068): Likewise.
* testsuite/ld-elf/loadaddr1.d: Update expected readelf output.
* testsuite/ld-elf/noload-2.d: Likewise.
* testsuite/ld-powerpc/vxworks2.sd: Likewise.
* testsuite/ld-scripts/phdrs3a.d: Likewise.
* testsuite/ld-scripts/size-2.d: Likewise.
* testsuite/ld-elf/group.ld: Add program headers.
* testsuite/ld-elf/overlay.d: Skip for SPU.
* testsuite/ld-elf/flags1.d: Skip for RX.
* testsuite/ld-elf/pr19162.d: Skip for HPPA64.
* testsuite/ld-elf/pr19539.d: Skip for ALPHA.
* testsuite/ld-scripts/empty-orphan.t: Update program headers.
* testsuite/ld-scripts/size-2.t: Likewise.

48 files changed:
bfd/ChangeLog
bfd/elf-bfd.h
bfd/elf-m10300.c
bfd/elf.c
bfd/elf32-arc.c
bfd/elf32-score7.c
bfd/elf64-hppa.c
bfd/elfcode.h
bfd/elfxx-target.h
binutils/ChangeLog
binutils/readelf.c
ld/ChangeLog
ld/ld.texinfo
ld/testsuite/ld-discard/discard.ld
ld/testsuite/ld-elf/ehdr_start-missing.d
ld/testsuite/ld-elf/ehdr_start-weak.d
ld/testsuite/ld-elf/elf.exp
ld/testsuite/ld-elf/flags1.d
ld/testsuite/ld-elf/flags1.ld
ld/testsuite/ld-elf/group.ld
ld/testsuite/ld-elf/loadaddr1.d
ld/testsuite/ld-elf/maxpage3.t
ld/testsuite/ld-elf/noload-1.t
ld/testsuite/ld-elf/noload-2.d
ld/testsuite/ld-elf/orphan.ld
ld/testsuite/ld-elf/overlay.d
ld/testsuite/ld-elf/overlay.t
ld/testsuite/ld-elf/pr14052.t
ld/testsuite/ld-elf/pr19162.d
ld/testsuite/ld-elf/pr19539.d
ld/testsuite/ld-elf/pr19539.t
ld/testsuite/ld-elf/provide-hidden-1.ld
ld/testsuite/ld-elf/provide-hidden-s.ld
ld/testsuite/ld-elf/weak-dyn-1.ld
ld/testsuite/ld-i386/pr19539.t
ld/testsuite/ld-powerpc/vxworks2.sd
ld/testsuite/ld-scripts/defined.t
ld/testsuite/ld-scripts/defined6.t
ld/testsuite/ld-scripts/dynamic-sections.t
ld/testsuite/ld-scripts/empty-aligned.t
ld/testsuite/ld-scripts/empty-orphan.t
ld/testsuite/ld-scripts/phdrs3a.d
ld/testsuite/ld-scripts/provide-2.t
ld/testsuite/ld-scripts/provide-4.t
ld/testsuite/ld-scripts/size-2.d
ld/testsuite/ld-scripts/size-2.t
ld/testsuite/ld-vax-elf/plt-local.ld
ld/testsuite/ld-x86-64/pr19539.t

index 19a1026..346ff29 100644 (file)
@@ -1,3 +1,32 @@
+2016-11-23  Nick Clifton  <nickc@redhat.com>
+
+       PR ld/20815
+       * elf.c (elf_modify_segment_map): Allow empty LOAD segments if
+       they contain the program headers.
+       (_bfd_elf_map_sections_to_segments): If the linker created the
+       PHDR segment then always attempt to include it in a LOAD segment.
+       (assign_file_positions_for_non_load_sections): Allow LOAD segments
+       to overlap PHDR segments.
+       (phdr_sorter): New function.  Sorts program headers.
+       (assign_file_positions_except_relocs): Sort the program headers
+       before writing them out.  Issue an error if the PHDR segment is
+       not covered by a LOAD segment, unless the backend allows it.
+       * elf-bfd.h (struct elf_backend_data): Add
+       elf_backend_allow_non_load_phdr.
+       * elfxx-target.h (elf_backend_allow_non_load_phdr): Provide
+       default definition that returns FALSE.
+       (elfNN_bed): Initialise the elf_backend_allow_non_load_phdr
+       field.
+       * elf64-hppa.c (elf64_hppa_allow_non_load_phdr): New function.
+       Returns TRUE.
+       (elf_backend_allow_non_load_phdr): Define.
+       * elf-m10300.c (_bfd_mn10300_elf_size_dynamic_sections): Do not
+       place the interpreter string into the .interp section if the
+       nointerp flag is set in the link info structure.
+       * elf32-arc.c (elf_arc_size_dynamic_sections): Likewise.
+       * elf32-score7.c (score_elf_final_link_relocate): Allow for the
+       _gp symbol not being part of the output.
+
 2016-11-23  Alan Modra  <amodra@gmail.com>
 
        * elf-bfd.h (struct elf_backend_data): Add dtrel_excludes_plt.
index 7c78899..06bd800 100644 (file)
@@ -1077,6 +1077,11 @@ struct elf_backend_data
   bfd_boolean (*elf_backend_modify_program_headers)
     (bfd *, struct bfd_link_info *);
 
+  /* This function is called to see if the PHDR header should be
+     checked for validity.  */
+  bfd_boolean (*elf_backend_allow_non_load_phdr)
+    (bfd *,  const Elf_Internal_Phdr *, unsigned);
+
   /* This function is called before section garbage collection to
      mark entry symbol sections.  */
   void (*gc_keep)
index 1ea5c27..4a8a297 100644 (file)
@@ -5035,7 +5035,7 @@ _bfd_mn10300_elf_size_dynamic_sections (bfd * output_bfd,
   if (elf_hash_table (info)->dynamic_sections_created)
     {
       /* Set the contents of the .interp section to the interpreter.  */
-      if (bfd_link_executable (info))
+      if (bfd_link_executable (info) && !info->nointerp)
        {
          s = bfd_get_linker_section (dynobj, ".interp");
          BFD_ASSERT (s != NULL);
index e7252c6..936255e 100644 (file)
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -4254,7 +4254,7 @@ get_program_header_size (bfd *abfd, struct bfd_link_info *info)
         PT_INTERP segment.  In this case, assume we also need a
         PT_PHDR segment, although that may not be true for all
         targets.  */
-      segs += 2;
+      segs += 3;
     }
 
   if (bfd_get_section_by_name (abfd, ".dynamic") != NULL)
@@ -4438,7 +4438,10 @@ elf_modify_segment_map (bfd *abfd,
        }
       (*m)->count = new_count;
 
-      if (remove_empty_load && (*m)->p_type == PT_LOAD && (*m)->count == 0)
+      if (remove_empty_load
+         && (*m)->p_type == PT_LOAD
+         && (*m)->count == 0
+         && !(*m)->includes_phdrs)
        *m = (*m)->next;
       else
        m = &(*m)->next;
@@ -4488,6 +4491,7 @@ _bfd_elf_map_sections_to_segments (bfd *abfd, struct bfd_link_info *info)
       asection *dynsec, *eh_frame_hdr;
       bfd_size_type amt;
       bfd_vma addr_mask, wrap_to = 0;
+      bfd_boolean linker_created_pt_phdr_segment = FALSE;
 
       /* Select the allocated sections, and sort them.  */
 
@@ -4540,7 +4544,7 @@ _bfd_elf_map_sections_to_segments (bfd *abfd, struct bfd_link_info *info)
          m->p_flags = PF_R | PF_X;
          m->p_flags_valid = 1;
          m->includes_phdrs = 1;
-
+         linker_created_pt_phdr_segment = TRUE;
          *pm = m;
          pm = &m->next;
 
@@ -4591,7 +4595,19 @@ _bfd_elf_map_sections_to_segments (bfd *abfd, struct bfd_link_info *info)
              || ((sections[0]->lma & addr_mask) % maxpagesize
                  < phdr_size % maxpagesize)
              || (sections[0]->lma & addr_mask & -maxpagesize) < wrap_to)
-           phdr_in_segment = FALSE;
+           {
+             /* 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;
+           }
        }
 
       for (i = 0, hdrpp = sections; i < count; i++, hdrpp++)
@@ -5773,16 +5789,25 @@ assign_file_positions_for_non_load_sections (bfd *abfd,
       else if (m->count != 0)
        {
          unsigned int i;
+
          if (p->p_type != PT_LOAD
              && (p->p_type != PT_NOTE
                  || bfd_get_format (abfd) != bfd_core))
            {
+             /* A user specified segment layout may include a PHDR
+                segment that overlaps with a LOAD segment...  */
+             if (p->p_type == PT_PHDR)
+               {
+                 m->count = 0;
+                 continue;
+               }
+
              if (m->includes_filehdr || m->includes_phdrs)
                {
                  /* PR 17512: file: 2195325e.  */
                  _bfd_error_handler
-                   (_("%B: warning: non-load segment includes file header and/or program header"),
-                    abfd);
+                   (_("%B: error: non-load segment %d includes file header and/or program header"),
+                    abfd, (int)(p - phdrs));
                  return FALSE;
                }
 
@@ -5829,6 +5854,52 @@ find_section_in_list (unsigned int i, elf_section_list * list)
   return list;
 }
 
+/* Compare function used when sorting the program header table.
+   The ELF standard requires that a PT_PHDR segment, if present,
+   must appear before any PT_LOAD segments.  It also requires
+   that all PT_LOAD segments are sorted into order of increasing
+   p_vaddr.  */
+
+static signed int
+phdr_sorter (const void * a, const void * b)
+{
+  Elf_Internal_Phdr * ahdr = (Elf_Internal_Phdr *) a;
+  Elf_Internal_Phdr * bhdr = (Elf_Internal_Phdr *) b;
+
+  switch (ahdr->p_type)
+    {
+    case PT_LOAD:
+      switch (bhdr->p_type)
+       {
+       case PT_PHDR:
+         return 1;
+       case PT_LOAD:
+         if (ahdr->p_vaddr < bhdr->p_vaddr)
+           return -1;
+         if (ahdr->p_vaddr > bhdr->p_vaddr)
+           return 1;
+         return 0;
+       default:
+         return 0;
+       }
+      break;
+    case PT_PHDR:
+      switch (bhdr->p_type)
+       {
+       case PT_PHDR:
+         _bfd_error_handler (_("error: multiple PHDR segments detecetd"));
+         return 0;
+       case PT_LOAD:
+         return -1;
+       default:
+         return 0;
+       }
+      break;
+    default:
+      return 0;
+    }
+}
+
 /* Work out the file positions of all the sections.  This is called by
    _bfd_elf_compute_section_file_positions.  All the section sizes and
    VMAs must be known before this is called.
@@ -5892,6 +5963,7 @@ assign_file_positions_except_relocs (bfd *abfd,
     }
   else
     {
+      Elf_Internal_Phdr * map;
       unsigned int alloc;
 
       /* Assign file positions for the loaded sections based on the
@@ -5930,9 +6002,46 @@ assign_file_positions_except_relocs (bfd *abfd,
 
       /* 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;
+
+      map = (Elf_Internal_Phdr *) xmalloc (alloc * sizeof (* tdata->phdr));
+      memcpy (map, tdata->phdr, alloc * sizeof (* tdata->phdr));
+      qsort (map, alloc, sizeof (* tdata->phdr), phdr_sorter);
+         
+      /* 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.  */
+      if (alloc > 1
+         && map[0].p_type == PT_PHDR
+         && ! bed->elf_backend_allow_non_load_phdr (abfd, map, alloc)
+         && map[1].p_type == PT_LOAD
+         && (map[1].p_vaddr > map[0].p_vaddr
+             || (map[1].p_vaddr + map[1].p_memsz) < (map[0].p_vaddr + map[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);
+         free (map);
+         return FALSE;
+       }
+
       if (bfd_seek (abfd, (bfd_signed_vma) bed->s->sizeof_ehdr, SEEK_SET) != 0
-         || bed->s->write_out_phdrs (abfd, tdata->phdr, alloc) != 0)
-       return FALSE;
+         || bed->s->write_out_phdrs (abfd, map, alloc) != 0)
+       {
+         free (map);
+         return FALSE;
+       }
+
+      free (map);
     }
 
   return TRUE;
index 3d39c3a..9ef5368 100644 (file)
@@ -2363,7 +2363,7 @@ elf_arc_size_dynamic_sections (bfd * output_bfd,
 
       /* Set the contents of the .interp section to the
         interpreter.  */
-      if (!bfd_link_pic (info))
+      if (!bfd_link_pic (info) && !info->nointerp)
        {
          s = bfd_get_section_by_name (dynobj, ".interp");
          BFD_ASSERT (s != NULL);
index 79d6768..3813184 100644 (file)
@@ -1852,9 +1852,12 @@ score_elf_final_link_relocate (reloc_howto_type *howto,
 
       bh = bfd_link_hash_lookup (info->hash, "_gp", 0, 0, 1);
       if (bh != NULL && bh->type == bfd_link_hash_defined)
-        elf_gp (output_bfd) = (bh->u.def.value
-                               + bh->u.def.section->output_section->vma
-                               + bh->u.def.section->output_offset);
+       {
+         elf_gp (output_bfd) = (bh->u.def.value
+                                + bh->u.def.section->output_offset);
+         if (bh->u.def.section->output_section)
+           elf_gp (output_bfd) += bh->u.def.section->output_section->vma;
+       }
       else if (bfd_link_relocatable (info))
         {
           bfd_vma lo = -1;
index a9e8d0c..0e19f0a 100644 (file)
@@ -2666,6 +2666,14 @@ elf64_hppa_additional_program_headers (bfd *abfd,
   return 0;
 }
 
+static bfd_boolean
+elf64_hppa_allow_non_load_phdr (bfd *abfd ATTRIBUTE_UNUSED,
+                               const Elf_Internal_Phdr *phdr ATTRIBUTE_UNUSED,
+                               unsigned int count ATTRIBUTE_UNUSED)
+{
+  return TRUE;
+}
+
 /* Allocate and initialize any program headers required by this
    specific backend.
 
@@ -2692,6 +2700,7 @@ elf64_hppa_modify_segment_map (bfd *abfd,
       for (m = elf_seg_map (abfd); m != NULL; m = m->next)
        if (m->p_type == PT_PHDR)
          break;
+
       if (m == NULL)
        {
          m = ((struct elf_segment_map *)
@@ -4084,6 +4093,9 @@ const struct elf_size_info hppa64_elf_size_info =
 #define elf_backend_modify_segment_map \
        elf64_hppa_modify_segment_map
 
+#define elf_backend_allow_non_load_phdr \
+       elf64_hppa_allow_non_load_phdr
+
 #define elf_backend_link_output_symbol_hook \
        elf64_hppa_link_output_symbol_hook
 
index eb3a1ff..c7e0e46 100644 (file)
@@ -756,7 +756,8 @@ elf_object_p (bfd *abfd)
             So we are kind, and reset the string index value to 0
             so that at least some processing can be done.  */
          i_ehdrp->e_shstrndx = SHN_UNDEF;
-         _bfd_error_handler (_("warning: %s has a corrupt string table index - ignoring"), abfd->filename);
+         _bfd_error_handler (_("warning: %s has a corrupt string table index - ignoring"),
+                             abfd->filename);
        }
     }
   else if (i_ehdrp->e_shstrndx != SHN_UNDEF)
@@ -973,6 +974,7 @@ elf_write_out_phdrs (bfd *abfd,
   while (count--)
     {
       Elf_External_Phdr extphdr;
+
       elf_swap_phdr_out (abfd, phdr, &extphdr);
       if (bfd_bwrite (&extphdr, sizeof (Elf_External_Phdr), abfd)
          != sizeof (Elf_External_Phdr))
index 5ff39dd..aff8621 100644 (file)
 #ifndef elf_backend_modify_program_headers
 #define elf_backend_modify_program_headers     0
 #endif
+#ifndef elf_backend_allow_non_load_phdr
+#define elf_backend_allow_non_load_phdr        \
+  ((bfd_boolean (*) (bfd *, const Elf_Internal_Phdr *, unsigned)) bfd_false)
+#endif
 #ifndef elf_backend_ecoff_debug_swap
 #define elf_backend_ecoff_debug_swap   0
 #endif
@@ -765,6 +769,7 @@ static struct elf_backend_data elfNN_bed =
   elf_backend_additional_program_headers,
   elf_backend_modify_segment_map,
   elf_backend_modify_program_headers,
+  elf_backend_allow_non_load_phdr,
   elf_backend_gc_keep,
   elf_backend_gc_mark_dynamic_ref,
   elf_backend_gc_mark_hook,
index 0f3d167..f625a26 100644 (file)
@@ -1,3 +1,9 @@
+2016-11-23  Nick Clifton  <nickc@redhat.com>
+
+       PR ld/20815
+       * readelf.c (process_program_headers): Check PT_LOAD and PT_PHDR
+       segments for validity.
+
 2016-11-22  Ambrogino Modigliani  <ambrogino.modigliani@gmail.com>
 
         * configure: Regenerate.
index e782e95..ee55852 100644 (file)
@@ -3797,7 +3797,7 @@ get_segment_type (unsigned long p_type)
          if (result != NULL)
            return result;
 
-         sprintf (buff, "LOPROC+%lx", p_type - PT_LOPROC);
+         sprintf (buff, "LOPROC+%#lx", p_type - PT_LOPROC);
        }
       else if ((p_type >= PT_LOOS) && (p_type <= PT_HIOS))
        {
@@ -3822,7 +3822,7 @@ get_segment_type (unsigned long p_type)
          if (result != NULL)
            return result;
 
-         sprintf (buff, "LOOS+%lx", p_type - PT_LOOS);
+         sprintf (buff, "LOOS+%#lx", p_type - PT_LOOS);
        }
       else
        snprintf (buff, sizeof (buff), _("<unknown>: %lx"), p_type);
@@ -4770,6 +4770,7 @@ process_program_headers (FILE * file)
 {
   Elf_Internal_Phdr * segment;
   unsigned int i;
+  Elf_Internal_Phdr * previous_load = NULL;
 
   if (elf_header.e_phnum == 0)
     {
@@ -4901,13 +4902,39 @@ process_program_headers (FILE * file)
                      (segment->p_flags & PF_X ? 'E' : ' '));
              print_vma (segment->p_align, HEX);
            }
-       }
 
-      if (do_segments)
-       putc ('\n', stdout);
+         putc ('\n', stdout);
+       }
 
       switch (segment->p_type)
        {
+       case PT_LOAD:
+         if (previous_load
+             && previous_load->p_vaddr > segment->p_vaddr)
+           error (_("LOAD segments must be sorted in order of increasing VirtAddr\n"));
+         if (segment->p_memsz < segment->p_filesz)
+           error (_("the segment's file size is larger than its memory size\n"));
+         previous_load = segment;
+         break;
+
+       case PT_PHDR:
+         /* PR 20815 - Verify that the program header is loaded into memory.  */
+         if (i > 0 && previous_load != NULL)
+           error (_("the PHDR segment must occur before any LOAD segment\n"));
+         if (elf_header.e_machine != EM_PARISC)
+           {
+             unsigned int j;
+
+             for (j = 1; j < elf_header.e_phnum; j++)
+               if (program_headers[j].p_vaddr <= segment->p_vaddr
+                   && (program_headers[j].p_vaddr + program_headers[j].p_memsz)
+                   >= (segment->p_vaddr + segment->p_filesz))
+                 break;
+             if (j == elf_header.e_phnum)
+               error (_("the PHDR segment is not covered by a LOAD segment\n"));
+           }
+         break;
+
        case PT_DYNAMIC:
          if (dynamic_addr)
            error (_("more than one dynamic segment\n"));
@@ -6068,7 +6095,9 @@ process_section_headers (FILE * file)
          if (section->sh_type == SHT_NOBITS)
            /* NOBITS section headers with non-zero sh_info fields can be
               created when a binary is stripped of everything but its debug
-              information.  The stripped sections have their headers preserved but their types set to SHT_NOBITS.  so do not check this type of section.  */
+              information.  The stripped sections have their headers
+              preserved but their types set to SHT_NOBITS.  So do not check
+              this type of section.  */
            ;
          else if (section->sh_flags & SHF_INFO_LINK)
            {
index 1f4814d..8d28692 100644 (file)
@@ -1,3 +1,44 @@
+2016-11-23  Nick Clifton  <nickc@redhat.com>
+
+       PR ld/20815
+       * ld.texinfo: Note that PT_TLS can be used as a segment type.
+       * testsuite/ld-discard/discard.ld: Add space for program headers.
+       * testsuite/ld-elf/flags1.ld: Likewise.
+       * testsuite/ld-elf/maxpage3.t: Likewise.
+       * testsuite/ld-elf/noload-1.t: Likewise.
+       * testsuite/ld-elf/orphan.ld: Likewise.
+       * testsuite/ld-elf/overlay.t: Likewise.
+       * testsuite/ld-elf/pr14052.t: Likewise.
+       * testsuite/ld-elf/pr19539.t: Likewise.
+       * testsuite/ld-elf/provide-hidden-1.ld: Likewise.
+       * testsuite/ld-elf/provide-hidden-s.ld: Likewise.
+       * testsuite/ld-elf/weak-dyn-1.ld: Likewise.
+       * testsuite/ld-i386/pr19539.t: Likewise.
+       * testsuite/ld-scripts/defined.t: Likewise.
+       * testsuite/ld-scripts/defined6.t: Likewise.
+       * testsuite/ld-scripts/dynamic-sections.t: Likewise.
+       * testsuite/ld-scripts/empty-aligned.t: Likewise.
+       * testsuite/ld-scripts/provide-2.t: Likewise.
+       * testsuite/ld-scripts/provide-4.t: Likewise.
+       * testsuite/ld-vax-elf/plt-local.ld: Likewise.
+       * testsuite/ld-x86-64/pr19539.t: Likewise.
+       * testsuite/ld-elf/ehdr_start-missing.d: Do not initialise the
+       dynamic linker.
+       * testsuite/ld-elf/ehdr_start-weak.d: Likewise.
+       * testsuite/ld-elf/elf.exp (pr14170, pr17068): Likewise.
+       * testsuite/ld-elf/loadaddr1.d: Update expected readelf output.
+       * testsuite/ld-elf/noload-2.d: Likewise.
+       * testsuite/ld-powerpc/vxworks2.sd: Likewise.
+       * testsuite/ld-scripts/phdrs3a.d: Likewise.
+       * testsuite/ld-scripts/size-2.d: Likewise.
+       * testsuite/ld-elf/group.ld: Add program headers.
+       * testsuite/ld-elf/overlay.d: Skip for SPU.
+       * testsuite/ld-elf/flags1.d: Skip for RX.
+       * testsuite/ld-elf/pr19162.d: Skip for HPPA64.
+       * testsuite/ld-elf/pr19539.d: Skip for ALPHA.
+       * testsuite/ld-scripts/empty-orphan.t: Update program headers.
+       * testsuite/ld-scripts/size-2.t: Likewise.
+
 2016-11-22  Ambrogino Modigliani  <ambrogino.modigliani@gmail.com>
 
         * configure: Regenerate.
index d4f33b7..ec7ff1b 100644 (file)
@@ -5359,6 +5359,9 @@ ABI.
 @item @code{PT_PHDR} (6)
 Indicates a segment where the program headers may be found.
 
+@item @code{PT_TLS} (7)
+Indicates a segment containing thread local storage.
+
 @item @var{expression}
 An expression giving the numeric type of the program header.  This may
 be used for types not defined above.
index a7ff4a5..64f3350 100644 (file)
@@ -1,6 +1,7 @@
 ENTRY(_start)
 SECTIONS
 {
+  . = SIZEOF_HEADERS;
   /* Sections to be discarded */
   /DISCARD/ : {
        *(.data.exit)
index 5c2090f..046e39a 100644 (file)
@@ -1,4 +1,4 @@
 #source: ehdr_start-strongref.s
-#ld: -e _start -T ehdr_start-missing.t
+#ld: -e _start -T ehdr_start-missing.t --no-dynamic-linker
 #error: .*: undefined reference to `__ehdr_start'
 #target: *-*-linux* *-*-gnu* *-*-nacl*
index 5644d05..d3d5af7 100644 (file)
@@ -1,5 +1,5 @@
 #source: ehdr_start.s
-#ld: -e _start -T ehdr_start-missing.t
+#ld: -e _start -T ehdr_start-missing.t --no-dynamic-linker
 #nm: -n
 #target: *-*-linux* *-*-gnu* *-*-nacl*
 #xfail: frv-*-*
index 59284bd..f93ad46 100644 (file)
@@ -75,7 +75,7 @@ if { ![istarget hppa64*-hpux*] } {
        setup_xfail "bfin-*-*"
        run_ld_link_tests {
            {"PR ld/14170"
-               "tmpdir/pr14170a.o tmpdir/pr14170.so" "" "" "pr14170c.s"
+               "--no-dynamic-linker tmpdir/pr14170a.o tmpdir/pr14170.so" "" "" "pr14170c.s"
                { } "pr14170" }
        }
     }
@@ -112,7 +112,7 @@ if { [check_shared_lib_support] } then {
     setup_xfail "bfin-*-*"
     run_ld_link_tests {
        {"pr17068 link --as-needed lib in group"
-           "--as-needed" "--start-group tmpdir/pr17068a.a tmpdir/pr17068.so tmpdir/pr17068b.a --end-group" ""
+           "--as-needed --no-dynamic-linker" "--start-group tmpdir/pr17068a.a tmpdir/pr17068.so tmpdir/pr17068b.a --end-group" ""
            {start.s pr17068.s} {} "pr17068"}
     }
     # xfail on tic6x due to non-PIC/non-PID warnings
index 6cd8b3f..aadf936 100644 (file)
@@ -2,6 +2,7 @@
 #ld: -Tflags1.ld
 #objcopy_linked_file: --set-section-flags .post_text_reserve=contents,alloc,load,readonly,code
 #readelf: -S --wide
+#notarget: rx-*-*
 
 #...
 Section Headers:
index a94cbe8..c003ce7 100644 (file)
@@ -1,5 +1,6 @@
 SECTIONS
 {
+  . = SIZEOF_HEADERS;
   .text :
   {
     *(.text)
index f8e50c3..53e2790 100644 (file)
@@ -1,6 +1,12 @@
+PHDRS
+{
+  header PT_PHDR PHDRS ;
+  image  PT_LOAD PHDRS;
+}
+
 SECTIONS
 {
   . = 0x1000;
-  .text : { *(.text) *(.rodata.brlt) }
+  .text : { *(.text) *(.rodata.brlt) } :image :header
   /DISCARD/ : { *(.dropme) *(.reginfo) *(.MIPS.abiflags) }
 }
index 0fd96a7..0aa372c 100644 (file)
@@ -5,6 +5,6 @@
 
 #...
   LOAD +0x000000 0xf*80000000 0xf*80000000 0x100050 0x100050 RWE 0x200000
-  LOAD +0x200000 0xf*ff600000 0xf*80101000 0x0*10 0x0*10 R E 0x200000
   LOAD +0x302000 0xf*80102000 0xf*80102000 0x0*10 0x0*10 RW  0x200000
+  LOAD +0x200000 0xf*ff600000 0xf*80101000 0x0*10 0x0*10 R E 0x200000
 #pass
index 556dcd5..f5ada18 100644 (file)
@@ -1,5 +1,6 @@
 SECTIONS
 {
+  . = SIZEOF_HEADERS;
   .text : {*(.text)}
   . = ALIGN(CONSTANT (MAXPAGESIZE));
   .data : {*(.data)}
index 1efd06c..768cd42 100644 (file)
@@ -1,5 +1,6 @@
 SECTIONS
 {
+  . = SIZEOF_HEADERS;
   TEST (NOLOAD) :
   {
     *(TEST)
index 0e25d9b..c9668a0 100644 (file)
@@ -4,5 +4,5 @@
 #target: *-*-linux* *-*-gnu*
 
 #...
- +LOAD +0x200000 +0x0+ +0x0+ +0x0+ +0x0+1 +RW +0x200000
+ +LOAD +0x.00000 +0x0+ +0x0+ +0x0+.. +0x0+.. +RW +0x200000
 #pass
index 1ae908b..8b5015e 100644 (file)
@@ -1,5 +1,6 @@
 SECTIONS
 {
+  . = SIZEOF_HEADERS;
   .text : { *(.text) }
   .data : { *(.data) }
   .bss : { *(.bss) *(COMMON) }
index 00d25d5..c4409ae 100644 (file)
@@ -1,5 +1,7 @@
 # ld: -T overlay.t -u __load_start_text1 -u __load_start_text2 -u __load_stop_text1 -u __load_stop_text2
 #readelf: -s
+#notarget: spu-*-*
+# The SPU adds its own LOAD segments, out of order, at the start of the program header table.
 
 #...
 [      ]+[0-9]+:[      ]+0*4000[       ]+0[    ]+NOTYPE[       ]+GLOBAL[       ]+DEFAULT[      ]+ABS __load_start_text1
index bdb33c8..dd374bb 100644 (file)
@@ -1,10 +1,11 @@
 SECTIONS
 {
+  . = SIZEOF_HEADERS;
   .text : { *(.text) }
   OVERLAY 0x1000 : AT (0x4000)
   {
     .text1 {*(.text1)}
     .text2 {*(.text2)}
-  }
+  } 
   /DISCARD/ : { *(.*) }
 }
index 360c231..84fffbd 100644 (file)
@@ -1,4 +1,5 @@
 SECTIONS {
+       . = SIZEOF_HEADERS;
        .text : {
                *(.text)
        }
index 1a54546..4d706ff 100644 (file)
@@ -3,7 +3,7 @@
 #ld: -shared -z max-page-size=0x200000
 #readelf: -l --wide
 #target: *-*-linux* *-*-gnu* *-*-nacl*
-#notarget: arc*-*-* hppa-*-*
+#notarget: arc*-*-* hppa*-*-*
 # arc target has an extra 64K stack section.
 # hppa fails due to PR 12376.
 
index 87c2b1b..e7d8298 100644 (file)
@@ -3,7 +3,7 @@
 #ld: -pie -T pr19539.t
 #readelf : --dyn-syms --wide
 #target: *-*-linux* *-*-gnu* *-*-solaris*
-#notarget: cris*-*-*
+#notarget: cris*-*-* alpha-*-*
 
 Symbol table '\.dynsym' contains [0-9]+ entries:
 #pass
index b6b48e7..82ef917 100644 (file)
@@ -1 +1,6 @@
 HIDDEN (foo = .);
+
+SECTIONS
+{
+  . = SIZEOF_HEADERS;
+}
index 47cdbb7..479862d 100644 (file)
@@ -1,5 +1,6 @@
 SECTIONS
 {
+  . = SIZEOF_HEADERS;
   . = 0x12300000;
   .data :
     {
index cca804f..fc5761a 100644 (file)
@@ -1,5 +1,6 @@
 SECTIONS
 {
+  . = SIZEOF_HEADERS;
   . = 0x12300000;
   .data : { *(.data) }
   .got : { *(.got) }
index 495b712..25a510c 100644 (file)
@@ -1,5 +1,6 @@
 SECTIONS
 {
+  . = SIZEOF_HEADERS;
   . = 0x800000;
   PROVIDE (bar = .);
   .data : {
index b6b48e7..82ef917 100644 (file)
@@ -1 +1,6 @@
 HIDDEN (foo = .);
+
+SECTIONS
+{
+  . = SIZEOF_HEADERS;
+}
index 0876568..2294cb6 100644 (file)
@@ -6,7 +6,7 @@ Program Headers:
   Type .*
   PHDR .*
 #...
-  LOAD .* 0x00080000 0x00080000 .* R E 0x10000
+  LOAD .* 0x00070000 0x00070000 .* R E 0x10000
   LOAD .* 0x00090000 0x00090000 .* RW  0x10000
   DYNAMIC .*
 
index c1ef1b6..e4e105f 100644 (file)
@@ -1,4 +1,5 @@
 SECTIONS {
+       . = SIZEOF_HEADERS;
        .text : { *(.text) }
        .data : { *(.data) }
        .bss : { *(.bss) *(COMMON) }
index f4ca38a..9713aac 100644 (file)
@@ -1,5 +1,6 @@
 SECTIONS
 {
+  . = SIZEOF_HEADERS;
   .text : { *(.text) }
   .data : { *(.data) }
   .bss  : { *(.bss) *(COMMON) }
index f1f24c8..64cf47d 100644 (file)
@@ -1,5 +1,6 @@
 SECTIONS
 {
+  . = SIZEOF_HEADERS;
   .data : { *(.data) }
   .rodata : { *(.rodata) }
 
index 5f6a38d..0073f13 100644 (file)
@@ -1,5 +1,6 @@
 SECTIONS
 {
+  . = SIZEOF_HEADERS;
   .text : { *(.text) }
   /* Alignment at beginning shouldn't result in empty section being kept.  */
   .text1 ALIGN (4096) :
index b57e164..c0dc628 100644 (file)
@@ -7,14 +7,14 @@ MEMORY
 
 PHDRS
 {
-  default_phdr PT_LOAD;
-  text_phdr PT_LOAD;
+  headers PT_PHDR PHDRS;
+  text_phdr PT_LOAD PHDRS;
   data_phdr PT_LOAD;
 }
 
 SECTIONS
 {
-   .text : { *(.text) } > text_mem : text_phdr
+   .text : { *(.text) } > text_mem : text_phdr :headers
    .data : { *(.data) } > data_mem : data_phdr
    .bss : { *(.bss) } > data_mem : data_phdr
    /DISCARD/ : { *(.reginfo) *(.glue*) }
index 80bde71..d96bd13 100644 (file)
@@ -4,6 +4,6 @@
 #readelf: -l --wide
 
 #...
-[ \t]+LOAD[ x0-9a-f]+ R [ x0-9a-f]+
 [ \t]+LOAD[ x0-9a-f]+ E [ x0-9a-f]+
+[ \t]+LOAD[ x0-9a-f]+ R [ x0-9a-f]+
 #pass
index fe30dd8..abf6eb3 100644 (file)
@@ -1,5 +1,6 @@
 SECTIONS 
 {
+  . = SIZEOF_HEADERS;
   PROVIDE (foo = 1);
   PROVIDE (bar = 2);
   PROVIDE (baz = 3);
index 424c238..da663db 100644 (file)
@@ -1,5 +1,6 @@
 SECTIONS
 {
+  . = SIZEOF_HEADERS;
   PROVIDE (foo = 1);
   PROVIDE (bar = 2);
   PROVIDE (baz = 3);
index c925673..d76745e 100644 (file)
@@ -6,9 +6,9 @@
 #...
 Program Headers:
  +Type +Offset +VirtAddr +PhysAddr +FileSiz +MemSiz +Flg +Align
- +PHDR +0x[0-9a-f]+ 0x0+0000 0x0+0000 0x[0-9a-f]+ 0x[0-9a-f]+ R +0x[0-9a-f]+
+ +PHDR +0x[0-9a-f]+ 0x0+00.. 0x0+00.. 0x[0-9a-f]+ 0x[0-9a-f]+ R +0x[0-9a-f]+
 #...
- +LOAD +0x[0-9a-f]+ 0x0+0100 0x0+0100 0x0+0030 0x0+0030 R E +0x[0-9a-f]+
+ +LOAD +0x[0-9a-f]+ 0x0+0... 0x0+0... 0x0+0... 0x0+0... R E +0x[0-9a-f]+
  +TLS +0x[0-9a-f]+ 0x0+0108 0x0+0108 0x0+0014 0x0+002c R +0x[0-9a-f]+
 
  Section to Segment mapping:
index e67b3fa..7238639 100644 (file)
@@ -1,8 +1,8 @@
 PHDRS
 {
-  header PT_PHDR FILEHDR PHDRS ;
+  header PT_PHDR PHDRS ;
         
-  image PT_LOAD FLAGS (5);
+  image PT_LOAD FLAGS (5) PHDRS;
   tls PT_TLS FLAGS (4);
   
 }
index ca87459..03c74a4 100644 (file)
@@ -1,7 +1,7 @@
 ENTRY (foo_global)
 SECTIONS
 {
-  . = 0;
+  . = SIZEOF_HEADERS;
   .interp              : { *(.interp) }
   .hash                        : { *(.hash) }
   .dynsym              : { *(.dynsym) }
index b6b48e7..82ef917 100644 (file)
@@ -1 +1,6 @@
 HIDDEN (foo = .);
+
+SECTIONS
+{
+  . = SIZEOF_HEADERS;
+}