]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gdb/nat/linux-procfs.c
gdb/nat/linux: Fix attaching to process when it has zombie threads
[thirdparty/binutils-gdb.git] / gdb / nat / linux-procfs.c
CommitLineData
13da1c97 1/* Linux-specific PROCFS manipulation routines.
1d506c26 2 Copyright (C) 2009-2024 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
13da1c97 19#include "linux-procfs.h"
268a13a5 20#include "gdbsupport/filestuff.h"
8784d563 21#include <dirent.h>
2db9a427 22#include <sys/stat.h>
c930a077
TJB
23#include <unordered_set>
24#include <utility>
13da1c97
LM
25
26/* Return the TGID of LWPID from /proc/pid/status. Returns -1 if not
27 found. */
28
87b0bb13 29static int
8784d563 30linux_proc_get_int (pid_t lwpid, const char *field, int warn)
13da1c97 31{
87b0bb13 32 size_t field_len = strlen (field);
13da1c97 33 char buf[100];
87b0bb13 34 int retval = -1;
13da1c97
LM
35
36 snprintf (buf, sizeof (buf), "/proc/%d/status", (int) lwpid);
d419f42d 37 gdb_file_up 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
d419f42d 45 while (fgets (buf, sizeof (buf), status_file.get ()))
87b0bb13
JK
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
87b0bb13 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
d617208b
PA
72/* Process states as discovered in the 'State' line of
73 /proc/PID/status. Not all possible states are represented here,
74 only those that we care about. */
75
76enum proc_state
77{
78 /* Some state we don't handle. */
79 PROC_STATE_UNKNOWN,
80
81 /* Stopped on a signal. */
82 PROC_STATE_STOPPED,
83
84 /* Tracing stop. */
85 PROC_STATE_TRACING_STOP,
86
87 /* Dead. */
88 PROC_STATE_DEAD,
89
90 /* Zombie. */
91 PROC_STATE_ZOMBIE,
92};
93
94/* Parse a PROC_STATE out of STATE, a buffer with the state found in
95 the 'State:' line of /proc/PID/status. */
96
97static enum proc_state
98parse_proc_status_state (const char *state)
99{
f1735a53 100 state = skip_spaces (state);
d617208b
PA
101
102 switch (state[0])
103 {
0e1a6a51
PA
104 case 't':
105 return PROC_STATE_TRACING_STOP;
d617208b 106 case 'T':
0e1a6a51 107 /* Before Linux 2.6.33, tracing stop used uppercase T. */
5c811d30 108 if (strcmp (state, "T (stopped)\n") == 0)
d617208b 109 return PROC_STATE_STOPPED;
5c811d30
JK
110 else /* "T (tracing stop)\n" */
111 return PROC_STATE_TRACING_STOP;
d617208b
PA
112 case 'X':
113 return PROC_STATE_DEAD;
114 case 'Z':
115 return PROC_STATE_ZOMBIE;
116 }
117
118 return PROC_STATE_UNKNOWN;
119}
120
121
122/* Fill in STATE, a buffer with BUFFER_SIZE bytes with the 'State'
8784d563
PA
123 line of /proc/PID/status. Returns -1 on failure to open the /proc
124 file, 1 if the line is found, and 0 if not found. If WARN, warn on
125 failure to open the /proc file. */
5f572dec 126
87b0bb13 127static int
d617208b 128linux_proc_pid_get_state (pid_t pid, int warn, enum proc_state *state)
5f572dec 129{
5f572dec 130 int have_state;
d617208b 131 char buffer[100];
5f572dec 132
d617208b 133 xsnprintf (buffer, sizeof (buffer), "/proc/%d/status", (int) pid);
d419f42d 134 gdb_file_up procfile = gdb_fopen_cloexec (buffer, "r");
5f572dec
JK
135 if (procfile == NULL)
136 {
8784d563
PA
137 if (warn)
138 warning (_("unable to open /proc file '%s'"), buffer);
139 return -1;
5f572dec
JK
140 }
141
142 have_state = 0;
d419f42d 143 while (fgets (buffer, sizeof (buffer), procfile.get ()) != NULL)
61012eef 144 if (startswith (buffer, "State:"))
5f572dec
JK
145 {
146 have_state = 1;
d617208b 147 *state = parse_proc_status_state (buffer + sizeof ("State:") - 1);
5f572dec
JK
148 break;
149 }
8784d563
PA
150 return have_state;
151}
152
153/* See linux-procfs.h declaration. */
154
155int
156linux_proc_pid_is_gone (pid_t pid)
157{
8784d563 158 int have_state;
d617208b 159 enum proc_state state;
8784d563 160
d617208b 161 have_state = linux_proc_pid_get_state (pid, 0, &state);
8784d563
PA
162 if (have_state < 0)
163 {
164 /* If we can't open the status file, assume the thread has
165 disappeared. */
166 return 1;
167 }
168 else if (have_state == 0)
169 {
170 /* No "State:" line, assume thread is alive. */
171 return 0;
172 }
173 else
d617208b 174 return (state == PROC_STATE_ZOMBIE || state == PROC_STATE_DEAD);
8784d563
PA
175}
176
177/* Return non-zero if 'State' of /proc/PID/status contains STATE. If
178 WARN, warn on failure to open the /proc file. */
179
180static int
d617208b 181linux_proc_pid_has_state (pid_t pid, enum proc_state state, int warn)
8784d563 182{
8784d563 183 int have_state;
d617208b 184 enum proc_state cur_state;
8784d563 185
d617208b
PA
186 have_state = linux_proc_pid_get_state (pid, warn, &cur_state);
187 return (have_state > 0 && cur_state == state);
5f572dec 188}
87b0bb13
JK
189
190/* Detect `T (stopped)' in `/proc/PID/status'.
191 Other states including `T (tracing stop)' are reported as false. */
192
193int
194linux_proc_pid_is_stopped (pid_t pid)
195{
d617208b 196 return linux_proc_pid_has_state (pid, PROC_STATE_STOPPED, 1);
8784d563
PA
197}
198
d617208b 199/* Detect `t (tracing stop)' in `/proc/PID/status'.
23f238d3
PA
200 Other states including `T (stopped)' are reported as false. */
201
202int
203linux_proc_pid_is_trace_stopped_nowarn (pid_t pid)
204{
d617208b 205 return linux_proc_pid_has_state (pid, PROC_STATE_TRACING_STOP, 1);
23f238d3
PA
206}
207
8784d563
PA
208/* Return non-zero if PID is a zombie. If WARN, warn on failure to
209 open the /proc file. */
210
211static int
212linux_proc_pid_is_zombie_maybe_warn (pid_t pid, int warn)
213{
d617208b 214 return linux_proc_pid_has_state (pid, PROC_STATE_ZOMBIE, warn);
8784d563
PA
215}
216
217/* See linux-procfs.h declaration. */
218
219int
220linux_proc_pid_is_zombie_nowarn (pid_t pid)
221{
222 return linux_proc_pid_is_zombie_maybe_warn (pid, 0);
87b0bb13
JK
223}
224
225/* See linux-procfs.h declaration. */
226
227int
228linux_proc_pid_is_zombie (pid_t pid)
229{
8784d563 230 return linux_proc_pid_is_zombie_maybe_warn (pid, 1);
87b0bb13 231}
015de688 232
8784d563
PA
233/* See linux-procfs.h. */
234
16a447be
TJB
235std::optional<std::string>
236linux_proc_get_stat_field (ptid_t ptid, int field)
237{
238 /* We never need to read PID from the stat file, and there's
239 command_from_pid to read the comm field. */
240 gdb_assert (field >= LINUX_PROC_STAT_STATE);
241
242 std::string filename = string_printf ("/proc/%ld/task/%ld/stat",
243 (long) ptid.pid (), (long) ptid.lwp ());
244
245 std::optional<std::string> content
246 = read_text_file_to_string (filename.c_str ());
247 if (!content.has_value ())
248 return {};
249
250 /* ps command also relies on no trailing fields ever containing ')'. */
251 std::string::size_type pos = content->find_last_of (')');
252 if (pos == std::string::npos)
253 return {};
254
255 /* The first field after program name is LINUX_PROC_STAT_STATE. */
256 for (int i = LINUX_PROC_STAT_STATE; i <= field; ++i)
257 {
258 /* Find separator. */
259 pos = content->find_first_of (' ', pos);
260 if (pos == std::string::npos)
261 return {};
262
263 /* Find beginning of field. */
264 pos = content->find_first_not_of (' ', pos);
265 if (pos == std::string::npos)
266 return {};
267 }
268
269 /* Find end of field. */
270 std::string::size_type end_pos = content->find_first_of (' ', pos);
271 if (end_pos == std::string::npos)
272 return content->substr (pos);
273 else
274 return content->substr (pos, end_pos - pos);
275}
276
c930a077
TJB
277/* Get the start time of thread PTID. */
278
279static std::optional<ULONGEST>
280linux_proc_get_starttime (ptid_t ptid)
281{
282 std::optional<std::string> field
283 = linux_proc_get_stat_field (ptid, LINUX_PROC_STAT_STARTTIME);
284
285 if (!field.has_value ())
286 return {};
287
288 errno = 0;
289 const char *trailer;
290 ULONGEST starttime = strtoulst (field->c_str (), &trailer, 10);
291 if (starttime == ULONGEST_MAX && errno == ERANGE)
292 return {};
293 else if (*trailer != '\0')
294 /* There were unexpected characters. */
295 return {};
296
297 return starttime;
298}
299
16a447be
TJB
300/* See linux-procfs.h. */
301
79efa585
SM
302const char *
303linux_proc_tid_get_name (ptid_t ptid)
304{
305#define TASK_COMM_LEN 16 /* As defined in the kernel's sched.h. */
306
307 static char comm_buf[TASK_COMM_LEN];
308 char comm_path[100];
79efa585 309 const char *comm_val;
e99b03dc 310 pid_t pid = ptid.pid ();
15a9e13e 311 pid_t tid = ptid.lwp_p () ? ptid.lwp () : ptid.pid ();
79efa585
SM
312
313 xsnprintf (comm_path, sizeof (comm_path),
314 "/proc/%ld/task/%ld/comm", (long) pid, (long) tid);
315
d419f42d 316 gdb_file_up comm_file = gdb_fopen_cloexec (comm_path, "r");
79efa585
SM
317 if (comm_file == NULL)
318 return NULL;
319
d419f42d 320 comm_val = fgets (comm_buf, sizeof (comm_buf), comm_file.get ());
79efa585
SM
321
322 if (comm_val != NULL)
323 {
324 int i;
325
326 /* Make sure there is no newline at the end. */
327 for (i = 0; i < sizeof (comm_buf); i++)
328 {
329 if (comm_buf[i] == '\n')
330 {
331 comm_buf[i] = '\0';
332 break;
333 }
334 }
335 }
336
337 return comm_val;
338}
339
340/* See linux-procfs.h. */
341
8784d563
PA
342void
343linux_proc_attach_tgid_threads (pid_t pid,
344 linux_proc_attach_lwp_func attach_lwp)
345{
8784d563
PA
346 char pathname[128];
347 int new_threads_found;
348 int iterations;
349
350 if (linux_proc_get_tgid (pid) != pid)
351 return;
352
353 xsnprintf (pathname, sizeof (pathname), "/proc/%ld/task", (long) pid);
596cd22c 354 gdb_dir_up dir (opendir (pathname));
8784d563
PA
355 if (dir == NULL)
356 {
31141b55 357 warning (_("Could not open %s."), pathname);
8784d563
PA
358 return;
359 }
360
c930a077
TJB
361 /* Callable object to hash elements in visited_lpws. */
362 struct pair_hash
363 {
364 std::size_t operator() (const std::pair<unsigned long, ULONGEST> &v) const
365 {
366 return (std::hash<unsigned long>() (v.first)
367 ^ std::hash<ULONGEST>() (v.second));
368 }
369 };
370
371 /* Keeps track of the LWPs we have already visited in /proc,
372 identified by their PID and starttime to detect PID reuse. */
373 std::unordered_set<std::pair<unsigned long, ULONGEST>,
374 pair_hash> visited_lwps;
375
8784d563
PA
376 /* Scan the task list for existing threads. While we go through the
377 threads, new threads may be spawned. Cycle through the list of
378 threads until we have done two iterations without finding new
379 threads. */
380 for (iterations = 0; iterations < 2; iterations++)
381 {
382 struct dirent *dp;
383
384 new_threads_found = 0;
596cd22c 385 while ((dp = readdir (dir.get ())) != NULL)
8784d563
PA
386 {
387 unsigned long lwp;
388
389 /* Fetch one lwp. */
390 lwp = strtoul (dp->d_name, NULL, 10);
391 if (lwp != 0)
392 {
184ea2f7 393 ptid_t ptid = ptid_t (pid, lwp);
c930a077
TJB
394 std::optional<ULONGEST> starttime
395 = linux_proc_get_starttime (ptid);
396
397 if (starttime.has_value ())
398 {
399 std::pair<unsigned long, ULONGEST> key (lwp, *starttime);
400
401 /* If we already visited this LWP, skip it this time. */
402 if (visited_lwps.find (key) != visited_lwps.cend ())
403 continue;
404
405 visited_lwps.insert (key);
406 }
8784d563
PA
407
408 if (attach_lwp (ptid))
409 new_threads_found = 1;
410 }
411 }
412
413 if (new_threads_found)
414 {
415 /* Start over. */
416 iterations = -1;
417 }
418
596cd22c 419 rewinddir (dir.get ());
8784d563 420 }
8784d563 421}
2db9a427
PA
422
423/* See linux-procfs.h. */
424
425int
426linux_proc_task_list_dir_exists (pid_t pid)
427{
428 char pathname[128];
429 struct stat buf;
430
431 xsnprintf (pathname, sizeof (pathname), "/proc/%ld/task", (long) pid);
432 return (stat (pathname, &buf) == 0);
433}
e0d86d2c
GB
434
435/* See linux-procfs.h. */
436
0e90c441 437const char *
e0d86d2c
GB
438linux_proc_pid_to_exec_file (int pid)
439{
440 static char buf[PATH_MAX];
441 char name[PATH_MAX];
442 ssize_t len;
443
444 xsnprintf (name, PATH_MAX, "/proc/%d/exe", pid);
445 len = readlink (name, buf, PATH_MAX - 1);
446 if (len <= 0)
447 strcpy (buf, name);
448 else
449 buf[len] = '\0';
450
e58beedf
AB
451 /* Use /proc/PID/exe if the actual file can't be read, but /proc/PID/exe
452 can be. */
453 if (access (buf, R_OK) != 0 && access (name, R_OK) == 0)
454 strcpy (buf, name);
455
e0d86d2c
GB
456 return buf;
457}
1b919490
VB
458
459/* See linux-procfs.h. */
460
461void
462linux_proc_init_warnings ()
463{
464 static bool warned = false;
465
466 if (warned)
467 return;
468 warned = true;
469
470 struct stat st;
471
472 if (stat ("/proc/self", &st) != 0)
473 warning (_("/proc is not accessible."));
474}