diff --git a/elf/dl-map-segments.h b/elf/dl-map-segments.h
index 203b6c7b0b..ee68dda550 100644
--- a/elf/dl-map-segments.h
+++ b/elf/dl-map-segments.h
@@ -18,6 +18,7 @@
. */
#include
+#include
/* Map a segment and align it properly. */
@@ -182,12 +183,41 @@ _dl_map_segments (struct link_map *l, int fd,
if (zeroend > zeropage)
{
/* Map the remaining zero pages in from the zero fill FD. */
+ char bssname[ANON_VMA_NAME_MAX_LEN] = " glibc: .bss";
+
caddr_t mapat;
mapat = __mmap ((caddr_t) zeropage, zeroend - zeropage,
c->prot, MAP_ANON|MAP_PRIVATE|MAP_FIXED,
-1, 0);
if (__glibc_unlikely (mapat == MAP_FAILED))
return DL_MAP_SEGMENTS_ERROR_MAP_ZERO_FILL;
+ if (__is_decorate_maps_enabled ())
+ {
+ if (l->l_name != NULL && *l->l_name != '\0')
+ {
+ int i = strlen (bssname), j = 0;
+ int namelen = strlen (l->l_name);
+
+ bssname[i++] = ' ';
+ if (namelen > sizeof (bssname) - i - 1)
+ for (j = namelen - 1; j > 0; j--)
+ if (l->l_name[j - 1] == '/')
+ break;
+
+ for (; l->l_name[j] != '\0' && i < sizeof (bssname) - 1;
+ i++, j++)
+ {
+ char ch = l->l_name[j];
+ /* Replace non-printable characters and
+ \, `, $, [ and ]. */
+ if (ch <= 0x1f || ch >= 0x7f || strchr("\\`$[]", ch))
+ ch = '!';
+ bssname[i] = ch;
+ }
+ bssname[i] = 0;
+ }
+ __set_vma_name ((void*)zeropage, zeroend - zeropage, bssname);
+ }
}
}
diff --git a/nptl/allocatestack.c b/nptl/allocatestack.c
index cffcd3d421..800ca89720 100644
--- a/nptl/allocatestack.c
+++ b/nptl/allocatestack.c
@@ -638,10 +638,6 @@ allocate_stack (const struct pthread_attr *attr, struct pthread **pdp,
return 0;
}
-/* Maximum supported name from initial kernel support, not exported
- by user API. */
-#define ANON_VMA_NAME_MAX_LEN 80
-
#define SET_STACK_NAME(__prefix, __stack, __stacksize, __tid) \
({ \
char __stack_name[sizeof (__prefix) + \
diff --git a/sysdeps/generic/setvmaname.h b/sysdeps/generic/setvmaname.h
index baca984a54..496fcca33b 100644
--- a/sysdeps/generic/setvmaname.h
+++ b/sysdeps/generic/setvmaname.h
@@ -19,6 +19,18 @@
#ifndef __SETVMANAME_H
#define __SETVMANAME_H
+#include
+
+/* Set this to small value to not waste memory on systems, which do
+ * not support VMA name. */
+#define ANON_VMA_NAME_MAX_LEN 16
+
+static inline bool
+__is_decorate_maps_enabled (void)
+{
+ return false;
+}
+
static inline
void __set_vma_name (void *start, size_t len, const char *name)
{
diff --git a/sysdeps/unix/sysv/linux/setvmaname.c b/sysdeps/unix/sysv/linux/setvmaname.c
index 749c587f12..ea93a5ffbe 100644
--- a/sysdeps/unix/sysv/linux/setvmaname.c
+++ b/sysdeps/unix/sysv/linux/setvmaname.c
@@ -22,6 +22,33 @@
#include
#include
+static enum {
+ decorate_unknown = -1,
+ decorate_off,
+ decorate_on
+} decorate_maps = decorate_unknown;
+
+bool
+__is_decorate_maps_enabled (void)
+{
+ switch (atomic_load_relaxed (&decorate_maps))
+ {
+ case decorate_unknown:
+ if (TUNABLE_GET (glibc, mem, decorate_maps, int32_t, NULL) != 0)
+ {
+ atomic_store_relaxed (&decorate_maps, decorate_on);
+ return true;
+ }
+ atomic_store_relaxed (&decorate_maps, decorate_off);
+ return false;
+ case decorate_off:
+ return false;
+ case decorate_on:
+ return true;
+ }
+ __builtin_unreachable ();
+}
+
/* If PR_SET_VMA_ANON_NAME is not supported by the kernel, prctl returns
EINVAL. However, it also returns the same error for invalid argument.
Since it is an internal-only API, it assumes well formatted input:
@@ -31,19 +58,13 @@
void
__set_vma_name (void *start, size_t len, const char *name)
{
- static int prctl_supported = 1;
- if (atomic_load_relaxed (&prctl_supported) == 0)
- return;
-
- /* Set the prctl as not supported to avoid checking the tunable on every
- call. */
- if (TUNABLE_GET (glibc, mem, decorate_maps, int32_t, NULL) != 0)
+ if (__is_decorate_maps_enabled ())
{
int r = INTERNAL_SYSCALL_CALL (prctl, PR_SET_VMA, PR_SET_VMA_ANON_NAME,
- start, len, name);
- if (r == 0 || r != -EINVAL)
- return;
+ start, len, name);
+
+ /* Disable further attempts if not supported by the kernel. */
+ if (r == -EINVAL)
+ atomic_store_relaxed (&decorate_maps, decorate_off);
}
- atomic_store_relaxed (&prctl_supported, 0);
- return;
}
diff --git a/sysdeps/unix/sysv/linux/setvmaname.h b/sysdeps/unix/sysv/linux/setvmaname.h
index 715b096799..48643d0dad 100644
--- a/sysdeps/unix/sysv/linux/setvmaname.h
+++ b/sysdeps/unix/sysv/linux/setvmaname.h
@@ -19,9 +19,17 @@
#ifndef __SETVMANAME_H
#define __SETVMANAME_H
+/* Maximum supported name from initial kernel support, not exported
+ by user API. */
+#define ANON_VMA_NAME_MAX_LEN 80
+
/* Set the NAME to the anonymous memory map START with size of LEN.
It assumes well-formatted input. */
#if IS_IN(libc) || IS_IN(rtld)
+#include
+
+bool __is_decorate_maps_enabled (void) attribute_hidden;
+
void __set_vma_name (void *start, size_t len, const char *name)
attribute_hidden;
#else