mirror of git://sourceware.org/git/glibc.git
Implement _Unwind_Resume in libc on top of <unwind-link.h>
Temporarily move the arm _Unwind_Resume implementation to the file used by libpthread. It will be ported to <unwind-link.h> along with the rest of nptl. Reviewed-by: Carlos O'Donell <carlos@redhat.com>
This commit is contained in:
parent
d14624825a
commit
6b7efa3d87
|
|
@ -18,29 +18,29 @@
|
|||
|
||||
#include <sysdep.h>
|
||||
|
||||
/* This is just implementing exactly what the C version does.
|
||||
/* This is equivalent to the following C implementation:
|
||||
|
||||
void
|
||||
_Unwind_Resume (struct _Unwind_Exception *exc)
|
||||
{
|
||||
__unwind_link_get_resume () (exc);
|
||||
}
|
||||
|
||||
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 need to save and restore LR (for our own return address)
|
||||
and R0 (for the argument to _Unwind_Resume) around the call. */
|
||||
1: push {r0, lr}
|
||||
push {r0, lr}
|
||||
cfi_adjust_cfa_offset (8)
|
||||
cfi_rel_offset (r0, 0)
|
||||
cfi_rel_offset (lr, 4)
|
||||
bl __libgcc_s_init
|
||||
bl __unwind_link_get_resume
|
||||
mov r3, r0
|
||||
pop {r0, lr}
|
||||
cfi_adjust_cfa_offset (-8)
|
||||
cfi_restore (r0)
|
||||
cfi_restore (r4)
|
||||
cfi_restore (lr)
|
||||
|
||||
LDR_HIDDEN (ip, ip, __libgcc_s_resume, 0)
|
||||
b 0b
|
||||
bx r3
|
||||
END (_Unwind_Resume)
|
||||
|
|
|
|||
|
|
@ -1,2 +1,46 @@
|
|||
#define __libgcc_s_init pthread_cancel_init
|
||||
#include <arm-unwind-resume.S>
|
||||
/* _Unwind_Resume wrapper for ARM EABI.
|
||||
Copyright (C) 2015-2021 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
|
||||
<https://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 need to save and restore LR (for our own return address)
|
||||
and R0 (for the argument to _Unwind_Resume) around the call. */
|
||||
1: push {r0, lr}
|
||||
cfi_adjust_cfa_offset (8)
|
||||
cfi_rel_offset (r0, 0)
|
||||
cfi_rel_offset (lr, 4)
|
||||
bl pthread_cancel_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)
|
||||
|
|
|
|||
|
|
@ -32,4 +32,8 @@
|
|||
assert (local.ptr__Unwind_VRS_Get != NULL); \
|
||||
PTR_MANGLE (local.ptr__Unwind_VRS_Get);
|
||||
|
||||
/* This is used by the _Unwind_Resume assembler implementation to
|
||||
obtain the address to jump to. */
|
||||
void *__unwind_link_get_resume (void) attribute_hidden;
|
||||
|
||||
#endif /* _ARCH_UNWIND_LINK_H */
|
||||
|
|
|
|||
|
|
@ -0,0 +1,25 @@
|
|||
/* Unwinder function forwarders for libc. Arm version.
|
||||
Copyright (C) 2021 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 <https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <sysdeps/generic/unwind-resume.c>
|
||||
|
||||
void *
|
||||
__unwind_link_get_resume (void)
|
||||
{
|
||||
return UNWIND_LINK_PTR (link (), _Unwind_Resume);
|
||||
}
|
||||
|
|
@ -16,68 +16,31 @@
|
|||
License along with the GNU C Library; see the file COPYING.LIB. If
|
||||
not, see <https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <dlfcn.h>
|
||||
#include <stdio.h>
|
||||
#include <unwind.h>
|
||||
#include <gnu/lib-names.h>
|
||||
#include <unwind-link.h>
|
||||
#include <sysdep.h>
|
||||
#include <unwind-resume.h>
|
||||
|
||||
|
||||
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)
|
||||
static struct unwind_link *
|
||||
link (void)
|
||||
{
|
||||
void *resume, *personality;
|
||||
void *handle;
|
||||
|
||||
/* See include/dlfcn.h. Use of __libc_dlopen requires RTLD_NOW. */
|
||||
handle = __libc_dlopen (LIBGCC_S_SO);
|
||||
|
||||
if (handle == NULL
|
||||
|| (resume = __libc_dlsym (handle, "_Unwind_Resume")) == NULL
|
||||
|| (personality = __libc_dlsym (handle, "__gcc_personality_v0")) == NULL)
|
||||
__libc_fatal (LIBGCC_S_SO
|
||||
" must be installed for unwinding to work\n");
|
||||
|
||||
#ifdef PTR_MANGLE
|
||||
PTR_MANGLE (resume);
|
||||
#endif
|
||||
__libgcc_s_resume = resume;
|
||||
#ifdef PTR_MANGLE
|
||||
PTR_MANGLE (personality);
|
||||
#endif
|
||||
libgcc_s_personality = personality;
|
||||
struct unwind_link *unwind_link = __libc_unwind_link_get ();
|
||||
if (unwind_link == NULL)
|
||||
__libc_fatal (LIBGCC_S_SO " must be installed for unwinding to work\n");
|
||||
return unwind_link;
|
||||
}
|
||||
|
||||
#if !HAVE_ARCH_UNWIND_RESUME
|
||||
void
|
||||
_Unwind_Resume (struct _Unwind_Exception *exc)
|
||||
{
|
||||
if (__glibc_unlikely (__libgcc_s_resume == NULL))
|
||||
__libgcc_s_init ();
|
||||
|
||||
__typeof (__libgcc_s_resume) resume = __libgcc_s_resume;
|
||||
#ifdef PTR_DEMANGLE
|
||||
PTR_DEMANGLE (resume);
|
||||
#endif
|
||||
(*resume) (exc);
|
||||
UNWIND_LINK_PTR (link (), _Unwind_Resume) (exc);
|
||||
}
|
||||
#endif
|
||||
|
||||
_Unwind_Reason_Code
|
||||
__gcc_personality_v0 PERSONALITY_PROTO
|
||||
{
|
||||
if (__glibc_unlikely (libgcc_s_personality == NULL))
|
||||
__libgcc_s_init ();
|
||||
|
||||
__typeof (libgcc_s_personality) personality = libgcc_s_personality;
|
||||
#ifdef PTR_DEMANGLE
|
||||
PTR_DEMANGLE (personality);
|
||||
#endif
|
||||
return (*personality) PERSONALITY_ARGS;
|
||||
return UNWIND_LINK_PTR (link (), personality) PERSONALITY_ARGS;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue