summary refs log tree commit diff
diff options
context:
space:
mode:
authorRoland McGrath <roland@gnu.org>2002-08-22 00:09:26 +0000
committerRoland McGrath <roland@gnu.org>2002-08-22 00:09:26 +0000
commitc2248c44e4eec619d2cf53d01fef544dd2624d96 (patch)
treeaf0b927c0eb5b76b313fa915c9195020fea5241a
parent6a9340b515bd4b834abe3343e6473cff400ad147 (diff)
downloadglibc-c2248c44e4eec619d2cf53d01fef544dd2624d96.tar.gz
glibc-c2248c44e4eec619d2cf53d01fef544dd2624d96.tar.xz
glibc-c2248c44e4eec619d2cf53d01fef544dd2624d96.zip
2002-08-21 Roland McGrath <roland@redhat.com>
	* elf/rtld.c (_dl_start_final): Move defn before _dl_start so it can
	be inlined.  Declare it with always_inline if [DONT_USE_BOOTSTRAP_MAP]
	and with noinline otherwise.  Remove hack alloca use to prevent
	inlining, we can ask for it explicitly nowadays.
-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.  */