This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH] ld: provide __ehdr_start magic symbol


On Wed, Jun 20, 2012 at 7:12 PM, Alan Modra <amodra@gmail.com> wrote:
> "we don't test for undefweak" was correct, but not the conclusion that
> undef weaks stay undefined. ?What happens is that
> bfd_record_link_assignment gets in first and flips
> bfd_link_hash_undefweak to bfd_link_hash_new.. ?So I suppose it
> doesn't really matter that your code differs from the ldexp.c code.

I don't understand the phases of the linker enough to know why it matters
differently here than there.  But removing the undefweak test from the
condition I added makes it fail to define __ehdr_start for a weak
reference, so I'm leaving it in.

>> Do you really mean
>> that it should use a section-relative symbol with a value outside the section?
>
> Yes.

I think this notion is quite misguided, but that issue is entirely separate
from what this change is about.  So I'm happy to make my change comport
with the new norm you've established, departure though it is from prior
behavior and specifications.  I'll discuss the section-vs-absolute issue in
a separate thread.


Is this version OK to commit?


Thanks,
Roland


bfd/
2012-06-21  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.

ld/
2012-06-21  Roland McGrath  <mcgrathr@google.com>

	* NEWS: Mention __ehdr_start.

ld/testsuite/
2012-06-21  Roland McGrath  <mcgrathr@google.com>

	* ld-elf/ehdr_start.s: New file.
	* ld-elf/ehdr_start.d: New file.

diff --git a/bfd/elf.c b/bfd/elf.c
index 0296ef5..172782a 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,66 @@ 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))
+	{
+	  /* The headers never sit inside any section, so this is really a
+	     case for which an absolute symbol (SHN_ABS) is appropriate.
+	     But the norm for linker-provided symbols now is that they are
+	     associated with some section, even if the address is outside
+	     the bounds of that section.  So pick an arbitrary section to
+	     associate this symbol with.  */
+
+	  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/NEWS b/ld/NEWS
index cb2d428..8701c5c 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.
diff --git a/ld/testsuite/ld-elf/ehdr_start.d b/ld/testsuite/ld-elf/ehdr_start.d
new file mode 100644
index 0000000..3965eeb
--- /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 0000000..2086801
--- /dev/null
+++ b/ld/testsuite/ld-elf/ehdr_start.s
@@ -0,0 +1,9 @@
+	.text
+	.globl _start
+_start:
+	.space 16
+
+	.section .rodata,"a",%progbits
+	.globl foo
+foo:
+	.dc.a __ehdr_start


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]