From 62655c7b8bfc33e6c12694f439ff8f7e8da3005a Mon Sep 17 00:00:00 2001 From: Roland McGrath Date: Fri, 22 Jun 2012 16:52:33 +0000 Subject: [PATCH] bfd/ * elf.c (assign_file_positions_for_non_load_sections): Define __ehdr_start symbol if it's referenced and there's a PT_LOAD segment that covers both the file and program headers. ld/ * NEWS: Mention __ehdr_start. ld/testsuite/ * ld-elf/ehdr_start.s: New file. * ld-elf/ehdr_start.d: New file. --- bfd/ChangeLog | 6 ++++ bfd/elf.c | 49 ++++++++++++++++++++++++++++++++ ld/ChangeLog | 4 +++ ld/NEWS | 6 +++- ld/testsuite/ChangeLog | 5 ++++ ld/testsuite/ld-elf/ehdr_start.d | 7 +++++ ld/testsuite/ld-elf/ehdr_start.s | 10 +++++++ 7 files changed, 86 insertions(+), 1 deletion(-) create mode 100644 ld/testsuite/ld-elf/ehdr_start.d create mode 100644 ld/testsuite/ld-elf/ehdr_start.s diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 9f8fb8a23a..538864d3b9 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,9 @@ +2012-06-22 Roland McGrath + + * elf.c (assign_file_positions_for_non_load_sections): Define + __ehdr_start symbol if it's referenced and there's a PT_LOAD + segment that covers both the file and program headers. + 2012-06-22 Andreas Schwab * elf32-m68k.c (elf_m68k_finish_dynamic_symbol): Don't make diff --git a/bfd/elf.c b/bfd/elf.c index 0296ef5672..1a5354895d 100644 --- a/bfd/elf.c +++ b/bfd/elf.c @@ -4826,6 +4826,7 @@ assign_file_positions_for_non_load_sections (bfd *abfd, Elf_Internal_Phdr *phdrs; Elf_Internal_Phdr *p; struct elf_segment_map *m; + struct elf_segment_map *hdrs_segment; bfd_vma filehdr_vaddr, filehdr_paddr; bfd_vma phdrs_vaddr, phdrs_paddr; file_ptr off; @@ -4883,6 +4884,7 @@ assign_file_positions_for_non_load_sections (bfd *abfd, filehdr_paddr = 0; phdrs_vaddr = bed->maxpagesize + bed->s->sizeof_ehdr; phdrs_paddr = 0; + hdrs_segment = NULL; phdrs = elf_tdata (abfd)->phdr; for (m = elf_tdata (abfd)->segment_map, p = phdrs; m != NULL; @@ -4903,12 +4905,59 @@ assign_file_positions_for_non_load_sections (bfd *abfd, phdrs_paddr = p->p_paddr; if (m->includes_filehdr) { + hdrs_segment = m; phdrs_vaddr += bed->s->sizeof_ehdr; phdrs_paddr += bed->s->sizeof_ehdr; } } } + if (hdrs_segment != NULL && link_info != NULL) + { + /* There is a segment that contains both the file headers and the + program headers, so provide a symbol __ehdr_start pointing there. + A program can use this to examine itself robustly. */ + + struct elf_link_hash_entry *hash + = elf_link_hash_lookup (elf_hash_table (link_info), "__ehdr_start", + FALSE, FALSE, TRUE); + /* If the symbol was referenced and not defined, define it. */ + if (hash != NULL + && (hash->root.type == bfd_link_hash_new + || hash->root.type == bfd_link_hash_undefined + || hash->root.type == bfd_link_hash_undefweak + || hash->root.type == bfd_link_hash_common)) + { + asection *s = NULL; + if (hdrs_segment->count != 0) + /* The segment contains sections, so use the first one. */ + s = hdrs_segment->sections[0]; + else + /* Use the first (i.e. lowest-addressed) section in any segment. */ + for (m = elf_tdata (abfd)->segment_map; m != NULL; m = m->next) + if (m->count != 0) + { + s = m->sections[0]; + break; + } + + if (s != NULL) + { + hash->root.u.def.value = filehdr_vaddr - s->vma; + hash->root.u.def.section = s; + } + else + { + hash->root.u.def.value = filehdr_vaddr; + hash->root.u.def.section = bfd_abs_section_ptr; + } + + hash->root.type = bfd_link_hash_defined; + hash->def_regular = 1; + hash->non_elf = 0; + } + } + for (m = elf_tdata (abfd)->segment_map, p = phdrs; m != NULL; m = m->next, p++) diff --git a/ld/ChangeLog b/ld/ChangeLog index f6e78f2feb..91a4211b89 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,3 +1,7 @@ +2012-06-22 Roland McGrath + + * NEWS: Mention __ehdr_start. + 2012-06-21 Alan Modra * ldlang.c (lang_insert_orphan): Don't make __start_ symbol diff --git a/ld/NEWS b/ld/NEWS index cb2d428a28..8701c5cd2c 100644 --- a/ld/NEWS +++ b/ld/NEWS @@ -1,5 +1,9 @@ -*- text -*- +* Add a linker-provided symbol when producing ELF output, '__ehdr_start' + to point to the ELF file header (and nearby program headers) in the + program's memory image. + * Add support for S12X processor. * Add support for the VLE extension to the PowerPC architecture. @@ -103,7 +107,7 @@ Changes in 2.20: * Add support for Lattice Mico32 (lm32) architecture. -* Add CR16 ELF --embedded-relocs (used to embedded relocations into binaries +* Add CR16 ELF --embedded-relocs (used to embedded relocations into binaries for Embedded-PIC code) option. * Add to the PE/PE+ targets the support of two different kinds of diff --git a/ld/testsuite/ChangeLog b/ld/testsuite/ChangeLog index 57996a7ffe..d03c432d7d 100644 --- a/ld/testsuite/ChangeLog +++ b/ld/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2012-06-22 Roland McGrath + + * ld-elf/ehdr_start.s: New file. + * ld-elf/ehdr_start.d: New file. + 2012-06-21 Alan Modra * ld-gc/start.d: Update. diff --git a/ld/testsuite/ld-elf/ehdr_start.d b/ld/testsuite/ld-elf/ehdr_start.d new file mode 100644 index 0000000000..3965eeba4f --- /dev/null +++ b/ld/testsuite/ld-elf/ehdr_start.d @@ -0,0 +1,7 @@ +#source: ehdr_start.s +#ld: +#nm: -n + +#... +[0-9a-f]*000 [ADRT] __ehdr_start +#pass diff --git a/ld/testsuite/ld-elf/ehdr_start.s b/ld/testsuite/ld-elf/ehdr_start.s new file mode 100644 index 0000000000..ab029dc19d --- /dev/null +++ b/ld/testsuite/ld-elf/ehdr_start.s @@ -0,0 +1,10 @@ + .text + .globl _start +_start: + .space 16 + + .section .rodata,"a",%progbits + .globl foo +foo: + .weak __ehdr_start + .dc.a __ehdr_start -- 2.34.1