diff options
-rw-r--r-- | ChangeLog | 6 | ||||
-rw-r--r-- | csu/libc-start.c | 18 | ||||
-rw-r--r-- | sysdeps/mach/hurd/i386/init-first.c | 22 |
3 files changed, 38 insertions, 8 deletions
@@ -1,5 +1,11 @@ 2013-03-28 Roland McGrath <roland@hack.frob.com> + * csu/libc-start.c (__libc_start_main) [!SHARED]: If _dl_aux_init + didn't do it already, then set _dl_phdr and _dl_phnum based on the + magic __ehdr_start linker symbol if it's defined. + * sysdeps/mach/hurd/i386/init-first.c (init1) [!SHARED]: Don't set + them up here if it was already done. + * elf/dl-support.c (_dl_phdr): Make pointer to const. (_dl_aux_init): Use const in cast when setting it. * sysdeps/mach/hurd/i386/init-first.c (init1): Remove superfluous cast. diff --git a/csu/libc-start.c b/csu/libc-start.c index 9c4c01d..fa9085c 100644 --- a/csu/libc-start.c +++ b/csu/libc-start.c @@ -15,6 +15,7 @@ License along with the GNU C Library; if not, see <http://www.gnu.org/licenses/>. */ +#include <assert.h> #include <stdlib.h> #include <stdio.h> #include <unistd.h> @@ -151,7 +152,24 @@ LIBC_START_MAIN (int (*main) (int, char **, char ** MAIN_AUXVEC_DECL), } # endif _dl_aux_init (auxvec); + if (GL(dl_phdr) == NULL) # endif + { + /* 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. + So we can set up _dl_phdr and _dl_phnum even without any + information from auxv. */ + + extern const ElfW(Ehdr) __ehdr_start __attribute__ ((weak)); + if (&__ehdr_start != NULL) + { + assert (__ehdr_start.e_phentsize == sizeof *GL(dl_phdr)); + GL(dl_phdr) = (const void *) &__ehdr_start + __ehdr_start.e_phoff; + GL(dl_phnum) = __ehdr_start.e_phnum; + } + } + # ifdef DL_SYSDEP_OSCHECK if (!__libc_multiple_libcs) { diff --git a/sysdeps/mach/hurd/i386/init-first.c b/sysdeps/mach/hurd/i386/init-first.c index 59253db..fc3330c 100644 --- a/sysdeps/mach/hurd/i386/init-first.c +++ b/sysdeps/mach/hurd/i386/init-first.c @@ -117,14 +117,20 @@ init1 (int argc, char *arg0, ...) if ((void *) d == argv[0]) { #ifndef SHARED - /* We may need to see our own phdrs, e.g. for TLS setup. - Try the usual kludge to find the headers without help from - the exec server. */ - extern const void _start; - const ElfW(Ehdr) *const ehdr = &_start; - _dl_phdr = (const void *) ehdr + ehdr->e_phoff; - _dl_phnum = ehdr->e_phnum; - assert (ehdr->e_phentsize == sizeof (ElfW(Phdr))); + /* With a new enough linker (binutils-2.23 or better), + the magic __ehdr_start symbol will be available and + __libc_start_main will have done this that way already. */ + if (_dl_phdr == NULL) + { + /* We may need to see our own phdrs, e.g. for TLS setup. + Try the usual kludge to find the headers without help from + the exec server. */ + extern const void _start; + const ElfW(Ehdr) *const ehdr = &_start; + _dl_phdr = (const void *) ehdr + ehdr->e_phoff; + _dl_phnum = ehdr->e_phnum; + assert (ehdr->e_phentsize == sizeof (ElfW(Phdr))); + } #endif return; } |