aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gdb/ChangeLog8
-rw-r--r--gdb/linux-thread-db.c29
-rw-r--r--gdb/nat/linux-procfs.c19
-rw-r--r--gdb/nat/linux-procfs.h6
4 files changed, 62 insertions, 0 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 6a9b660..10321fd 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,11 @@
+2014-11-11 Daniel Colascione <dancol@dancol.org>
+
+ Warn about cross-PID-namespace debugging.
+ * nat/linux-procfs.h (linux_proc_pid_get_ns): New prototype.
+ * nat/linux-procfs.c (linux_proc_pid_get_ns): New function.
+ * linux-thread-db.c (check_pid_namespace_match): New function.
+ (thread_db_inferior_created): Call it.
+
2014-11-10 Doug Evans <xdje42@gmail.com>
* symmisc.c (print_objfile_statistics): Remove trailing whitespace.
diff --git a/gdb/linux-thread-db.c b/gdb/linux-thread-db.c
index 352fac1..c49b567 100644
--- a/gdb/linux-thread-db.c
+++ b/gdb/linux-thread-db.c
@@ -1217,12 +1217,41 @@ thread_db_new_objfile (struct objfile *objfile)
check_for_thread_db ();
}
+static void
+check_pid_namespace_match (void)
+{
+ /* Check is only relevant for local targets targets. */
+ if (target_can_run (&current_target))
+ {
+ /* If the child is in a different PID namespace, its idea of its
+ PID will differ from our idea of its PID. When we scan the
+ child's thread list, we'll mistakenly think it has no threads
+ since the thread PID fields won't match the PID we give to
+ libthread_db. */
+ char *our_pid_ns = linux_proc_pid_get_ns (getpid (), "pid");
+ char *inferior_pid_ns = linux_proc_pid_get_ns (
+ ptid_get_pid (inferior_ptid), "pid");
+
+ if (our_pid_ns != NULL && inferior_pid_ns != NULL
+ && strcmp (our_pid_ns, inferior_pid_ns) != 0)
+ {
+ warning (_ ("Target and debugger are in different PID "
+ "namespaces; thread lists and other data are "
+ "likely unreliable"));
+ }
+
+ xfree (our_pid_ns);
+ xfree (inferior_pid_ns);
+ }
+}
+
/* This function is called via the inferior_created observer.
This handles the case of debugging statically linked executables. */
static void
thread_db_inferior_created (struct target_ops *target, int from_tty)
{
+ check_pid_namespace_match ();
check_for_thread_db ();
}
diff --git a/gdb/nat/linux-procfs.c b/gdb/nat/linux-procfs.c
index 30797da..00f2f08 100644
--- a/gdb/nat/linux-procfs.c
+++ b/gdb/nat/linux-procfs.c
@@ -113,3 +113,22 @@ linux_proc_pid_is_zombie (pid_t pid)
{
return linux_proc_pid_has_state (pid, "Z (zombie)");
}
+
+/* See linux-procfs.h declaration. */
+
+char *
+linux_proc_pid_get_ns (pid_t pid, const char *ns)
+{
+ char buf[100];
+ char nsval[64];
+ int ret;
+ xsnprintf (buf, sizeof (buf), "/proc/%d/ns/%s", (int) pid, ns);
+ ret = readlink (buf, nsval, sizeof (nsval));
+ if (0 < ret && ret < sizeof (nsval))
+ {
+ nsval[ret] = '\0';
+ return xstrdup (nsval);
+ }
+
+ return NULL;
+}
diff --git a/gdb/nat/linux-procfs.h b/gdb/nat/linux-procfs.h
index d13fff7..5e2a9ea 100644
--- a/gdb/nat/linux-procfs.h
+++ b/gdb/nat/linux-procfs.h
@@ -40,4 +40,10 @@ extern int linux_proc_pid_is_stopped (pid_t pid);
extern int linux_proc_pid_is_zombie (pid_t pid);
+/* Return an opaque string identifying PID's NS namespace or NULL if
+ * the information is unavailable. The returned string must be
+ * released with xfree. */
+
+extern char *linux_proc_pid_get_ns (pid_t pid, const char *ns);
+
#endif /* COMMON_LINUX_PROCFS_H */