]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - gdb/nat/linux-procfs.c
RISC-V: [gprofng] Allow building gprofng without asm/hwprobe.h
[thirdparty/binutils-gdb.git] / gdb / nat / linux-procfs.c
1 /* Linux-specific PROCFS manipulation routines.
2 Copyright (C) 2009-2025 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 "linux-procfs.h"
20 #include "gdbsupport/filestuff.h"
21 #include "gdbsupport/unordered_set.h"
22 #include <dirent.h>
23 #include <sys/stat.h>
24 #include <utility>
25
26 /* Return the TGID of LWPID from /proc/pid/status. Returns -1 if not
27 found. */
28
29 static int
30 linux_proc_get_int (pid_t lwpid, const char *field, int warn)
31 {
32 size_t field_len = strlen (field);
33 char buf[100];
34 int retval = -1;
35
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)
39 {
40 if (warn)
41 warning (_("unable to open /proc file '%s'"), buf);
42 return -1;
43 }
44
45 while (fgets (buf, sizeof (buf), status_file.get ()))
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 return retval;
53 }
54
55 /* Return the TGID of LWPID from /proc/pid/status. Returns -1 if not
56 found. */
57
58 int
59 linux_proc_get_tgid (pid_t lwpid)
60 {
61 return linux_proc_get_int (lwpid, "Tgid", 1);
62 }
63
64 /* See linux-procfs.h. */
65
66 pid_t
67 linux_proc_get_tracerpid_nowarn (pid_t lwpid)
68 {
69 return linux_proc_get_int (lwpid, "TracerPid", 0);
70 }
71
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
76 enum 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
97 static enum proc_state
98 parse_proc_status_state (const char *state)
99 {
100 state = skip_spaces (state);
101
102 switch (state[0])
103 {
104 case 't':
105 return PROC_STATE_TRACING_STOP;
106 case 'T':
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;
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'
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. */
126
127 static int
128 linux_proc_pid_get_state (pid_t pid, int warn, enum proc_state *state)
129 {
130 int have_state;
131 char buffer[100];
132
133 xsnprintf (buffer, sizeof (buffer), "/proc/%d/status", (int) pid);
134 gdb_file_up procfile = gdb_fopen_cloexec (buffer, "r");
135 if (procfile == NULL)
136 {
137 if (warn)
138 warning (_("unable to open /proc file '%s'"), buffer);
139 return -1;
140 }
141
142 have_state = 0;
143 while (fgets (buffer, sizeof (buffer), procfile.get ()) != NULL)
144 if (startswith (buffer, "State:"))
145 {
146 have_state = 1;
147 *state = parse_proc_status_state (buffer + sizeof ("State:") - 1);
148 break;
149 }
150 return have_state;
151 }
152
153 /* See linux-procfs.h declaration. */
154
155 int
156 linux_proc_pid_is_gone (pid_t pid)
157 {
158 int have_state;
159 enum proc_state state;
160
161 have_state = linux_proc_pid_get_state (pid, 0, &state);
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
174 return (state == PROC_STATE_ZOMBIE || state == PROC_STATE_DEAD);
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
180 static int
181 linux_proc_pid_has_state (pid_t pid, enum proc_state state, int warn)
182 {
183 int have_state;
184 enum proc_state cur_state;
185
186 have_state = linux_proc_pid_get_state (pid, warn, &cur_state);
187 return (have_state > 0 && cur_state == state);
188 }
189
190 /* Detect `T (stopped)' in `/proc/PID/status'.
191 Other states including `T (tracing stop)' are reported as false. */
192
193 int
194 linux_proc_pid_is_stopped (pid_t pid)
195 {
196 return linux_proc_pid_has_state (pid, PROC_STATE_STOPPED, 1);
197 }
198
199 /* Detect `t (tracing stop)' in `/proc/PID/status'.
200 Other states including `T (stopped)' are reported as false. */
201
202 int
203 linux_proc_pid_is_trace_stopped_nowarn (pid_t pid)
204 {
205 return linux_proc_pid_has_state (pid, PROC_STATE_TRACING_STOP, 1);
206 }
207
208 /* Return non-zero if PID is a zombie. If WARN, warn on failure to
209 open the /proc file. */
210
211 static int
212 linux_proc_pid_is_zombie_maybe_warn (pid_t pid, int warn)
213 {
214 return linux_proc_pid_has_state (pid, PROC_STATE_ZOMBIE, warn);
215 }
216
217 /* See linux-procfs.h declaration. */
218
219 int
220 linux_proc_pid_is_zombie_nowarn (pid_t pid)
221 {
222 return linux_proc_pid_is_zombie_maybe_warn (pid, 0);
223 }
224
225 /* See linux-procfs.h declaration. */
226
227 int
228 linux_proc_pid_is_zombie (pid_t pid)
229 {
230 return linux_proc_pid_is_zombie_maybe_warn (pid, 1);
231 }
232
233 /* See linux-procfs.h. */
234
235 std::optional<std::string>
236 linux_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
277 /* Get the start time of thread PTID. */
278
279 static std::optional<ULONGEST>
280 linux_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
300 /* See linux-procfs.h. */
301
302 const char *
303 linux_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];
309 const char *comm_val;
310 pid_t pid = ptid.pid ();
311 pid_t tid = ptid.lwp_p () ? ptid.lwp () : ptid.pid ();
312
313 xsnprintf (comm_path, sizeof (comm_path),
314 "/proc/%ld/task/%ld/comm", (long) pid, (long) tid);
315
316 gdb_file_up comm_file = gdb_fopen_cloexec (comm_path, "r");
317 if (comm_file == NULL)
318 return NULL;
319
320 comm_val = fgets (comm_buf, sizeof (comm_buf), comm_file.get ());
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
342 void
343 linux_proc_attach_tgid_threads (pid_t pid,
344 linux_proc_attach_lwp_func attach_lwp)
345 {
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);
354 gdb_dir_up dir (opendir (pathname));
355 if (dir == NULL)
356 {
357 warning (_("Could not open %s."), pathname);
358 return;
359 }
360
361 /* Keeps track of the LWPs we have already visited in /proc,
362 identified by their PID and starttime to detect PID reuse. */
363 gdb::unordered_set<std::pair<unsigned long, ULONGEST>> visited_lwps;
364
365 /* Scan the task list for existing threads. While we go through the
366 threads, new threads may be spawned. Cycle through the list of
367 threads until we have done two iterations without finding new
368 threads. */
369 for (iterations = 0; iterations < 2; iterations++)
370 {
371 struct dirent *dp;
372
373 new_threads_found = 0;
374 while ((dp = readdir (dir.get ())) != NULL)
375 {
376 unsigned long lwp;
377
378 /* Fetch one lwp. */
379 lwp = strtoul (dp->d_name, NULL, 10);
380 if (lwp != 0)
381 {
382 ptid_t ptid = ptid_t (pid, lwp);
383 std::optional<ULONGEST> starttime
384 = linux_proc_get_starttime (ptid);
385
386 if (starttime.has_value ())
387 {
388 std::pair<unsigned long, ULONGEST> key (lwp, *starttime);
389
390 /* If we already visited this LWP, skip it this time. */
391 if (visited_lwps.find (key) != visited_lwps.cend ())
392 continue;
393
394 visited_lwps.insert (key);
395 }
396
397 if (attach_lwp (ptid))
398 new_threads_found = 1;
399 }
400 }
401
402 if (new_threads_found)
403 {
404 /* Start over. */
405 iterations = -1;
406 }
407
408 rewinddir (dir.get ());
409 }
410 }
411
412 /* See linux-procfs.h. */
413
414 int
415 linux_proc_task_list_dir_exists (pid_t pid)
416 {
417 char pathname[128];
418 struct stat buf;
419
420 xsnprintf (pathname, sizeof (pathname), "/proc/%ld/task", (long) pid);
421 return (stat (pathname, &buf) == 0);
422 }
423
424 /* See linux-procfs.h. */
425
426 const char *
427 linux_proc_pid_to_exec_file (int pid, bool is_local_fs)
428 {
429 static char buf[PATH_MAX];
430 char name[PATH_MAX];
431 ssize_t len;
432
433 xsnprintf (name, PATH_MAX, "/proc/%d/exe", pid);
434 len = readlink (name, buf, PATH_MAX - 1);
435 if (len <= 0)
436 strcpy (buf, name);
437 else
438 buf[len] = '\0';
439
440 /* If the inferior and GDB can see the same filesystem, and NAME
441 cannot be read, maybe the file has been deleted, then we can
442 potentially use /proc/PID/exe instead.
443
444 GDB always interprets the results of this function within the
445 current sysroot (which is 'target:' by default). This means
446 that, if we return /proc/PID/exe, GDB will try to find this file
447 within the sysroot.
448
449 This doesn't make sense if GDB is using a sysroot like:
450 '/some/random/directory/', not only is it possible that NAME
451 could be found within the sysroot, it is unlikely that
452 /proc/PID/exe will exist within the sysroot.
453
454 Similarly, if the sysroot is 'target:', but the inferior is
455 running within a separate MNT namespace, then it is more than
456 likely that the inferior will also be running in a separate PID
457 namespace, in this case PID is the pid on the host system,
458 /proc/PID/exe will not be correct within the inferiors MNT/PID
459 namespace.
460
461 So, we can fallback to use /proc/PID/exe only if IS_LOCAL_FS is
462 true, this indicates that GDB and the inferior are using the same
463 MNT namespace, and GDB's sysroot is either empty, or 'target:'. */
464 if (is_local_fs && access (buf, R_OK) != 0 && access (name, R_OK) == 0)
465 strcpy (buf, name);
466
467 return buf;
468 }
469
470 /* See linux-procfs.h. */
471
472 void
473 linux_proc_init_warnings ()
474 {
475 static bool warned = false;
476
477 if (warned)
478 return;
479 warned = true;
480
481 struct stat st;
482
483 if (stat ("/proc/self", &st) != 0)
484 warning (_("/proc is not accessible."));
485 }