diff options
| author | Khem Raj <raj.khem@gmail.com> | 2010-06-23 16:30:54 -0700 | 
|---|---|---|
| committer | Khem Raj <raj.khem@gmail.com> | 2010-06-23 16:30:54 -0700 | 
| commit | 6cbeaa5dd11a1b506a8a97b4dfb4e632240f9953 (patch) | |
| tree | 2c8e5e67a572e27a6a2a03b9e9cd3ec1c779102f /libpthread | |
| parent | 84fa9cf6cb8d8b59a0d2fc889fd78ce6a9309420 (diff) | |
arm/nptl: Sync unwinding with glibc.
Signed-off-by: Khem Raj <raj.khem@gmail.com>
Diffstat (limited to 'libpthread')
| -rw-r--r-- | libpthread/nptl/sysdeps/unix/sysv/linux/arm/unwind-forcedunwind.c | 108 | ||||
| -rw-r--r-- | libpthread/nptl/sysdeps/unix/sysv/linux/arm/unwind-resume.c | 102 | 
2 files changed, 116 insertions, 94 deletions
diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/arm/unwind-forcedunwind.c b/libpthread/nptl/sysdeps/unix/sysv/linux/arm/unwind-forcedunwind.c index d095d3083..011746d0e 100644 --- a/libpthread/nptl/sysdeps/unix/sysv/linux/arm/unwind-forcedunwind.c +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/arm/unwind-forcedunwind.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2003, 2009 Free Software Foundation, Inc. +/* Copyright (C) 2003, 2005, 2007, 2009, 2010 Free Software Foundation, Inc.     This file is part of the GNU C Library.     Contributed by Jakub Jelinek <jakub@redhat.com>. @@ -21,20 +21,14 @@  #include <stdio.h>  #include <unwind.h>  #include <pthreadP.h> -#define __libc_dlopen(x)        dlopen(x, (RTLD_LOCAL | RTLD_LAZY)) -#define __libc_dlsym            dlsym -#define __libc_dlclose          dlclose  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 *); +  (_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 *); -static void (*libgcc_s_sjlj_register) (struct SjLj_Function_Context *); -static void (*libgcc_s_sjlj_unregister) (struct SjLj_Function_Context *);  void  __attribute_noinline__ @@ -42,7 +36,6 @@ pthread_cancel_init (void)  {    void *resume, *personality, *forcedunwind, *getcfa;    void *handle; -  void *sjlj_register, *sjlj_unregister;    if (__builtin_expect (libgcc_s_handle != NULL, 1))      { @@ -54,21 +47,20 @@ pthread_cancel_init (void)    handle = __libc_dlopen ("libgcc_s.so.1");    if (handle == NULL -      || (sjlj_register = __libc_dlsym (handle, "_Unwind_SjLj_Register")) == NULL -      || (sjlj_unregister = __libc_dlsym (handle, "_Unwind_SjLj_Unregister")) == NULL -      || (resume = __libc_dlsym (handle, "_Unwind_SjLj_Resume")) == NULL -      || (personality = __libc_dlsym (handle, "__gcc_personality_sj0")) == NULL -      || (forcedunwind = __libc_dlsym (handle, "_Unwind_SjLj_ForcedUnwind")) +      || (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        ) -      fprintf(stderr, "libgcc_s.so.1 must be installed for pthread_cancel to work\n"); +    __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_sjlj_register = sjlj_register; -  libgcc_s_sjlj_unregister = sjlj_unregister;    libgcc_s_getcfa = getcfa;    /* Make sure libgcc_s_getcfa is written last.  Otherwise,       pthread_cancel_init might return early even when the pointer the @@ -89,26 +81,62 @@ __unwind_freeres (void)      }  } -void -_Unwind_Resume (struct _Unwind_Exception *exc) -{ -  if (__builtin_expect (libgcc_s_resume == NULL, 0)) -    pthread_cancel_init (); - -  libgcc_s_resume (exc); -} +/* 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.  */ + +asm ( +"	.globl	_Unwind_Resume\n" +"	.type	_Unwind_Resume, %function\n" +"_Unwind_Resume:\n" +"	.cfi_sections .debug_frame\n" +"	" CFI_STARTPROC "\n" +"	stmfd	sp!, {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" +"	ldmfd	sp!, {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" +#ifdef __thumb2__ +"1:	.word	_GLOBAL_OFFSET_TABLE_ - 3b - 4\n" +#else +"1:	.word	_GLOBAL_OFFSET_TABLE_ - 3b - 8\n" +#endif +"2:	.word	libgcc_s_resume(GOTOFF)\n" +"	.size	_Unwind_Resume, .-_Unwind_Resume\n" +);  _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 (_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 (version, actions, exception_class, -			       ue_header, context); +  return libgcc_s_personality (state, ue_header, context);  }  _Unwind_Reason_Code @@ -129,21 +157,3 @@ _Unwind_GetCFA (struct _Unwind_Context *context)    return libgcc_s_getcfa (context);  } - -void -_Unwind_SjLj_Register (struct SjLj_Function_Context *fc) -{ -  if (__builtin_expect (libgcc_s_sjlj_register == NULL, 0)) -    pthread_cancel_init (); - -  libgcc_s_sjlj_register (fc); -} - -void -_Unwind_SjLj_Unregister (struct SjLj_Function_Context *fc) -{ -  if (__builtin_expect (libgcc_s_sjlj_unregister == NULL, 0)) -    pthread_cancel_init (); - -  libgcc_s_sjlj_unregister (fc); -} diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/arm/unwind-resume.c b/libpthread/nptl/sysdeps/unix/sysv/linux/arm/unwind-resume.c index bf0348ac2..cdab10e30 100644 --- a/libpthread/nptl/sysdeps/unix/sysv/linux/arm/unwind-resume.c +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/arm/unwind-resume.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2003 Free Software Foundation, Inc. +/* Copyright (C) 2003, 2005, 2010 Free Software Foundation, Inc.     This file is part of the GNU C Library.     Contributed by Jakub Jelinek <jakub@redhat.com>. @@ -20,71 +20,83 @@  #include <dlfcn.h>  #include <stdio.h>  #include <unwind.h> -#define __libc_dlopen(x)        dlopen(x, (RTLD_LOCAL | RTLD_LAZY)) -#define __libc_dlsym            dlsym -#define __libc_dlclose		dlclose  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 *); -static void (*libgcc_s_sjlj_register) (struct SjLj_Function_Context *); -static void (*libgcc_s_sjlj_unregister) (struct SjLj_Function_Context *); +  (_Unwind_State, struct _Unwind_Exception *, struct _Unwind_Context *); + +static void init (void) __attribute_used__;  static void  init (void)  {    void *resume, *personality;    void *handle; -  void *sjlj_register, *sjlj_unregister;    handle = __libc_dlopen ("libgcc_s.so.1");    if (handle == NULL -      || (sjlj_register = __libc_dlsym (handle, "_Unwind_SjLj_Register")) == NULL -      || (sjlj_unregister = __libc_dlsym (handle, "_Unwind_SjLj_Unregister")) == NULL -      || (resume = __libc_dlsym (handle, "_Unwind_SjLj_Resume")) == NULL -      || (personality = __libc_dlsym (handle, "__gcc_personality_sj0")) == NULL) -      fprintf(stderr, "libgcc_s.so.1 must be installed for pthread_cancel to work\n"); +      || (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; -  libgcc_s_sjlj_register = sjlj_register; -  libgcc_s_sjlj_unregister = sjlj_unregister;  } -void -_Unwind_Resume (struct _Unwind_Exception *exc) -{ -  if (__builtin_expect (libgcc_s_resume == NULL, 0)) -    init (); -  libgcc_s_resume (exc); -} +/* 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.  */ + +asm ( +"	.globl	_Unwind_Resume\n" +"	.type	_Unwind_Resume, %function\n" +"_Unwind_Resume:\n" +"	.cfi_sections .debug_frame\n" +"	" CFI_STARTPROC "\n" +"	stmfd	sp!, {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" +"	ldmfd	sp!, {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" +#ifdef __thumb2__ +"1:	.word	_GLOBAL_OFFSET_TABLE_ - 3b - 4\n" +#else +"1:	.word	_GLOBAL_OFFSET_TABLE_ - 3b - 8\n" +#endif +"2:	.word	libgcc_s_resume(GOTOFF)\n" +"	.size	_Unwind_Resume, .-_Unwind_Resume\n" +);  _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 (_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 (version, actions, exception_class, -			       ue_header, context); -} - -void -_Unwind_SjLj_Register (struct SjLj_Function_Context *fc) -{ -  if (__builtin_expect (libgcc_s_sjlj_register == NULL, 0)) -    init (); -  libgcc_s_sjlj_register (fc); -} - -void -_Unwind_SjLj_Unregister (struct SjLj_Function_Context *fc) -{ -  if (__builtin_expect (libgcc_s_sjlj_unregister == NULL, 0)) -    init (); -  libgcc_s_sjlj_unregister (fc); +  return libgcc_s_personality (state, ue_header, context);  }  | 
