diff options
author | Joonas Kylmälä <joonas.kylmala@iki.fi> | 2018-08-27 14:09:09 -0400 |
---|---|---|
committer | Joonas Kylmälä <joonas.kylmala@iki.fi> | 2018-08-27 14:09:09 -0400 |
commit | 989f332ea4e1ac952625139fbd7c18e8a8b31c8a (patch) | |
tree | 28f03931fa1c2148a015d59d9855bf976231101a /gcc-4.9/libgcc | |
parent | b0c259403b7b74b55fc93f50fd1f2fbae3510ece (diff) | |
parent | a74813a825e49267faa0b2ba45e9cd4bd6ccf4f4 (diff) | |
download | toolchain_gcc-replicant-6.0-0004-rc1.tar.gz toolchain_gcc-replicant-6.0-0004-rc1.tar.bz2 toolchain_gcc-replicant-6.0-0004-rc1.zip |
Merge remote-tracking branch 'aosp/master' into replicant-6.0HEADreplicant-6.0-0004-transitionreplicant-6.0-0004-rc6replicant-6.0-0004-rc5-transitionreplicant-6.0-0004-rc5replicant-6.0-0004-rc4replicant-6.0-0004-rc3replicant-6.0-0004-rc2replicant-6.0-0004-rc1replicant-6.0-0004replicant-6.0master
Diffstat (limited to 'gcc-4.9/libgcc')
-rw-r--r-- | gcc-4.9/libgcc/config/aarch64/linux-unwind.h | 2 | ||||
-rw-r--r-- | gcc-4.9/libgcc/config/alpha/linux-unwind.h | 2 | ||||
-rw-r--r-- | gcc-4.9/libgcc/config/bfin/linux-unwind.h | 2 | ||||
-rw-r--r-- | gcc-4.9/libgcc/config/i386/linux-unwind.h | 4 | ||||
-rw-r--r-- | gcc-4.9/libgcc/config/m68k/linux-unwind.h | 2 | ||||
-rw-r--r-- | gcc-4.9/libgcc/config/nios2/linux-unwind.h | 2 | ||||
-rw-r--r-- | gcc-4.9/libgcc/config/pa/linux-unwind.h | 2 | ||||
-rw-r--r-- | gcc-4.9/libgcc/config/sh/linux-unwind.h | 2 | ||||
-rw-r--r-- | gcc-4.9/libgcc/config/tilepro/linux-unwind.h | 2 | ||||
-rw-r--r-- | gcc-4.9/libgcc/config/xtensa/linux-unwind.h | 2 | ||||
-rw-r--r-- | gcc-4.9/libgcc/emutls.c | 62 | ||||
-rw-r--r-- | gcc-4.9/libgcc/unwind-dw2-fde-dip.c | 24 |
12 files changed, 89 insertions, 19 deletions
diff --git a/gcc-4.9/libgcc/config/aarch64/linux-unwind.h b/gcc-4.9/libgcc/config/aarch64/linux-unwind.h index 6b5b3cd1d..d13dc3482 100644 --- a/gcc-4.9/libgcc/config/aarch64/linux-unwind.h +++ b/gcc-4.9/libgcc/config/aarch64/linux-unwind.h @@ -52,7 +52,7 @@ aarch64_fallback_frame_state (struct _Unwind_Context *context, struct rt_sigframe { siginfo_t info; - struct ucontext uc; + ucontext_t uc; }; struct rt_sigframe *rt_; diff --git a/gcc-4.9/libgcc/config/alpha/linux-unwind.h b/gcc-4.9/libgcc/config/alpha/linux-unwind.h index b5bfd1c91..166d3d2cf 100644 --- a/gcc-4.9/libgcc/config/alpha/linux-unwind.h +++ b/gcc-4.9/libgcc/config/alpha/linux-unwind.h @@ -51,7 +51,7 @@ alpha_fallback_frame_state (struct _Unwind_Context *context, { struct rt_sigframe { siginfo_t info; - struct ucontext uc; + ucontext_t uc; } *rt_ = context->cfa; sc = &rt_->uc.uc_mcontext; } diff --git a/gcc-4.9/libgcc/config/bfin/linux-unwind.h b/gcc-4.9/libgcc/config/bfin/linux-unwind.h index dc58f0a81..8b94568bb 100644 --- a/gcc-4.9/libgcc/config/bfin/linux-unwind.h +++ b/gcc-4.9/libgcc/config/bfin/linux-unwind.h @@ -52,7 +52,7 @@ bfin_fallback_frame_state (struct _Unwind_Context *context, void *puc; char retcode[8]; siginfo_t info; - struct ucontext uc; + ucontext_t uc; } *rt_ = context->cfa; /* The void * cast is necessary to avoid an aliasing warning. diff --git a/gcc-4.9/libgcc/config/i386/linux-unwind.h b/gcc-4.9/libgcc/config/i386/linux-unwind.h index 7986928cf..a9d621c31 100644 --- a/gcc-4.9/libgcc/config/i386/linux-unwind.h +++ b/gcc-4.9/libgcc/config/i386/linux-unwind.h @@ -58,7 +58,7 @@ x86_64_fallback_frame_state (struct _Unwind_Context *context, if (*(unsigned char *)(pc+0) == 0x48 && *(unsigned long long *)(pc+1) == RT_SIGRETURN_SYSCALL) { - struct ucontext *uc_ = context->cfa; + ucontext_t *uc_ = context->cfa; /* The void * cast is necessary to avoid an aliasing warning. The aliasing warning is correct, but should not be a problem because it does not alias anything. */ @@ -138,7 +138,7 @@ x86_fallback_frame_state (struct _Unwind_Context *context, siginfo_t *pinfo; void *puc; siginfo_t info; - struct ucontext uc; + ucontext_t uc; } *rt_ = context->cfa; /* The void * cast is necessary to avoid an aliasing warning. The aliasing warning is correct, but should not be a problem diff --git a/gcc-4.9/libgcc/config/m68k/linux-unwind.h b/gcc-4.9/libgcc/config/m68k/linux-unwind.h index 1ba2a0c43..d67767e33 100644 --- a/gcc-4.9/libgcc/config/m68k/linux-unwind.h +++ b/gcc-4.9/libgcc/config/m68k/linux-unwind.h @@ -33,7 +33,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see /* <sys/ucontext.h> is unfortunately broken right now. */ struct uw_ucontext { unsigned long uc_flags; - struct ucontext *uc_link; + ucontext_t *uc_link; stack_t uc_stack; mcontext_t uc_mcontext; unsigned long uc_filler[80]; diff --git a/gcc-4.9/libgcc/config/nios2/linux-unwind.h b/gcc-4.9/libgcc/config/nios2/linux-unwind.h index ba4bd801d..897886852 100644 --- a/gcc-4.9/libgcc/config/nios2/linux-unwind.h +++ b/gcc-4.9/libgcc/config/nios2/linux-unwind.h @@ -38,7 +38,7 @@ struct nios2_mcontext { struct nios2_ucontext { unsigned long uc_flags; - struct ucontext *uc_link; + ucontext_t *uc_link; stack_t uc_stack; struct nios2_mcontext uc_mcontext; sigset_t uc_sigmask; /* mask last for extensibility */ diff --git a/gcc-4.9/libgcc/config/pa/linux-unwind.h b/gcc-4.9/libgcc/config/pa/linux-unwind.h index 4a3cfffd1..d2ac437a4 100644 --- a/gcc-4.9/libgcc/config/pa/linux-unwind.h +++ b/gcc-4.9/libgcc/config/pa/linux-unwind.h @@ -80,7 +80,7 @@ pa32_fallback_frame_state (struct _Unwind_Context *context, struct sigcontext *sc; struct rt_sigframe { siginfo_t info; - struct ucontext uc; + ucontext_t uc; } *frame; /* rt_sigreturn trampoline: diff --git a/gcc-4.9/libgcc/config/sh/linux-unwind.h b/gcc-4.9/libgcc/config/sh/linux-unwind.h index 4875706d4..671bde715 100644 --- a/gcc-4.9/libgcc/config/sh/linux-unwind.h +++ b/gcc-4.9/libgcc/config/sh/linux-unwind.h @@ -180,7 +180,7 @@ sh_fallback_frame_state (struct _Unwind_Context *context, { struct rt_sigframe { siginfo_t info; - struct ucontext uc; + ucontext_t uc; } *rt_ = context->cfa; /* The void * cast is necessary to avoid an aliasing warning. The aliasing warning is correct, but should not be a problem diff --git a/gcc-4.9/libgcc/config/tilepro/linux-unwind.h b/gcc-4.9/libgcc/config/tilepro/linux-unwind.h index 27481cfcd..c24d58c94 100644 --- a/gcc-4.9/libgcc/config/tilepro/linux-unwind.h +++ b/gcc-4.9/libgcc/config/tilepro/linux-unwind.h @@ -61,7 +61,7 @@ tile_fallback_frame_state (struct _Unwind_Context *context, struct rt_sigframe { unsigned char save_area[C_ABI_SAVE_AREA_SIZE]; siginfo_t info; - struct ucontext uc; + ucontext_t uc; } *rt_; /* Return if this is not a signal handler. */ diff --git a/gcc-4.9/libgcc/config/xtensa/linux-unwind.h b/gcc-4.9/libgcc/config/xtensa/linux-unwind.h index 6832d0b48..cb15b4c71 100644 --- a/gcc-4.9/libgcc/config/xtensa/linux-unwind.h +++ b/gcc-4.9/libgcc/config/xtensa/linux-unwind.h @@ -63,7 +63,7 @@ xtensa_fallback_frame_state (struct _Unwind_Context *context, struct rt_sigframe { siginfo_t info; - struct ucontext uc; + ucontext_t uc; } *rt_; /* movi a2, __NR_rt_sigreturn; syscall */ diff --git a/gcc-4.9/libgcc/emutls.c b/gcc-4.9/libgcc/emutls.c index fd6d86ed9..93c3c0788 100644 --- a/gcc-4.9/libgcc/emutls.c +++ b/gcc-4.9/libgcc/emutls.c @@ -30,6 +30,22 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see #include "libgcc_tm.h" #include "gthr.h" +#ifdef __BIONIC__ +/* There are 4 pthread key cleanup rounds on Bionic. Delay emutls deallocation + to round 2. We need to delay deallocation because: + - Android versions older than M lack __cxa_thread_atexit_impl, so apps + use a pthread key destructor to call C++ destructors. + - Apps might use __thread/thread_local variables in pthread destructors. + We can't wait until the final two rounds, because jemalloc needs two rounds + after the final malloc/free call to free its thread-specific data (see + https://reviews.llvm.org/D46978#1107507). Bugs: + - https://github.com/android-ndk/ndk/issues/687. + - http://b/16847284, http://b/78022094. */ +#define EMUTLS_SKIP_DESTRUCTOR_ROUNDS 1 +#else +#define EMUTLS_SKIP_DESTRUCTOR_ROUNDS 0 +#endif + typedef unsigned int word __attribute__((mode(word))); typedef unsigned int pointer __attribute__((mode(pointer))); @@ -46,6 +62,7 @@ struct __emutls_object struct __emutls_array { + pointer skip_destructor_rounds; pointer size; void **data[]; }; @@ -60,22 +77,37 @@ static __gthread_mutex_t emutls_mutex = __GTHREAD_MUTEX_INIT; static __gthread_mutex_t emutls_mutex; #endif static __gthread_key_t emutls_key; +static int emutls_key_created = 0; static pointer emutls_size; static void emutls_destroy (void *ptr) { struct __emutls_array *arr = ptr; - pointer size = arr->size; - pointer i; - for (i = 0; i < size; ++i) + /* emutls is deallocated using a pthread key destructor. These destructors + are called in several rounds to accommodate destructor functions that + (re)initialize key values with pthread_setspecific. Delay the emutls + deallocation to accommodate other end-of-thread cleanup tasks like + calling thread_local destructors. */ + if (arr->skip_destructor_rounds > 0) { - if (arr->data[i]) - free (arr->data[i][-1]); + arr->skip_destructor_rounds--; + __gthread_setspecific (emutls_key, (void *) arr); } + else + { + pointer size = arr->size; + pointer i; + + for (i = 0; i < size; ++i) + { + if (arr->data[i]) + free (arr->data[i][-1]); + } - free (ptr); + free (ptr); + } } static void @@ -86,6 +118,18 @@ emutls_init (void) #endif if (__gthread_key_create (&emutls_key, emutls_destroy) != 0) abort (); + emutls_key_created = 1; +} + +__attribute__((visibility("hidden"))) +void +__emutls_unregister_key (void) +{ + if (emutls_key_created) + { + emutls_key_created = 0; + __gthread_key_delete (emutls_key); + } } #endif @@ -153,12 +197,14 @@ __emutls_get_address (struct __emutls_object *obj) } struct __emutls_array *arr = __gthread_getspecific (emutls_key); + const pointer hdr_size = sizeof (struct __emutls_array) / sizeof (void *); if (__builtin_expect (arr == NULL, 0)) { pointer size = offset + 32; - arr = calloc (size + 1, sizeof (void *)); + arr = calloc (size + hdr_size, sizeof (void *)); if (arr == NULL) abort (); + arr->skip_destructor_rounds = EMUTLS_SKIP_DESTRUCTOR_ROUNDS; arr->size = size; __gthread_setspecific (emutls_key, (void *) arr); } @@ -168,7 +214,7 @@ __emutls_get_address (struct __emutls_object *obj) pointer size = orig_size * 2; if (offset > size) size = offset + 32; - arr = realloc (arr, (size + 1) * sizeof (void *)); + arr = realloc (arr, (size + hdr_size) * sizeof (void *)); if (arr == NULL) abort (); arr->size = size; diff --git a/gcc-4.9/libgcc/unwind-dw2-fde-dip.c b/gcc-4.9/libgcc/unwind-dw2-fde-dip.c index d6c052165..db98b5961 100644 --- a/gcc-4.9/libgcc/unwind-dw2-fde-dip.c +++ b/gcc-4.9/libgcc/unwind-dw2-fde-dip.c @@ -183,6 +183,30 @@ _Unwind_IteratePhdrCallback (struct dl_phdr_info *info, size_t size, void *ptr) p_eh_frame_hdr = NULL; p_dynamic = NULL; +#if defined(__BIONIC__) && defined(__i386__) + if (load_base == 0) + { + /* A load_base of 0 normally indicates a non-PIE executable. There was a + bug in Android's dynamic loader prior to API 18, though, where + dl_iterate_phdr incorrectly passed a load_base of 0 for a PIE + executable. Work around the bug by recalculating load_base using + the PT_PHDR segment. This code path isn't needed for arm32, because + arm32 didn't have dl_iterate_phdr until API 21. + https://github.com/android-ndk/ndk/issues/505. */ + size_t i; + for (i = 0; i < info->dlpi_phnum; ++i) + { + const ElfW(Phdr) *fix_phdr = &info->dlpi_phdr[i]; + if (fix_phdr->p_type == PT_PHDR) + { + load_base = (_Unwind_Ptr) info->dlpi_phdr - + (_Unwind_Ptr) fix_phdr->p_vaddr; + break; + } + } + } +#endif + struct frame_hdr_cache_element *prev_cache_entry = NULL, *last_cache_entry = NULL; |