[PATCH 4/6] nptl: Use __libc_procmaps_iterate on pthread_getattr_np
Adhemerval Zanella
adhemerval.zanella@linaro.org
Tue Sep 15 18:34:48 GMT 2026
Instead of stdio and __getline, which removes the malloc usage and the
fstat that stdio issues to size the stream buffer, and shares the
/proc/self/maps parsing with __readonly_area_fallback.
Checked on x86_64-linux-gnu.
---
nptl/pthread_getattr_np.c | 186 ++++++++++++++++++--------------------
1 file changed, 89 insertions(+), 97 deletions(-)
diff --git a/nptl/pthread_getattr_np.c b/nptl/pthread_getattr_np.c
index b0d2343a59a..698954f405a 100644
--- a/nptl/pthread_getattr_np.c
+++ b/nptl/pthread_getattr_np.c
@@ -17,15 +17,98 @@
#include <assert.h>
#include <errno.h>
-#include <inttypes.h>
-#include <stdio.h>
-#include <stdio_ext.h>
+#include <ldsodefs.h>
+#include <procmaps.h>
+#include <shlib-compat.h>
+#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <sys/resource.h>
#include "pthreadP.h"
#include <lowlevellock.h>
-#include <ldsodefs.h>
+
+
+struct find_stack_args
+{
+ uintptr_t stack_end;
+ uintptr_t to;
+#if _STACK_GROWS_DOWN
+ uintptr_t last_to;
+#endif
+ bool found;
+};
+
+/* Check whether the mapping address range contains ARGS->stack_end. */
+static bool
+find_stack_vma (uintptr_t start, uintptr_t end, const char *perm, void *arg)
+{
+ struct find_stack_args *args = arg;
+
+ if (start <= args->stack_end && args->stack_end < end)
+ {
+ args->to = end;
+ args->found = true;
+ return true;
+ }
+#if _STACK_GROWS_DOWN
+ args->last_to = end;
+#endif
+ return false;
+}
+
+static int
+pthread_main_stack (void **stackaddr, size_t *stacksize)
+{
+ /* Stack size limit. */
+ struct rlimit rl;
+
+ /* We need the limit of the stack in any case. */
+ if (__getrlimit (RLIMIT_STACK, &rl) != 0)
+ return errno;
+
+ /* We consider the main process stack to have ended with the page
+ containing __libc_stack_end. There is stuff below it in the stack too,
+ like the program arguments, environment variables and auxv info, but we
+ ignore those pages when returning size so that the output is consistent
+ when the stack is marked executable due to a loaded DSO requiring it. */
+ void *stack_end = (void *) ((uintptr_t) __libc_stack_end
+ & -(uintptr_t) GLRO(dl_pagesize));
+#if _STACK_GROWS_DOWN
+ stack_end += GLRO(dl_pagesize);
+#endif
+ /* The safest way to get the top of the stack is to read
+ /proc/self/maps and locate the line into which __libc_stack_end
+ falls. */
+ struct find_stack_args args =
+ {
+ .stack_end = (uintptr_t) __libc_stack_end,
+ };
+
+ if (__libc_procmaps_iterate (find_stack_vma, &args) == procutils_read_error)
+ return errno;
+ if (!args.found)
+ /* No entry was found (there should always be one). */
+ return ENOENT;
+
+ size_t size = rl.rlim_cur - (size_t) (args.to - (uintptr_t) stack_end);
+
+ /* Cut it down to align it to page size since otherwise we risk going beyond
+ rlimit when the kernel rounds up the stack extension request. */
+ size &= -(uintptr_t) GLRO(dl_pagesize);
+#if _STACK_GROWS_DOWN
+ /* The limit might be too high. */
+ if (size > (uintptr_t) stack_end - args.last_to)
+ size = (uintptr_t) stack_end - args.last_to;
+#else
+ /* The limit might be too low. */
+ if (size < args.to - (uintptr_t) stack_end)
+ size = args.to - (uintptr_t) stack_end;
+#endif
+
+ *stackaddr = stack_end;
+ *stacksize = size;
+ return 0;
+}
int
@@ -72,99 +155,8 @@ __pthread_getattr_np (pthread_t thread_id, pthread_attr_t *attr)
#endif
}
else
- {
- /* No stack information available. This must be for the initial
- thread. Get the info in some magical way. */
-
- /* Stack size limit. */
- struct rlimit rl;
-
- /* The safest way to get the top of the stack is to read
- /proc/self/maps and locate the line into which
- __libc_stack_end falls. */
- FILE *fp = fopen ("/proc/self/maps", "rce");
- if (fp == NULL)
- ret = errno;
- /* We need the limit of the stack in any case. */
- else
- {
- if (__getrlimit (RLIMIT_STACK, &rl) != 0)
- ret = errno;
- else
- {
- /* We consider the main process stack to have ended with
- the page containing __libc_stack_end. There is stuff below
- it in the stack too, like the program arguments, environment
- variables and auxv info, but we ignore those pages when
- returning size so that the output is consistent when the
- stack is marked executable due to a loaded DSO requiring
- it. */
- void *stack_end = (void *) ((uintptr_t) __libc_stack_end
- & -(uintptr_t) GLRO(dl_pagesize));
-#if _STACK_GROWS_DOWN
- stack_end += GLRO(dl_pagesize);
-#endif
- /* We need no locking. */
- __fsetlocking (fp, FSETLOCKING_BYCALLER);
-
- /* Until we found an entry (which should always be the case)
- mark the result as a failure. */
- ret = ENOENT;
-
- char *line = NULL;
- size_t linelen = 0;
-#if _STACK_GROWS_DOWN
- uintptr_t last_to = 0;
-#endif
-
- while (! feof_unlocked (fp))
- {
- if (__getline (&line, &linelen, fp) <= 0)
- break;
-
- uintptr_t from;
- uintptr_t to;
- if (sscanf (line, "%" SCNxPTR "-%" SCNxPTR, &from, &to) != 2)
- continue;
- if (from <= (uintptr_t) __libc_stack_end
- && (uintptr_t) __libc_stack_end < to)
- {
- /* Found the entry. Now we have the info we need. */
- iattr->stackaddr = stack_end;
- iattr->stacksize =
- rl.rlim_cur - (size_t) (to - (uintptr_t) stack_end);
-
- /* Cut it down to align it to page size since otherwise we
- risk going beyond rlimit when the kernel rounds up the
- stack extension request. */
- iattr->stacksize = (iattr->stacksize
- & -(intptr_t) GLRO(dl_pagesize));
-#if _STACK_GROWS_DOWN
- /* The limit might be too high. */
- if ((size_t) iattr->stacksize
- > (size_t) iattr->stackaddr - last_to)
- iattr->stacksize = (size_t) iattr->stackaddr - last_to;
-#else
- /* The limit might be too low. */
- if ((size_t) iattr->stacksize
- < to - (size_t) iattr->stackaddr)
- iattr->stacksize = to - (size_t) iattr->stackaddr;
-#endif
- /* We succeed and no need to look further. */
- ret = 0;
- break;
- }
-#if _STACK_GROWS_DOWN
- last_to = to;
-#endif
- }
-
- free (line);
- }
-
- fclose (fp);
- }
- }
+ /* No stack information available. This must be for the initial thread. */
+ ret = pthread_main_stack (&iattr->stackaddr, &iattr->stacksize);
iattr->flags |= ATTR_FLAG_STACKADDR;
--
2.53.0
More information about the Libc-alpha
mailing list