bfd/
authorRoland McGrath <roland@gnu.org>
Fri, 22 Jun 2012 16:52:33 +0000 (16:52 +0000)
committerRoland McGrath <roland@gnu.org>
Fri, 22 Jun 2012 16:52:33 +0000 (16:52 +0000)
* 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
bfd/elf.c
ld/ChangeLog
ld/NEWS
ld/testsuite/ChangeLog
ld/testsuite/ld-elf/ehdr_start.d [new file with mode: 0644]
ld/testsuite/ld-elf/ehdr_start.s [new file with mode: 0644]

index 9f8fb8a..538864d 100644 (file)
@@ -1,3 +1,9 @@
+2012-06-22  Roland McGrath  <mcgrathr@google.com>
+
+       * 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  <schwab@linux-m68k.org>
 
        * elf32-m68k.c (elf_m68k_finish_dynamic_symbol): Don't make
index 0296ef5..1a53548 100644 (file)
--- 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++)
index f6e78f2..91a4211 100644 (file)
@@ -1,3 +1,7 @@
+2012-06-22  Roland McGrath  <mcgrathr@google.com>
+
+       * NEWS: Mention __ehdr_start.
+
 2012-06-21  Alan Modra  <amodra@gmail.com>
 
        * ldlang.c (lang_insert_orphan): Don't make __start_<sec> symbol
diff --git a/ld/NEWS b/ld/NEWS
index cb2d428..8701c5c 100644 (file)
--- 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
index 57996a7..d03c432 100644 (file)
@@ -1,3 +1,8 @@
+2012-06-22  Roland McGrath  <mcgrathr@google.com>
+
+       * ld-elf/ehdr_start.s: New file.
+       * ld-elf/ehdr_start.d: New file.
+
 2012-06-21  Alan Modra  <amodra@gmail.com>
 
        * 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 (file)
index 0000000..3965eeb
--- /dev/null
@@ -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 (file)
index 0000000..ab029dc
--- /dev/null
@@ -0,0 +1,10 @@
+       .text
+       .globl _start
+_start:
+       .space 16
+
+       .section .rodata,"a",%progbits
+       .globl foo
+foo:
+       .weak __ehdr_start
+       .dc.a __ehdr_start