record-full: Remove unused function netorder16
[deliverable/binutils-gdb.git] / gdb / nat / linux-procfs.c
index 44364c5fbbd01c570226739e5e2aba49051a4886..5290045cc3fcd97b3574e51b84a9276f15dc8c0a 100644 (file)
@@ -1,5 +1,5 @@
 /* Linux-specific PROCFS manipulation routines.
-   Copyright (C) 2009-2015 Free Software Foundation, Inc.
+   Copyright (C) 2009-2017 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -70,19 +70,69 @@ linux_proc_get_tracerpid_nowarn (pid_t lwpid)
   return linux_proc_get_int (lwpid, "TracerPid", 0);
 }
 
-/* Fill in BUFFER, a buffer with BUFFER_SIZE bytes with the 'State'
+/* Process states as discovered in the 'State' line of
+   /proc/PID/status.  Not all possible states are represented here,
+   only those that we care about.  */
+
+enum proc_state
+{
+  /* Some state we don't handle.  */
+  PROC_STATE_UNKNOWN,
+
+  /* Stopped on a signal.  */
+  PROC_STATE_STOPPED,
+
+  /* Tracing stop.  */
+  PROC_STATE_TRACING_STOP,
+
+  /* Dead.  */
+  PROC_STATE_DEAD,
+
+  /* Zombie.  */
+  PROC_STATE_ZOMBIE,
+};
+
+/* Parse a PROC_STATE out of STATE, a buffer with the state found in
+   the 'State:' line of /proc/PID/status.  */
+
+static enum proc_state
+parse_proc_status_state (const char *state)
+{
+  state = skip_spaces_const (state);
+
+  switch (state[0])
+    {
+    case 't':
+      return PROC_STATE_TRACING_STOP;
+    case 'T':
+      /* Before Linux 2.6.33, tracing stop used uppercase T.  */
+      if (strcmp (state, "T (tracing stop)") == 0)
+       return PROC_STATE_TRACING_STOP;
+      else
+       return PROC_STATE_STOPPED;
+    case 'X':
+      return PROC_STATE_DEAD;
+    case 'Z':
+      return PROC_STATE_ZOMBIE;
+    }
+
+  return PROC_STATE_UNKNOWN;
+}
+
+
+/* Fill in STATE, a buffer with BUFFER_SIZE bytes with the 'State'
    line of /proc/PID/status.  Returns -1 on failure to open the /proc
    file, 1 if the line is found, and 0 if not found.  If WARN, warn on
    failure to open the /proc file.  */
 
 static int
-linux_proc_pid_get_state (pid_t pid, char *buffer, size_t buffer_size,
-                         int warn)
+linux_proc_pid_get_state (pid_t pid, int warn, enum proc_state *state)
 {
   FILE *procfile;
   int have_state;
+  char buffer[100];
 
-  xsnprintf (buffer, buffer_size, "/proc/%d/status", (int) pid);
+  xsnprintf (buffer, sizeof (buffer), "/proc/%d/status", (int) pid);
   procfile = gdb_fopen_cloexec (buffer, "r");
   if (procfile == NULL)
     {
@@ -92,10 +142,11 @@ linux_proc_pid_get_state (pid_t pid, char *buffer, size_t buffer_size,
     }
 
   have_state = 0;
-  while (fgets (buffer, buffer_size, procfile) != NULL)
+  while (fgets (buffer, sizeof (buffer), procfile) != NULL)
     if (startswith (buffer, "State:"))
       {
        have_state = 1;
+       *state = parse_proc_status_state (buffer + sizeof ("State:") - 1);
        break;
       }
   fclose (procfile);
@@ -107,10 +158,10 @@ linux_proc_pid_get_state (pid_t pid, char *buffer, size_t buffer_size,
 int
 linux_proc_pid_is_gone (pid_t pid)
 {
-  char buffer[100];
   int have_state;
+  enum proc_state state;
 
-  have_state = linux_proc_pid_get_state (pid, buffer, sizeof buffer, 0);
+  have_state = linux_proc_pid_get_state (pid, 0, &state);
   if (have_state < 0)
     {
       /* If we can't open the status file, assume the thread has
@@ -123,23 +174,20 @@ linux_proc_pid_is_gone (pid_t pid)
       return 0;
     }
   else
-    {
-      return (strstr (buffer, "Z (") != NULL
-             || strstr (buffer, "X (") != NULL);
-    }
+    return (state == PROC_STATE_ZOMBIE || state == PROC_STATE_DEAD);
 }
 
 /* Return non-zero if 'State' of /proc/PID/status contains STATE.  If
    WARN, warn on failure to open the /proc file.  */
 
 static int
-linux_proc_pid_has_state (pid_t pid, const char *state, int warn)
+linux_proc_pid_has_state (pid_t pid, enum proc_state state, int warn)
 {
-  char buffer[100];
   int have_state;
+  enum proc_state cur_state;
 
-  have_state = linux_proc_pid_get_state (pid, buffer, sizeof buffer, warn);
-  return (have_state > 0 && strstr (buffer, state) != NULL);
+  have_state = linux_proc_pid_get_state (pid, warn, &cur_state);
+  return (have_state > 0 && cur_state == state);
 }
 
 /* Detect `T (stopped)' in `/proc/PID/status'.
@@ -148,16 +196,16 @@ linux_proc_pid_has_state (pid_t pid, const char *state, int warn)
 int
 linux_proc_pid_is_stopped (pid_t pid)
 {
-  return linux_proc_pid_has_state (pid, "T (stopped)", 1);
+  return linux_proc_pid_has_state (pid, PROC_STATE_STOPPED, 1);
 }
 
-/* Detect `T (tracing stop)' in `/proc/PID/status'.
+/* Detect `t (tracing stop)' in `/proc/PID/status'.
    Other states including `T (stopped)' are reported as false.  */
 
 int
 linux_proc_pid_is_trace_stopped_nowarn (pid_t pid)
 {
-  return linux_proc_pid_has_state (pid, "T (tracing stop)", 1);
+  return linux_proc_pid_has_state (pid, PROC_STATE_TRACING_STOP, 1);
 }
 
 /* Return non-zero if PID is a zombie.  If WARN, warn on failure to
@@ -166,7 +214,7 @@ linux_proc_pid_is_trace_stopped_nowarn (pid_t pid)
 static int
 linux_proc_pid_is_zombie_maybe_warn (pid_t pid, int warn)
 {
-  return linux_proc_pid_has_state (pid, "Z (zombie)", warn);
+  return linux_proc_pid_has_state (pid, PROC_STATE_ZOMBIE, warn);
 }
 
 /* See linux-procfs.h declaration.  */
@@ -185,23 +233,46 @@ linux_proc_pid_is_zombie (pid_t pid)
   return linux_proc_pid_is_zombie_maybe_warn (pid, 1);
 }
 
-/* See linux-procfs.h declaration.  */
+/* See linux-procfs.h.  */
 
-char *
-linux_proc_pid_get_ns (pid_t pid, const char *ns)
+const char *
+linux_proc_tid_get_name (ptid_t ptid)
 {
-  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))
+#define TASK_COMM_LEN 16  /* As defined in the kernel's sched.h.  */
+
+  static char comm_buf[TASK_COMM_LEN];
+  char comm_path[100];
+  FILE *comm_file;
+  const char *comm_val;
+  pid_t pid = ptid_get_pid (ptid);
+  pid_t tid = ptid_lwp_p (ptid) ? ptid_get_lwp (ptid) : ptid_get_pid (ptid);
+
+  xsnprintf (comm_path, sizeof (comm_path),
+            "/proc/%ld/task/%ld/comm", (long) pid, (long) tid);
+
+  comm_file = gdb_fopen_cloexec (comm_path, "r");
+  if (comm_file == NULL)
+    return NULL;
+
+  comm_val = fgets (comm_buf, sizeof (comm_buf), comm_file);
+  fclose (comm_file);
+
+  if (comm_val != NULL)
     {
-      nsval[ret] = '\0';
-      return xstrdup (nsval);
+      int i;
+
+      /* Make sure there is no newline at the end.  */
+      for (i = 0; i < sizeof (comm_buf); i++)
+       {
+         if (comm_buf[i] == '\n')
+           {
+             comm_buf[i] = '\0';
+             break;
+           }
+       }
     }
 
-  return NULL;
+  return comm_val;
 }
 
 /* See linux-procfs.h.  */
This page took 0.026968 seconds and 4 git commands to generate.