<https://www.gnu.org/licenses/>. */
#include <dl-load.h>
+#include <setvmaname.h>
/* Map a segment and align it properly. */
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);
+ }
}
}
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) + \
#ifndef __SETVMANAME_H
#define __SETVMANAME_H
+#include <stdbool.h>
+
+/* 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)
{
#include <sysdep.h>
#include <elf/dl-tunables.h>
+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:
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;
}
#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 <stdbool.h>
+
+bool __is_decorate_maps_enabled (void) attribute_hidden;
+
void __set_vma_name (void *start, size_t len, const char *name)
attribute_hidden;
#else