1/* Linux-specific PROCFS manipulation routines. 2 Copyright (C) 2009-2020 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 "gdbsupport/common-defs.h" 20#include "linux-procfs.h" 21#include "gdbsupport/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 28static int 29linux_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 57int 58linux_proc_get_tgid (pid_t lwpid) 59{ 60 return linux_proc_get_int (lwpid, "Tgid", 1); 61} 62 63/* See linux-procfs.h. */ 64 65pid_t 66linux_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 75enum 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 96static enum proc_state 97parse_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 126static int 127linux_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 154int 155linux_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 179static int 180linux_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 192int 193linux_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 201int 202linux_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 210static int 211linux_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 218int 219linux_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 226int 227linux_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 234const char * 235linux_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.pid (); 243 pid_t tid = ptid.lwp_p () ? ptid.lwp () : ptid.pid (); 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 274void 275linux_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_t (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 332int 333linux_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 344char * 345linux_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} 360 361/* See linux-procfs.h. */ 362 363void 364linux_proc_init_warnings () 365{ 366 static bool warned = false; 367 368 if (warned) 369 return; 370 warned = true; 371 372 struct stat st; 373 374 if (stat ("/proc/self", &st) != 0) 375 warning (_("/proc is not accessible.")); 376} 377