aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRob Landley <rob@landley.net>2013-08-27 23:48:54 -0500
committerRob Landley <rob@landley.net>2013-08-27 23:48:54 -0500
commit455865a837f2a6c44f91e5a5a2cd40c3a64d4b68 (patch)
tree6eb787bd75914d35c7d742e02dc7be9c279d3d03
parent8b5c671958071ee2a9967551f0490623b73e30b5 (diff)
downloadtoybox-455865a837f2a6c44f91e5a5a2cd40c3a64d4b68.tar.gz
Rewrite pmap to be simpler and match other implementation's output more closely.
-rw-r--r--lib/lib.c2
-rw-r--r--toys/other/pmap.c111
-rw-r--r--toys/pending/pmap.c128
3 files changed, 113 insertions, 128 deletions
diff --git a/lib/lib.c b/lib/lib.c
index 7f4413ad..58670921 100644
--- a/lib/lib.c
+++ b/lib/lib.c
@@ -325,6 +325,8 @@ char *readfile(char *name)
fd = open(name, O_RDONLY);
if (fd == -1) return 0;
len = fdlength(fd);
+ // proc files don't report a length, so try 1 page minimum.
+ if (len<4096) len = 4095;
buf = xmalloc(len+1);
buf[readall(fd, buf, len)] = 0;
diff --git a/toys/other/pmap.c b/toys/other/pmap.c
new file mode 100644
index 00000000..012280dd
--- /dev/null
+++ b/toys/other/pmap.c
@@ -0,0 +1,111 @@
+/* pmap.c - Reports the memory map of a process or processes.
+ *
+ * Copyright 2013 Ranjan Kumar <ranjankumar.bth@gmail.com>
+ * Copyright 2013 Kyungwan Han <asura321@gmail.com>
+ *
+ * No Standard.
+
+USE_PMAP(NEWTOY(pmap, "<1xq", TOYFLAG_BIN))
+
+config PMAP
+ bool "pmap"
+ default y
+ help
+ usage: pmap [-xq] [pids...]
+
+ Reports the memory map of a process or processes.
+
+ -x Show the extended format.
+ -q Do not display some header/footer lines.
+*/
+
+#define FOR_pmap
+#include "toys.h"
+
+void pmap_main(void)
+{
+ while (*toys.optargs) {
+ pid_t pid = atolx(*toys.optargs++);
+ FILE *fp;
+ char *line, *oldline = 0, *name = 0,
+ *k = (toys.optflags & FLAG_x) ? "" : "K";
+ size_t len;
+ long long start, end, pss, tpss = 0, dirty, tdirty = 0, swap, tswap = 0,
+ total = 0;
+ int count, xx = 0;
+
+ snprintf(toybuf, sizeof(toybuf), "/proc/%u/cmdline", pid);
+ line = readfile(toybuf);
+ if (!line) error_msg("No %lu", (long)pid);
+ xprintf("%u: %s\n", (int)pid, line);
+ free(line);
+
+ // Header
+ // Only use the more verbose file in -x mode
+ sprintf(toybuf, "/proc/%u/%smaps", pid,
+ (toys.optflags & FLAG_x) ? "s" : "");
+ if (!(fp = fopen(toybuf, "r"))) {
+ error_msg("No %ld\n", (long)pid);
+ return;
+ }
+
+ if ((toys.optflags & (FLAG_q|FLAG_x)) == FLAG_x)
+ xprintf("Address%*cKbytes PSS Dirty Swap Mode Mapping\n",
+ (sizeof(long)*2)-4, ' ');
+
+ // Loop through mappings
+ for (;;) {
+ int off;
+
+ line = 0;
+ if (0 >= getline(&line, &len, fp)) break;
+ count = sscanf(line, "%llx-%llx %s %*s %*s %*s %n",
+ &start, &end, toybuf, &off);
+
+ if (count == 3) {
+ name = line[off] ? line+off : " [anon]\n";
+ if (toybuf[3] == 'p') toybuf[3] = '-';
+ total += end = (end-start)/1024;
+ printf("%0*llx % *lld%s ", (int)(2*sizeof(long)), start,
+ 6+!!(toys.optflags & FLAG_x), end, k);
+ if (toys.optflags & FLAG_x) {
+ oldline = line;
+ continue;
+ }
+ } else {
+ if (0<sscanf(line, "Pss: %lld", &pss)
+ || 0<sscanf(line, "Private_Dirty: %lld", &dirty)
+ || 0<sscanf(line, "Swap: %lld", &swap)) xx++;
+ free(line);
+ if (xx<3) continue;
+ line = oldline;
+ name = basename(name);
+ xx = 0;
+ printf("% 7lld %7lld %7lld ", pss, dirty, swap);
+ tpss += pss;
+ tdirty += dirty;
+ tswap += swap;
+ }
+
+ xprintf("%s- %s%s", toybuf, line[off]=='[' ? " " : "", name);
+
+ free(line);
+ line = 0;
+ }
+
+ // Trailer
+ if (!(toys.optflags & FLAG_q)) {
+ int x = !!(toys.optflags & FLAG_x);
+ if (x) {
+ memset(toybuf, '-', 16);
+ xprintf("%.*s ------ ------ ------ ------\n", (int)(sizeof(long)*2),
+ toybuf);
+ }
+ printf("total% *lld%s", 2*(int)(sizeof(long)+1)+x, total, k);
+ if (x) printf("% 8lld% 8lld% 8lld", tpss, tdirty, tswap);
+ xputc('\n');
+ }
+
+ fclose(fp);
+ }
+}
diff --git a/toys/pending/pmap.c b/toys/pending/pmap.c
deleted file mode 100644
index 7d54c430..00000000
--- a/toys/pending/pmap.c
+++ /dev/null
@@ -1,128 +0,0 @@
-/* pmap.c - Reports the memory map of a process or processes.
- *
- * Copyright 2013 Ranjan Kumar <ranjankumar.bth@gmail.com>
- * Copyright 2013 Kyungwan Han <asura321@gmail.com>
- *
- * No Standard.
- *
-USE_PMAP(NEWTOY(pmap, "xq", TOYFLAG_BIN))
-
-config PMAP
- bool "pmap"
- default y
- help
- usage: pmap [-xq] [pids...]
-
- Reports the memory map of a process or processes.
-
- -x Show the extended format.
- -q Do not display some header/footer lines.
-*/
-#define FOR_pmap
-#include "toys.h"
-
-#if ULONG_MAX == 0xffffffff
- # define TAB "\t"
- # define WIDTH "8"
- # define DASHES ""
-#else
- # define TAB "\t\t"
- # define WIDTH "16"
- # define DASHES "--------"
-#endif
-
-struct _smaps {
- unsigned long start_addr, size, pss, pdirty, swap;
- char mode[5], *mapping;
-};
-
-//Display mapping info.
-static void show_maps(struct _smaps *map)
-{
- xprintf("%0" WIDTH "lx ", map->start_addr);
- if (toys.optflags & FLAG_x)
- xprintf("%7lu %7lu %7lu %7lu ", map->size, map->pss, map->pdirty, map->swap);
- else xprintf("%7luK", map->size);
- xprintf(" %.4s \n", map->mode, map->mapping);
- free(map->mapping);
-}
-
-//Read "/proc/pid/smaps" file and extract data.
-static int read_smaps(pid_t pid, struct _smaps *total)
-{
- struct _smaps curmap;
- char *line;
- int fd, nitems;
-
- snprintf(toybuf, sizeof(toybuf), "/proc/%u/smaps", pid);
- if ((fd = open(toybuf, O_RDONLY)) < 0) return fd;
- memset(&curmap, 0, sizeof(struct _smaps));
- while ((line = get_line(fd))) {
- char *ptr = NULL;
- *toybuf = *(toybuf+34) = *(toybuf+40) = '\0';
- //1st line format -> start_addr-End_addr rw-s ADR M:m OFS
- if ((ptr = strchr(line, '-'))) {
- if (curmap.size) show_maps(&curmap);
- memset(&curmap, 0, sizeof(struct _smaps));
- nitems = sscanf(line, "%s %s %*s %*s %*s %s\n", toybuf, toybuf+34, toybuf+40);
- if (nitems >= 2) {
- ptr = strchr(toybuf, '-');
- *ptr = '\0';
- total->size += curmap.size = (strtoul(++ptr, NULL, 16) -
- (curmap.start_addr = strtoul(toybuf, NULL, 16))) >> 10;
- strncpy(curmap.mode, toybuf+34, sizeof(curmap.mode)-1);
- if (!*(toybuf+40)) curmap.mapping = xstrdup(" [ anon ]");
- else curmap.mapping = xstrdup(toybuf+40);
- }
- } else { //2nd line onwards..
- unsigned long val = 0;
- nitems = sscanf(line, "%s %lu\n", toybuf, &val);
- if (nitems == 2) {
- if (!strcmp("Pss:", toybuf)) total->pss += (curmap.pss = val);
- else if (!strcmp("Private_Dirty:", toybuf)) total->pdirty += (curmap.pdirty = val);
- else if (!strcmp("Swap:", toybuf)) total->swap += (curmap.swap = val);
- }
- }
- free(line);
- }
- if (curmap.size) show_maps(&curmap);
- xclose(fd);
- return 0;
-}
-
-void pmap_main(void)
-{
- struct _smaps total;
- int fd;
-
- while (*toys.optargs) {
- pid_t pid = get_int_value(*toys.optargs++, 0, INT_MAX);
- snprintf(toybuf, sizeof(toybuf), "/proc/%u/cmdline", pid);
- if ((fd = open(toybuf, O_RDONLY)) == -1) xprintf("%u: [no such process]\n", pid);
- else {
- ssize_t len = readall(fd, toybuf, sizeof(toybuf) -1);
- if (len <= 0) xprintf("%u: [no such process]\n", (int)pid);
- else {
- toybuf[len] = '\0';
- while (--len >= 0 && toybuf[len] == '\0') continue;
- for (; len > 0; len--)
- if ((unsigned char)toybuf[len] < ' ') toybuf[len] = ' ';
- xprintf("%u: %s\n", (int)pid, toybuf);
- }
- xclose(fd);
- }
- if (!(toys.optflags & FLAG_q) && (toys.optflags & FLAG_x))
- xprintf("Address" TAB " Kbytes PSS Dirty Swap Mode Mapping\n");
-
- memset(&total, 0, sizeof(struct _smaps));
- if (read_smaps(pid, &total)) toys.exitval = 42;
- else { //to display total mapping.
- if (!(toys.optflags & FLAG_q) )
- (toys.optflags & FLAG_x)
- ? xprintf("--------" DASHES " ------ ------ ------ ------\n"
- "total" TAB " %7lu %7lu %7lu %7lu\n",
- total.size, total.pss, total.pdirty, total.swap)
- : xprintf("mapped: %luK\n", total.size);
- }
- }
-}