1a45ae5f8SJohn Marino /* Linux-specific PROCFS manipulation routines.
2*ef5ccd6cSJohn Marino Copyright (C) 2009-2013 Free Software Foundation, Inc.
3a45ae5f8SJohn Marino
4a45ae5f8SJohn Marino This file is part of GDB.
5a45ae5f8SJohn Marino
6a45ae5f8SJohn Marino This program is free software; you can redistribute it and/or modify
7a45ae5f8SJohn Marino it under the terms of the GNU General Public License as published by
8a45ae5f8SJohn Marino the Free Software Foundation; either version 3 of the License, or
9a45ae5f8SJohn Marino (at your option) any later version.
10a45ae5f8SJohn Marino
11a45ae5f8SJohn Marino This program is distributed in the hope that it will be useful,
12a45ae5f8SJohn Marino but WITHOUT ANY WARRANTY; without even the implied warranty of
13a45ae5f8SJohn Marino MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14a45ae5f8SJohn Marino GNU General Public License for more details.
15a45ae5f8SJohn Marino
16a45ae5f8SJohn Marino You should have received a copy of the GNU General Public License
17a45ae5f8SJohn Marino along with this program. If not, see <http://www.gnu.org/licenses/>. */
18a45ae5f8SJohn Marino
19a45ae5f8SJohn Marino #ifdef GDBSERVER
20a45ae5f8SJohn Marino #include "server.h"
21a45ae5f8SJohn Marino #else
22a45ae5f8SJohn Marino #include "defs.h"
23a45ae5f8SJohn Marino #include "gdb_string.h"
24a45ae5f8SJohn Marino #endif
25a45ae5f8SJohn Marino
26a45ae5f8SJohn Marino #include "linux-procfs.h"
27a45ae5f8SJohn Marino
28a45ae5f8SJohn Marino /* Return the TGID of LWPID from /proc/pid/status. Returns -1 if not
29a45ae5f8SJohn Marino found. */
30a45ae5f8SJohn Marino
31*ef5ccd6cSJohn Marino static int
linux_proc_get_int(pid_t lwpid,const char * field)32*ef5ccd6cSJohn Marino linux_proc_get_int (pid_t lwpid, const char *field)
33a45ae5f8SJohn Marino {
34*ef5ccd6cSJohn Marino size_t field_len = strlen (field);
35a45ae5f8SJohn Marino FILE *status_file;
36a45ae5f8SJohn Marino char buf[100];
37*ef5ccd6cSJohn Marino int retval = -1;
38a45ae5f8SJohn Marino
39a45ae5f8SJohn Marino snprintf (buf, sizeof (buf), "/proc/%d/status", (int) lwpid);
40a45ae5f8SJohn Marino status_file = fopen (buf, "r");
41*ef5ccd6cSJohn Marino if (status_file == NULL)
42a45ae5f8SJohn Marino {
43*ef5ccd6cSJohn Marino warning (_("unable to open /proc file '%s'"), buf);
44*ef5ccd6cSJohn Marino return -1;
45a45ae5f8SJohn Marino }
46*ef5ccd6cSJohn Marino
47*ef5ccd6cSJohn Marino while (fgets (buf, sizeof (buf), status_file))
48*ef5ccd6cSJohn Marino if (strncmp (buf, field, field_len) == 0 && buf[field_len] == ':')
49*ef5ccd6cSJohn Marino {
50*ef5ccd6cSJohn Marino retval = strtol (&buf[field_len + 1], NULL, 10);
51*ef5ccd6cSJohn Marino break;
52a45ae5f8SJohn Marino }
53a45ae5f8SJohn Marino
54a45ae5f8SJohn Marino fclose (status_file);
55*ef5ccd6cSJohn Marino return retval;
56a45ae5f8SJohn Marino }
57a45ae5f8SJohn Marino
58*ef5ccd6cSJohn Marino /* Return the TGID of LWPID from /proc/pid/status. Returns -1 if not
59*ef5ccd6cSJohn Marino found. */
60*ef5ccd6cSJohn Marino
61*ef5ccd6cSJohn Marino int
linux_proc_get_tgid(pid_t lwpid)62*ef5ccd6cSJohn Marino linux_proc_get_tgid (pid_t lwpid)
63*ef5ccd6cSJohn Marino {
64*ef5ccd6cSJohn Marino return linux_proc_get_int (lwpid, "Tgid");
65*ef5ccd6cSJohn Marino }
66*ef5ccd6cSJohn Marino
67*ef5ccd6cSJohn Marino /* See linux-procfs.h. */
68*ef5ccd6cSJohn Marino
69*ef5ccd6cSJohn Marino pid_t
linux_proc_get_tracerpid(pid_t lwpid)70*ef5ccd6cSJohn Marino linux_proc_get_tracerpid (pid_t lwpid)
71*ef5ccd6cSJohn Marino {
72*ef5ccd6cSJohn Marino return linux_proc_get_int (lwpid, "TracerPid");
73*ef5ccd6cSJohn Marino }
74*ef5ccd6cSJohn Marino
75*ef5ccd6cSJohn Marino /* Return non-zero if 'State' of /proc/PID/status contains STATE. */
76*ef5ccd6cSJohn Marino
77*ef5ccd6cSJohn Marino static int
linux_proc_pid_has_state(pid_t pid,const char * state)78*ef5ccd6cSJohn Marino linux_proc_pid_has_state (pid_t pid, const char *state)
79*ef5ccd6cSJohn Marino {
80*ef5ccd6cSJohn Marino char buffer[100];
81*ef5ccd6cSJohn Marino FILE *procfile;
82*ef5ccd6cSJohn Marino int retval;
83*ef5ccd6cSJohn Marino int have_state;
84*ef5ccd6cSJohn Marino
85*ef5ccd6cSJohn Marino xsnprintf (buffer, sizeof (buffer), "/proc/%d/status", (int) pid);
86*ef5ccd6cSJohn Marino procfile = fopen (buffer, "r");
87*ef5ccd6cSJohn Marino if (procfile == NULL)
88*ef5ccd6cSJohn Marino {
89*ef5ccd6cSJohn Marino warning (_("unable to open /proc file '%s'"), buffer);
90*ef5ccd6cSJohn Marino return 0;
91*ef5ccd6cSJohn Marino }
92*ef5ccd6cSJohn Marino
93*ef5ccd6cSJohn Marino have_state = 0;
94*ef5ccd6cSJohn Marino while (fgets (buffer, sizeof (buffer), procfile) != NULL)
95*ef5ccd6cSJohn Marino if (strncmp (buffer, "State:", 6) == 0)
96*ef5ccd6cSJohn Marino {
97*ef5ccd6cSJohn Marino have_state = 1;
98*ef5ccd6cSJohn Marino break;
99*ef5ccd6cSJohn Marino }
100*ef5ccd6cSJohn Marino retval = (have_state && strstr (buffer, state) != NULL);
101*ef5ccd6cSJohn Marino fclose (procfile);
102*ef5ccd6cSJohn Marino return retval;
103*ef5ccd6cSJohn Marino }
104*ef5ccd6cSJohn Marino
105*ef5ccd6cSJohn Marino /* Detect `T (stopped)' in `/proc/PID/status'.
106*ef5ccd6cSJohn Marino Other states including `T (tracing stop)' are reported as false. */
107*ef5ccd6cSJohn Marino
108*ef5ccd6cSJohn Marino int
linux_proc_pid_is_stopped(pid_t pid)109*ef5ccd6cSJohn Marino linux_proc_pid_is_stopped (pid_t pid)
110*ef5ccd6cSJohn Marino {
111*ef5ccd6cSJohn Marino return linux_proc_pid_has_state (pid, "T (stopped)");
112*ef5ccd6cSJohn Marino }
113*ef5ccd6cSJohn Marino
114*ef5ccd6cSJohn Marino /* See linux-procfs.h declaration. */
115*ef5ccd6cSJohn Marino
116*ef5ccd6cSJohn Marino int
linux_proc_pid_is_zombie(pid_t pid)117*ef5ccd6cSJohn Marino linux_proc_pid_is_zombie (pid_t pid)
118*ef5ccd6cSJohn Marino {
119*ef5ccd6cSJohn Marino return linux_proc_pid_has_state (pid, "Z (zombie)");
120a45ae5f8SJohn Marino }
121