Home | History | Annotate | Download | only in other
      1 /* pmap.c - Reports the memory map of a process or processes.
      2  *
      3  * Copyright 2013 Ranjan Kumar <ranjankumar.bth (at) gmail.com>
      4  * Copyright 2013 Kyungwan Han <asura321 (at) gmail.com>
      5  *
      6  * No Standard.
      7 
      8 USE_PMAP(NEWTOY(pmap, "<1xq", TOYFLAG_BIN))
      9 
     10 config PMAP
     11   bool "pmap"
     12   default y
     13   help
     14     usage: pmap [-xq] [pids...]
     15 
     16     Reports the memory map of a process or processes.
     17 
     18     -x Show the extended format.
     19     -q Do not display some header/footer lines.
     20 */
     21 
     22 #define FOR_pmap
     23 #include "toys.h"
     24 
     25 void pmap_main(void)
     26 {
     27   char **optargs;
     28 
     29   for (optargs = toys.optargs; *optargs; optargs++) {
     30     pid_t pid = atolx(*optargs);
     31     FILE *fp;
     32     char *line, *oldline = 0, *name = 0,
     33          *k = (toys.optflags & FLAG_x) ? "" : "K";
     34     size_t len;
     35     long long start, end, pss, tpss = 0, dirty, tdirty = 0, swap, tswap = 0,
     36               total = 0;
     37     int xx = 0;
     38 
     39     snprintf(toybuf, sizeof(toybuf), "/proc/%u/cmdline", pid);
     40     line = readfile(toybuf, 0, 0);
     41     if (!line) error_msg("No %lu", (long)pid);
     42     xprintf("%u: %s\n", (int)pid, line);
     43     free(line);
     44 
     45     // Header
     46     // Only use the more verbose file in -x mode
     47     sprintf(toybuf, "/proc/%u/%smaps", pid,
     48       (toys.optflags & FLAG_x) ? "s" : "");
     49     if (!(fp = fopen(toybuf, "r"))) {
     50       error_msg("No %ld\n", (long)pid);
     51       return;
     52     }
     53 
     54     if ((toys.optflags & (FLAG_q|FLAG_x)) == FLAG_x)
     55       xprintf("Address%*cKbytes     PSS   Dirty    Swap  Mode  Mapping\n",
     56         (int)(sizeof(long)*2)-4, ' ');
     57 
     58     // Loop through mappings
     59     for (;;) {
     60       int off, count;
     61 
     62       line = 0;
     63       if (0 >= getline(&line, &len, fp)) break;
     64       count = sscanf(line, "%llx-%llx %s %*s %*s %*s %n",
     65         &start, &end, toybuf, &off);
     66 
     67       if (count == 3) {
     68         name = line[off] ? line+off : "  [anon]\n";
     69         if (toybuf[3] == 'p') toybuf[3] = '-';
     70         total += end = (end-start)/1024;
     71         printf("%0*llx % *lld%s ", (int)(2*sizeof(long)), start,
     72           6+!!(toys.optflags & FLAG_x), end, k);
     73         if (toys.optflags & FLAG_x) {
     74           oldline = line;
     75           continue;
     76         }
     77       } else {
     78         if (0<sscanf(line, "Pss: %lld", &pss)
     79             || 0<sscanf(line, "Private_Dirty: %lld", &dirty)
     80             || 0<sscanf(line, "Swap: %lld", &swap)) xx++;
     81         free(line);
     82         if (xx<3) continue;
     83         line = oldline;
     84         name = basename(name);
     85         xx = 0;
     86         printf("% 7lld %7lld %7lld ", pss, dirty, swap);
     87         tpss += pss;
     88         tdirty += dirty;
     89         tswap += swap;
     90       }
     91 
     92       xprintf("%s-  %s%s", toybuf, line[off]=='[' ? "  " : "", name);
     93 
     94       free(line);
     95       line = 0;
     96     }
     97 
     98     // Trailer
     99     if (!(toys.optflags & FLAG_q)) {
    100       int x = !!(toys.optflags & FLAG_x);
    101       if (x) {
    102         memset(toybuf, '-', 16);
    103         xprintf("%.*s  ------  ------  ------  ------\n", (int)(sizeof(long)*2),
    104           toybuf);
    105       }
    106       printf("total% *lld%s", 2*(int)(sizeof(long)+1)+x, total, k);
    107       if (x) printf("% 8lld% 8lld% 8lld", tpss, tdirty, tswap);
    108       xputc('\n');
    109     }
    110 
    111     fclose(fp);
    112   }
    113 }
    114