summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--utils/ChangeLog7
-rw-r--r--utils/vminfo.c231
2 files changed, 238 insertions, 0 deletions
diff --git a/utils/ChangeLog b/utils/ChangeLog
index 6e2a24e3..6b97d653 100644
--- a/utils/ChangeLog
+++ b/utils/ChangeLog
@@ -1,3 +1,10 @@
+Fri Aug 30 16:54:57 1996 Miles Bader <miles@gnu.ai.mit.edu>
+
+ * vminfo.c: New file.
+ * Makefile (targets): Add vminfo.
+ (SRCS): Add vminfo.c.
+ (INSTALL-vminfo-ops): New variable.
+
Mon Aug 19 15:19:20 1996 Miles Bader <miles@gnu.ai.mit.edu>
* devprobe.c, fsysopts.c, hurdids.c, login.c, portinfo.c, ps.c,
diff --git a/utils/vminfo.c b/utils/vminfo.c
new file mode 100644
index 00000000..e570589a
--- /dev/null
+++ b/utils/vminfo.c
@@ -0,0 +1,231 @@
+/* Print task vm information
+
+ Copyright (C) 1996 Free Software Foundation, Inc.
+
+ Written by Miles Bader <miles@gnu.ai.mit.edu>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include <stdio.h>
+#include <stddef.h>
+#include <argp.h>
+#include <error.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+#include <mach.h>
+#include <mach/vm_statistics.h>
+#include <mach/default_pager.h>
+#include <hurd.h>
+
+char *argp_program_version = "vminfo 1.0 (GNU " HURD_RELEASE ")";
+
+static const struct argp_option options[] = {
+ {"verbose", 'v', 0, 0, "Give more detailed information"},
+ {"addresses", 'a', 0, 0, "Print region start addresses"},
+ {"sizes", 's', 0, 0, "Print region sizes"},
+ {"decimal", 'd', 0, 0, "Show number is decimal"},
+ {"holes", 'h', 0, 0, "Show holes between regions explicitly"},
+ {0}
+};
+static const char *args_doc = "PID [ADDR [SIZE]]]";
+static const char *doc = "Show virtual memory regions for process PID"
+"\vIf ADDR, and possibly SIZE, are given only regions enclosing the range"
+" ADDR to ADDR+SIZE are shown (SIZE defaults to 0)."
+"\nIf neither --addresses nor --sizes is specified, both are assumed.";
+
+/* Possible things to show about regions. */
+#define W_ADDRS 0x1
+#define W_SIZES 0x2
+#define W_DETAILS 0x4
+
+static char *
+prot_rep (vm_prot_t prot)
+{
+ if (prot == 0)
+ return "0";
+ else
+ {
+ static char buf[20];
+ char *p = buf;
+ if (prot & VM_PROT_READ)
+ *p++ = 'R';
+ if (prot & VM_PROT_WRITE)
+ *p++ = 'W';
+ if (prot & VM_PROT_EXECUTE)
+ *p++ = 'X';
+ if (prot & ~VM_PROT_ALL)
+ sprintf (p, "+%#x", (prot & ~VM_PROT_ALL));
+ else
+ *p = '\0';
+ return buf;
+ }
+}
+
+static char *
+inh_rep (vm_inherit_t inh)
+{
+ static char buf[20];
+ switch (inh)
+ {
+ case VM_INHERIT_SHARE: return "share";
+ case VM_INHERIT_COPY: return "copy";
+ case VM_INHERIT_NONE: return "none";
+ default:
+ sprintf (buf, "%d", inh);
+ return buf;
+ }
+}
+
+static unsigned
+parse_num (char *arg, unsigned base, struct argp_state *state, char *what)
+{
+ char *arg_end;
+ unsigned long num = strtoul (arg, &arg_end, base);
+ if (*arg == '\0' || *arg_end != '\0')
+ argp_error (state, "%s: Invalid %s", arg, what);
+ return num;
+}
+
+int
+main (int argc, char **argv)
+{
+ error_t err;
+ int what = 0, hex = 1, holes = 0;
+ vm_offset_t addr = 0, max_addr = ~addr;
+ task_t task;
+
+ /* Parse our options... */
+ error_t parse_opt (int key, char *arg, struct argp_state *state)
+ {
+ switch (key)
+ {
+ pid_t pid;
+ process_t proc;
+
+ case 'a': what |= W_ADDRS; break;
+ case 's': what |= W_SIZES; break;
+ case 'v': what |= W_DETAILS; break;
+ case 'd': hex = 0; break;
+ case 'h': holes = 1; break;
+
+ case ARGP_KEY_ARG:
+ switch (state->arg_num)
+ {
+ case 0: /* PID */
+ pid = parse_num (arg, 10, state, "PID");
+ proc = getproc ();
+ err = proc_pid2task (proc, pid, &task);
+ if (err)
+ argp_failure (state, 11, err, "%s", arg);
+ break;
+ case 1: /* ADDR */
+ addr = max_addr = parse_num (arg, 0, state, "address"); break;
+ case 2: /* SIZE */
+ max_addr = addr + parse_num (arg, 0, state, "size"); break;
+ default:
+ argp_usage (state);
+ }
+ break;
+
+ case ARGP_KEY_NO_ARGS:
+ argp_usage (state);
+
+ default:
+ return ARGP_ERR_UNKNOWN;
+ }
+ return 0;
+ }
+ const struct argp argp = { options, parse_opt, args_doc, doc };
+
+ /* Parse our arguments. */
+ argp_parse (&argp, argc, argv, 0, 0, 0);
+
+ if ((what & ~W_DETAILS) == 0)
+ what = W_ADDRS | W_SIZES | W_DETAILS;
+
+ while (addr <= max_addr)
+ {
+ vm_size_t size;
+ vm_prot_t prot, max_prot;
+ mach_port_t obj;
+ vm_offset_t offs;
+ vm_inherit_t inh;
+ int shared;
+ vm_offset_t hole_addr = addr;
+
+ err =
+ vm_region (task, &addr, &size, &prot, &max_prot, &inh, &shared,
+ &obj, &offs);
+ if (err)
+ {
+ if (err != EKERN_NO_SPACE)
+ error (12, err, "vm_region");
+ break;
+ }
+
+ if (holes && hole_addr != addr)
+ if ((what & (W_ADDRS|W_SIZES)) == (W_ADDRS|W_SIZES))
+ if (hex)
+ printf (" [%#x] (hole)\n", addr - hole_addr);
+ else
+ printf (" [%d] (hole)\n", addr - hole_addr);
+ else if ((what & (W_ADDRS|W_SIZES)) == W_SIZES)
+ if (hex)
+ printf ("%#10x (hole)\n", addr - hole_addr);
+ else
+ printf ("%10u (hole)\n", addr - hole_addr);
+
+ if ((what & (W_ADDRS|W_SIZES)) == (W_ADDRS|W_SIZES))
+ if (hex)
+ printf ("%#10x[%#x]", addr, size);
+ else
+ printf ("%10u[%d]", addr, size);
+ else if ((what & (W_ADDRS|W_SIZES)) == W_ADDRS)
+ if (hex)
+ printf ("%#10x", addr);
+ else
+ printf ("%10u", addr);
+ else if ((what & (W_ADDRS|W_SIZES)) == W_SIZES)
+ if (hex)
+ printf ("%#10x", size);
+ else
+ printf ("%10u", size);
+ if (what & W_DETAILS)
+ {
+ printf (" (prot=%s", prot_rep (prot));
+ if (max_prot != prot)
+ printf (", max_prot=%s", prot_rep (max_prot));
+ if (inh != VM_INHERIT_DEFAULT)
+ printf (", inherit=%s", inh_rep (inh));
+ if (shared)
+ printf (", shared");
+ if (obj != MACH_PORT_NULL)
+ printf (", mem_obj=%d", obj);
+ if (offs != 0)
+ if (hex)
+ printf (", offs=%#x", offs);
+ else
+ printf (", offs=%d", offs);
+ putchar (')');
+ }
+ putchar ('\n');
+
+ addr += size;
+ }
+
+ exit (0);
+}