summaryrefslogtreecommitdiff
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)
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;