* [PATCH 10/11] Implement _Unwind_Resume in libc on top of <unwind-link.h>
2020-02-13 17:08 [PATCH 00/11] Unify dynamic loading of the libgcc_s unwinder Florian Weimer
@ 2020-02-13 17:08 ` Florian Weimer
2020-02-13 17:08 ` [PATCH 01/11] Implement <unwind-link.h> for dynamically loading the libgcc_s unwinder Florian Weimer
` (9 subsequent siblings)
10 siblings, 0 replies; 13+ messages in thread
From: Florian Weimer @ 2020-02-13 17:08 UTC (permalink / raw)
To: libc-alpha
Temporarily move the arm _Unwind_Resume implementation to the file
used by libpthread. It will be ported next.
---
sysdeps/arm/arch-unwind-link.h | 4 +++
sysdeps/arm/arm-unwind-resume.S | 26 +++++++-------
sysdeps/arm/pt-arm-unwind-resume.S | 48 ++++++++++++++++++++++++--
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/arch-unwind-link.h b/sysdeps/arm/arch-unwind-link.h
index b16a94e02a..abb3ba28d6 100644
--- a/sysdeps/arm/arch-unwind-link.h
+++ b/sysdeps/arm/arch-unwind-link.h
@@ -31,4 +31,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/arm-unwind-resume.S b/sysdeps/arm/arm-unwind-resume.S
index 60df9aac46..48059475e4 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..86ff5cbeea 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-2020 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-resume.c b/sysdeps/arm/unwind-resume.c
new file mode 100644
index 0000000000..ea0bf8998a
--- /dev/null
+++ b/sysdeps/arm/unwind-resume.c
@@ -0,0 +1,25 @@
+/* Unwinder function forwarders for libc. Arm version.
+ Copyright (C) 2020 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 42593c3f61..539b2b3574 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.24.1
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH 05/11] m68k: Implement backtrace on top of <unwind-link.h>
2020-02-13 17:08 [PATCH 00/11] Unify dynamic loading of the libgcc_s unwinder Florian Weimer
` (6 preceding siblings ...)
2020-02-13 17:08 ` [PATCH 03/11] arm: Implement backtrace on top of <unwind-link.h> Florian Weimer
@ 2020-02-13 17:08 ` Florian Weimer
2020-02-13 17:08 ` [PATCH 09/11] Move sysdeps/gnu/unwind-resume.c to sysdeps/generic/unwind-resume.c Florian Weimer
` (2 subsequent siblings)
10 siblings, 0 replies; 13+ messages in thread
From: Florian Weimer @ 2020-02-13 17:08 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 6020acae2f..c586a14b0b 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.24.1
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH 02/11] backtrace: Implement on top of <unwind-link.h>
2020-02-13 17:08 [PATCH 00/11] Unify dynamic loading of the libgcc_s unwinder Florian Weimer
` (3 preceding siblings ...)
2020-02-13 17:08 ` [PATCH 04/11] i386: Implement backtrace on top of <unwind-link.h> Florian Weimer
@ 2020-02-13 17:08 ` Florian Weimer
2020-02-13 17:08 ` [PATCH 06/11] sparc: Implement backtrace on top <unwind-link.h> Florian Weimer
` (5 subsequent siblings)
10 siblings, 0 replies; 13+ messages in thread
From: Florian Weimer @ 2020-02-13 17:08 UTC (permalink / raw)
To: libc-alpha
This reimplements the generic version of backtrace.
---
debug/backtrace.c | 86 ++++++++++-------------------------------------
1 file changed, 18 insertions(+), 68 deletions(-)
diff --git a/debug/backtrace.c b/debug/backtrace.c
index cc4b9a5c90..921c9053c8 100644
--- a/debug/backtrace.c
+++ b/debug/backtrace.c
@@ -17,57 +17,19 @@
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>
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)
{
@@ -77,10 +39,12 @@ 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);
/* 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)
@@ -95,20 +59,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. */
@@ -118,17 +82,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.24.1
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH 06/11] sparc: Implement backtrace on top <unwind-link.h>
2020-02-13 17:08 [PATCH 00/11] Unify dynamic loading of the libgcc_s unwinder Florian Weimer
` (4 preceding siblings ...)
2020-02-13 17:08 ` [PATCH 02/11] backtrace: Implement " Florian Weimer
@ 2020-02-13 17:08 ` Florian Weimer
2020-02-13 17:08 ` [PATCH 03/11] arm: Implement backtrace on top of <unwind-link.h> Florian Weimer
` (4 subsequent siblings)
10 siblings, 0 replies; 13+ messages in thread
From: Florian Weimer @ 2020-02-13 17:08 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 297da33904..8cedf7fb3a 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.24.1
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH 00/11] Unify dynamic loading of the libgcc_s unwinder
@ 2020-02-13 17:08 Florian Weimer
2020-02-13 17:08 ` [PATCH 10/11] Implement _Unwind_Resume in libc on top of <unwind-link.h> Florian Weimer
` (10 more replies)
0 siblings, 11 replies; 13+ messages in thread
From: Florian Weimer @ 2020-02-13 17:08 UTC (permalink / raw)
To: libc-alpha
This series unifies the way glibc loads the libgcc_s unwinder via
internal dlopen. There are presently four uses:
* The backtrace function.
* Legacy support for unwinder frame registration, which needs
__frame_state_for.
* GCC unwind personality support (__gcc_personality_v0 _Unwind_Resume)
for C sources with -fexceptions. This is needed in libc and
libpthread.
* The libpthread unwinder, which also needs the canonical frame address
to properly de-interleave longjump frames.
Only the backtrace function could be ported separately in a
per-architecture fashion. The last two commits in the series correspond
to the libc part of the personality support, and the libpthread
personality support and the unwinder there.
The S/390 version preserves the backchain fallback for now.
Tested on aarch64-linux-gnu, arm-linux-gnueabi, s390-linux-gnu,
s390x-linux-gnu, i686-linux-gnu, powerpc-linux-gnu, powerpc64-linux-gnu,
powerpc64le-linux-gnu, x86_64-linux-gnu. Built successfully with
build-many-glibcs.py.
Thanks,
Florian
Florian Weimer (11):
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>
s390: Implement backtrace on top of <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 | 149 ++++++++++++++++++
nptl/nptlfreeres.c | 1 -
nptl/pthreadP.h | 6 +-
nptl/pthread_cancel.c | 3 +-
sysdeps/alpha/arch-unwind-link.h | 27 ++++
sysdeps/arm/arch-unwind-link.h | 38 +++++
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-resume.c | 25 +++
sysdeps/generic/arch-unwind-link.h | 32 ++++
sysdeps/generic/framestate.c | 21 +--
sysdeps/generic/unwind-link.h | 99 ++++++++++++
sysdeps/generic/unwind-resume.c | 46 ++++++
sysdeps/gnu/unwind-resume.c | 83 ----------
sysdeps/i386/arch-unwind-link.h | 38 +++++
sysdeps/i386/backtrace.c | 82 +++-------
sysdeps/ia64/arch-unwind-link.h | 31 ++++
sysdeps/m68k/arch-unwind-link.h | 34 ++++
sysdeps/m68k/backtrace.c | 82 +++-------
sysdeps/m68k/m680x0/arch-unwind-link.h | 26 +++
sysdeps/mach/hurd/fork.c | 3 +
sysdeps/mips/arch-unwind-link.h | 27 ++++
sysdeps/nptl/fork.c | 3 +
sysdeps/nptl/unwind-forcedunwind.c | 115 ++------------
sysdeps/powerpc/powerpc32/arch-unwind-link.h | 27 ++++
sysdeps/s390/arch-unwind-link.h | 27 ++++
sysdeps/s390/s390-32/backtrace.c | 45 ++----
sysdeps/s390/s390-64/backtrace.c | 46 ++----
sysdeps/sh/arch-unwind-link.h | 27 ++++
sysdeps/sparc/arch-unwind-link.h | 27 ++++
sysdeps/sparc/backtrace.c | 66 ++------
.../sysv/linux/ia64/unwind-forcedunwind.c | 16 +-
38 files changed, 899 insertions(+), 597 deletions(-)
create mode 100644 misc/unwind-link.c
create mode 100644 sysdeps/alpha/arch-unwind-link.h
create mode 100644 sysdeps/arm/arch-unwind-link.h
create mode 100644 sysdeps/arm/nptl/unwind-forcedunwind.c
create mode 100644 sysdeps/arm/unwind-resume.c
create mode 100644 sysdeps/generic/arch-unwind-link.h
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/arch-unwind-link.h
create mode 100644 sysdeps/ia64/arch-unwind-link.h
create mode 100644 sysdeps/m68k/arch-unwind-link.h
create mode 100644 sysdeps/m68k/m680x0/arch-unwind-link.h
create mode 100644 sysdeps/mips/arch-unwind-link.h
create mode 100644 sysdeps/powerpc/powerpc32/arch-unwind-link.h
create mode 100644 sysdeps/s390/arch-unwind-link.h
create mode 100644 sysdeps/sh/arch-unwind-link.h
create mode 100644 sysdeps/sparc/arch-unwind-link.h
--
2.24.1
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH 08/11] __frame_state_for: Use <unwind-link.h> for unwinder access
2020-02-13 17:08 [PATCH 00/11] Unify dynamic loading of the libgcc_s unwinder Florian Weimer
` (9 preceding siblings ...)
2020-02-13 17:08 ` [PATCH 07/11] s390: Implement backtrace on top of <unwind-link.h> Florian Weimer
@ 2020-02-13 17:08 ` Florian Weimer
10 siblings, 0 replies; 13+ messages in thread
From: Florian Weimer @ 2020-02-13 17:08 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 e342ce8e54..83cfcd20fd 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.24.1
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH 07/11] s390: Implement backtrace on top of <unwind-link.h>
2020-02-13 17:08 [PATCH 00/11] Unify dynamic loading of the libgcc_s unwinder Florian Weimer
` (8 preceding siblings ...)
2020-02-13 17:08 ` [PATCH 09/11] Move sysdeps/gnu/unwind-resume.c to sysdeps/generic/unwind-resume.c Florian Weimer
@ 2020-02-13 17:08 ` Florian Weimer
2020-02-14 11:55 ` Stefan Liebler
2020-02-13 17:08 ` [PATCH 08/11] __frame_state_for: Use <unwind-link.h> for unwinder access Florian Weimer
10 siblings, 1 reply; 13+ messages in thread
From: Florian Weimer @ 2020-02-13 17:08 UTC (permalink / raw)
To: libc-alpha
---
sysdeps/s390/s390-32/backtrace.c | 45 ++++++++++---------------------
sysdeps/s390/s390-64/backtrace.c | 46 ++++++++++----------------------
2 files changed, 28 insertions(+), 63 deletions(-)
diff --git a/sysdeps/s390/s390-32/backtrace.c b/sysdeps/s390/s390-32/backtrace.c
index 497e4f8875..21da6761f2 100644
--- a/sysdeps/s390/s390-32/backtrace.c
+++ b/sysdeps/s390/s390-32/backtrace.c
@@ -17,12 +17,10 @@
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 <stddef.h>
#include <stdlib.h>
-#include <unwind.h>
+#include <unwind-link.h>
/* This is a global variable set at program start time. It marks the
highest used stack address. */
@@ -57,27 +55,11 @@ struct layout
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_Ptr (*unwind_getip) (struct _Unwind_Context *);
-
-static void
-init (void)
-{
- void *handle = __libc_dlopen ("libgcc_s.so.1");
-
- if (handle == NULL)
- return;
-
- unwind_backtrace = __libc_dlsym (handle, "_Unwind_Backtrace");
- unwind_getip = __libc_dlsym (handle, "_Unwind_GetIP");
- if (unwind_getip == NULL)
- unwind_backtrace = NULL;
-}
-
static int
__backchain_backtrace (void **array, int size)
{
@@ -103,9 +85,6 @@ __backchain_backtrace (void **array, int size)
return cnt;
}
-#else
-# define unwind_backtrace _Unwind_Backtrace
-# define unwind_getip _Unwind_GetIP
#endif
static _Unwind_Reason_Code
@@ -116,7 +95,8 @@ 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;
return _URC_NO_REASON;
@@ -125,21 +105,24 @@ backtrace_helper (struct _Unwind_Context *ctx, void *a)
int
__backtrace (void **array, int size)
{
- struct trace_arg arg = { .array = array, .size = size, .cnt = -1 };
+ struct trace_arg arg =
+ {
+ .array = array,
+ .unwind_link = __libc_unwind_link_get (),
+ .size = size,
+ .cnt = -1
+ };
if (size <= 0)
return 0;
#ifdef SHARED
- __libc_once_define (static, once);
-
- __libc_once (once, init);
-
- if (unwind_backtrace == NULL)
+ if (arg.unwind_link == NULL)
return __backchain_backtrace (array, size);
#endif
- unwind_backtrace (backtrace_helper, &arg);
+ UNWIND_LINK_PTR (arg.unwind_link, _Unwind_Backtrace)
+ (backtrace_helper, &arg);
return arg.cnt != -1 ? arg.cnt : 0;
}
diff --git a/sysdeps/s390/s390-64/backtrace.c b/sysdeps/s390/s390-64/backtrace.c
index 5d14e01280..1b8818f219 100644
--- a/sysdeps/s390/s390-64/backtrace.c
+++ b/sysdeps/s390/s390-64/backtrace.c
@@ -17,13 +17,10 @@
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 <stddef.h>
#include <stdlib.h>
-#include <unwind.h>
-
+#include <unwind-link.h>
/* This is a global variable set at program start time. It marks the
highest used stack address. */
@@ -56,27 +53,11 @@ struct layout
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_Ptr (*unwind_getip) (struct _Unwind_Context *);
-
-static void
-init (void)
-{
- void *handle = __libc_dlopen ("libgcc_s.so.1");
-
- if (handle == NULL)
- return;
-
- unwind_backtrace = __libc_dlsym (handle, "_Unwind_Backtrace");
- unwind_getip = __libc_dlsym (handle, "_Unwind_GetIP");
- if (unwind_getip == NULL)
- unwind_backtrace = NULL;
-}
-
static int
__backchain_backtrace (void **array, int size)
{
@@ -102,9 +83,6 @@ __backchain_backtrace (void **array, int size)
return cnt;
}
-#else
-# define unwind_backtrace _Unwind_Backtrace
-# define unwind_getip _Unwind_GetIP
#endif
static _Unwind_Reason_Code
@@ -115,7 +93,8 @@ 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;
return _URC_NO_REASON;
@@ -124,21 +103,24 @@ backtrace_helper (struct _Unwind_Context *ctx, void *a)
int
__backtrace (void **array, int size)
{
- struct trace_arg arg = { .array = array, .size = size, .cnt = -1 };
+ struct trace_arg arg =
+ {
+ .array = array,
+ .unwind_link = __libc_unwind_link_get (),
+ .size = size,
+ .cnt = -1
+ };
if (size <= 0)
return 0;
#ifdef SHARED
- __libc_once_define (static, once);
-
- __libc_once (once, init);
-
- if (unwind_backtrace == NULL)
+ if (arg.unwind_link == NULL)
return __backchain_backtrace (array, size);
#endif
- unwind_backtrace (backtrace_helper, &arg);
+ UNWIND_LINK_PTR (arg.unwind_link, _Unwind_Backtrace)
+ (backtrace_helper, &arg);
return arg.cnt != -1 ? arg.cnt : 0;
}
--
2.24.1
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH 09/11] Move sysdeps/gnu/unwind-resume.c to sysdeps/generic/unwind-resume.c
2020-02-13 17:08 [PATCH 00/11] Unify dynamic loading of the libgcc_s unwinder Florian Weimer
` (7 preceding siblings ...)
2020-02-13 17:08 ` [PATCH 05/11] m68k: " Florian Weimer
@ 2020-02-13 17:08 ` Florian Weimer
2020-02-13 17:08 ` [PATCH 07/11] s390: Implement backtrace on top of <unwind-link.h> Florian Weimer
2020-02-13 17:08 ` [PATCH 08/11] __frame_state_for: Use <unwind-link.h> for unwinder access Florian Weimer
10 siblings, 0 replies; 13+ messages in thread
From: Florian Weimer @ 2020-02-13 17:08 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.24.1
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH 11/11] nptl: Use <unwind-link.h> for accessing the libgcc_s unwinder
2020-02-13 17:08 [PATCH 00/11] Unify dynamic loading of the libgcc_s unwinder Florian Weimer
2020-02-13 17:08 ` [PATCH 10/11] Implement _Unwind_Resume in libc on top of <unwind-link.h> Florian Weimer
2020-02-13 17:08 ` [PATCH 01/11] Implement <unwind-link.h> for dynamically loading the libgcc_s unwinder Florian Weimer
@ 2020-02-13 17:08 ` Florian Weimer
2020-02-13 17:08 ` [PATCH 04/11] i386: Implement backtrace on top of <unwind-link.h> Florian Weimer
` (7 subsequent siblings)
10 siblings, 0 replies; 13+ messages in thread
From: Florian Weimer @ 2020-02-13 17:08 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 dda11e5922..644d196ab4 100644
--- a/nptl/nptlfreeres.c
+++ b/nptl/nptlfreeres.c
@@ -27,5 +27,4 @@ __libpthread_freeres (void)
{
call_function_static_weak (__nptl_stacks_freeres);
call_function_static_weak (__shm_directory_freeres);
- call_function_static_weak (__nptl_unwind_freeres);
}
diff --git a/nptl/pthreadP.h b/nptl/pthreadP.h
index 7e0ab8ef42..2f370ae0ae 100644
--- a/nptl/pthreadP.h
+++ b/nptl/pthreadP.h
@@ -290,9 +290,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 8e7be996e9..42b58b7034 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..ae64e61b85
--- /dev/null
+++ b/sysdeps/arm/nptl/unwind-forcedunwind.c
@@ -0,0 +1,25 @@
+/* Unwinder function forwarders for libpthread. Arm version.
+ Copyright (C) 2020 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 86ff5cbeea..d01e129cf4 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 50a089282b..f57a3d0c18 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 4c953bf63c..17c35aa68a 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.24.1
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH 04/11] i386: Implement backtrace on top of <unwind-link.h>
2020-02-13 17:08 [PATCH 00/11] Unify dynamic loading of the libgcc_s unwinder Florian Weimer
` (2 preceding siblings ...)
2020-02-13 17:08 ` [PATCH 11/11] nptl: Use <unwind-link.h> for accessing " Florian Weimer
@ 2020-02-13 17:08 ` Florian Weimer
2020-02-13 17:08 ` [PATCH 02/11] backtrace: Implement " Florian Weimer
` (6 subsequent siblings)
10 siblings, 0 replies; 13+ messages in thread
From: Florian Weimer @ 2020-02-13 17:08 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 2491a637d9..29027a478d 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.24.1
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH 03/11] arm: Implement backtrace on top of <unwind-link.h>
2020-02-13 17:08 [PATCH 00/11] Unify dynamic loading of the libgcc_s unwinder Florian Weimer
` (5 preceding siblings ...)
2020-02-13 17:08 ` [PATCH 06/11] sparc: Implement backtrace on top <unwind-link.h> Florian Weimer
@ 2020-02-13 17:08 ` Florian Weimer
2020-02-13 17:08 ` [PATCH 05/11] m68k: " Florian Weimer
` (3 subsequent siblings)
10 siblings, 0 replies; 13+ messages in thread
From: Florian Weimer @ 2020-02-13 17:08 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 ffd3f526b2..893ca39272 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.24.1
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH 01/11] Implement <unwind-link.h> for dynamically loading the libgcc_s unwinder
2020-02-13 17:08 [PATCH 00/11] Unify dynamic loading of the libgcc_s unwinder Florian Weimer
2020-02-13 17:08 ` [PATCH 10/11] Implement _Unwind_Resume in libc on top of <unwind-link.h> Florian Weimer
@ 2020-02-13 17:08 ` Florian Weimer
2020-02-13 17:08 ` [PATCH 11/11] nptl: Use <unwind-link.h> for accessing " Florian Weimer
` (8 subsequent siblings)
10 siblings, 0 replies; 13+ messages in thread
From: Florian Weimer @ 2020-02-13 17:08 UTC (permalink / raw)
To: libc-alpha
This will be used to consolidate the libgcc_s access for backtrace
and pthread_cancel.
Unlike the backtrace implementations, it provides some hardening
based on pointer mangling.
---
malloc/set-freeres.c | 5 +
misc/Makefile | 2 +-
misc/Versions | 1 +
misc/unwind-link.c | 149 +++++++++++++++++++
sysdeps/alpha/arch-unwind-link.h | 27 ++++
sysdeps/arm/arch-unwind-link.h | 34 +++++
sysdeps/generic/arch-unwind-link.h | 32 ++++
sysdeps/generic/unwind-link.h | 99 ++++++++++++
sysdeps/i386/arch-unwind-link.h | 38 +++++
sysdeps/ia64/arch-unwind-link.h | 31 ++++
sysdeps/m68k/arch-unwind-link.h | 34 +++++
sysdeps/m68k/m680x0/arch-unwind-link.h | 26 ++++
sysdeps/mach/hurd/fork.c | 3 +
sysdeps/mips/arch-unwind-link.h | 27 ++++
sysdeps/nptl/fork.c | 3 +
sysdeps/powerpc/powerpc32/arch-unwind-link.h | 27 ++++
sysdeps/s390/arch-unwind-link.h | 27 ++++
sysdeps/sh/arch-unwind-link.h | 27 ++++
sysdeps/sparc/arch-unwind-link.h | 27 ++++
19 files changed, 618 insertions(+), 1 deletion(-)
create mode 100644 misc/unwind-link.c
create mode 100644 sysdeps/alpha/arch-unwind-link.h
create mode 100644 sysdeps/arm/arch-unwind-link.h
create mode 100644 sysdeps/generic/arch-unwind-link.h
create mode 100644 sysdeps/generic/unwind-link.h
create mode 100644 sysdeps/i386/arch-unwind-link.h
create mode 100644 sysdeps/ia64/arch-unwind-link.h
create mode 100644 sysdeps/m68k/arch-unwind-link.h
create mode 100644 sysdeps/m68k/m680x0/arch-unwind-link.h
create mode 100644 sysdeps/mips/arch-unwind-link.h
create mode 100644 sysdeps/powerpc/powerpc32/arch-unwind-link.h
create mode 100644 sysdeps/s390/arch-unwind-link.h
create mode 100644 sysdeps/sh/arch-unwind-link.h
create mode 100644 sysdeps/sparc/arch-unwind-link.h
diff --git a/malloc/set-freeres.c b/malloc/set-freeres.c
index aa80eb64b8..a80cd301a1 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 "../libio/libioP.h"
@@ -56,6 +57,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 e0465980c7..aae52412ef 100644
--- a/misc/Makefile
+++ b/misc/Makefile
@@ -72,7 +72,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
+ allocate_once 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 e749582369..a9cfe3b912 100644
--- a/misc/Versions
+++ b/misc/Versions
@@ -169,5 +169,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..49076f8a59
--- /dev/null
+++ b/misc/unwind-link.c
@@ -0,0 +1,149 @@
+/* Dynamic loading of the libgcc unwinder.
+ Copyright (C) 2020 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 (__libc_lock_trylock (lock) == 0)
+ {
+ if (global_libgcc_handle != NULL)
+ {
+ __libc_dlclose (global_libgcc_handle );
+ global_libgcc_handle = NULL;
+ }
+ __libc_lock_unlock (lock);
+ }
+}
+
+#endif /* SHARED */
diff --git a/sysdeps/alpha/arch-unwind-link.h b/sysdeps/alpha/arch-unwind-link.h
new file mode 100644
index 0000000000..998e47c949
--- /dev/null
+++ b/sysdeps/alpha/arch-unwind-link.h
@@ -0,0 +1,27 @@
+/* Dynamic loading of the libgcc unwinder. alpha customization.
+ Copyright (C) 2020 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_EXTRA_FIELDS
+#define UNWIND_LINK_EXTRA_INIT
+
+#endif /* _ARCH_UNWIND_LINK_H */
diff --git a/sysdeps/arm/arch-unwind-link.h b/sysdeps/arm/arch-unwind-link.h
new file mode 100644
index 0000000000..b16a94e02a
--- /dev/null
+++ b/sysdeps/arm/arch-unwind-link.h
@@ -0,0 +1,34 @@
+/* Dynamic loading of the libgcc unwinder. Arm customization.
+ Copyright (C) 2020 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_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/arch-unwind-link.h b/sysdeps/generic/arch-unwind-link.h
new file mode 100644
index 0000000000..f63a3f7a7d
--- /dev/null
+++ b/sysdeps/generic/arch-unwind-link.h
@@ -0,0 +1,32 @@
+/* Dynamic loading of the libgcc unwinder. Generic version of parameters.
+ Copyright (C) 2020 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
+
+/* The _Unwind_GetIP function is supported. */
+#define UNWIND_LINK_GETIP 1
+
+/* The __frame_state_for function is needed and re-exported from glibc. */
+#define UNWIND_LINK_FRAME_STATE_FOR 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..56488e997d
--- /dev/null
+++ b/sysdeps/generic/unwind-link.h
@@ -0,0 +1,99 @@
+/* Dynamic loading of the libgcc unwinder. Generic version.
+ Copyright (C) 2020 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>
+
+#ifdef SHARED
+
+#include <arch-unwind-link.h>
+#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/arch-unwind-link.h b/sysdeps/i386/arch-unwind-link.h
new file mode 100644
index 0000000000..bc9c3a1f97
--- /dev/null
+++ b/sysdeps/i386/arch-unwind-link.h
@@ -0,0 +1,38 @@
+/* Dynamic loading of the libgcc unwinder. i386 customization.
+ Copyright (C) 2020 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_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/arch-unwind-link.h b/sysdeps/ia64/arch-unwind-link.h
new file mode 100644
index 0000000000..570b711dcd
--- /dev/null
+++ b/sysdeps/ia64/arch-unwind-link.h
@@ -0,0 +1,31 @@
+/* Dynamic loading of the libgcc unwinder. ia64 customization.
+ Copyright (C) 2020 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_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/arch-unwind-link.h b/sysdeps/m68k/arch-unwind-link.h
new file mode 100644
index 0000000000..e0105140ed
--- /dev/null
+++ b/sysdeps/m68k/arch-unwind-link.h
@@ -0,0 +1,34 @@
+/* Dynamic loading of the libgcc unwinder. m68k customization.
+ Copyright (C) 2020 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_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/m68k/m680x0/arch-unwind-link.h b/sysdeps/m68k/m680x0/arch-unwind-link.h
new file mode 100644
index 0000000000..1adbf23c79
--- /dev/null
+++ b/sysdeps/m68k/m680x0/arch-unwind-link.h
@@ -0,0 +1,26 @@
+/* Dynamic loading of the libgcc unwinder. Baseline m68k customization.
+ Copyright (C) 2020 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/arch-unwind-link.h>
+
+#undef UNWIND_LINK_FRAME_STATE_FOR
+#define UNWIND_LINK_FRAME_STATE_FOR 1
+
+#endif /* _ARCH_UNWIND_LINK_H */
diff --git a/sysdeps/mach/hurd/fork.c b/sysdeps/mach/hurd/fork.c
index 32783069ec..1d4819ed53 100644
--- a/sysdeps/mach/hurd/fork.c
+++ b/sysdeps/mach/hurd/fork.c
@@ -28,6 +28,7 @@
#include "hurdmalloc.h" /* XXX */
#include <tls.h>
#include <malloc/malloc-internal.h>
+#include <unwind-link.h>
#undef __fork
@@ -662,6 +663,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/mips/arch-unwind-link.h b/sysdeps/mips/arch-unwind-link.h
new file mode 100644
index 0000000000..9835c0f9d6
--- /dev/null
+++ b/sysdeps/mips/arch-unwind-link.h
@@ -0,0 +1,27 @@
+/* Dynamic loading of the libgcc unwinder. MIPS customization.
+ Copyright (C) 2020 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_EXTRA_FIELDS
+#define UNWIND_LINK_EXTRA_INIT
+
+#endif /* _ARCH_UNWIND_LINK_H */
diff --git a/sysdeps/nptl/fork.c b/sysdeps/nptl/fork.c
index f5cf88d68c..19e8381bb1 100644
--- a/sysdeps/nptl/fork.c
+++ b/sysdeps/nptl/fork.c
@@ -32,6 +32,7 @@
#include <arch-fork.h>
#include <futex-internal.h>
#include <malloc/malloc-internal.h>
+#include <unwind-link.h>
static void
fresetlockfiles (void)
@@ -112,6 +113,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/arch-unwind-link.h b/sysdeps/powerpc/powerpc32/arch-unwind-link.h
new file mode 100644
index 0000000000..6a87daaa88
--- /dev/null
+++ b/sysdeps/powerpc/powerpc32/arch-unwind-link.h
@@ -0,0 +1,27 @@
+/* Dynamic loading of the libgcc unwinder. powerpc customization.
+ Copyright (C) 2020 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_EXTRA_FIELDS
+#define UNWIND_LINK_EXTRA_INIT
+
+#endif /* _ARCH_UNWIND_LINK_H */
diff --git a/sysdeps/s390/arch-unwind-link.h b/sysdeps/s390/arch-unwind-link.h
new file mode 100644
index 0000000000..c50b7f2f0d
--- /dev/null
+++ b/sysdeps/s390/arch-unwind-link.h
@@ -0,0 +1,27 @@
+/* Dynamic loading of the libgcc unwinder. S/390 customization.
+ Copyright (C) 2020 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_EXTRA_FIELDS
+#define UNWIND_LINK_EXTRA_INIT
+
+#endif /* _ARCH_UNWIND_LINK_H */
diff --git a/sysdeps/sh/arch-unwind-link.h b/sysdeps/sh/arch-unwind-link.h
new file mode 100644
index 0000000000..519c224093
--- /dev/null
+++ b/sysdeps/sh/arch-unwind-link.h
@@ -0,0 +1,27 @@
+/* Dynamic loading of the libgcc unwinder. SH customization.
+ Copyright (C) 2020 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_EXTRA_FIELDS
+#define UNWIND_LINK_EXTRA_INIT
+
+#endif /* _ARCH_UNWIND_LINK_H */
diff --git a/sysdeps/sparc/arch-unwind-link.h b/sysdeps/sparc/arch-unwind-link.h
new file mode 100644
index 0000000000..4b7e2f160d
--- /dev/null
+++ b/sysdeps/sparc/arch-unwind-link.h
@@ -0,0 +1,27 @@
+/* Dynamic loading of the libgcc unwinder. SPARC customization.
+ Copyright (C) 2020 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_EXTRA_FIELDS
+#define UNWIND_LINK_EXTRA_INIT
+
+#endif /* _ARCH_UNWIND_LINK_H */
--
2.24.1
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH 07/11] s390: Implement backtrace on top of <unwind-link.h>
2020-02-13 17:08 ` [PATCH 07/11] s390: Implement backtrace on top of <unwind-link.h> Florian Weimer
@ 2020-02-14 11:55 ` Stefan Liebler
0 siblings, 0 replies; 13+ messages in thread
From: Stefan Liebler @ 2020-02-14 11:55 UTC (permalink / raw)
To: libc-alpha
Hi Florian,
I've applied your patch series and also successfully run the testsuite
on s390x/s390.
For s390, this is okay.
Just as info for future readers regarding
"The S/390 version preserves the backchain fallback for now.":
Here is the previous discussion:
https://www.sourceware.org/ml/libc-alpha/2020-02/msg00453.html
As soon as I have any news, I will reply there.
If we remove the backchain fallback. I assume the s390 specific
backtrace.c files can be removed. Thus the debug/backtrace.c would be
used. But I have to double check at this time.
If we still need the backchain fallback, I would either update the
implementation in order to also get those "features":
/* Check whether we make any progress. */
/* _Unwind_Backtrace seems to put NULL address above
_start. Fix it up here. */
Or perhaps even better, add an architecture-fallback-hook in the default
implementation.
Bye,
Stefan
On 2/13/20 6:08 PM, Florian Weimer wrote:
> ---
> sysdeps/s390/s390-32/backtrace.c | 45 ++++++++++---------------------
> sysdeps/s390/s390-64/backtrace.c | 46 ++++++++++----------------------
> 2 files changed, 28 insertions(+), 63 deletions(-)
>
> diff --git a/sysdeps/s390/s390-32/backtrace.c b/sysdeps/s390/s390-32/backtrace.c
> index 497e4f8875..21da6761f2 100644
> --- a/sysdeps/s390/s390-32/backtrace.c
> +++ b/sysdeps/s390/s390-32/backtrace.c
> @@ -17,12 +17,10 @@
> 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 <stddef.h>
> #include <stdlib.h>
> -#include <unwind.h>
> +#include <unwind-link.h>
>
> /* This is a global variable set at program start time. It marks the
> highest used stack address. */
> @@ -57,27 +55,11 @@ struct layout
> 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_Ptr (*unwind_getip) (struct _Unwind_Context *);
> -
> -static void
> -init (void)
> -{
> - void *handle = __libc_dlopen ("libgcc_s.so.1");
> -
> - if (handle == NULL)
> - return;
> -
> - unwind_backtrace = __libc_dlsym (handle, "_Unwind_Backtrace");
> - unwind_getip = __libc_dlsym (handle, "_Unwind_GetIP");
> - if (unwind_getip == NULL)
> - unwind_backtrace = NULL;
> -}
> -
> static int
> __backchain_backtrace (void **array, int size)
> {
> @@ -103,9 +85,6 @@ __backchain_backtrace (void **array, int size)
>
> return cnt;
> }
> -#else
> -# define unwind_backtrace _Unwind_Backtrace
> -# define unwind_getip _Unwind_GetIP
> #endif
>
> static _Unwind_Reason_Code
> @@ -116,7 +95,8 @@ 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;
> return _URC_NO_REASON;
> @@ -125,21 +105,24 @@ backtrace_helper (struct _Unwind_Context *ctx, void *a)
> int
> __backtrace (void **array, int size)
> {
> - struct trace_arg arg = { .array = array, .size = size, .cnt = -1 };
> + struct trace_arg arg =
> + {
> + .array = array,
> + .unwind_link = __libc_unwind_link_get (),
> + .size = size,
> + .cnt = -1
> + };
>
> if (size <= 0)
> return 0;
>
> #ifdef SHARED
> - __libc_once_define (static, once);
> -
> - __libc_once (once, init);
> -
> - if (unwind_backtrace == NULL)
> + if (arg.unwind_link == NULL)
> return __backchain_backtrace (array, size);
> #endif
>
> - unwind_backtrace (backtrace_helper, &arg);
> + UNWIND_LINK_PTR (arg.unwind_link, _Unwind_Backtrace)
> + (backtrace_helper, &arg);
>
> return arg.cnt != -1 ? arg.cnt : 0;
> }
> diff --git a/sysdeps/s390/s390-64/backtrace.c b/sysdeps/s390/s390-64/backtrace.c
> index 5d14e01280..1b8818f219 100644
> --- a/sysdeps/s390/s390-64/backtrace.c
> +++ b/sysdeps/s390/s390-64/backtrace.c
> @@ -17,13 +17,10 @@
> 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 <stddef.h>
> #include <stdlib.h>
> -#include <unwind.h>
> -
> +#include <unwind-link.h>
>
> /* This is a global variable set at program start time. It marks the
> highest used stack address. */
> @@ -56,27 +53,11 @@ struct layout
> 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_Ptr (*unwind_getip) (struct _Unwind_Context *);
> -
> -static void
> -init (void)
> -{
> - void *handle = __libc_dlopen ("libgcc_s.so.1");
> -
> - if (handle == NULL)
> - return;
> -
> - unwind_backtrace = __libc_dlsym (handle, "_Unwind_Backtrace");
> - unwind_getip = __libc_dlsym (handle, "_Unwind_GetIP");
> - if (unwind_getip == NULL)
> - unwind_backtrace = NULL;
> -}
> -
> static int
> __backchain_backtrace (void **array, int size)
> {
> @@ -102,9 +83,6 @@ __backchain_backtrace (void **array, int size)
>
> return cnt;
> }
> -#else
> -# define unwind_backtrace _Unwind_Backtrace
> -# define unwind_getip _Unwind_GetIP
> #endif
>
> static _Unwind_Reason_Code
> @@ -115,7 +93,8 @@ 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;
> return _URC_NO_REASON;
> @@ -124,21 +103,24 @@ backtrace_helper (struct _Unwind_Context *ctx, void *a)
> int
> __backtrace (void **array, int size)
> {
> - struct trace_arg arg = { .array = array, .size = size, .cnt = -1 };
> + struct trace_arg arg =
> + {
> + .array = array,
> + .unwind_link = __libc_unwind_link_get (),
> + .size = size,
> + .cnt = -1
> + };
>
> if (size <= 0)
> return 0;
>
> #ifdef SHARED
> - __libc_once_define (static, once);
> -
> - __libc_once (once, init);
> -
> - if (unwind_backtrace == NULL)
> + if (arg.unwind_link == NULL)
> return __backchain_backtrace (array, size);
> #endif
>
> - unwind_backtrace (backtrace_helper, &arg);
> + UNWIND_LINK_PTR (arg.unwind_link, _Unwind_Backtrace)
> + (backtrace_helper, &arg);
>
> return arg.cnt != -1 ? arg.cnt : 0;
> }
>
^ permalink raw reply [flat|nested] 13+ messages in thread
end of thread, other threads:[~2020-02-14 11:55 UTC | newest]
Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-02-13 17:08 [PATCH 00/11] Unify dynamic loading of the libgcc_s unwinder Florian Weimer
2020-02-13 17:08 ` [PATCH 10/11] Implement _Unwind_Resume in libc on top of <unwind-link.h> Florian Weimer
2020-02-13 17:08 ` [PATCH 01/11] Implement <unwind-link.h> for dynamically loading the libgcc_s unwinder Florian Weimer
2020-02-13 17:08 ` [PATCH 11/11] nptl: Use <unwind-link.h> for accessing " Florian Weimer
2020-02-13 17:08 ` [PATCH 04/11] i386: Implement backtrace on top of <unwind-link.h> Florian Weimer
2020-02-13 17:08 ` [PATCH 02/11] backtrace: Implement " Florian Weimer
2020-02-13 17:08 ` [PATCH 06/11] sparc: Implement backtrace on top <unwind-link.h> Florian Weimer
2020-02-13 17:08 ` [PATCH 03/11] arm: Implement backtrace on top of <unwind-link.h> Florian Weimer
2020-02-13 17:08 ` [PATCH 05/11] m68k: " Florian Weimer
2020-02-13 17:08 ` [PATCH 09/11] Move sysdeps/gnu/unwind-resume.c to sysdeps/generic/unwind-resume.c Florian Weimer
2020-02-13 17:08 ` [PATCH 07/11] s390: Implement backtrace on top of <unwind-link.h> Florian Weimer
2020-02-14 11:55 ` Stefan Liebler
2020-02-13 17:08 ` [PATCH 08/11] __frame_state_for: Use <unwind-link.h> for unwinder access Florian Weimer
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).