]> Git Repo - binutils.git/blob - gdb/linux-proc.c
2002-11-09 Klee Dienes <[email protected]>
[binutils.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 #include "gdb_string.h"
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  */
42
43 char *
44 child_pid_to_exec_file (int pid)
45 {
46   char *name1, *name2;
47
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;
59 }
60
61 /* Function: read_mappings
62  *
63  * Service function for corefiles and info proc.
64  */
65
66 static int 
67 read_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     {
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);
89     }
90   else
91     {
92       filename[0] = '\0';       /* no filename */
93       fscanf (mapfile, "\n");
94     }
95   return (ret != 0 && ret != EOF);
96 }
97
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
104 static int
105 linux_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);
112   char mapsfilename[MAXPATHLEN];
113   FILE *mapsfile;
114   long long addr, endaddr, size, offset, inode;
115   char permissions[8], device[8], filename[MAXPATHLEN];
116   int read, write, exec;
117   int ret;
118
119   /* Compose the filename for the /proc memory map, and open it. */
120   sprintf (mapsfilename, "/proc/%lld/maps", pid);
121   if ((mapsfile = fopen (mapsfilename, "r")) == NULL)
122     error ("Could not open %s\n", mapsfilename);
123
124   if (info_verbose)
125     fprintf_filtered (gdb_stdout, 
126                       "Reading memory regions from %s\n", mapsfilename);
127
128   /* Now iterate until end-of-file. */
129   while (read_mapping (mapsfile, &addr, &endaddr, &permissions[0], 
130                        &offset, &device[0], &inode, &filename[0]))
131     {
132       size = endaddr - addr;
133
134       /* Get the segment's permissions.  */
135       read  = (strchr (permissions, 'r') != 0);
136       write = (strchr (permissions, 'w') != 0);
137       exec  = (strchr (permissions, 'x') != 0);
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);
155     }
156   fclose (mapsfile);
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
165 static char *
166 linux_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;
171 #ifdef FILL_FPXREGSET
172   gdb_fpxregset_t fpxregs;
173 #endif
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));
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
198   return note_data;
199 }
200
201 struct linux_corefile_thread_data
202 {
203   bfd *obfd;
204   char *note_data;
205   int *note_size;
206   int num_notes;
207 };
208
209 /* Function: linux_corefile_thread_callback
210  * 
211  * Called by gdbthread.c once per thread.
212  * Records the thread's register state for the corefile note section.
213  */
214
215 static int
216 linux_corefile_thread_callback (struct thread_info *ti, void *data)
217 {
218   struct linux_corefile_thread_data *args = data;
219   ptid_t saved_ptid = inferior_ptid;
220
221   inferior_ptid = ti->ptid;
222   registers_changed ();
223   target_fetch_registers (-1);  /* FIXME should not be necessary; 
224                                    fill_gregset should do it automatically. */
225   args->note_data = linux_do_thread_registers (args->obfd, 
226                                                ti->ptid, 
227                                                args->note_data, 
228                                                args->note_size);
229   args->num_notes++;
230   inferior_ptid = saved_ptid;
231   registers_changed ();
232   target_fetch_registers (-1);  /* FIXME should not be necessary; 
233                                    fill_gregset should do it automatically. */
234   return 0;
235 }
236
237 /* Function: linux_make_note_section
238  *
239  * Fills the "to_make_corefile_note" target vector.
240  * Builds the note section for a corefile, and returns it 
241  * in a malloc buffer. 
242  */
243
244 static char *
245 linux_make_note_section (bfd *obfd, int *note_size)
246 {
247   struct linux_corefile_thread_data thread_args;
248   struct cleanup *old_chain;
249   char fname[16] = {'\0'};
250   char psargs[80] = {'\0'};
251   char *note_data = NULL;
252   ptid_t current_ptid = inferior_ptid;
253
254   if (get_exec_file (0))
255     {
256       strncpy (fname, strrchr (get_exec_file (0), '/') + 1, sizeof (fname));
257       strncpy (psargs, get_exec_file (0), 
258                sizeof (psargs));
259       if (get_inferior_args ())
260         {
261           strncat (psargs, " ", 
262                    sizeof (psargs) - strlen (psargs));
263           strncat (psargs, get_inferior_args (), 
264                    sizeof (psargs) - strlen (psargs));
265         }
266       note_data = (char *) elfcore_write_prpsinfo (obfd, 
267                                                    note_data, 
268                                                    note_size, 
269                                                    fname, 
270                                                    psargs);
271     }
272
273   /* Dump information for threads.  */
274   thread_args.obfd = obfd;
275   thread_args.note_data = note_data;
276   thread_args.note_size = note_size;
277   thread_args.num_notes = 0;
278   iterate_over_threads (linux_corefile_thread_callback, &thread_args);
279   if (thread_args.num_notes == 0)
280     {
281       /* iterate_over_threads didn't come up with any threads;
282          just use inferior_ptid.  */
283       note_data = linux_do_thread_registers (obfd, inferior_ptid, 
284                                              note_data, note_size);
285     }
286   else
287     {
288       note_data = thread_args.note_data;
289     }
290
291   make_cleanup (xfree, note_data);
292   return note_data;
293 }
294
295 /*
296  * Function: linux_info_proc_cmd
297  *
298  * Implement the "info proc" command.
299  */
300
301 static void
302 linux_info_proc_cmd (char *args, int from_tty)
303 {
304   long long pid = PIDGET (inferior_ptid);
305   FILE *procfile;
306   char **argv = NULL;
307   char buffer[MAXPATHLEN];
308   char fname1[MAXPATHLEN], fname2[MAXPATHLEN];
309   int cmdline_f = 1;
310   int cwd_f = 1;
311   int exe_f = 1;
312   int mappings_f = 0;
313   int environ_f = 0;
314   int status_f = 0;
315   int stat_f = 0;
316   int all = 0;
317   struct stat dummy;
318
319   if (args)
320     {
321       /* Break up 'args' into an argv array. */
322       if ((argv = buildargv (args)) == NULL)
323         nomem (0);
324       else
325         make_cleanup_freeargv (argv);
326     }
327   while (argv != NULL && *argv != NULL)
328     {
329       if (isdigit (argv[0][0]))
330         {
331           pid = strtoul (argv[0], NULL, 10);
332         }
333       else if (strncmp (argv[0], "mappings", strlen (argv[0])) == 0)
334         {
335           mappings_f = 1;
336         }
337       else if (strcmp (argv[0], "status") == 0)
338         {
339           status_f = 1;
340         }
341       else if (strcmp (argv[0], "stat") == 0)
342         {
343           stat_f = 1;
344         }
345       else if (strcmp (argv[0], "cmd") == 0)
346         {
347           cmdline_f = 1;
348         }
349       else if (strncmp (argv[0], "exe", strlen (argv[0])) == 0)
350         {
351           exe_f = 1;
352         }
353       else if (strcmp (argv[0], "cwd") == 0)
354         {
355           cwd_f = 1;
356         }
357       else if (strncmp (argv[0], "all", strlen (argv[0])) == 0)
358         {
359           all = 1;
360         }
361       else
362         {
363           /* [...] (future options here) */
364         }
365       argv++;
366     }
367   if (pid == 0)
368     error ("No current process: you must name one.");
369
370   sprintf (fname1, "/proc/%lld", pid);
371   if (stat (fname1, &dummy) != 0)
372     error ("No /proc directory: '%s'", fname1);
373
374   printf_filtered ("process %lld\n", pid);
375   if (cmdline_f || all)
376     {
377       sprintf (fname1, "/proc/%lld/cmdline", pid);
378       if ((procfile = fopen (fname1, "r")) > 0)
379         {
380           fgets (buffer, sizeof (buffer), procfile);
381           printf_filtered ("cmdline = '%s'\n", buffer);
382           fclose (procfile);
383         }
384       else
385         warning ("unable to open /proc file '%s'", fname1);
386     }
387   if (cwd_f || all)
388     {
389       sprintf (fname1, "/proc/%lld/cwd", pid);
390       memset (fname2, 0, sizeof (fname2));
391       if (readlink (fname1, fname2, sizeof (fname2)) > 0)
392         printf_filtered ("cwd = '%s'\n", fname2);
393       else
394         warning ("unable to read link '%s'", fname1);
395     }
396   if (exe_f || all)
397     {
398       sprintf (fname1, "/proc/%lld/exe", pid);
399       memset (fname2, 0, sizeof (fname2));
400       if (readlink (fname1, fname2, sizeof (fname2)) > 0)
401         printf_filtered ("exe = '%s'\n", fname2);
402       else
403         warning ("unable to read link '%s'", fname1);
404     }
405   if (mappings_f || all)
406     {
407       sprintf (fname1, "/proc/%lld/maps", pid);
408       if ((procfile = fopen (fname1, "r")) > 0)
409         {
410           long long addr, endaddr, size, offset, inode;
411           char permissions[8], device[8], filename[MAXPATHLEN];
412           char *header_fmt_string, *data_fmt_string;
413
414           if (TARGET_ADDR_BIT == 32)
415             {
416               header_fmt_string = "\t%10s %10s %10s %10s %7s\n";
417               data_fmt_string   = "\t%#10lx %#10lx %#10x %#10x %7s\n";
418             }
419           else
420             {
421               header_fmt_string = "  %18s %18s %10s %10s %7s\n";
422               data_fmt_string   = "  %#18lx %#18lx %#10x %#10x %7s\n";
423             }
424
425           printf_filtered ("Mapped address spaces:\n\n");
426           printf_filtered (header_fmt_string, 
427                            "Start Addr",
428                            "  End Addr",
429                            "      Size",
430                            "    Offset",
431                            "objfile");
432           
433           while (read_mapping (procfile, &addr, &endaddr, &permissions[0], 
434                                &offset, &device[0], &inode, &filename[0]))
435             {
436               size = endaddr - addr;
437               printf_filtered (data_fmt_string, 
438                                (unsigned long) addr, /* FIXME: pr_addr */
439                                (unsigned long) endaddr, 
440                                (int) size, 
441                                (unsigned int) offset, 
442                                filename[0] ? filename : "");
443               
444             }
445
446           fclose (procfile);
447         }
448       else
449         warning ("unable to open /proc file '%s'", fname1);
450     }
451   if (status_f || all)
452     {
453       sprintf (fname1, "/proc/%lld/status", pid);
454       if ((procfile = fopen (fname1, "r")) > 0)
455         {
456           while (fgets (buffer, sizeof (buffer), procfile) != NULL)
457             printf_filtered (buffer);
458           fclose (procfile);
459         }
460       else 
461         warning ("unable to open /proc file '%s'", fname1);
462     }
463   if (stat_f || all)
464     {
465       sprintf (fname1, "/proc/%lld/stat", pid);
466       if ((procfile = fopen (fname1, "r")) > 0)
467         {
468           int itmp;
469           char ctmp;
470
471           if (fscanf (procfile, "%d ", &itmp) > 0)
472             printf_filtered ("Process: %d\n", itmp);
473           if (fscanf (procfile, "%s ", &buffer[0]) > 0)
474             printf_filtered ("Exec file: %s\n", buffer);
475           if (fscanf (procfile, "%c ", &ctmp) > 0)
476             printf_filtered ("State: %c\n", ctmp);
477           if (fscanf (procfile, "%d ", &itmp) > 0)
478             printf_filtered ("Parent process: %d\n", itmp);
479           if (fscanf (procfile, "%d ", &itmp) > 0)
480             printf_filtered ("Process group: %d\n", itmp);
481           if (fscanf (procfile, "%d ", &itmp) > 0)
482             printf_filtered ("Session id: %d\n", itmp);
483           if (fscanf (procfile, "%d ", &itmp) > 0)
484             printf_filtered ("TTY: %d\n", itmp);
485           if (fscanf (procfile, "%d ", &itmp) > 0)
486             printf_filtered ("TTY owner process group: %d\n", itmp);
487           if (fscanf (procfile, "%u ", &itmp) > 0)
488             printf_filtered ("Flags: 0x%x\n", itmp);
489           if (fscanf (procfile, "%u ", &itmp) > 0)
490             printf_filtered ("Minor faults (no memory page): %u\n", 
491                              (unsigned int) itmp);
492           if (fscanf (procfile, "%u ", &itmp) > 0)
493             printf_filtered ("Minor faults, children: %u\n", 
494                              (unsigned int) itmp);
495           if (fscanf (procfile, "%u ", &itmp) > 0)
496             printf_filtered ("Major faults (memory page faults): %u\n", 
497                              (unsigned int) itmp);
498           if (fscanf (procfile, "%u ", &itmp) > 0)
499             printf_filtered ("Major faults, children: %u\n", 
500                              (unsigned int) itmp);
501           if (fscanf (procfile, "%d ", &itmp) > 0)
502             printf_filtered ("utime: %d\n", itmp);
503           if (fscanf (procfile, "%d ", &itmp) > 0)
504             printf_filtered ("stime: %d\n", itmp);
505           if (fscanf (procfile, "%d ", &itmp) > 0)
506             printf_filtered ("utime, children: %d\n", itmp);
507           if (fscanf (procfile, "%d ", &itmp) > 0)
508             printf_filtered ("stime, children: %d\n", itmp);
509           if (fscanf (procfile, "%d ", &itmp) > 0)
510             printf_filtered ("jiffies remaining in current time slice: %d\n", 
511                              itmp);
512           if (fscanf (procfile, "%d ", &itmp) > 0)
513             printf_filtered ("'nice' value: %d\n", itmp);
514           if (fscanf (procfile, "%u ", &itmp) > 0)
515             printf_filtered ("jiffies until next timeout: %u\n", 
516                              (unsigned int) itmp);
517           if (fscanf (procfile, "%u ", &itmp) > 0)
518             printf_filtered ("jiffies until next SIGALRM: %u\n", 
519                              (unsigned int) itmp);
520           if (fscanf (procfile, "%d ", &itmp) > 0)
521             printf_filtered ("start time (jiffies since system boot): %d\n", 
522                              itmp);
523           if (fscanf (procfile, "%u ", &itmp) > 0)
524             printf_filtered ("Virtual memory size: %u\n", 
525                              (unsigned int) itmp);
526           if (fscanf (procfile, "%u ", &itmp) > 0)
527             printf_filtered ("Resident set size: %u\n", 
528                              (unsigned int) itmp);
529           if (fscanf (procfile, "%u ", &itmp) > 0)
530             printf_filtered ("rlim: %u\n", 
531                              (unsigned int) itmp);
532           if (fscanf (procfile, "%u ", &itmp) > 0)
533             printf_filtered ("Start of text: 0x%x\n", itmp);
534           if (fscanf (procfile, "%u ", &itmp) > 0)
535             printf_filtered ("End of text: 0x%x\n", itmp);
536           if (fscanf (procfile, "%u ", &itmp) > 0)
537             printf_filtered ("Start of stack: 0x%x\n", itmp);
538 #if 0   /* Don't know how architecture-dependent the rest is... 
539            Anyway the signal bitmap info is available from "status".  */
540           if (fscanf (procfile, "%u ", &itmp) > 0)      /* FIXME arch? */
541             printf_filtered ("Kernel stack pointer: 0x%x\n", itmp);
542           if (fscanf (procfile, "%u ", &itmp) > 0)      /* FIXME arch? */
543             printf_filtered ("Kernel instr pointer: 0x%x\n", itmp);
544           if (fscanf (procfile, "%d ", &itmp) > 0)
545             printf_filtered ("Pending signals bitmap: 0x%x\n", itmp);
546           if (fscanf (procfile, "%d ", &itmp) > 0)
547             printf_filtered ("Blocked signals bitmap: 0x%x\n", itmp);
548           if (fscanf (procfile, "%d ", &itmp) > 0)
549             printf_filtered ("Ignored signals bitmap: 0x%x\n", itmp);
550           if (fscanf (procfile, "%d ", &itmp) > 0)
551             printf_filtered ("Catched signals bitmap: 0x%x\n", itmp);
552           if (fscanf (procfile, "%u ", &itmp) > 0)      /* FIXME arch? */
553             printf_filtered ("wchan (system call): 0x%x\n", itmp);
554 #endif
555           fclose (procfile);
556         }
557       else
558         warning ("unable to open /proc file '%s'", fname1);
559     }
560 }
561
562 void
563 _initialize_linux_proc (void)
564 {
565   extern void inftarg_set_find_memory_regions ();
566   extern void inftarg_set_make_corefile_notes ();
567
568   inftarg_set_find_memory_regions (linux_find_memory_regions);
569   inftarg_set_make_corefile_notes (linux_make_note_section);
570
571   add_info ("proc", linux_info_proc_cmd, 
572             "Show /proc process information about any running process.\n\
573 Specify any process id, or use the program being debugged by default.\n\
574 Specify any of the following keywords for detailed info:\n\
575   mappings -- list of mapped memory regions.\n\
576   stat     -- list a bunch of random process info.\n\
577   status   -- list a different bunch of random process info.\n\
578   all      -- list all available /proc info.");
579 }
This page took 0.057937 seconds and 4 git commands to generate.