diff mbox series

[v2,08/13] support: Add support_count_maps

Message ID e3d2b6c46386cbc4a2442186403e4951b1e2814c.1722193092.git.fweimer@redhat.com
State New
Headers show
Series getenv/environ thread safety | expand

Commit Message

Florian Weimer July 28, 2024, 7:03 p.m. UTC
---
 support/Makefile                 |  2 ++
 support/support.h                |  5 +++
 support/support_count_maps.c     | 51 +++++++++++++++++++++++++++++++
 support/tst-support_count_maps.c | 52 ++++++++++++++++++++++++++++++++
 4 files changed, 110 insertions(+)
 create mode 100644 support/support_count_maps.c
 create mode 100644 support/tst-support_count_maps.c
diff mbox series

Patch

diff --git a/support/Makefile b/support/Makefile
index aa57207bdc..bc35faa325 100644
--- a/support/Makefile
+++ b/support/Makefile
@@ -53,6 +53,7 @@  libsupport-routines = \
   support_chroot \
   support_copy_file \
   support_copy_file_range \
+  support_count_maps \
   support_create_timer \
   support_descriptor_supports_holes \
   support_descriptors \
@@ -319,6 +320,7 @@  tests = \
   tst-support-process_state \
   tst-support_blob_repeat \
   tst-support_capture_subprocess \
+  tst-support_count_maps \
   tst-support_descriptors \
   tst-support_format_dns_packet \
   tst-support_quote_blob \
diff --git a/support/support.h b/support/support.h
index ba21ec9b5a..5769e8c5f3 100644
--- a/support/support.h
+++ b/support/support.h
@@ -96,6 +96,11 @@  int support_descriptor_supports_holes (int fd);
    WHY_MSG as part of the diagnostic.  */
 void support_need_proc (const char *why_msg);
 
+/* Counts the number of mappings in the process address space.
+   Currently implemented using /proc/self/maps on Linux, so it needs
+   that to exist.  */
+size_t support_count_maps (void);
+
 /* Error-checking wrapper functions which terminate the process on
    error.  */
 
diff --git a/support/support_count_maps.c b/support/support_count_maps.c
new file mode 100644
index 0000000000..2a6dd9fee3
--- /dev/null
+++ b/support/support_count_maps.c
@@ -0,0 +1,51 @@ 
+/* Count the number of mappings.
+   Copyright (C) 2024 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 <support/support.h>
+#include <support/check.h>
+#include <support/xstdio.h>
+#include <errno.h>
+
+size_t
+support_count_maps (void)
+{
+  FILE *fp = fopen ("/proc/self/maps", "r");
+  if (fp == NULL)
+    {
+      if (errno == ENOENT)
+        FAIL_UNSUPPORTED ("support_count_maps: test needs /proc/self/maps");
+      else
+        FAIL_EXIT1 ("cannot open /proc/self/maps: %m");
+    }
+  size_t count = 0;
+  while (true)
+    {
+      switch (getc_unlocked (fp))
+        {
+        case EOF:
+          /* Error will be reported by xfclose below.  */
+          goto out;
+        case '\n':
+          ++count;
+          break;
+        }
+    }
+ out:
+  xfclose (fp);
+  return count;
+}
diff --git a/support/tst-support_count_maps.c b/support/tst-support_count_maps.c
new file mode 100644
index 0000000000..e904a00cd4
--- /dev/null
+++ b/support/tst-support_count_maps.c
@@ -0,0 +1,52 @@ 
+/* Test counting the number of mappings.
+   Copyright (C) 2024 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 <stdio.h>
+#include <support/support.h>
+#include <support/check.h>
+#include <support/xstdio.h>
+#include <sys/mman.h>
+#include <support/xunistd.h>
+
+static int
+do_test (void)
+{
+  long int page_size = xsysconf (_SC_PAGESIZE);
+
+  size_t initial = support_count_maps ();
+  printf ("info: initial number of maps: %zu\n", initial);
+
+  void *ptr = xmmap (NULL, 2 * page_size, PROT_READ | PROT_WRITE,
+                     MAP_PRIVATE | MAP_ANONYMOUS, -1);
+  size_t one_mapping = support_count_maps ();
+  printf ("info: new number of maps: %zu\n", one_mapping);
+  TEST_COMPARE (initial + 1, one_mapping);
+
+  /* The mapping gets split due to the protection flags change.  */
+  xmprotect (ptr, page_size, PROT_READ);
+  size_t two_mappings = support_count_maps ();
+  TEST_COMPARE (initial + 2, two_mappings);
+
+  xmunmap (ptr, 2 * page_size);
+  size_t final = support_count_maps ();
+  TEST_COMPARE (initial, final);
+
+  return 0;
+}
+
+#include <support/test-driver.c>