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