]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blobdiff - gdb/procfs.c
2001-12-28 Michael Snyder <msnyder@redhat.com>
[thirdparty/binutils-gdb.git] / gdb / procfs.c
index 53f04896035190a0298b5e683145c76f214160e3..32b4e6054f31cab045af393b69adfd29e0545d6d 100644 (file)
@@ -315,18 +315,6 @@ typedef prstatus_t gdb_prstatus_t;
 typedef prstatus_t gdb_lwpstatus_t;
 #endif /* NEW_PROC_API */
 
-
-/* Provide default composite pid manipulation macros for systems that
-   don't have threads. */
-
-#ifndef PIDGET
-#define PIDGET(PID)            (PID)
-#define TIDGET(PID)            (PID)
-#endif
-#ifndef MERGEPID
-#define MERGEPID(PID, TID)     (PID)
-#endif
-
 typedef struct procinfo {
   struct procinfo *next;
   int pid;                     /* Process ID    */
@@ -686,6 +674,9 @@ create_procinfo (int pid, int tid)
   load_syscalls (pi);
 #endif
 
+  pi->saved_entryset = sysset_t_alloc (pi);
+  pi->saved_exitset = sysset_t_alloc (pi);
+
   /* Chain into list.  */
   if (tid == 0)
     {
@@ -755,6 +746,8 @@ destroy_one_procinfo (procinfo **list, procinfo *pi)
 #ifdef DYNAMIC_SYSCALLS
   free_syscalls (pi);
 #endif
+  xfree (pi->saved_entryset);
+  xfree (pi->saved_exitset);
   xfree (pi);
 }
 
@@ -2855,7 +2848,11 @@ proc_set_watchpoint (procinfo *pi, CORE_ADDR addr, int len, int wflags)
   prwatch_t *pwatch;
 
   pwatch            = (prwatch_t *) &arg.watch;
-  pwatch->pr_vaddr  = address_to_host_pointer (addr);
+#ifdef PCAGENT /* Horrible hack: only defined on Solaris 2.6+ */
+  pwatch->pr_vaddr  = (uintptr_t) address_to_host_pointer (addr);
+#else
+  pwatch->pr_vaddr  = (caddr_t) address_to_host_pointer (addr);
+#endif
   pwatch->pr_size   = len;
   pwatch->pr_wflags = wflags;
 #if defined(NEW_PROC_API) && defined (PCWATCH)
@@ -2872,118 +2869,6 @@ proc_set_watchpoint (procinfo *pi, CORE_ADDR addr, int len, int wflags)
 #endif
 }
 
-/*
- * Function: proc_iterate_over_mappings
- *
- * Given a pointer to a function, call that function once for every
- * mapped address space in the process.  The callback function 
- * receives an open file descriptor for the file corresponding to
- * that mapped address space (if there is one), and the base address
- * of the mapped space.  Quit when the callback function returns a
- * nonzero value, or at teh end of the mappings.
- *
- * Returns: the first non-zero return value of the callback function,
- * or zero.
- */
-
-/* FIXME: it's probably a waste to cache this FD. 
-   It doesn't get called that often... and if I open it
-   every time, I don't need to lseek it.  */
-int
-proc_iterate_over_mappings (int (*func) (int, CORE_ADDR))
-{
-  struct prmap *map;
-  procinfo *pi;
-#ifndef NEW_PROC_API   /* avoid compiler warning */
-  int nmaps = 0;
-  int i;
-#else
-  int map_fd;
-  char pathname[MAX_PROC_NAME_SIZE];
-#endif
-  int funcstat = 0;
-  int fd;
-
-  pi = find_procinfo_or_die (PIDGET (inferior_ptid), 0);
-
-#ifdef NEW_PROC_API
-  /* Open map fd.  */
-  sprintf (pathname, "/proc/%d/map", pi->pid);
-  if ((map_fd = open_with_retry (pathname, O_RDONLY)) < 0)
-    proc_error (pi, "proc_iterate_over_mappings (open)", __LINE__);
-
-  /* Make sure it gets closed again.  */
-  make_cleanup_close (map_fd);
-
-  /* Allocate space for mapping (lifetime only for this function). */
-  map = alloca (sizeof (struct prmap));
-
-  /* Now read the mappings from the file, 
-     open a file descriptor for those that have a name, 
-     and call the callback function.  */
-  while (read (map_fd, 
-              (void *) map, 
-              sizeof (struct prmap)) == sizeof (struct prmap))
-    {
-      char name[MAX_PROC_NAME_SIZE + sizeof (map->pr_mapname)];
-
-      if (map->pr_vaddr == 0 && map->pr_size == 0)
-       break;          /* sanity */
-
-      if (map->pr_mapname[0] == 0)
-       {
-         fd = -1;      /* no map file */
-       }
-      else
-       {
-         sprintf (name, "/proc/%d/object/%s", pi->pid, map->pr_mapname);
-         /* Note: caller's responsibility to close this fd!  */
-         fd = open_with_retry (name, O_RDONLY);
-         /* Note: we don't test the above call for failure;
-            we just pass the FD on as given.  Sometimes there is 
-            no file, so the ioctl may return failure, but that's
-            not a problem.  */
-       }
-
-      /* Stop looping if the callback returns non-zero.  */
-      if ((funcstat = (*func) (fd, (CORE_ADDR) map->pr_vaddr)) != 0)
-       break;
-    }  
-#else
-  /* Get the number of mapping entries.  */
-  if (ioctl (pi->ctl_fd, PIOCNMAP, &nmaps) < 0)
-    proc_error (pi, "proc_iterate_over_mappings (PIOCNMAP)", __LINE__);
-
-  /* Allocate space for mappings (lifetime only this function).  */
-  map = (struct prmap *) alloca ((nmaps + 1) * sizeof (struct prmap));
-
-  /* Read in all the mappings.  */
-  if (ioctl (pi->ctl_fd, PIOCMAP, map) < 0)
-    proc_error (pi, "proc_iterate_over_mappings (PIOCMAP)", __LINE__);
-
-  /* Now loop through the mappings, open an fd for each, and
-     call the callback function.  */
-  for (i = 0; 
-       i < nmaps && map[i].pr_size != 0; 
-       i++)
-    {
-      /* Note: caller's responsibility to close this fd!  */
-      fd = ioctl (pi->ctl_fd, PIOCOPENM, &map[i].pr_vaddr);
-      /* Note: we don't test the above call for failure;
-        we just pass the FD on as given.  Sometimes there is 
-        no file, so the ioctl may return failure, but that's
-        not a problem.  */
-
-      /* Stop looping if the callback returns non-zero.  */
-      funcstat = (*func) (fd, host_pointer_to_address (map[i].pr_vaddr));
-      if (funcstat != 0)
-       break;
-    }
-#endif
-
-  return funcstat;
-}
-
 #ifdef TM_I386SOL2_H           /* Is it hokey to use this? */
 
 #include <sys/sysi86.h>
@@ -4547,10 +4432,7 @@ procfs_resume (ptid_t ptid, int step, enum target_signal signo)
     {
       /* Resume a specific thread, presumably suppressing the others. */
       thread = find_procinfo (PIDGET (ptid), TIDGET (ptid));
-      if (thread == NULL)
-       warning ("procfs: resume can't find thread %ld -- resuming all.",
-                TIDGET (ptid));
-      else
+      if (thread != NULL)
        {
          if (thread->tid != 0)
            {
@@ -5320,18 +5202,269 @@ procfs_find_LDT_entry (ptid_t ptid)
 }
 #endif /* TM_I386SOL2_H */
 
+/*
+ * Memory Mappings Functions:
+ */
 
+/* 
+ * Function: iterate_over_mappings
+ *
+ * Call a callback function once for each mapping, passing it the mapping,
+ * an optional secondary callback function, and some optional opaque data.
+ * Quit and return the first non-zero value returned from the callback.
+ *
+ * Arguments:
+ *   pi   -- procinfo struct for the process to be mapped.
+ *   func -- callback function to be called by this iterator.
+ *   data -- optional opaque data to be passed to the callback function.
+ *   child_func -- optional secondary function pointer to be passed
+ *                 to the child function.
+ *
+ * Return: First non-zero return value from the callback function, 
+ *         or zero.
+ */
+
+static int
+iterate_over_mappings (procinfo *pi, int (*child_func) (), void *data, 
+                      int (*func) (struct prmap *map, 
+                                   int (*child_func) (), 
+                                   void *data))
+{
+  char pathname[MAX_PROC_NAME_SIZE];
+  struct prmap *prmaps;
+  struct prmap *prmap;
+  int funcstat;
+  int map_fd;
+  int nmap;
+#ifdef NEW_PROC_API
+  struct stat sbuf;
+#endif
+
+  /* Get the number of mappings, allocate space, 
+     and read the mappings into prmaps.  */
+#ifdef NEW_PROC_API
+  /* Open map fd. */
+  sprintf (pathname, "/proc/%d/map", pi->pid);
+  if ((map_fd = open (pathname, O_RDONLY)) < 0)
+    proc_error (pi, "iterate_over_mappings (open)", __LINE__);
+
+  /* Make sure it gets closed again. */
+  make_cleanup_close (map_fd);
+
+  /* Use stat to determine the file size, and compute 
+     the number of prmap_t objects it contains.  */
+  if (fstat (map_fd, &sbuf) != 0)
+    proc_error (pi, "iterate_over_mappings (fstat)", __LINE__);
+
+  nmap = sbuf.st_size / sizeof (prmap_t);
+  prmaps = (struct prmap *) alloca ((nmap + 1) * sizeof (*prmaps));
+  if (read (map_fd, (char *) prmaps, nmap * sizeof (*prmaps))
+      != (nmap * sizeof (*prmaps)))
+    proc_error (pi, "iterate_over_mappings (read)", __LINE__);
+#else
+  /* Use ioctl command PIOCNMAP to get number of mappings.  */
+  if (ioctl (pi->ctl_fd, PIOCNMAP, &nmap) != 0)
+    proc_error (pi, "iterate_over_mappings (PIOCNMAP)", __LINE__);
+
+  prmaps = (struct prmap *) alloca ((nmap + 1) * sizeof (*prmaps));
+  if (ioctl (pi->ctl_fd, PIOCMAP, prmaps) != 0)
+    proc_error (pi, "iterate_over_mappings (PIOCMAP)", __LINE__);
+#endif
+
+  for (prmap = prmaps; nmap > 0; prmap++, nmap--)
+    if ((funcstat = (*func) (prmap, child_func, data)) != 0)
+      return funcstat;
+
+  return 0;
+}
+
+/*
+ * Function: solib_mappings_callback
+ *
+ * Calls the supplied callback function once for each mapped address 
+ * space in the process.  The callback function  receives an open 
+ * file descriptor for the file corresponding to that mapped 
+ * address space (if there is one), and the base address of the 
+ * mapped space.  Quit when the callback function returns a
+ * nonzero value, or at teh end of the mappings.
+ *
+ * Returns: the first non-zero return value of the callback function,
+ * or zero.
+ */
+
+int solib_mappings_callback (struct prmap *map, 
+                            int (*func) (int, CORE_ADDR),
+                            void *data)
+{
+  procinfo *pi = data;
+  int fd;
+
+#ifdef NEW_PROC_API
+  char name[MAX_PROC_NAME_SIZE + sizeof (map->pr_mapname)];
+
+  if (map->pr_vaddr == 0 && map->pr_size == 0)
+    return -1;         /* sanity */
+
+  if (map->pr_mapname[0] == 0)
+    {
+      fd = -1; /* no map file */
+    }
+  else
+    {
+      sprintf (name, "/proc/%d/object/%s", pi->pid, map->pr_mapname);
+      /* Note: caller's responsibility to close this fd!  */
+      fd = open_with_retry (name, O_RDONLY);
+      /* Note: we don't test the above call for failure;
+        we just pass the FD on as given.  Sometimes there is 
+        no file, so the open may return failure, but that's
+        not a problem.  */
+    }
+#else
+  fd = ioctl (pi->ctl_fd, PIOCOPENM, &map->pr_vaddr);
+  /* Note: we don't test the above call for failure;
+     we just pass the FD on as given.  Sometimes there is 
+     no file, so the ioctl may return failure, but that's
+     not a problem.  */
+#endif
+  return (*func) (fd, (CORE_ADDR) map->pr_vaddr);
+}
+
+/*
+ * Function: proc_iterate_over_mappings
+ *
+ * Uses the unified "iterate_over_mappings" function
+ * to implement the exported interface to solib-svr4.c.
+ *
+ * Given a pointer to a function, call that function once for every
+ * mapped address space in the process.  The callback function 
+ * receives an open file descriptor for the file corresponding to
+ * that mapped address space (if there is one), and the base address
+ * of the mapped space.  Quit when the callback function returns a
+ * nonzero value, or at teh end of the mappings.
+ *
+ * Returns: the first non-zero return value of the callback function,
+ * or zero.
+ */
+
+int
+proc_iterate_over_mappings (int (*func) (int, CORE_ADDR))
+{
+  procinfo *pi = find_procinfo_or_die (PIDGET (inferior_ptid), 0);
+
+  return iterate_over_mappings (pi, func, pi, solib_mappings_callback);
+}
+
+/*
+ * Function: mappingflags
+ *
+ * Returns an ascii representation of a memory mapping's flags.
+ */
+
+static char *
+mappingflags (flags)
+     long flags;
+{
+  static char asciiflags[8];
+
+  strcpy (asciiflags, "-------");
+#if defined (MA_PHYS)
+  if (flags & MA_PHYS)
+    asciiflags[0] = 'd';
+#endif
+  if (flags & MA_STACK)
+    asciiflags[1] = 's';
+  if (flags & MA_BREAK)
+    asciiflags[2] = 'b';
+  if (flags & MA_SHARED)
+    asciiflags[3] = 's';
+  if (flags & MA_READ)
+    asciiflags[4] = 'r';
+  if (flags & MA_WRITE)
+    asciiflags[5] = 'w';
+  if (flags & MA_EXEC)
+    asciiflags[6] = 'x';
+  return (asciiflags);
+}
+
+/*
+ * Function: info_mappings_callback
+ *
+ * Callback function, does the actual work for 'info proc mappings'.
+ */
+
+/* ARGSUSED */
+static int
+info_mappings_callback (struct prmap *map, int (*ignore) (), void *unused)
+{
+  char *data_fmt_string;
+
+  if (TARGET_ADDR_BIT == 32)
+    data_fmt_string   = "\t%#10lx %#10lx %#10x %#10x %7s\n";
+  else
+    data_fmt_string   = "  %#18lx %#18lx %#10x %#10x %7s\n";
+
+  printf_filtered (data_fmt_string, 
+                  (unsigned long) map->pr_vaddr,
+                  (unsigned long) map->pr_vaddr + map->pr_size - 1,
+                  map->pr_size,
+#ifdef PCAGENT /* Horrible hack: only defined on Solaris 2.6+ */
+                  (unsigned int) map->pr_offset, 
+#else
+                  map->pr_off,
+#endif
+                  mappingflags (map->pr_mflags));
+
+  return 0;
+}
+
+/*
+ * Function: info_proc_mappings
+ *
+ * Implement the "info proc mappings" subcommand.
+ */
+
+static void
+info_proc_mappings (procinfo *pi, int summary)
+{
+  char *header_fmt_string;
+
+  if (TARGET_PTR_BIT == 32)
+    header_fmt_string = "\t%10s %10s %10s %10s %7s\n";
+  else
+    header_fmt_string = "  %18s %18s %10s %10s %7s\n";
+
+  if (summary)
+    return;    /* No output for summary mode. */
+
+  printf_filtered ("Mapped address spaces:\n\n");
+  printf_filtered (header_fmt_string, 
+                  "Start Addr",
+                  "  End Addr",
+                  "      Size",
+                  "    Offset",
+                  "Flags");
+
+  iterate_over_mappings (pi, NULL, NULL, info_mappings_callback);
+  printf_filtered ("\n");
+}
+
+/*
+ * Function: info_proc_cmd
+ *
+ * Implement the "info proc" command.
+ */
 
 static void
 info_proc_cmd (char *args, int from_tty)
 {
   struct cleanup *old_chain;
-  procinfo *process = NULL;
-  procinfo *thread  = NULL;
-  char    **argv    = NULL;
-  char     *tmp     = NULL;
-  int       pid     = 0;
-  int       tid     = 0;
+  procinfo *process  = NULL;
+  procinfo *thread   = NULL;
+  char    **argv     = NULL;
+  char     *tmp      = NULL;
+  int       pid      = 0;
+  int       tid      = 0;
+  int       mappings = 0;
 
   old_chain = make_cleanup (null_cleanup, 0);
   if (args)
@@ -5353,6 +5486,10 @@ info_proc_cmd (char *args, int from_tty)
        {
          tid = strtoul (argv[0] + 1, NULL, 10);
        }
+      else if (strncmp (argv[0], "mappings", strlen (argv[0])) == 0)
+       {
+         mappings = 1;
+       }
       else
        {
          /* [...] */
@@ -5399,6 +5536,11 @@ info_proc_cmd (char *args, int from_tty)
        proc_prettyprint_why (proc_why (thread), proc_what (thread), 1);
     }
 
+  if (mappings)
+    {
+      info_proc_mappings (process, 0);
+    }
+
   do_cleanups (old_chain);
 }
 
@@ -5476,8 +5618,9 @@ _initialize_procfs (void)
   init_procfs_ops ();
   add_target (&procfs_ops);
   add_info ("proc", info_proc_cmd, 
-           "Show /proc process information about any running process.\
-Default is the process being debugged.");
+           "Show /proc process information about any running process.\n\
+Specify process id, or use the program being debugged by default.\n\
+Specify keyword 'mappings' for detailed info on memory mappings.");
   add_com ("proc-trace-entry", no_class, proc_trace_sysentry_cmd, 
           "Give a trace of entries into the syscall.");
   add_com ("proc-trace-exit", no_class, proc_trace_sysexit_cmd,