This is the mail archive of the libc-alpha@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[COMMITTED PATCH] Support static IFUNC calls irrespective of USE_MULTIARCH.


The library support for running IFUNC selectors at startup in a
statically-linked program should not depend on whether libc itself
is using IFUNCs for multi-arch.  There was also no reason for this
code to be split out into a global function in csu/elf-init.c, so I
moved it into a static in the file where it's called, so it can be
inlined.

The only material change here is that __rel{,a}_iplt_{start,end} are
now referenced weakly, in case someone is doing static linking with
an older linker.  If someone is doing that with a libc that actually
includes multi-arch functions (and the call chain from their program
uses them), then things will break badly.  If we're concerned about
that, we could make the weakness conditional on [!USE_MULTIARCH].
But we don't want to break someone using an older linker to build
their statically-linked programs when no IFUNCs happen to be involved.

Build-tested on x86_64-linux-gnu and eyeballed the statically-linked
ldconfig for correctness.


Thanks,
Roland


2012-08-21  Roland McGrath  <roland@hack.frob.com>

	* csu/elf-init.c (__libc_csu_irel): Function removed.
	* csu/libc-start.c (apply_irel): New function.
	(LIBC_START_MAIN): Call it instead of __libc_csu_irel.

diff --git a/csu/elf-init.c b/csu/elf-init.c
index 91ba74c..8b4431b 100644
--- a/csu/elf-init.c
+++ b/csu/elf-init.c
@@ -1,6 +1,5 @@
 /* Startup support for ELF initializers/finalizers in the main executable.
-   Copyright (C) 2002,2003,2004,2005,2009,2011
-	Free Software Foundation, Inc.
+   Copyright (C) 2002-2012 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -36,20 +35,6 @@
 
 #include <stddef.h>
 
-#if defined USE_MULTIARCH && !defined LIBC_NONSHARED
-# include <link.h>
-# include <dl-irel.h>
-
-# ifdef ELF_MACHINE_IRELA
-extern const ElfW(Rela) __rela_iplt_start [];
-extern const ElfW(Rela) __rela_iplt_end [];
-# endif
-
-# ifdef ELF_MACHINE_IREL
-extern const ElfW(Rel) __rel_iplt_start [];
-extern const ElfW(Rel) __rel_iplt_end [];
-# endif
-#endif	/* LIBC_NONSHARED */
 
 /* These magic symbols are provided by the linker.  */
 extern void (*__preinit_array_start []) (int, char **, char **)
@@ -72,33 +57,7 @@ extern void _fini (void);
 /* These functions are passed to __libc_start_main by the startup code.
    These get statically linked into each program.  For dynamically linked
    programs, this module will come from libc_nonshared.a and differs from
-   the libc.a module in that it doesn't call the preinit array and performs
-   explicit IREL{,A} relocations.  */
-
-
-#ifndef LIBC_NONSHARED
-void
-__libc_csu_irel (void)
-{
-# ifdef USE_MULTIARCH
-#  ifdef ELF_MACHINE_IRELA
-  {
-    const size_t size = __rela_iplt_end - __rela_iplt_start;
-    for (size_t i = 0; i < size; i++)
-      elf_irela (&__rela_iplt_start [i]);
-  }
-#  endif
-
-#  ifdef ELF_MACHINE_IREL
-  {
-    const size_t size = __rel_iplt_end - __rel_iplt_start;
-    for (size_t i = 0; i < size; i++)
-      elf_irel (&__rel_iplt_start [i]);
-  }
-#  endif
-# endif
-}
-#endif
+   the libc.a module in that it doesn't call the preinit array.  */
 
 
 void
diff --git a/csu/libc-start.c b/csu/libc-start.c
index 0f9bfd7..7e541d4 100644
--- a/csu/libc-start.c
+++ b/csu/libc-start.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1998-2006, 2007, 2009 Free Software Foundation, Inc.
+/* Copyright (C) 1998-2012 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -46,6 +46,38 @@ uintptr_t __stack_chk_guard attribute_relro;
 #endif
 
 
+#ifndef SHARED
+# include <link.h>
+# include <dl-irel.h>
+
+# ifdef ELF_MACHINE_IRELA
+#  define IREL_T	ElfW(Rela)
+#  define IPLT_START	__rela_iplt_start
+#  define IPLT_END	__rela_iplt_end
+#  define IREL		elf_irela
+# elif defined ELF_MACHINE_IREL
+#  define IREL_T	ElfW(Rel)
+#  define IPLT_START	__rel_iplt_start
+#  define IPLT_END	__rel_iplt_end
+#  define IREL		elf_irel
+# endif
+
+/* We use weak references for these so that we'll still work with a linker
+   that doesn't define them.  Such a linker doesn't support IFUNC at all
+   and so uses won't work, but a statically-linked program that doesn't
+   use any IFUNC symbols won't have a problem.  */
+extern const IREL_T IPLT_START[] __attribute__ ((weak));
+extern const IREL_T IPLT_END[] __attribute__ ((weak));
+
+static void
+apply_irel (void)
+{
+  for (const IREL_T *ipltent = IPLT_START; ipltent < IPLT_END; ++ipltent)
+    IREL (ipltent);
+}
+#endif
+
+
 #ifdef LIBC_START_MAIN
 # ifdef LIBC_START_DISABLE_INLINE
 #  define STATIC static
@@ -136,8 +168,8 @@ LIBC_START_MAIN (int (*main) (int, char **, char ** MAIN_AUXVEC_DECL),
     }
 # endif
 
-  /* Performe IREL{,A} relocations.  */
-  __libc_csu_irel ();
+  /* Perform IREL{,A} relocations.  */
+  apply_irel ();
 
   /* Initialize the thread library at least a bit since the libgcc
      functions are using thread functions if these are available and


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]