[PATCH] nptl: Skip tst-pthread-gdb-attach{, -static} on env mismatches
Adhemerval Zanella
adhemerval.zanella@linaro.org
Thu May 21 16:30:47 GMT 2026
The test previously failed with confusing diagnostics in two situations
that are properties of the runtime environment rather than of glibc:
1. find_gdb only checked access(X_OK), which is true for directories
too. A 'gdb' directory ahead of /usr/bin in PATH (e.g. one holding
gdb python helpers) was therefore returned as the gdb executable,
and the subsequent execl failed with errno != ENOENT, causing the
test to fail with `numeric comparison failure ... status 256'.
2. The in-tree libthread_db.so.1 is built with -z mark-plt and
therefore carries a versioned dependency on
GLIBC_ABI_DT_X86_64_PLT in libc.so (see BZ #33212). When the
system gdb is linked against a libc older than 2.41, that version
is not provided and gdb's dlopen of the in-tree libthread_db.so.1
fails. Thread debugging is then disabled, the gdb script's
`thread 1' / `thread 2' commands fail, gdb exits non-zero, and the
test reports a generic status mismatch.
Two changes:
* Require S_ISREG in find_gdb so a directory named 'gdb' on PATH is
skipped, falling through to the next candidate.
* Before running the real gdb scenario, run a minimal probe script
that triggers libthread_db loading (set debug libthread-db 1; set
libthread-db-search-path; file /proc/self/exe; start). If the
probe output contains `dlopen failed', mark the test UNSUPPORTED
with a clear message instead of letting the real run fail.
---
nptl/tst-pthread-gdb-attach.c | 62 ++++++++++++++++++++++++++++++++++-
1 file changed, 61 insertions(+), 1 deletion(-)
diff --git a/nptl/tst-pthread-gdb-attach.c b/nptl/tst-pthread-gdb-attach.c
index b183dc0f30f..c737188a6c0 100644
--- a/nptl/tst-pthread-gdb-attach.c
+++ b/nptl/tst-pthread-gdb-attach.c
@@ -25,6 +25,7 @@
#include <fcntl.h>
#include <signal.h>
#include <stdbool.h>
+#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <support/capture_subprocess.h>
@@ -37,6 +38,7 @@
#include <support/xstdio.h>
#include <support/xthread.h>
#include <support/xunistd.h>
+#include <sys/stat.h>
#include <unistd.h>
/* Starts out as zero, changed to 1 or 2 by the debugger, depending on
@@ -65,6 +67,51 @@ read_elf_header (const char *path, struct elf_prefix *elf)
return result;
}
+/* Runs gdb with a minimal probe script and returns true if gdb prints
+ 'dlopen failed' while attempting to load libthread_db. */
+static bool
+libthread_db_probe_fails (const char *gdb_path)
+{
+ support_need_proc ("Reads /proc/self/exec to probe gdb");
+
+ /* The probe inferior just needs to be any pthread-linked binary; reusing
+ /proc/self/exe avoids hard-coding a path. */
+ char *self = xreadlink ("/proc/self/exe");
+
+ char *probe_script;
+ xclose (create_temp_file ("tst-pthread-gdb-attach-probe-", &probe_script));
+ FILE *fp = xfopen (probe_script, "w");
+ fprintf (fp,
+ "set debuginfod enabled off\n"
+ "set debug libthread-db 1\n"
+ "set auto-load safe-path %1$s/nptl_db\n"
+ "set libthread-db-search-path %1$s/nptl_db\n"
+ "file %2$s\n"
+ "start\n",
+ support_objdir_root, self);
+ xfclose (fp);
+ free (self);
+
+ char *cmd = xasprintf ("%s -nx -batch -x %s 2>&1",
+ gdb_path, probe_script);
+ FILE *gdb_out = popen (cmd, "r");
+ free (cmd);
+
+ bool fails = false;
+ if (gdb_out != NULL)
+ {
+ char *line = NULL;
+ size_t linecap = 0;
+ while (xgetline (&line, &linecap, gdb_out) > 0)
+ if (strstr (line, "dlopen failed") != NULL)
+ fails = true;
+ free (line);
+ pclose (gdb_out);
+ }
+ free (probe_script);
+ return fails;
+}
+
/* Searches for "gdb" alongside the path variable. See execvpe. */
static char *
find_gdb (void)
@@ -76,7 +123,10 @@ find_gdb (void)
{
const char *colon = strchrnul (path, ':');
char *candidate = xasprintf ("%.*s/gdb", (int) (colon - path), path);
- if (access (candidate, X_OK) == 0)
+ struct stat st;
+ if (access (candidate, X_OK) == 0
+ && stat (candidate, &st) == 0
+ && S_ISREG (st.st_mode))
return candidate;
free (candidate);
if (*colon == '\0')
@@ -199,10 +249,20 @@ do_test (void)
FAIL_UNSUPPORTED ("GDB at %s has wrong data", gdb_path);
if (elf_gdb.e_machine != elf_threaddb.e_machine)
FAIL_UNSUPPORTED ("GDB at %s has wrong machine", gdb_path);
+
}
free (threaddb_path);
}
+ /* Probe gdb with a minimal script that triggers libthread_db loading. If
+ the probe reports a dlopen failure (e.g. because the libc gdb is linked
+ against is older than the one in-tree libthread_db.so.1 requires, see
+ BZ #33212), skip the test as UNSUPPORTED. */
+ if (libthread_db_probe_fails (gdb_path))
+ FAIL_UNSUPPORTED ("gdb cannot dlopen the in-tree libthread_db.so.1;"
+ " its libc is missing a required ABI version"
+ " (see BZ #33212)");
+
/* Check if our subprocess can be debugged with ptrace. */
{
int ptrace_scope = support_ptrace_scope ();
--
2.43.0
More information about the Libc-alpha
mailing list