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:
Florian Weimer 2021-03-01 15:56:36 +01:00
parent d14624825a
commit 6b7efa3d87
5 changed files with 97 additions and 61 deletions

View File

@ -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)

View File

@ -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)

View File

@ -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 */

View File

@ -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);
}

View File

@ -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;
}