GDBserver

linux-procfs.c
Go to the documentation of this file.
1 /* Linux-specific PROCFS manipulation routines.
2 Copyright (C) 2009-2018 Free Software Foundation, Inc.
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
19 #include "common-defs.h"
20 #include "linux-procfs.h"
21 #include "filestuff.h"
22 #include <dirent.h>
23 #include <sys/stat.h>
24
25 /* Return the TGID of LWPID from /proc/pid/status. Returns -1 if not
26 found. */
27
28 static int
29 linux_proc_get_int (pid_t lwpid, const char *field, int warn)
30 {
31 size_t field_len = strlen (field);
32 char buf[100];
33 int retval = -1;
34
35 snprintf (buf, sizeof (buf), "/proc/%d/status", (int) lwpid);
36 gdb_file_up status_file = gdb_fopen_cloexec (buf, "r");
37 if (status_file == NULL)
38 {
39 if (warn)
40 warning (_("unable to open /proc file '%s'"), buf);
41 return -1;
42 }
43
44 while (fgets (buf, sizeof (buf), status_file.get ()))
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 return retval;
52 }
53
54 /* Return the TGID of LWPID from /proc/pid/status. Returns -1 if not
55 found. */
56
57 int
58 linux_proc_get_tgid (pid_t lwpid)
59 {
60 return linux_proc_get_int (lwpid, "Tgid", 1);
61 }
62
63 /* See linux-procfs.h. */
64
65 pid_t
66 linux_proc_get_tracerpid_nowarn (pid_t lwpid)
67 {
68 return linux_proc_get_int (lwpid, "TracerPid", 0);
69 }
70
71 /* Process states as discovered in the 'State' line of
72 /proc/PID/status. Not all possible states are represented here,
73 only those that we care about. */
74
75 enum proc_state
76 {
77 /* Some state we don't handle. */
78 PROC_STATE_UNKNOWN,
79
80 /* Stopped on a signal. */
81 PROC_STATE_STOPPED,
82
83 /* Tracing stop. */
84 PROC_STATE_TRACING_STOP,
85
86 /* Dead. */
87 PROC_STATE_DEAD,
88
89 /* Zombie. */
90 PROC_STATE_ZOMBIE,
91 };
92
93 /* Parse a PROC_STATE out of STATE, a buffer with the state found in
94 the 'State:' line of /proc/PID/status. */
95
96 static enum proc_state
97 parse_proc_status_state (const char *state)
98 {
99 state = skip_spaces (state);
100
101 switch (state[0])
102 {
103 case 't':
104 return PROC_STATE_TRACING_STOP;
105 case 'T':
106 /* Before Linux 2.6.33, tracing stop used uppercase T. */
107 if (strcmp (state, "T (stopped)\n") == 0)
108 return PROC_STATE_STOPPED;
109 else /* "T (tracing stop)\n" */
110 return PROC_STATE_TRACING_STOP;
111 case 'X':
112 return PROC_STATE_DEAD;
113 case 'Z':
114 return PROC_STATE_ZOMBIE;
115 }
116
117 return PROC_STATE_UNKNOWN;
118 }
119
120
121 /* Fill in STATE, a buffer with BUFFER_SIZE bytes with the 'State'
122 line of /proc/PID/status. Returns -1 on failure to open the /proc
123 file, 1 if the line is found, and 0 if not found. If WARN, warn on
124 failure to open the /proc file. */
125
126 static int
127 linux_proc_pid_get_state (pid_t pid, int warn, enum proc_state *state)
128 {
129 int have_state;
130 char buffer[100];
131
132 xsnprintf (buffer, sizeof (buffer), "/proc/%d/status", (int) pid);
133 gdb_file_up procfile = gdb_fopen_cloexec (buffer, "r");
134 if (procfile == NULL)
135 {
136 if (warn)
137 warning (_("unable to open /proc file '%s'"), buffer);
138 return -1;
139 }
140
141 have_state = 0;
142 while (fgets (buffer, sizeof (buffer), procfile.get ()) != NULL)
143 if (startswith (buffer, "State:"))
144 {
145 have_state = 1;
146 *state = parse_proc_status_state (buffer + sizeof ("State:") - 1);
147 break;
148 }
149 return have_state;
150 }
151
152 /* See linux-procfs.h declaration. */
153
154 int
155 linux_proc_pid_is_gone (pid_t pid)
156 {
157 int have_state;
158 enum proc_state state;
159
160 have_state = linux_proc_pid_get_state (pid, 0, &state);
161 if (have_state < 0)
162 {
163 /* If we can't open the status file, assume the thread has
164 disappeared. */
165 return 1;
166 }
167 else if (have_state == 0)
168 {
169 /* No "State:" line, assume thread is alive. */
170 return 0;
171 }
172 else
173 return (state == PROC_STATE_ZOMBIE || state == PROC_STATE_DEAD);
174 }
175
176 /* Return non-zero if 'State' of /proc/PID/status contains STATE. If
177 WARN, warn on failure to open the /proc file. */
178
179 static int
180 linux_proc_pid_has_state (pid_t pid, enum proc_state state, int warn)
181 {
182 int have_state;
183 enum proc_state cur_state;
184
185 have_state = linux_proc_pid_get_state (pid, warn, &cur_state);
186 return (have_state > 0 && cur_state == state);
187 }
188
189 /* Detect `T (stopped)' in `/proc/PID/status'.
190 Other states including `T (tracing stop)' are reported as false. */
191
192 int
193 linux_proc_pid_is_stopped (pid_t pid)
194 {
195 return linux_proc_pid_has_state (pid, PROC_STATE_STOPPED, 1);
196 }
197
198 /* Detect `t (tracing stop)' in `/proc/PID/status'.
199 Other states including `T (stopped)' are reported as false. */
200
201 int
202 linux_proc_pid_is_trace_stopped_nowarn (pid_t pid)
203 {
204 return linux_proc_pid_has_state (pid, PROC_STATE_TRACING_STOP, 1);
205 }
206
207 /* Return non-zero if PID is a zombie. If WARN, warn on failure to
208 open the /proc file. */
209
210 static int
211 linux_proc_pid_is_zombie_maybe_warn (pid_t pid, int warn)
212 {
213 return linux_proc_pid_has_state (pid, PROC_STATE_ZOMBIE, warn);
214 }
215
216 /* See linux-procfs.h declaration. */
217
218 int
219 linux_proc_pid_is_zombie_nowarn (pid_t pid)
220 {
221 return linux_proc_pid_is_zombie_maybe_warn (pid, 0);
222 }
223
224 /* See linux-procfs.h declaration. */
225
226 int
227 linux_proc_pid_is_zombie (pid_t pid)
228 {
229 return linux_proc_pid_is_zombie_maybe_warn (pid, 1);
230 }
231
232 /* See linux-procfs.h. */
233
234 const char *
235 linux_proc_tid_get_name (ptid_t ptid)
236 {
237 #define TASK_COMM_LEN 16 /* As defined in the kernel's sched.h. */
238
239 static char comm_buf[TASK_COMM_LEN];
240 char comm_path[100];
241 const char *comm_val;
242 pid_t pid = ptid_get_pid (ptid);
243 pid_t tid = ptid_lwp_p (ptid) ? ptid_get_lwp (ptid) : ptid_get_pid (ptid);
244
245 xsnprintf (comm_path, sizeof (comm_path),
246 "/proc/%ld/task/%ld/comm", (long) pid, (long) tid);
247
248 gdb_file_up comm_file = gdb_fopen_cloexec (comm_path, "r");
249 if (comm_file == NULL)
250 return NULL;
251
252 comm_val = fgets (comm_buf, sizeof (comm_buf), comm_file.get ());
253
254 if (comm_val != NULL)
255 {
256 int i;
257
258 /* Make sure there is no newline at the end. */
259 for (i = 0; i < sizeof (comm_buf); i++)
260 {
261 if (comm_buf[i] == '\n')
262 {
263 comm_buf[i] = '\0';
264 break;
265 }
266 }
267 }
268
269 return comm_val;
270 }
271
272 /* See linux-procfs.h. */
273
274 void
275 linux_proc_attach_tgid_threads (pid_t pid,
276 linux_proc_attach_lwp_func attach_lwp)
277 {
278 DIR *dir;
279 char pathname[128];
280 int new_threads_found;
281 int iterations;
282
283 if (linux_proc_get_tgid (pid) != pid)
284 return;
285
286 xsnprintf (pathname, sizeof (pathname), "/proc/%ld/task", (long) pid);
287 dir = opendir (pathname);
288 if (dir == NULL)
289 {
290 warning (_("Could not open /proc/%ld/task."), (long) pid);
291 return;
292 }
293
294 /* Scan the task list for existing threads. While we go through the
295 threads, new threads may be spawned. Cycle through the list of
296 threads until we have done two iterations without finding new
297 threads. */
298 for (iterations = 0; iterations < 2; iterations++)
299 {
300 struct dirent *dp;
301
302 new_threads_found = 0;
303 while ((dp = readdir (dir)) != NULL)
304 {
305 unsigned long lwp;
306
307 /* Fetch one lwp. */
308 lwp = strtoul (dp->d_name, NULL, 10);
309 if (lwp != 0)
310 {
311 ptid_t ptid = ptid_build (pid, lwp, 0);
312
313 if (attach_lwp (ptid))
314 new_threads_found = 1;
315 }
316 }
317
318 if (new_threads_found)
319 {
320 /* Start over. */
321 iterations = -1;
322 }
323
324 rewinddir (dir);
325 }
326
327 closedir (dir);
328 }
329
330 /* See linux-procfs.h. */
331
332 int
333 linux_proc_task_list_dir_exists (pid_t pid)
334 {
335 char pathname[128];
336 struct stat buf;
337
338 xsnprintf (pathname, sizeof (pathname), "/proc/%ld/task", (long) pid);
339 return (stat (pathname, &buf) == 0);
340 }
341
342 /* See linux-procfs.h. */
343
344 char *
345 linux_proc_pid_to_exec_file (int pid)
346 {
347 static char buf[PATH_MAX];
348 char name[PATH_MAX];
349 ssize_t len;
350
351 xsnprintf (name, PATH_MAX, "/proc/%d/exe", pid);
352 len = readlink (name, buf, PATH_MAX - 1);
353 if (len <= 0)
354 strcpy (buf, name);
355 else
356 buf[len] = '\0';
357
358 return buf;
359 }
linux_proc_attach_lwp_func
int(* linux_proc_attach_lwp_func)(ptid_t ptid)
Definition: linux-procfs.h:67
linux_proc_task_list_dir_exists
int linux_proc_task_list_dir_exists(pid_t pid)
Definition: linux-procfs.c:333
ptid_get_pid
int ptid_get_pid(const ptid_t &ptid)
Definition: ptid.c:47
PROC_STATE_STOPPED
Definition: linux-procfs.c:81
warning
void warning(const char *fmt,...)
Definition: errors.c:26
PROC_STATE_DEAD
Definition: linux-procfs.c:87
name
const char * name
Definition: tracepoint.c:180
linux_proc_tid_get_name
const char * linux_proc_tid_get_name(ptid_t ptid)
Definition: linux-procfs.c:235
linux_proc_pid_get_state
static int linux_proc_pid_get_state(pid_t pid, int warn, enum proc_state *state)
Definition: linux-procfs.c:127
skip_spaces
char * skip_spaces(char *chp)
Definition: common-utils.c:337
_
#define _(String)
Definition: gdb_locale.h:35
linux_proc_pid_has_state
static int linux_proc_pid_has_state(pid_t pid, enum proc_state state, int warn)
Definition: linux-procfs.c:180
linux_proc_get_int
static int linux_proc_get_int(pid_t lwpid, const char *field, int warn)
Definition: linux-procfs.c:29
TASK_COMM_LEN
#define TASK_COMM_LEN
dirent.h
linux_proc_pid_is_zombie_nowarn
int linux_proc_pid_is_zombie_nowarn(pid_t pid)
Definition: linux-procfs.c:219
ptid_build
ptid_t ptid_build(int pid, long lwp, long tid)
Definition: ptid.c:31
stat.h
parse_proc_status_state
static enum proc_state parse_proc_status_state(const char *state)
Definition: linux-procfs.c:97
gdb_file_up
std::unique_ptr< FILE, gdb_file_deleter > gdb_file_up
Definition: filestuff.h:59
ptid_t
Definition: ptid.h:35
PROC_STATE_TRACING_STOP
Definition: linux-procfs.c:84
linux_proc_get_tgid
int linux_proc_get_tgid(pid_t lwpid)
Definition: linux-procfs.c:58
linux_proc_pid_is_stopped
int linux_proc_pid_is_stopped(pid_t pid)
Definition: linux-procfs.c:193
linux_proc_pid_to_exec_file
char * linux_proc_pid_to_exec_file(int pid)
Definition: linux-procfs.c:345
common-defs.h
gdb_fopen_cloexec
gdb_file_up gdb_fopen_cloexec(const char *filename, const char *opentype)
Definition: filestuff.c:296
startswith
static int startswith(const char *string, const char *pattern)
Definition: common-utils.h:107
PROC_STATE_ZOMBIE
Definition: linux-procfs.c:90
ptid_get_lwp
long ptid_get_lwp(const ptid_t &ptid)
Definition: ptid.c:55
proc_state
proc_state
Definition: linux-procfs.c:75
ptid_lwp_p
int ptid_lwp_p(const ptid_t &ptid)
Definition: ptid.c:87
linux_proc_pid_is_gone
int linux_proc_pid_is_gone(pid_t pid)
Definition: linux-procfs.c:155
linux-procfs.h
PROC_STATE_UNKNOWN
Definition: linux-procfs.c:78
xsnprintf
int xsnprintf(char *str, size_t size, const char *format,...)
Definition: common-utils.c:134
linux_proc_get_tracerpid_nowarn
pid_t linux_proc_get_tracerpid_nowarn(pid_t lwpid)
Definition: linux-procfs.c:66
buffer
Definition: buffer.h:23
linux_proc_pid_is_zombie
int linux_proc_pid_is_zombie(pid_t pid)
Definition: linux-procfs.c:227
linux_proc_attach_tgid_threads
void linux_proc_attach_tgid_threads(pid_t pid, linux_proc_attach_lwp_func attach_lwp)
Definition: linux-procfs.c:275
linux_proc_pid_is_zombie_maybe_warn
static int linux_proc_pid_is_zombie_maybe_warn(pid_t pid, int warn)
Definition: linux-procfs.c:211
filestuff.h
linux_proc_pid_is_trace_stopped_nowarn
int linux_proc_pid_is_trace_stopped_nowarn(pid_t pid)
Definition: linux-procfs.c:202