diff options
-rw-r--r-- | gdb/ChangeLog | 8 | ||||
-rw-r--r-- | gdb/linux-thread-db.c | 29 | ||||
-rw-r--r-- | gdb/nat/linux-procfs.c | 19 | ||||
-rw-r--r-- | gdb/nat/linux-procfs.h | 6 |
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 (¤t_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 */ |