aboutsummaryrefslogtreecommitdiffstats
path: root/gcc-4.9/libgcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc-4.9/libgcc')
-rw-r--r--gcc-4.9/libgcc/config/aarch64/linux-unwind.h2
-rw-r--r--gcc-4.9/libgcc/config/alpha/linux-unwind.h2
-rw-r--r--gcc-4.9/libgcc/config/bfin/linux-unwind.h2
-rw-r--r--gcc-4.9/libgcc/config/i386/linux-unwind.h4
-rw-r--r--gcc-4.9/libgcc/config/m68k/linux-unwind.h2
-rw-r--r--gcc-4.9/libgcc/config/nios2/linux-unwind.h2
-rw-r--r--gcc-4.9/libgcc/config/pa/linux-unwind.h2
-rw-r--r--gcc-4.9/libgcc/config/sh/linux-unwind.h2
-rw-r--r--gcc-4.9/libgcc/config/tilepro/linux-unwind.h2
-rw-r--r--gcc-4.9/libgcc/config/xtensa/linux-unwind.h2
-rw-r--r--gcc-4.9/libgcc/emutls.c62
-rw-r--r--gcc-4.9/libgcc/unwind-dw2-fde-dip.c24
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 6b5b3cd..d13dc34 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 b5bfd1c..166d3d2 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 dc58f0a..8b94568 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 7986928..a9d621c 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 1ba2a0c..d67767e 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 ba4bd80..8978868 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 4a3cfff..d2ac437 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 4875706..671bde7 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 27481cf..c24d58c 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 6832d0b..cb15b4c 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 fd6d86e..93c3c07 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 d6c0521..db98b59 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;