[PATCH v4] elf: parse /proc/self/maps as the last resort to find the gap for tst-link-map-contiguous-ldso
Florian Weimer
fweimer@redhat.com
Mon Feb 2 10:13:08 GMT 2026
* Xi Ruoyao:
> 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>
Just a few style nits.
> +/* 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 && l->l_map_start == from)
We generally prefer writing path_ldso != NULL.
> + {
> + TEST_COMPARE (r, 3);
> + path_ldso = path;
> + continue;
> + }
> +
> + if (from > l->l_map_start && to < l->l_map_end
> + && (r == 2 || (path_ldso && strcmp (path, path_ldso))))
Here as well.
> + {
> + if (r == 2)
> + printf ("info: anonymous mapping found at 0x%" SCNxPTR " - 0x%"
> + SCNxPTR "\n", from, to);
> + else
> + printf ("info: object \"%s\" found at 0x%" SCNxPTR " - 0x%"
> + SCNxPTR "\n", path, from, to);
Please use PRIxPTR here.
> +
> + found = true;
> + }
> +
> + free (path);
> + }
> +
> + free (path_ldso);
> + return found;
> +}
Could close f here and free line.
Thanks,
Florian
More information about the Libc-alpha
mailing list