From 1a9ccd70f9a75dc6b48d340059f28ef3550c107b Mon Sep 17 00:00:00 2001 From: Nick Clifton Date: Wed, 23 Nov 2016 11:10:39 +0000 Subject: [PATCH] Fix the linker so that it will not silently generate ELF binaries with invalid program headers. Fix readelf to report such invalid binaries. 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. --- bfd/ChangeLog | 29 +++++ bfd/elf-bfd.h | 5 + bfd/elf-m10300.c | 2 +- bfd/elf.c | 125 +++++++++++++++++++-- bfd/elf32-arc.c | 2 +- bfd/elf32-score7.c | 9 +- bfd/elf64-hppa.c | 12 ++ bfd/elfcode.h | 4 +- bfd/elfxx-target.h | 5 + binutils/ChangeLog | 6 + binutils/readelf.c | 41 ++++++- ld/ChangeLog | 41 +++++++ ld/ld.texinfo | 3 + ld/testsuite/ld-discard/discard.ld | 1 + ld/testsuite/ld-elf/ehdr_start-missing.d | 2 +- ld/testsuite/ld-elf/ehdr_start-weak.d | 2 +- ld/testsuite/ld-elf/elf.exp | 4 +- ld/testsuite/ld-elf/flags1.d | 1 + ld/testsuite/ld-elf/flags1.ld | 1 + ld/testsuite/ld-elf/group.ld | 8 +- ld/testsuite/ld-elf/loadaddr1.d | 2 +- ld/testsuite/ld-elf/maxpage3.t | 1 + ld/testsuite/ld-elf/noload-1.t | 1 + ld/testsuite/ld-elf/noload-2.d | 2 +- ld/testsuite/ld-elf/orphan.ld | 1 + ld/testsuite/ld-elf/overlay.d | 2 + ld/testsuite/ld-elf/overlay.t | 3 +- ld/testsuite/ld-elf/pr14052.t | 1 + ld/testsuite/ld-elf/pr19162.d | 2 +- ld/testsuite/ld-elf/pr19539.d | 2 +- ld/testsuite/ld-elf/pr19539.t | 5 + ld/testsuite/ld-elf/provide-hidden-1.ld | 1 + ld/testsuite/ld-elf/provide-hidden-s.ld | 1 + ld/testsuite/ld-elf/weak-dyn-1.ld | 1 + ld/testsuite/ld-i386/pr19539.t | 5 + ld/testsuite/ld-powerpc/vxworks2.sd | 2 +- ld/testsuite/ld-scripts/defined.t | 1 + ld/testsuite/ld-scripts/defined6.t | 1 + ld/testsuite/ld-scripts/dynamic-sections.t | 1 + ld/testsuite/ld-scripts/empty-aligned.t | 1 + ld/testsuite/ld-scripts/empty-orphan.t | 6 +- ld/testsuite/ld-scripts/phdrs3a.d | 2 +- ld/testsuite/ld-scripts/provide-2.t | 1 + ld/testsuite/ld-scripts/provide-4.t | 1 + ld/testsuite/ld-scripts/size-2.d | 4 +- ld/testsuite/ld-scripts/size-2.t | 4 +- ld/testsuite/ld-vax-elf/plt-local.ld | 2 +- ld/testsuite/ld-x86-64/pr19539.t | 5 + 48 files changed, 324 insertions(+), 40 deletions(-) diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 19a1026af3..346ff297e4 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,32 @@ +2016-11-23 Nick Clifton + + 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 * elf-bfd.h (struct elf_backend_data): Add dtrel_excludes_plt. diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h index 7c78899c34..06bd800b4c 100644 --- a/bfd/elf-bfd.h +++ b/bfd/elf-bfd.h @@ -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) diff --git a/bfd/elf-m10300.c b/bfd/elf-m10300.c index 1ea5c27b4f..4a8a29787a 100644 --- a/bfd/elf-m10300.c +++ b/bfd/elf-m10300.c @@ -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); diff --git a/bfd/elf.c b/bfd/elf.c index e7252c634d..936255e061 100644 --- 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; diff --git a/bfd/elf32-arc.c b/bfd/elf32-arc.c index 3d39c3a135..9ef53688a7 100644 --- a/bfd/elf32-arc.c +++ b/bfd/elf32-arc.c @@ -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); diff --git a/bfd/elf32-score7.c b/bfd/elf32-score7.c index 79d67689a1..3813184590 100644 --- a/bfd/elf32-score7.c +++ b/bfd/elf32-score7.c @@ -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; diff --git a/bfd/elf64-hppa.c b/bfd/elf64-hppa.c index a9e8d0c7cf..0e19f0a728 100644 --- a/bfd/elf64-hppa.c +++ b/bfd/elf64-hppa.c @@ -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 diff --git a/bfd/elfcode.h b/bfd/elfcode.h index eb3a1ff892..c7e0e466c6 100644 --- a/bfd/elfcode.h +++ b/bfd/elfcode.h @@ -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)) diff --git a/bfd/elfxx-target.h b/bfd/elfxx-target.h index 5ff39dd447..aff8621485 100644 --- a/bfd/elfxx-target.h +++ b/bfd/elfxx-target.h @@ -479,6 +479,10 @@ #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, diff --git a/binutils/ChangeLog b/binutils/ChangeLog index 0f3d167138..f625a268bc 100644 --- a/binutils/ChangeLog +++ b/binutils/ChangeLog @@ -1,3 +1,9 @@ +2016-11-23 Nick Clifton + + PR ld/20815 + * readelf.c (process_program_headers): Check PT_LOAD and PT_PHDR + segments for validity. + 2016-11-22 Ambrogino Modigliani * configure: Regenerate. diff --git a/binutils/readelf.c b/binutils/readelf.c index e782e9561f..ee55852bdb 100644 --- a/binutils/readelf.c +++ b/binutils/readelf.c @@ -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), _(": %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) { diff --git a/ld/ChangeLog b/ld/ChangeLog index 1f4814d8f5..8d28692ad2 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,3 +1,44 @@ +2016-11-23 Nick Clifton + + 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 * configure: Regenerate. diff --git a/ld/ld.texinfo b/ld/ld.texinfo index d4f33b7c92..ec7ff1b85a 100644 --- a/ld/ld.texinfo +++ b/ld/ld.texinfo @@ -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. diff --git a/ld/testsuite/ld-discard/discard.ld b/ld/testsuite/ld-discard/discard.ld index a7ff4a5802..64f3350642 100644 --- a/ld/testsuite/ld-discard/discard.ld +++ b/ld/testsuite/ld-discard/discard.ld @@ -1,6 +1,7 @@ ENTRY(_start) SECTIONS { + . = SIZEOF_HEADERS; /* Sections to be discarded */ /DISCARD/ : { *(.data.exit) diff --git a/ld/testsuite/ld-elf/ehdr_start-missing.d b/ld/testsuite/ld-elf/ehdr_start-missing.d index 5c2090fe69..046e39a75c 100644 --- a/ld/testsuite/ld-elf/ehdr_start-missing.d +++ b/ld/testsuite/ld-elf/ehdr_start-missing.d @@ -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* diff --git a/ld/testsuite/ld-elf/ehdr_start-weak.d b/ld/testsuite/ld-elf/ehdr_start-weak.d index 5644d0537d..d3d5af7138 100644 --- a/ld/testsuite/ld-elf/ehdr_start-weak.d +++ b/ld/testsuite/ld-elf/ehdr_start-weak.d @@ -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-*-* diff --git a/ld/testsuite/ld-elf/elf.exp b/ld/testsuite/ld-elf/elf.exp index 59284bd37b..f93ad467b5 100644 --- a/ld/testsuite/ld-elf/elf.exp +++ b/ld/testsuite/ld-elf/elf.exp @@ -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 diff --git a/ld/testsuite/ld-elf/flags1.d b/ld/testsuite/ld-elf/flags1.d index 6cd8b3f383..aadf936c1e 100644 --- a/ld/testsuite/ld-elf/flags1.d +++ b/ld/testsuite/ld-elf/flags1.d @@ -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: diff --git a/ld/testsuite/ld-elf/flags1.ld b/ld/testsuite/ld-elf/flags1.ld index a94cbe8259..c003ce72c1 100644 --- a/ld/testsuite/ld-elf/flags1.ld +++ b/ld/testsuite/ld-elf/flags1.ld @@ -1,5 +1,6 @@ SECTIONS { + . = SIZEOF_HEADERS; .text : { *(.text) diff --git a/ld/testsuite/ld-elf/group.ld b/ld/testsuite/ld-elf/group.ld index f8e50c379b..53e2790356 100644 --- a/ld/testsuite/ld-elf/group.ld +++ b/ld/testsuite/ld-elf/group.ld @@ -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) } } diff --git a/ld/testsuite/ld-elf/loadaddr1.d b/ld/testsuite/ld-elf/loadaddr1.d index 0fd96a78ea..0aa372c4de 100644 --- a/ld/testsuite/ld-elf/loadaddr1.d +++ b/ld/testsuite/ld-elf/loadaddr1.d @@ -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 diff --git a/ld/testsuite/ld-elf/maxpage3.t b/ld/testsuite/ld-elf/maxpage3.t index 556dcd533c..f5ada18433 100644 --- a/ld/testsuite/ld-elf/maxpage3.t +++ b/ld/testsuite/ld-elf/maxpage3.t @@ -1,5 +1,6 @@ SECTIONS { + . = SIZEOF_HEADERS; .text : {*(.text)} . = ALIGN(CONSTANT (MAXPAGESIZE)); .data : {*(.data)} diff --git a/ld/testsuite/ld-elf/noload-1.t b/ld/testsuite/ld-elf/noload-1.t index 1efd06c2e1..768cd423e0 100644 --- a/ld/testsuite/ld-elf/noload-1.t +++ b/ld/testsuite/ld-elf/noload-1.t @@ -1,5 +1,6 @@ SECTIONS { + . = SIZEOF_HEADERS; TEST (NOLOAD) : { *(TEST) diff --git a/ld/testsuite/ld-elf/noload-2.d b/ld/testsuite/ld-elf/noload-2.d index 0e25d9beef..c9668a0286 100644 --- a/ld/testsuite/ld-elf/noload-2.d +++ b/ld/testsuite/ld-elf/noload-2.d @@ -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 diff --git a/ld/testsuite/ld-elf/orphan.ld b/ld/testsuite/ld-elf/orphan.ld index 1ae908b126..8b5015e157 100644 --- a/ld/testsuite/ld-elf/orphan.ld +++ b/ld/testsuite/ld-elf/orphan.ld @@ -1,5 +1,6 @@ SECTIONS { + . = SIZEOF_HEADERS; .text : { *(.text) } .data : { *(.data) } .bss : { *(.bss) *(COMMON) } diff --git a/ld/testsuite/ld-elf/overlay.d b/ld/testsuite/ld-elf/overlay.d index 00d25d5e20..c4409ae01d 100644 --- a/ld/testsuite/ld-elf/overlay.d +++ b/ld/testsuite/ld-elf/overlay.d @@ -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 diff --git a/ld/testsuite/ld-elf/overlay.t b/ld/testsuite/ld-elf/overlay.t index bdb33c815c..dd374bb68b 100644 --- a/ld/testsuite/ld-elf/overlay.t +++ b/ld/testsuite/ld-elf/overlay.t @@ -1,10 +1,11 @@ SECTIONS { + . = SIZEOF_HEADERS; .text : { *(.text) } OVERLAY 0x1000 : AT (0x4000) { .text1 {*(.text1)} .text2 {*(.text2)} - } + } /DISCARD/ : { *(.*) } } diff --git a/ld/testsuite/ld-elf/pr14052.t b/ld/testsuite/ld-elf/pr14052.t index 360c231d9c..84fffbd499 100644 --- a/ld/testsuite/ld-elf/pr14052.t +++ b/ld/testsuite/ld-elf/pr14052.t @@ -1,4 +1,5 @@ SECTIONS { + . = SIZEOF_HEADERS; .text : { *(.text) } diff --git a/ld/testsuite/ld-elf/pr19162.d b/ld/testsuite/ld-elf/pr19162.d index 1a54546198..4d706ffaca 100644 --- a/ld/testsuite/ld-elf/pr19162.d +++ b/ld/testsuite/ld-elf/pr19162.d @@ -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. diff --git a/ld/testsuite/ld-elf/pr19539.d b/ld/testsuite/ld-elf/pr19539.d index 87c2b1b437..e7d82984dc 100644 --- a/ld/testsuite/ld-elf/pr19539.d +++ b/ld/testsuite/ld-elf/pr19539.d @@ -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 diff --git a/ld/testsuite/ld-elf/pr19539.t b/ld/testsuite/ld-elf/pr19539.t index b6b48e71d3..82ef9178a1 100644 --- a/ld/testsuite/ld-elf/pr19539.t +++ b/ld/testsuite/ld-elf/pr19539.t @@ -1 +1,6 @@ HIDDEN (foo = .); + +SECTIONS +{ + . = SIZEOF_HEADERS; +} diff --git a/ld/testsuite/ld-elf/provide-hidden-1.ld b/ld/testsuite/ld-elf/provide-hidden-1.ld index 47cdbb7fa2..479862db93 100644 --- a/ld/testsuite/ld-elf/provide-hidden-1.ld +++ b/ld/testsuite/ld-elf/provide-hidden-1.ld @@ -1,5 +1,6 @@ SECTIONS { + . = SIZEOF_HEADERS; . = 0x12300000; .data : { diff --git a/ld/testsuite/ld-elf/provide-hidden-s.ld b/ld/testsuite/ld-elf/provide-hidden-s.ld index cca804f775..fc5761a2c0 100644 --- a/ld/testsuite/ld-elf/provide-hidden-s.ld +++ b/ld/testsuite/ld-elf/provide-hidden-s.ld @@ -1,5 +1,6 @@ SECTIONS { + . = SIZEOF_HEADERS; . = 0x12300000; .data : { *(.data) } .got : { *(.got) } diff --git a/ld/testsuite/ld-elf/weak-dyn-1.ld b/ld/testsuite/ld-elf/weak-dyn-1.ld index 495b712161..25a510c4da 100644 --- a/ld/testsuite/ld-elf/weak-dyn-1.ld +++ b/ld/testsuite/ld-elf/weak-dyn-1.ld @@ -1,5 +1,6 @@ SECTIONS { + . = SIZEOF_HEADERS; . = 0x800000; PROVIDE (bar = .); .data : { diff --git a/ld/testsuite/ld-i386/pr19539.t b/ld/testsuite/ld-i386/pr19539.t index b6b48e71d3..82ef9178a1 100644 --- a/ld/testsuite/ld-i386/pr19539.t +++ b/ld/testsuite/ld-i386/pr19539.t @@ -1 +1,6 @@ HIDDEN (foo = .); + +SECTIONS +{ + . = SIZEOF_HEADERS; +} diff --git a/ld/testsuite/ld-powerpc/vxworks2.sd b/ld/testsuite/ld-powerpc/vxworks2.sd index 087656882a..2294cb63bd 100644 --- a/ld/testsuite/ld-powerpc/vxworks2.sd +++ b/ld/testsuite/ld-powerpc/vxworks2.sd @@ -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 .* diff --git a/ld/testsuite/ld-scripts/defined.t b/ld/testsuite/ld-scripts/defined.t index c1ef1b6a79..e4e105f3b3 100644 --- a/ld/testsuite/ld-scripts/defined.t +++ b/ld/testsuite/ld-scripts/defined.t @@ -1,4 +1,5 @@ SECTIONS { + . = SIZEOF_HEADERS; .text : { *(.text) } .data : { *(.data) } .bss : { *(.bss) *(COMMON) } diff --git a/ld/testsuite/ld-scripts/defined6.t b/ld/testsuite/ld-scripts/defined6.t index f4ca38a90f..9713aacf0a 100644 --- a/ld/testsuite/ld-scripts/defined6.t +++ b/ld/testsuite/ld-scripts/defined6.t @@ -1,5 +1,6 @@ SECTIONS { + . = SIZEOF_HEADERS; .text : { *(.text) } .data : { *(.data) } .bss : { *(.bss) *(COMMON) } diff --git a/ld/testsuite/ld-scripts/dynamic-sections.t b/ld/testsuite/ld-scripts/dynamic-sections.t index f1f24c830e..64cf47d674 100644 --- a/ld/testsuite/ld-scripts/dynamic-sections.t +++ b/ld/testsuite/ld-scripts/dynamic-sections.t @@ -1,5 +1,6 @@ SECTIONS { + . = SIZEOF_HEADERS; .data : { *(.data) } .rodata : { *(.rodata) } diff --git a/ld/testsuite/ld-scripts/empty-aligned.t b/ld/testsuite/ld-scripts/empty-aligned.t index 5f6a38d888..0073f13fa6 100644 --- a/ld/testsuite/ld-scripts/empty-aligned.t +++ b/ld/testsuite/ld-scripts/empty-aligned.t @@ -1,5 +1,6 @@ SECTIONS { + . = SIZEOF_HEADERS; .text : { *(.text) } /* Alignment at beginning shouldn't result in empty section being kept. */ .text1 ALIGN (4096) : diff --git a/ld/testsuite/ld-scripts/empty-orphan.t b/ld/testsuite/ld-scripts/empty-orphan.t index b57e164aa7..c0dc628604 100644 --- a/ld/testsuite/ld-scripts/empty-orphan.t +++ b/ld/testsuite/ld-scripts/empty-orphan.t @@ -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*) } diff --git a/ld/testsuite/ld-scripts/phdrs3a.d b/ld/testsuite/ld-scripts/phdrs3a.d index 80bde71ea3..d96bd13187 100644 --- a/ld/testsuite/ld-scripts/phdrs3a.d +++ b/ld/testsuite/ld-scripts/phdrs3a.d @@ -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 diff --git a/ld/testsuite/ld-scripts/provide-2.t b/ld/testsuite/ld-scripts/provide-2.t index fe30dd8590..abf6eb324a 100644 --- a/ld/testsuite/ld-scripts/provide-2.t +++ b/ld/testsuite/ld-scripts/provide-2.t @@ -1,5 +1,6 @@ SECTIONS { + . = SIZEOF_HEADERS; PROVIDE (foo = 1); PROVIDE (bar = 2); PROVIDE (baz = 3); diff --git a/ld/testsuite/ld-scripts/provide-4.t b/ld/testsuite/ld-scripts/provide-4.t index 424c238e43..da663db215 100644 --- a/ld/testsuite/ld-scripts/provide-4.t +++ b/ld/testsuite/ld-scripts/provide-4.t @@ -1,5 +1,6 @@ SECTIONS { + . = SIZEOF_HEADERS; PROVIDE (foo = 1); PROVIDE (bar = 2); PROVIDE (baz = 3); diff --git a/ld/testsuite/ld-scripts/size-2.d b/ld/testsuite/ld-scripts/size-2.d index c9256738db..d76745ee8f 100644 --- a/ld/testsuite/ld-scripts/size-2.d +++ b/ld/testsuite/ld-scripts/size-2.d @@ -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: diff --git a/ld/testsuite/ld-scripts/size-2.t b/ld/testsuite/ld-scripts/size-2.t index e67b3fa8f8..723863995e 100644 --- a/ld/testsuite/ld-scripts/size-2.t +++ b/ld/testsuite/ld-scripts/size-2.t @@ -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); } diff --git a/ld/testsuite/ld-vax-elf/plt-local.ld b/ld/testsuite/ld-vax-elf/plt-local.ld index ca87459e91..03c74a4f31 100644 --- a/ld/testsuite/ld-vax-elf/plt-local.ld +++ b/ld/testsuite/ld-vax-elf/plt-local.ld @@ -1,7 +1,7 @@ ENTRY (foo_global) SECTIONS { - . = 0; + . = SIZEOF_HEADERS; .interp : { *(.interp) } .hash : { *(.hash) } .dynsym : { *(.dynsym) } diff --git a/ld/testsuite/ld-x86-64/pr19539.t b/ld/testsuite/ld-x86-64/pr19539.t index b6b48e71d3..82ef9178a1 100644 --- a/ld/testsuite/ld-x86-64/pr19539.t +++ b/ld/testsuite/ld-x86-64/pr19539.t @@ -1 +1,6 @@ HIDDEN (foo = .); + +SECTIONS +{ + . = SIZEOF_HEADERS; +} -- 2.34.1