This is the mail archive of the gdb-patches@sources.redhat.com mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[RFA] procfs.c: iterating over memory regions.



There are two functions now that iterate over memory regions, 
and I'm about to add a third.  This patch implements a single
general-purpose iterator over memory regions using callbacks, 
and reimplements the existing functions (shared libraries and
info proc mappings) in terms of the new iterator.

2001-12-28  Michael Snyder  <msnyder@redhat.com>

	Abstract the functionality of iterating over mapped memory
	regions into a general purpose iterator function.
	procfs.c (iterate_over_mappings): New function, general purpose 
	iterator for memory sections.
	(proc_iterate_over_mappings): Reimplement using iterate_over_mappings.
	(solib_mappings_callback): New function, callback for above.
	(info_proc_mappings): Reimpliment using iterate_over_mappings.
	(info_mappings_callback): New function, callback for above.

	* procfs.c (proc_set_watchpoint): Add cast to suppress warning.

Index: procfs.c
===================================================================
RCS file: /cvs/src/src/gdb/procfs.c,v
retrieving revision 1.33
diff -c -3 -p -r1.33 procfs.c
*** procfs.c	2001/12/28 19:47:08	1.33
--- procfs.c	2001/12/28 20:59:42
*************** proc_set_watchpoint (procinfo *pi, CORE_
*** 2848,2854 ****
    prwatch_t *pwatch;
  
    pwatch            = (prwatch_t *) &arg.watch;
!   pwatch->pr_vaddr  = address_to_host_pointer (addr);
    pwatch->pr_size   = len;
    pwatch->pr_wflags = wflags;
  #if defined(NEW_PROC_API) && defined (PCWATCH)
--- 2848,2858 ----
    prwatch_t *pwatch;
  
    pwatch            = (prwatch_t *) &arg.watch;
! #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)
*************** proc_set_watchpoint (procinfo *pi, CORE_
*** 2865,2979 ****
  #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.
-  */
- 
- 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>
--- 2869,2874 ----
*************** procfs_find_LDT_entry (ptid_t ptid)
*** 5308,5313 ****
--- 5203,5360 ----
  #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.
*************** mappingflags (flags)
*** 5340,5345 ****
--- 5387,5423 ----
  }
  
  /*
+  * 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.
*************** mappingflags (flags)
*** 5348,5406 ****
  static void
  info_proc_mappings (procinfo *pi, int summary)
  {
!   char *header_fmt_string, *data_fmt_string;
!   char pathname[MAX_PROC_NAME_SIZE];
!   struct prmap *prmaps;
!   struct prmap *prmap;
!   int map_fd;
!   int nmap;
! #ifdef NEW_PROC_API
!   struct stat sbuf;
! #endif
  
    if (TARGET_PTR_BIT == 32)
!     {
!       header_fmt_string = "\t%10s %10s %10s %10s %7s\n";
!       data_fmt_string   = "\t%#10lx %#10lx %#10x %#10x %7s\n";
!     }
    else
!     {
!       header_fmt_string = "  %18s %18s %10s %10s %7s\n";
!       data_fmt_string   = "  %#18lx %#18lx %#10x %#10x %7s\n";
!     }
  
    if (summary)
      return;	/* No output for summary mode. */
  
-   /* 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)
-     return;		/* Can't open map file. */
-   /* 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)
-     return;		/* Can't stat file.  */
- 
-   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)))
-     return;		/* Can't read file. */
- #else
-   /* Use ioctl command PIOCNMAP to get number of mappings.  */
-   if (ioctl (pi->ctl_fd, PIOCNMAP, &nmap) != 0)
-     return;	/* Can't get number of mappings.  */
-   prmaps = (struct prmap *) alloca ((nmap + 1) * sizeof (*prmaps));
-   if (ioctl (pi->ctl_fd, PIOCMAP, prmaps) != 0)
-     return;	/* Can't read mappings. */
- #endif
- 
    printf_filtered ("Mapped address spaces:\n\n");
    printf_filtered (header_fmt_string, 
  		   "Start Addr",
--- 5426,5441 ----
  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",
*************** info_proc_mappings (procinfo *pi, int su
*** 5409,5428 ****
  		   "    Offset",
  		   "Flags");
  
!   for (prmap = prmaps; nmap > 0; prmap++, nmap--)
!     {
!       printf_filtered (data_fmt_string, 
! 		       (unsigned long) prmap->pr_vaddr,
! 		       (unsigned long) prmap->pr_vaddr
! 		       + prmap->pr_size - 1,
! 		       prmap->pr_size,
! #ifdef PCAGENT		/* Gross hack: only defined on Solaris 2.6+ */
! 		       (unsigned int) prmap->pr_offset, 
! #else
! 		       prmap->pr_off,
! #endif
! 		       mappingflags (prmap->pr_mflags));
!     }
    printf_filtered ("\n");
  }
  
--- 5444,5450 ----
  		   "    Offset",
  		   "Flags");
  
!   iterate_over_mappings (pi, NULL, NULL, info_mappings_callback);
    printf_filtered ("\n");
  }
  


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]