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
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
pmap_main(void)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