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