Partially revert patch for PR 20815 - do not sort the PT_LOAD segments. Non-ordered segments are needed by the Linux kernel.
PR ld/20815 * elf.c (phdr_sorter): Delete. (assign_file_positions_except_relocs): Do not sort program headers.
This commit is contained in:
parent
abfcb414b9
commit
cd58485720
|
@ -5,6 +5,13 @@
|
||||||
(elf_link_output_extsym): Don't change bind from global to
|
(elf_link_output_extsym): Don't change bind from global to
|
||||||
local when linking executable.
|
local when linking executable.
|
||||||
|
|
||||||
|
2016-11-28 Nick Clifton <nickc@redhat.com>
|
||||||
|
|
||||||
|
PR ld/20815
|
||||||
|
* elf.c (phdr_sorter): Delete.
|
||||||
|
(assign_file_positions_except_relocs): Do not sort program
|
||||||
|
headers.
|
||||||
|
|
||||||
2016-11-25 Jon Turney <jon.turney@dronecode.org.uk>
|
2016-11-25 Jon Turney <jon.turney@dronecode.org.uk>
|
||||||
|
|
||||||
PR ld/20193
|
PR ld/20193
|
||||||
|
|
79
bfd/elf.c
79
bfd/elf.c
|
@ -5854,52 +5854,6 @@ find_section_in_list (unsigned int i, elf_section_list * list)
|
||||||
return 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
|
/* Work out the file positions of all the sections. This is called by
|
||||||
_bfd_elf_compute_section_file_positions. All the section sizes and
|
_bfd_elf_compute_section_file_positions. All the section sizes and
|
||||||
VMAs must be known before this is called.
|
VMAs must be known before this is called.
|
||||||
|
@ -5963,7 +5917,6 @@ assign_file_positions_except_relocs (bfd *abfd,
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Elf_Internal_Phdr * map;
|
|
||||||
unsigned int alloc;
|
unsigned int alloc;
|
||||||
|
|
||||||
/* Assign file positions for the loaded sections based on the
|
/* Assign file positions for the loaded sections based on the
|
||||||
|
@ -6007,22 +5960,24 @@ assign_file_positions_except_relocs (bfd *abfd,
|
||||||
if (alloc == 0)
|
if (alloc == 0)
|
||||||
return TRUE;
|
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
|
/* PR ld/20815 - Check that the program header segment, if present, will
|
||||||
be loaded into memory. FIXME: The check below is not sufficient as
|
be loaded into memory. FIXME: The check below is not sufficient as
|
||||||
really all PT_LOAD segments should be checked before issuing an error
|
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
|
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
|
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
|
if (alloc > 1
|
||||||
&& map[0].p_type == PT_PHDR
|
&& tdata->phdr[0].p_type == PT_PHDR
|
||||||
&& ! bed->elf_backend_allow_non_load_phdr (abfd, map, alloc)
|
&& ! bed->elf_backend_allow_non_load_phdr (abfd, tdata->phdr, alloc)
|
||||||
&& map[1].p_type == PT_LOAD
|
&& tdata->phdr[1].p_type == PT_LOAD
|
||||||
&& (map[1].p_vaddr > map[0].p_vaddr
|
&& (tdata->phdr[1].p_vaddr > tdata->phdr[0].p_vaddr
|
||||||
|| (map[1].p_vaddr + map[1].p_memsz) < (map[0].p_vaddr + map[0].p_memsz)))
|
|| (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
|
/* The fix for this error is usually to edit the linker script being
|
||||||
used and set up the program headers manually. Either that or
|
used and set up the program headers manually. Either that or
|
||||||
|
@ -6030,18 +5985,12 @@ assign_file_positions_except_relocs (bfd *abfd,
|
||||||
_bfd_error_handler (_("\
|
_bfd_error_handler (_("\
|
||||||
%B: error: PHDR segment not covered by LOAD segment"),
|
%B: error: PHDR segment not covered by LOAD segment"),
|
||||||
abfd);
|
abfd);
|
||||||
free (map);
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bfd_seek (abfd, (bfd_signed_vma) bed->s->sizeof_ehdr, SEEK_SET) != 0
|
if (bfd_seek (abfd, (bfd_signed_vma) bed->s->sizeof_ehdr, SEEK_SET) != 0
|
||||||
|| bed->s->write_out_phdrs (abfd, map, alloc) != 0)
|
|| bed->s->write_out_phdrs (abfd, tdata->phdr, alloc) != 0)
|
||||||
{
|
return FALSE;
|
||||||
free (map);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
free (map);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
Loading…
Reference in New Issue