]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gdb/nat/linux-procfs.c
Add myself as a write-after-approval GDB maintainer.
[thirdparty/binutils-gdb.git] / gdb / nat / linux-procfs.c
CommitLineData
13da1c97 1/* Linux-specific PROCFS manipulation routines.
618f726f 2 Copyright (C) 2009-2016 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>
2db9a427 23#include <sys/stat.h>
13da1c97
LM
24
25/* Return the TGID of LWPID from /proc/pid/status. Returns -1 if not
26 found. */
27
87b0bb13 28static int
8784d563 29linux_proc_get_int (pid_t lwpid, const char *field, int warn)
13da1c97 30{
87b0bb13 31 size_t field_len = strlen (field);
13da1c97
LM
32 FILE *status_file;
33 char buf[100];
87b0bb13 34 int retval = -1;
13da1c97
LM
35
36 snprintf (buf, sizeof (buf), "/proc/%d/status", (int) lwpid);
614c279d 37 status_file = gdb_fopen_cloexec (buf, "r");
87b0bb13 38 if (status_file == NULL)
13da1c97 39 {
8784d563
PA
40 if (warn)
41 warning (_("unable to open /proc file '%s'"), buf);
87b0bb13 42 return -1;
13da1c97
LM
43 }
44
87b0bb13
JK
45 while (fgets (buf, sizeof (buf), status_file))
46 if (strncmp (buf, field, field_len) == 0 && buf[field_len] == ':')
47 {
48 retval = strtol (&buf[field_len + 1], NULL, 10);
49 break;
50 }
51
52 fclose (status_file);
53 return retval;
13da1c97 54}
644cebc9 55
87b0bb13
JK
56/* Return the TGID of LWPID from /proc/pid/status. Returns -1 if not
57 found. */
644cebc9
PA
58
59int
87b0bb13 60linux_proc_get_tgid (pid_t lwpid)
644cebc9 61{
8784d563 62 return linux_proc_get_int (lwpid, "Tgid", 1);
87b0bb13 63}
644cebc9 64
87b0bb13
JK
65/* See linux-procfs.h. */
66
67pid_t
8784d563 68linux_proc_get_tracerpid_nowarn (pid_t lwpid)
87b0bb13 69{
8784d563 70 return linux_proc_get_int (lwpid, "TracerPid", 0);
644cebc9 71}
5f572dec 72
8784d563
PA
73/* Fill in BUFFER, a buffer with BUFFER_SIZE bytes with the 'State'
74 line of /proc/PID/status. Returns -1 on failure to open the /proc
75 file, 1 if the line is found, and 0 if not found. If WARN, warn on
76 failure to open the /proc file. */
5f572dec 77
87b0bb13 78static int
8784d563
PA
79linux_proc_pid_get_state (pid_t pid, char *buffer, size_t buffer_size,
80 int warn)
5f572dec 81{
5f572dec 82 FILE *procfile;
5f572dec
JK
83 int have_state;
84
8784d563 85 xsnprintf (buffer, buffer_size, "/proc/%d/status", (int) pid);
614c279d 86 procfile = gdb_fopen_cloexec (buffer, "r");
5f572dec
JK
87 if (procfile == NULL)
88 {
8784d563
PA
89 if (warn)
90 warning (_("unable to open /proc file '%s'"), buffer);
91 return -1;
5f572dec
JK
92 }
93
94 have_state = 0;
8784d563 95 while (fgets (buffer, buffer_size, procfile) != NULL)
61012eef 96 if (startswith (buffer, "State:"))
5f572dec
JK
97 {
98 have_state = 1;
99 break;
100 }
5f572dec 101 fclose (procfile);
8784d563
PA
102 return have_state;
103}
104
105/* See linux-procfs.h declaration. */
106
107int
108linux_proc_pid_is_gone (pid_t pid)
109{
110 char buffer[100];
111 int have_state;
112
113 have_state = linux_proc_pid_get_state (pid, buffer, sizeof buffer, 0);
114 if (have_state < 0)
115 {
116 /* If we can't open the status file, assume the thread has
117 disappeared. */
118 return 1;
119 }
120 else if (have_state == 0)
121 {
122 /* No "State:" line, assume thread is alive. */
123 return 0;
124 }
125 else
126 {
127 return (strstr (buffer, "Z (") != NULL
128 || strstr (buffer, "X (") != NULL);
129 }
130}
131
132/* Return non-zero if 'State' of /proc/PID/status contains STATE. If
133 WARN, warn on failure to open the /proc file. */
134
135static int
136linux_proc_pid_has_state (pid_t pid, const char *state, int warn)
137{
138 char buffer[100];
139 int have_state;
140
141 have_state = linux_proc_pid_get_state (pid, buffer, sizeof buffer, warn);
142 return (have_state > 0 && strstr (buffer, state) != NULL);
5f572dec 143}
87b0bb13
JK
144
145/* Detect `T (stopped)' in `/proc/PID/status'.
146 Other states including `T (tracing stop)' are reported as false. */
147
148int
149linux_proc_pid_is_stopped (pid_t pid)
150{
8784d563
PA
151 return linux_proc_pid_has_state (pid, "T (stopped)", 1);
152}
153
23f238d3
PA
154/* Detect `T (tracing stop)' in `/proc/PID/status'.
155 Other states including `T (stopped)' are reported as false. */
156
157int
158linux_proc_pid_is_trace_stopped_nowarn (pid_t pid)
159{
160 return linux_proc_pid_has_state (pid, "T (tracing stop)", 1);
161}
162
8784d563
PA
163/* Return non-zero if PID is a zombie. If WARN, warn on failure to
164 open the /proc file. */
165
166static int
167linux_proc_pid_is_zombie_maybe_warn (pid_t pid, int warn)
168{
169 return linux_proc_pid_has_state (pid, "Z (zombie)", warn);
170}
171
172/* See linux-procfs.h declaration. */
173
174int
175linux_proc_pid_is_zombie_nowarn (pid_t pid)
176{
177 return linux_proc_pid_is_zombie_maybe_warn (pid, 0);
87b0bb13
JK
178}
179
180/* See linux-procfs.h declaration. */
181
182int
183linux_proc_pid_is_zombie (pid_t pid)
184{
8784d563 185 return linux_proc_pid_is_zombie_maybe_warn (pid, 1);
87b0bb13 186}
015de688 187
8784d563
PA
188/* See linux-procfs.h. */
189
79efa585
SM
190const char *
191linux_proc_tid_get_name (ptid_t ptid)
192{
193#define TASK_COMM_LEN 16 /* As defined in the kernel's sched.h. */
194
195 static char comm_buf[TASK_COMM_LEN];
196 char comm_path[100];
197 FILE *comm_file;
198 const char *comm_val;
199 pid_t pid = ptid_get_pid (ptid);
200 pid_t tid = ptid_lwp_p (ptid) ? ptid_get_lwp (ptid) : ptid_get_pid (ptid);
201
202 xsnprintf (comm_path, sizeof (comm_path),
203 "/proc/%ld/task/%ld/comm", (long) pid, (long) tid);
204
205 comm_file = gdb_fopen_cloexec (comm_path, "r");
206 if (comm_file == NULL)
207 return NULL;
208
209 comm_val = fgets (comm_buf, sizeof (comm_buf), comm_file);
210 fclose (comm_file);
211
212 if (comm_val != NULL)
213 {
214 int i;
215
216 /* Make sure there is no newline at the end. */
217 for (i = 0; i < sizeof (comm_buf); i++)
218 {
219 if (comm_buf[i] == '\n')
220 {
221 comm_buf[i] = '\0';
222 break;
223 }
224 }
225 }
226
227 return comm_val;
228}
229
230/* See linux-procfs.h. */
231
8784d563
PA
232void
233linux_proc_attach_tgid_threads (pid_t pid,
234 linux_proc_attach_lwp_func attach_lwp)
235{
236 DIR *dir;
237 char pathname[128];
238 int new_threads_found;
239 int iterations;
240
241 if (linux_proc_get_tgid (pid) != pid)
242 return;
243
244 xsnprintf (pathname, sizeof (pathname), "/proc/%ld/task", (long) pid);
245 dir = opendir (pathname);
246 if (dir == NULL)
247 {
92fc2e69 248 warning (_("Could not open /proc/%ld/task."), (long) pid);
8784d563
PA
249 return;
250 }
251
252 /* Scan the task list for existing threads. While we go through the
253 threads, new threads may be spawned. Cycle through the list of
254 threads until we have done two iterations without finding new
255 threads. */
256 for (iterations = 0; iterations < 2; iterations++)
257 {
258 struct dirent *dp;
259
260 new_threads_found = 0;
261 while ((dp = readdir (dir)) != NULL)
262 {
263 unsigned long lwp;
264
265 /* Fetch one lwp. */
266 lwp = strtoul (dp->d_name, NULL, 10);
267 if (lwp != 0)
268 {
269 ptid_t ptid = ptid_build (pid, lwp, 0);
270
271 if (attach_lwp (ptid))
272 new_threads_found = 1;
273 }
274 }
275
276 if (new_threads_found)
277 {
278 /* Start over. */
279 iterations = -1;
280 }
281
282 rewinddir (dir);
283 }
284
285 closedir (dir);
286}
2db9a427
PA
287
288/* See linux-procfs.h. */
289
290int
291linux_proc_task_list_dir_exists (pid_t pid)
292{
293 char pathname[128];
294 struct stat buf;
295
296 xsnprintf (pathname, sizeof (pathname), "/proc/%ld/task", (long) pid);
297 return (stat (pathname, &buf) == 0);
298}
e0d86d2c
GB
299
300/* See linux-procfs.h. */
301
302char *
303linux_proc_pid_to_exec_file (int pid)
304{
305 static char buf[PATH_MAX];
306 char name[PATH_MAX];
307 ssize_t len;
308
309 xsnprintf (name, PATH_MAX, "/proc/%d/exe", pid);
310 len = readlink (name, buf, PATH_MAX - 1);
311 if (len <= 0)
312 strcpy (buf, name);
313 else
314 buf[len] = '\0';
315
316 return buf;
317}