public inbox for libc-alpha@sourceware.org
 help / color / mirror / Atom feed
* [PATCH 00/10] Unwinder interface consolidation
@ 2021-02-17 16:02 Florian Weimer
  2021-02-17 16:02 ` [PATCH 01/10] Implement <unwind-link.h> for dynamically loading the libgcc_s unwinder Florian Weimer
                   ` (10 more replies)
  0 siblings, 11 replies; 22+ messages in thread
From: Florian Weimer @ 2021-02-17 16:02 UTC (permalink / raw)
  To: libc-alpha

This series is basically a repost.  I had to tweak it somewhat to pick
up the <unwind-arch.h> customization for MIPS.  I switched to reusing
that header for all customization.

This is a prequiste for consolidating and libc and nptl implementations
of unwinding, and moving the cancellation implementation into libc.

Thanks,
Florian

Florian Weimer (10):
  Implement <unwind-link.h> for dynamically loading the libgcc_s
    unwinder
  backtrace: Implement on top of <unwind-link.h>
  arm: Implement backtrace on top of <unwind-link.h>
  i386: Implement backtrace on top of <unwind-link.h>
  m68k: Implement backtrace on top of <unwind-link.h>
  sparc: Implement backtrace on top <unwind-link.h>
  __frame_state_for: Use <unwind-link.h> for unwinder access
  Move sysdeps/gnu/unwind-resume.c to sysdeps/generic/unwind-resume.c
  Implement _Unwind_Resume in libc on top of <unwind-link.h>
  nptl: Use <unwind-link.h> for accessing the libgcc_s unwinder

 debug/backtrace.c                             |  86 +++--------
 malloc/set-freeres.c                          |   5 +
 misc/Makefile                                 |   2 +-
 misc/Versions                                 |   1 +
 misc/unwind-link.c                            | 145 ++++++++++++++++++
 nptl/nptlfreeres.c                            |   1 -
 nptl/pthreadP.h                               |   6 +-
 nptl/pthread_cancel.c                         |   3 +-
 sysdeps/alpha/unwind-arch.h                   |  28 ++++
 sysdeps/arm/arm-unwind-resume.S               |  26 ++--
 sysdeps/arm/backtrace.c                       |  77 +++-------
 sysdeps/arm/nptl/unwind-forcedunwind.c        |  25 +++
 sysdeps/arm/pt-arm-unwind-resume.S            |  22 ++-
 sysdeps/arm/unwind-arch.h                     |  39 +++++
 sysdeps/arm/unwind-resume.c                   |  25 +++
 sysdeps/generic/framestate.c                  |  21 +--
 sysdeps/generic/unwind-arch.h                 |  27 ++--
 sysdeps/generic/unwind-link.h                 | 106 +++++++++++++
 sysdeps/generic/unwind-resume.c               |  46 ++++++
 sysdeps/gnu/unwind-resume.c                   |  83 ----------
 sysdeps/i386/backtrace.c                      |  82 +++-------
 sysdeps/i386/unwind-arch.h                    |  39 +++++
 sysdeps/ia64/unwind-arch.h                    |  32 ++++
 sysdeps/m68k/backtrace.c                      |  82 +++-------
 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/nptl/unwind-forcedunwind.c            | 115 ++------------
 sysdeps/powerpc/powerpc32/unwind-arch.h       |  28 ++++
 sysdeps/s390/unwind-arch.h                    |  28 ++++
 sysdeps/sh/unwind-arch.h                      |  28 ++++
 sysdeps/sparc/backtrace.c                     |  66 ++------
 sysdeps/sparc/unwind-arch.h                   |  28 ++++
 .../sysv/linux/ia64/unwind-forcedunwind.c     |  16 +-
 36 files changed, 852 insertions(+), 550 deletions(-)
 create mode 100644 misc/unwind-link.c
 create mode 100644 sysdeps/alpha/unwind-arch.h
 create mode 100644 sysdeps/arm/nptl/unwind-forcedunwind.c
 create mode 100644 sysdeps/arm/unwind-arch.h
 create mode 100644 sysdeps/arm/unwind-resume.c
 create mode 100644 sysdeps/generic/unwind-link.h
 create mode 100644 sysdeps/generic/unwind-resume.c
 delete mode 100644 sysdeps/gnu/unwind-resume.c
 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


^ permalink raw reply	[flat|nested] 22+ messages in thread

* [PATCH 01/10] Implement <unwind-link.h> for dynamically loading the libgcc_s unwinder
  2021-02-17 16:02 [PATCH 00/10] Unwinder interface consolidation Florian Weimer
@ 2021-02-17 16:02 ` Florian Weimer
  2021-03-01 13:54   ` Carlos O'Donell
  2021-02-17 16:02 ` [PATCH 02/10] backtrace: Implement on top of <unwind-link.h> Florian Weimer
                   ` (9 subsequent siblings)
  10 siblings, 1 reply; 22+ messages in thread
From: Florian Weimer @ 2021-02-17 16:02 UTC (permalink / raw)
  To: libc-alpha

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

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



^ permalink raw reply	[flat|nested] 22+ messages in thread

* [PATCH 02/10] backtrace: Implement on top of <unwind-link.h>
  2021-02-17 16:02 [PATCH 00/10] Unwinder interface consolidation Florian Weimer
  2021-02-17 16:02 ` [PATCH 01/10] Implement <unwind-link.h> for dynamically loading the libgcc_s unwinder Florian Weimer
@ 2021-02-17 16:02 ` Florian Weimer
  2021-03-01 13:54   ` Carlos O'Donell
  2021-02-17 16:02 ` [PATCH 03/10] arm: Implement backtrace " Florian Weimer
                   ` (8 subsequent siblings)
  10 siblings, 1 reply; 22+ messages in thread
From: Florian Weimer @ 2021-02-17 16:02 UTC (permalink / raw)
  To: libc-alpha

This reimplements the generic version of backtrace.
---
 debug/backtrace.c | 84 ++++++++++-------------------------------------
 1 file changed, 17 insertions(+), 67 deletions(-)

diff --git a/debug/backtrace.c b/debug/backtrace.c
index 5ded57bfc4..187d911a0d 100644
--- a/debug/backtrace.c
+++ b/debug/backtrace.c
@@ -17,10 +17,7 @@
    License along with the GNU C Library; if not, see
    <https://www.gnu.org/licenses/>.  */
 
-#include <libc-lock.h>
-#include <dlfcn.h>
 #include <execinfo.h>
-#include <gnu/lib-names.h>
 #include <stdlib.h>
 #include <unwind.h>
 #include <unwind-link.h>
@@ -28,47 +25,12 @@
 struct trace_arg
 {
   void **array;
+  struct unwind_link *unwind_link;
   _Unwind_Word cfa;
   int cnt;
   int size;
 };
 
-#ifdef SHARED
-static _Unwind_Reason_Code (*unwind_backtrace) (_Unwind_Trace_Fn, void *);
-static _Unwind_Ptr (*unwind_getip) (struct _Unwind_Context *);
-static _Unwind_Word (*unwind_getcfa) (struct _Unwind_Context *);
-static void *libgcc_handle;
-
-
-/* Dummy version in case libgcc_s does not contain the real code.  */
-static _Unwind_Word
-dummy_getcfa (struct _Unwind_Context *ctx __attribute__ ((unused)))
-{
-  return 0;
-}
-
-
-static void
-init (void)
-{
-  libgcc_handle = __libc_dlopen (LIBGCC_S_SO);
-
-  if (libgcc_handle == NULL)
-    return;
-
-  unwind_backtrace = __libc_dlsym (libgcc_handle, "_Unwind_Backtrace");
-  unwind_getip = __libc_dlsym (libgcc_handle, "_Unwind_GetIP");
-  if (unwind_getip == NULL)
-    unwind_backtrace = NULL;
-  unwind_getcfa = (__libc_dlsym (libgcc_handle, "_Unwind_GetCFA")
-		  ?: dummy_getcfa);
-}
-#else
-# define unwind_backtrace _Unwind_Backtrace
-# define unwind_getip _Unwind_GetIP
-# define unwind_getcfa _Unwind_GetCFA
-#endif
-
 static _Unwind_Reason_Code
 backtrace_helper (struct _Unwind_Context *ctx, void *a)
 {
@@ -78,14 +40,16 @@ backtrace_helper (struct _Unwind_Context *ctx, void *a)
      Skip it.  */
   if (arg->cnt != -1)
     {
-      arg->array[arg->cnt] = (void *) unwind_getip (ctx);
+      arg->array[arg->cnt]
+	= (void *) UNWIND_LINK_PTR (arg->unwind_link, _Unwind_GetIP) (ctx);
       if (arg->cnt > 0)
 	arg->array[arg->cnt]
 	  = unwind_arch_adjustment (arg->array[arg->cnt - 1],
 				    arg->array[arg->cnt]);
 
       /* Check whether we make any progress.  */
-      _Unwind_Word cfa = unwind_getcfa (ctx);
+      _Unwind_Word cfa
+	= UNWIND_LINK_PTR (arg->unwind_link, _Unwind_GetCFA) (ctx);
 
       if (arg->cnt > 0 && arg->array[arg->cnt - 1] == arg->array[arg->cnt]
 	 && cfa == arg->cfa)
@@ -100,20 +64,20 @@ backtrace_helper (struct _Unwind_Context *ctx, void *a)
 int
 __backtrace (void **array, int size)
 {
-  struct trace_arg arg = { .array = array, .cfa = 0, .size = size, .cnt = -1 };
-
-  if (size <= 0)
-    return 0;
-
-#ifdef SHARED
-  __libc_once_define (static, once);
-
-  __libc_once (once, init);
-  if (unwind_backtrace == NULL)
+  struct trace_arg arg =
+    {
+     .array = array,
+     .unwind_link = __libc_unwind_link_get (),
+     .cfa = 0,
+     .size = size,
+     .cnt = -1
+    };
+
+  if (size <= 0 || arg.unwind_link == NULL)
     return 0;
-#endif
 
-  unwind_backtrace (backtrace_helper, &arg);
+  UNWIND_LINK_PTR (arg.unwind_link, _Unwind_Backtrace)
+    (backtrace_helper, &arg);
 
   /* _Unwind_Backtrace seems to put NULL address above
      _start.  Fix it up here.  */
@@ -123,17 +87,3 @@ __backtrace (void **array, int size)
 }
 weak_alias (__backtrace, backtrace)
 libc_hidden_def (__backtrace)
-
-
-#ifdef SHARED
-/* Free all resources if necessary.  */
-libc_freeres_fn (free_mem)
-{
-  unwind_backtrace = NULL;
-  if (libgcc_handle != NULL)
-    {
-      __libc_dlclose (libgcc_handle);
-      libgcc_handle = NULL;
-    }
-}
-#endif
-- 
2.29.2



^ permalink raw reply	[flat|nested] 22+ messages in thread

* [PATCH 03/10] arm: Implement backtrace on top of <unwind-link.h>
  2021-02-17 16:02 [PATCH 00/10] Unwinder interface consolidation Florian Weimer
  2021-02-17 16:02 ` [PATCH 01/10] Implement <unwind-link.h> for dynamically loading the libgcc_s unwinder Florian Weimer
  2021-02-17 16:02 ` [PATCH 02/10] backtrace: Implement on top of <unwind-link.h> Florian Weimer
@ 2021-02-17 16:02 ` Florian Weimer
  2021-03-01 13:54   ` Carlos O'Donell
  2021-02-17 16:03 ` [PATCH 04/10] i386: " Florian Weimer
                   ` (7 subsequent siblings)
  10 siblings, 1 reply; 22+ messages in thread
From: Florian Weimer @ 2021-02-17 16:02 UTC (permalink / raw)
  To: libc-alpha

---
 sysdeps/arm/backtrace.c | 77 +++++++++++------------------------------
 1 file changed, 20 insertions(+), 57 deletions(-)

diff --git a/sysdeps/arm/backtrace.c b/sysdeps/arm/backtrace.c
index 3ed975fb96..193f2410ba 100644
--- a/sysdeps/arm/backtrace.c
+++ b/sysdeps/arm/backtrace.c
@@ -17,58 +17,36 @@
    License along with the GNU C Library.  If not, see
    <https://www.gnu.org/licenses/>.  */
 
-#include <libc-lock.h>
-#include <dlfcn.h>
 #include <execinfo.h>
 #include <stdlib.h>
-#include <unwind.h>
+#include <unwind-link.h>
 
 struct trace_arg
 {
   void **array;
+  struct unwind_link *unwind_link;
   int cnt, size;
 };
 
 #ifdef SHARED
-static _Unwind_Reason_Code (*unwind_backtrace) (_Unwind_Trace_Fn, void *);
-static _Unwind_VRS_Result (*unwind_vrs_get) (_Unwind_Context *,
-					     _Unwind_VRS_RegClass,
-					     _uw,
-					     _Unwind_VRS_DataRepresentation,
-					     void *);
-
-static void *libgcc_handle;
-
-static void
-init (void)
-{
-  libgcc_handle = __libc_dlopen ("libgcc_s.so.1");
-
-  if (libgcc_handle == NULL)
-    return;
-
-  unwind_backtrace = __libc_dlsym (libgcc_handle, "_Unwind_Backtrace");
-  unwind_vrs_get = __libc_dlsym (libgcc_handle, "_Unwind_VRS_Get");
-  if (unwind_vrs_get == NULL)
-    unwind_backtrace = NULL;
-}
-
 /* This function is identical to "_Unwind_GetGR", except that it uses
    "unwind_vrs_get" instead of "_Unwind_VRS_Get".  */
 static inline _Unwind_Word
-unwind_getgr (_Unwind_Context *context, int regno)
+unwind_getgr (struct unwind_link *unwind_link,
+	      _Unwind_Context *context, int regno)
 {
   _uw val;
-  unwind_vrs_get (context, _UVRSC_CORE, regno, _UVRSD_UINT32, &val);
+  UNWIND_LINK_PTR (unwind_link, _Unwind_VRS_Get)
+    (context, _UVRSC_CORE, regno, _UVRSD_UINT32, &val);
   return val;
 }
 
 /* This macro is identical to the _Unwind_GetIP macro, except that it
    uses "unwind_getgr" instead of "_Unwind_GetGR".  */
-# define unwind_getip(context) \
-  (unwind_getgr (context, 15) & ~(_Unwind_Word)1)
-#else
-# define unwind_backtrace _Unwind_Backtrace
+#define unwind_getip(context) \
+  (unwind_getgr (arg->unwind_link, context, 15) & ~(_Unwind_Word)1)
+
+#else /* !SHARED */
 # define unwind_getip _Unwind_GetIP
 #endif
 
@@ -89,20 +67,19 @@ backtrace_helper (struct _Unwind_Context *ctx, void *a)
 int
 __backtrace (void **array, int size)
 {
-  struct trace_arg arg = { .array = array, .size = size, .cnt = -1 };
-
-  if (size <= 0)
-    return 0;
-
-#ifdef SHARED
-  __libc_once_define (static, once);
+  struct trace_arg arg =
+    {
+     .array = array,
+     .unwind_link = __libc_unwind_link_get (),
+     .size = size,
+     .cnt = -1
+    };
 
-  __libc_once (once, init);
-  if (unwind_backtrace == NULL)
+  if (size <= 0 || arg.unwind_link == NULL)
     return 0;
-#endif
 
-  unwind_backtrace (backtrace_helper, &arg);
+  UNWIND_LINK_PTR (arg.unwind_link, _Unwind_Backtrace)
+    (backtrace_helper, &arg);
 
   if (arg.cnt > 1 && arg.array[arg.cnt - 1] == NULL)
     --arg.cnt;
@@ -110,17 +87,3 @@ __backtrace (void **array, int size)
 }
 weak_alias (__backtrace, backtrace)
 libc_hidden_def (__backtrace)
-
-
-#ifdef SHARED
-/* Free all resources if necessary.  */
-libc_freeres_fn (free_mem)
-{
-  unwind_backtrace = NULL;
-  if (libgcc_handle != NULL)
-    {
-      __libc_dlclose (libgcc_handle);
-      libgcc_handle = NULL;
-    }
-}
-#endif
-- 
2.29.2



^ permalink raw reply	[flat|nested] 22+ messages in thread

* [PATCH 04/10] i386: Implement backtrace on top of <unwind-link.h>
  2021-02-17 16:02 [PATCH 00/10] Unwinder interface consolidation Florian Weimer
                   ` (2 preceding siblings ...)
  2021-02-17 16:02 ` [PATCH 03/10] arm: Implement backtrace " Florian Weimer
@ 2021-02-17 16:03 ` Florian Weimer
  2021-03-01 13:54   ` Carlos O'Donell
  2021-02-17 16:03 ` [PATCH 05/10] m68k: " Florian Weimer
                   ` (6 subsequent siblings)
  10 siblings, 1 reply; 22+ messages in thread
From: Florian Weimer @ 2021-02-17 16:03 UTC (permalink / raw)
  To: libc-alpha

---
 sysdeps/i386/backtrace.c | 82 +++++++++-------------------------------
 1 file changed, 18 insertions(+), 64 deletions(-)

diff --git a/sysdeps/i386/backtrace.c b/sysdeps/i386/backtrace.c
index 124b0b73e3..4631f68fdc 100644
--- a/sysdeps/i386/backtrace.c
+++ b/sysdeps/i386/backtrace.c
@@ -17,52 +17,18 @@
    License along with the GNU C Library; if not, see
    <https://www.gnu.org/licenses/>.  */
 
-#include <libc-lock.h>
-#include <dlfcn.h>
 #include <execinfo.h>
 #include <stdlib.h>
-#include <unwind.h>
+#include <unwind-link.h>
 
 struct trace_arg
 {
   void **array;
+  struct unwind_link *unwind_link;
   int cnt, size;
   void *lastebp, *lastesp;
 };
 
-#ifdef SHARED
-static _Unwind_Reason_Code (*unwind_backtrace) (_Unwind_Trace_Fn, void *);
-static _Unwind_Ptr (*unwind_getip) (struct _Unwind_Context *);
-static _Unwind_Ptr (*unwind_getcfa) (struct _Unwind_Context *);
-static _Unwind_Ptr (*unwind_getgr) (struct _Unwind_Context *, int);
-static void *libgcc_handle;
-
-static void
-init (void)
-{
-  libgcc_handle = __libc_dlopen ("libgcc_s.so.1");
-
-  if (libgcc_handle == NULL)
-    return;
-
-  unwind_backtrace = __libc_dlsym (libgcc_handle, "_Unwind_Backtrace");
-  unwind_getip = __libc_dlsym (libgcc_handle, "_Unwind_GetIP");
-  unwind_getcfa = __libc_dlsym (libgcc_handle, "_Unwind_GetCFA");
-  unwind_getgr = __libc_dlsym (libgcc_handle, "_Unwind_GetGR");
-  if (unwind_getip == NULL || unwind_getgr == NULL || unwind_getcfa == NULL)
-    {
-      unwind_backtrace = NULL;
-      __libc_dlclose (libgcc_handle);
-      libgcc_handle = NULL;
-    }
-}
-#else
-# define unwind_backtrace _Unwind_Backtrace
-# define unwind_getip _Unwind_GetIP
-# define unwind_getcfa _Unwind_GetCFA
-# define unwind_getgr _Unwind_GetGR
-#endif
-
 static _Unwind_Reason_Code
 backtrace_helper (struct _Unwind_Context *ctx, void *a)
 {
@@ -71,13 +37,16 @@ backtrace_helper (struct _Unwind_Context *ctx, void *a)
   /* We are first called with address in the __backtrace function.
      Skip it.  */
   if (arg->cnt != -1)
-    arg->array[arg->cnt] = (void *) unwind_getip (ctx);
+    arg->array[arg->cnt]
+      = (void *) UNWIND_LINK_PTR (arg->unwind_link, _Unwind_GetIP) (ctx);
   if (++arg->cnt == arg->size)
     return _URC_END_OF_STACK;
 
   /* %ebp is DWARF2 register 5 on IA-32.  */
-  arg->lastebp = (void *) unwind_getgr (ctx, 5);
-  arg->lastesp = (void *) unwind_getcfa (ctx);
+  arg->lastebp
+    = (void *) UNWIND_LINK_PTR (arg->unwind_link, _Unwind_GetGR) (ctx, 5);
+  arg->lastesp
+    = (void *) UNWIND_LINK_PTR (arg->unwind_link, _Unwind_GetCFA) (ctx);
   return _URC_NO_REASON;
 }
 
@@ -111,20 +80,19 @@ struct layout
 int
 __backtrace (void **array, int size)
 {
-  struct trace_arg arg = { .array = array, .size = size, .cnt = -1 };
-
-  if (size <= 0)
-    return 0;
-
-#ifdef SHARED
-  __libc_once_define (static, once);
+  struct trace_arg arg =
+    {
+     .array = array,
+     .unwind_link = __libc_unwind_link_get (),
+     .size = size,
+     .cnt = -1,
+    };
 
-  __libc_once (once, init);
-  if (unwind_backtrace == NULL)
+  if (size <= 0 || arg.unwind_link == NULL)
     return 0;
-#endif
 
-  unwind_backtrace (backtrace_helper, &arg);
+  UNWIND_LINK_PTR (arg.unwind_link, _Unwind_Backtrace)
+    (backtrace_helper, &arg);
 
   if (arg.cnt > 1 && arg.array[arg.cnt - 1] == NULL)
     --arg.cnt;
@@ -147,17 +115,3 @@ __backtrace (void **array, int size)
 }
 weak_alias (__backtrace, backtrace)
 libc_hidden_def (__backtrace)
-
-
-#ifdef SHARED
-/* Free all resources if necessary.  */
-libc_freeres_fn (free_mem)
-{
-  unwind_backtrace = NULL;
-  if (libgcc_handle != NULL)
-    {
-      __libc_dlclose (libgcc_handle);
-      libgcc_handle = NULL;
-    }
-}
-#endif
-- 
2.29.2



^ permalink raw reply	[flat|nested] 22+ messages in thread

* [PATCH 05/10] m68k: Implement backtrace on top of <unwind-link.h>
  2021-02-17 16:02 [PATCH 00/10] Unwinder interface consolidation Florian Weimer
                   ` (3 preceding siblings ...)
  2021-02-17 16:03 ` [PATCH 04/10] i386: " Florian Weimer
@ 2021-02-17 16:03 ` Florian Weimer
  2021-03-01 13:54   ` Carlos O'Donell
  2021-02-17 16:03 ` [PATCH 06/10] sparc: Implement backtrace on top <unwind-link.h> Florian Weimer
                   ` (5 subsequent siblings)
  10 siblings, 1 reply; 22+ messages in thread
From: Florian Weimer @ 2021-02-17 16:03 UTC (permalink / raw)
  To: libc-alpha

---
 sysdeps/m68k/backtrace.c | 82 +++++++++-------------------------------
 1 file changed, 18 insertions(+), 64 deletions(-)

diff --git a/sysdeps/m68k/backtrace.c b/sysdeps/m68k/backtrace.c
index 86e9a888f0..27b9c58167 100644
--- a/sysdeps/m68k/backtrace.c
+++ b/sysdeps/m68k/backtrace.c
@@ -16,52 +16,18 @@
    License along with the GNU C Library; if not, see
    <https://www.gnu.org/licenses/>.  */
 
-#include <libc-lock.h>
-#include <dlfcn.h>
 #include <execinfo.h>
 #include <stdlib.h>
-#include <unwind.h>
+#include <unwind-link.h>
 
 struct trace_arg
 {
   void **array;
+  struct unwind_link *unwind_link;
   int cnt, size;
   void *lastfp, *lastsp;
 };
 
-#ifdef SHARED
-static _Unwind_Reason_Code (*unwind_backtrace) (_Unwind_Trace_Fn, void *);
-static _Unwind_Ptr (*unwind_getip) (struct _Unwind_Context *);
-static _Unwind_Ptr (*unwind_getcfa) (struct _Unwind_Context *);
-static _Unwind_Ptr (*unwind_getgr) (struct _Unwind_Context *, int);
-static void *libgcc_handle;
-
-static void
-init (void)
-{
-  libgcc_handle = __libc_dlopen ("libgcc_s.so.2");
-
-  if (libgcc_handle == NULL)
-    return;
-
-  unwind_backtrace = __libc_dlsym (libgcc_handle, "_Unwind_Backtrace");
-  unwind_getip = __libc_dlsym (libgcc_handle, "_Unwind_GetIP");
-  unwind_getcfa = __libc_dlsym (libgcc_handle, "_Unwind_GetCFA");
-  unwind_getgr = __libc_dlsym (libgcc_handle, "_Unwind_GetGR");
-  if (unwind_getip == NULL || unwind_getgr == NULL || unwind_getcfa == NULL)
-    {
-      unwind_backtrace = NULL;
-      __libc_dlclose (libgcc_handle);
-      libgcc_handle = NULL;
-    }
-}
-#else
-# define unwind_backtrace _Unwind_Backtrace
-# define unwind_getip _Unwind_GetIP
-# define unwind_getcfa _Unwind_GetCFA
-# define unwind_getgr _Unwind_GetGR
-#endif
-
 static _Unwind_Reason_Code
 backtrace_helper (struct _Unwind_Context *ctx, void *a)
 {
@@ -70,13 +36,16 @@ backtrace_helper (struct _Unwind_Context *ctx, void *a)
   /* We are first called with address in the __backtrace function.
      Skip it.  */
   if (arg->cnt != -1)
-    arg->array[arg->cnt] = (void *) unwind_getip (ctx);
+    arg->array[arg->cnt]
+      = (void *) UNWIND_LINK_PTR (arg->unwind_link, _Unwind_GetIP) (ctx);
   if (++arg->cnt == arg->size)
     return _URC_END_OF_STACK;
 
   /* %fp is DWARF2 register 14 on M68K.  */
-  arg->lastfp = (void *) unwind_getgr (ctx, 14);
-  arg->lastsp = (void *) unwind_getcfa (ctx);
+  arg->lastfp
+    = (void *) UNWIND_LINK_PTR (arg->unwind_link, _Unwind_GetGR) (ctx, 14);
+  arg->lastsp
+    = (void *) UNWIND_LINK_PTR (arg->unwind_link, _Unwind_GetCFA) (ctx);
   return _URC_NO_REASON;
 }
 
@@ -110,20 +79,19 @@ struct layout
 int
 __backtrace (void **array, int size)
 {
-  struct trace_arg arg = { .array = array, .size = size, .cnt = -1 };
-
-  if (size <= 0)
-    return 0;
-
-#ifdef SHARED
-  __libc_once_define (static, once);
+  struct trace_arg arg =
+    {
+     .array = array,
+     .unwind_link = __libc_unwind_link_get (),
+     .size = size,
+     .cnt = -1,
+    };
 
-  __libc_once (once, init);
-  if (unwind_backtrace == NULL)
+  if (size <= 0 || arg.unwind_link == NULL)
     return 0;
-#endif
 
-  unwind_backtrace (backtrace_helper, &arg);
+  UNWIND_LINK_PTR (arg.unwind_link, _Unwind_Backtrace)
+    (backtrace_helper, &arg);
 
   if (arg.cnt > 1 && arg.array[arg.cnt - 1] == NULL)
     --arg.cnt;
@@ -146,17 +114,3 @@ __backtrace (void **array, int size)
 }
 weak_alias (__backtrace, backtrace)
 libc_hidden_def (__backtrace)
-
-
-#ifdef SHARED
-/* Free all resources if necessary.  */
-libc_freeres_fn (free_mem)
-{
-  unwind_backtrace = NULL;
-  if (libgcc_handle != NULL)
-    {
-      __libc_dlclose (libgcc_handle);
-      libgcc_handle = NULL;
-    }
-}
-#endif
-- 
2.29.2



^ permalink raw reply	[flat|nested] 22+ messages in thread

* [PATCH 06/10] sparc: Implement backtrace on top <unwind-link.h>
  2021-02-17 16:02 [PATCH 00/10] Unwinder interface consolidation Florian Weimer
                   ` (4 preceding siblings ...)
  2021-02-17 16:03 ` [PATCH 05/10] m68k: " Florian Weimer
@ 2021-02-17 16:03 ` Florian Weimer
  2021-03-01 13:54   ` Carlos O'Donell
  2021-02-17 16:03 ` [PATCH 07/10] __frame_state_for: Use <unwind-link.h> for unwinder access Florian Weimer
                   ` (4 subsequent siblings)
  10 siblings, 1 reply; 22+ messages in thread
From: Florian Weimer @ 2021-02-17 16:03 UTC (permalink / raw)
  To: libc-alpha

---
 sysdeps/sparc/backtrace.c | 66 +++++++++------------------------------
 1 file changed, 15 insertions(+), 51 deletions(-)

diff --git a/sysdeps/sparc/backtrace.c b/sysdeps/sparc/backtrace.c
index 62196f0538..1bad755b7f 100644
--- a/sysdeps/sparc/backtrace.c
+++ b/sysdeps/sparc/backtrace.c
@@ -21,9 +21,8 @@
 #include <stddef.h>
 #include <sysdep.h>
 #include <sys/trap.h>
-#include <dlfcn.h>
-#include <unwind.h>
 #include <backtrace.h>
+#include <unwind-link.h>
 
 struct layout
 {
@@ -36,45 +35,12 @@ struct layout
 struct trace_arg
 {
   void **array;
+  struct unwind_link *unwind_link;
   _Unwind_Word cfa;
   int cnt;
   int size;
 };
 
-#ifdef SHARED
-static _Unwind_Reason_Code (*unwind_backtrace) (_Unwind_Trace_Fn, void *);
-static _Unwind_Ptr (*unwind_getip) (struct _Unwind_Context *);
-static _Unwind_Word (*unwind_getcfa) (struct _Unwind_Context *);
-static void *libgcc_handle;
-
-/* Dummy version in case libgcc_s does not contain the real code.  */
-static _Unwind_Word
-dummy_getcfa (struct _Unwind_Context *ctx __attribute__ ((unused)))
-{
-  return 0;
-}
-
-static void
-init (void)
-{
-  libgcc_handle = __libc_dlopen ("libgcc_s.so.1");
-
-  if (libgcc_handle == NULL)
-    return;
-
-  unwind_backtrace = __libc_dlsym (libgcc_handle, "_Unwind_Backtrace");
-  unwind_getip = __libc_dlsym (libgcc_handle, "_Unwind_GetIP");
-  if (unwind_getip == NULL)
-    unwind_backtrace = NULL;
-  unwind_getcfa = (__libc_dlsym (libgcc_handle, "_Unwind_GetCFA")
-		  ?: dummy_getcfa);
-}
-#else
-# define unwind_backtrace _Unwind_Backtrace
-# define unwind_getip _Unwind_GetIP
-# define unwind_getcfa _Unwind_GetCFA
-#endif
-
 static _Unwind_Reason_Code
 backtrace_helper (struct _Unwind_Context *ctx, void *a)
 {
@@ -85,11 +51,12 @@ backtrace_helper (struct _Unwind_Context *ctx, void *a)
      Skip it.  */
   if (arg->cnt != -1)
     {
-      ip = unwind_getip (ctx);
+      ip = UNWIND_LINK_PTR (arg->unwind_link, _Unwind_GetIP) (ctx);
       arg->array[arg->cnt] = (void *) ip;
 
       /* Check whether we make any progress.  */
-      _Unwind_Word cfa = unwind_getcfa (ctx);
+      _Unwind_Word cfa
+	= UNWIND_LINK_PTR (arg->unwind_link, _Unwind_GetCFA) (ctx);
 
       if (arg->cnt > 0 && arg->array[arg->cnt - 1] == arg->array[arg->cnt]
 	 && cfa == arg->cfa)
@@ -104,23 +71,19 @@ backtrace_helper (struct _Unwind_Context *ctx, void *a)
 int
 __backtrace (void **array, int size)
 {
-  struct trace_arg arg = { .array = array, .cfa = 0, .size = size, .cnt = -1 };
-  bool use_unwinder;
   int count;
+  struct trace_arg arg =
+    {
+     .array = array,
+     .unwind_link = __libc_unwind_link_get (),
+     .size = size,
+     .cnt = -1,
+    };
 
   if (size <= 0)
     return 0;
 
-  use_unwinder = true;
-#ifdef SHARED
-  __libc_once_define (static, once);
-
-  __libc_once (once, init);
-  if (unwind_backtrace == NULL)
-    use_unwinder = false;
-#endif
-
-  if (use_unwinder == false)
+  if (arg.unwind_link == NULL)
     {
       struct layout *current;
       unsigned long fp, i7;
@@ -145,7 +108,8 @@ __backtrace (void **array, int size)
     }
   else
     {
-      unwind_backtrace (backtrace_helper, &arg);
+      UNWIND_LINK_PTR (arg.unwind_link, _Unwind_Backtrace)
+	(backtrace_helper, &arg);
 
       /* _Unwind_Backtrace seems to put NULL address above
 	 _start.  Fix it up here.  */
-- 
2.29.2



^ permalink raw reply	[flat|nested] 22+ messages in thread

* [PATCH 07/10] __frame_state_for: Use <unwind-link.h> for unwinder access
  2021-02-17 16:02 [PATCH 00/10] Unwinder interface consolidation Florian Weimer
                   ` (5 preceding siblings ...)
  2021-02-17 16:03 ` [PATCH 06/10] sparc: Implement backtrace on top <unwind-link.h> Florian Weimer
@ 2021-02-17 16:03 ` Florian Weimer
  2021-03-01 13:54   ` Carlos O'Donell
  2021-02-17 16:03 ` [PATCH 08/10] Move sysdeps/gnu/unwind-resume.c to sysdeps/generic/unwind-resume.c Florian Weimer
                   ` (3 subsequent siblings)
  10 siblings, 1 reply; 22+ messages in thread
From: Florian Weimer @ 2021-02-17 16:03 UTC (permalink / raw)
  To: libc-alpha

---
 sysdeps/generic/framestate.c | 21 ++++++++-------------
 1 file changed, 8 insertions(+), 13 deletions(-)

diff --git a/sysdeps/generic/framestate.c b/sysdeps/generic/framestate.c
index c1b364dbaa..54c4817f37 100644
--- a/sysdeps/generic/framestate.c
+++ b/sysdeps/generic/framestate.c
@@ -17,7 +17,6 @@
    License along with the GNU C Library; if not, see
    <https://www.gnu.org/licenses/>.  */
 
-#include <dlfcn.h>
 #include <stdlib.h>
 #define STATIC static
 #define __frame_state_for fallback_frame_state_for
@@ -25,6 +24,8 @@
 #undef __frame_state_for
 #include <gnu/lib-names.h>
 
+#include <unwind-link.h>
+
 typedef struct frame_state * (*framesf)(void *pc, struct frame_state *);
 struct frame_state *__frame_state_for (void *pc,
 				       struct frame_state *frame_state);
@@ -32,21 +33,15 @@ struct frame_state *__frame_state_for (void *pc,
 struct frame_state *
 __frame_state_for (void *pc, struct frame_state *frame_state)
 {
-  static framesf frame_state_for;
-
-  if (frame_state_for == NULL)
+  struct unwind_link *unwind_link = __libc_unwind_link_get ();
+  if (unwind_link != NULL)
+    return UNWIND_LINK_PTR (unwind_link, __frame_state_for) (pc, frame_state);
+  else
     {
-      void *handle = __libc_dlopen (LIBGCC_S_SO);
-
-      if (handle == NULL
-	  || (frame_state_for
-	      = (framesf) __libc_dlsym (handle, "__frame_state_for")) == NULL)
 #ifndef __USING_SJLJ_EXCEPTIONS__
-	frame_state_for = fallback_frame_state_for;
+      return fallback_frame_state_for (pc, frame_state);
 #else
-	frame_state_for = abort;
+      abort ();
 #endif
     }
-
-  return frame_state_for (pc, frame_state);
 }
-- 
2.29.2



^ permalink raw reply	[flat|nested] 22+ messages in thread

* [PATCH 08/10] Move sysdeps/gnu/unwind-resume.c to sysdeps/generic/unwind-resume.c
  2021-02-17 16:02 [PATCH 00/10] Unwinder interface consolidation Florian Weimer
                   ` (6 preceding siblings ...)
  2021-02-17 16:03 ` [PATCH 07/10] __frame_state_for: Use <unwind-link.h> for unwinder access Florian Weimer
@ 2021-02-17 16:03 ` Florian Weimer
  2021-03-01 13:55   ` Carlos O'Donell
  2021-02-17 16:03 ` [PATCH 09/10] Implement _Unwind_Resume in libc on top of <unwind-link.h> Florian Weimer
                   ` (2 subsequent siblings)
  10 siblings, 1 reply; 22+ messages in thread
From: Florian Weimer @ 2021-02-17 16:03 UTC (permalink / raw)
  To: libc-alpha

This change allows architecture-specific sysdeps directories to override
it.
---
 sysdeps/{gnu => generic}/unwind-resume.c | 0
 1 file changed, 0 insertions(+), 0 deletions(-)
 rename sysdeps/{gnu => generic}/unwind-resume.c (100%)

diff --git a/sysdeps/gnu/unwind-resume.c b/sysdeps/generic/unwind-resume.c
similarity index 100%
rename from sysdeps/gnu/unwind-resume.c
rename to sysdeps/generic/unwind-resume.c
-- 
2.29.2



^ permalink raw reply	[flat|nested] 22+ messages in thread

* [PATCH 09/10] Implement _Unwind_Resume in libc on top of <unwind-link.h>
  2021-02-17 16:02 [PATCH 00/10] Unwinder interface consolidation Florian Weimer
                   ` (7 preceding siblings ...)
  2021-02-17 16:03 ` [PATCH 08/10] Move sysdeps/gnu/unwind-resume.c to sysdeps/generic/unwind-resume.c Florian Weimer
@ 2021-02-17 16:03 ` Florian Weimer
  2021-03-01 13:55   ` Carlos O'Donell
  2021-02-17 16:03 ` [PATCH 10/10] nptl: Use <unwind-link.h> for accessing the libgcc_s unwinder Florian Weimer
  2021-03-01 13:54 ` [PATCH 00/10] Unwinder interface consolidation Carlos O'Donell
  10 siblings, 1 reply; 22+ messages in thread
From: Florian Weimer @ 2021-02-17 16:03 UTC (permalink / raw)
  To: libc-alpha

Temporarily move the arm _Unwind_Resume implementation to the file
used by libpthread.  It will be ported to <unwind-link.h> along with
the rest of nptl.
---
 sysdeps/arm/arm-unwind-resume.S    | 26 +++++++-------
 sysdeps/arm/pt-arm-unwind-resume.S | 48 ++++++++++++++++++++++++--
 sysdeps/arm/unwind-arch.h          |  4 +++
 sysdeps/arm/unwind-resume.c        | 25 ++++++++++++++
 sysdeps/generic/unwind-resume.c    | 55 +++++-------------------------
 5 files changed, 97 insertions(+), 61 deletions(-)
 create mode 100644 sysdeps/arm/unwind-resume.c

diff --git a/sysdeps/arm/arm-unwind-resume.S b/sysdeps/arm/arm-unwind-resume.S
index 22525f4db0..92c171fe0f 100644
--- a/sysdeps/arm/arm-unwind-resume.S
+++ b/sysdeps/arm/arm-unwind-resume.S
@@ -18,29 +18,29 @@
 
 #include <sysdep.h>
 
-/* This is just implementing exactly what the C version does.
+/* This is equivalent to the following C implementation:
+
+   void
+   _Unwind_Resume (struct _Unwind_Exception *exc)
+   {
+     __unwind_link_get_resume () (exc);
+   }
+
    We do it in assembly just to ensure that we get an unmolested tail
    call to the libgcc function, which is necessary for the ARM unwinder.  */
 
 ENTRY (_Unwind_Resume)
-	LDR_HIDDEN (ip, ip, __libgcc_s_resume, 0)
-	cmp	ip, #0
-	beq	1f
-0:	PTR_DEMANGLE (ip, ip, r2, r3)
-	bx	ip
-
 	/* We need to save and restore LR (for our own return address)
 	   and R0 (for the argument to _Unwind_Resume) around the call.  */
-1:	push	{r0, lr}
+	push	{r0, lr}
 	cfi_adjust_cfa_offset (8)
 	cfi_rel_offset (r0, 0)
 	cfi_rel_offset (lr, 4)
-	bl	__libgcc_s_init
+	bl	__unwind_link_get_resume
+	mov	r3, r0
 	pop	{r0, lr}
 	cfi_adjust_cfa_offset (-8)
-	cfi_restore (r0)
+	cfi_restore (r4)
 	cfi_restore (lr)
-
-	LDR_HIDDEN (ip, ip, __libgcc_s_resume, 0)
-	b	0b
+	bx	r3
 END (_Unwind_Resume)
diff --git a/sysdeps/arm/pt-arm-unwind-resume.S b/sysdeps/arm/pt-arm-unwind-resume.S
index 7cb555c02b..d579848696 100644
--- a/sysdeps/arm/pt-arm-unwind-resume.S
+++ b/sysdeps/arm/pt-arm-unwind-resume.S
@@ -1,2 +1,46 @@
-#define __libgcc_s_init	pthread_cancel_init
-#include <arm-unwind-resume.S>
+/* _Unwind_Resume wrapper for ARM EABI.
+   Copyright (C) 2015-2021 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public License as
+   published by the Free Software Foundation; either version 2.1 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library.  If not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <sysdep.h>
+
+/* This is just implementing exactly what the C version does.
+   We do it in assembly just to ensure that we get an unmolested tail
+   call to the libgcc function, which is necessary for the ARM unwinder.  */
+
+ENTRY (_Unwind_Resume)
+	LDR_HIDDEN (ip, ip, __libgcc_s_resume, 0)
+	cmp	ip, #0
+	beq	1f
+0:	PTR_DEMANGLE (ip, ip, r2, r3)
+	bx	ip
+
+	/* We need to save and restore LR (for our own return address)
+	   and R0 (for the argument to _Unwind_Resume) around the call.  */
+1:	push	{r0, lr}
+	cfi_adjust_cfa_offset (8)
+	cfi_rel_offset (r0, 0)
+	cfi_rel_offset (lr, 4)
+	bl	pthread_cancel_init
+	pop	{r0, lr}
+	cfi_adjust_cfa_offset (-8)
+	cfi_restore (r0)
+	cfi_restore (lr)
+
+	LDR_HIDDEN (ip, ip, __libgcc_s_resume, 0)
+	b	0b
+END (_Unwind_Resume)
diff --git a/sysdeps/arm/unwind-arch.h b/sysdeps/arm/unwind-arch.h
index fcf889b3c7..62f643b221 100644
--- a/sysdeps/arm/unwind-arch.h
+++ b/sysdeps/arm/unwind-arch.h
@@ -32,4 +32,8 @@
   assert (local.ptr__Unwind_VRS_Get != NULL);                 \
   PTR_MANGLE (local.ptr__Unwind_VRS_Get);
 
+/* This is used by the _Unwind_Resume assembler implementation to
+   obtain the address to jump to.  */
+void *__unwind_link_get_resume (void) attribute_hidden;
+
 #endif /* _ARCH_UNWIND_LINK_H */
diff --git a/sysdeps/arm/unwind-resume.c b/sysdeps/arm/unwind-resume.c
new file mode 100644
index 0000000000..169d5c30e6
--- /dev/null
+++ b/sysdeps/arm/unwind-resume.c
@@ -0,0 +1,25 @@
+/* Unwinder function forwarders for libc.  Arm version.
+   Copyright (C) 2021 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public License as
+   published by the Free Software Foundation; either version 2.1 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If
+   not, see <https://www.gnu.org/licenses/>.  */
+
+#include <sysdeps/generic/unwind-resume.c>
+
+void *
+__unwind_link_get_resume (void)
+{
+  return UNWIND_LINK_PTR (link (), _Unwind_Resume);
+}
diff --git a/sysdeps/generic/unwind-resume.c b/sysdeps/generic/unwind-resume.c
index 09533d6992..9e63762bf1 100644
--- a/sysdeps/generic/unwind-resume.c
+++ b/sysdeps/generic/unwind-resume.c
@@ -16,68 +16,31 @@
    License along with the GNU C Library; see the file COPYING.LIB.  If
    not, see <https://www.gnu.org/licenses/>.  */
 
-#include <dlfcn.h>
 #include <stdio.h>
-#include <unwind.h>
 #include <gnu/lib-names.h>
+#include <unwind-link.h>
 #include <sysdep.h>
 #include <unwind-resume.h>
 
-
-void (*__libgcc_s_resume) (struct _Unwind_Exception *exc)
-  attribute_hidden __attribute__ ((noreturn));
-
-static _Unwind_Reason_Code (*libgcc_s_personality) PERSONALITY_PROTO;
-
-void attribute_hidden __attribute__ ((cold))
-__libgcc_s_init (void)
+static struct unwind_link *
+link (void)
 {
-  void *resume, *personality;
-  void *handle;
-
-  /* See include/dlfcn.h. Use of __libc_dlopen requires RTLD_NOW.  */
-  handle = __libc_dlopen (LIBGCC_S_SO);
-
-  if (handle == NULL
-      || (resume = __libc_dlsym (handle, "_Unwind_Resume")) == NULL
-      || (personality = __libc_dlsym (handle, "__gcc_personality_v0")) == NULL)
-    __libc_fatal (LIBGCC_S_SO
-                  " must be installed for unwinding to work\n");
-
-#ifdef PTR_MANGLE
-  PTR_MANGLE (resume);
-#endif
-  __libgcc_s_resume = resume;
-#ifdef PTR_MANGLE
-  PTR_MANGLE (personality);
-#endif
-  libgcc_s_personality = personality;
+  struct unwind_link *unwind_link = __libc_unwind_link_get ();
+  if (unwind_link == NULL)
+    __libc_fatal (LIBGCC_S_SO " must be installed for unwinding to work\n");
+  return unwind_link;
 }
 
 #if !HAVE_ARCH_UNWIND_RESUME
 void
 _Unwind_Resume (struct _Unwind_Exception *exc)
 {
-  if (__glibc_unlikely (__libgcc_s_resume == NULL))
-    __libgcc_s_init ();
-
-  __typeof (__libgcc_s_resume) resume = __libgcc_s_resume;
-#ifdef PTR_DEMANGLE
-  PTR_DEMANGLE (resume);
-#endif
-  (*resume) (exc);
+  UNWIND_LINK_PTR (link (), _Unwind_Resume) (exc);
 }
 #endif
 
 _Unwind_Reason_Code
 __gcc_personality_v0 PERSONALITY_PROTO
 {
-  if (__glibc_unlikely (libgcc_s_personality == NULL))
-    __libgcc_s_init ();
-
-  __typeof (libgcc_s_personality) personality = libgcc_s_personality;
-#ifdef PTR_DEMANGLE
-  PTR_DEMANGLE (personality);
-#endif
-  return (*personality) PERSONALITY_ARGS;
+  return UNWIND_LINK_PTR (link (), personality) PERSONALITY_ARGS;
 }
-- 
2.29.2



^ permalink raw reply	[flat|nested] 22+ messages in thread

* [PATCH 10/10] nptl: Use <unwind-link.h> for accessing the libgcc_s unwinder
  2021-02-17 16:02 [PATCH 00/10] Unwinder interface consolidation Florian Weimer
                   ` (8 preceding siblings ...)
  2021-02-17 16:03 ` [PATCH 09/10] Implement _Unwind_Resume in libc on top of <unwind-link.h> Florian Weimer
@ 2021-02-17 16:03 ` Florian Weimer
  2021-03-01 13:55   ` Carlos O'Donell
  2021-03-01 13:54 ` [PATCH 00/10] Unwinder interface consolidation Carlos O'Donell
  10 siblings, 1 reply; 22+ messages in thread
From: Florian Weimer @ 2021-02-17 16:03 UTC (permalink / raw)
  To: libc-alpha

---
 nptl/nptlfreeres.c                            |   1 -
 nptl/pthreadP.h                               |   6 +-
 nptl/pthread_cancel.c                         |   3 +-
 sysdeps/arm/nptl/unwind-forcedunwind.c        |  25 ++++
 sysdeps/arm/pt-arm-unwind-resume.S            |  30 +----
 sysdeps/nptl/unwind-forcedunwind.c            | 115 +++---------------
 .../sysv/linux/ia64/unwind-forcedunwind.c     |  16 +--
 7 files changed, 50 insertions(+), 146 deletions(-)
 create mode 100644 sysdeps/arm/nptl/unwind-forcedunwind.c

diff --git a/nptl/nptlfreeres.c b/nptl/nptlfreeres.c
index d295bcb3c3..4833f04714 100644
--- a/nptl/nptlfreeres.c
+++ b/nptl/nptlfreeres.c
@@ -27,5 +27,4 @@ __libpthread_freeres (void)
 {
   call_function_static_weak (__default_pthread_attr_freeres);
   call_function_static_weak (__nptl_stacks_freeres);
-  call_function_static_weak (__nptl_unwind_freeres);
 }
diff --git a/nptl/pthreadP.h b/nptl/pthreadP.h
index d078128230..d2fd0826fe 100644
--- a/nptl/pthreadP.h
+++ b/nptl/pthreadP.h
@@ -287,9 +287,11 @@ hidden_proto (__pthread_unwind_next)
 hidden_proto (__pthread_register_cancel)
 hidden_proto (__pthread_unregister_cancel)
 # ifdef SHARED
-extern void attribute_hidden pthread_cancel_init (void);
+/* The difference from __libc_unwind_link_get is that here, errors
+   terminate the process.  */
+struct unwind_link ;
+struct unwind_link *__pthread_unwind_link_get (void) attribute_hidden;
 # endif
-extern void __nptl_unwind_freeres (void) attribute_hidden;
 #endif
 
 
diff --git a/nptl/pthread_cancel.c b/nptl/pthread_cancel.c
index f88fa24e19..a011d72fa1 100644
--- a/nptl/pthread_cancel.c
+++ b/nptl/pthread_cancel.c
@@ -35,7 +35,8 @@ __pthread_cancel (pthread_t th)
     return ESRCH;
 
 #ifdef SHARED
-  pthread_cancel_init ();
+  /* Trigger an error if libgcc_s cannot be loaded.  */
+  __pthread_unwind_link_get ();
 #endif
   int result = 0;
   int oldval;
diff --git a/sysdeps/arm/nptl/unwind-forcedunwind.c b/sysdeps/arm/nptl/unwind-forcedunwind.c
new file mode 100644
index 0000000000..61db34c0b5
--- /dev/null
+++ b/sysdeps/arm/nptl/unwind-forcedunwind.c
@@ -0,0 +1,25 @@
+/* Unwinder function forwarders for libpthread.  Arm version.
+   Copyright (C) 2021 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public License as
+   published by the Free Software Foundation; either version 2.1 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If
+   not, see <https://www.gnu.org/licenses/>.  */
+
+#include <sysdeps/nptl/unwind-forcedunwind.c>
+
+void *
+__unwind_link_get_resume (void)
+{
+  return UNWIND_LINK_PTR (__pthread_unwind_link_get (), _Unwind_Resume);
+}
diff --git a/sysdeps/arm/pt-arm-unwind-resume.S b/sysdeps/arm/pt-arm-unwind-resume.S
index d579848696..c056eb38d0 100644
--- a/sysdeps/arm/pt-arm-unwind-resume.S
+++ b/sysdeps/arm/pt-arm-unwind-resume.S
@@ -16,31 +16,5 @@
    License along with the GNU C Library.  If not, see
    <https://www.gnu.org/licenses/>.  */
 
-#include <sysdep.h>
-
-/* This is just implementing exactly what the C version does.
-   We do it in assembly just to ensure that we get an unmolested tail
-   call to the libgcc function, which is necessary for the ARM unwinder.  */
-
-ENTRY (_Unwind_Resume)
-	LDR_HIDDEN (ip, ip, __libgcc_s_resume, 0)
-	cmp	ip, #0
-	beq	1f
-0:	PTR_DEMANGLE (ip, ip, r2, r3)
-	bx	ip
-
-	/* We need to save and restore LR (for our own return address)
-	   and R0 (for the argument to _Unwind_Resume) around the call.  */
-1:	push	{r0, lr}
-	cfi_adjust_cfa_offset (8)
-	cfi_rel_offset (r0, 0)
-	cfi_rel_offset (lr, 4)
-	bl	pthread_cancel_init
-	pop	{r0, lr}
-	cfi_adjust_cfa_offset (-8)
-	cfi_restore (r0)
-	cfi_restore (lr)
-
-	LDR_HIDDEN (ip, ip, __libgcc_s_resume, 0)
-	b	0b
-END (_Unwind_Resume)
+/* The implementation in libpthread is identical to the one in libc.  */
+#include <sysdeps/arm/arm-unwind-resume.S>
diff --git a/sysdeps/nptl/unwind-forcedunwind.c b/sysdeps/nptl/unwind-forcedunwind.c
index b70aae06ae..c0234670cf 100644
--- a/sysdeps/nptl/unwind-forcedunwind.c
+++ b/sysdeps/nptl/unwind-forcedunwind.c
@@ -16,134 +16,49 @@
    License along with the GNU C Library; see the file COPYING.LIB.  If
    not, see <https://www.gnu.org/licenses/>.  */
 
-#include <dlfcn.h>
 #include <stdio.h>
-#include <unwind.h>
+#include <unwind-link.h>
 #include <pthreadP.h>
 #include <sysdep.h>
 #include <gnu/lib-names.h>
 #include <unwind-resume.h>
 
-static void *libgcc_s_handle;
-void (*__libgcc_s_resume) (struct _Unwind_Exception *exc)
-  attribute_hidden __attribute__ ((noreturn));
-static _Unwind_Reason_Code (*libgcc_s_personality) PERSONALITY_PROTO;
-static _Unwind_Reason_Code (*libgcc_s_forcedunwind)
-  (struct _Unwind_Exception *, _Unwind_Stop_Fn, void *);
-static _Unwind_Word (*libgcc_s_getcfa) (struct _Unwind_Context *);
-
-void
-__attribute_noinline__
-pthread_cancel_init (void)
+struct unwind_link *
+__pthread_unwind_link_get (void)
 {
-  void *resume;
-  void *personality;
-  void *forcedunwind;
-  void *getcfa;
-  void *handle;
-
-  if (__glibc_likely (libgcc_s_handle != NULL))
-    {
-      /* Force gcc to reload all values.  */
-      asm volatile ("" ::: "memory");
-      return;
-    }
-
-  /* See include/dlfcn.h. Use of __libc_dlopen requires RTLD_NOW.  */
-  handle = __libc_dlopen (LIBGCC_S_SO);
-
-  if (handle == NULL
-      || (resume = __libc_dlsym (handle, "_Unwind_Resume")) == NULL
-      || (personality = __libc_dlsym (handle, "__gcc_personality_v0")) == NULL
-      || (forcedunwind = __libc_dlsym (handle, "_Unwind_ForcedUnwind"))
-	 == NULL
-      || (getcfa = __libc_dlsym (handle, "_Unwind_GetCFA")) == NULL
-#ifdef ARCH_CANCEL_INIT
-      || ARCH_CANCEL_INIT (handle)
-#endif
-      )
-    __libc_fatal (LIBGCC_S_SO " must be installed for pthread_cancel to work\n");
-
-  PTR_MANGLE (resume);
-  __libgcc_s_resume = resume;
-  PTR_MANGLE (personality);
-  libgcc_s_personality = personality;
-  PTR_MANGLE (forcedunwind);
-  libgcc_s_forcedunwind = forcedunwind;
-  PTR_MANGLE (getcfa);
-  libgcc_s_getcfa = getcfa;
-  /* Make sure libgcc_s_handle is written last.  Otherwise,
-     pthread_cancel_init might return early even when the pointer the
-     caller is interested in is not initialized yet.  */
-  atomic_write_barrier ();
-  libgcc_s_handle = handle;
-}
-
-/* Register for cleanup in libpthread.so.  */
-void
-__nptl_unwind_freeres (void)
-{
-  void *handle = libgcc_s_handle;
-  if (handle != NULL)
-    {
-      libgcc_s_handle = NULL;
-      __libc_dlclose (handle);
-    }
+  struct unwind_link *unwind_link = __libc_unwind_link_get ();
+  if (unwind_link == NULL)
+    __libc_fatal (LIBGCC_S_SO
+		  " must be installed for pthread_cancel to work\n");
+  return unwind_link;
 }
 
 #if !HAVE_ARCH_UNWIND_RESUME
 void
 _Unwind_Resume (struct _Unwind_Exception *exc)
 {
-  if (__glibc_unlikely (libgcc_s_handle == NULL))
-    pthread_cancel_init ();
-  else
-    atomic_read_barrier ();
-
-  void (*resume) (struct _Unwind_Exception *exc) = __libgcc_s_resume;
-  PTR_DEMANGLE (resume);
-  resume (exc);
+  UNWIND_LINK_PTR (__pthread_unwind_link_get (), _Unwind_Resume) (exc);
 }
 #endif
 
 _Unwind_Reason_Code
 __gcc_personality_v0 PERSONALITY_PROTO
 {
-  if (__glibc_unlikely (libgcc_s_handle == NULL))
-    pthread_cancel_init ();
-  else
-    atomic_read_barrier ();
-
-  __typeof (libgcc_s_personality) personality = libgcc_s_personality;
-  PTR_DEMANGLE (personality);
-  return (*personality) PERSONALITY_ARGS;
+  return UNWIND_LINK_PTR (__pthread_unwind_link_get (), personality)
+    PERSONALITY_ARGS;
 }
 
 _Unwind_Reason_Code
 _Unwind_ForcedUnwind (struct _Unwind_Exception *exc, _Unwind_Stop_Fn stop,
 		      void *stop_argument)
 {
-  if (__glibc_unlikely (libgcc_s_handle == NULL))
-    pthread_cancel_init ();
-  else
-    atomic_read_barrier ();
-
-  _Unwind_Reason_Code (*forcedunwind)
-    (struct _Unwind_Exception *, _Unwind_Stop_Fn, void *)
-    = libgcc_s_forcedunwind;
-  PTR_DEMANGLE (forcedunwind);
-  return forcedunwind (exc, stop, stop_argument);
+  return UNWIND_LINK_PTR (__pthread_unwind_link_get (), _Unwind_ForcedUnwind)
+    (exc, stop, stop_argument);
 }
 
 _Unwind_Word
 _Unwind_GetCFA (struct _Unwind_Context *context)
 {
-  if (__glibc_unlikely (libgcc_s_handle == NULL))
-    pthread_cancel_init ();
-  else
-    atomic_read_barrier ();
-
-  _Unwind_Word (*getcfa) (struct _Unwind_Context *) = libgcc_s_getcfa;
-  PTR_DEMANGLE (getcfa);
-  return getcfa (context);
+  return UNWIND_LINK_PTR (__pthread_unwind_link_get (), _Unwind_GetCFA)
+    (context);
 }
diff --git a/sysdeps/unix/sysv/linux/ia64/unwind-forcedunwind.c b/sysdeps/unix/sysv/linux/ia64/unwind-forcedunwind.c
index e797ea22aa..eaed6cf2ef 100644
--- a/sysdeps/unix/sysv/linux/ia64/unwind-forcedunwind.c
+++ b/sysdeps/unix/sysv/linux/ia64/unwind-forcedunwind.c
@@ -16,23 +16,11 @@
    License along with the GNU C Library; if not, see
    <https://www.gnu.org/licenses/>.  */
 
-#include <dlfcn.h>
-#include <stdio.h>
-#include <unwind.h>
-#include <pthreadP.h>
-
-static _Unwind_Word (*libgcc_s_getbsp) (struct _Unwind_Context *);
-
-#define ARCH_CANCEL_INIT(handle) \
-  ((libgcc_s_getbsp = __libc_dlsym (handle, "_Unwind_GetBSP")) == NULL)
-
 #include <sysdeps/nptl/unwind-forcedunwind.c>
 
 _Unwind_Word
 _Unwind_GetBSP (struct _Unwind_Context *context)
 {
-  if (__builtin_expect (libgcc_s_getbsp == NULL, 0))
-    pthread_cancel_init ();
-
-  return libgcc_s_getbsp (context);
+  return UNWIND_LINK_PTR (__pthread_unwind_link_get (), _Unwind_GetBSP)
+    (context);
 }
-- 
2.29.2


^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 00/10] Unwinder interface consolidation
  2021-02-17 16:02 [PATCH 00/10] Unwinder interface consolidation Florian Weimer
                   ` (9 preceding siblings ...)
  2021-02-17 16:03 ` [PATCH 10/10] nptl: Use <unwind-link.h> for accessing the libgcc_s unwinder Florian Weimer
@ 2021-03-01 13:54 ` Carlos O'Donell
  10 siblings, 0 replies; 22+ messages in thread
From: Carlos O'Donell @ 2021-03-01 13:54 UTC (permalink / raw)
  To: Florian Weimer, libc-alpha

On 2/17/21 11:02 AM, Florian Weimer via Libc-alpha wrote:
> This series is basically a repost.  I had to tweak it somewhat to pick
> up the <unwind-arch.h> customization for MIPS.  I switched to reusing
> that header for all customization.
> 
> This is a prequiste for consolidating and libc and nptl implementations
> of unwinding, and moving the cancellation implementation into libc.

This is a great idea. It has been a long standing problem that we have
two distinct copies of unwinding for backtrace and cancellation and
that they are not harmonized to avoid duplication or mistakes.

Thank you for tackling this cleanup.

The series as a whole looks good to me.

Reviewed-by: Carlos <carlos@redhat.com>
 
> Thanks,
> Florian
> 
> Florian Weimer (10):
>   Implement <unwind-link.h> for dynamically loading the libgcc_s
>     unwinder
>   backtrace: Implement on top of <unwind-link.h>
>   arm: Implement backtrace on top of <unwind-link.h>
>   i386: Implement backtrace on top of <unwind-link.h>
>   m68k: Implement backtrace on top of <unwind-link.h>
>   sparc: Implement backtrace on top <unwind-link.h>
>   __frame_state_for: Use <unwind-link.h> for unwinder access
>   Move sysdeps/gnu/unwind-resume.c to sysdeps/generic/unwind-resume.c
>   Implement _Unwind_Resume in libc on top of <unwind-link.h>
>   nptl: Use <unwind-link.h> for accessing the libgcc_s unwinder
> 
>  debug/backtrace.c                             |  86 +++--------
>  malloc/set-freeres.c                          |   5 +
>  misc/Makefile                                 |   2 +-
>  misc/Versions                                 |   1 +
>  misc/unwind-link.c                            | 145 ++++++++++++++++++
>  nptl/nptlfreeres.c                            |   1 -
>  nptl/pthreadP.h                               |   6 +-
>  nptl/pthread_cancel.c                         |   3 +-
>  sysdeps/alpha/unwind-arch.h                   |  28 ++++
>  sysdeps/arm/arm-unwind-resume.S               |  26 ++--
>  sysdeps/arm/backtrace.c                       |  77 +++-------
>  sysdeps/arm/nptl/unwind-forcedunwind.c        |  25 +++
>  sysdeps/arm/pt-arm-unwind-resume.S            |  22 ++-
>  sysdeps/arm/unwind-arch.h                     |  39 +++++
>  sysdeps/arm/unwind-resume.c                   |  25 +++
>  sysdeps/generic/framestate.c                  |  21 +--
>  sysdeps/generic/unwind-arch.h                 |  27 ++--
>  sysdeps/generic/unwind-link.h                 | 106 +++++++++++++
>  sysdeps/generic/unwind-resume.c               |  46 ++++++
>  sysdeps/gnu/unwind-resume.c                   |  83 ----------
>  sysdeps/i386/backtrace.c                      |  82 +++-------
>  sysdeps/i386/unwind-arch.h                    |  39 +++++
>  sysdeps/ia64/unwind-arch.h                    |  32 ++++
>  sysdeps/m68k/backtrace.c                      |  82 +++-------
>  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/nptl/unwind-forcedunwind.c            | 115 ++------------
>  sysdeps/powerpc/powerpc32/unwind-arch.h       |  28 ++++
>  sysdeps/s390/unwind-arch.h                    |  28 ++++
>  sysdeps/sh/unwind-arch.h                      |  28 ++++
>  sysdeps/sparc/backtrace.c                     |  66 ++------
>  sysdeps/sparc/unwind-arch.h                   |  28 ++++
>  .../sysv/linux/ia64/unwind-forcedunwind.c     |  16 +-
>  36 files changed, 852 insertions(+), 550 deletions(-)
>  create mode 100644 misc/unwind-link.c
>  create mode 100644 sysdeps/alpha/unwind-arch.h
>  create mode 100644 sysdeps/arm/nptl/unwind-forcedunwind.c
>  create mode 100644 sysdeps/arm/unwind-arch.h
>  create mode 100644 sysdeps/arm/unwind-resume.c
>  create mode 100644 sysdeps/generic/unwind-link.h
>  create mode 100644 sysdeps/generic/unwind-resume.c
>  delete mode 100644 sysdeps/gnu/unwind-resume.c
>  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
> 


-- 
Cheers,
Carlos.


^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 01/10] Implement <unwind-link.h> for dynamically loading the libgcc_s unwinder
  2021-02-17 16:02 ` [PATCH 01/10] Implement <unwind-link.h> for dynamically loading the libgcc_s unwinder Florian Weimer
@ 2021-03-01 13:54   ` Carlos O'Donell
  0 siblings, 0 replies; 22+ messages in thread
From: Carlos O'Donell @ 2021-03-01 13:54 UTC (permalink / raw)
  To: Florian Weimer, libc-alpha

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.


^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 02/10] backtrace: Implement on top of <unwind-link.h>
  2021-02-17 16:02 ` [PATCH 02/10] backtrace: Implement on top of <unwind-link.h> Florian Weimer
@ 2021-03-01 13:54   ` Carlos O'Donell
  0 siblings, 0 replies; 22+ messages in thread
From: Carlos O'Donell @ 2021-03-01 13:54 UTC (permalink / raw)
  To: Florian Weimer, libc-alpha

On 2/17/21 11:02 AM, Florian Weimer via Libc-alpha wrote:
> This reimplements the generic version of backtrace.

LGTM.

Reviewed-by: Carlos O'Donell <carlos@redhat.com>

> ---
>  debug/backtrace.c | 84 ++++++++++-------------------------------------
>  1 file changed, 17 insertions(+), 67 deletions(-)
> 
> diff --git a/debug/backtrace.c b/debug/backtrace.c
> index 5ded57bfc4..187d911a0d 100644
> --- a/debug/backtrace.c
> +++ b/debug/backtrace.c
> @@ -17,10 +17,7 @@
>     License along with the GNU C Library; if not, see
>     <https://www.gnu.org/licenses/>.  */
>  
> -#include <libc-lock.h>
> -#include <dlfcn.h>
>  #include <execinfo.h>
> -#include <gnu/lib-names.h>
>  #include <stdlib.h>
>  #include <unwind.h>
>  #include <unwind-link.h>
> @@ -28,47 +25,12 @@
>  struct trace_arg
>  {
>    void **array;
> +  struct unwind_link *unwind_link;

OK. Loaded unwinder.

>    _Unwind_Word cfa;
>    int cnt;
>    int size;
>  };
>  
> -#ifdef SHARED
> -static _Unwind_Reason_Code (*unwind_backtrace) (_Unwind_Trace_Fn, void *);
> -static _Unwind_Ptr (*unwind_getip) (struct _Unwind_Context *);
> -static _Unwind_Word (*unwind_getcfa) (struct _Unwind_Context *);
> -static void *libgcc_handle;
> -
> -
> -/* Dummy version in case libgcc_s does not contain the real code.  */
> -static _Unwind_Word
> -dummy_getcfa (struct _Unwind_Context *ctx __attribute__ ((unused)))
> -{
> -  return 0;
> -}
> -
> -
> -static void
> -init (void)
> -{
> -  libgcc_handle = __libc_dlopen (LIBGCC_S_SO);
> -
> -  if (libgcc_handle == NULL)
> -    return;
> -
> -  unwind_backtrace = __libc_dlsym (libgcc_handle, "_Unwind_Backtrace");
> -  unwind_getip = __libc_dlsym (libgcc_handle, "_Unwind_GetIP");
> -  if (unwind_getip == NULL)
> -    unwind_backtrace = NULL;
> -  unwind_getcfa = (__libc_dlsym (libgcc_handle, "_Unwind_GetCFA")
> -		  ?: dummy_getcfa);
> -}
> -#else
> -# define unwind_backtrace _Unwind_Backtrace
> -# define unwind_getip _Unwind_GetIP
> -# define unwind_getcfa _Unwind_GetCFA
> -#endif
> -
>  static _Unwind_Reason_Code
>  backtrace_helper (struct _Unwind_Context *ctx, void *a)
>  {
> @@ -78,14 +40,16 @@ backtrace_helper (struct _Unwind_Context *ctx, void *a)
>       Skip it.  */
>    if (arg->cnt != -1)
>      {
> -      arg->array[arg->cnt] = (void *) unwind_getip (ctx);
> +      arg->array[arg->cnt]
> +	= (void *) UNWIND_LINK_PTR (arg->unwind_link, _Unwind_GetIP) (ctx);
>        if (arg->cnt > 0)
>  	arg->array[arg->cnt]
>  	  = unwind_arch_adjustment (arg->array[arg->cnt - 1],
>  				    arg->array[arg->cnt]);
>  
>        /* Check whether we make any progress.  */
> -      _Unwind_Word cfa = unwind_getcfa (ctx);
> +      _Unwind_Word cfa
> +	= UNWIND_LINK_PTR (arg->unwind_link, _Unwind_GetCFA) (ctx);
>  
>        if (arg->cnt > 0 && arg->array[arg->cnt - 1] == arg->array[arg->cnt]
>  	 && cfa == arg->cfa)
> @@ -100,20 +64,20 @@ backtrace_helper (struct _Unwind_Context *ctx, void *a)
>  int
>  __backtrace (void **array, int size)
>  {
> -  struct trace_arg arg = { .array = array, .cfa = 0, .size = size, .cnt = -1 };
> -
> -  if (size <= 0)
> -    return 0;
> -
> -#ifdef SHARED
> -  __libc_once_define (static, once);
> -
> -  __libc_once (once, init);
> -  if (unwind_backtrace == NULL)
> +  struct trace_arg arg =
> +    {
> +     .array = array,
> +     .unwind_link = __libc_unwind_link_get (),
> +     .cfa = 0,
> +     .size = size,
> +     .cnt = -1
> +    };
> +
> +  if (size <= 0 || arg.unwind_link == NULL)
>      return 0;
> -#endif
>  
> -  unwind_backtrace (backtrace_helper, &arg);
> +  UNWIND_LINK_PTR (arg.unwind_link, _Unwind_Backtrace)
> +    (backtrace_helper, &arg);
>  
>    /* _Unwind_Backtrace seems to put NULL address above
>       _start.  Fix it up here.  */
> @@ -123,17 +87,3 @@ __backtrace (void **array, int size)
>  }
>  weak_alias (__backtrace, backtrace)
>  libc_hidden_def (__backtrace)
> -
> -
> -#ifdef SHARED
> -/* Free all resources if necessary.  */
> -libc_freeres_fn (free_mem)
> -{
> -  unwind_backtrace = NULL;
> -  if (libgcc_handle != NULL)
> -    {
> -      __libc_dlclose (libgcc_handle);
> -      libgcc_handle = NULL;
> -    }
> -}

OK. Not needed because we handle the loaded libgcc in the unwind-link changes.

> -#endif
> 


-- 
Cheers,
Carlos.


^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 03/10] arm: Implement backtrace on top of <unwind-link.h>
  2021-02-17 16:02 ` [PATCH 03/10] arm: Implement backtrace " Florian Weimer
@ 2021-03-01 13:54   ` Carlos O'Donell
  0 siblings, 0 replies; 22+ messages in thread
From: Carlos O'Donell @ 2021-03-01 13:54 UTC (permalink / raw)
  To: Florian Weimer, libc-alpha

On 2/17/21 11:02 AM, Florian Weimer via Libc-alpha wrote:

LGTM. The arm version.

Reviewed-by: Carlos O'Donell <carlos@redhat.com>

> ---
>  sysdeps/arm/backtrace.c | 77 +++++++++++------------------------------
>  1 file changed, 20 insertions(+), 57 deletions(-)
> 
> diff --git a/sysdeps/arm/backtrace.c b/sysdeps/arm/backtrace.c
> index 3ed975fb96..193f2410ba 100644
> --- a/sysdeps/arm/backtrace.c
> +++ b/sysdeps/arm/backtrace.c
> @@ -17,58 +17,36 @@
>     License along with the GNU C Library.  If not, see
>     <https://www.gnu.org/licenses/>.  */
>  
> -#include <libc-lock.h>
> -#include <dlfcn.h>
>  #include <execinfo.h>
>  #include <stdlib.h>
> -#include <unwind.h>
> +#include <unwind-link.h>
>  
>  struct trace_arg
>  {
>    void **array;
> +  struct unwind_link *unwind_link;
>    int cnt, size;
>  };
>  
>  #ifdef SHARED
> -static _Unwind_Reason_Code (*unwind_backtrace) (_Unwind_Trace_Fn, void *);
> -static _Unwind_VRS_Result (*unwind_vrs_get) (_Unwind_Context *,
> -					     _Unwind_VRS_RegClass,
> -					     _uw,
> -					     _Unwind_VRS_DataRepresentation,
> -					     void *);
> -
> -static void *libgcc_handle;
> -
> -static void
> -init (void)
> -{
> -  libgcc_handle = __libc_dlopen ("libgcc_s.so.1");
> -
> -  if (libgcc_handle == NULL)
> -    return;
> -
> -  unwind_backtrace = __libc_dlsym (libgcc_handle, "_Unwind_Backtrace");
> -  unwind_vrs_get = __libc_dlsym (libgcc_handle, "_Unwind_VRS_Get");
> -  if (unwind_vrs_get == NULL)
> -    unwind_backtrace = NULL;
> -}
> -
>  /* This function is identical to "_Unwind_GetGR", except that it uses
>     "unwind_vrs_get" instead of "_Unwind_VRS_Get".  */
>  static inline _Unwind_Word
> -unwind_getgr (_Unwind_Context *context, int regno)
> +unwind_getgr (struct unwind_link *unwind_link,
> +	      _Unwind_Context *context, int regno)
>  {
>    _uw val;
> -  unwind_vrs_get (context, _UVRSC_CORE, regno, _UVRSD_UINT32, &val);
> +  UNWIND_LINK_PTR (unwind_link, _Unwind_VRS_Get)
> +    (context, _UVRSC_CORE, regno, _UVRSD_UINT32, &val);
>    return val;
>  }
>  
>  /* This macro is identical to the _Unwind_GetIP macro, except that it
>     uses "unwind_getgr" instead of "_Unwind_GetGR".  */
> -# define unwind_getip(context) \
> -  (unwind_getgr (context, 15) & ~(_Unwind_Word)1)
> -#else
> -# define unwind_backtrace _Unwind_Backtrace
> +#define unwind_getip(context) \
> +  (unwind_getgr (arg->unwind_link, context, 15) & ~(_Unwind_Word)1)
> +
> +#else /* !SHARED */
>  # define unwind_getip _Unwind_GetIP
>  #endif
>  
> @@ -89,20 +67,19 @@ backtrace_helper (struct _Unwind_Context *ctx, void *a)
>  int
>  __backtrace (void **array, int size)
>  {
> -  struct trace_arg arg = { .array = array, .size = size, .cnt = -1 };
> -
> -  if (size <= 0)
> -    return 0;
> -
> -#ifdef SHARED
> -  __libc_once_define (static, once);
> +  struct trace_arg arg =
> +    {
> +     .array = array,
> +     .unwind_link = __libc_unwind_link_get (),
> +     .size = size,
> +     .cnt = -1
> +    };
>  
> -  __libc_once (once, init);
> -  if (unwind_backtrace == NULL)
> +  if (size <= 0 || arg.unwind_link == NULL)
>      return 0;
> -#endif
>  
> -  unwind_backtrace (backtrace_helper, &arg);
> +  UNWIND_LINK_PTR (arg.unwind_link, _Unwind_Backtrace)
> +    (backtrace_helper, &arg);
>  
>    if (arg.cnt > 1 && arg.array[arg.cnt - 1] == NULL)
>      --arg.cnt;
> @@ -110,17 +87,3 @@ __backtrace (void **array, int size)
>  }
>  weak_alias (__backtrace, backtrace)
>  libc_hidden_def (__backtrace)
> -
> -
> -#ifdef SHARED
> -/* Free all resources if necessary.  */
> -libc_freeres_fn (free_mem)
> -{
> -  unwind_backtrace = NULL;
> -  if (libgcc_handle != NULL)
> -    {
> -      __libc_dlclose (libgcc_handle);
> -      libgcc_handle = NULL;
> -    }
> -}
> -#endif
> 


-- 
Cheers,
Carlos.


^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 04/10] i386: Implement backtrace on top of <unwind-link.h>
  2021-02-17 16:03 ` [PATCH 04/10] i386: " Florian Weimer
@ 2021-03-01 13:54   ` Carlos O'Donell
  0 siblings, 0 replies; 22+ messages in thread
From: Carlos O'Donell @ 2021-03-01 13:54 UTC (permalink / raw)
  To: Florian Weimer, libc-alpha

On 2/17/21 11:03 AM, Florian Weimer via Libc-alpha wrote:

LGTM. And the i386 version.

Reviewed-by: Carlos O'Donell <carlos@redhat.com>

> ---
>  sysdeps/i386/backtrace.c | 82 +++++++++-------------------------------
>  1 file changed, 18 insertions(+), 64 deletions(-)
> 
> diff --git a/sysdeps/i386/backtrace.c b/sysdeps/i386/backtrace.c
> index 124b0b73e3..4631f68fdc 100644
> --- a/sysdeps/i386/backtrace.c
> +++ b/sysdeps/i386/backtrace.c
> @@ -17,52 +17,18 @@
>     License along with the GNU C Library; if not, see
>     <https://www.gnu.org/licenses/>.  */
>  
> -#include <libc-lock.h>
> -#include <dlfcn.h>
>  #include <execinfo.h>
>  #include <stdlib.h>
> -#include <unwind.h>
> +#include <unwind-link.h>
>  
>  struct trace_arg
>  {
>    void **array;
> +  struct unwind_link *unwind_link;
>    int cnt, size;
>    void *lastebp, *lastesp;
>  };
>  
> -#ifdef SHARED
> -static _Unwind_Reason_Code (*unwind_backtrace) (_Unwind_Trace_Fn, void *);
> -static _Unwind_Ptr (*unwind_getip) (struct _Unwind_Context *);
> -static _Unwind_Ptr (*unwind_getcfa) (struct _Unwind_Context *);
> -static _Unwind_Ptr (*unwind_getgr) (struct _Unwind_Context *, int);
> -static void *libgcc_handle;
> -
> -static void
> -init (void)
> -{
> -  libgcc_handle = __libc_dlopen ("libgcc_s.so.1");
> -
> -  if (libgcc_handle == NULL)
> -    return;
> -
> -  unwind_backtrace = __libc_dlsym (libgcc_handle, "_Unwind_Backtrace");
> -  unwind_getip = __libc_dlsym (libgcc_handle, "_Unwind_GetIP");
> -  unwind_getcfa = __libc_dlsym (libgcc_handle, "_Unwind_GetCFA");
> -  unwind_getgr = __libc_dlsym (libgcc_handle, "_Unwind_GetGR");
> -  if (unwind_getip == NULL || unwind_getgr == NULL || unwind_getcfa == NULL)
> -    {
> -      unwind_backtrace = NULL;
> -      __libc_dlclose (libgcc_handle);
> -      libgcc_handle = NULL;
> -    }
> -}
> -#else
> -# define unwind_backtrace _Unwind_Backtrace
> -# define unwind_getip _Unwind_GetIP
> -# define unwind_getcfa _Unwind_GetCFA
> -# define unwind_getgr _Unwind_GetGR
> -#endif
> -
>  static _Unwind_Reason_Code
>  backtrace_helper (struct _Unwind_Context *ctx, void *a)
>  {
> @@ -71,13 +37,16 @@ backtrace_helper (struct _Unwind_Context *ctx, void *a)
>    /* We are first called with address in the __backtrace function.
>       Skip it.  */
>    if (arg->cnt != -1)
> -    arg->array[arg->cnt] = (void *) unwind_getip (ctx);
> +    arg->array[arg->cnt]
> +      = (void *) UNWIND_LINK_PTR (arg->unwind_link, _Unwind_GetIP) (ctx);
>    if (++arg->cnt == arg->size)
>      return _URC_END_OF_STACK;
>  
>    /* %ebp is DWARF2 register 5 on IA-32.  */
> -  arg->lastebp = (void *) unwind_getgr (ctx, 5);
> -  arg->lastesp = (void *) unwind_getcfa (ctx);
> +  arg->lastebp
> +    = (void *) UNWIND_LINK_PTR (arg->unwind_link, _Unwind_GetGR) (ctx, 5);
> +  arg->lastesp
> +    = (void *) UNWIND_LINK_PTR (arg->unwind_link, _Unwind_GetCFA) (ctx);
>    return _URC_NO_REASON;
>  }
>  
> @@ -111,20 +80,19 @@ struct layout
>  int
>  __backtrace (void **array, int size)
>  {
> -  struct trace_arg arg = { .array = array, .size = size, .cnt = -1 };
> -
> -  if (size <= 0)
> -    return 0;
> -
> -#ifdef SHARED
> -  __libc_once_define (static, once);
> +  struct trace_arg arg =
> +    {
> +     .array = array,
> +     .unwind_link = __libc_unwind_link_get (),
> +     .size = size,
> +     .cnt = -1,
> +    };
>  
> -  __libc_once (once, init);
> -  if (unwind_backtrace == NULL)
> +  if (size <= 0 || arg.unwind_link == NULL)
>      return 0;
> -#endif
>  
> -  unwind_backtrace (backtrace_helper, &arg);
> +  UNWIND_LINK_PTR (arg.unwind_link, _Unwind_Backtrace)
> +    (backtrace_helper, &arg);
>  
>    if (arg.cnt > 1 && arg.array[arg.cnt - 1] == NULL)
>      --arg.cnt;
> @@ -147,17 +115,3 @@ __backtrace (void **array, int size)
>  }
>  weak_alias (__backtrace, backtrace)
>  libc_hidden_def (__backtrace)
> -
> -
> -#ifdef SHARED
> -/* Free all resources if necessary.  */
> -libc_freeres_fn (free_mem)
> -{
> -  unwind_backtrace = NULL;
> -  if (libgcc_handle != NULL)
> -    {
> -      __libc_dlclose (libgcc_handle);
> -      libgcc_handle = NULL;
> -    }
> -}
> -#endif
> 


-- 
Cheers,
Carlos.


^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 05/10] m68k: Implement backtrace on top of <unwind-link.h>
  2021-02-17 16:03 ` [PATCH 05/10] m68k: " Florian Weimer
@ 2021-03-01 13:54   ` Carlos O'Donell
  0 siblings, 0 replies; 22+ messages in thread
From: Carlos O'Donell @ 2021-03-01 13:54 UTC (permalink / raw)
  To: Florian Weimer, libc-alpha

On 2/17/21 11:03 AM, Florian Weimer via Libc-alpha wrote:

LGTM. And the m68k version.

Reviewed-by: Carlos O'Donell <carlos@redhat.com>

> ---
>  sysdeps/m68k/backtrace.c | 82 +++++++++-------------------------------
>  1 file changed, 18 insertions(+), 64 deletions(-)
> 
> diff --git a/sysdeps/m68k/backtrace.c b/sysdeps/m68k/backtrace.c
> index 86e9a888f0..27b9c58167 100644
> --- a/sysdeps/m68k/backtrace.c
> +++ b/sysdeps/m68k/backtrace.c
> @@ -16,52 +16,18 @@
>     License along with the GNU C Library; if not, see
>     <https://www.gnu.org/licenses/>.  */
>  
> -#include <libc-lock.h>
> -#include <dlfcn.h>
>  #include <execinfo.h>
>  #include <stdlib.h>
> -#include <unwind.h>
> +#include <unwind-link.h>
>  
>  struct trace_arg
>  {
>    void **array;
> +  struct unwind_link *unwind_link;
>    int cnt, size;
>    void *lastfp, *lastsp;
>  };
>  
> -#ifdef SHARED
> -static _Unwind_Reason_Code (*unwind_backtrace) (_Unwind_Trace_Fn, void *);
> -static _Unwind_Ptr (*unwind_getip) (struct _Unwind_Context *);
> -static _Unwind_Ptr (*unwind_getcfa) (struct _Unwind_Context *);
> -static _Unwind_Ptr (*unwind_getgr) (struct _Unwind_Context *, int);
> -static void *libgcc_handle;
> -
> -static void
> -init (void)
> -{
> -  libgcc_handle = __libc_dlopen ("libgcc_s.so.2");
> -
> -  if (libgcc_handle == NULL)
> -    return;
> -
> -  unwind_backtrace = __libc_dlsym (libgcc_handle, "_Unwind_Backtrace");
> -  unwind_getip = __libc_dlsym (libgcc_handle, "_Unwind_GetIP");
> -  unwind_getcfa = __libc_dlsym (libgcc_handle, "_Unwind_GetCFA");
> -  unwind_getgr = __libc_dlsym (libgcc_handle, "_Unwind_GetGR");
> -  if (unwind_getip == NULL || unwind_getgr == NULL || unwind_getcfa == NULL)
> -    {
> -      unwind_backtrace = NULL;
> -      __libc_dlclose (libgcc_handle);
> -      libgcc_handle = NULL;
> -    }
> -}
> -#else
> -# define unwind_backtrace _Unwind_Backtrace
> -# define unwind_getip _Unwind_GetIP
> -# define unwind_getcfa _Unwind_GetCFA
> -# define unwind_getgr _Unwind_GetGR
> -#endif
> -
>  static _Unwind_Reason_Code
>  backtrace_helper (struct _Unwind_Context *ctx, void *a)
>  {
> @@ -70,13 +36,16 @@ backtrace_helper (struct _Unwind_Context *ctx, void *a)
>    /* We are first called with address in the __backtrace function.
>       Skip it.  */
>    if (arg->cnt != -1)
> -    arg->array[arg->cnt] = (void *) unwind_getip (ctx);
> +    arg->array[arg->cnt]
> +      = (void *) UNWIND_LINK_PTR (arg->unwind_link, _Unwind_GetIP) (ctx);
>    if (++arg->cnt == arg->size)
>      return _URC_END_OF_STACK;
>  
>    /* %fp is DWARF2 register 14 on M68K.  */
> -  arg->lastfp = (void *) unwind_getgr (ctx, 14);
> -  arg->lastsp = (void *) unwind_getcfa (ctx);
> +  arg->lastfp
> +    = (void *) UNWIND_LINK_PTR (arg->unwind_link, _Unwind_GetGR) (ctx, 14);
> +  arg->lastsp
> +    = (void *) UNWIND_LINK_PTR (arg->unwind_link, _Unwind_GetCFA) (ctx);
>    return _URC_NO_REASON;
>  }
>  
> @@ -110,20 +79,19 @@ struct layout
>  int
>  __backtrace (void **array, int size)
>  {
> -  struct trace_arg arg = { .array = array, .size = size, .cnt = -1 };
> -
> -  if (size <= 0)
> -    return 0;
> -
> -#ifdef SHARED
> -  __libc_once_define (static, once);
> +  struct trace_arg arg =
> +    {
> +     .array = array,
> +     .unwind_link = __libc_unwind_link_get (),
> +     .size = size,
> +     .cnt = -1,
> +    };
>  
> -  __libc_once (once, init);
> -  if (unwind_backtrace == NULL)
> +  if (size <= 0 || arg.unwind_link == NULL)
>      return 0;
> -#endif
>  
> -  unwind_backtrace (backtrace_helper, &arg);
> +  UNWIND_LINK_PTR (arg.unwind_link, _Unwind_Backtrace)
> +    (backtrace_helper, &arg);
>  
>    if (arg.cnt > 1 && arg.array[arg.cnt - 1] == NULL)
>      --arg.cnt;
> @@ -146,17 +114,3 @@ __backtrace (void **array, int size)
>  }
>  weak_alias (__backtrace, backtrace)
>  libc_hidden_def (__backtrace)
> -
> -
> -#ifdef SHARED
> -/* Free all resources if necessary.  */
> -libc_freeres_fn (free_mem)
> -{
> -  unwind_backtrace = NULL;
> -  if (libgcc_handle != NULL)
> -    {
> -      __libc_dlclose (libgcc_handle);
> -      libgcc_handle = NULL;
> -    }
> -}
> -#endif
> 


-- 
Cheers,
Carlos.


^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 06/10] sparc: Implement backtrace on top <unwind-link.h>
  2021-02-17 16:03 ` [PATCH 06/10] sparc: Implement backtrace on top <unwind-link.h> Florian Weimer
@ 2021-03-01 13:54   ` Carlos O'Donell
  0 siblings, 0 replies; 22+ messages in thread
From: Carlos O'Donell @ 2021-03-01 13:54 UTC (permalink / raw)
  To: Florian Weimer, libc-alpha

On 2/17/21 11:03 AM, Florian Weimer via Libc-alpha wrote:

LGTM. And the sparc version.

Reviewed-by: Carlos O'Donell <carlos@redhat.com>

> ---
>  sysdeps/sparc/backtrace.c | 66 +++++++++------------------------------
>  1 file changed, 15 insertions(+), 51 deletions(-)
> 
> diff --git a/sysdeps/sparc/backtrace.c b/sysdeps/sparc/backtrace.c
> index 62196f0538..1bad755b7f 100644
> --- a/sysdeps/sparc/backtrace.c
> +++ b/sysdeps/sparc/backtrace.c
> @@ -21,9 +21,8 @@
>  #include <stddef.h>
>  #include <sysdep.h>
>  #include <sys/trap.h>
> -#include <dlfcn.h>
> -#include <unwind.h>
>  #include <backtrace.h>
> +#include <unwind-link.h>
>  
>  struct layout
>  {
> @@ -36,45 +35,12 @@ struct layout
>  struct trace_arg
>  {
>    void **array;
> +  struct unwind_link *unwind_link;
>    _Unwind_Word cfa;
>    int cnt;
>    int size;
>  };
>  
> -#ifdef SHARED
> -static _Unwind_Reason_Code (*unwind_backtrace) (_Unwind_Trace_Fn, void *);
> -static _Unwind_Ptr (*unwind_getip) (struct _Unwind_Context *);
> -static _Unwind_Word (*unwind_getcfa) (struct _Unwind_Context *);
> -static void *libgcc_handle;
> -
> -/* Dummy version in case libgcc_s does not contain the real code.  */
> -static _Unwind_Word
> -dummy_getcfa (struct _Unwind_Context *ctx __attribute__ ((unused)))
> -{
> -  return 0;
> -}
> -
> -static void
> -init (void)
> -{
> -  libgcc_handle = __libc_dlopen ("libgcc_s.so.1");
> -
> -  if (libgcc_handle == NULL)
> -    return;
> -
> -  unwind_backtrace = __libc_dlsym (libgcc_handle, "_Unwind_Backtrace");
> -  unwind_getip = __libc_dlsym (libgcc_handle, "_Unwind_GetIP");
> -  if (unwind_getip == NULL)
> -    unwind_backtrace = NULL;
> -  unwind_getcfa = (__libc_dlsym (libgcc_handle, "_Unwind_GetCFA")
> -		  ?: dummy_getcfa);
> -}
> -#else
> -# define unwind_backtrace _Unwind_Backtrace
> -# define unwind_getip _Unwind_GetIP
> -# define unwind_getcfa _Unwind_GetCFA
> -#endif
> -
>  static _Unwind_Reason_Code
>  backtrace_helper (struct _Unwind_Context *ctx, void *a)
>  {
> @@ -85,11 +51,12 @@ backtrace_helper (struct _Unwind_Context *ctx, void *a)
>       Skip it.  */
>    if (arg->cnt != -1)
>      {
> -      ip = unwind_getip (ctx);
> +      ip = UNWIND_LINK_PTR (arg->unwind_link, _Unwind_GetIP) (ctx);
>        arg->array[arg->cnt] = (void *) ip;
>  
>        /* Check whether we make any progress.  */
> -      _Unwind_Word cfa = unwind_getcfa (ctx);
> +      _Unwind_Word cfa
> +	= UNWIND_LINK_PTR (arg->unwind_link, _Unwind_GetCFA) (ctx);
>  
>        if (arg->cnt > 0 && arg->array[arg->cnt - 1] == arg->array[arg->cnt]
>  	 && cfa == arg->cfa)
> @@ -104,23 +71,19 @@ backtrace_helper (struct _Unwind_Context *ctx, void *a)
>  int
>  __backtrace (void **array, int size)
>  {
> -  struct trace_arg arg = { .array = array, .cfa = 0, .size = size, .cnt = -1 };
> -  bool use_unwinder;
>    int count;
> +  struct trace_arg arg =
> +    {
> +     .array = array,
> +     .unwind_link = __libc_unwind_link_get (),
> +     .size = size,
> +     .cnt = -1,
> +    };
>  
>    if (size <= 0)
>      return 0;
>  
> -  use_unwinder = true;
> -#ifdef SHARED
> -  __libc_once_define (static, once);
> -
> -  __libc_once (once, init);
> -  if (unwind_backtrace == NULL)
> -    use_unwinder = false;
> -#endif
> -
> -  if (use_unwinder == false)
> +  if (arg.unwind_link == NULL)
>      {
>        struct layout *current;
>        unsigned long fp, i7;
> @@ -145,7 +108,8 @@ __backtrace (void **array, int size)
>      }
>    else
>      {
> -      unwind_backtrace (backtrace_helper, &arg);
> +      UNWIND_LINK_PTR (arg.unwind_link, _Unwind_Backtrace)
> +	(backtrace_helper, &arg);
>  
>        /* _Unwind_Backtrace seems to put NULL address above
>  	 _start.  Fix it up here.  */
> 


-- 
Cheers,
Carlos.


^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 07/10] __frame_state_for: Use <unwind-link.h> for unwinder access
  2021-02-17 16:03 ` [PATCH 07/10] __frame_state_for: Use <unwind-link.h> for unwinder access Florian Weimer
@ 2021-03-01 13:54   ` Carlos O'Donell
  0 siblings, 0 replies; 22+ messages in thread
From: Carlos O'Donell @ 2021-03-01 13:54 UTC (permalink / raw)
  To: Florian Weimer, libc-alpha

On 2/17/21 11:03 AM, Florian Weimer via Libc-alpha wrote:

LGTM. Cleanup generic __frame_state_for.

Reviewed-by: Carlos O'Donell <carlos@redhat.com>

> ---
>  sysdeps/generic/framestate.c | 21 ++++++++-------------
>  1 file changed, 8 insertions(+), 13 deletions(-)
> 
> diff --git a/sysdeps/generic/framestate.c b/sysdeps/generic/framestate.c
> index c1b364dbaa..54c4817f37 100644
> --- a/sysdeps/generic/framestate.c
> +++ b/sysdeps/generic/framestate.c
> @@ -17,7 +17,6 @@
>     License along with the GNU C Library; if not, see
>     <https://www.gnu.org/licenses/>.  */
>  
> -#include <dlfcn.h>
>  #include <stdlib.h>
>  #define STATIC static
>  #define __frame_state_for fallback_frame_state_for
> @@ -25,6 +24,8 @@
>  #undef __frame_state_for
>  #include <gnu/lib-names.h>
>  
> +#include <unwind-link.h>
> +
>  typedef struct frame_state * (*framesf)(void *pc, struct frame_state *);
>  struct frame_state *__frame_state_for (void *pc,
>  				       struct frame_state *frame_state);
> @@ -32,21 +33,15 @@ struct frame_state *__frame_state_for (void *pc,
>  struct frame_state *
>  __frame_state_for (void *pc, struct frame_state *frame_state)
>  {
> -  static framesf frame_state_for;
> -
> -  if (frame_state_for == NULL)
> +  struct unwind_link *unwind_link = __libc_unwind_link_get ();
> +  if (unwind_link != NULL)
> +    return UNWIND_LINK_PTR (unwind_link, __frame_state_for) (pc, frame_state);
> +  else
>      {
> -      void *handle = __libc_dlopen (LIBGCC_S_SO);
> -
> -      if (handle == NULL
> -	  || (frame_state_for
> -	      = (framesf) __libc_dlsym (handle, "__frame_state_for")) == NULL)
>  #ifndef __USING_SJLJ_EXCEPTIONS__
> -	frame_state_for = fallback_frame_state_for;
> +      return fallback_frame_state_for (pc, frame_state);
>  #else
> -	frame_state_for = abort;
> +      abort ();
>  #endif
>      }
> -
> -  return frame_state_for (pc, frame_state);
>  }
> 


-- 
Cheers,
Carlos.


^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 08/10] Move sysdeps/gnu/unwind-resume.c to sysdeps/generic/unwind-resume.c
  2021-02-17 16:03 ` [PATCH 08/10] Move sysdeps/gnu/unwind-resume.c to sysdeps/generic/unwind-resume.c Florian Weimer
@ 2021-03-01 13:55   ` Carlos O'Donell
  0 siblings, 0 replies; 22+ messages in thread
From: Carlos O'Donell @ 2021-03-01 13:55 UTC (permalink / raw)
  To: Florian Weimer, libc-alpha

On 2/17/21 11:03 AM, Florian Weimer via Libc-alpha wrote:
> This change allows architecture-specific sysdeps directories to override
> it.

LGTM. Just moves a file.

Reviewed-by: Carlos O'Donell <carlos@redhat.com>

> ---
>  sysdeps/{gnu => generic}/unwind-resume.c | 0
>  1 file changed, 0 insertions(+), 0 deletions(-)
>  rename sysdeps/{gnu => generic}/unwind-resume.c (100%)
> 
> diff --git a/sysdeps/gnu/unwind-resume.c b/sysdeps/generic/unwind-resume.c
> similarity index 100%
> rename from sysdeps/gnu/unwind-resume.c
> rename to sysdeps/generic/unwind-resume.c
> 


-- 
Cheers,
Carlos.


^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 09/10] Implement _Unwind_Resume in libc on top of <unwind-link.h>
  2021-02-17 16:03 ` [PATCH 09/10] Implement _Unwind_Resume in libc on top of <unwind-link.h> Florian Weimer
@ 2021-03-01 13:55   ` Carlos O'Donell
  0 siblings, 0 replies; 22+ messages in thread
From: Carlos O'Donell @ 2021-03-01 13:55 UTC (permalink / raw)
  To: Florian Weimer, libc-alpha

On 2/17/21 11:03 AM, Florian Weimer via Libc-alpha wrote:
> Temporarily move the arm _Unwind_Resume implementation to the file
> used by libpthread.  It will be ported to <unwind-link.h> along with
> the rest of nptl.

LGTM.

Reviewed-by: Carlos O'Donell <carlos@redhat.com>

> ---
>  sysdeps/arm/arm-unwind-resume.S    | 26 +++++++-------
>  sysdeps/arm/pt-arm-unwind-resume.S | 48 ++++++++++++++++++++++++--
>  sysdeps/arm/unwind-arch.h          |  4 +++
>  sysdeps/arm/unwind-resume.c        | 25 ++++++++++++++
>  sysdeps/generic/unwind-resume.c    | 55 +++++-------------------------
>  5 files changed, 97 insertions(+), 61 deletions(-)
>  create mode 100644 sysdeps/arm/unwind-resume.c
> 
> diff --git a/sysdeps/arm/arm-unwind-resume.S b/sysdeps/arm/arm-unwind-resume.S
> index 22525f4db0..92c171fe0f 100644
> --- a/sysdeps/arm/arm-unwind-resume.S
> +++ b/sysdeps/arm/arm-unwind-resume.S
> @@ -18,29 +18,29 @@
>  
>  #include <sysdep.h>
>  
> -/* This is just implementing exactly what the C version does.
> +/* This is equivalent to the following C implementation:
> +
> +   void
> +   _Unwind_Resume (struct _Unwind_Exception *exc)
> +   {
> +     __unwind_link_get_resume () (exc);
> +   }
> +
>     We do it in assembly just to ensure that we get an unmolested tail
>     call to the libgcc function, which is necessary for the ARM unwinder.  */
>  
>  ENTRY (_Unwind_Resume)
> -	LDR_HIDDEN (ip, ip, __libgcc_s_resume, 0)
> -	cmp	ip, #0
> -	beq	1f
> -0:	PTR_DEMANGLE (ip, ip, r2, r3)
> -	bx	ip
> -
>  	/* We need to save and restore LR (for our own return address)
>  	   and R0 (for the argument to _Unwind_Resume) around the call.  */
> -1:	push	{r0, lr}
> +	push	{r0, lr}
>  	cfi_adjust_cfa_offset (8)
>  	cfi_rel_offset (r0, 0)
>  	cfi_rel_offset (lr, 4)
> -	bl	__libgcc_s_init
> +	bl	__unwind_link_get_resume
> +	mov	r3, r0
>  	pop	{r0, lr}
>  	cfi_adjust_cfa_offset (-8)
> -	cfi_restore (r0)
> +	cfi_restore (r4)
>  	cfi_restore (lr)
> -
> -	LDR_HIDDEN (ip, ip, __libgcc_s_resume, 0)
> -	b	0b
> +	bx	r3
>  END (_Unwind_Resume)
> diff --git a/sysdeps/arm/pt-arm-unwind-resume.S b/sysdeps/arm/pt-arm-unwind-resume.S
> index 7cb555c02b..d579848696 100644
> --- a/sysdeps/arm/pt-arm-unwind-resume.S
> +++ b/sysdeps/arm/pt-arm-unwind-resume.S
> @@ -1,2 +1,46 @@
> -#define __libgcc_s_init	pthread_cancel_init
> -#include <arm-unwind-resume.S>
> +/* _Unwind_Resume wrapper for ARM EABI.
> +   Copyright (C) 2015-2021 Free Software Foundation, Inc.
> +   This file is part of the GNU C Library.
> +
> +   The GNU C Library is free software; you can redistribute it and/or
> +   modify it under the terms of the GNU Lesser General Public License as
> +   published by the Free Software Foundation; either version 2.1 of the
> +   License, or (at your option) any later version.
> +
> +   The GNU C Library is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +   Lesser General Public License for more details.
> +
> +   You should have received a copy of the GNU Lesser General Public
> +   License along with the GNU C Library.  If not, see
> +   <https://www.gnu.org/licenses/>.  */
> +
> +#include <sysdep.h>
> +
> +/* This is just implementing exactly what the C version does.
> +   We do it in assembly just to ensure that we get an unmolested tail
> +   call to the libgcc function, which is necessary for the ARM unwinder.  */
> +
> +ENTRY (_Unwind_Resume)
> +	LDR_HIDDEN (ip, ip, __libgcc_s_resume, 0)
> +	cmp	ip, #0
> +	beq	1f
> +0:	PTR_DEMANGLE (ip, ip, r2, r3)
> +	bx	ip
> +
> +	/* We need to save and restore LR (for our own return address)
> +	   and R0 (for the argument to _Unwind_Resume) around the call.  */
> +1:	push	{r0, lr}
> +	cfi_adjust_cfa_offset (8)
> +	cfi_rel_offset (r0, 0)
> +	cfi_rel_offset (lr, 4)
> +	bl	pthread_cancel_init
> +	pop	{r0, lr}
> +	cfi_adjust_cfa_offset (-8)
> +	cfi_restore (r0)
> +	cfi_restore (lr)
> +
> +	LDR_HIDDEN (ip, ip, __libgcc_s_resume, 0)
> +	b	0b
> +END (_Unwind_Resume)
> diff --git a/sysdeps/arm/unwind-arch.h b/sysdeps/arm/unwind-arch.h
> index fcf889b3c7..62f643b221 100644
> --- a/sysdeps/arm/unwind-arch.h
> +++ b/sysdeps/arm/unwind-arch.h
> @@ -32,4 +32,8 @@
>    assert (local.ptr__Unwind_VRS_Get != NULL);                 \
>    PTR_MANGLE (local.ptr__Unwind_VRS_Get);
>  
> +/* This is used by the _Unwind_Resume assembler implementation to
> +   obtain the address to jump to.  */
> +void *__unwind_link_get_resume (void) attribute_hidden;
> +
>  #endif /* _ARCH_UNWIND_LINK_H */
> diff --git a/sysdeps/arm/unwind-resume.c b/sysdeps/arm/unwind-resume.c
> new file mode 100644
> index 0000000000..169d5c30e6
> --- /dev/null
> +++ b/sysdeps/arm/unwind-resume.c
> @@ -0,0 +1,25 @@
> +/* Unwinder function forwarders for libc.  Arm version.
> +   Copyright (C) 2021 Free Software Foundation, Inc.
> +   This file is part of the GNU C Library.
> +
> +   The GNU C Library is free software; you can redistribute it and/or
> +   modify it under the terms of the GNU Lesser General Public License as
> +   published by the Free Software Foundation; either version 2.1 of the
> +   License, or (at your option) any later version.
> +
> +   The GNU C Library is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +   Lesser General Public License for more details.
> +
> +   You should have received a copy of the GNU Lesser General Public
> +   License along with the GNU C Library; see the file COPYING.LIB.  If
> +   not, see <https://www.gnu.org/licenses/>.  */
> +
> +#include <sysdeps/generic/unwind-resume.c>
> +
> +void *
> +__unwind_link_get_resume (void)
> +{
> +  return UNWIND_LINK_PTR (link (), _Unwind_Resume);
> +}
> diff --git a/sysdeps/generic/unwind-resume.c b/sysdeps/generic/unwind-resume.c
> index 09533d6992..9e63762bf1 100644
> --- a/sysdeps/generic/unwind-resume.c
> +++ b/sysdeps/generic/unwind-resume.c
> @@ -16,68 +16,31 @@
>     License along with the GNU C Library; see the file COPYING.LIB.  If
>     not, see <https://www.gnu.org/licenses/>.  */
>  
> -#include <dlfcn.h>
>  #include <stdio.h>
> -#include <unwind.h>
>  #include <gnu/lib-names.h>
> +#include <unwind-link.h>
>  #include <sysdep.h>
>  #include <unwind-resume.h>
>  
> -
> -void (*__libgcc_s_resume) (struct _Unwind_Exception *exc)
> -  attribute_hidden __attribute__ ((noreturn));
> -
> -static _Unwind_Reason_Code (*libgcc_s_personality) PERSONALITY_PROTO;
> -
> -void attribute_hidden __attribute__ ((cold))
> -__libgcc_s_init (void)
> +static struct unwind_link *
> +link (void)
>  {
> -  void *resume, *personality;
> -  void *handle;
> -
> -  /* See include/dlfcn.h. Use of __libc_dlopen requires RTLD_NOW.  */
> -  handle = __libc_dlopen (LIBGCC_S_SO);
> -
> -  if (handle == NULL
> -      || (resume = __libc_dlsym (handle, "_Unwind_Resume")) == NULL
> -      || (personality = __libc_dlsym (handle, "__gcc_personality_v0")) == NULL)
> -    __libc_fatal (LIBGCC_S_SO
> -                  " must be installed for unwinding to work\n");
> -
> -#ifdef PTR_MANGLE
> -  PTR_MANGLE (resume);
> -#endif
> -  __libgcc_s_resume = resume;
> -#ifdef PTR_MANGLE
> -  PTR_MANGLE (personality);
> -#endif
> -  libgcc_s_personality = personality;
> +  struct unwind_link *unwind_link = __libc_unwind_link_get ();
> +  if (unwind_link == NULL)
> +    __libc_fatal (LIBGCC_S_SO " must be installed for unwinding to work\n");
> +  return unwind_link;
>  }
>  
>  #if !HAVE_ARCH_UNWIND_RESUME
>  void
>  _Unwind_Resume (struct _Unwind_Exception *exc)
>  {
> -  if (__glibc_unlikely (__libgcc_s_resume == NULL))
> -    __libgcc_s_init ();
> -
> -  __typeof (__libgcc_s_resume) resume = __libgcc_s_resume;
> -#ifdef PTR_DEMANGLE
> -  PTR_DEMANGLE (resume);
> -#endif
> -  (*resume) (exc);
> +  UNWIND_LINK_PTR (link (), _Unwind_Resume) (exc);
>  }
>  #endif
>  
>  _Unwind_Reason_Code
>  __gcc_personality_v0 PERSONALITY_PROTO
>  {
> -  if (__glibc_unlikely (libgcc_s_personality == NULL))
> -    __libgcc_s_init ();
> -
> -  __typeof (libgcc_s_personality) personality = libgcc_s_personality;
> -#ifdef PTR_DEMANGLE
> -  PTR_DEMANGLE (personality);
> -#endif
> -  return (*personality) PERSONALITY_ARGS;
> +  return UNWIND_LINK_PTR (link (), personality) PERSONALITY_ARGS;
>  }
> 


-- 
Cheers,
Carlos.


^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 10/10] nptl: Use <unwind-link.h> for accessing the libgcc_s unwinder
  2021-02-17 16:03 ` [PATCH 10/10] nptl: Use <unwind-link.h> for accessing the libgcc_s unwinder Florian Weimer
@ 2021-03-01 13:55   ` Carlos O'Donell
  0 siblings, 0 replies; 22+ messages in thread
From: Carlos O'Donell @ 2021-03-01 13:55 UTC (permalink / raw)
  To: Florian Weimer, libc-alpha

On 2/17/21 11:03 AM, Florian Weimer via Libc-alpha wrote:

LGTM. Uses __libc_unwind_link_get@@GLIBC_PRIVATE as the new
interface to access the unwinder. This creates an upgrade
hazard for long running processes that don't link against
libpthread but load libpthread later. There isn't anything
we can do about that except accelerate your work to fold
libpthread into libc.

Reviewed-by: Carlos O'Donell <carlos@redhat.com>

> ---
>  nptl/nptlfreeres.c                            |   1 -
>  nptl/pthreadP.h                               |   6 +-
>  nptl/pthread_cancel.c                         |   3 +-
>  sysdeps/arm/nptl/unwind-forcedunwind.c        |  25 ++++
>  sysdeps/arm/pt-arm-unwind-resume.S            |  30 +----
>  sysdeps/nptl/unwind-forcedunwind.c            | 115 +++---------------
>  .../sysv/linux/ia64/unwind-forcedunwind.c     |  16 +--
>  7 files changed, 50 insertions(+), 146 deletions(-)
>  create mode 100644 sysdeps/arm/nptl/unwind-forcedunwind.c
> 
> diff --git a/nptl/nptlfreeres.c b/nptl/nptlfreeres.c
> index d295bcb3c3..4833f04714 100644
> --- a/nptl/nptlfreeres.c
> +++ b/nptl/nptlfreeres.c
> @@ -27,5 +27,4 @@ __libpthread_freeres (void)
>  {
>    call_function_static_weak (__default_pthread_attr_freeres);
>    call_function_static_weak (__nptl_stacks_freeres);
> -  call_function_static_weak (__nptl_unwind_freeres);

OK. Remove one because we don't need to free this resource anymore.

>  }
> diff --git a/nptl/pthreadP.h b/nptl/pthreadP.h
> index d078128230..d2fd0826fe 100644
> --- a/nptl/pthreadP.h
> +++ b/nptl/pthreadP.h
> @@ -287,9 +287,11 @@ hidden_proto (__pthread_unwind_next)
>  hidden_proto (__pthread_register_cancel)
>  hidden_proto (__pthread_unregister_cancel)
>  # ifdef SHARED
> -extern void attribute_hidden pthread_cancel_init (void);
> +/* The difference from __libc_unwind_link_get is that here, errors
> +   terminate the process.  */
> +struct unwind_link ;
> +struct unwind_link *__pthread_unwind_link_get (void) attribute_hidden;
>  # endif
> -extern void __nptl_unwind_freeres (void) attribute_hidden;
>  #endif
>  
>  
> diff --git a/nptl/pthread_cancel.c b/nptl/pthread_cancel.c
> index f88fa24e19..a011d72fa1 100644
> --- a/nptl/pthread_cancel.c
> +++ b/nptl/pthread_cancel.c
> @@ -35,7 +35,8 @@ __pthread_cancel (pthread_t th)
>      return ESRCH;
>  
>  #ifdef SHARED
> -  pthread_cancel_init ();
> +  /* Trigger an error if libgcc_s cannot be loaded.  */
> +  __pthread_unwind_link_get ();
>  #endif
>    int result = 0;
>    int oldval;
> diff --git a/sysdeps/arm/nptl/unwind-forcedunwind.c b/sysdeps/arm/nptl/unwind-forcedunwind.c
> new file mode 100644
> index 0000000000..61db34c0b5
> --- /dev/null
> +++ b/sysdeps/arm/nptl/unwind-forcedunwind.c
> @@ -0,0 +1,25 @@
> +/* Unwinder function forwarders for libpthread.  Arm version.
> +   Copyright (C) 2021 Free Software Foundation, Inc.
> +   This file is part of the GNU C Library.
> +
> +   The GNU C Library is free software; you can redistribute it and/or
> +   modify it under the terms of the GNU Lesser General Public License as
> +   published by the Free Software Foundation; either version 2.1 of the
> +   License, or (at your option) any later version.
> +
> +   The GNU C Library is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +   Lesser General Public License for more details.
> +
> +   You should have received a copy of the GNU Lesser General Public
> +   License along with the GNU C Library; see the file COPYING.LIB.  If
> +   not, see <https://www.gnu.org/licenses/>.  */
> +
> +#include <sysdeps/nptl/unwind-forcedunwind.c>
> +
> +void *
> +__unwind_link_get_resume (void)
> +{
> +  return UNWIND_LINK_PTR (__pthread_unwind_link_get (), _Unwind_Resume);
> +}

OK.

> diff --git a/sysdeps/arm/pt-arm-unwind-resume.S b/sysdeps/arm/pt-arm-unwind-resume.S
> index d579848696..c056eb38d0 100644
> --- a/sysdeps/arm/pt-arm-unwind-resume.S
> +++ b/sysdeps/arm/pt-arm-unwind-resume.S
> @@ -16,31 +16,5 @@
>     License along with the GNU C Library.  If not, see
>     <https://www.gnu.org/licenses/>.  */
>  
> -#include <sysdep.h>
> -
> -/* This is just implementing exactly what the C version does.
> -   We do it in assembly just to ensure that we get an unmolested tail
> -   call to the libgcc function, which is necessary for the ARM unwinder.  */
> -
> -ENTRY (_Unwind_Resume)
> -	LDR_HIDDEN (ip, ip, __libgcc_s_resume, 0)
> -	cmp	ip, #0
> -	beq	1f
> -0:	PTR_DEMANGLE (ip, ip, r2, r3)
> -	bx	ip
> -
> -	/* We need to save and restore LR (for our own return address)
> -	   and R0 (for the argument to _Unwind_Resume) around the call.  */
> -1:	push	{r0, lr}
> -	cfi_adjust_cfa_offset (8)
> -	cfi_rel_offset (r0, 0)
> -	cfi_rel_offset (lr, 4)
> -	bl	pthread_cancel_init
> -	pop	{r0, lr}
> -	cfi_adjust_cfa_offset (-8)
> -	cfi_restore (r0)
> -	cfi_restore (lr)
> -
> -	LDR_HIDDEN (ip, ip, __libgcc_s_resume, 0)
> -	b	0b
> -END (_Unwind_Resume)
> +/* The implementation in libpthread is identical to the one in libc.  */
> +#include <sysdeps/arm/arm-unwind-resume.S>

OK.

> diff --git a/sysdeps/nptl/unwind-forcedunwind.c b/sysdeps/nptl/unwind-forcedunwind.c
> index b70aae06ae..c0234670cf 100644
> --- a/sysdeps/nptl/unwind-forcedunwind.c
> +++ b/sysdeps/nptl/unwind-forcedunwind.c
> @@ -16,134 +16,49 @@
>     License along with the GNU C Library; see the file COPYING.LIB.  If
>     not, see <https://www.gnu.org/licenses/>.  */
>  
> -#include <dlfcn.h>
>  #include <stdio.h>
> -#include <unwind.h>
> +#include <unwind-link.h>
>  #include <pthreadP.h>
>  #include <sysdep.h>
>  #include <gnu/lib-names.h>
>  #include <unwind-resume.h>
>  
> -static void *libgcc_s_handle;
> -void (*__libgcc_s_resume) (struct _Unwind_Exception *exc)
> -  attribute_hidden __attribute__ ((noreturn));
> -static _Unwind_Reason_Code (*libgcc_s_personality) PERSONALITY_PROTO;
> -static _Unwind_Reason_Code (*libgcc_s_forcedunwind)
> -  (struct _Unwind_Exception *, _Unwind_Stop_Fn, void *);
> -static _Unwind_Word (*libgcc_s_getcfa) (struct _Unwind_Context *);
> -
> -void
> -__attribute_noinline__
> -pthread_cancel_init (void)
> +struct unwind_link *
> +__pthread_unwind_link_get (void)
>  {
> -  void *resume;
> -  void *personality;
> -  void *forcedunwind;
> -  void *getcfa;
> -  void *handle;
> -
> -  if (__glibc_likely (libgcc_s_handle != NULL))
> -    {
> -      /* Force gcc to reload all values.  */
> -      asm volatile ("" ::: "memory");
> -      return;
> -    }
> -
> -  /* See include/dlfcn.h. Use of __libc_dlopen requires RTLD_NOW.  */
> -  handle = __libc_dlopen (LIBGCC_S_SO);
> -
> -  if (handle == NULL
> -      || (resume = __libc_dlsym (handle, "_Unwind_Resume")) == NULL
> -      || (personality = __libc_dlsym (handle, "__gcc_personality_v0")) == NULL
> -      || (forcedunwind = __libc_dlsym (handle, "_Unwind_ForcedUnwind"))
> -	 == NULL
> -      || (getcfa = __libc_dlsym (handle, "_Unwind_GetCFA")) == NULL
> -#ifdef ARCH_CANCEL_INIT
> -      || ARCH_CANCEL_INIT (handle)
> -#endif
> -      )
> -    __libc_fatal (LIBGCC_S_SO " must be installed for pthread_cancel to work\n");
> -
> -  PTR_MANGLE (resume);
> -  __libgcc_s_resume = resume;
> -  PTR_MANGLE (personality);
> -  libgcc_s_personality = personality;
> -  PTR_MANGLE (forcedunwind);
> -  libgcc_s_forcedunwind = forcedunwind;
> -  PTR_MANGLE (getcfa);
> -  libgcc_s_getcfa = getcfa;
> -  /* Make sure libgcc_s_handle is written last.  Otherwise,
> -     pthread_cancel_init might return early even when the pointer the
> -     caller is interested in is not initialized yet.  */
> -  atomic_write_barrier ();
> -  libgcc_s_handle = handle;
> -}
> -
> -/* Register for cleanup in libpthread.so.  */
> -void
> -__nptl_unwind_freeres (void)
> -{
> -  void *handle = libgcc_s_handle;
> -  if (handle != NULL)
> -    {
> -      libgcc_s_handle = NULL;
> -      __libc_dlclose (handle);
> -    }
> +  struct unwind_link *unwind_link = __libc_unwind_link_get ();
> +  if (unwind_link == NULL)
> +    __libc_fatal (LIBGCC_S_SO
> +		  " must be installed for pthread_cancel to work\n");
> +  return unwind_link;
>  }
>  
>  #if !HAVE_ARCH_UNWIND_RESUME
>  void
>  _Unwind_Resume (struct _Unwind_Exception *exc)
>  {
> -  if (__glibc_unlikely (libgcc_s_handle == NULL))
> -    pthread_cancel_init ();
> -  else
> -    atomic_read_barrier ();
> -
> -  void (*resume) (struct _Unwind_Exception *exc) = __libgcc_s_resume;
> -  PTR_DEMANGLE (resume);
> -  resume (exc);
> +  UNWIND_LINK_PTR (__pthread_unwind_link_get (), _Unwind_Resume) (exc);
>  }
>  #endif
>  
>  _Unwind_Reason_Code
>  __gcc_personality_v0 PERSONALITY_PROTO
>  {
> -  if (__glibc_unlikely (libgcc_s_handle == NULL))
> -    pthread_cancel_init ();
> -  else
> -    atomic_read_barrier ();
> -
> -  __typeof (libgcc_s_personality) personality = libgcc_s_personality;
> -  PTR_DEMANGLE (personality);
> -  return (*personality) PERSONALITY_ARGS;
> +  return UNWIND_LINK_PTR (__pthread_unwind_link_get (), personality)
> +    PERSONALITY_ARGS;
>  }
>  
>  _Unwind_Reason_Code
>  _Unwind_ForcedUnwind (struct _Unwind_Exception *exc, _Unwind_Stop_Fn stop,
>  		      void *stop_argument)
>  {
> -  if (__glibc_unlikely (libgcc_s_handle == NULL))
> -    pthread_cancel_init ();
> -  else
> -    atomic_read_barrier ();
> -
> -  _Unwind_Reason_Code (*forcedunwind)
> -    (struct _Unwind_Exception *, _Unwind_Stop_Fn, void *)
> -    = libgcc_s_forcedunwind;
> -  PTR_DEMANGLE (forcedunwind);
> -  return forcedunwind (exc, stop, stop_argument);
> +  return UNWIND_LINK_PTR (__pthread_unwind_link_get (), _Unwind_ForcedUnwind)
> +    (exc, stop, stop_argument);
>  }
>  
>  _Unwind_Word
>  _Unwind_GetCFA (struct _Unwind_Context *context)
>  {
> -  if (__glibc_unlikely (libgcc_s_handle == NULL))
> -    pthread_cancel_init ();
> -  else
> -    atomic_read_barrier ();
> -
> -  _Unwind_Word (*getcfa) (struct _Unwind_Context *) = libgcc_s_getcfa;
> -  PTR_DEMANGLE (getcfa);
> -  return getcfa (context);
> +  return UNWIND_LINK_PTR (__pthread_unwind_link_get (), _Unwind_GetCFA)
> +    (context);
>  }

OK. All just wrappers.

> diff --git a/sysdeps/unix/sysv/linux/ia64/unwind-forcedunwind.c b/sysdeps/unix/sysv/linux/ia64/unwind-forcedunwind.c
> index e797ea22aa..eaed6cf2ef 100644
> --- a/sysdeps/unix/sysv/linux/ia64/unwind-forcedunwind.c
> +++ b/sysdeps/unix/sysv/linux/ia64/unwind-forcedunwind.c
> @@ -16,23 +16,11 @@
>     License along with the GNU C Library; if not, see
>     <https://www.gnu.org/licenses/>.  */
>  
> -#include <dlfcn.h>
> -#include <stdio.h>
> -#include <unwind.h>
> -#include <pthreadP.h>
> -
> -static _Unwind_Word (*libgcc_s_getbsp) (struct _Unwind_Context *);
> -
> -#define ARCH_CANCEL_INIT(handle) \
> -  ((libgcc_s_getbsp = __libc_dlsym (handle, "_Unwind_GetBSP")) == NULL)
> -
>  #include <sysdeps/nptl/unwind-forcedunwind.c>
>  
>  _Unwind_Word
>  _Unwind_GetBSP (struct _Unwind_Context *context)
>  {
> -  if (__builtin_expect (libgcc_s_getbsp == NULL, 0))
> -    pthread_cancel_init ();
> -
> -  return libgcc_s_getbsp (context);
> +  return UNWIND_LINK_PTR (__pthread_unwind_link_get (), _Unwind_GetBSP)
> +    (context);
>  }

OK. Likewise a wrapper.

> 


-- 
Cheers,
Carlos.


^ permalink raw reply	[flat|nested] 22+ messages in thread

end of thread, other threads:[~2021-03-01 13:55 UTC | newest]

Thread overview: 22+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-02-17 16:02 [PATCH 00/10] Unwinder interface consolidation Florian Weimer
2021-02-17 16:02 ` [PATCH 01/10] Implement <unwind-link.h> for dynamically loading the libgcc_s unwinder Florian Weimer
2021-03-01 13:54   ` Carlos O'Donell
2021-02-17 16:02 ` [PATCH 02/10] backtrace: Implement on top of <unwind-link.h> Florian Weimer
2021-03-01 13:54   ` Carlos O'Donell
2021-02-17 16:02 ` [PATCH 03/10] arm: Implement backtrace " Florian Weimer
2021-03-01 13:54   ` Carlos O'Donell
2021-02-17 16:03 ` [PATCH 04/10] i386: " Florian Weimer
2021-03-01 13:54   ` Carlos O'Donell
2021-02-17 16:03 ` [PATCH 05/10] m68k: " Florian Weimer
2021-03-01 13:54   ` Carlos O'Donell
2021-02-17 16:03 ` [PATCH 06/10] sparc: Implement backtrace on top <unwind-link.h> Florian Weimer
2021-03-01 13:54   ` Carlos O'Donell
2021-02-17 16:03 ` [PATCH 07/10] __frame_state_for: Use <unwind-link.h> for unwinder access Florian Weimer
2021-03-01 13:54   ` Carlos O'Donell
2021-02-17 16:03 ` [PATCH 08/10] Move sysdeps/gnu/unwind-resume.c to sysdeps/generic/unwind-resume.c Florian Weimer
2021-03-01 13:55   ` Carlos O'Donell
2021-02-17 16:03 ` [PATCH 09/10] Implement _Unwind_Resume in libc on top of <unwind-link.h> Florian Weimer
2021-03-01 13:55   ` Carlos O'Donell
2021-02-17 16:03 ` [PATCH 10/10] nptl: Use <unwind-link.h> for accessing the libgcc_s unwinder Florian Weimer
2021-03-01 13:55   ` Carlos O'Donell
2021-03-01 13:54 ` [PATCH 00/10] Unwinder interface consolidation Carlos O'Donell

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).