+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.
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)
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);
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)
}
(*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;
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. */
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;
|| ((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++)
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;
}
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.
}
else
{
+ Elf_Internal_Phdr * map;
unsigned int alloc;
/* Assign file positions for the loaded sections based on the
/* 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;
/* 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);
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;
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.
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 *)
#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
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)
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))
#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
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,
+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.
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))
{
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);
{
Elf_Internal_Phdr * segment;
unsigned int i;
+ Elf_Internal_Phdr * previous_load = NULL;
if (elf_header.e_phnum == 0)
{
(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"));
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)
{
+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.
@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.
ENTRY(_start)
SECTIONS
{
+ . = SIZEOF_HEADERS;
/* Sections to be discarded */
/DISCARD/ : {
*(.data.exit)
#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*
#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-*-*
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" }
}
}
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
#ld: -Tflags1.ld
#objcopy_linked_file: --set-section-flags .post_text_reserve=contents,alloc,load,readonly,code
#readelf: -S --wide
+#notarget: rx-*-*
#...
Section Headers:
SECTIONS
{
+ . = SIZEOF_HEADERS;
.text :
{
*(.text)
+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) }
}
#...
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
SECTIONS
{
+ . = SIZEOF_HEADERS;
.text : {*(.text)}
. = ALIGN(CONSTANT (MAXPAGESIZE));
.data : {*(.data)}
SECTIONS
{
+ . = SIZEOF_HEADERS;
TEST (NOLOAD) :
{
*(TEST)
#target: *-*-linux* *-*-gnu*
#...
- +LOAD +0x200000 +0x0+ +0x0+ +0x0+ +0x0+1 +RW +0x200000
+ +LOAD +0x.00000 +0x0+ +0x0+ +0x0+.. +0x0+.. +RW +0x200000
#pass
SECTIONS
{
+ . = SIZEOF_HEADERS;
.text : { *(.text) }
.data : { *(.data) }
.bss : { *(.bss) *(COMMON) }
# 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
SECTIONS
{
+ . = SIZEOF_HEADERS;
.text : { *(.text) }
OVERLAY 0x1000 : AT (0x4000)
{
.text1 {*(.text1)}
.text2 {*(.text2)}
- }
+ }
/DISCARD/ : { *(.*) }
}
SECTIONS {
+ . = SIZEOF_HEADERS;
.text : {
*(.text)
}
#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.
#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
HIDDEN (foo = .);
+
+SECTIONS
+{
+ . = SIZEOF_HEADERS;
+}
SECTIONS
{
+ . = SIZEOF_HEADERS;
. = 0x12300000;
.data :
{
SECTIONS
{
+ . = SIZEOF_HEADERS;
. = 0x12300000;
.data : { *(.data) }
.got : { *(.got) }
SECTIONS
{
+ . = SIZEOF_HEADERS;
. = 0x800000;
PROVIDE (bar = .);
.data : {
HIDDEN (foo = .);
+
+SECTIONS
+{
+ . = SIZEOF_HEADERS;
+}
Type .*
PHDR .*
#...
- LOAD .* 0x00080000 0x00080000 .* R E 0x10000
+ LOAD .* 0x00070000 0x00070000 .* R E 0x10000
LOAD .* 0x00090000 0x00090000 .* RW 0x10000
DYNAMIC .*
SECTIONS {
+ . = SIZEOF_HEADERS;
.text : { *(.text) }
.data : { *(.data) }
.bss : { *(.bss) *(COMMON) }
SECTIONS
{
+ . = SIZEOF_HEADERS;
.text : { *(.text) }
.data : { *(.data) }
.bss : { *(.bss) *(COMMON) }
SECTIONS
{
+ . = SIZEOF_HEADERS;
.data : { *(.data) }
.rodata : { *(.rodata) }
SECTIONS
{
+ . = SIZEOF_HEADERS;
.text : { *(.text) }
/* Alignment at beginning shouldn't result in empty section being kept. */
.text1 ALIGN (4096) :
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*) }
#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
SECTIONS
{
+ . = SIZEOF_HEADERS;
PROVIDE (foo = 1);
PROVIDE (bar = 2);
PROVIDE (baz = 3);
SECTIONS
{
+ . = SIZEOF_HEADERS;
PROVIDE (foo = 1);
PROVIDE (bar = 2);
PROVIDE (baz = 3);
#...
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:
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);
}
ENTRY (foo_global)
SECTIONS
{
- . = 0;
+ . = SIZEOF_HEADERS;
.interp : { *(.interp) }
.hash : { *(.hash) }
.dynsym : { *(.dynsym) }
HIDDEN (foo = .);
+
+SECTIONS
+{
+ . = SIZEOF_HEADERS;
+}