1 /* Linux-specific PROCFS manipulation routines.
2 Copyright (C) 2009-2024 Free Software Foundation, Inc.
4 This file is part of GDB.
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.
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.
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/>. */
19 #include "linux-procfs.h"
20 #include "gdbsupport/filestuff.h"
23 #include <unordered_set>
26 /* Return the TGID of LWPID from /proc/pid/status. Returns -1 if not
30 linux_proc_get_int (pid_t lwpid
, const char *field
, int warn
)
32 size_t field_len
= strlen (field
);
36 snprintf (buf
, sizeof (buf
), "/proc/%d/status", (int) lwpid
);
37 gdb_file_up status_file
= gdb_fopen_cloexec (buf
, "r");
38 if (status_file
== NULL
)
41 warning (_("unable to open /proc file '%s'"), buf
);
45 while (fgets (buf
, sizeof (buf
), status_file
.get ()))
46 if (strncmp (buf
, field
, field_len
) == 0 && buf
[field_len
] == ':')
48 retval
= strtol (&buf
[field_len
+ 1], NULL
, 10);
55 /* Return the TGID of LWPID from /proc/pid/status. Returns -1 if not
59 linux_proc_get_tgid (pid_t lwpid
)
61 return linux_proc_get_int (lwpid
, "Tgid", 1);
64 /* See linux-procfs.h. */
67 linux_proc_get_tracerpid_nowarn (pid_t lwpid
)
69 return linux_proc_get_int (lwpid
, "TracerPid", 0);
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. */
78 /* Some state we don't handle. */
81 /* Stopped on a signal. */
85 PROC_STATE_TRACING_STOP
,
94 /* Parse a PROC_STATE out of STATE, a buffer with the state found in
95 the 'State:' line of /proc/PID/status. */
97 static enum proc_state
98 parse_proc_status_state (const char *state
)
100 state
= skip_spaces (state
);
105 return PROC_STATE_TRACING_STOP
;
107 /* Before Linux 2.6.33, tracing stop used uppercase T. */
108 if (strcmp (state
, "T (stopped)\n") == 0)
109 return PROC_STATE_STOPPED
;
110 else /* "T (tracing stop)\n" */
111 return PROC_STATE_TRACING_STOP
;
113 return PROC_STATE_DEAD
;
115 return PROC_STATE_ZOMBIE
;
118 return PROC_STATE_UNKNOWN
;
122 /* Fill in STATE, a buffer with BUFFER_SIZE bytes with the 'State'
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. */
128 linux_proc_pid_get_state (pid_t pid
, int warn
, enum proc_state
*state
)
133 xsnprintf (buffer
, sizeof (buffer
), "/proc/%d/status", (int) pid
);
134 gdb_file_up procfile
= gdb_fopen_cloexec (buffer
, "r");
135 if (procfile
== NULL
)
138 warning (_("unable to open /proc file '%s'"), buffer
);
143 while (fgets (buffer
, sizeof (buffer
), procfile
.get ()) != NULL
)
144 if (startswith (buffer
, "State:"))
147 *state
= parse_proc_status_state (buffer
+ sizeof ("State:") - 1);
153 /* See linux-procfs.h declaration. */
156 linux_proc_pid_is_gone (pid_t pid
)
159 enum proc_state state
;
161 have_state
= linux_proc_pid_get_state (pid
, 0, &state
);
164 /* If we can't open the status file, assume the thread has
168 else if (have_state
== 0)
170 /* No "State:" line, assume thread is alive. */
174 return (state
== PROC_STATE_ZOMBIE
|| state
== PROC_STATE_DEAD
);
177 /* Return non-zero if 'State' of /proc/PID/status contains STATE. If
178 WARN, warn on failure to open the /proc file. */
181 linux_proc_pid_has_state (pid_t pid
, enum proc_state state
, int warn
)
184 enum proc_state cur_state
;
186 have_state
= linux_proc_pid_get_state (pid
, warn
, &cur_state
);
187 return (have_state
> 0 && cur_state
== state
);
190 /* Detect `T (stopped)' in `/proc/PID/status'.
191 Other states including `T (tracing stop)' are reported as false. */
194 linux_proc_pid_is_stopped (pid_t pid
)
196 return linux_proc_pid_has_state (pid
, PROC_STATE_STOPPED
, 1);
199 /* Detect `t (tracing stop)' in `/proc/PID/status'.
200 Other states including `T (stopped)' are reported as false. */
203 linux_proc_pid_is_trace_stopped_nowarn (pid_t pid
)
205 return linux_proc_pid_has_state (pid
, PROC_STATE_TRACING_STOP
, 1);
208 /* Return non-zero if PID is a zombie. If WARN, warn on failure to
209 open the /proc file. */
212 linux_proc_pid_is_zombie_maybe_warn (pid_t pid
, int warn
)
214 return linux_proc_pid_has_state (pid
, PROC_STATE_ZOMBIE
, warn
);
217 /* See linux-procfs.h declaration. */
220 linux_proc_pid_is_zombie_nowarn (pid_t pid
)
222 return linux_proc_pid_is_zombie_maybe_warn (pid
, 0);
225 /* See linux-procfs.h declaration. */
228 linux_proc_pid_is_zombie (pid_t pid
)
230 return linux_proc_pid_is_zombie_maybe_warn (pid
, 1);
233 /* See linux-procfs.h. */
235 std::optional
<std::string
>
236 linux_proc_get_stat_field (ptid_t ptid
, int field
)
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
);
242 std::string filename
= string_printf ("/proc/%ld/task/%ld/stat",
243 (long) ptid
.pid (), (long) ptid
.lwp ());
245 std::optional
<std::string
> content
246 = read_text_file_to_string (filename
.c_str ());
247 if (!content
.has_value ())
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
)
255 /* The first field after program name is LINUX_PROC_STAT_STATE. */
256 for (int i
= LINUX_PROC_STAT_STATE
; i
<= field
; ++i
)
258 /* Find separator. */
259 pos
= content
->find_first_of (' ', pos
);
260 if (pos
== std::string::npos
)
263 /* Find beginning of field. */
264 pos
= content
->find_first_not_of (' ', pos
);
265 if (pos
== std::string::npos
)
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
);
274 return content
->substr (pos
, end_pos
- pos
);
277 /* Get the start time of thread PTID. */
279 static std::optional
<ULONGEST
>
280 linux_proc_get_starttime (ptid_t ptid
)
282 std::optional
<std::string
> field
283 = linux_proc_get_stat_field (ptid
, LINUX_PROC_STAT_STARTTIME
);
285 if (!field
.has_value ())
290 ULONGEST starttime
= strtoulst (field
->c_str (), &trailer
, 10);
291 if (starttime
== ULONGEST_MAX
&& errno
== ERANGE
)
293 else if (*trailer
!= '\0')
294 /* There were unexpected characters. */
300 /* See linux-procfs.h. */
303 linux_proc_tid_get_name (ptid_t ptid
)
305 #define TASK_COMM_LEN 16 /* As defined in the kernel's sched.h. */
307 static char comm_buf
[TASK_COMM_LEN
];
309 const char *comm_val
;
310 pid_t pid
= ptid
.pid ();
311 pid_t tid
= ptid
.lwp_p () ? ptid
.lwp () : ptid
.pid ();
313 xsnprintf (comm_path
, sizeof (comm_path
),
314 "/proc/%ld/task/%ld/comm", (long) pid
, (long) tid
);
316 gdb_file_up comm_file
= gdb_fopen_cloexec (comm_path
, "r");
317 if (comm_file
== NULL
)
320 comm_val
= fgets (comm_buf
, sizeof (comm_buf
), comm_file
.get ());
322 if (comm_val
!= NULL
)
326 /* Make sure there is no newline at the end. */
327 for (i
= 0; i
< sizeof (comm_buf
); i
++)
329 if (comm_buf
[i
] == '\n')
340 /* See linux-procfs.h. */
343 linux_proc_attach_tgid_threads (pid_t pid
,
344 linux_proc_attach_lwp_func attach_lwp
)
347 int new_threads_found
;
350 if (linux_proc_get_tgid (pid
) != pid
)
353 xsnprintf (pathname
, sizeof (pathname
), "/proc/%ld/task", (long) pid
);
354 gdb_dir_up
dir (opendir (pathname
));
357 warning (_("Could not open %s."), pathname
);
361 /* Callable object to hash elements in visited_lpws. */
364 std::size_t operator() (const std::pair
<unsigned long, ULONGEST
> &v
) const
366 return (std::hash
<unsigned long>() (v
.first
)
367 ^ std::hash
<ULONGEST
>() (v
.second
));
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
;
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
380 for (iterations
= 0; iterations
< 2; iterations
++)
384 new_threads_found
= 0;
385 while ((dp
= readdir (dir
.get ())) != NULL
)
390 lwp
= strtoul (dp
->d_name
, NULL
, 10);
393 ptid_t ptid
= ptid_t (pid
, lwp
);
394 std::optional
<ULONGEST
> starttime
395 = linux_proc_get_starttime (ptid
);
397 if (starttime
.has_value ())
399 std::pair
<unsigned long, ULONGEST
> key (lwp
, *starttime
);
401 /* If we already visited this LWP, skip it this time. */
402 if (visited_lwps
.find (key
) != visited_lwps
.cend ())
405 visited_lwps
.insert (key
);
408 if (attach_lwp (ptid
))
409 new_threads_found
= 1;
413 if (new_threads_found
)
419 rewinddir (dir
.get ());
423 /* See linux-procfs.h. */
426 linux_proc_task_list_dir_exists (pid_t pid
)
431 xsnprintf (pathname
, sizeof (pathname
), "/proc/%ld/task", (long) pid
);
432 return (stat (pathname
, &buf
) == 0);
435 /* See linux-procfs.h. */
438 linux_proc_pid_to_exec_file (int pid
)
440 static char buf
[PATH_MAX
];
444 xsnprintf (name
, PATH_MAX
, "/proc/%d/exe", pid
);
445 len
= readlink (name
, buf
, PATH_MAX
- 1);
451 /* Use /proc/PID/exe if the actual file can't be read, but /proc/PID/exe
453 if (access (buf
, R_OK
) != 0 && access (name
, R_OK
) == 0)
459 /* See linux-procfs.h. */
462 linux_proc_init_warnings ()
464 static bool warned
= false;
472 if (stat ("/proc/self", &st
) != 0)
473 warning (_("/proc is not accessible."));