@@ -50,6 +50,9 @@ shared-only-routines += libc-aeabi_read_tp
# cantunwind marker. There's one in start.S. To make sure we reach it, add
# unwind tables for __libc_start_main.
CFLAGS-libc-start.c += -fexceptions
+
+sysdep_routines += arm-unwind-resume
+shared-only-routines += arm-unwind-resume
endif
ifeq ($(subdir),gmon)
@@ -61,6 +64,11 @@ CFLAGS-backtrace.c += -funwind-tables
endif
ifeq ($(subdir),rt)
-librt-sysdep_routines += rt-aeabi_unwind_cpp_pr1
-librt-shared-only-routines += rt-aeabi_unwind_cpp_pr1
+librt-sysdep_routines += rt-aeabi_unwind_cpp_pr1 rt-arm-unwind-resume
+librt-shared-only-routines += rt-aeabi_unwind_cpp_pr1 rt-arm-unwind-resume
+endif
+
+ifeq ($(subdir),nptl)
+libpthread-sysdep_routines += pt-arm-unwind-resume
+libpthread-shared-only-routines += pt-arm-unwind-resume
endif
@@ -0,0 +1,47 @@
+/* _Unwind_Resume wrapper for ARM EABI.
+ Copyright (C) 2014 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
+ modify it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <sysdep.h>
+
+/* This is just implementing exactly what the C version does.
+ We do it in assembly just to ensure that we get an unmolested tail
+ call to the libgcc function, which is necessary for the ARM unwinder. */
+
+ENTRY (_Unwind_Resume)
+ LDR_HIDDEN (ip, ip, __libgcc_s_resume, 0)
+ cmp ip, #0
+ beq 1f
+0: PTR_DEMANGLE (ip, ip, r2, r3)
+ bx ip
+
+ /* We only really need to save and restore LR, but
+ the ABI requires the stack be kept aligned to 8 bytes,
+ so we push and pop r0 as well just to even out the stack. */
+1: push {r0, lr}
+ cfi_adjust_cfa_offset (8)
+ cfi_rel_offset (r0, 0)
+ cfi_rel_offset (lr, 4)
+ bl __libgcc_s_init
+ pop {r0, lr}
+ cfi_adjust_cfa_offset (-8)
+ cfi_restore (r0)
+ cfi_restore (lr)
+
+ LDR_HIDDEN (ip, ip, __libgcc_s_resume, 0)
+ b 0b
+END (_Unwind_Resume)
@@ -0,0 +1,2 @@
+#define __libgcc_s_init pthread_cancel_init
+#include <arm-unwind-resume.S>
@@ -0,0 +1 @@
+#include <arm-unwind-resume.S>
@@ -0,0 +1,33 @@
+/* Definitions for unwind-resume.c. ARM (EABI) version.
+ Copyright (C) 2014 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
+ modify it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; see the file COPYING.LIB. If
+ not, see <http://www.gnu.org/licenses/>. */
+
+/* The EABI personality routine has a different signature than the
+ canonical one. These macros tell sysdeps/gnu/unwind*.c how to
+ define __gcc_personality_v0. */
+#define PERSONALITY_PROTO \
+ (_Unwind_State state, \
+ struct _Unwind_Exception *ue_header, \
+ struct _Unwind_Context *context)
+#define PERSONALITY_ARGS \
+ (state, ue_header, context)
+
+/* It's vitally important that _Unwind_Resume not have a stack frame; the
+ ARM unwinder relies on register state at entrance. So we write this in
+ assembly (see arm-unwind-resume.S). This macro tells the generic code
+ not to provide the generic C definition. */
+#define HAVE_ARCH_UNWIND_RESUME 1
@@ -0,0 +1,33 @@
+/* Definitions for unwind-resume.c. Generic version.
+ Copyright (C) 2014 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
+ modify it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; see the file COPYING.LIB. If
+ not, see <http://www.gnu.org/licenses/>. */
+
+/* These describe the arguments to unwinder personality functions,
+ specifically __gcc_personality_v0. A machine-specific sysdeps
+ file might define them differently. */
+#define PERSONALITY_PROTO \
+ (int version, _Unwind_Action actions, \
+ _Unwind_Exception_Class exception_class, \
+ struct _Unwind_Exception *ue_header, \
+ struct _Unwind_Context *context)
+#define PERSONALITY_ARGS \
+ (version, actions, exception_class, ue_header, context)
+
+/* This is defined nonzero by a machine-specific sysdeps file if
+ _Unwind_Resume is provided separately and thus the generic C
+ version should not be defined. */
+#define HAVE_ARCH_UNWIND_RESUME 0
@@ -21,15 +21,16 @@
#include <unwind.h>
#include <gnu/lib-names.h>
#include <sysdep.h>
+#include <unwind-resume.h>
-static void (*libgcc_s_resume) (struct _Unwind_Exception *exc)
- __attribute__ ((noreturn));
-static _Unwind_Reason_Code (*libgcc_s_personality)
- (int, _Unwind_Action, _Unwind_Exception_Class, struct _Unwind_Exception *,
- struct _Unwind_Context *);
-static void
-init (void)
+void (*__libgcc_s_resume) (struct _Unwind_Exception *exc)
+ attribute_hidden __attribute__ ((noreturn));
+
+static _Unwind_Reason_Code (*libgcc_s_personality) PERSONALITY_PROTO;
+
+void attribute_hidden __attribute__ ((cold))
+__libgcc_s_init (void)
{
void *resume, *personality;
void *handle;
@@ -43,33 +44,31 @@ init (void)
" must be installed for pthread_cancel to work\n");
PTR_MANGLE (resume);
- libgcc_s_resume = resume;
+ __libgcc_s_resume = resume;
PTR_MANGLE (personality);
libgcc_s_personality = personality;
}
+#if !HAVE_ARCH_UNWIND_RESUME
void
_Unwind_Resume (struct _Unwind_Exception *exc)
{
- if (__glibc_unlikely (libgcc_s_resume == NULL))
- init ();
+ if (__glibc_unlikely (__libgcc_s_resume == NULL))
+ __libgcc_s_init ();
- __typeof (libgcc_s_resume) resume = libgcc_s_resume;
+ __typeof (__libgcc_s_resume) resume = __libgcc_s_resume;
PTR_DEMANGLE (resume);
(*resume) (exc);
}
+#endif
_Unwind_Reason_Code
-__gcc_personality_v0 (int version, _Unwind_Action actions,
- _Unwind_Exception_Class exception_class,
- struct _Unwind_Exception *ue_header,
- struct _Unwind_Context *context)
+__gcc_personality_v0 PERSONALITY_PROTO
{
if (__glibc_unlikely (libgcc_s_personality == NULL))
- init ();
+ __libgcc_s_init ();
__typeof (libgcc_s_personality) personality = libgcc_s_personality;
PTR_DEMANGLE (personality);
-
- return (*personality) (version, actions, exception_class, ue_header, context);
+ return (*personality) PERSONALITY_ARGS;
}
@@ -22,12 +22,12 @@
#include <pthreadP.h>
#include <sysdep.h>
#include <gnu/lib-names.h>
+#include <unwind-resume.h>
static void *libgcc_s_handle;
-static void (*libgcc_s_resume) (struct _Unwind_Exception *exc);
-static _Unwind_Reason_Code (*libgcc_s_personality)
- (int, _Unwind_Action, _Unwind_Exception_Class, struct _Unwind_Exception *,
- struct _Unwind_Context *);
+void (*__libgcc_s_resume) (struct _Unwind_Exception *exc)
+ attribute_hidden __attribute__ ((noreturn));
+static _Unwind_Reason_Code (*libgcc_s_personality) PERSONALITY_PROTO;
static _Unwind_Reason_Code (*libgcc_s_forcedunwind)
(struct _Unwind_Exception *, _Unwind_Stop_Fn, void *);
static _Unwind_Word (*libgcc_s_getcfa) (struct _Unwind_Context *);
@@ -64,7 +64,7 @@ pthread_cancel_init (void)
__libc_fatal (LIBGCC_S_SO " must be installed for pthread_cancel to work\n");
PTR_MANGLE (resume);
- libgcc_s_resume = resume;
+ __libgcc_s_resume = resume;
PTR_MANGLE (personality);
libgcc_s_personality = personality;
PTR_MANGLE (forcedunwind);
@@ -90,6 +90,7 @@ __unwind_freeres (void)
}
}
+#if !HAVE_ARCH_UNWIND_RESUME
void
_Unwind_Resume (struct _Unwind_Exception *exc)
{
@@ -98,27 +99,23 @@ _Unwind_Resume (struct _Unwind_Exception *exc)
else
atomic_read_barrier ();
- void (*resume) (struct _Unwind_Exception *exc) = libgcc_s_resume;
+ void (*resume) (struct _Unwind_Exception *exc) = __libgcc_s_resume;
PTR_DEMANGLE (resume);
resume (exc);
}
+#endif
_Unwind_Reason_Code
-__gcc_personality_v0 (int version, _Unwind_Action actions,
- _Unwind_Exception_Class exception_class,
- struct _Unwind_Exception *ue_header,
- struct _Unwind_Context *context)
+__gcc_personality_v0 PERSONALITY_PROTO
{
if (__glibc_unlikely (libgcc_s_handle == NULL))
pthread_cancel_init ();
else
atomic_read_barrier ();
- _Unwind_Reason_Code (*personality)
- (int, _Unwind_Action, _Unwind_Exception_Class, struct _Unwind_Exception *,
- struct _Unwind_Context *) = libgcc_s_personality;
+ __typeof (libgcc_s_personality) personality = libgcc_s_personality;
PTR_DEMANGLE (personality);
- return personality (version, actions, exception_class, ue_header, context);
+ return (*personality) PERSONALITY_ARGS;
}
_Unwind_Reason_Code
@@ -1,158 +0,0 @@
-/* Copyright (C) 2003-2014 Free Software Foundation, Inc.
- This file is part of the GNU C Library.
- Contributed by Jakub Jelinek <jakub@redhat.com>.
-
- The GNU C Library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public License as
- published by the Free Software Foundation; either version 2.1 of the
- License, or (at your option) any later version.
-
- The GNU C Library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with the GNU C Library. If not, see
- <http://www.gnu.org/licenses/>. */
-
-#include <dlfcn.h>
-#include <stdio.h>
-#include <unwind.h>
-#include <pthreadP.h>
-
-static void *libgcc_s_handle;
-static void (*libgcc_s_resume) (struct _Unwind_Exception *exc)
- __attribute_used__;
-static _Unwind_Reason_Code (*libgcc_s_personality)
- (_Unwind_State, struct _Unwind_Exception *, struct _Unwind_Context *);
-static _Unwind_Reason_Code (*libgcc_s_forcedunwind)
- (struct _Unwind_Exception *, _Unwind_Stop_Fn, void *);
-static _Unwind_Word (*libgcc_s_getcfa) (struct _Unwind_Context *);
-
-void
-__attribute_noinline__
-pthread_cancel_init (void)
-{
- void *resume, *personality, *forcedunwind, *getcfa;
- void *handle;
-
- if (__builtin_expect (libgcc_s_handle != NULL, 1))
- {
- /* Force gcc to reload all values. */
- asm volatile ("" ::: "memory");
- return;
- }
-
- handle = __libc_dlopen ("libgcc_s.so.1");
-
- if (handle == NULL
- || (resume = __libc_dlsym (handle, "_Unwind_Resume")) == NULL
- || (personality = __libc_dlsym (handle, "__gcc_personality_v0")) == NULL
- || (forcedunwind = __libc_dlsym (handle, "_Unwind_ForcedUnwind"))
- == NULL
- || (getcfa = __libc_dlsym (handle, "_Unwind_GetCFA")) == NULL
-#ifdef ARCH_CANCEL_INIT
- || ARCH_CANCEL_INIT (handle)
-#endif
- )
- __libc_fatal ("libgcc_s.so.1 must be installed for pthread_cancel to work\n");
-
- libgcc_s_resume = resume;
- libgcc_s_personality = personality;
- libgcc_s_forcedunwind = forcedunwind;
- libgcc_s_getcfa = getcfa;
- /* Make sure libgcc_s_getcfa is written last. Otherwise,
- pthread_cancel_init might return early even when the pointer the
- caller is interested in is not initialized yet. */
- atomic_write_barrier ();
- libgcc_s_handle = handle;
-}
-
-void
-__libc_freeres_fn_section
-__unwind_freeres (void)
-{
- void *handle = libgcc_s_handle;
- if (handle != NULL)
- {
- libgcc_s_handle = NULL;
- __libc_dlclose (handle);
- }
-}
-
-/* It's vitally important that _Unwind_Resume not have a stack frame; the
- ARM unwinder relies on register state at entrance. So we write this in
- assembly. */
-
-#define STR1(S) #S
-#define STR(S) STR1(S)
-
-asm (
-" .globl _Unwind_Resume\n"
-" .type _Unwind_Resume, %function\n"
-"_Unwind_Resume:\n"
-" .cfi_sections .debug_frame\n"
-" " CFI_STARTPROC "\n"
-" push {r4, r5, r6, lr}\n"
-" " CFI_ADJUST_CFA_OFFSET (16)" \n"
-" " CFI_REL_OFFSET (r4, 0) "\n"
-" " CFI_REL_OFFSET (r5, 4) "\n"
-" " CFI_REL_OFFSET (r6, 8) "\n"
-" " CFI_REL_OFFSET (lr, 12) "\n"
-" " CFI_REMEMBER_STATE "\n"
-" ldr r4, 1f\n"
-" ldr r5, 2f\n"
-"3: add r4, pc, r4\n"
-" ldr r3, [r4, r5]\n"
-" mov r6, r0\n"
-" cmp r3, #0\n"
-" beq 4f\n"
-"5: mov r0, r6\n"
-" pop {r4, r5, r6, lr}\n"
-" " CFI_ADJUST_CFA_OFFSET (-16) "\n"
-" " CFI_RESTORE (r4) "\n"
-" " CFI_RESTORE (r5) "\n"
-" " CFI_RESTORE (r6) "\n"
-" " CFI_RESTORE (lr) "\n"
-" bx r3\n"
-" " CFI_RESTORE_STATE "\n"
-"4: bl pthread_cancel_init\n"
-" ldr r3, [r4, r5]\n"
-" b 5b\n"
-" " CFI_ENDPROC "\n"
-" .align 2\n"
-"1: .word _GLOBAL_OFFSET_TABLE_ - 3b - " STR (PC_OFS) "\n"
-"2: .word libgcc_s_resume(GOTOFF)\n"
-" .size _Unwind_Resume, .-_Unwind_Resume\n"
-);
-
-_Unwind_Reason_Code
-__gcc_personality_v0 (_Unwind_State state,
- struct _Unwind_Exception *ue_header,
- struct _Unwind_Context *context)
-{
- if (__builtin_expect (libgcc_s_personality == NULL, 0))
- pthread_cancel_init ();
-
- return libgcc_s_personality (state, ue_header, context);
-}
-
-_Unwind_Reason_Code
-_Unwind_ForcedUnwind (struct _Unwind_Exception *exc, _Unwind_Stop_Fn stop,
- void *stop_argument)
-{
- if (__builtin_expect (libgcc_s_forcedunwind == NULL, 0))
- pthread_cancel_init ();
-
- return libgcc_s_forcedunwind (exc, stop, stop_argument);
-}
-
-_Unwind_Word
-_Unwind_GetCFA (struct _Unwind_Context *context)
-{
- if (__builtin_expect (libgcc_s_getcfa == NULL, 0))
- pthread_cancel_init ();
-
- return libgcc_s_getcfa (context);
-}
@@ -1,101 +0,0 @@
-/* Copyright (C) 2003-2014 Free Software Foundation, Inc.
- This file is part of the GNU C Library.
- Contributed by Jakub Jelinek <jakub@redhat.com>.
-
- The GNU C Library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public License as
- published by the Free Software Foundation; either version 2.1 of the
- License, or (at your option) any later version.
-
- The GNU C Library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with the GNU C Library. If not, see
- <http://www.gnu.org/licenses/>. */
-
-#include <dlfcn.h>
-#include <stdio.h>
-#include <unwind.h>
-
-static void (*libgcc_s_resume) (struct _Unwind_Exception *exc)
- __attribute_used__;
-static _Unwind_Reason_Code (*libgcc_s_personality)
- (_Unwind_State, struct _Unwind_Exception *, struct _Unwind_Context *);
-
-static void init (void) __attribute_used__;
-
-static void
-init (void)
-{
- void *resume, *personality;
- void *handle;
-
- handle = __libc_dlopen ("libgcc_s.so.1");
-
- if (handle == NULL
- || (resume = __libc_dlsym (handle, "_Unwind_Resume")) == NULL
- || (personality = __libc_dlsym (handle, "__gcc_personality_v0")) == NULL)
- __libc_fatal ("libgcc_s.so.1 must be installed for pthread_cancel to work\n");
-
- libgcc_s_resume = resume;
- libgcc_s_personality = personality;
-}
-
-/* It's vitally important that _Unwind_Resume not have a stack frame; the
- ARM unwinder relies on register state at entrance. So we write this in
- assembly. */
-
-#define STR1(S) #S
-#define STR(S) STR1(S)
-
-asm (
-" .globl _Unwind_Resume\n"
-" .type _Unwind_Resume, %function\n"
-"_Unwind_Resume:\n"
-" .cfi_sections .debug_frame\n"
-" " CFI_STARTPROC "\n"
-" push {r4, r5, r6, lr}\n"
-" " CFI_ADJUST_CFA_OFFSET (16)" \n"
-" " CFI_REL_OFFSET (r4, 0) "\n"
-" " CFI_REL_OFFSET (r5, 4) "\n"
-" " CFI_REL_OFFSET (r6, 8) "\n"
-" " CFI_REL_OFFSET (lr, 12) "\n"
-" " CFI_REMEMBER_STATE "\n"
-" ldr r4, 1f\n"
-" ldr r5, 2f\n"
-"3: add r4, pc, r4\n"
-" ldr r3, [r4, r5]\n"
-" mov r6, r0\n"
-" cmp r3, #0\n"
-" beq 4f\n"
-"5: mov r0, r6\n"
-" pop {r4, r5, r6, lr}\n"
-" " CFI_ADJUST_CFA_OFFSET (-16) "\n"
-" " CFI_RESTORE (r4) "\n"
-" " CFI_RESTORE (r5) "\n"
-" " CFI_RESTORE (r6) "\n"
-" " CFI_RESTORE (lr) "\n"
-" bx r3\n"
-" " CFI_RESTORE_STATE "\n"
-"4: bl init\n"
-" ldr r3, [r4, r5]\n"
-" b 5b\n"
-" " CFI_ENDPROC "\n"
-" .align 2\n"
-"1: .word _GLOBAL_OFFSET_TABLE_ - 3b - " STR (PC_OFS) "\n"
-"2: .word libgcc_s_resume(GOTOFF)\n"
-" .size _Unwind_Resume, .-_Unwind_Resume\n"
-);
-
-_Unwind_Reason_Code
-__gcc_personality_v0 (_Unwind_State state,
- struct _Unwind_Exception *ue_header,
- struct _Unwind_Context *context)
-{
- if (__builtin_expect (libgcc_s_personality == NULL, 0))
- init ();
- return libgcc_s_personality (state, ue_header, context);
-}