gdb: Make ldirname return a std::string
[deliverable/binutils-gdb.git] / gdb / nat / linux-procfs.c
CommitLineData
13da1c97 1/* Linux-specific PROCFS manipulation routines.
61baf725 2 Copyright (C) 2009-2017 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
d617208b
PA
73/* Process states as discovered in the 'State' line of
74 /proc/PID/status. Not all possible states are represented here,
75 only those that we care about. */
76
77enum proc_state
78{
79 /* Some state we don't handle. */
80 PROC_STATE_UNKNOWN,
81
82 /* Stopped on a signal. */
83 PROC_STATE_STOPPED,
84
85 /* Tracing stop. */
86 PROC_STATE_TRACING_STOP,
87
88 /* Dead. */
89 PROC_STATE_DEAD,
90
91 /* Zombie. */
92 PROC_STATE_ZOMBIE,
93};
94
95/* Parse a PROC_STATE out of STATE, a buffer with the state found in
96 the 'State:' line of /proc/PID/status. */
97
98static enum proc_state
99parse_proc_status_state (const char *state)
100{
101 state = skip_spaces_const (state);
102
103 switch (state[0])
104 {
0e1a6a51
PA
105 case 't':
106 return PROC_STATE_TRACING_STOP;
d617208b 107 case 'T':
0e1a6a51 108 /* Before Linux 2.6.33, tracing stop used uppercase T. */
d617208b
PA
109 if (strcmp (state, "T (tracing stop)") == 0)
110 return PROC_STATE_TRACING_STOP;
111 else
112 return PROC_STATE_STOPPED;
113 case 'X':
114 return PROC_STATE_DEAD;
115 case 'Z':
116 return PROC_STATE_ZOMBIE;
117 }
118
119 return PROC_STATE_UNKNOWN;
120}
121
122
123/* Fill in STATE, a buffer with BUFFER_SIZE bytes with the 'State'
8784d563
PA
124 line of /proc/PID/status. Returns -1 on failure to open the /proc
125 file, 1 if the line is found, and 0 if not found. If WARN, warn on
126 failure to open the /proc file. */
5f572dec 127
87b0bb13 128static int
d617208b 129linux_proc_pid_get_state (pid_t pid, int warn, enum proc_state *state)
5f572dec 130{
5f572dec 131 FILE *procfile;
5f572dec 132 int have_state;
d617208b 133 char buffer[100];
5f572dec 134
d617208b 135 xsnprintf (buffer, sizeof (buffer), "/proc/%d/status", (int) pid);
614c279d 136 procfile = gdb_fopen_cloexec (buffer, "r");
5f572dec
JK
137 if (procfile == NULL)
138 {
8784d563
PA
139 if (warn)
140 warning (_("unable to open /proc file '%s'"), buffer);
141 return -1;
5f572dec
JK
142 }
143
144 have_state = 0;
d617208b 145 while (fgets (buffer, sizeof (buffer), procfile) != NULL)
61012eef 146 if (startswith (buffer, "State:"))
5f572dec
JK
147 {
148 have_state = 1;
d617208b 149 *state = parse_proc_status_state (buffer + sizeof ("State:") - 1);
5f572dec
JK
150 break;
151 }
5f572dec 152 fclose (procfile);
8784d563
PA
153 return have_state;
154}
155
156/* See linux-procfs.h declaration. */
157
158int
159linux_proc_pid_is_gone (pid_t pid)
160{
8784d563 161 int have_state;
d617208b 162 enum proc_state state;
8784d563 163
d617208b 164 have_state = linux_proc_pid_get_state (pid, 0, &state);
8784d563
PA
165 if (have_state < 0)
166 {
167 /* If we can't open the status file, assume the thread has
168 disappeared. */
169 return 1;
170 }
171 else if (have_state == 0)
172 {
173 /* No "State:" line, assume thread is alive. */
174 return 0;
175 }
176 else
d617208b 177 return (state == PROC_STATE_ZOMBIE || state == PROC_STATE_DEAD);
8784d563
PA
178}
179
180/* Return non-zero if 'State' of /proc/PID/status contains STATE. If
181 WARN, warn on failure to open the /proc file. */
182
183static int
d617208b 184linux_proc_pid_has_state (pid_t pid, enum proc_state state, int warn)
8784d563 185{
8784d563 186 int have_state;
d617208b 187 enum proc_state cur_state;
8784d563 188
d617208b
PA
189 have_state = linux_proc_pid_get_state (pid, warn, &cur_state);
190 return (have_state > 0 && cur_state == state);
5f572dec 191}
87b0bb13
JK
192
193/* Detect `T (stopped)' in `/proc/PID/status'.
194 Other states including `T (tracing stop)' are reported as false. */
195
196int
197linux_proc_pid_is_stopped (pid_t pid)
198{
d617208b 199 return linux_proc_pid_has_state (pid, PROC_STATE_STOPPED, 1);
8784d563
PA
200}
201
d617208b 202/* Detect `t (tracing stop)' in `/proc/PID/status'.
23f238d3
PA
203 Other states including `T (stopped)' are reported as false. */
204
205int
206linux_proc_pid_is_trace_stopped_nowarn (pid_t pid)
207{
d617208b 208 return linux_proc_pid_has_state (pid, PROC_STATE_TRACING_STOP, 1);
23f238d3
PA
209}
210
8784d563
PA
211/* Return non-zero if PID is a zombie. If WARN, warn on failure to
212 open the /proc file. */
213
214static int
215linux_proc_pid_is_zombie_maybe_warn (pid_t pid, int warn)
216{
d617208b 217 return linux_proc_pid_has_state (pid, PROC_STATE_ZOMBIE, warn);
8784d563
PA
218}
219
220/* See linux-procfs.h declaration. */
221
222int
223linux_proc_pid_is_zombie_nowarn (pid_t pid)
224{
225 return linux_proc_pid_is_zombie_maybe_warn (pid, 0);
87b0bb13
JK
226}
227
228/* See linux-procfs.h declaration. */
229
230int
231linux_proc_pid_is_zombie (pid_t pid)
232{
8784d563 233 return linux_proc_pid_is_zombie_maybe_warn (pid, 1);
87b0bb13 234}
015de688 235
8784d563
PA
236/* See linux-procfs.h. */
237
79efa585
SM
238const char *
239linux_proc_tid_get_name (ptid_t ptid)
240{
241#define TASK_COMM_LEN 16 /* As defined in the kernel's sched.h. */
242
243 static char comm_buf[TASK_COMM_LEN];
244 char comm_path[100];
245 FILE *comm_file;
246 const char *comm_val;
247 pid_t pid = ptid_get_pid (ptid);
248 pid_t tid = ptid_lwp_p (ptid) ? ptid_get_lwp (ptid) : ptid_get_pid (ptid);
249
250 xsnprintf (comm_path, sizeof (comm_path),
251 "/proc/%ld/task/%ld/comm", (long) pid, (long) tid);
252
253 comm_file = gdb_fopen_cloexec (comm_path, "r");
254 if (comm_file == NULL)
255 return NULL;
256
257 comm_val = fgets (comm_buf, sizeof (comm_buf), comm_file);
258 fclose (comm_file);
259
260 if (comm_val != NULL)
261 {
262 int i;
263
264 /* Make sure there is no newline at the end. */
265 for (i = 0; i < sizeof (comm_buf); i++)
266 {
267 if (comm_buf[i] == '\n')
268 {
269 comm_buf[i] = '\0';
270 break;
271 }
272 }
273 }
274
275 return comm_val;
276}
277
278/* See linux-procfs.h. */
279
8784d563
PA
280void
281linux_proc_attach_tgid_threads (pid_t pid,
282 linux_proc_attach_lwp_func attach_lwp)
283{
284 DIR *dir;
285 char pathname[128];
286 int new_threads_found;
287 int iterations;
288
289 if (linux_proc_get_tgid (pid) != pid)
290 return;
291
292 xsnprintf (pathname, sizeof (pathname), "/proc/%ld/task", (long) pid);
293 dir = opendir (pathname);
294 if (dir == NULL)
295 {
92fc2e69 296 warning (_("Could not open /proc/%ld/task."), (long) pid);
8784d563
PA
297 return;
298 }
299
300 /* Scan the task list for existing threads. While we go through the
301 threads, new threads may be spawned. Cycle through the list of
302 threads until we have done two iterations without finding new
303 threads. */
304 for (iterations = 0; iterations < 2; iterations++)
305 {
306 struct dirent *dp;
307
308 new_threads_found = 0;
309 while ((dp = readdir (dir)) != NULL)
310 {
311 unsigned long lwp;
312
313 /* Fetch one lwp. */
314 lwp = strtoul (dp->d_name, NULL, 10);
315 if (lwp != 0)
316 {
317 ptid_t ptid = ptid_build (pid, lwp, 0);
318
319 if (attach_lwp (ptid))
320 new_threads_found = 1;
321 }
322 }
323
324 if (new_threads_found)
325 {
326 /* Start over. */
327 iterations = -1;
328 }
329
330 rewinddir (dir);
331 }
332
333 closedir (dir);
334}
2db9a427
PA
335
336/* See linux-procfs.h. */
337
338int
339linux_proc_task_list_dir_exists (pid_t pid)
340{
341 char pathname[128];
342 struct stat buf;
343
344 xsnprintf (pathname, sizeof (pathname), "/proc/%ld/task", (long) pid);
345 return (stat (pathname, &buf) == 0);
346}
e0d86d2c
GB
347
348/* See linux-procfs.h. */
349
350char *
351linux_proc_pid_to_exec_file (int pid)
352{
353 static char buf[PATH_MAX];
354 char name[PATH_MAX];
355 ssize_t len;
356
357 xsnprintf (name, PATH_MAX, "/proc/%d/exe", pid);
358 len = readlink (name, buf, PATH_MAX - 1);
359 if (len <= 0)
360 strcpy (buf, name);
361 else
362 buf[len] = '\0';
363
364 return buf;
365}
This page took 0.434556 seconds and 4 git commands to generate.