[PATCH v5] elf: parse /proc/self/maps as the last resort to find the gap for tst-link-map-contiguous-ldso
Adhemerval Zanella Netto
adhemerval.zanella@linaro.org
Fri Feb 13 14:06:11 GMT 2026
On 03/02/26 05:20, Xi Ruoyao wrote:
> The initialization process of libc.so calls mmap() several times and the
> kernel may lay the maps into the gap. If all pages in the gap are
> occupied, the test would not be able to find the gap with mmap() and the
> test would fail.
>
> The failure reproduces most frequently on LoongArch because with the
> commonly used page size (16 KiB) the gap only contains 4 pages and the
> probability they are all occupied is not near to zero.
>
> With the changes in the patch, a test run may output:
>
> info: ld.so link map is not contiguous
> info: object "/dev/zero" found at 0x7ffff1fe0000 - 0x7ffff1fe4000
> info: anonymous mapping found at 0x7ffff1fe4000 - 0x7ffff1fec000
>
> Also take the chance to fix a mistake in the "object found at" message
> which has puzzled me during the initial debug session.
>
> Signed-off-by: Xi Ruoyao <xry111@xry111.site>
I think this version addresses the missing point raised by Florian.
LGTM, thanks.
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
> ---
>
> ChangeLog:
>
> v1 -> v2: parse mmap to avoid false postive
> v2 -> v3: use %ms to simplify the code and get the full path of ld.so by
> matching l_map_start in the maps file
> v3 -> v4: move the definition of "path" into the loop body
> v4 -> v5: fix memory and fd leak, fix format string macro for printf,
> and make pointer nullity check more explicit
>
> elf/tst-link-map-contiguous-ldso.c | 64 +++++++++++++++++++++++++++++-
> 1 file changed, 62 insertions(+), 2 deletions(-)
>
> diff --git a/elf/tst-link-map-contiguous-ldso.c b/elf/tst-link-map-contiguous-ldso.c
> index 9f97b8b95a..4d04d37581 100644
> --- a/elf/tst-link-map-contiguous-ldso.c
> +++ b/elf/tst-link-map-contiguous-ldso.c
> @@ -18,15 +18,73 @@
>
> #include <dlfcn.h>
> #include <gnu/lib-names.h>
> +#include <inttypes.h>
> #include <link.h>
> #include <stdbool.h>
> #include <stdio.h>
> #include <support/check.h>
> +#include <support/support.h>
> #include <support/xdlfcn.h>
> #include <support/xunistd.h>
> +#include <support/xstdio.h>
> #include <sys/mman.h>
> #include <unistd.h>
>
> +/* Slow path in case we cannot find a gap with mmap (when the runtime has
> + mapped all the pages in the gap for some reason). */
> +static bool
> +find_gap_with_proc_self_map (const struct link_map *l)
> +{
> + int pagesize = getpagesize ();
> +
> + support_need_proc ("Reads /proc/self/maps to find gap in ld.so mapping");
> +
> + /* Parse /proc/self/maps and find all the mappings in the ld.so range
> + but not from ld.so. */
> + FILE *f = xfopen ("/proc/self/maps", "r");
> + char *line = NULL, *path_ldso = NULL;
> + size_t len;
> + bool found = false;
> + while (xgetline (&line, &len, f))
> + {
> + uintptr_t from, to;
> + char *path = NULL;
> + int r = sscanf (line, "%" SCNxPTR "-%" SCNxPTR "%*s%*s%*s%*s%ms",
> + &from, &to, &path);
> +
> + TEST_VERIFY (r == 2 || r == 3);
> + TEST_COMPARE (from % pagesize, 0);
> + TEST_COMPARE (to % pagesize, 0);
> +
> + if (path_ldso == NULL && l->l_map_start == from)
> + {
> + TEST_COMPARE (r, 3);
> + path_ldso = path;
> + continue;
> + }
> +
> + if (from > l->l_map_start && to < l->l_map_end
> + && (r == 2 || (path_ldso != NULL && strcmp (path, path_ldso))))
> + {
> + if (r == 2)
> + printf ("info: anonymous mapping found at 0x%" PRIxPTR " - 0x%"
> + PRIxPTR "\n", from, to);
> + else
> + printf ("info: object \"%s\" found at 0x%" PRIxPTR " - 0x%"
> + PRIxPTR "\n", path, from, to);
> +
> + found = true;
> + }
> +
> + free (path);
> + }
> +
> + free (path_ldso);
> + free (line);
> + xfclose (f);
> + return found;
> +}
> +
> static int
> do_test (void)
> {
> @@ -64,16 +122,18 @@ do_test (void)
> if ((void *) dlfo.dlfo_link_map != (void *) l)
> {
> printf ("info: object \"%s\" found at %p\n",
> - dlfo.dlfo_link_map->l_name, ptr);
> + dlfo.dlfo_link_map->l_name, expected);
> gap_found = true;
> }
> }
> else
> TEST_COMPARE (dlfo_ret, -1);
> +
> xmunmap (ptr, 1);
> addr += pagesize;
> }
> - if (!gap_found)
> +
> + if (!gap_found && !find_gap_with_proc_self_map (l))
> FAIL ("no ld.so gap found");
> }
> else
More information about the Libc-alpha
mailing list