[ARI] Remove trailing new-line in argument of call to warning.
[deliverable/binutils-gdb.git] / gdb / nat / linux-procfs.c
CommitLineData
13da1c97 1/* Linux-specific PROCFS manipulation routines.
32d0add0 2 Copyright (C) 2009-2015 Free Software Foundation, Inc.
13da1c97
LM
3
4 This file is part of GDB.
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>. */
18
727605ca 19#include "common-defs.h"
13da1c97 20#include "linux-procfs.h"
614c279d 21#include "filestuff.h"
8784d563 22#include <dirent.h>
13da1c97
LM
23
24/* Return the TGID of LWPID from /proc/pid/status. Returns -1 if not
25 found. */
26
87b0bb13 27static int
8784d563 28linux_proc_get_int (pid_t lwpid, const char *field, int warn)
13da1c97 29{
87b0bb13 30 size_t field_len = strlen (field);
13da1c97
LM
31 FILE *status_file;
32 char buf[100];
87b0bb13 33 int retval = -1;
13da1c97
LM
34
35 snprintf (buf, sizeof (buf), "/proc/%d/status", (int) lwpid);
614c279d 36 status_file = gdb_fopen_cloexec (buf, "r");
87b0bb13 37 if (status_file == NULL)
13da1c97 38 {
8784d563
PA
39 if (warn)
40 warning (_("unable to open /proc file '%s'"), buf);
87b0bb13 41 return -1;
13da1c97
LM
42 }
43
87b0bb13
JK
44 while (fgets (buf, sizeof (buf), status_file))
45 if (strncmp (buf, field, field_len) == 0 && buf[field_len] == ':')
46 {
47 retval = strtol (&buf[field_len + 1], NULL, 10);
48 break;
49 }
50
51 fclose (status_file);
52 return retval;
13da1c97 53}
644cebc9 54
87b0bb13
JK
55/* Return the TGID of LWPID from /proc/pid/status. Returns -1 if not
56 found. */
644cebc9
PA
57
58int
87b0bb13 59linux_proc_get_tgid (pid_t lwpid)
644cebc9 60{
8784d563 61 return linux_proc_get_int (lwpid, "Tgid", 1);
87b0bb13 62}
644cebc9 63
87b0bb13
JK
64/* See linux-procfs.h. */
65
66pid_t
8784d563 67linux_proc_get_tracerpid_nowarn (pid_t lwpid)
87b0bb13 68{
8784d563 69 return linux_proc_get_int (lwpid, "TracerPid", 0);
644cebc9 70}
5f572dec 71
8784d563
PA
72/* Fill in BUFFER, a buffer with BUFFER_SIZE bytes with the 'State'
73 line of /proc/PID/status. Returns -1 on failure to open the /proc
74 file, 1 if the line is found, and 0 if not found. If WARN, warn on
75 failure to open the /proc file. */
5f572dec 76
87b0bb13 77static int
8784d563
PA
78linux_proc_pid_get_state (pid_t pid, char *buffer, size_t buffer_size,
79 int warn)
5f572dec 80{
5f572dec 81 FILE *procfile;
5f572dec
JK
82 int have_state;
83
8784d563 84 xsnprintf (buffer, buffer_size, "/proc/%d/status", (int) pid);
614c279d 85 procfile = gdb_fopen_cloexec (buffer, "r");
5f572dec
JK
86 if (procfile == NULL)
87 {
8784d563
PA
88 if (warn)
89 warning (_("unable to open /proc file '%s'"), buffer);
90 return -1;
5f572dec
JK
91 }
92
93 have_state = 0;
8784d563 94 while (fgets (buffer, buffer_size, procfile) != NULL)
5f572dec
JK
95 if (strncmp (buffer, "State:", 6) == 0)
96 {
97 have_state = 1;
98 break;
99 }
5f572dec 100 fclose (procfile);
8784d563
PA
101 return have_state;
102}
103
104/* See linux-procfs.h declaration. */
105
106int
107linux_proc_pid_is_gone (pid_t pid)
108{
109 char buffer[100];
110 int have_state;
111
112 have_state = linux_proc_pid_get_state (pid, buffer, sizeof buffer, 0);
113 if (have_state < 0)
114 {
115 /* If we can't open the status file, assume the thread has
116 disappeared. */
117 return 1;
118 }
119 else if (have_state == 0)
120 {
121 /* No "State:" line, assume thread is alive. */
122 return 0;
123 }
124 else
125 {
126 return (strstr (buffer, "Z (") != NULL
127 || strstr (buffer, "X (") != NULL);
128 }
129}
130
131/* Return non-zero if 'State' of /proc/PID/status contains STATE. If
132 WARN, warn on failure to open the /proc file. */
133
134static int
135linux_proc_pid_has_state (pid_t pid, const char *state, int warn)
136{
137 char buffer[100];
138 int have_state;
139
140 have_state = linux_proc_pid_get_state (pid, buffer, sizeof buffer, warn);
141 return (have_state > 0 && strstr (buffer, state) != NULL);
5f572dec 142}
87b0bb13
JK
143
144/* Detect `T (stopped)' in `/proc/PID/status'.
145 Other states including `T (tracing stop)' are reported as false. */
146
147int
148linux_proc_pid_is_stopped (pid_t pid)
149{
8784d563
PA
150 return linux_proc_pid_has_state (pid, "T (stopped)", 1);
151}
152
153/* Return non-zero if PID is a zombie. If WARN, warn on failure to
154 open the /proc file. */
155
156static int
157linux_proc_pid_is_zombie_maybe_warn (pid_t pid, int warn)
158{
159 return linux_proc_pid_has_state (pid, "Z (zombie)", warn);
160}
161
162/* See linux-procfs.h declaration. */
163
164int
165linux_proc_pid_is_zombie_nowarn (pid_t pid)
166{
167 return linux_proc_pid_is_zombie_maybe_warn (pid, 0);
87b0bb13
JK
168}
169
170/* See linux-procfs.h declaration. */
171
172int
173linux_proc_pid_is_zombie (pid_t pid)
174{
8784d563 175 return linux_proc_pid_is_zombie_maybe_warn (pid, 1);
87b0bb13 176}
015de688
DC
177
178/* See linux-procfs.h declaration. */
179
180char *
181linux_proc_pid_get_ns (pid_t pid, const char *ns)
182{
183 char buf[100];
184 char nsval[64];
185 int ret;
186 xsnprintf (buf, sizeof (buf), "/proc/%d/ns/%s", (int) pid, ns);
187 ret = readlink (buf, nsval, sizeof (nsval));
188 if (0 < ret && ret < sizeof (nsval))
189 {
190 nsval[ret] = '\0';
191 return xstrdup (nsval);
192 }
193
194 return NULL;
195}
8784d563
PA
196
197/* See linux-procfs.h. */
198
199void
200linux_proc_attach_tgid_threads (pid_t pid,
201 linux_proc_attach_lwp_func attach_lwp)
202{
203 DIR *dir;
204 char pathname[128];
205 int new_threads_found;
206 int iterations;
207
208 if (linux_proc_get_tgid (pid) != pid)
209 return;
210
211 xsnprintf (pathname, sizeof (pathname), "/proc/%ld/task", (long) pid);
212 dir = opendir (pathname);
213 if (dir == NULL)
214 {
92fc2e69 215 warning (_("Could not open /proc/%ld/task."), (long) pid);
8784d563
PA
216 return;
217 }
218
219 /* Scan the task list for existing threads. While we go through the
220 threads, new threads may be spawned. Cycle through the list of
221 threads until we have done two iterations without finding new
222 threads. */
223 for (iterations = 0; iterations < 2; iterations++)
224 {
225 struct dirent *dp;
226
227 new_threads_found = 0;
228 while ((dp = readdir (dir)) != NULL)
229 {
230 unsigned long lwp;
231
232 /* Fetch one lwp. */
233 lwp = strtoul (dp->d_name, NULL, 10);
234 if (lwp != 0)
235 {
236 ptid_t ptid = ptid_build (pid, lwp, 0);
237
238 if (attach_lwp (ptid))
239 new_threads_found = 1;
240 }
241 }
242
243 if (new_threads_found)
244 {
245 /* Start over. */
246 iterations = -1;
247 }
248
249 rewinddir (dir);
250 }
251
252 closedir (dir);
253}
This page took 0.266257 seconds and 4 git commands to generate.