[PATCH] Implement "info proc mappings" for NetBSD

Kamil Rytarowski n54@gmx.com
Thu Mar 19 13:07:59 GMT 2020


Ping?

I depend on this patch with more feature in "info proc" and

This one is mostly resuing prior art from the FreeBSD code.

On 16.03.2020 18:34, Kamil Rytarowski wrote:
> Define nbsd_nat_target::find_memory_regions and
> nbsd_nat_target::info_proc. info_proc handles as of now only
> the "mappings" command.
> 
> Define a local static function kinfo_get_vmmap() that reads
> the process memory layout of a specified process.
> kinfo_get_vmmap() wraps the sysctl(3) call.
> 
> nbsd-tdep.c defines now utility functions for printing the
> process memory layout:
>  * nbsd_info_proc_mappings_header()
>  * nbsd_vm_map_entry_flags()
>  * nbsd_info_proc_mappings_entry()
> 
> This code is based on the FreeBSD implementation.
> 
> gdb/ChangeLog:
> 
> 	* nbsd-nat.c; Include "nbsd-tdep.h", "inferior.h" and "gdbarch.h".
> 	* nbsd-nat.c (nbsd_nat_target::find_memory_regions)
> 	(nbsd_nat_target::info_proc): New functions.
> 	* nbsd-nat.c (kinfo_get_vmmap): New function.
> 	* nbsd-nat.c (nbsd_nat_target::info_proc) Use
> 	nbsd_info_proc_mappings_header and nbsd_info_proc_mappings_entry.
> 	* nbsd-tdep.c (nbsd_info_proc_mappings_header)
> 	(nbsd_info_proc_mappings_entry, nbsd_vm_map_entry_flags): New
> 	functions.
> 	* nbsd-tdep.c (KINFO_VME_PROT_READ, KINFO_VME_PROT_WRITE)
> 	(KINFO_VME_PROT_EXEC, KINFO_VME_FLAG_COW)
> 	(KINFO_VME_FLAG_NEEDS_COPY, KINFO_VME_FLAG_NOCOREDUMP)
> 	(KINFO_VME_FLAG_PAGEABLE, KINFO_VME_FLAG_GROWS_UP)
> 	(KINFO_VME_FLAG_GROWS_DOWN): New.
> ---
>  gdb/ChangeLog   |  17 ++++++
>  gdb/nbsd-nat.c  | 149 ++++++++++++++++++++++++++++++++++++++++++++++++
>  gdb/nbsd-nat.h  |   2 +
>  gdb/nbsd-tdep.c |  91 +++++++++++++++++++++++++++++
>  gdb/nbsd-tdep.h |  18 ++++++
>  5 files changed, 277 insertions(+)
> 
> diff --git a/gdb/ChangeLog b/gdb/ChangeLog
> index a0d97584189..b690222068a 100644
> --- a/gdb/ChangeLog
> +++ b/gdb/ChangeLog
> @@ -1,3 +1,20 @@
> +2020-03-16  Kamil Rytarowski  <n54@gmx.com>
> +
> +	* nbsd-nat.c; Include "nbsd-tdep.h", "inferior.h" and "gdbarch.h".
> +	* nbsd-nat.c (nbsd_nat_target::find_memory_regions)
> +	(nbsd_nat_target::info_proc): New functions.
> +	* nbsd-nat.c (kinfo_get_vmmap): New function.
> +	* nbsd-nat.c (nbsd_nat_target::info_proc) Use
> +	nbsd_info_proc_mappings_header and nbsd_info_proc_mappings_entry.
> +	* nbsd-tdep.c (nbsd_info_proc_mappings_header)
> +	(nbsd_info_proc_mappings_entry, nbsd_vm_map_entry_flags): New
> +	functions.
> +	* nbsd-tdep.c (KINFO_VME_PROT_READ, KINFO_VME_PROT_WRITE)
> +	(KINFO_VME_PROT_EXEC, KINFO_VME_FLAG_COW)
> +	(KINFO_VME_FLAG_NEEDS_COPY, KINFO_VME_FLAG_NOCOREDUMP)
> +	(KINFO_VME_FLAG_PAGEABLE, KINFO_VME_FLAG_GROWS_UP)
> +	(KINFO_VME_FLAG_GROWS_DOWN): New.
> +
>  2020-03-14  Tom Tromey  <tom@tromey.com>
> 
>  	* c-typeprint.c (cp_type_print_method_args): Print "__restrict__"
> diff --git a/gdb/nbsd-nat.c b/gdb/nbsd-nat.c
> index e7f91bebb0d..3cafd24b1dc 100644
> --- a/gdb/nbsd-nat.c
> +++ b/gdb/nbsd-nat.c
> @@ -20,6 +20,9 @@
>  #include "defs.h"
> 
>  #include "nbsd-nat.h"
> +#include "nbsd-tdep.h"
> +#include "inferior.h"
> +#include "gdbarch.h"
> 
>  /* Return the name of a file that can be opened to get the symbols for
>     the child process identified by PID.  */
> @@ -41,3 +44,149 @@ nbsd_nat_target::pid_to_exec_file (int pid)
> 
>    return NULL;
>  }
> +
> +/* Retrieve all the memory regions in the specified process.  */
> +
> +static struct kinfo_vmentry *
> +kinfo_get_vmmap(pid_t pid, size_t *size)
> +{
> +  int mib[5] = {CTL_VM, VM_PROC, VM_PROC_MAP, pid, sizeof(struct kinfo_vmentry)};
> +
> +  size_t length = 0;
> +  if (sysctl(mib, ARRAY_SIZE (mib), NULL, &length, NULL, 0)) {
> +    *size = 0;
> +    return NULL;
> +  }
> +
> +  /* Prereserve more space. */
> +  length = length * 5 / 3;
> +
> +  struct kinfo_vmentry *kiv = (struct kinfo_vmentry *) calloc(length, 1);
> +  if (kiv == NULL) {
> +    *size = 0;
> +    return NULL;
> +  }
> +
> +  if (sysctl(mib, ARRAY_SIZE (mib), kiv, &length, NULL, 0)) {
> +    *size = 0;
> +    free(kiv);
> +    return NULL;
> +  }
> +
> +  *size = length / sizeof(*kiv);
> +  return kiv;
> +}
> +
> +/* Iterate over all the memory regions in the current inferior,
> +   calling FUNC for each memory region.  OBFD is passed as the last
> +   argument to FUNC.  */
> +
> +int
> +nbsd_nat_target::find_memory_regions (find_memory_region_ftype func,
> +				      void *obfd)
> +{
> +  pid_t pid = inferior_ptid.pid ();
> +  struct kinfo_vmentry *kve;
> +  uint64_t size;
> +  int i;
> +  size_t nitems;
> +
> +  gdb::unique_xmalloc_ptr<struct kinfo_vmentry>
> +    vmentl (kinfo_get_vmmap (pid, &nitems));
> +  if (vmentl == NULL)
> +    perror_with_name (_("Couldn't fetch VM map entries."));
> +
> +  for (i = 0, kve = vmentl.get (); i < nitems; i++, kve++)
> +    {
> +      /* Skip unreadable segments and those where MAP_NOCORE has been set.  */
> +      if (!(kve->kve_protection & KVME_PROT_READ)
> +	  || kve->kve_flags & KVME_FLAG_NOCOREDUMP)
> +	continue;
> +
> +      /* Skip segments with an invalid type.  */
> +      switch (kve->kve_type) {
> +	case KVME_TYPE_VNODE:
> +	case KVME_TYPE_ANON:
> +	case KVME_TYPE_SUBMAP:
> +	case KVME_TYPE_OBJECT:
> +	  break;
> +	default:
> +	  continue;
> +      }
> +
> +      size = kve->kve_end - kve->kve_start;
> +      if (info_verbose)
> +	{
> +	  fprintf_filtered (gdb_stdout,
> +			    "Save segment, %ld bytes at %s (%c%c%c)\n",
> +			    (long) size,
> +			    paddress (target_gdbarch (), kve->kve_start),
> +			    kve->kve_protection & KVME_PROT_READ ? 'r' : '-',
> +			    kve->kve_protection & KVME_PROT_WRITE ? 'w' : '-',
> +			    kve->kve_protection & KVME_PROT_EXEC ? 'x' : '-');
> +	}
> +
> +      /* Invoke the callback function to create the corefile segment.
> +	 Pass MODIFIED as true, we do not know the real modification state.  */
> +      func (kve->kve_start, size, kve->kve_protection & KVME_PROT_READ,
> +	    kve->kve_protection & KVME_PROT_WRITE,
> +	    kve->kve_protection & KVME_PROT_EXEC, 1, obfd);
> +    }
> +  return 0;
> +}
> +
> +/* Implement the "info_proc" target_ops method.  */
> +
> +bool
> +nbsd_nat_target::info_proc (const char *args, enum info_proc_what what)
> +{
> +  pid_t pid;
> +  bool do_mappings = false;
> +
> +  switch (what)
> +    {
> +    case IP_MAPPINGS:
> +      do_mappings = true;
> +      break;
> +    default:
> +      error (_("Not supported on this target."));
> +    }
> +
> +  gdb_argv built_argv (args);
> +  if (built_argv.count () == 0)
> +    {
> +      pid = inferior_ptid.pid ();
> +      if (pid == 0)
> +        error (_("No current process: you must name one."));
> +    }
> +  else if (built_argv.count () == 1 && isdigit (built_argv[0][0]))
> +    pid = strtol (built_argv[0], NULL, 10);
> +  else
> +    error (_("Invalid arguments."));
> +
> +  printf_filtered (_("process %d\n"), pid);
> +
> +  if (do_mappings)
> +    {
> +      size_t nvment;
> +      gdb::unique_xmalloc_ptr<struct kinfo_vmentry>
> +	vmentl (kinfo_get_vmmap (pid, &nvment));
> +
> +      if (vmentl != nullptr)
> +	{
> +	  int addr_bit = TARGET_CHAR_BIT * sizeof (void *);
> +	  nbsd_info_proc_mappings_header (addr_bit);
> +
> +	  struct kinfo_vmentry *kve = vmentl.get ();
> +	  for (int i = 0; i < nvment; i++, kve++)
> +	    nbsd_info_proc_mappings_entry (addr_bit, kve->kve_start,
> +					   kve->kve_end, kve->kve_offset,
> +					   kve->kve_flags, kve->kve_protection,
> +					   kve->kve_path);
> +	}
> +      else
> +	warning (_("unable to fetch virtual memory map"));
> +    }
> +
> +  return true;
> +}
> diff --git a/gdb/nbsd-nat.h b/gdb/nbsd-nat.h
> index a752fbe572d..98af21d0bda 100644
> --- a/gdb/nbsd-nat.h
> +++ b/gdb/nbsd-nat.h
> @@ -27,6 +27,8 @@
>  struct nbsd_nat_target : public inf_ptrace_target
>  {
>    char *pid_to_exec_file (int pid) override;
> +  int find_memory_regions (find_memory_region_ftype func, void *data) override;
> +  bool info_proc (const char *, enum info_proc_what) override;
>  };
> 
>  #endif /* nbsd-nat.h */
> diff --git a/gdb/nbsd-tdep.c b/gdb/nbsd-tdep.c
> index 49bb2b706bd..23732854172 100644
> --- a/gdb/nbsd-tdep.c
> +++ b/gdb/nbsd-tdep.c
> @@ -23,6 +23,23 @@
>  #include "solib-svr4.h"
>  #include "nbsd-tdep.h"
> 
> +/* Flags in the 'kve_protection' field in struct kinfo_vmentry.  These
> +   match the KVME_PROT_* constants in <sys/sysctl.h>.  */
> +
> +#define	KINFO_VME_PROT_READ	0x00000001
> +#define	KINFO_VME_PROT_WRITE	0x00000002
> +#define	KINFO_VME_PROT_EXEC	0x00000004
> +
> +/* Flags in the 'kve_flags' field in struct kinfo_vmentry.  These
> +   match the KVME_FLAG_* constants in <sys/sysctl.h>.  */
> +
> +#define	KINFO_VME_FLAG_COW		0x00000001
> +#define	KINFO_VME_FLAG_NEEDS_COPY	0x00000002
> +#define	KINFO_VME_FLAG_NOCOREDUMP	0x00000004
> +#define	KINFO_VME_FLAG_PAGEABLE		0x00000008
> +#define	KINFO_VME_FLAG_GROWS_UP		0x00000010
> +#define	KINFO_VME_FLAG_GROWS_DOWN	0x00000020
> +
>  /* FIXME: kettenis/20060115: We should really eliminate the next two
>     functions completely.  */
> 
> @@ -47,3 +64,77 @@ nbsd_pc_in_sigtramp (CORE_ADDR pc, const char *func_name)
>    return (func_name != NULL
>  	  && startswith (func_name, "__sigtramp"));
>  }
> +
> +/* See fbsd-tdep.h.  */
> +
> +void
> +nbsd_info_proc_mappings_header (int addr_bit)
> +{
> +  printf_filtered (_("Mapped address spaces:\n\n"));
> +  if (addr_bit == 64)
> +    {
> +      printf_filtered ("  %18s %18s %10s %10s %9s %s\n",
> +		       "Start Addr",
> +		       "  End Addr",
> +		       "      Size", "    Offset", "Flags  ", "File");
> +    }
> +  else
> +    {
> +      printf_filtered ("\t%10s %10s %10s %10s %9s %s\n",
> +		       "Start Addr",
> +		       "  End Addr",
> +		       "      Size", "    Offset", "Flags  ", "File");
> +    }
> +}
> +
> +/* Helper function to generate mappings flags for a single VM map
> +   entry in 'info proc mappings'.  */
> +
> +static const char *
> +nbsd_vm_map_entry_flags (int kve_flags, int kve_protection)
> +{
> +  static char vm_flags[9];
> +
> +  vm_flags[0] = (kve_protection & KINFO_VME_PROT_READ) ? 'r' : '-';
> +  vm_flags[1] = (kve_protection & KINFO_VME_PROT_WRITE) ? 'w' : '-';
> +  vm_flags[2] = (kve_protection & KINFO_VME_PROT_EXEC) ? 'x' : '-';
> +  vm_flags[3] = ' ';
> +  vm_flags[4] = (kve_flags & KINFO_VME_FLAG_COW) ? 'C' : '-';
> +  vm_flags[5] = (kve_flags & KINFO_VME_FLAG_NEEDS_COPY) ? 'N' : '-';
> +  vm_flags[6] = (kve_flags & KINFO_VME_FLAG_PAGEABLE) ? 'P' : '-';
> +  vm_flags[7] = (kve_flags & KINFO_VME_FLAG_GROWS_UP) ? 'U'
> +    : (kve_flags & KINFO_VME_FLAG_GROWS_DOWN) ? 'D' : '-';
> +  vm_flags[8] = '\0';
> +
> +  return vm_flags;
> +}
> +
> +/* See nbsd-tdep.h.  */
> +
> +void
> +nbsd_info_proc_mappings_entry (int addr_bit, ULONGEST kve_start,
> +			       ULONGEST kve_end, ULONGEST kve_offset,
> +			       int kve_flags, int kve_protection,
> +			       const void *kve_path)
> +{
> +  if (addr_bit == 64)
> +    {
> +      printf_filtered ("  %18s %18s %10s %10s %9s %s\n",
> +		       hex_string (kve_start),
> +		       hex_string (kve_end),
> +		       hex_string (kve_end - kve_start),
> +		       hex_string (kve_offset),
> +		       nbsd_vm_map_entry_flags (kve_flags, kve_protection),
> +		       reinterpret_cast<const char *> (kve_path));
> +    }
> +  else
> +    {
> +      printf_filtered ("\t%10s %10s %10s %10s %9s %s\n",
> +		       hex_string (kve_start),
> +		       hex_string (kve_end),
> +		       hex_string (kve_end - kve_start),
> +		       hex_string (kve_offset),
> +		       nbsd_vm_map_entry_flags (kve_flags, kve_protection),
> +		       reinterpret_cast<const char *> (kve_path));
> +    }
> +}
> diff --git a/gdb/nbsd-tdep.h b/gdb/nbsd-tdep.h
> index c99a8b537b6..81bdb2510f5 100644
> --- a/gdb/nbsd-tdep.h
> +++ b/gdb/nbsd-tdep.h
> @@ -25,4 +25,22 @@ struct link_map_offsets *nbsd_lp64_solib_svr4_fetch_link_map_offsets (void);
> 
>  int nbsd_pc_in_sigtramp (CORE_ADDR, const char *);
> 
> +/* Output the header for "info proc mappings".  ADDR_BIT is the size
> +   of a virtual address in bits.  */
> +
> +extern void nbsd_info_proc_mappings_header (int addr_bit);
> +
> +/* Output description of a single memory range for "info proc
> +   mappings".  ADDR_BIT is the size of a virtual address in bits.  The
> +   KVE_START, KVE_END, KVE_OFFSET, KVE_FLAGS, and KVE_PROTECTION
> +   parameters should contain the value of the corresponding fields in
> +   a 'struct kinfo_vmentry'.  The KVE_PATH parameter should contain a
> +   pointer to the 'kve_path' field in a 'struct kinfo_vmentry'. */
> +
> +extern void nbsd_info_proc_mappings_entry (int addr_bit, ULONGEST kve_start,
> +					   ULONGEST kve_end,
> +					   ULONGEST kve_offset,
> +					   int kve_flags, int kve_protection,
> +					   const void *kve_path);
> +
>  #endif /* NBSD_TDEP_H */
> --
> 2.25.0
> 


-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: OpenPGP digital signature
URL: <http://sourceware.org/pipermail/gdb-patches/attachments/20200319/1e68df71/attachment-0001.sig>


More information about the Gdb-patches mailing list