about summary refs log tree commit diff
path: root/elf
diff options
context:
space:
mode:
authorAdhemerval Zanella <adhemerval.zanella@linaro.org>2023-11-01 09:56:08 -0300
committerAdhemerval Zanella <adhemerval.zanella@linaro.org>2023-11-07 10:27:20 -0300
commitfee9e40a8da75fad9717668f6dddcc26f3feca2d (patch)
tree318af06cfcad98364192c6b01bb2a0ed6a08b577 /elf
parent6afce56c197ee83520994a2c94a82c2ca2bce9fa (diff)
downloadglibc-fee9e40a8da75fad9717668f6dddcc26f3feca2d.tar.gz
glibc-fee9e40a8da75fad9717668f6dddcc26f3feca2d.tar.xz
glibc-fee9e40a8da75fad9717668f6dddcc26f3feca2d.zip
malloc: Decorate malloc maps
Add anonymous mmap annotations on loader malloc, malloc when it
allocates memory with mmap, and on malloc arena.  The /proc/self/maps
will now print:

   [anon: glibc: malloc arena]
   [anon: glibc: malloc]
   [anon: glibc: loader malloc]

On arena allocation, glibc annotates only the read/write mapping.

Checked on x86_64-linux-gnu and aarch64-linux-gnu.
Reviewed-by: DJ Delorie <dj@redhat.com>
Diffstat (limited to 'elf')
-rw-r--r--elf/Makefile4
-rw-r--r--elf/dl-minimal-malloc.c2
-rw-r--r--elf/tst-decorate-maps.c36
3 files changed, 42 insertions, 0 deletions
diff --git a/elf/Makefile b/elf/Makefile
index 33f88bae96..328dbe82de 100644
--- a/elf/Makefile
+++ b/elf/Makefile
@@ -2983,3 +2983,7 @@ $(objpfx)tst-dlclose-lazy.out: \
   $(objpfx)tst-dlclose-lazy-mod1.so $(objpfx)tst-dlclose-lazy-mod2.so
 
 $(objpfx)tst-decorate-maps: $(shared-thread-library)
+
+tst-decorate-maps-ENV = \
+  GLIBC_TUNABLES=glibc.malloc.arena_max=8:glibc.malloc.mmap_threshold=1024
+tst-decorate-maps-ARGS = 8
diff --git a/elf/dl-minimal-malloc.c b/elf/dl-minimal-malloc.c
index 27549645d0..da36986269 100644
--- a/elf/dl-minimal-malloc.c
+++ b/elf/dl-minimal-malloc.c
@@ -26,6 +26,7 @@
 #include <string.h>
 #include <ldsodefs.h>
 #include <malloc/malloc-internal.h>
+#include <setvmaname.h>
 
 static void *alloc_ptr, *alloc_end, *alloc_last_block;
 
@@ -60,6 +61,7 @@ __minimal_malloc (size_t n)
 		     MAP_ANON|MAP_PRIVATE, -1, 0);
       if (page == MAP_FAILED)
 	return NULL;
+      __set_vma_name (page, nup, " glibc: loader malloc");
       if (page != alloc_end)
 	alloc_ptr = page;
       alloc_end = page + nup;
diff --git a/elf/tst-decorate-maps.c b/elf/tst-decorate-maps.c
index b40a0e9b49..b0ea65ffd7 100644
--- a/elf/tst-decorate-maps.c
+++ b/elf/tst-decorate-maps.c
@@ -32,15 +32,21 @@
 
 static pthread_barrier_t b;
 
+static int expected_n_arenas;
+
 static void *
 tf (void *closure)
 {
+  void *p = xmalloc (1024);
+
   /* Wait the thread startup, so thread stack is allocated.  */
   xpthread_barrier_wait (&b);
 
   /* Wait the test to read the process mapping.  */
   xpthread_barrier_wait (&b);
 
+  free (p);
+
   return NULL;
 }
 
@@ -48,6 +54,9 @@ struct proc_maps_t
 {
   int n_def_threads;
   int n_user_threads;
+  int n_arenas;
+  int n_malloc_mmap;
+  int n_loader_malloc_mmap;
 };
 
 static struct proc_maps_t
@@ -69,6 +78,12 @@ read_proc_maps (void)
 	r.n_def_threads++;
       else if (strstr (line, "[anon: glibc: pthread user stack:") != NULL)
 	r.n_user_threads++;
+      else if (strstr (line, "[anon: glibc: malloc arena]") != NULL)
+	r.n_arenas++;
+      else if (strstr (line, "[anon: glibc: malloc]") != NULL)
+	r.n_malloc_mmap++;
+      else if (strstr (line, "[anon: glibc: loader malloc]") != NULL)
+	r.n_loader_malloc_mmap++;
     }
   free (line);
   xfclose (f);
@@ -90,6 +105,9 @@ do_test_threads (bool set_guard)
 
   xpthread_barrier_init (&b, NULL, num_threads + 1);
 
+  /* Issue a large malloc to trigger a mmap call.  */
+  void *p = xmalloc (256 * 1024);
+
   pthread_t thr[num_threads];
   {
     int i = 0;
@@ -128,6 +146,10 @@ do_test_threads (bool set_guard)
     struct proc_maps_t r = read_proc_maps ();
     TEST_COMPARE (r.n_def_threads, num_def_threads);
     TEST_COMPARE (r.n_user_threads, num_user_threads);
+    TEST_COMPARE (r.n_arenas, expected_n_arenas);
+    TEST_COMPARE (r.n_malloc_mmap, 1);
+    /* On some architectures the loader might use more than one page.  */
+    TEST_VERIFY (r.n_loader_malloc_mmap >= 1);
   }
 
   /* Let the threads finish.  */
@@ -140,8 +162,22 @@ do_test_threads (bool set_guard)
     struct proc_maps_t r = read_proc_maps ();
     TEST_COMPARE (r.n_def_threads, 0);
     TEST_COMPARE (r.n_user_threads, 0);
+    TEST_COMPARE (r.n_arenas, expected_n_arenas);
+    TEST_COMPARE (r.n_malloc_mmap, 1);
+    TEST_VERIFY (r.n_loader_malloc_mmap >= 1);
   }
+
+  free (p);
+}
+
+static void
+do_prepare (int argc, char *argv[])
+{
+  TEST_VERIFY_EXIT (argc == 2);
+  expected_n_arenas = strtol (argv[1], NULL, 10);
+  expected_n_arenas = expected_n_arenas - 1;
 }
+#define PREPARE do_prepare
 
 static int
 do_test (void)