[01/10] Implement <unwind-link.h> for dynamically loading the libgcc_s unwinder
Commit Message
This will be used to consolidate the libgcc_s access for backtrace
and pthread_cancel.
Unlike the existing backtrace implementations, it provides some
hardening based on pointer mangling.
---
debug/backtrace.c | 2 +-
malloc/set-freeres.c | 5 +
misc/Makefile | 2 +-
misc/Versions | 1 +
misc/unwind-link.c | 145 ++++++++++++++++++
sysdeps/alpha/unwind-arch.h | 28 ++++
sysdeps/arm/unwind-arch.h | 35 +++++
sysdeps/generic/unwind-arch.h | 27 ++--
sysdeps/generic/unwind-link.h | 106 +++++++++++++
sysdeps/i386/unwind-arch.h | 39 +++++
sysdeps/ia64/unwind-arch.h | 32 ++++
sysdeps/m68k/m680x0/unwind-arch.h | 26 ++++
sysdeps/m68k/unwind-arch.h | 35 +++++
sysdeps/mach/hurd/fork.c | 3 +
.../{unix/sysv/linux => }/mips/unwind-arch.h | 17 +-
sysdeps/nptl/fork.c | 3 +
sysdeps/powerpc/powerpc32/unwind-arch.h | 28 ++++
sysdeps/s390/unwind-arch.h | 28 ++++
sysdeps/sh/unwind-arch.h | 28 ++++
sysdeps/sparc/unwind-arch.h | 28 ++++
20 files changed, 600 insertions(+), 18 deletions(-)
create mode 100644 misc/unwind-link.c
create mode 100644 sysdeps/alpha/unwind-arch.h
create mode 100644 sysdeps/arm/unwind-arch.h
create mode 100644 sysdeps/generic/unwind-link.h
create mode 100644 sysdeps/i386/unwind-arch.h
create mode 100644 sysdeps/ia64/unwind-arch.h
create mode 100644 sysdeps/m68k/m680x0/unwind-arch.h
create mode 100644 sysdeps/m68k/unwind-arch.h
rename sysdeps/{unix/sysv/linux => }/mips/unwind-arch.h (85%)
create mode 100644 sysdeps/powerpc/powerpc32/unwind-arch.h
create mode 100644 sysdeps/s390/unwind-arch.h
create mode 100644 sysdeps/sh/unwind-arch.h
create mode 100644 sysdeps/sparc/unwind-arch.h
Comments
On 2/17/21 11:02 AM, Florian Weimer via Libc-alpha wrote:
> This will be used to consolidate the libgcc_s access for backtrace
> and pthread_cancel.
>
> Unlike the existing backtrace implementations, it provides some
> hardening based on pointer mangling.
LGTM. Creates unwind-link.h framework. Adds
__libc_unwind_link_get@@GLIBC_PRIVATE for use by libpthread.
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
> ---
> debug/backtrace.c | 2 +-
> malloc/set-freeres.c | 5 +
> misc/Makefile | 2 +-
> misc/Versions | 1 +
> misc/unwind-link.c | 145 ++++++++++++++++++
> sysdeps/alpha/unwind-arch.h | 28 ++++
> sysdeps/arm/unwind-arch.h | 35 +++++
> sysdeps/generic/unwind-arch.h | 27 ++--
> sysdeps/generic/unwind-link.h | 106 +++++++++++++
> sysdeps/i386/unwind-arch.h | 39 +++++
> sysdeps/ia64/unwind-arch.h | 32 ++++
> sysdeps/m68k/m680x0/unwind-arch.h | 26 ++++
> sysdeps/m68k/unwind-arch.h | 35 +++++
> sysdeps/mach/hurd/fork.c | 3 +
> .../{unix/sysv/linux => }/mips/unwind-arch.h | 17 +-
> sysdeps/nptl/fork.c | 3 +
> sysdeps/powerpc/powerpc32/unwind-arch.h | 28 ++++
> sysdeps/s390/unwind-arch.h | 28 ++++
> sysdeps/sh/unwind-arch.h | 28 ++++
> sysdeps/sparc/unwind-arch.h | 28 ++++
> 20 files changed, 600 insertions(+), 18 deletions(-)
> create mode 100644 misc/unwind-link.c
> create mode 100644 sysdeps/alpha/unwind-arch.h
> create mode 100644 sysdeps/arm/unwind-arch.h
> create mode 100644 sysdeps/generic/unwind-link.h
> create mode 100644 sysdeps/i386/unwind-arch.h
> create mode 100644 sysdeps/ia64/unwind-arch.h
> create mode 100644 sysdeps/m68k/m680x0/unwind-arch.h
> create mode 100644 sysdeps/m68k/unwind-arch.h
> rename sysdeps/{unix/sysv/linux => }/mips/unwind-arch.h (85%)
> create mode 100644 sysdeps/powerpc/powerpc32/unwind-arch.h
> create mode 100644 sysdeps/s390/unwind-arch.h
> create mode 100644 sysdeps/sh/unwind-arch.h
> create mode 100644 sysdeps/sparc/unwind-arch.h
>
> diff --git a/debug/backtrace.c b/debug/backtrace.c
> index 9449c51f06..5ded57bfc4 100644
> --- a/debug/backtrace.c
> +++ b/debug/backtrace.c
> @@ -23,7 +23,7 @@
> #include <gnu/lib-names.h>
> #include <stdlib.h>
> #include <unwind.h>
> -#include <unwind-arch.h>
> +#include <unwind-link.h>
>
> struct trace_arg
> {
> diff --git a/malloc/set-freeres.c b/malloc/set-freeres.c
> index 24c7194aa8..817fbea8b8 100644
> --- a/malloc/set-freeres.c
> +++ b/malloc/set-freeres.c
> @@ -19,6 +19,7 @@
> #include <stdlib.h>
> #include <set-hooks.h>
> #include <libc-internal.h>
> +#include <unwind-link.h>
>
> #include "../nss/nsswitch.h"
> #include "../libio/libioP.h"
> @@ -61,6 +62,10 @@ __libc_freeres (void)
> if (&__libpthread_freeres != NULL)
> __libpthread_freeres ();
>
> +#ifdef SHARED
> + __libc_unwind_link_freeres ();
> +#endif
> +
> for (p = symbol_set_first_element (__libc_freeres_ptrs);
> !symbol_set_end_p (__libc_freeres_ptrs, p); ++p)
> free (*p);
> diff --git a/misc/Makefile b/misc/Makefile
> index b08d7c68ab..cfc15355d6 100644
> --- a/misc/Makefile
> +++ b/misc/Makefile
> @@ -73,7 +73,7 @@ routines := brk sbrk sstk ioctl \
> fgetxattr flistxattr fremovexattr fsetxattr getxattr \
> listxattr lgetxattr llistxattr lremovexattr lsetxattr \
> removexattr setxattr getauxval ifunc-impl-list makedev \
> - allocate_once fd_to_filename single_threaded
> + allocate_once fd_to_filename single_threaded unwind-link
>
> generated += tst-error1.mtrace tst-error1-mem.out \
> tst-allocate_once.mtrace tst-allocate_once-mem.out
> diff --git a/misc/Versions b/misc/Versions
> index 95666f6548..d5b348e83a 100644
> --- a/misc/Versions
> +++ b/misc/Versions
> @@ -172,5 +172,6 @@ libc {
> __mmap; __munmap; __mprotect;
> __sched_get_priority_min; __sched_get_priority_max;
> __libc_allocate_once_slow;
> + __libc_unwind_link_get;
> }
> }
> diff --git a/misc/unwind-link.c b/misc/unwind-link.c
> new file mode 100644
> index 0000000000..ad3d02bf32
> --- /dev/null
> +++ b/misc/unwind-link.c
> @@ -0,0 +1,145 @@
> +/* Dynamic loading of the libgcc unwinder.
> + 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; if not, see
> + <https://www.gnu.org/licenses/>. */
> +
> +#ifdef SHARED
> +
> +#include <assert.h>
> +#include <dlfcn.h>
> +#include <gnu/lib-names.h>
> +#include <unwind-link.h>
> +#include <libc-lock.h>
> +
> +/* Statically allocate the object, so that we do not have to deal with
> + malloc failure. __libc_unwind_link_get must not fail if libgcc_s
> + has already been loaded by other means. */
> +static struct unwind_link global;
> +
> +/* dlopen handle. Also used for the double-checked locking idiom. */
> +static void *global_libgcc_handle;
> +
> +/* We cannot use __libc_once because the pthread_once implementation
> + may depend on unwinding. */
> +__libc_lock_define (static, lock);
> +
> +struct unwind_link *
> +__libc_unwind_link_get (void)
> +{
> + /* Double-checked locking idiom. Synchronizes with the release MO
> + store at the end of this function. */
> + if (atomic_load_acquire (&global_libgcc_handle) != NULL)
> + return &global;
> +
> + /* Initialize a copy of the data, so that we do not need about
> + unlocking in case the dynamic loader somehow triggers
> + unwinding. */
> + void *local_libgcc_handle = __libc_dlopen (LIBGCC_S_SO);
> + if (local_libgcc_handle == NULL)
> + {
> + __libc_lock_unlock (lock);
> + return NULL;
> + }
> +
> + struct unwind_link local;
> + local.ptr__Unwind_Backtrace
> + = __libc_dlsym (local_libgcc_handle, "_Unwind_Backtrace");
> + local.ptr__Unwind_ForcedUnwind
> + = __libc_dlsym (local_libgcc_handle, "_Unwind_ForcedUnwind");
> + local.ptr__Unwind_GetCFA
> + = __libc_dlsym (local_libgcc_handle, "_Unwind_GetCFA");
> +#if UNWIND_LINK_GETIP
> + local.ptr__Unwind_GetIP
> + = __libc_dlsym (local_libgcc_handle, "_Unwind_GetIP");
> +#endif
> + local.ptr__Unwind_Resume
> + = __libc_dlsym (local_libgcc_handle, "_Unwind_Resume");
> +#if UNWIND_LINK_FRAME_STATE_FOR
> + local.ptr___frame_state_for
> + = __libc_dlsym (local_libgcc_handle, "__frame_state_for");
> +#endif
> + local.ptr_personality
> + = __libc_dlsym (local_libgcc_handle, "__gcc_personality_v0");
> + UNWIND_LINK_EXTRA_INIT
> +
> + /* If a symbol is missing, libgcc_s has somehow been corrupted. */
> + assert (local.ptr__Unwind_Backtrace != NULL);
> + assert (local.ptr__Unwind_ForcedUnwind != NULL);
> + assert (local.ptr__Unwind_GetCFA != NULL);
> +#if UNWIND_LINK_GETIP
> + assert (local.ptr__Unwind_GetIP != NULL);
> +#endif
> + assert (local.ptr__Unwind_Resume != NULL);
> + assert (local.ptr_personality != NULL);
> +
> +#ifdef PTR_MANGLE
> + PTR_MANGLE (local.ptr__Unwind_Backtrace);
> + PTR_MANGLE (local.ptr__Unwind_ForcedUnwind);
> + PTR_MANGLE (local.ptr__Unwind_GetCFA);
> +# if UNWIND_LINK_GETIP
> + PTR_MANGLE (local.ptr__Unwind_GetIP);
> +# endif
> + PTR_MANGLE (local.ptr__Unwind_Resume);
> +# if UNWIND_LINK_FRAME_STATE_FOR
> + PTR_MANGLE (local.ptr___frame_state_for);
> +# endif
> + PTR_MANGLE (local.ptr_personality);
> +#endif
> +
> + __libc_lock_lock (lock);
> + if (atomic_load_relaxed (&global_libgcc_handle) != NULL)
> + /* This thread lost the race. Clean up. */
> + __libc_dlclose (local_libgcc_handle);
> + else
> + {
> + global = local;
> +
> + /* Completes the double-checked locking idiom. */
> + atomic_store_release (&global_libgcc_handle, local_libgcc_handle);
> + }
> +
> + __libc_lock_unlock (lock);
> + return &global;
> +}
> +libc_hidden_def (__libc_unwind_link_get)
> +
> +void
> +__libc_unwind_link_after_fork (void)
> +{
> + if (__libc_lock_trylock (lock) == 0)
> + /* The lock was not acquired during the fork. This covers both
> + the initialized and uninitialized case. */
> + __libc_lock_unlock (lock);
> + else
> + {
> + /* Initialization was in progress in another thread.
> + Reinitialize the lock. */
> + __libc_lock_init (lock);
> + global_libgcc_handle = NULL;
> + }
> +}
> +
> +void __libc_freeres_fn_section
> +__libc_unwind_link_freeres (void)
> +{
> + if (global_libgcc_handle != NULL)
> + {
> + __libc_dlclose (global_libgcc_handle );
> + global_libgcc_handle = NULL;
> + }
> +}
OK.
> +
> +#endif /* SHARED */
> diff --git a/sysdeps/alpha/unwind-arch.h b/sysdeps/alpha/unwind-arch.h
> new file mode 100644
> index 0000000000..9cb37fa604
> --- /dev/null
> +++ b/sysdeps/alpha/unwind-arch.h
> @@ -0,0 +1,28 @@
> +/* Dynamic loading of the libgcc unwinder. alpha customization.
> + 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; if not, see
> + <https://www.gnu.org/licenses/>. */
> +
> +#ifndef _ARCH_UNWIND_LINK_H
> +#define _ARCH_UNWIND_LINK_H
> +
> +#define UNWIND_LINK_GETIP 1
> +#define UNWIND_LINK_FRAME_STATE_FOR 1
> +#define UNWIND_LINK_FRAME_ADJUSTMENT 0
> +#define UNWIND_LINK_EXTRA_FIELDS
> +#define UNWIND_LINK_EXTRA_INIT
OK.
> +
> +#endif /* _ARCH_UNWIND_LINK_H */
> diff --git a/sysdeps/arm/unwind-arch.h b/sysdeps/arm/unwind-arch.h
> new file mode 100644
> index 0000000000..fcf889b3c7
> --- /dev/null
> +++ b/sysdeps/arm/unwind-arch.h
> @@ -0,0 +1,35 @@
> +/* Dynamic loading of the libgcc unwinder. Arm customization.
> + 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; if not, see
> + <https://www.gnu.org/licenses/>. */
> +
> +#ifndef _ARCH_UNWIND_LINK_H
> +#define _ARCH_UNWIND_LINK_H
> +
> +/* On arm, _Unwind_GetIP is a macro. */
> +#define UNWIND_LINK_GETIP 0
> +
> +#define UNWIND_LINK_FRAME_STATE_FOR 0
> +#define UNWIND_LINK_FRAME_ADJUSTMENT 0
> +#define UNWIND_LINK_EXTRA_FIELDS \
> + __typeof (_Unwind_VRS_Get) *ptr__Unwind_VRS_Get;
> +#define UNWIND_LINK_EXTRA_INIT \
> + local.ptr__Unwind_VRS_Get \
> + = __libc_dlsym (local_libgcc_handle, "_Unwind_VRS_Get"); \
> + assert (local.ptr__Unwind_VRS_Get != NULL); \
> + PTR_MANGLE (local.ptr__Unwind_VRS_Get);
> +
> +#endif /* _ARCH_UNWIND_LINK_H */
> diff --git a/sysdeps/generic/unwind-arch.h b/sysdeps/generic/unwind-arch.h
> index feda585e8d..ead6674279 100644
> --- a/sysdeps/generic/unwind-arch.h
> +++ b/sysdeps/generic/unwind-arch.h
> @@ -1,5 +1,5 @@
> -/* Return backtrace of current program state. Arch-specific bits.
> - Copyright (C) 2020-2021 Free Software Foundation, Inc.
> +/* Dynamic loading of the libgcc unwinder. Generic version of parameters.
> + 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
> @@ -16,15 +16,20 @@
> License along with the GNU C Library; if not, see
> <https://www.gnu.org/licenses/>. */
>
> -#ifndef _UNWIND_ARCH_H
> -#define _UNWIND_ARCH_H
> +#ifndef _ARCH_UNWIND_LINK_H
> +#define _ARCH_UNWIND_LINK_H
>
> -#include <unwind.h>
> +/* The _Unwind_GetIP function is supported. */
> +#define UNWIND_LINK_GETIP 1
>
> -static inline void *
> -unwind_arch_adjustment (void *prev, void *addr)
> -{
> - return addr;
> -}
> +/* The __frame_state_for function is needed and re-exported from glibc. */
> +#define UNWIND_LINK_FRAME_STATE_FOR 0
>
> -#endif
> +/* No adjustment of the is needed. */
> +#define UNWIND_LINK_FRAME_ADJUSTMENT 0
> +
> +/* There are no extra fields in struct unwind_link in the generic version. */
> +#define UNWIND_LINK_EXTRA_FIELDS
> +#define UNWIND_LINK_EXTRA_INIT
> +
> +#endif /* _ARCH_UNWIND_LINK_H */
> diff --git a/sysdeps/generic/unwind-link.h b/sysdeps/generic/unwind-link.h
> new file mode 100644
> index 0000000000..3527cebe2d
> --- /dev/null
> +++ b/sysdeps/generic/unwind-link.h
> @@ -0,0 +1,106 @@
> +/* Dynamic loading of the libgcc unwinder. Generic 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; if not, see
> + <https://www.gnu.org/licenses/>. */
> +
> +#ifndef _UNWIND_LINK_H
> +#define _UNWIND_LINK_H
> +
> +#include <unwind.h>
> +#include <unwind-arch.h>
> +
> +#if !UNWIND_LINK_FRAME_ADJUSTMENT
> +static inline void *
> +unwind_arch_adjustment (void *prev, void *addr)
> +{
> + return addr;
> +}
> +#endif
> +
> +#ifdef SHARED
> +# include <sysdep.h>
> +# include <unwind-resume.h>
> +
> +# if UNWIND_LINK_FRAME_STATE_FOR
> +struct frame_state;
> +# endif
> +
> +struct unwind_link
> +{
> + __typeof (_Unwind_Backtrace) *ptr__Unwind_Backtrace;
> + __typeof (_Unwind_ForcedUnwind) *ptr__Unwind_ForcedUnwind;
> + __typeof (_Unwind_GetCFA) *ptr__Unwind_GetCFA;
> +# if UNWIND_LINK_GETIP
> + __typeof (_Unwind_GetIP) *ptr__Unwind_GetIP;
> +# endif
> + __typeof (_Unwind_Resume) *ptr__Unwind_Resume;
> +#if UNWIND_LINK_FRAME_STATE_FOR
> + struct frame_state *(*ptr___frame_state_for) (void *, struct frame_state *);
> +#endif
> + _Unwind_Reason_Code (*ptr_personality) PERSONALITY_PROTO;
> + UNWIND_LINK_EXTRA_FIELDS
> +};
> +
> +/* Return a pointer to the implementation, or NULL on failure. */
> +struct unwind_link *__libc_unwind_link_get (void);
> +libc_hidden_proto (__libc_unwind_link_get)
> +
> +/* UNWIND_LINK_PTR returns the stored function pointer NAME from the
> + cached unwind link OBJ (which was previously returned by
> + __libc_unwind_link_get). */
> +# ifdef PTR_DEMANGLE
> +# define UNWIND_LINK_PTR(obj, name, ...) \
> + ({ \
> + __typeof ((obj)->ptr_##name) __unwind_fptr = (obj)->ptr_##name; \
> + PTR_DEMANGLE (__unwind_fptr); \
> + __unwind_fptr; \
> + })
> +# else /* !PTR_DEMANGLE */
> +# define UNWIND_LINK_PTR(obj, name, ...) ((obj)->ptr_##name)
> +# endif
> +
> +/* Called from fork, in the new subprocess. */
> +void __libc_unwind_link_after_fork (void);
> +
> +/* Called from __libc_freeres. */
> +void __libc_unwind_link_freeres (void) attribute_hidden;
> +
> +#else /* !SHARED */
> +
> +/* Dummy implementation so that the code can be shared with the SHARED
> + version. */
> +struct unwind_link;
> +static inline struct unwind_link *
> +__libc_unwind_link_get (void)
> +{
> + /* Return something that is not a null pointer, so that error checks
> + succeed. */
> + return (struct unwind_link *) 1;
> +}
> +
> +/* Directly call the static implementation. */
> +# define UNWIND_LINK_PTR(obj, name, ...) \
> + ((void) (obj), &name)
> +
> +static inline void
> +__libc_unwind_link_after_fork (void)
> +{
> + /* No need to clean up if the unwinder is statically linked. */
> +}
> +
> +#endif /* !SHARED */
> +
> +#endif /* _UNWIND_LINK_H */
> diff --git a/sysdeps/i386/unwind-arch.h b/sysdeps/i386/unwind-arch.h
> new file mode 100644
> index 0000000000..01c74fe814
> --- /dev/null
> +++ b/sysdeps/i386/unwind-arch.h
> @@ -0,0 +1,39 @@
> +/* Dynamic loading of the libgcc unwinder. i386 customization.
> + 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; if not, see
> + <https://www.gnu.org/licenses/>. */
> +
> +#ifndef _ARCH_UNWIND_LINK_H
> +#define _ARCH_UNWIND_LINK_H
> +
> +#define UNWIND_LINK_GETIP 1
> +#define UNWIND_LINK_FRAME_STATE_FOR 1
> +#define UNWIND_LINK_FRAME_ADJUSTMENT 0
> +#define UNWIND_LINK_EXTRA_FIELDS \
> + __typeof (_Unwind_GetGR) *ptr__Unwind_GetGR;
> +#define UNWIND_LINK_EXTRA_INIT_SHARED \
> + local.ptr__Unwind_GetGR \
> + = __libc_dlsym (local_libgcc_handle, "_Unwind_GetGR"); \
> + assert (local.ptr__Unwind_GetGR != NULL);
> +#ifdef PTR_MANGLE
> +# define UNWIND_LINK_EXTRA_INIT \
> + UNWIND_LINK_EXTRA_INIT_SHARED \
> + PTR_MANGLE (local.ptr__Unwind_GetGR);
> +#else
> +# define UNWIND_LINK_EXTRA_INIT UNWIND_LINK_EXTRA_INIT_SHARED
> +#endif
> +
> +#endif /* _ARCH_UNWIND_LINK_H */
> diff --git a/sysdeps/ia64/unwind-arch.h b/sysdeps/ia64/unwind-arch.h
> new file mode 100644
> index 0000000000..df294dedbe
> --- /dev/null
> +++ b/sysdeps/ia64/unwind-arch.h
> @@ -0,0 +1,32 @@
> +/* Dynamic loading of the libgcc unwinder. ia64 customization.
> + 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; if not, see
> + <https://www.gnu.org/licenses/>. */
> +
> +#ifndef _ARCH_UNWIND_LINK_H
> +
> +#define UNWIND_LINK_GETIP 1
> +#define UNWIND_LINK_FRAME_STATE_FOR 1
> +#define UNWIND_LINK_FRAME_ADJUSTMENT 0
> +#define UNWIND_LINK_EXTRA_FIELDS \
> + __typeof (_Unwind_GetBSP) *ptr__Unwind_GetBSP;
> +#define UNWIND_LINK_EXTRA_INIT \
> + local.ptr__Unwind_GetBSP \
> + = __libc_dlsym (local_libgcc_handle, "_Unwind_GetBSP"); \
> + assert (local.ptr__Unwind_GetBSP != NULL); \
> + PTR_MANGLE (local.ptr__Unwind_GetBSP);
> +
> +#endif /* _ARCH_UNWIND_LINK_H */
> diff --git a/sysdeps/m68k/m680x0/unwind-arch.h b/sysdeps/m68k/m680x0/unwind-arch.h
> new file mode 100644
> index 0000000000..fea71d45ce
> --- /dev/null
> +++ b/sysdeps/m68k/m680x0/unwind-arch.h
> @@ -0,0 +1,26 @@
> +/* Dynamic loading of the libgcc unwinder. Baseline m68k customization.
> + 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; if not, see
> + <https://www.gnu.org/licenses/>. */
> +
> +#ifndef _ARCH_UNWIND_LINK_H
> +
> +#include <sysdeps/m68k/unwind-arch.h>
> +
> +#undef UNWIND_LINK_FRAME_STATE_FOR
> +#define UNWIND_LINK_FRAME_STATE_FOR 1
> +
> +#endif /* _ARCH_UNWIND_LINK_H */
> diff --git a/sysdeps/m68k/unwind-arch.h b/sysdeps/m68k/unwind-arch.h
> new file mode 100644
> index 0000000000..37f1013c7e
> --- /dev/null
> +++ b/sysdeps/m68k/unwind-arch.h
> @@ -0,0 +1,35 @@
> +/* Dynamic loading of the libgcc unwinder. m68k customization.
> + 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; if not, see
> + <https://www.gnu.org/licenses/>. */
> +
> +#ifndef _ARCH_UNWIND_LINK_H
> +#define _ARCH_UNWIND_LINK_H
> +
> +#define UNWIND_LINK_GETIP 1
> +#define UNWIND_LINK_FRAME_ADJUSTMENT 0
> +#define UNWIND_LINK_EXTRA_FIELDS \
> + __typeof (_Unwind_GetGR) *ptr__Unwind_GetGR;
> +#define UNWIND_LINK_EXTRA_INIT \
> + local.ptr__Unwind_GetGR \
> + = __libc_dlsym (local_libgcc_handle, "_Unwind_GetGR"); \
> + assert (local.ptr__Unwind_GetGR != NULL); \
> + PTR_MANGLE (local.ptr__Unwind_GetGR);
> +
> +/* This is overriden by the m680x0 variant. */
> +#define UNWIND_LINK_FRAME_STATE_FOR 0
> +
> +#endif /* _ARCH_UNWIND_LINK_H */
> diff --git a/sysdeps/mach/hurd/fork.c b/sysdeps/mach/hurd/fork.c
> index fb6c7ee8b7..2b39f4e8b5 100644
> --- a/sysdeps/mach/hurd/fork.c
> +++ b/sysdeps/mach/hurd/fork.c
> @@ -29,6 +29,7 @@
> #include <tls.h>
> #include <malloc/malloc-internal.h>
> #include <nss/nss_database.h>
> +#include <unwind-link.h>
>
> #undef __fork
>
> @@ -667,6 +668,8 @@ __fork (void)
> __sigemptyset (&_hurd_global_sigstate->pending);
> __sigemptyset (&ss->pending);
>
> + __libc_unwind_link_after_fork ();
> +
> /* Release malloc locks. */
> _hurd_malloc_fork_child ();
> call_function_static_weak (__malloc_fork_unlock_child);
> diff --git a/sysdeps/unix/sysv/linux/mips/unwind-arch.h b/sysdeps/mips/unwind-arch.h
> similarity index 85%
> rename from sysdeps/unix/sysv/linux/mips/unwind-arch.h
> rename to sysdeps/mips/unwind-arch.h
> index 38bc60cde6..78de42e001 100644
> --- a/sysdeps/unix/sysv/linux/mips/unwind-arch.h
> +++ b/sysdeps/mips/unwind-arch.h
> @@ -1,4 +1,4 @@
> -/* Return backtrace of current program state. Arch-specific bits.
> +/* Dynamic loading of the libgcc unwinder. MIPS customization.
> Copyright (C) 2020-2021 Free Software Foundation, Inc.
> This file is part of the GNU C Library.
>
> @@ -16,10 +16,17 @@
> License along with the GNU C Library; if not, see
> <https://www.gnu.org/licenses/>. */
>
> -#ifndef _UNWIND_ARCH_H
> -#define _UNWIND_ARCH_H
> +#ifndef _ARCH_UNWIND_LINK_H
> +#define _ARCH_UNWIND_LINK_H
>
> #include <stdint.h>
> +#include <sys/syscall.h>
> +
> +#define UNWIND_LINK_GETIP 1
> +#define UNWIND_LINK_FRAME_STATE_FOR 1
> +#define UNWIND_LINK_FRAME_ADJUSTMENT 1
> +#define UNWIND_LINK_EXTRA_FIELDS
> +#define UNWIND_LINK_EXTRA_INIT
>
> /* MIPS fallback code handle a frame where its FDE can not be obtained
> (for instance a signal frame) by reading the kernel allocated signal frame
> @@ -49,7 +56,7 @@ unwind_arch_adjustment (void *prev, void *addr)
>
> 24021061 li v0, 0x1061 (rt_sigreturn)
> 0000000c syscall
> - or
> + or
> 24021017 li v0, 0x1017 (sigreturn)
> 0000000c syscall */
> if (pc[1] != 0x0000000c)
> @@ -64,4 +71,4 @@ unwind_arch_adjustment (void *prev, void *addr)
> return addr;
> }
>
> -#endif
> +#endif /* _ARCH_UNWIND_LINK_H */
> diff --git a/sysdeps/nptl/fork.c b/sysdeps/nptl/fork.c
> index 26703d958f..4fb4c2d254 100644
> --- a/sysdeps/nptl/fork.c
> +++ b/sysdeps/nptl/fork.c
> @@ -33,6 +33,7 @@
> #include <futex-internal.h>
> #include <malloc/malloc-internal.h>
> #include <nss/nss_database.h>
> +#include <unwind-link.h>
>
> static void
> fresetlockfiles (void)
> @@ -116,6 +117,8 @@ __libc_fork (void)
> /* Reset the lock state in the multi-threaded case. */
> if (multiple_threads)
> {
> + __libc_unwind_link_after_fork ();
> +
> /* Release malloc locks. */
> call_function_static_weak (__malloc_fork_unlock_child);
>
> diff --git a/sysdeps/powerpc/powerpc32/unwind-arch.h b/sysdeps/powerpc/powerpc32/unwind-arch.h
> new file mode 100644
> index 0000000000..f2869ac3ae
> --- /dev/null
> +++ b/sysdeps/powerpc/powerpc32/unwind-arch.h
> @@ -0,0 +1,28 @@
> +/* Dynamic loading of the libgcc unwinder. powerpc customization.
> + 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; if not, see
> + <https://www.gnu.org/licenses/>. */
> +
> +#ifndef _ARCH_UNWIND_LINK_H
> +#define _ARCH_UNWIND_LINK_H
> +
> +#define UNWIND_LINK_GETIP 1
> +#define UNWIND_LINK_FRAME_STATE_FOR 1
> +#define UNWIND_LINK_FRAME_ADJUSTMENT 0
> +#define UNWIND_LINK_EXTRA_FIELDS
> +#define UNWIND_LINK_EXTRA_INIT
> +
> +#endif /* _ARCH_UNWIND_LINK_H */
> diff --git a/sysdeps/s390/unwind-arch.h b/sysdeps/s390/unwind-arch.h
> new file mode 100644
> index 0000000000..64d976de03
> --- /dev/null
> +++ b/sysdeps/s390/unwind-arch.h
> @@ -0,0 +1,28 @@
> +/* Dynamic loading of the libgcc unwinder. S/390 customization.
> + 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; if not, see
> + <https://www.gnu.org/licenses/>. */
> +
> +#ifndef _ARCH_UNWIND_LINK_H
> +#define _ARCH_UNWIND_LINK_H
> +
> +#define UNWIND_LINK_GETIP 1
> +#define UNWIND_LINK_FRAME_STATE_FOR 1
> +#define UNWIND_LINK_FRAME_ADJUSTMENT 0
> +#define UNWIND_LINK_EXTRA_FIELDS
> +#define UNWIND_LINK_EXTRA_INIT
> +
> +#endif /* _ARCH_UNWIND_LINK_H */
> diff --git a/sysdeps/sh/unwind-arch.h b/sysdeps/sh/unwind-arch.h
> new file mode 100644
> index 0000000000..8fdac6322b
> --- /dev/null
> +++ b/sysdeps/sh/unwind-arch.h
> @@ -0,0 +1,28 @@
> +/* Dynamic loading of the libgcc unwinder. SH customization.
> + 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; if not, see
> + <https://www.gnu.org/licenses/>. */
> +
> +#ifndef _ARCH_UNWIND_LINK_H
> +#define _ARCH_UNWIND_LINK_H
> +
> +#define UNWIND_LINK_GETIP 1
> +#define UNWIND_LINK_FRAME_STATE_FOR 1
> +#define UNWIND_LINK_FRAME_ADJUSTMENT 0
> +#define UNWIND_LINK_EXTRA_FIELDS
> +#define UNWIND_LINK_EXTRA_INIT
> +
> +#endif /* _ARCH_UNWIND_LINK_H */
> diff --git a/sysdeps/sparc/unwind-arch.h b/sysdeps/sparc/unwind-arch.h
> new file mode 100644
> index 0000000000..299fa006be
> --- /dev/null
> +++ b/sysdeps/sparc/unwind-arch.h
> @@ -0,0 +1,28 @@
> +/* Dynamic loading of the libgcc unwinder. SPARC customization.
> + 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; if not, see
> + <https://www.gnu.org/licenses/>. */
> +
> +#ifndef _ARCH_UNWIND_LINK_H
> +#define _ARCH_UNWIND_LINK_H
> +
> +#define UNWIND_LINK_GETIP 1
> +#define UNWIND_LINK_FRAME_STATE_FOR 1
> +#define UNWIND_LINK_FRAME_ADJUSTMENT 0
> +#define UNWIND_LINK_EXTRA_FIELDS
> +#define UNWIND_LINK_EXTRA_INIT
> +
> +#endif /* _ARCH_UNWIND_LINK_H */
>
@@ -23,7 +23,7 @@
#include <gnu/lib-names.h>
#include <stdlib.h>
#include <unwind.h>
-#include <unwind-arch.h>
+#include <unwind-link.h>
struct trace_arg
{
@@ -19,6 +19,7 @@
#include <stdlib.h>
#include <set-hooks.h>
#include <libc-internal.h>
+#include <unwind-link.h>
#include "../nss/nsswitch.h"
#include "../libio/libioP.h"
@@ -61,6 +62,10 @@ __libc_freeres (void)
if (&__libpthread_freeres != NULL)
__libpthread_freeres ();
+#ifdef SHARED
+ __libc_unwind_link_freeres ();
+#endif
+
for (p = symbol_set_first_element (__libc_freeres_ptrs);
!symbol_set_end_p (__libc_freeres_ptrs, p); ++p)
free (*p);
@@ -73,7 +73,7 @@ routines := brk sbrk sstk ioctl \
fgetxattr flistxattr fremovexattr fsetxattr getxattr \
listxattr lgetxattr llistxattr lremovexattr lsetxattr \
removexattr setxattr getauxval ifunc-impl-list makedev \
- allocate_once fd_to_filename single_threaded
+ allocate_once fd_to_filename single_threaded unwind-link
generated += tst-error1.mtrace tst-error1-mem.out \
tst-allocate_once.mtrace tst-allocate_once-mem.out
@@ -172,5 +172,6 @@ libc {
__mmap; __munmap; __mprotect;
__sched_get_priority_min; __sched_get_priority_max;
__libc_allocate_once_slow;
+ __libc_unwind_link_get;
}
}
new file mode 100644
@@ -0,0 +1,145 @@
+/* Dynamic loading of the libgcc unwinder.
+ 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; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#ifdef SHARED
+
+#include <assert.h>
+#include <dlfcn.h>
+#include <gnu/lib-names.h>
+#include <unwind-link.h>
+#include <libc-lock.h>
+
+/* Statically allocate the object, so that we do not have to deal with
+ malloc failure. __libc_unwind_link_get must not fail if libgcc_s
+ has already been loaded by other means. */
+static struct unwind_link global;
+
+/* dlopen handle. Also used for the double-checked locking idiom. */
+static void *global_libgcc_handle;
+
+/* We cannot use __libc_once because the pthread_once implementation
+ may depend on unwinding. */
+__libc_lock_define (static, lock);
+
+struct unwind_link *
+__libc_unwind_link_get (void)
+{
+ /* Double-checked locking idiom. Synchronizes with the release MO
+ store at the end of this function. */
+ if (atomic_load_acquire (&global_libgcc_handle) != NULL)
+ return &global;
+
+ /* Initialize a copy of the data, so that we do not need about
+ unlocking in case the dynamic loader somehow triggers
+ unwinding. */
+ void *local_libgcc_handle = __libc_dlopen (LIBGCC_S_SO);
+ if (local_libgcc_handle == NULL)
+ {
+ __libc_lock_unlock (lock);
+ return NULL;
+ }
+
+ struct unwind_link local;
+ local.ptr__Unwind_Backtrace
+ = __libc_dlsym (local_libgcc_handle, "_Unwind_Backtrace");
+ local.ptr__Unwind_ForcedUnwind
+ = __libc_dlsym (local_libgcc_handle, "_Unwind_ForcedUnwind");
+ local.ptr__Unwind_GetCFA
+ = __libc_dlsym (local_libgcc_handle, "_Unwind_GetCFA");
+#if UNWIND_LINK_GETIP
+ local.ptr__Unwind_GetIP
+ = __libc_dlsym (local_libgcc_handle, "_Unwind_GetIP");
+#endif
+ local.ptr__Unwind_Resume
+ = __libc_dlsym (local_libgcc_handle, "_Unwind_Resume");
+#if UNWIND_LINK_FRAME_STATE_FOR
+ local.ptr___frame_state_for
+ = __libc_dlsym (local_libgcc_handle, "__frame_state_for");
+#endif
+ local.ptr_personality
+ = __libc_dlsym (local_libgcc_handle, "__gcc_personality_v0");
+ UNWIND_LINK_EXTRA_INIT
+
+ /* If a symbol is missing, libgcc_s has somehow been corrupted. */
+ assert (local.ptr__Unwind_Backtrace != NULL);
+ assert (local.ptr__Unwind_ForcedUnwind != NULL);
+ assert (local.ptr__Unwind_GetCFA != NULL);
+#if UNWIND_LINK_GETIP
+ assert (local.ptr__Unwind_GetIP != NULL);
+#endif
+ assert (local.ptr__Unwind_Resume != NULL);
+ assert (local.ptr_personality != NULL);
+
+#ifdef PTR_MANGLE
+ PTR_MANGLE (local.ptr__Unwind_Backtrace);
+ PTR_MANGLE (local.ptr__Unwind_ForcedUnwind);
+ PTR_MANGLE (local.ptr__Unwind_GetCFA);
+# if UNWIND_LINK_GETIP
+ PTR_MANGLE (local.ptr__Unwind_GetIP);
+# endif
+ PTR_MANGLE (local.ptr__Unwind_Resume);
+# if UNWIND_LINK_FRAME_STATE_FOR
+ PTR_MANGLE (local.ptr___frame_state_for);
+# endif
+ PTR_MANGLE (local.ptr_personality);
+#endif
+
+ __libc_lock_lock (lock);
+ if (atomic_load_relaxed (&global_libgcc_handle) != NULL)
+ /* This thread lost the race. Clean up. */
+ __libc_dlclose (local_libgcc_handle);
+ else
+ {
+ global = local;
+
+ /* Completes the double-checked locking idiom. */
+ atomic_store_release (&global_libgcc_handle, local_libgcc_handle);
+ }
+
+ __libc_lock_unlock (lock);
+ return &global;
+}
+libc_hidden_def (__libc_unwind_link_get)
+
+void
+__libc_unwind_link_after_fork (void)
+{
+ if (__libc_lock_trylock (lock) == 0)
+ /* The lock was not acquired during the fork. This covers both
+ the initialized and uninitialized case. */
+ __libc_lock_unlock (lock);
+ else
+ {
+ /* Initialization was in progress in another thread.
+ Reinitialize the lock. */
+ __libc_lock_init (lock);
+ global_libgcc_handle = NULL;
+ }
+}
+
+void __libc_freeres_fn_section
+__libc_unwind_link_freeres (void)
+{
+ if (global_libgcc_handle != NULL)
+ {
+ __libc_dlclose (global_libgcc_handle );
+ global_libgcc_handle = NULL;
+ }
+}
+
+#endif /* SHARED */
new file mode 100644
@@ -0,0 +1,28 @@
+/* Dynamic loading of the libgcc unwinder. alpha customization.
+ 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; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#ifndef _ARCH_UNWIND_LINK_H
+#define _ARCH_UNWIND_LINK_H
+
+#define UNWIND_LINK_GETIP 1
+#define UNWIND_LINK_FRAME_STATE_FOR 1
+#define UNWIND_LINK_FRAME_ADJUSTMENT 0
+#define UNWIND_LINK_EXTRA_FIELDS
+#define UNWIND_LINK_EXTRA_INIT
+
+#endif /* _ARCH_UNWIND_LINK_H */
new file mode 100644
@@ -0,0 +1,35 @@
+/* Dynamic loading of the libgcc unwinder. Arm customization.
+ 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; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#ifndef _ARCH_UNWIND_LINK_H
+#define _ARCH_UNWIND_LINK_H
+
+/* On arm, _Unwind_GetIP is a macro. */
+#define UNWIND_LINK_GETIP 0
+
+#define UNWIND_LINK_FRAME_STATE_FOR 0
+#define UNWIND_LINK_FRAME_ADJUSTMENT 0
+#define UNWIND_LINK_EXTRA_FIELDS \
+ __typeof (_Unwind_VRS_Get) *ptr__Unwind_VRS_Get;
+#define UNWIND_LINK_EXTRA_INIT \
+ local.ptr__Unwind_VRS_Get \
+ = __libc_dlsym (local_libgcc_handle, "_Unwind_VRS_Get"); \
+ assert (local.ptr__Unwind_VRS_Get != NULL); \
+ PTR_MANGLE (local.ptr__Unwind_VRS_Get);
+
+#endif /* _ARCH_UNWIND_LINK_H */
@@ -1,5 +1,5 @@
-/* Return backtrace of current program state. Arch-specific bits.
- Copyright (C) 2020-2021 Free Software Foundation, Inc.
+/* Dynamic loading of the libgcc unwinder. Generic version of parameters.
+ 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
@@ -16,15 +16,20 @@
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
-#ifndef _UNWIND_ARCH_H
-#define _UNWIND_ARCH_H
+#ifndef _ARCH_UNWIND_LINK_H
+#define _ARCH_UNWIND_LINK_H
-#include <unwind.h>
+/* The _Unwind_GetIP function is supported. */
+#define UNWIND_LINK_GETIP 1
-static inline void *
-unwind_arch_adjustment (void *prev, void *addr)
-{
- return addr;
-}
+/* The __frame_state_for function is needed and re-exported from glibc. */
+#define UNWIND_LINK_FRAME_STATE_FOR 0
-#endif
+/* No adjustment of the is needed. */
+#define UNWIND_LINK_FRAME_ADJUSTMENT 0
+
+/* There are no extra fields in struct unwind_link in the generic version. */
+#define UNWIND_LINK_EXTRA_FIELDS
+#define UNWIND_LINK_EXTRA_INIT
+
+#endif /* _ARCH_UNWIND_LINK_H */
new file mode 100644
@@ -0,0 +1,106 @@
+/* Dynamic loading of the libgcc unwinder. Generic 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; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#ifndef _UNWIND_LINK_H
+#define _UNWIND_LINK_H
+
+#include <unwind.h>
+#include <unwind-arch.h>
+
+#if !UNWIND_LINK_FRAME_ADJUSTMENT
+static inline void *
+unwind_arch_adjustment (void *prev, void *addr)
+{
+ return addr;
+}
+#endif
+
+#ifdef SHARED
+# include <sysdep.h>
+# include <unwind-resume.h>
+
+# if UNWIND_LINK_FRAME_STATE_FOR
+struct frame_state;
+# endif
+
+struct unwind_link
+{
+ __typeof (_Unwind_Backtrace) *ptr__Unwind_Backtrace;
+ __typeof (_Unwind_ForcedUnwind) *ptr__Unwind_ForcedUnwind;
+ __typeof (_Unwind_GetCFA) *ptr__Unwind_GetCFA;
+# if UNWIND_LINK_GETIP
+ __typeof (_Unwind_GetIP) *ptr__Unwind_GetIP;
+# endif
+ __typeof (_Unwind_Resume) *ptr__Unwind_Resume;
+#if UNWIND_LINK_FRAME_STATE_FOR
+ struct frame_state *(*ptr___frame_state_for) (void *, struct frame_state *);
+#endif
+ _Unwind_Reason_Code (*ptr_personality) PERSONALITY_PROTO;
+ UNWIND_LINK_EXTRA_FIELDS
+};
+
+/* Return a pointer to the implementation, or NULL on failure. */
+struct unwind_link *__libc_unwind_link_get (void);
+libc_hidden_proto (__libc_unwind_link_get)
+
+/* UNWIND_LINK_PTR returns the stored function pointer NAME from the
+ cached unwind link OBJ (which was previously returned by
+ __libc_unwind_link_get). */
+# ifdef PTR_DEMANGLE
+# define UNWIND_LINK_PTR(obj, name, ...) \
+ ({ \
+ __typeof ((obj)->ptr_##name) __unwind_fptr = (obj)->ptr_##name; \
+ PTR_DEMANGLE (__unwind_fptr); \
+ __unwind_fptr; \
+ })
+# else /* !PTR_DEMANGLE */
+# define UNWIND_LINK_PTR(obj, name, ...) ((obj)->ptr_##name)
+# endif
+
+/* Called from fork, in the new subprocess. */
+void __libc_unwind_link_after_fork (void);
+
+/* Called from __libc_freeres. */
+void __libc_unwind_link_freeres (void) attribute_hidden;
+
+#else /* !SHARED */
+
+/* Dummy implementation so that the code can be shared with the SHARED
+ version. */
+struct unwind_link;
+static inline struct unwind_link *
+__libc_unwind_link_get (void)
+{
+ /* Return something that is not a null pointer, so that error checks
+ succeed. */
+ return (struct unwind_link *) 1;
+}
+
+/* Directly call the static implementation. */
+# define UNWIND_LINK_PTR(obj, name, ...) \
+ ((void) (obj), &name)
+
+static inline void
+__libc_unwind_link_after_fork (void)
+{
+ /* No need to clean up if the unwinder is statically linked. */
+}
+
+#endif /* !SHARED */
+
+#endif /* _UNWIND_LINK_H */
new file mode 100644
@@ -0,0 +1,39 @@
+/* Dynamic loading of the libgcc unwinder. i386 customization.
+ 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; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#ifndef _ARCH_UNWIND_LINK_H
+#define _ARCH_UNWIND_LINK_H
+
+#define UNWIND_LINK_GETIP 1
+#define UNWIND_LINK_FRAME_STATE_FOR 1
+#define UNWIND_LINK_FRAME_ADJUSTMENT 0
+#define UNWIND_LINK_EXTRA_FIELDS \
+ __typeof (_Unwind_GetGR) *ptr__Unwind_GetGR;
+#define UNWIND_LINK_EXTRA_INIT_SHARED \
+ local.ptr__Unwind_GetGR \
+ = __libc_dlsym (local_libgcc_handle, "_Unwind_GetGR"); \
+ assert (local.ptr__Unwind_GetGR != NULL);
+#ifdef PTR_MANGLE
+# define UNWIND_LINK_EXTRA_INIT \
+ UNWIND_LINK_EXTRA_INIT_SHARED \
+ PTR_MANGLE (local.ptr__Unwind_GetGR);
+#else
+# define UNWIND_LINK_EXTRA_INIT UNWIND_LINK_EXTRA_INIT_SHARED
+#endif
+
+#endif /* _ARCH_UNWIND_LINK_H */
new file mode 100644
@@ -0,0 +1,32 @@
+/* Dynamic loading of the libgcc unwinder. ia64 customization.
+ 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; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#ifndef _ARCH_UNWIND_LINK_H
+
+#define UNWIND_LINK_GETIP 1
+#define UNWIND_LINK_FRAME_STATE_FOR 1
+#define UNWIND_LINK_FRAME_ADJUSTMENT 0
+#define UNWIND_LINK_EXTRA_FIELDS \
+ __typeof (_Unwind_GetBSP) *ptr__Unwind_GetBSP;
+#define UNWIND_LINK_EXTRA_INIT \
+ local.ptr__Unwind_GetBSP \
+ = __libc_dlsym (local_libgcc_handle, "_Unwind_GetBSP"); \
+ assert (local.ptr__Unwind_GetBSP != NULL); \
+ PTR_MANGLE (local.ptr__Unwind_GetBSP);
+
+#endif /* _ARCH_UNWIND_LINK_H */
new file mode 100644
@@ -0,0 +1,26 @@
+/* Dynamic loading of the libgcc unwinder. Baseline m68k customization.
+ 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; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#ifndef _ARCH_UNWIND_LINK_H
+
+#include <sysdeps/m68k/unwind-arch.h>
+
+#undef UNWIND_LINK_FRAME_STATE_FOR
+#define UNWIND_LINK_FRAME_STATE_FOR 1
+
+#endif /* _ARCH_UNWIND_LINK_H */
new file mode 100644
@@ -0,0 +1,35 @@
+/* Dynamic loading of the libgcc unwinder. m68k customization.
+ 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; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#ifndef _ARCH_UNWIND_LINK_H
+#define _ARCH_UNWIND_LINK_H
+
+#define UNWIND_LINK_GETIP 1
+#define UNWIND_LINK_FRAME_ADJUSTMENT 0
+#define UNWIND_LINK_EXTRA_FIELDS \
+ __typeof (_Unwind_GetGR) *ptr__Unwind_GetGR;
+#define UNWIND_LINK_EXTRA_INIT \
+ local.ptr__Unwind_GetGR \
+ = __libc_dlsym (local_libgcc_handle, "_Unwind_GetGR"); \
+ assert (local.ptr__Unwind_GetGR != NULL); \
+ PTR_MANGLE (local.ptr__Unwind_GetGR);
+
+/* This is overriden by the m680x0 variant. */
+#define UNWIND_LINK_FRAME_STATE_FOR 0
+
+#endif /* _ARCH_UNWIND_LINK_H */
@@ -29,6 +29,7 @@
#include <tls.h>
#include <malloc/malloc-internal.h>
#include <nss/nss_database.h>
+#include <unwind-link.h>
#undef __fork
@@ -667,6 +668,8 @@ __fork (void)
__sigemptyset (&_hurd_global_sigstate->pending);
__sigemptyset (&ss->pending);
+ __libc_unwind_link_after_fork ();
+
/* Release malloc locks. */
_hurd_malloc_fork_child ();
call_function_static_weak (__malloc_fork_unlock_child);
similarity index 85%
rename from sysdeps/unix/sysv/linux/mips/unwind-arch.h
rename to sysdeps/mips/unwind-arch.h
@@ -1,4 +1,4 @@
-/* Return backtrace of current program state. Arch-specific bits.
+/* Dynamic loading of the libgcc unwinder. MIPS customization.
Copyright (C) 2020-2021 Free Software Foundation, Inc.
This file is part of the GNU C Library.
@@ -16,10 +16,17 @@
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
-#ifndef _UNWIND_ARCH_H
-#define _UNWIND_ARCH_H
+#ifndef _ARCH_UNWIND_LINK_H
+#define _ARCH_UNWIND_LINK_H
#include <stdint.h>
+#include <sys/syscall.h>
+
+#define UNWIND_LINK_GETIP 1
+#define UNWIND_LINK_FRAME_STATE_FOR 1
+#define UNWIND_LINK_FRAME_ADJUSTMENT 1
+#define UNWIND_LINK_EXTRA_FIELDS
+#define UNWIND_LINK_EXTRA_INIT
/* MIPS fallback code handle a frame where its FDE can not be obtained
(for instance a signal frame) by reading the kernel allocated signal frame
@@ -49,7 +56,7 @@ unwind_arch_adjustment (void *prev, void *addr)
24021061 li v0, 0x1061 (rt_sigreturn)
0000000c syscall
- or
+ or
24021017 li v0, 0x1017 (sigreturn)
0000000c syscall */
if (pc[1] != 0x0000000c)
@@ -64,4 +71,4 @@ unwind_arch_adjustment (void *prev, void *addr)
return addr;
}
-#endif
+#endif /* _ARCH_UNWIND_LINK_H */
@@ -33,6 +33,7 @@
#include <futex-internal.h>
#include <malloc/malloc-internal.h>
#include <nss/nss_database.h>
+#include <unwind-link.h>
static void
fresetlockfiles (void)
@@ -116,6 +117,8 @@ __libc_fork (void)
/* Reset the lock state in the multi-threaded case. */
if (multiple_threads)
{
+ __libc_unwind_link_after_fork ();
+
/* Release malloc locks. */
call_function_static_weak (__malloc_fork_unlock_child);
new file mode 100644
@@ -0,0 +1,28 @@
+/* Dynamic loading of the libgcc unwinder. powerpc customization.
+ 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; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#ifndef _ARCH_UNWIND_LINK_H
+#define _ARCH_UNWIND_LINK_H
+
+#define UNWIND_LINK_GETIP 1
+#define UNWIND_LINK_FRAME_STATE_FOR 1
+#define UNWIND_LINK_FRAME_ADJUSTMENT 0
+#define UNWIND_LINK_EXTRA_FIELDS
+#define UNWIND_LINK_EXTRA_INIT
+
+#endif /* _ARCH_UNWIND_LINK_H */
new file mode 100644
@@ -0,0 +1,28 @@
+/* Dynamic loading of the libgcc unwinder. S/390 customization.
+ 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; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#ifndef _ARCH_UNWIND_LINK_H
+#define _ARCH_UNWIND_LINK_H
+
+#define UNWIND_LINK_GETIP 1
+#define UNWIND_LINK_FRAME_STATE_FOR 1
+#define UNWIND_LINK_FRAME_ADJUSTMENT 0
+#define UNWIND_LINK_EXTRA_FIELDS
+#define UNWIND_LINK_EXTRA_INIT
+
+#endif /* _ARCH_UNWIND_LINK_H */
new file mode 100644
@@ -0,0 +1,28 @@
+/* Dynamic loading of the libgcc unwinder. SH customization.
+ 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; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#ifndef _ARCH_UNWIND_LINK_H
+#define _ARCH_UNWIND_LINK_H
+
+#define UNWIND_LINK_GETIP 1
+#define UNWIND_LINK_FRAME_STATE_FOR 1
+#define UNWIND_LINK_FRAME_ADJUSTMENT 0
+#define UNWIND_LINK_EXTRA_FIELDS
+#define UNWIND_LINK_EXTRA_INIT
+
+#endif /* _ARCH_UNWIND_LINK_H */
new file mode 100644
@@ -0,0 +1,28 @@
+/* Dynamic loading of the libgcc unwinder. SPARC customization.
+ 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; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#ifndef _ARCH_UNWIND_LINK_H
+#define _ARCH_UNWIND_LINK_H
+
+#define UNWIND_LINK_GETIP 1
+#define UNWIND_LINK_FRAME_STATE_FOR 1
+#define UNWIND_LINK_FRAME_ADJUSTMENT 0
+#define UNWIND_LINK_EXTRA_FIELDS
+#define UNWIND_LINK_EXTRA_INIT
+
+#endif /* _ARCH_UNWIND_LINK_H */