This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
Re: [binutils-gdb] Fix the linker so that it will not silently generate ELF binaries with invalid program headers. Fix
On Sat, Dec 10, 2016 at 12:13:46AM +0000, Maciej W. Rozycki wrote:
> Thanks for your and Nick's effort; I'll be looking into these patches
> once I have offloaded my immediately pending queue, which has to take
I should note that the patch I posted was just a quick hack to
experiment with removing the PT_PHDR header. A proper patch minus
testsuite tweaking is more like the following, due to elf-nacl.c
fiddling with segments.
diff --git a/bfd/elf.c b/bfd/elf.c
index 678c043..9c8a167 100644
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -4483,6 +4483,7 @@ _bfd_elf_map_sections_to_segments (bfd *abfd, struct bfd_link_info *info)
asection **sections = NULL;
const struct elf_backend_data *bed = get_elf_backend_data (abfd);
bfd_boolean no_user_phdrs;
+ bfd_boolean phdr_in_segment = TRUE;
no_user_phdrs = elf_seg_map (abfd) == NULL;
@@ -4500,14 +4501,12 @@ _bfd_elf_map_sections_to_segments (bfd *abfd, struct bfd_link_info *info)
unsigned int phdr_index;
bfd_vma maxpagesize;
asection **hdrpp;
- bfd_boolean phdr_in_segment = TRUE;
bfd_boolean writable;
int tls_count = 0;
asection *first_tls = NULL;
asection *dynsec, *eh_frame_hdr;
bfd_size_type amt;
bfd_vma addr_mask, wrap_to = 0;
- bfd_boolean linker_created_pt_phdr_segment = FALSE;
/* Select the allocated sections, and sort them. */
@@ -4560,7 +4559,6 @@ _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;
@@ -4611,19 +4609,7 @@ _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)
- {
- /* 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;
- }
+ phdr_in_segment = FALSE;
}
for (i = 0, hdrpp = sections; i < count; i++, hdrpp++)
@@ -4965,8 +4951,26 @@ _bfd_elf_map_sections_to_segments (bfd *abfd, struct bfd_link_info *info)
if (!elf_modify_segment_map (abfd, info, no_user_phdrs))
return FALSE;
+ phdr_in_segment = FALSE;
for (count = 0, m = elf_seg_map (abfd); m != NULL; m = m->next)
- ++count;
+ {
+ if (m->p_type == PT_LOAD && m->includes_phdrs)
+ phdr_in_segment = TRUE;
+ ++count;
+ }
+ if (no_user_phdrs && !phdr_in_segment && count != 0)
+ {
+ /* PR 20815: The ELF standard says that a PT_PHDR segment, if
+ present, must be included as part of the memory image of the
+ program. Ie it must be part of a PT_LOAD segment as well.
+ If PHDR won't be part of the memory image, remove it. */
+ m = elf_seg_map (abfd);
+ if (m->p_type == PT_PHDR)
+ {
+ elf_seg_map (abfd) = m->next;
+ --count;
+ }
+ }
elf_program_header_size (abfd) = count * bed->s->sizeof_phdr;
return TRUE;
--
Alan Modra
Australia Development Lab, IBM