* config/tc-xtensa.c (xtensa_mark_literal_pool_location): Remove
[deliverable/binutils-gdb.git] / gdb / linux-proc.c
1 /* GNU/Linux specific methods for using the /proc file system.
2
3 Copyright 2001, 2002 Free Software Foundation, Inc.
4
5 This file is part of GDB.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
21
22 #include "defs.h"
23 #include "inferior.h"
24 #include <sys/param.h> /* for MAXPATHLEN */
25 #include <sys/procfs.h> /* for elf_gregset etc. */
26 #include "gdb_stat.h" /* for struct stat */
27 #include <ctype.h> /* for isdigit */
28 #include <unistd.h> /* for open, pread64 */
29 #include <fcntl.h> /* for O_RDONLY */
30 #include "regcache.h" /* for registers_changed */
31 #include "gregset.h" /* for gregset */
32 #include "gdbcore.h" /* for get_exec_file */
33 #include "gdbthread.h" /* for struct thread_info etc. */
34 #include "elf-bfd.h" /* for elfcore_write_* */
35 #include "cli/cli-decode.h" /* for add_info */
36 #include "gdb_string.h"
37
38 #include <signal.h>
39
40 #include "linux-nat.h"
41
42 #ifndef O_LARGEFILE
43 #define O_LARGEFILE 0
44 #endif
45
46 /* Function: child_pid_to_exec_file
47 *
48 * Accepts an integer pid
49 * Returns a string representing a file that can be opened
50 * to get the symbols for the child process.
51 */
52
53 char *
54 child_pid_to_exec_file (int pid)
55 {
56 char *name1, *name2;
57
58 name1 = xmalloc (MAXPATHLEN);
59 name2 = xmalloc (MAXPATHLEN);
60 make_cleanup (xfree, name1);
61 make_cleanup (xfree, name2);
62 memset (name2, 0, MAXPATHLEN);
63
64 sprintf (name1, "/proc/%d/exe", pid);
65 if (readlink (name1, name2, MAXPATHLEN) > 0)
66 return name2;
67 else
68 return name1;
69 }
70
71 /* Function: read_mappings
72 *
73 * Service function for corefiles and info proc.
74 */
75
76 static int
77 read_mapping (FILE *mapfile,
78 long long *addr,
79 long long *endaddr,
80 char *permissions,
81 long long *offset,
82 char *device, long long *inode, char *filename)
83 {
84 int ret = fscanf (mapfile, "%llx-%llx %s %llx %s %llx",
85 addr, endaddr, permissions, offset, device, inode);
86
87 if (ret > 0 && ret != EOF && *inode != 0)
88 {
89 /* Eat everything up to EOL for the filename. This will prevent
90 weird filenames (such as one with embedded whitespace) from
91 confusing this code. It also makes this code more robust
92 in respect to annotations the kernel may add after the
93 filename.
94
95 Note the filename is used for informational purposes only. */
96 ret += fscanf (mapfile, "%[^\n]\n", filename);
97 }
98 else
99 {
100 filename[0] = '\0'; /* no filename */
101 fscanf (mapfile, "\n");
102 }
103 return (ret != 0 && ret != EOF);
104 }
105
106 /* Function: linux_find_memory_regions
107 *
108 * Fills the "to_find_memory_regions" target vector.
109 * Lists the memory regions in the inferior for a corefile.
110 */
111
112 static int
113 linux_find_memory_regions (int (*func) (CORE_ADDR,
114 unsigned long,
115 int, int, int, void *), void *obfd)
116 {
117 long long pid = PIDGET (inferior_ptid);
118 char mapsfilename[MAXPATHLEN];
119 FILE *mapsfile;
120 long long addr, endaddr, size, offset, inode;
121 char permissions[8], device[8], filename[MAXPATHLEN];
122 int read, write, exec;
123 int ret;
124
125 /* Compose the filename for the /proc memory map, and open it. */
126 sprintf (mapsfilename, "/proc/%lld/maps", pid);
127 if ((mapsfile = fopen (mapsfilename, "r")) == NULL)
128 error ("Could not open %s\n", mapsfilename);
129
130 if (info_verbose)
131 fprintf_filtered (gdb_stdout,
132 "Reading memory regions from %s\n", mapsfilename);
133
134 /* Now iterate until end-of-file. */
135 while (read_mapping (mapsfile, &addr, &endaddr, &permissions[0],
136 &offset, &device[0], &inode, &filename[0]))
137 {
138 size = endaddr - addr;
139
140 /* Get the segment's permissions. */
141 read = (strchr (permissions, 'r') != 0);
142 write = (strchr (permissions, 'w') != 0);
143 exec = (strchr (permissions, 'x') != 0);
144
145 if (info_verbose)
146 {
147 fprintf_filtered (gdb_stdout,
148 "Save segment, %lld bytes at 0x%s (%c%c%c)",
149 size, paddr_nz (addr),
150 read ? 'r' : ' ',
151 write ? 'w' : ' ', exec ? 'x' : ' ');
152 if (filename && filename[0])
153 fprintf_filtered (gdb_stdout, " for %s", filename);
154 fprintf_filtered (gdb_stdout, "\n");
155 }
156
157 /* Invoke the callback function to create the corefile segment. */
158 func (addr, size, read, write, exec, obfd);
159 }
160 fclose (mapsfile);
161 return 0;
162 }
163
164 /* Function: linux_do_thread_registers
165 *
166 * Records the thread's register state for the corefile note section.
167 */
168
169 static char *
170 linux_do_thread_registers (bfd *obfd, ptid_t ptid,
171 char *note_data, int *note_size)
172 {
173 gdb_gregset_t gregs;
174 gdb_fpregset_t fpregs;
175 #ifdef FILL_FPXREGSET
176 gdb_fpxregset_t fpxregs;
177 #endif
178 unsigned long lwp = ptid_get_lwp (ptid);
179
180 fill_gregset (&gregs, -1);
181 note_data = (char *) elfcore_write_prstatus (obfd,
182 note_data,
183 note_size,
184 lwp,
185 stop_signal, &gregs);
186
187 fill_fpregset (&fpregs, -1);
188 note_data = (char *) elfcore_write_prfpreg (obfd,
189 note_data,
190 note_size,
191 &fpregs, sizeof (fpregs));
192 #ifdef FILL_FPXREGSET
193 fill_fpxregset (&fpxregs, -1);
194 note_data = (char *) elfcore_write_prxfpreg (obfd,
195 note_data,
196 note_size,
197 &fpxregs, sizeof (fpxregs));
198 #endif
199 return note_data;
200 }
201
202 struct linux_corefile_thread_data
203 {
204 bfd *obfd;
205 char *note_data;
206 int *note_size;
207 int num_notes;
208 };
209
210 /* Function: linux_corefile_thread_callback
211 *
212 * Called by gdbthread.c once per thread.
213 * Records the thread's register state for the corefile note section.
214 */
215
216 static int
217 linux_corefile_thread_callback (struct lwp_info *ti, void *data)
218 {
219 struct linux_corefile_thread_data *args = data;
220 ptid_t saved_ptid = inferior_ptid;
221
222 inferior_ptid = ti->ptid;
223 registers_changed ();
224 target_fetch_registers (-1); /* FIXME should not be necessary;
225 fill_gregset should do it automatically. */
226 args->note_data = linux_do_thread_registers (args->obfd,
227 ti->ptid,
228 args->note_data,
229 args->note_size);
230 args->num_notes++;
231 inferior_ptid = saved_ptid;
232 registers_changed ();
233 target_fetch_registers (-1); /* FIXME should not be necessary;
234 fill_gregset should do it automatically. */
235 return 0;
236 }
237
238 /* Function: linux_make_note_section
239 *
240 * Fills the "to_make_corefile_note" target vector.
241 * Builds the note section for a corefile, and returns it
242 * in a malloc buffer.
243 */
244
245 static char *
246 linux_make_note_section (bfd *obfd, int *note_size)
247 {
248 struct linux_corefile_thread_data thread_args;
249 struct cleanup *old_chain;
250 char fname[16] = { '\0' };
251 char psargs[80] = { '\0' };
252 char *note_data = NULL;
253 ptid_t current_ptid = inferior_ptid;
254
255 if (get_exec_file (0))
256 {
257 strncpy (fname, strrchr (get_exec_file (0), '/') + 1, sizeof (fname));
258 strncpy (psargs, get_exec_file (0), sizeof (psargs));
259 if (get_inferior_args ())
260 {
261 strncat (psargs, " ", sizeof (psargs) - strlen (psargs));
262 strncat (psargs, get_inferior_args (),
263 sizeof (psargs) - strlen (psargs));
264 }
265 note_data = (char *) elfcore_write_prpsinfo (obfd,
266 note_data,
267 note_size, fname, psargs);
268 }
269
270 /* Dump information for threads. */
271 thread_args.obfd = obfd;
272 thread_args.note_data = note_data;
273 thread_args.note_size = note_size;
274 thread_args.num_notes = 0;
275 iterate_over_lwps (linux_corefile_thread_callback, &thread_args);
276 if (thread_args.num_notes == 0)
277 {
278 /* iterate_over_threads didn't come up with any threads;
279 just use inferior_ptid. */
280 note_data = linux_do_thread_registers (obfd, inferior_ptid,
281 note_data, note_size);
282 }
283 else
284 {
285 note_data = thread_args.note_data;
286 }
287
288 make_cleanup (xfree, note_data);
289 return note_data;
290 }
291
292 /*
293 * Function: linux_info_proc_cmd
294 *
295 * Implement the "info proc" command.
296 */
297
298 static void
299 linux_info_proc_cmd (char *args, int from_tty)
300 {
301 long long pid = PIDGET (inferior_ptid);
302 FILE *procfile;
303 char **argv = NULL;
304 char buffer[MAXPATHLEN];
305 char fname1[MAXPATHLEN], fname2[MAXPATHLEN];
306 int cmdline_f = 1;
307 int cwd_f = 1;
308 int exe_f = 1;
309 int mappings_f = 0;
310 int environ_f = 0;
311 int status_f = 0;
312 int stat_f = 0;
313 int all = 0;
314 struct stat dummy;
315
316 if (args)
317 {
318 /* Break up 'args' into an argv array. */
319 if ((argv = buildargv (args)) == NULL)
320 nomem (0);
321 else
322 make_cleanup_freeargv (argv);
323 }
324 while (argv != NULL && *argv != NULL)
325 {
326 if (isdigit (argv[0][0]))
327 {
328 pid = strtoul (argv[0], NULL, 10);
329 }
330 else if (strncmp (argv[0], "mappings", strlen (argv[0])) == 0)
331 {
332 mappings_f = 1;
333 }
334 else if (strcmp (argv[0], "status") == 0)
335 {
336 status_f = 1;
337 }
338 else if (strcmp (argv[0], "stat") == 0)
339 {
340 stat_f = 1;
341 }
342 else if (strcmp (argv[0], "cmd") == 0)
343 {
344 cmdline_f = 1;
345 }
346 else if (strncmp (argv[0], "exe", strlen (argv[0])) == 0)
347 {
348 exe_f = 1;
349 }
350 else if (strcmp (argv[0], "cwd") == 0)
351 {
352 cwd_f = 1;
353 }
354 else if (strncmp (argv[0], "all", strlen (argv[0])) == 0)
355 {
356 all = 1;
357 }
358 else
359 {
360 /* [...] (future options here) */
361 }
362 argv++;
363 }
364 if (pid == 0)
365 error ("No current process: you must name one.");
366
367 sprintf (fname1, "/proc/%lld", pid);
368 if (stat (fname1, &dummy) != 0)
369 error ("No /proc directory: '%s'", fname1);
370
371 printf_filtered ("process %lld\n", pid);
372 if (cmdline_f || all)
373 {
374 sprintf (fname1, "/proc/%lld/cmdline", pid);
375 if ((procfile = fopen (fname1, "r")) > 0)
376 {
377 fgets (buffer, sizeof (buffer), procfile);
378 printf_filtered ("cmdline = '%s'\n", buffer);
379 fclose (procfile);
380 }
381 else
382 warning ("unable to open /proc file '%s'", fname1);
383 }
384 if (cwd_f || all)
385 {
386 sprintf (fname1, "/proc/%lld/cwd", pid);
387 memset (fname2, 0, sizeof (fname2));
388 if (readlink (fname1, fname2, sizeof (fname2)) > 0)
389 printf_filtered ("cwd = '%s'\n", fname2);
390 else
391 warning ("unable to read link '%s'", fname1);
392 }
393 if (exe_f || all)
394 {
395 sprintf (fname1, "/proc/%lld/exe", pid);
396 memset (fname2, 0, sizeof (fname2));
397 if (readlink (fname1, fname2, sizeof (fname2)) > 0)
398 printf_filtered ("exe = '%s'\n", fname2);
399 else
400 warning ("unable to read link '%s'", fname1);
401 }
402 if (mappings_f || all)
403 {
404 sprintf (fname1, "/proc/%lld/maps", pid);
405 if ((procfile = fopen (fname1, "r")) > 0)
406 {
407 long long addr, endaddr, size, offset, inode;
408 char permissions[8], device[8], filename[MAXPATHLEN];
409
410 printf_filtered ("Mapped address spaces:\n\n");
411 if (TARGET_ADDR_BIT == 32)
412 {
413 printf_filtered ("\t%10s %10s %10s %10s %7s\n",
414 "Start Addr",
415 " End Addr",
416 " Size", " Offset", "objfile");
417 }
418 else
419 {
420 printf_filtered (" %18s %18s %10s %10s %7s\n",
421 "Start Addr",
422 " End Addr",
423 " Size", " Offset", "objfile");
424 }
425
426 while (read_mapping (procfile, &addr, &endaddr, &permissions[0],
427 &offset, &device[0], &inode, &filename[0]))
428 {
429 size = endaddr - addr;
430
431 /* FIXME: carlton/2003-08-27: Maybe the printf_filtered
432 calls here (and possibly above) should be abstracted
433 out into their own functions? Andrew suggests using
434 a generic local_address_string instead to print out
435 the addresses; that makes sense to me, too. */
436
437 if (TARGET_ADDR_BIT == 32)
438 {
439 printf_filtered ("\t%#10lx %#10lx %#10x %#10x %7s\n",
440 (unsigned long) addr, /* FIXME: pr_addr */
441 (unsigned long) endaddr,
442 (int) size,
443 (unsigned int) offset,
444 filename[0] ? filename : "");
445 }
446 else
447 {
448 printf_filtered (" %#18lx %#18lx %#10x %#10x %7s\n",
449 (unsigned long) addr, /* FIXME: pr_addr */
450 (unsigned long) endaddr,
451 (int) size,
452 (unsigned int) offset,
453 filename[0] ? filename : "");
454 }
455 }
456
457 fclose (procfile);
458 }
459 else
460 warning ("unable to open /proc file '%s'", fname1);
461 }
462 if (status_f || all)
463 {
464 sprintf (fname1, "/proc/%lld/status", pid);
465 if ((procfile = fopen (fname1, "r")) > 0)
466 {
467 while (fgets (buffer, sizeof (buffer), procfile) != NULL)
468 puts_filtered (buffer);
469 fclose (procfile);
470 }
471 else
472 warning ("unable to open /proc file '%s'", fname1);
473 }
474 if (stat_f || all)
475 {
476 sprintf (fname1, "/proc/%lld/stat", pid);
477 if ((procfile = fopen (fname1, "r")) > 0)
478 {
479 int itmp;
480 char ctmp;
481
482 if (fscanf (procfile, "%d ", &itmp) > 0)
483 printf_filtered ("Process: %d\n", itmp);
484 if (fscanf (procfile, "%s ", &buffer[0]) > 0)
485 printf_filtered ("Exec file: %s\n", buffer);
486 if (fscanf (procfile, "%c ", &ctmp) > 0)
487 printf_filtered ("State: %c\n", ctmp);
488 if (fscanf (procfile, "%d ", &itmp) > 0)
489 printf_filtered ("Parent process: %d\n", itmp);
490 if (fscanf (procfile, "%d ", &itmp) > 0)
491 printf_filtered ("Process group: %d\n", itmp);
492 if (fscanf (procfile, "%d ", &itmp) > 0)
493 printf_filtered ("Session id: %d\n", itmp);
494 if (fscanf (procfile, "%d ", &itmp) > 0)
495 printf_filtered ("TTY: %d\n", itmp);
496 if (fscanf (procfile, "%d ", &itmp) > 0)
497 printf_filtered ("TTY owner process group: %d\n", itmp);
498 if (fscanf (procfile, "%u ", &itmp) > 0)
499 printf_filtered ("Flags: 0x%x\n", itmp);
500 if (fscanf (procfile, "%u ", &itmp) > 0)
501 printf_filtered ("Minor faults (no memory page): %u\n",
502 (unsigned int) itmp);
503 if (fscanf (procfile, "%u ", &itmp) > 0)
504 printf_filtered ("Minor faults, children: %u\n",
505 (unsigned int) itmp);
506 if (fscanf (procfile, "%u ", &itmp) > 0)
507 printf_filtered ("Major faults (memory page faults): %u\n",
508 (unsigned int) itmp);
509 if (fscanf (procfile, "%u ", &itmp) > 0)
510 printf_filtered ("Major faults, children: %u\n",
511 (unsigned int) itmp);
512 if (fscanf (procfile, "%d ", &itmp) > 0)
513 printf_filtered ("utime: %d\n", itmp);
514 if (fscanf (procfile, "%d ", &itmp) > 0)
515 printf_filtered ("stime: %d\n", itmp);
516 if (fscanf (procfile, "%d ", &itmp) > 0)
517 printf_filtered ("utime, children: %d\n", itmp);
518 if (fscanf (procfile, "%d ", &itmp) > 0)
519 printf_filtered ("stime, children: %d\n", itmp);
520 if (fscanf (procfile, "%d ", &itmp) > 0)
521 printf_filtered ("jiffies remaining in current time slice: %d\n",
522 itmp);
523 if (fscanf (procfile, "%d ", &itmp) > 0)
524 printf_filtered ("'nice' value: %d\n", itmp);
525 if (fscanf (procfile, "%u ", &itmp) > 0)
526 printf_filtered ("jiffies until next timeout: %u\n",
527 (unsigned int) itmp);
528 if (fscanf (procfile, "%u ", &itmp) > 0)
529 printf_filtered ("jiffies until next SIGALRM: %u\n",
530 (unsigned int) itmp);
531 if (fscanf (procfile, "%d ", &itmp) > 0)
532 printf_filtered ("start time (jiffies since system boot): %d\n",
533 itmp);
534 if (fscanf (procfile, "%u ", &itmp) > 0)
535 printf_filtered ("Virtual memory size: %u\n",
536 (unsigned int) itmp);
537 if (fscanf (procfile, "%u ", &itmp) > 0)
538 printf_filtered ("Resident set size: %u\n", (unsigned int) itmp);
539 if (fscanf (procfile, "%u ", &itmp) > 0)
540 printf_filtered ("rlim: %u\n", (unsigned int) itmp);
541 if (fscanf (procfile, "%u ", &itmp) > 0)
542 printf_filtered ("Start of text: 0x%x\n", itmp);
543 if (fscanf (procfile, "%u ", &itmp) > 0)
544 printf_filtered ("End of text: 0x%x\n", itmp);
545 if (fscanf (procfile, "%u ", &itmp) > 0)
546 printf_filtered ("Start of stack: 0x%x\n", itmp);
547 #if 0 /* Don't know how architecture-dependent the rest is...
548 Anyway the signal bitmap info is available from "status". */
549 if (fscanf (procfile, "%u ", &itmp) > 0) /* FIXME arch? */
550 printf_filtered ("Kernel stack pointer: 0x%x\n", itmp);
551 if (fscanf (procfile, "%u ", &itmp) > 0) /* FIXME arch? */
552 printf_filtered ("Kernel instr pointer: 0x%x\n", itmp);
553 if (fscanf (procfile, "%d ", &itmp) > 0)
554 printf_filtered ("Pending signals bitmap: 0x%x\n", itmp);
555 if (fscanf (procfile, "%d ", &itmp) > 0)
556 printf_filtered ("Blocked signals bitmap: 0x%x\n", itmp);
557 if (fscanf (procfile, "%d ", &itmp) > 0)
558 printf_filtered ("Ignored signals bitmap: 0x%x\n", itmp);
559 if (fscanf (procfile, "%d ", &itmp) > 0)
560 printf_filtered ("Catched signals bitmap: 0x%x\n", itmp);
561 if (fscanf (procfile, "%u ", &itmp) > 0) /* FIXME arch? */
562 printf_filtered ("wchan (system call): 0x%x\n", itmp);
563 #endif
564 fclose (procfile);
565 }
566 else
567 warning ("unable to open /proc file '%s'", fname1);
568 }
569 }
570
571 void
572 _initialize_linux_proc (void)
573 {
574 extern void inftarg_set_find_memory_regions ();
575 extern void inftarg_set_make_corefile_notes ();
576
577 inftarg_set_find_memory_regions (linux_find_memory_regions);
578 inftarg_set_make_corefile_notes (linux_make_note_section);
579
580 add_info ("proc", linux_info_proc_cmd,
581 "Show /proc process information about any running process.\n\
582 Specify any process id, or use the program being debugged by default.\n\
583 Specify any of the following keywords for detailed info:\n\
584 mappings -- list of mapped memory regions.\n\
585 stat -- list a bunch of random process info.\n\
586 status -- list a different bunch of random process info.\n\
587 all -- list all available /proc info.");
588 }
589
590 int
591 linux_proc_xfer_memory (CORE_ADDR addr, char *myaddr, int len, int write,
592 struct mem_attrib *attrib, struct target_ops *target)
593 {
594 int fd, ret;
595 char filename[64];
596
597 if (write)
598 return 0;
599
600 /* Don't bother for one word. */
601 if (len < 3 * sizeof (long))
602 return 0;
603
604 /* We could keep this file open and cache it - possibly one
605 per thread. That requires some juggling, but is even faster. */
606 sprintf (filename, "/proc/%d/mem", PIDGET (inferior_ptid));
607 fd = open (filename, O_RDONLY | O_LARGEFILE);
608 if (fd == -1)
609 return 0;
610
611 /* If pread64 is available, use it. It's faster if the kernel
612 supports it (only one syscall), and it's 64-bit safe even
613 on 32-bit platforms (for instance, SPARC debugging a SPARC64
614 application). */
615 #ifdef HAVE_PREAD64
616 if (pread64 (fd, myaddr, len, addr) != len)
617 #else
618 if (lseek (fd, addr, SEEK_SET) == -1 || read (fd, myaddr, len) != len)
619 #endif
620 ret = 0;
621 else
622 ret = len;
623
624 close (fd);
625 return ret;
626 }
627
628 /* Parse LINE as a signal set and add its set bits to SIGS. */
629
630 static void
631 linux_proc_add_line_to_sigset (const char *line, sigset_t *sigs)
632 {
633 int len = strlen (line) - 1;
634 const char *p;
635 int signum;
636
637 if (line[len] != '\n')
638 error ("Could not parse signal set: %s", line);
639
640 p = line;
641 signum = len * 4;
642 while (len-- > 0)
643 {
644 int digit;
645
646 if (*p >= '0' && *p <= '9')
647 digit = *p - '0';
648 else if (*p >= 'a' && *p <= 'f')
649 digit = *p - 'a' + 10;
650 else
651 error ("Could not parse signal set: %s", line);
652
653 signum -= 4;
654
655 if (digit & 1)
656 sigaddset (sigs, signum + 1);
657 if (digit & 2)
658 sigaddset (sigs, signum + 2);
659 if (digit & 4)
660 sigaddset (sigs, signum + 3);
661 if (digit & 8)
662 sigaddset (sigs, signum + 4);
663
664 p++;
665 }
666 }
667
668 /* Find process PID's pending signals from /proc/pid/status and set SIGS
669 to match. */
670
671 void
672 linux_proc_pending_signals (int pid, sigset_t *pending, sigset_t *blocked, sigset_t *ignored)
673 {
674 FILE *procfile;
675 char buffer[MAXPATHLEN], fname[MAXPATHLEN];
676 int signum;
677
678 sigemptyset (pending);
679 sigemptyset (blocked);
680 sigemptyset (ignored);
681 sprintf (fname, "/proc/%d/status", pid);
682 procfile = fopen (fname, "r");
683 if (procfile == NULL)
684 error ("Could not open %s", fname);
685
686 while (fgets (buffer, MAXPATHLEN, procfile) != NULL)
687 {
688 /* Normal queued signals are on the SigPnd line in the status
689 file. However, 2.6 kernels also have a "shared" pending queue
690 for delivering signals to a thread group, so check for a ShdPnd
691 line also.
692
693 Unfortunately some Red Hat kernels include the shared pending queue
694 but not the ShdPnd status field. */
695
696 if (strncmp (buffer, "SigPnd:\t", 8) == 0)
697 linux_proc_add_line_to_sigset (buffer + 8, pending);
698 else if (strncmp (buffer, "ShdPnd:\t", 8) == 0)
699 linux_proc_add_line_to_sigset (buffer + 8, pending);
700 else if (strncmp (buffer, "SigBlk:\t", 8) == 0)
701 linux_proc_add_line_to_sigset (buffer + 8, blocked);
702 else if (strncmp (buffer, "SigIgn:\t", 8) == 0)
703 linux_proc_add_line_to_sigset (buffer + 8, ignored);
704 }
705
706 fclose (procfile);
707 }
This page took 0.044883 seconds and 4 git commands to generate.