hppa -z relro again
[deliverable/binutils-gdb.git] / bfd / elf.c
index 936255e06178543b1c2cdfb2703008b5ca4099e7..94726bad2e46782d1e6ce2168cea5d39c2882e63 100644 (file)
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -1,6 +1,6 @@
 /* ELF executable support for BFD.
 
-   Copyright (C) 1993-2016 Free Software Foundation, Inc.
+   Copyright (C) 1993-2017 Free Software Foundation, Inc.
 
    This file is part of BFD, the Binary File Descriptor library.
 
@@ -1062,7 +1062,7 @@ _bfd_elf_make_section_from_shdr (bfd *abfd,
       if (!bfd_malloc_and_get_section (abfd, newsect, &contents))
        return FALSE;
 
-      elf_parse_notes (abfd, (char *) contents, hdr->sh_size, -1);
+      elf_parse_notes (abfd, (char *) contents, hdr->sh_size, hdr->sh_offset);
       free (contents);
     }
 
@@ -1271,13 +1271,19 @@ find_link (const bfd * obfd, const Elf_Internal_Shdr * iheader, const unsigned i
   Elf_Internal_Shdr ** oheaders = elf_elfsections (obfd);
   unsigned int i;
 
-  if (section_match (oheaders[hint], iheader))
+  BFD_ASSERT (iheader != NULL);
+
+  /* See PR 20922 for a reproducer of the NULL test.  */
+  if (oheaders[hint] != NULL
+      && section_match (oheaders[hint], iheader))
     return hint;
 
   for (i = 1; i < elf_numsections (obfd); i++)
     {
       Elf_Internal_Shdr * oheader = oheaders[i];
 
+      if (oheader == NULL)
+       continue;
       if (section_match (oheader, iheader))
        /* FIXME: Do we care if there is a potential for
           multiple matches ?  */
@@ -1340,6 +1346,16 @@ copy_special_section_fields (const bfd *ibfd,
      in the input bfd.  */
   if (iheader->sh_link != SHN_UNDEF)
     {
+      /* See PR 20931 for a reproducer.  */
+      if (iheader->sh_link >= elf_numsections (ibfd))
+       {
+         (* _bfd_error_handler)
+           /* xgettext:c-format */
+           (_("%B: Invalid sh_link field (%d) in section number %d"),
+            ibfd, iheader->sh_link, secnum);
+         return FALSE;
+       }
+
       sh_link = find_link (obfd, iheaders[iheader->sh_link], iheader->sh_link);
       if (sh_link != SHN_UNDEF)
        {
@@ -4254,7 +4270,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 += 3;
+      segs += 2;
     }
 
   if (bfd_get_section_by_name (abfd, ".dynamic") != NULL)
@@ -5109,6 +5125,7 @@ assign_file_positions_for_load_sections (bfd *abfd,
   Elf_Internal_Phdr *p;
   file_ptr off;
   bfd_size_type maxpagesize;
+  unsigned int pt_load_count = 0;
   unsigned int alloc;
   unsigned int i, j;
   bfd_vma header_pad = 0;
@@ -5236,6 +5253,7 @@ assign_file_positions_for_load_sections (bfd *abfd,
            maxpagesize = m->p_align;
 
          p->p_align = maxpagesize;
+         pt_load_count += 1;
        }
       else if (m->p_align_valid)
        p->p_align = m->p_align;
@@ -5287,6 +5305,15 @@ assign_file_positions_for_load_sections (bfd *abfd,
              }
 
          off_adjust = vma_page_aligned_bias (p->p_vaddr, off, align);
+
+         /* Broken hardware and/or kernel require that files do not
+            map the same page with different permissions on some hppa
+            processors.  */
+         if (pt_load_count > 1
+             && bed->no_page_alias
+             && (off & (maxpagesize - 1)) != 0
+             && (off & -maxpagesize) == ((off + off_adjust) & -maxpagesize))
+           off_adjust += maxpagesize;
          off += off_adjust;
          if (no_contents)
            {
@@ -5854,52 +5881,6 @@ 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.
@@ -5963,7 +5944,6 @@ 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
@@ -6007,22 +5987,24 @@ assign_file_positions_except_relocs (bfd *abfd,
       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.  */
+        catch all real world use cases.
+
+        FIXME: We used to have code here to sort the PT_LOAD segments into
+        ascending order, as per the ELF spec.  But this breaks some programs,
+        including the Linux kernel.  But really either the spec should be
+         changed or the programs updated.  */
       if (alloc > 1
-         && 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)))
+         && tdata->phdr[0].p_type == PT_PHDR
+         && ! bed->elf_backend_allow_non_load_phdr (abfd, tdata->phdr, alloc)
+         && tdata->phdr[1].p_type == PT_LOAD
+         && (tdata->phdr[1].p_vaddr > tdata->phdr[0].p_vaddr
+             || (tdata->phdr[1].p_vaddr + tdata->phdr[1].p_memsz)
+             <  (tdata->phdr[0].p_vaddr + tdata->phdr[0].p_memsz)))
        {
          /* The fix for this error is usually to edit the linker script being
             used and set up the program headers manually.  Either that or
@@ -6030,18 +6012,12 @@ assign_file_positions_except_relocs (bfd *abfd,
          _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, map, alloc) != 0)
-       {
-         free (map);
-         return FALSE;
-       }
-
-      free (map);
+         || bed->s->write_out_phdrs (abfd, tdata->phdr, alloc) != 0)
+       return FALSE;
     }
 
   return TRUE;
This page took 0.02768 seconds and 4 git commands to generate.