diff options
author | Thomas Schwinge <thomas@codesourcery.com> | 2012-11-01 01:45:53 +0100 |
---|---|---|
committer | Thomas Schwinge <thomas@codesourcery.com> | 2012-11-01 01:45:53 +0100 |
commit | cefc074b32d1eed87b2b96c8943d7f1864a5bb15 (patch) | |
tree | 1f43da63f9bae90772538a6c5b051e34983a22e7 /csu | |
parent | 0ce6f3added7475bfd0f2f551c6c97baccde6da5 (diff) | |
parent | 343dc156c34702751b3cc63736caa0649c59421a (diff) |
Merge branch 'baseline' into refs/top-bases/tschwinge/Roger_Whittaker
Diffstat (limited to 'csu')
-rw-r--r-- | csu/elf-init.c | 45 | ||||
-rw-r--r-- | csu/init-first.c | 89 | ||||
-rw-r--r-- | csu/libc-start.c | 39 | ||||
-rw-r--r-- | csu/libc-tls.c | 20 |
4 files changed, 119 insertions, 74 deletions
diff --git a/csu/elf-init.c b/csu/elf-init.c index 91ba74ce55..8b4431ba0c 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/init-first.c b/csu/init-first.c index 050959dcb2..0cfabbce28 100644 --- a/csu/init-first.c +++ b/csu/init-first.c @@ -1,4 +1,4 @@ -/* Initialization code run first thing by the ELF startup code. Stub version. +/* Initialization code run first thing by the ELF startup code. Common version Copyright (C) 1995-2012 Free Software Foundation, Inc. This file is part of the GNU C Library. @@ -17,40 +17,76 @@ <http://www.gnu.org/licenses/>. */ #include <ctype.h> +#include <stdio.h> +#include <stdlib.h> +#include <fcntl.h> #include <unistd.h> +#include <sysdep.h> +#include <fpu_control.h> +#include <sys/param.h> #include <sys/types.h> +#include <libc-internal.h> + +#include <ldsodefs.h> /* Set nonzero if we have to be prepared for more then one libc being used in the process. Safe assumption if initializer never runs. */ int __libc_multiple_libcs attribute_hidden = 1; -extern void __libc_init (int, char **, char **); -#ifdef USE_NONOPTION_FLAGS -extern void __getopt_clean_environment (char **); -#endif +/* Remember the command line argument and enviroment contents for + later calls of initializers for dynamic libraries. */ +int __libc_argc attribute_hidden; +char **__libc_argv attribute_hidden; + -#ifdef SHARED void -__libc_init_first (void) +__libc_init_first (int argc, char **argv, char **envp) { +#ifdef SHARED + /* For DSOs we do not need __libc_init_first but instead _init. */ } + +void +attribute_hidden +_init (int argc, char **argv, char **envp) +{ +#endif +#ifdef USE_NONOPTION_FLAGS + extern void __getopt_clean_environment (char **); #endif + __libc_multiple_libcs = &_dl_starting_up && !_dl_starting_up; + + /* Make sure we don't initialize twice. */ + if (!__libc_multiple_libcs) + { + /* Set the FPU control word to the proper default value if the + kernel would use a different value. (In a static program we + don't have this information.) */ #ifdef SHARED -/* NOTE! The linker notices the magical name `_init' and sets the DT_INIT - pointer in the dynamic section based solely on that. It is convention - for this function to be in the `.init' section, but the symbol name is - the only thing that really matters!! */ -void _init -#else -void __libc_init_first + if (__fpu_control != GLRO(dl_fpu_control)) #endif -(int argc, char *arg0, ...) -{ - char **argv = &arg0, **envp = &argv[argc + 1]; + __setfpucw (__fpu_control); + } + /* Save the command-line arguments. */ + __libc_argc = argc; + __libc_argv = argv; __environ = envp; - __libc_init (argc, argv, envp); + +#ifndef SHARED + __libc_init_secure (); + + /* First the initialization which normally would be done by the + dynamic linker. */ + _dl_non_dynamic_init (); +#endif + +#ifdef VDSO_SETUP + VDSO_SETUP (); +#endif + + __init_misc (argc, argv, envp); #ifdef USE_NONOPTION_FLAGS /* This is a hack to make the special getopt in GNU libc working. */ @@ -59,4 +95,21 @@ void __libc_init_first /* Initialize ctype data. */ __ctype_init (); + +#if defined SHARED && !defined NO_CTORS_DTORS_SECTIONS + __libc_global_ctors (); +#endif +} + +/* This function is defined here so that if this file ever gets into + ld.so we will get a link error. Having this file silently included + in ld.so causes disaster, because the _init definition above will + cause ld.so to gain an init function, which is not a cool thing. */ + +extern void _dl_start (void) __attribute__ ((noreturn)); + +void +_dl_start (void) +{ + abort (); } diff --git a/csu/libc-start.c b/csu/libc-start.c index dcf2bac0e6..c15d3b790c 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,39 @@ 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 + +static void +apply_irel (void) +{ +# ifdef IREL + /* 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)); + for (const IREL_T *ipltent = IPLT_START; ipltent < IPLT_END; ++ipltent) + IREL (ipltent); +# endif +} +#endif + + #ifdef LIBC_START_MAIN # ifdef LIBC_START_DISABLE_INLINE # define STATIC static @@ -136,8 +169,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 (); #ifndef __GNU__ /* Initialize the thread library at least a bit since the libgcc diff --git a/csu/libc-tls.c b/csu/libc-tls.c index b00a5ccb9d..6c52262bab 100644 --- a/csu/libc-tls.c +++ b/csu/libc-tls.c @@ -1,5 +1,5 @@ /* Initialization code for TLS in statically linked application. - Copyright (C) 2002-2006, 2009 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 @@ -32,7 +32,7 @@ extern ElfW(Phdr) *_dl_phdr; extern size_t _dl_phnum; -static dtv_t static_dtv[2 + TLS_SLOTINFO_SURPLUS]; +dtv_t _dl_static_dtv[2 + TLS_SLOTINFO_SURPLUS]; static struct @@ -163,33 +163,33 @@ __libc_setup_tls (size_t tcbsize, size_t tcbalign) & ~(max_align - 1)); /* Initialize the dtv. [0] is the length, [1] the generation counter. */ - static_dtv[0].counter = (sizeof (static_dtv) / sizeof (static_dtv[0])) - 2; - // static_dtv[1].counter = 0; would be needed if not already done + _dl_static_dtv[0].counter = (sizeof (_dl_static_dtv) / sizeof (_dl_static_dtv[0])) - 2; + // _dl_static_dtv[1].counter = 0; would be needed if not already done /* Initialize the TLS block. */ #if TLS_TCB_AT_TP - static_dtv[2].pointer.val = ((char *) tlsblock + tcb_offset + _dl_static_dtv[2].pointer.val = ((char *) tlsblock + tcb_offset - roundup (memsz, align ?: 1)); static_map.l_tls_offset = roundup (memsz, align ?: 1); #elif TLS_DTV_AT_TP - static_dtv[2].pointer.val = (char *) tlsblock + tcb_offset; + _dl_static_dtv[2].pointer.val = (char *) tlsblock + tcb_offset; static_map.l_tls_offset = tcb_offset; #else # error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined" #endif - static_dtv[2].pointer.is_static = true; + _dl_static_dtv[2].pointer.is_static = true; /* sbrk gives us zero'd memory, so we don't need to clear the remainder. */ - memcpy (static_dtv[2].pointer.val, initimage, filesz); + memcpy (_dl_static_dtv[2].pointer.val, initimage, filesz); /* Install the pointer to the dtv. */ /* Initialize the thread pointer. */ #if TLS_TCB_AT_TP - INSTALL_DTV ((char *) tlsblock + tcb_offset, static_dtv); + INSTALL_DTV ((char *) tlsblock + tcb_offset, _dl_static_dtv); const char *lossage = TLS_INIT_TP ((char *) tlsblock + tcb_offset, 0); #elif TLS_DTV_AT_TP - INSTALL_DTV (tlsblock, static_dtv); + INSTALL_DTV (tlsblock, _dl_static_dtv); const char *lossage = TLS_INIT_TP (tlsblock, 0); #else # error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined" |