128 lines
4.0 KiB
Diff
128 lines
4.0 KiB
Diff
commit 0dc95ae10929aba1cc660e97cfc94903c2568efa
|
|
Author: Xi Ruoyao <xry111@xry111.site>
|
|
Date: Tue Feb 3 16:20:12 2026 +0800
|
|
|
|
elf: parse /proc/self/maps as the last resort to find the gap for tst-link-map-contiguous-ldso
|
|
|
|
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>
|
|
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
|
|
(cherry picked from commit aed8390a6a22e5751fc12704c0c5f2a8271fc286)
|
|
|
|
diff --git a/elf/tst-link-map-contiguous-ldso.c b/elf/tst-link-map-contiguous-ldso.c
|
|
index 04de808bb234fe38..f0e26682f2858414 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
|