glibc/glibc-upstream-2.39-248.patch
Arjun Shankar 53f4d259fa Sync with upstream branch release/2.39/master (RHEL-109536)
Upstream commit: fffc2df8a3e2c8cda2991063d23086360268b777

- i386: Provide GLIBC_ABI_GNU_TLS symbol version [BZ #33221]
- i386: Update ___tls_get_addr to preserve vector registers
- Extend struct r_debug to support multiple namespaces (RHEL-101985)
- Fix a potential crash in the dynamic loader when processing specific
  symbol versions (RHEL-109683)
- Signal la_objopen for ld.so with dlmopen (RHEL-109693)
- Switch to main malloc after final ld.so self-relocation (RHEL-109703)
- Prevent ld.so from asserting and crashing during audited library loads
  (RHEL-109702)
- x86-64: Provide GLIBC_ABI_DT_X86_64_PLT symbol version (RHEL-109621)
- x86-64, i386: Provide GLIBC_ABI_GNU2_TLS symbol version (RHEL-109625)
- Ensure fallback initialization of ctype TLS data pointers to fix segfaults in
  programs using dlmopen or auditors (RHEL-72018)
- Handle load segment gaps in _dl_find_object (RHEL-104854)
- AArch64: Improve codegen in SVE log1p
- AArch64: Optimize inverse trig functions
- AArch64: Avoid memset ifunc in cpu-features.c [BZ #33112]

Resolves: RHEL-109536

Resolves: RHEL-72018
Resolves: RHEL-101985
Resolves: RHEL-104854
Resolves: RHEL-109621
Resolves: RHEL-109625
Resolves: RHEL-109683
Resolves: RHEL-109693
Resolves: RHEL-109702
Resolves: RHEL-109703
2025-08-21 10:25:39 +02:00

160 lines
5.1 KiB
Diff

commit 5601ad79b75f03db3e30fc3358e63c1122985f95
Author: Florian Weimer <fweimer@redhat.com>
Date: Fri Jul 4 21:46:05 2025 +0200
elf: Introduce separate _r_debug_array variable
It replaces the ns_debug member of the namespaces. Previously,
the base namespace had an unused ns_debug member.
This change also fixes a concurrency issue: Now _dl_debug_initialize
only updates r_next of the previous namespace's r_debug after the new
r_debug is initialized, so that only the initialized version is
observed. (Client code accessing _r_debug will benefit from load
dependency tracking in CPUs even without explicit barriers.)
Reviewed-by: H.J. Lu <hjl.tools@gmail.com>
(cherry picked from commit 7278d11f3a0cd528188c719bab75575b0aea2c6e)
diff --git a/elf/dl-debug.c b/elf/dl-debug.c
index ef56de7a29565652..5c49fa847e91bd81 100644
--- a/elf/dl-debug.c
+++ b/elf/dl-debug.c
@@ -30,17 +30,37 @@ extern const int verify_link_map_members[(VERIFY_MEMBER (l_addr)
&& VERIFY_MEMBER (l_prev))
? 1 : -1];
+#ifdef SHARED
+/* r_debug structs for secondary namespaces. The first namespace is
+ handled separately because its r_debug structure must overlap with
+ the public _r_debug symbol, so the first array element corresponds
+ to LM_ID_BASE + 1. See elf/dl-debug-symbols.S. */
+struct r_debug_extended _r_debug_array[DL_NNS - 1];
+
+/* Return the r_debug object for the namespace NS. */
+static inline struct r_debug_extended *
+get_rdebug (Lmid_t ns)
+{
+ if (ns == LM_ID_BASE)
+ return &_r_debug_extended;
+ else
+ return &_r_debug_array[ns - 1];
+}
+#else /* !SHARED */
+static inline struct r_debug_extended *
+get_rdebug (Lmid_t ns)
+{
+ return &_r_debug_extended; /* There is just one namespace. */
+}
+#endif /* !SHARED */
+
/* Update the `r_map' member and return the address of `struct r_debug'
of the namespace NS. */
struct r_debug *
_dl_debug_update (Lmid_t ns)
{
- struct r_debug_extended *r;
- if (ns == LM_ID_BASE)
- r = &_r_debug_extended;
- else
- r = &GL(dl_ns)[ns]._ns_debug;
+ struct r_debug_extended *r = get_rdebug (ns);
if (r->base.r_map == NULL)
atomic_store_release (&r->base.r_map,
(void *) GL(dl_ns)[ns]._ns_loaded);
@@ -54,34 +74,7 @@ _dl_debug_update (Lmid_t ns)
struct r_debug *
_dl_debug_initialize (ElfW(Addr) ldbase, Lmid_t ns)
{
- struct r_debug_extended *r, **pp = NULL;
-
- if (ns == LM_ID_BASE)
- {
- r = &_r_debug_extended;
- /* Initialize r_version to 1. */
- if (_r_debug_extended.base.r_version == 0)
- _r_debug_extended.base.r_version = 1;
- }
- else if (DL_NNS > 1)
- {
- r = &GL(dl_ns)[ns]._ns_debug;
- if (r->base.r_brk == 0)
- {
- /* Add the new namespace to the linked list. After a namespace
- is initialized, r_brk becomes non-zero. A namespace becomes
- empty (r_map == NULL) when it is unused. But it is never
- removed from the linked list. */
- struct r_debug_extended *p;
- for (pp = &_r_debug_extended.r_next;
- (p = *pp) != NULL;
- pp = &p->r_next)
- ;
-
- r->base.r_version = 2;
- }
- }
-
+ struct r_debug_extended *r = get_rdebug (ns);
if (r->base.r_brk == 0)
{
/* Tell the debugger where to find the map of loaded objects.
@@ -89,20 +82,36 @@ _dl_debug_initialize (ElfW(Addr) ldbase, Lmid_t ns)
only once. */
r->base.r_ldbase = ldbase ?: _r_debug_extended.base.r_ldbase;
r->base.r_brk = (ElfW(Addr)) &_dl_debug_state;
- r->r_next = NULL;
+
+#ifdef SHARED
+ /* Add the new namespace to the linked list. This assumes that
+ namespaces are allocated in increasing order. After a
+ namespace is initialized, r_brk becomes non-zero. A
+ namespace becomes empty (r_map == NULL) when it is unused.
+ But it is never removed from the linked list. */
+
+ if (ns != LM_ID_BASE)
+ {
+ r->base.r_version = 2;
+ if (ns - 1 == LM_ID_BASE)
+ {
+ atomic_store_release (&_r_debug_extended.r_next, r);
+ /* Now there are multiple namespaces. */
+ atomic_store_release (&_r_debug_extended.base.r_version, 2);
+ }
+ else
+ /* Update r_debug_extended of the previous namespace. */
+ atomic_store_release (&_r_debug_array[ns - 2].r_next, r);
+ }
+ else
+#endif /* SHARED */
+ r->base.r_version = 1;
}
if (r->base.r_map == NULL)
atomic_store_release (&r->base.r_map,
(void *) GL(dl_ns)[ns]._ns_loaded);
- if (pp != NULL)
- {
- atomic_store_release (pp, r);
- /* Bump r_version to 2 for the new namespace. */
- atomic_store_release (&_r_debug_extended.base.r_version, 2);
- }
-
return &r->base;
}
diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h
index 91447a5e77c2466d..8b9ae3783056a29f 100644
--- a/sysdeps/generic/ldsodefs.h
+++ b/sysdeps/generic/ldsodefs.h
@@ -350,8 +350,6 @@ struct rtld_global
size_t n_elements;
void (*free) (void *);
} _ns_unique_sym_table;
- /* Keep track of changes to each namespace' list. */
- struct r_debug_extended _ns_debug;
} _dl_ns[DL_NNS];
/* One higher than index of last used namespace. */
EXTERN size_t _dl_nns;