about summary refs log tree commit diff
path: root/elf
diff options
context:
space:
mode:
authorRoland McGrath <roland@hack.frob.com>2014-03-13 10:38:27 -0700
committerRoland McGrath <roland@hack.frob.com>2014-03-13 10:38:27 -0700
commit44c4e5d598bfcbb309f05ceb7a57ab02662e7f34 (patch)
tree93cbc5ad24779ff1ecd1f644615aa2017ed94307 /elf
parent041a92472e6db60b42cf2db229382fc3482304b9 (diff)
downloadglibc-44c4e5d598bfcbb309f05ceb7a57ab02662e7f34.tar.gz
glibc-44c4e5d598bfcbb309f05ceb7a57ab02662e7f34.tar.xz
glibc-44c4e5d598bfcbb309f05ceb7a57ab02662e7f34.zip
Use __ehdr_start, when available, for rtld to get its own headers.
Diffstat (limited to 'elf')
-rw-r--r--elf/rtld.c23
1 files changed, 19 insertions, 4 deletions
diff --git a/elf/rtld.c b/elf/rtld.c
index 63e92d3006..9d121dc8f5 100644
--- a/elf/rtld.c
+++ b/elf/rtld.c
@@ -1371,10 +1371,25 @@ of this helper program; chances are you did not intend to run this program.\n\
     GLRO(dl_use_load_bias) = main_map->l_addr == 0 ? -1 : 0;
 
   /* Set up the program header information for the dynamic linker
-     itself.  It is needed in the dl_iterate_phdr() callbacks.  */
-  ElfW(Ehdr) *rtld_ehdr = (ElfW(Ehdr) *) GL(dl_rtld_map).l_map_start;
-  ElfW(Phdr) *rtld_phdr = (ElfW(Phdr) *) (GL(dl_rtld_map).l_map_start
-					  + rtld_ehdr->e_phoff);
+     itself.  It is needed in the dl_iterate_phdr callbacks.  */
+  const ElfW(Ehdr) *rtld_ehdr;
+
+  /* Starting from binutils-2.23, the linker will define the magic symbol
+     __ehdr_start to point to our own ELF header if it is visible in a
+     segment that also includes the phdrs.  If that's not available, we use
+     the old method that assumes the beginning of the file is part of the
+     lowest-addressed PT_LOAD segment.  */
+#ifdef HAVE_EHDR_START
+  extern const ElfW(Ehdr) __ehdr_start __attribute__ ((visibility ("hidden")));
+  rtld_ehdr = &__ehdr_start;
+#else
+  rtld_ehdr = (void *) GL(dl_rtld_map).l_map_start;
+#endif
+  assert (rtld_ehdr->e_ehsize == sizeof *rtld_ehdr);
+  assert (rtld_ehdr->e_phentsize == sizeof (ElfW(Phdr)));
+
+  const ElfW(Phdr) *rtld_phdr = (const void *) rtld_ehdr + rtld_ehdr->e_phoff;
+
   GL(dl_rtld_map).l_phdr = rtld_phdr;
   GL(dl_rtld_map).l_phnum = rtld_ehdr->e_phnum;