pmap.c revision 6db8529a785e2cab142e840b6e3fbdcc2c02dd1f
1/* pmap.c - Reports the memory map of a process or processes.
2 *
3 * Copyright 2013 Ranjan Kumar <ranjankumar.bth@gmail.com>
4 * Copyright 2013 Kyungwan Han <asura321@gmail.com>
5 *
6 * No Standard.
7
8USE_PMAP(NEWTOY(pmap, "<1xq", TOYFLAG_BIN))
9
10config 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
25void 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 count, 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        (sizeof(long)*2)-4, ' ');
57
58    // Loop through mappings
59    for (;;) {
60      int off;
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