2002-08-21 Andrew Cagney <ac131313@redhat.com>
[deliverable/binutils-gdb.git] / gdb / linux-proc.c
CommitLineData
ca557f44
AC
1/* GNU/Linux specific methods for using the /proc file system.
2
be4d1333 3 Copyright 2001, 2002 Free Software Foundation, Inc.
4b09dc8c
MS
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"
be4d1333 23#include "inferior.h"
4b09dc8c 24#include <sys/param.h> /* for MAXPATHLEN */
2bf543a6
MS
25#include <sys/procfs.h> /* for elf_gregset etc. */
26#include <sys/stat.h> /* for struct stat */
27#include <ctype.h> /* for isdigit */
1e4d76e7 28#include "regcache.h" /* for registers_changed */
be4d1333
MS
29#include "gregset.h" /* for gregset */
30#include "gdbcore.h" /* for get_exec_file */
31#include "gdbthread.h" /* for struct thread_info etc. */
2bf543a6
MS
32#include "elf-bfd.h" /* for elfcore_write_* */
33#include "cli/cli-decode.h" /* for add_info */
ff5922b5 34#include "gdb_string.h"
be4d1333
MS
35
36/* Function: child_pid_to_exec_file
37 *
38 * Accepts an integer pid
39 * Returns a string representing a file that can be opened
40 * to get the symbols for the child process.
41 */
4b09dc8c
MS
42
43char *
44child_pid_to_exec_file (int pid)
45{
145fdc6e 46 char *name1, *name2;
4b09dc8c 47
145fdc6e
MS
48 name1 = xmalloc (MAXPATHLEN);
49 name2 = xmalloc (MAXPATHLEN);
50 make_cleanup (xfree, name1);
51 make_cleanup (xfree, name2);
52 memset (name2, 0, MAXPATHLEN);
53
54 sprintf (name1, "/proc/%d/exe", pid);
55 if (readlink (name1, name2, MAXPATHLEN) > 0)
56 return name2;
57 else
58 return name1;
4b09dc8c 59}
be4d1333 60
2bf543a6
MS
61/* Function: read_mappings
62 *
63 * Service function for corefiles and info proc.
64 */
65
66static int
67read_mapping (FILE *mapfile,
68 long long *addr,
69 long long *endaddr,
70 char *permissions,
71 long long *offset,
72 char *device,
73 long long *inode,
74 char *filename)
75{
76 int ret = fscanf (mapfile, "%llx-%llx %s %llx %s %llx",
77 addr, endaddr, permissions, offset, device, inode);
78
79 if (ret > 0 && ret != EOF && *inode != 0)
80 {
ee677e8d
MS
81 /* Eat everything up to EOL for the filename. This will prevent
82 weird filenames (such as one with embedded whitespace) from
83 confusing this code. It also makes this code more robust
84 in respect to annotations the kernel may add after the
85 filename.
86
87 Note the filename is used for informational purposes only. */
88 ret += fscanf (mapfile, "%[^\n]\n", filename);
2bf543a6
MS
89 }
90 else
91 {
92 filename[0] = '\0'; /* no filename */
93 fscanf (mapfile, "\n");
94 }
95 return (ret != 0 && ret != EOF);
96}
97
be4d1333
MS
98/* Function: linux_find_memory_regions
99 *
100 * Fills the "to_find_memory_regions" target vector.
101 * Lists the memory regions in the inferior for a corefile.
102 */
103
104static int
105linux_find_memory_regions (int (*func) (CORE_ADDR,
106 unsigned long,
107 int, int, int,
108 void *),
109 void *obfd)
110{
111 long long pid = PIDGET (inferior_ptid);
2bf543a6
MS
112 char mapsfilename[MAXPATHLEN];
113 FILE *mapsfile;
be4d1333 114 long long addr, endaddr, size, offset, inode;
2bf543a6 115 char permissions[8], device[8], filename[MAXPATHLEN];
be4d1333
MS
116 int read, write, exec;
117 int ret;
118
119 /* Compose the filename for the /proc memory map, and open it. */
2bf543a6
MS
120 sprintf (mapsfilename, "/proc/%lld/maps", pid);
121 if ((mapsfile = fopen (mapsfilename, "r")) == NULL)
122 error ("Could not open %s\n", mapsfilename);
be4d1333
MS
123
124 if (info_verbose)
125 fprintf_filtered (gdb_stdout,
2bf543a6 126 "Reading memory regions from %s\n", mapsfilename);
be4d1333
MS
127
128 /* Now iterate until end-of-file. */
2bf543a6
MS
129 while (read_mapping (mapsfile, &addr, &endaddr, &permissions[0],
130 &offset, &device[0], &inode, &filename[0]))
be4d1333
MS
131 {
132 size = endaddr - addr;
133
134 /* Get the segment's permissions. */
2bf543a6
MS
135 read = (strchr (permissions, 'r') != 0);
136 write = (strchr (permissions, 'w') != 0);
137 exec = (strchr (permissions, 'x') != 0);
be4d1333
MS
138
139 if (info_verbose)
140 {
141 fprintf_filtered (gdb_stdout,
142 "Save segment, %lld bytes at 0x%s (%c%c%c)",
143 size, paddr_nz (addr),
144 read ? 'r' : ' ',
145 write ? 'w' : ' ',
146 exec ? 'x' : ' ');
147 if (filename && filename[0])
148 fprintf_filtered (gdb_stdout,
149 " for %s", filename);
150 fprintf_filtered (gdb_stdout, "\n");
151 }
152
153 /* Invoke the callback function to create the corefile segment. */
154 func (addr, size, read, write, exec, obfd);
be4d1333 155 }
2bf543a6 156 fclose (mapsfile);
be4d1333
MS
157 return 0;
158}
159
160/* Function: linux_do_thread_registers
161 *
162 * Records the thread's register state for the corefile note section.
163 */
164
165static char *
166linux_do_thread_registers (bfd *obfd, ptid_t ptid,
167 char *note_data, int *note_size)
168{
169 gdb_gregset_t gregs;
170 gdb_fpregset_t fpregs;
32872fa7
DJ
171#ifdef FILL_FPXREGSET
172 gdb_fpxregset_t fpxregs;
173#endif
be4d1333
MS
174 unsigned long merged_pid = ptid_get_tid (ptid) << 16 | ptid_get_pid (ptid);
175
176 fill_gregset (&gregs, -1);
177 note_data = (char *) elfcore_write_prstatus (obfd,
178 note_data,
179 note_size,
180 merged_pid,
181 stop_signal,
182 &gregs);
183
184 fill_fpregset (&fpregs, -1);
185 note_data = (char *) elfcore_write_prfpreg (obfd,
186 note_data,
187 note_size,
188 &fpregs,
189 sizeof (fpregs));
32872fa7
DJ
190#ifdef FILL_FPXREGSET
191 fill_fpxregset (&fpxregs, -1);
192 note_data = (char *) elfcore_write_prxfpreg (obfd,
193 note_data,
194 note_size,
195 &fpxregs,
196 sizeof (fpxregs));
197#endif
be4d1333
MS
198 return note_data;
199}
200
201struct linux_corefile_thread_data {
202 bfd *obfd;
203 char *note_data;
204 int *note_size;
205};
206
207/* Function: linux_corefile_thread_callback
208 *
209 * Called by gdbthread.c once per thread.
210 * Records the thread's register state for the corefile note section.
211 */
212
213static int
214linux_corefile_thread_callback (struct thread_info *ti, void *data)
215{
216 struct linux_corefile_thread_data *args = data;
217 ptid_t saved_ptid = inferior_ptid;
218
219 inferior_ptid = ti->ptid;
220 registers_changed ();
221 target_fetch_registers (-1); /* FIXME should not be necessary;
222 fill_gregset should do it automatically. */
223 args->note_data = linux_do_thread_registers (args->obfd,
224 ti->ptid,
225 args->note_data,
226 args->note_size);
227 inferior_ptid = saved_ptid;
228 registers_changed ();
229 target_fetch_registers (-1); /* FIXME should not be necessary;
230 fill_gregset should do it automatically. */
231 return 0;
232}
233
234/* Function: linux_make_note_section
235 *
236 * Fills the "to_make_corefile_note" target vector.
237 * Builds the note section for a corefile, and returns it
238 * in a malloc buffer.
239 */
240
241static char *
242linux_make_note_section (bfd *obfd, int *note_size)
243{
244 struct linux_corefile_thread_data thread_args;
245 struct cleanup *old_chain;
246 char fname[16] = {'\0'};
247 char psargs[80] = {'\0'};
248 char *note_data = NULL;
249 ptid_t current_ptid = inferior_ptid;
250
251 if (get_exec_file (0))
252 {
253 strncpy (fname, strrchr (get_exec_file (0), '/') + 1, sizeof (fname));
254 strncpy (psargs, get_exec_file (0),
255 sizeof (psargs));
256 if (get_inferior_args ())
257 {
258 strncat (psargs, " ",
259 sizeof (psargs) - strlen (psargs));
260 strncat (psargs, get_inferior_args (),
261 sizeof (psargs) - strlen (psargs));
262 }
263 note_data = (char *) elfcore_write_prpsinfo (obfd,
264 note_data,
265 note_size,
266 fname,
267 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 iterate_over_threads (linux_corefile_thread_callback, &thread_args);
275 if (thread_args.note_data == note_data)
276 {
277 /* iterate_over_threads didn't come up with any threads;
278 just use inferior_ptid. */
279 note_data = linux_do_thread_registers (obfd, inferior_ptid,
280 note_data, note_size);
281 }
282 else
283 {
284 note_data = thread_args.note_data;
285 }
286
287 make_cleanup (xfree, note_data);
288 return note_data;
289}
290
2bf543a6
MS
291/*
292 * Function: linux_info_proc_cmd
293 *
294 * Implement the "info proc" command.
295 */
296
297static void
298linux_info_proc_cmd (char *args, int from_tty)
299{
300 long long pid = PIDGET (inferior_ptid);
301 FILE *procfile;
302 char **argv = NULL;
303 char buffer[MAXPATHLEN];
304 char fname1[MAXPATHLEN], fname2[MAXPATHLEN];
305 int cmdline_f = 1;
306 int cwd_f = 1;
307 int exe_f = 1;
308 int mappings_f = 0;
309 int environ_f = 0;
310 int status_f = 0;
311 int stat_f = 0;
312 int all = 0;
313 struct stat dummy;
314
315 if (args)
316 {
317 /* Break up 'args' into an argv array. */
318 if ((argv = buildargv (args)) == NULL)
319 nomem (0);
320 else
321 make_cleanup_freeargv (argv);
322 }
323 while (argv != NULL && *argv != NULL)
324 {
325 if (isdigit (argv[0][0]))
326 {
327 pid = strtoul (argv[0], NULL, 10);
328 }
329 else if (strncmp (argv[0], "mappings", strlen (argv[0])) == 0)
330 {
331 mappings_f = 1;
332 }
333 else if (strcmp (argv[0], "status") == 0)
334 {
335 status_f = 1;
336 }
337 else if (strcmp (argv[0], "stat") == 0)
338 {
339 stat_f = 1;
340 }
341 else if (strcmp (argv[0], "cmd") == 0)
342 {
343 cmdline_f = 1;
344 }
345 else if (strncmp (argv[0], "exe", strlen (argv[0])) == 0)
346 {
347 exe_f = 1;
348 }
349 else if (strcmp (argv[0], "cwd") == 0)
350 {
351 cwd_f = 1;
352 }
353 else if (strncmp (argv[0], "all", strlen (argv[0])) == 0)
354 {
355 all = 1;
356 }
357 else
358 {
359 /* [...] (future options here) */
360 }
361 argv++;
362 }
363 if (pid == 0)
364 error ("No current process: you must name one.");
365
366 sprintf (fname1, "/proc/%lld", pid);
367 if (stat (fname1, &dummy) != 0)
368 error ("No /proc directory: '%s'", fname1);
369
370 printf_filtered ("process %lld\n", pid);
371 if (cmdline_f || all)
372 {
373 sprintf (fname1, "/proc/%lld/cmdline", pid);
374 if ((procfile = fopen (fname1, "r")) > 0)
375 {
376 fgets (buffer, sizeof (buffer), procfile);
377 printf_filtered ("cmdline = '%s'\n", buffer);
378 fclose (procfile);
379 }
380 else
381 warning ("unable to open /proc file '%s'", fname1);
382 }
383 if (cwd_f || all)
384 {
385 sprintf (fname1, "/proc/%lld/cwd", pid);
386 memset (fname2, 0, sizeof (fname2));
387 if (readlink (fname1, fname2, sizeof (fname2)) > 0)
388 printf_filtered ("cwd = '%s'\n", fname2);
389 else
390 warning ("unable to read link '%s'", fname1);
391 }
392 if (exe_f || all)
393 {
394 sprintf (fname1, "/proc/%lld/exe", pid);
395 memset (fname2, 0, sizeof (fname2));
396 if (readlink (fname1, fname2, sizeof (fname2)) > 0)
397 printf_filtered ("exe = '%s'\n", fname2);
398 else
399 warning ("unable to read link '%s'", fname1);
400 }
401 if (mappings_f || all)
402 {
403 sprintf (fname1, "/proc/%lld/maps", pid);
404 if ((procfile = fopen (fname1, "r")) > 0)
405 {
406 long long addr, endaddr, size, offset, inode;
407 char permissions[8], device[8], filename[MAXPATHLEN];
408 char *header_fmt_string, *data_fmt_string;
409
410 if (TARGET_ADDR_BIT == 32)
411 {
412 header_fmt_string = "\t%10s %10s %10s %10s %7s\n";
413 data_fmt_string = "\t%#10lx %#10lx %#10x %#10x %7s\n";
414 }
415 else
416 {
417 header_fmt_string = " %18s %18s %10s %10s %7s\n";
418 data_fmt_string = " %#18lx %#18lx %#10x %#10x %7s\n";
419 }
420
421 printf_filtered ("Mapped address spaces:\n\n");
422 printf_filtered (header_fmt_string,
423 "Start Addr",
424 " End Addr",
425 " Size",
426 " Offset",
427 "objfile");
428
429 while (read_mapping (procfile, &addr, &endaddr, &permissions[0],
430 &offset, &device[0], &inode, &filename[0]))
431 {
432 size = endaddr - addr;
433 printf_filtered (data_fmt_string,
434 (unsigned long) addr, /* FIXME: pr_addr */
435 (unsigned long) endaddr,
436 (int) size,
437 (unsigned int) offset,
438 filename[0] ? filename : "");
439
440 }
441
442 fclose (procfile);
443 }
444 else
445 warning ("unable to open /proc file '%s'", fname1);
446 }
447 if (status_f || all)
448 {
449 sprintf (fname1, "/proc/%lld/status", pid);
450 if ((procfile = fopen (fname1, "r")) > 0)
451 {
452 while (fgets (buffer, sizeof (buffer), procfile) != NULL)
453 printf_filtered (buffer);
454 fclose (procfile);
455 }
456 else
457 warning ("unable to open /proc file '%s'", fname1);
458 }
459 if (stat_f || all)
460 {
461 sprintf (fname1, "/proc/%lld/stat", pid);
462 if ((procfile = fopen (fname1, "r")) > 0)
463 {
464 int itmp;
465 char ctmp;
466
467 if (fscanf (procfile, "%d ", &itmp) > 0)
468 printf_filtered ("Process: %d\n", itmp);
469 if (fscanf (procfile, "%s ", &buffer[0]) > 0)
470 printf_filtered ("Exec file: %s\n", buffer);
471 if (fscanf (procfile, "%c ", &ctmp) > 0)
472 printf_filtered ("State: %c\n", ctmp);
473 if (fscanf (procfile, "%d ", &itmp) > 0)
474 printf_filtered ("Parent process: %d\n", itmp);
475 if (fscanf (procfile, "%d ", &itmp) > 0)
476 printf_filtered ("Process group: %d\n", itmp);
477 if (fscanf (procfile, "%d ", &itmp) > 0)
478 printf_filtered ("Session id: %d\n", itmp);
479 if (fscanf (procfile, "%d ", &itmp) > 0)
480 printf_filtered ("TTY: %d\n", itmp);
481 if (fscanf (procfile, "%d ", &itmp) > 0)
482 printf_filtered ("TTY owner process group: %d\n", itmp);
483 if (fscanf (procfile, "%u ", &itmp) > 0)
484 printf_filtered ("Flags: 0x%x\n", itmp);
485 if (fscanf (procfile, "%u ", &itmp) > 0)
486 printf_filtered ("Minor faults (no memory page): %u\n",
487 (unsigned int) itmp);
488 if (fscanf (procfile, "%u ", &itmp) > 0)
489 printf_filtered ("Minor faults, children: %u\n",
490 (unsigned int) itmp);
491 if (fscanf (procfile, "%u ", &itmp) > 0)
492 printf_filtered ("Major faults (memory page faults): %u\n",
493 (unsigned int) itmp);
494 if (fscanf (procfile, "%u ", &itmp) > 0)
495 printf_filtered ("Major faults, children: %u\n",
496 (unsigned int) itmp);
497 if (fscanf (procfile, "%d ", &itmp) > 0)
498 printf_filtered ("utime: %d\n", itmp);
499 if (fscanf (procfile, "%d ", &itmp) > 0)
500 printf_filtered ("stime: %d\n", itmp);
501 if (fscanf (procfile, "%d ", &itmp) > 0)
502 printf_filtered ("utime, children: %d\n", itmp);
503 if (fscanf (procfile, "%d ", &itmp) > 0)
504 printf_filtered ("stime, children: %d\n", itmp);
505 if (fscanf (procfile, "%d ", &itmp) > 0)
506 printf_filtered ("jiffies remaining in current time slice: %d\n",
507 itmp);
508 if (fscanf (procfile, "%d ", &itmp) > 0)
509 printf_filtered ("'nice' value: %d\n", itmp);
510 if (fscanf (procfile, "%u ", &itmp) > 0)
511 printf_filtered ("jiffies until next timeout: %u\n",
512 (unsigned int) itmp);
513 if (fscanf (procfile, "%u ", &itmp) > 0)
514 printf_filtered ("jiffies until next SIGALRM: %u\n",
515 (unsigned int) itmp);
516 if (fscanf (procfile, "%d ", &itmp) > 0)
517 printf_filtered ("start time (jiffies since system boot): %d\n",
518 itmp);
519 if (fscanf (procfile, "%u ", &itmp) > 0)
520 printf_filtered ("Virtual memory size: %u\n",
521 (unsigned int) itmp);
522 if (fscanf (procfile, "%u ", &itmp) > 0)
523 printf_filtered ("Resident set size: %u\n",
524 (unsigned int) itmp);
525 if (fscanf (procfile, "%u ", &itmp) > 0)
526 printf_filtered ("rlim: %u\n",
527 (unsigned int) itmp);
528 if (fscanf (procfile, "%u ", &itmp) > 0)
529 printf_filtered ("Start of text: 0x%x\n", itmp);
530 if (fscanf (procfile, "%u ", &itmp) > 0)
531 printf_filtered ("End of text: 0x%x\n", itmp);
532 if (fscanf (procfile, "%u ", &itmp) > 0)
533 printf_filtered ("Start of stack: 0x%x\n", itmp);
534#if 0 /* Don't know how architecture-dependent the rest is...
535 Anyway the signal bitmap info is available from "status". */
536 if (fscanf (procfile, "%u ", &itmp) > 0) /* FIXME arch? */
537 printf_filtered ("Kernel stack pointer: 0x%x\n", itmp);
538 if (fscanf (procfile, "%u ", &itmp) > 0) /* FIXME arch? */
539 printf_filtered ("Kernel instr pointer: 0x%x\n", itmp);
540 if (fscanf (procfile, "%d ", &itmp) > 0)
541 printf_filtered ("Pending signals bitmap: 0x%x\n", itmp);
542 if (fscanf (procfile, "%d ", &itmp) > 0)
543 printf_filtered ("Blocked signals bitmap: 0x%x\n", itmp);
544 if (fscanf (procfile, "%d ", &itmp) > 0)
545 printf_filtered ("Ignored signals bitmap: 0x%x\n", itmp);
546 if (fscanf (procfile, "%d ", &itmp) > 0)
547 printf_filtered ("Catched signals bitmap: 0x%x\n", itmp);
548 if (fscanf (procfile, "%u ", &itmp) > 0) /* FIXME arch? */
549 printf_filtered ("wchan (system call): 0x%x\n", itmp);
550#endif
551 fclose (procfile);
552 }
553 else
554 warning ("unable to open /proc file '%s'", fname1);
555 }
556}
557
be4d1333
MS
558void
559_initialize_linux_proc (void)
560{
561 extern void inftarg_set_find_memory_regions ();
562 extern void inftarg_set_make_corefile_notes ();
563
564 inftarg_set_find_memory_regions (linux_find_memory_regions);
565 inftarg_set_make_corefile_notes (linux_make_note_section);
2bf543a6
MS
566
567 add_info ("proc", linux_info_proc_cmd,
568 "Show /proc process information about any running process.\n\
569Specify any process id, or use the program being debugged by default.\n\
570Specify any of the following keywords for detailed info:\n\
571 mappings -- list of mapped memory regions.\n\
572 stat -- list a bunch of random process info.\n\
573 status -- list a different bunch of random process info.\n\
574 all -- list all available /proc info.");
be4d1333 575}
This page took 0.11685 seconds and 4 git commands to generate.