--- a/sysdeps/arm/Makefile
+++ b/sysdeps/arm/Makefile
@@ -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
--- /dev/null
+++ b/sysdeps/arm/arm-unwind-resume.S
@@ -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)
--- /dev/null
+++ b/sysdeps/arm/pt-arm-unwind-resume.S
@@ -0,0 +1,2 @@
+#define __libgcc_s_init	pthread_cancel_init
+#include <arm-unwind-resume.S>
--- /dev/null
+++ b/sysdeps/arm/rt-arm-unwind-resume.S
@@ -0,0 +1 @@
+#include <arm-unwind-resume.S>
--- /dev/null
+++ b/sysdeps/arm/unwind-resume.h
@@ -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
--- /dev/null
+++ b/sysdeps/generic/unwind-resume.h
@@ -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
--- a/sysdeps/gnu/unwind-resume.c
+++ b/sysdeps/gnu/unwind-resume.c
@@ -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;
 }
--- a/sysdeps/nptl/unwind-forcedunwind.c
+++ b/sysdeps/nptl/unwind-forcedunwind.c
@@ -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
--- a/sysdeps/unix/sysv/linux/arm/unwind-forcedunwind.c
+++ /dev/null
@@ -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);
-}
--- a/sysdeps/unix/sysv/linux/arm/unwind-resume.c
+++ /dev/null
@@ -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);
-}
