[01/10] Implement <unwind-link.h> for dynamically loading the libgcc_s unwinder

Message ID ee96e132dc4218741552c1220f9b81af3084f9e9.1613577607.git.fweimer@redhat.com
State New
Headers show
Series
  • Unwinder interface consolidation
Related show

Commit Message

Samuel Thibault via Libc-alpha Feb. 17, 2021, 4:02 p.m.
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

-- 
2.29.2

Comments

Samuel Thibault via Libc-alpha March 1, 2021, 1:54 p.m. | #1
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 */

> 



-- 
Cheers,
Carlos.

Patch

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;
+    }
+}
+
+#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
+
+#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 */