From 46936205f991de051a9555a03f856683475a2be5 Mon Sep 17 00:00:00 2001 From: Caroline Tice Date: Fri, 19 Jan 2018 11:35:09 -0800 Subject: [libgcc] Fix emutls.c to not leak pthread keys. Bug:b/71814577 Test:Built toolchain w/change and successfully tested building both platform and kernel images with new toolchain for marlin (pixel) device. Change-Id: Ia0c6944ce1d78b5bd57d65f705a3f7a59c944202 --- gcc-4.9/libgcc/emutls.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'gcc-4.9/libgcc') diff --git a/gcc-4.9/libgcc/emutls.c b/gcc-4.9/libgcc/emutls.c index fd6d86ed9..77550e057 100644 --- a/gcc-4.9/libgcc/emutls.c +++ b/gcc-4.9/libgcc/emutls.c @@ -60,6 +60,7 @@ 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 @@ -86,9 +87,18 @@ emutls_init (void) #endif if (__gthread_key_create (&emutls_key, emutls_destroy) != 0) abort (); + emutls_key_created = 1; } #endif +__attribute__((destructor)) +static void +unregister_emutls_key (void) +{ + if (emutls_key_created) + __gthread_key_delete (emutls_key); +} + static void * emutls_alloc (struct __emutls_object *obj) { -- cgit v1.2.3 From 2cdcfd30c27f0d836cc477f2ae9f456287fd6b1b Mon Sep 17 00:00:00 2001 From: Caroline Tice Date: Mon, 5 Feb 2018 08:43:33 -0800 Subject: [GCC] Fix #endif problem in libgcc/emutls.c Currently in emutls.c 'emutls_key_created' is defined within part of an ifdef, but is accessed outside the ifdef, which can cause issues in builds where the ifdef is not taken. This CL moves the #endif to include the new function that accesses 'emutls_key_created' so that all references to it are within the defining if-def. Bug: b/72942688 Test: Fix tested in ChromeOS. Change-Id: Ic1d6760d116b63abaef18f95e38de42af30952e4 --- gcc-4.9/libgcc/emutls.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'gcc-4.9/libgcc') diff --git a/gcc-4.9/libgcc/emutls.c b/gcc-4.9/libgcc/emutls.c index 77550e057..cba9c3b03 100644 --- a/gcc-4.9/libgcc/emutls.c +++ b/gcc-4.9/libgcc/emutls.c @@ -89,7 +89,6 @@ emutls_init (void) abort (); emutls_key_created = 1; } -#endif __attribute__((destructor)) static void @@ -98,6 +97,7 @@ unregister_emutls_key (void) if (emutls_key_created) __gthread_key_delete (emutls_key); } +#endif static void * emutls_alloc (struct __emutls_object *obj) -- cgit v1.2.3 From 5669c9914b411b5094532856815b2c4712be4d10 Mon Sep 17 00:00:00 2001 From: Yunlian Jiang Date: Tue, 24 Apr 2018 14:24:57 -0700 Subject: gcc: backport an upstream patch to make it work with newer glibc. Newer glibc removes 'struct' tag from ucontext_t. Because of this, gcc failed to bootstrap with newer glibc. This patch from upstream fixes that. BUG=chromium:834385 TEST=sudo emerge sys-devel/gcc passes with newer glibc installed. commit 14c2f22a1877f6b60a2f7c2f83ffb032759456a6 Author: jsm28 Date: Tue Jul 4 10:22:56 2017 +0000 Use ucontext_t not struct ucontext in linux-unwind.h files. Current glibc no longer gives the ucontext_t type the tag struct ucontext, to conform with POSIX namespace rules. This requires various linux-unwind.h files in libgcc, that were previously using struct ucontext, to be fixed to use ucontext_t instead. This is similar to the removal of the struct siginfo tag from siginfo_t some years ago. This patch changes those files to use ucontext_t instead. As the standard name that should be unconditionally safe, so this is not restricted to architectures supported by glibc, or conditioned on the glibc version. Tested compilation together with current glibc with glibc's build-many-glibcs.py. Change-Id: I433dd983b8d18c538d96486f7362b953ece3bfb8 --- gcc-4.9/libgcc/config/aarch64/linux-unwind.h | 2 +- gcc-4.9/libgcc/config/alpha/linux-unwind.h | 2 +- gcc-4.9/libgcc/config/bfin/linux-unwind.h | 2 +- gcc-4.9/libgcc/config/i386/linux-unwind.h | 4 ++-- gcc-4.9/libgcc/config/m68k/linux-unwind.h | 2 +- gcc-4.9/libgcc/config/nios2/linux-unwind.h | 2 +- gcc-4.9/libgcc/config/pa/linux-unwind.h | 2 +- gcc-4.9/libgcc/config/sh/linux-unwind.h | 2 +- gcc-4.9/libgcc/config/tilepro/linux-unwind.h | 2 +- gcc-4.9/libgcc/config/xtensa/linux-unwind.h | 2 +- 10 files changed, 11 insertions(+), 11 deletions(-) (limited to 'gcc-4.9/libgcc') 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 /* 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 */ -- cgit v1.2.3 From 81788f3d99d2c5952fa9a6d673e8d6a53b76d511 Mon Sep 17 00:00:00 2001 From: Ryan Prichard Date: Wed, 9 May 2018 15:37:24 -0700 Subject: Delay emutls deallocation for one round With Android/Bionic, delay deallocation to round 2 of 4. It must run after C++ thread_local destructors have been called, but before the final 2 rounds, because emutls calls free, and jemalloc then needs another 2 rounds to free its thread-specific data. Bug: https://github.com/android-ndk/ndk/issues/687 Bug: b/78022094 Test: manual Test: ./run_tests.py --rebuild --filter emutls-dealloc Change-Id: I01bd634d97b7d22161b5cc8ca71b3cb94064a03e --- gcc-4.9/libgcc/emutls.c | 49 +++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 41 insertions(+), 8 deletions(-) (limited to 'gcc-4.9/libgcc') diff --git a/gcc-4.9/libgcc/emutls.c b/gcc-4.9/libgcc/emutls.c index cba9c3b03..525db2839 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[]; }; @@ -67,16 +84,30 @@ 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; - free (ptr); + for (i = 0; i < size; ++i) + { + if (arr->data[i]) + free (arr->data[i][-1]); + } + + free (ptr); + } } static void @@ -163,12 +194,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); } @@ -178,7 +211,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; -- cgit v1.2.3 From 89b2029895df0a3f3587eeba0a519091c3f7a1b5 Mon Sep 17 00:00:00 2001 From: Ryan Prichard Date: Mon, 4 Jun 2018 14:35:57 -0700 Subject: Add __emutls_unregister_key function Replace the existing __attribute__((destructor)) function, unregister_emutls_key, with a function that something else must call explicitly. We don't want the pthread key deleted at program exit, because it's unnecessary and because it may delete the key before other tls-using cleanup code runs. Exposing __emutls_unregister_key allows limiting the cleanup to dlclose (e.g. by calling it only from crtbegin_so.c). Reset emutls_key_created so multiple calls to __emutls_unregister_key are safe. Bug: b/80453944 Test: manual Change-Id: I82d13614ae8042d0501fd2ca64f0ef6189669905 --- gcc-4.9/libgcc/emutls.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'gcc-4.9/libgcc') diff --git a/gcc-4.9/libgcc/emutls.c b/gcc-4.9/libgcc/emutls.c index 525db2839..93c3c0788 100644 --- a/gcc-4.9/libgcc/emutls.c +++ b/gcc-4.9/libgcc/emutls.c @@ -121,12 +121,15 @@ emutls_init (void) emutls_key_created = 1; } -__attribute__((destructor)) -static void -unregister_emutls_key (void) +__attribute__((visibility("hidden"))) +void +__emutls_unregister_key (void) { if (emutls_key_created) - __gthread_key_delete (emutls_key); + { + emutls_key_created = 0; + __gthread_key_delete (emutls_key); + } } #endif -- cgit v1.2.3 From 4089f56e6c7438eb98cb86c249cf0c01e22219c5 Mon Sep 17 00:00:00 2001 From: Ryan Prichard Date: Wed, 27 Jun 2018 17:21:50 -0700 Subject: libgcc: work around old Bionic loader bug dl_iterate_phdr returns a 0 load_base for a PIE executable when it should return the address where the executable was loaded (e.g. the load base or load bias). Recalculate the load base when it is zero. This recalculation should work on any ELF file with a PT_PHDR segment -- it will calculate 0 for a non-PIE executable. The load base is added to an ELF virtual address to produce a run-time address. Recalculate it by subtracting the PT_PHDR's virtual address from its run-time address. Bug: https://github.com/android-ndk/ndk/issues/505 Test: manual Test: run NDK tests (./checkbuild.py && ./run_tests.py) Change-Id: I7de46c07a8b04e794b59f07b4d554238cfd6d5d9 --- gcc-4.9/libgcc/unwind-dw2-fde-dip.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) (limited to 'gcc-4.9/libgcc') 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; -- cgit v1.2.3