diff options
Diffstat (limited to 'toys')
-rw-r--r-- | toys/pending/pmap.c | 128 |
1 files changed, 128 insertions, 0 deletions
diff --git a/toys/pending/pmap.c b/toys/pending/pmap.c new file mode 100644 index 00000000..7d54c430 --- /dev/null +++ b/toys/pending/pmap.c @@ -0,0 +1,128 @@ +/* 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); + } + } +} |