diff options
| -rw-r--r-- | libc/misc/internals/__uClibc_main.c | 45 | 
1 files changed, 45 insertions, 0 deletions
diff --git a/libc/misc/internals/__uClibc_main.c b/libc/misc/internals/__uClibc_main.c index d80565e2c..d8286f20b 100644 --- a/libc/misc/internals/__uClibc_main.c +++ b/libc/misc/internals/__uClibc_main.c @@ -48,6 +48,39 @@  int _pe_secure = 0;  libc_hidden_data_def(_pe_secure) +#if !defined(SHARED) && defined(__FDPIC__) +struct funcdesc_value +{ +	void *entry_point; +	void *got_value; +} __attribute__((__aligned__(8))); + + +/* Prevent compiler optimization that removes GOT assignment. + +  Due to optimization passes (block split and move), in the rare case +  where use r9 is the single instruction in a block we can have the +  following behaviour: +  - this block is marked as a forward block since use is not +  considered as an active instruction after reload pass. + +  - In this case a jump in this block can be moved to the start of the +  next one and so remove use in this flow of instructions which can +  lead to a removal of r9 restoration after a call. */ +#define _dl_stabilize_funcdesc(val)			\ +	({ __asm__ ("" : "+m" (*(val))); (val); }) + +static void fdpic_init_array_jump(void *addr) +{ +	struct funcdesc_value *fm = (struct funcdesc_value *) fdpic_init_array_jump; +	struct funcdesc_value fd = {addr, fm->got_value}; + +	void (*pf)(void) = (void*) _dl_stabilize_funcdesc(&fd); + +	(*pf)(); +} +#endif +  #ifndef SHARED  void *__libc_stack_end = NULL; @@ -307,7 +340,11 @@ void __uClibc_fini(void)  # elif !defined (__UCLIBC_FORMAT_SHARED_FLAT__)      size_t i = __fini_array_end - __fini_array_start;      while (i-- > 0) +#if !defined(SHARED) && defined(__FDPIC__) +	fdpic_init_array_jump(__fini_array_start[i]); +#else  	(*__fini_array_start [i]) (); +#endif  # endif      if (__app_fini != NULL)  	(__app_fini)(); @@ -436,7 +473,11 @@ void __uClibc_main(int (*main)(int, char **, char **), int argc,  	const size_t size = __preinit_array_end - __preinit_array_start;  	size_t i;  	for (i = 0; i < size; i++) +#if !defined(SHARED) && defined(__FDPIC__) +	    fdpic_init_array_jump(__preinit_array_start[i]); +#else  	    (*__preinit_array_start [i]) (); +#endif      }  # endif      /* Run all the application's ctors now.  */ @@ -452,7 +493,11 @@ void __uClibc_main(int (*main)(int, char **, char **), int argc,  	const size_t size = __init_array_end - __init_array_start;  	size_t i;  	for (i = 0; i < size; i++) +#if !defined(SHARED) && defined(__FDPIC__) +	    fdpic_init_array_jump(__init_array_start[i]); +#else  	    (*__init_array_start [i]) (); +#endif      }  # endif  #endif  | 
