aboutsummaryrefslogtreecommitdiff
path: root/elf/rtld.c
diff options
context:
space:
mode:
Diffstat (limited to 'elf/rtld.c')
-rw-r--r--elf/rtld.c193
1 files changed, 98 insertions, 95 deletions
diff --git a/elf/rtld.c b/elf/rtld.c
index 44fbf3e53a..e74da5438c 100644
--- a/elf/rtld.c
+++ b/elf/rtld.c
@@ -146,6 +146,104 @@ RTLD_START
# error "sysdeps/MACHINE/dl-machine.h fails to define RTLD_START"
#endif
+#ifndef VALIDX
+# define VALIDX(tag) (DT_NUM + DT_THISPROCNUM + DT_VERSIONTAGNUM \
+ + DT_EXTRANUM + DT_VALTAGIDX (tag))
+#endif
+#ifndef ADDRIDX
+# define ADDRIDX(tag) (DT_NUM + DT_THISPROCNUM + DT_VERSIONTAGNUM \
+ + DT_EXTRANUM + DT_VALNUM + DT_ADDRTAGIDX (tag))
+#endif
+
+/* This is the second half of _dl_start (below). It can be inlined safely
+ under DONT_USE_BOOTSTRAP_MAP, where it is careful not to make any GOT
+ references. When the tools don't permit us to avoid using a GOT entry
+ for _dl_rtld_global (no attribute_hidden support), we must make sure
+ this function is not inlined (see below). */
+
+#ifdef DONT_USE_BOOTSTRAP_MAP
+static inline ElfW(Addr) __attribute__ ((always_inline))
+_dl_start_final (void *arg)
+#else
+static ElfW(Addr) __attribute__ ((noinline))
+_dl_start_final (void *arg, struct link_map *bootstrap_map_p)
+#endif
+{
+ ElfW(Addr) start_addr;
+ extern char _begin[] attribute_hidden;
+ extern char _end[] attribute_hidden;
+
+ if (HP_TIMING_AVAIL)
+ {
+ /* If it hasn't happen yet record the startup time. */
+ if (! HP_TIMING_INLINE)
+ HP_TIMING_NOW (start_time);
+
+ /* Initialize the timing functions. */
+ HP_TIMING_DIFF_INIT ();
+ }
+
+ /* Transfer data about ourselves to the permanent link_map structure. */
+#ifndef DONT_USE_BOOTSTRAP_MAP
+ GL(dl_rtld_map).l_addr = bootstrap_map_p->l_addr;
+ GL(dl_rtld_map).l_ld = bootstrap_map_p->l_ld;
+ memcpy (GL(dl_rtld_map).l_info, bootstrap_map_p->l_info,
+ sizeof GL(dl_rtld_map).l_info);
+ GL(dl_rtld_map).l_mach = bootstrap_map_p->l_mach;
+#endif
+ _dl_setup_hash (&GL(dl_rtld_map));
+ GL(dl_rtld_map).l_opencount = 1;
+ GL(dl_rtld_map).l_map_start = (ElfW(Addr)) _begin;
+ GL(dl_rtld_map).l_map_end = (ElfW(Addr)) _end;
+ /* Copy the TLS related data if necessary. */
+#if USE_TLS && !defined DONT_USE_BOOTSTRAP_MAP
+# ifdef HAVE___THREAD
+ assert (bootstrap_map_p->l_tls_modid != 0);
+# else
+ if (bootstrap_map_p->l_tls_modid != 0)
+# endif
+ {
+ GL(dl_rtld_map).l_tls_blocksize = bootstrap_map_p->l_tls_blocksize;
+ GL(dl_rtld_map).l_tls_align = bootstrap_map_p->l_tls_align;
+ GL(dl_rtld_map).l_tls_initimage_size
+ = bootstrap_map_p->l_tls_initimage_size;
+ GL(dl_rtld_map).l_tls_initimage = bootstrap_map_p->l_tls_initimage;
+ GL(dl_rtld_map).l_tls_offset = bootstrap_map_p->l_tls_offset;
+ GL(dl_rtld_map).l_tls_modid = 1;
+ GL(dl_rtld_map).l_tls_tp_initialized
+ = bootstrap_map_p->l_tls_tp_initialized;
+ }
+#endif
+
+#if HP_TIMING_AVAIL
+ HP_TIMING_NOW (GL(dl_cpuclock_offset));
+#endif
+
+ /* Call the OS-dependent function to set up life so we can do things like
+ file access. It will call `dl_main' (below) to do all the real work
+ of the dynamic linker, and then unwind our frame and run the user
+ entry point on the same stack we entered on. */
+ start_addr = _dl_sysdep_start (arg, &dl_main);
+
+#ifndef HP_TIMING_NONAVAIL
+ if (HP_TIMING_AVAIL)
+ {
+ hp_timing_t end_time;
+
+ /* Get the current time. */
+ HP_TIMING_NOW (end_time);
+
+ /* Compute the difference. */
+ HP_TIMING_DIFF (rtld_total_time, start_time, end_time);
+ }
+#endif
+
+ if (__builtin_expect (GL(dl_debug_mask) & DL_DEBUG_STATISTICS, 0))
+ print_statistics ();
+
+ return start_addr;
+}
+
static ElfW(Addr) __attribute_used__ internal_function
_dl_start (void *arg)
{
@@ -343,101 +441,6 @@ _dl_start (void *arg)
}
-#ifndef VALIDX
-# define VALIDX(tag) (DT_NUM + DT_THISPROCNUM + DT_VERSIONTAGNUM \
- + DT_EXTRANUM + DT_VALTAGIDX (tag))
-#endif
-#ifndef ADDRIDX
-# define ADDRIDX(tag) (DT_NUM + DT_THISPROCNUM + DT_VERSIONTAGNUM \
- + DT_EXTRANUM + DT_VALNUM + DT_ADDRTAGIDX (tag))
-#endif
-
-#ifdef DONT_USE_BOOTSTRAP_MAP
-static ElfW(Addr)
-_dl_start_final (void *arg)
-#else
-static ElfW(Addr)
-_dl_start_final (void *arg, struct link_map *bootstrap_map_p)
-#endif
-{
- /* The use of `alloca' here looks ridiculous but it helps. The goal
- is to avoid the function from being inlined. There is no official
- way to do this so we use this trick. gcc never inlines functions
- which use `alloca'. */
- ElfW(Addr) *start_addr = alloca (sizeof (ElfW(Addr)));
- extern char _begin[] attribute_hidden;
- extern char _end[] attribute_hidden;
-
- if (HP_TIMING_AVAIL)
- {
- /* If it hasn't happen yet record the startup time. */
- if (! HP_TIMING_INLINE)
- HP_TIMING_NOW (start_time);
-
- /* Initialize the timing functions. */
- HP_TIMING_DIFF_INIT ();
- }
-
- /* Transfer data about ourselves to the permanent link_map structure. */
-#ifndef DONT_USE_BOOTSTRAP_MAP
- GL(dl_rtld_map).l_addr = bootstrap_map_p->l_addr;
- GL(dl_rtld_map).l_ld = bootstrap_map_p->l_ld;
- memcpy (GL(dl_rtld_map).l_info, bootstrap_map_p->l_info,
- sizeof GL(dl_rtld_map).l_info);
- GL(dl_rtld_map).l_mach = bootstrap_map_p->l_mach;
-#endif
- _dl_setup_hash (&GL(dl_rtld_map));
- GL(dl_rtld_map).l_opencount = 1;
- GL(dl_rtld_map).l_map_start = (ElfW(Addr)) _begin;
- GL(dl_rtld_map).l_map_end = (ElfW(Addr)) _end;
- /* Copy the TLS related data if necessary. */
-#if USE_TLS && !defined DONT_USE_BOOTSTRAP_MAP
-# ifdef HAVE___THREAD
- assert (bootstrap_map_p->l_tls_modid != 0);
-# else
- if (bootstrap_map_p->l_tls_modid != 0)
-# endif
- {
- GL(dl_rtld_map).l_tls_blocksize = bootstrap_map_p->l_tls_blocksize;
- GL(dl_rtld_map).l_tls_align = bootstrap_map_p->l_tls_align;
- GL(dl_rtld_map).l_tls_initimage_size
- = bootstrap_map_p->l_tls_initimage_size;
- GL(dl_rtld_map).l_tls_initimage = bootstrap_map_p->l_tls_initimage;
- GL(dl_rtld_map).l_tls_offset = bootstrap_map_p->l_tls_offset;
- GL(dl_rtld_map).l_tls_modid = 1;
- GL(dl_rtld_map).l_tls_tp_initialized
- = bootstrap_map_p->l_tls_tp_initialized;
- }
-#endif
-
-#if HP_TIMING_AVAIL
- HP_TIMING_NOW (GL(dl_cpuclock_offset));
-#endif
-
- /* Call the OS-dependent function to set up life so we can do things like
- file access. It will call `dl_main' (below) to do all the real work
- of the dynamic linker, and then unwind our frame and run the user
- entry point on the same stack we entered on. */
- *start_addr = _dl_sysdep_start (arg, &dl_main);
-
-#ifndef HP_TIMING_NONAVAIL
- if (HP_TIMING_AVAIL)
- {
- hp_timing_t end_time;
-
- /* Get the current time. */
- HP_TIMING_NOW (end_time);
-
- /* Compute the difference. */
- HP_TIMING_DIFF (rtld_total_time, start_time, end_time);
- }
-#endif
-
- if (__builtin_expect (GL(dl_debug_mask) & DL_DEBUG_STATISTICS, 0))
- print_statistics ();
-
- return *start_addr;
-}
/* Now life is peachy; we can do all normal operations.
On to the real work. */