diff options
author | Rob Landley <rob@landley.net> | 2013-08-27 23:48:54 -0500 |
---|---|---|
committer | Rob Landley <rob@landley.net> | 2013-08-27 23:48:54 -0500 |
commit | 455865a837f2a6c44f91e5a5a2cd40c3a64d4b68 (patch) | |
tree | 6eb787bd75914d35c7d742e02dc7be9c279d3d03 | |
parent | 8b5c671958071ee2a9967551f0490623b73e30b5 (diff) | |
download | toybox-455865a837f2a6c44f91e5a5a2cd40c3a64d4b68.tar.gz |
Rewrite pmap to be simpler and match other implementation's output more closely.
-rw-r--r-- | lib/lib.c | 2 | ||||
-rw-r--r-- | toys/other/pmap.c | 111 | ||||
-rw-r--r-- | toys/pending/pmap.c | 128 |
3 files changed, 113 insertions, 128 deletions
@@ -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); - } - } -} |