xref: /aosp_15_r20/external/toybox/toys/other/pmap.c (revision cf5a6c84e2b8763fc1a7db14496fd4742913b199)
1 /* pmap.c - Reports the memory map of a process or processes.
2  *
3  * Copyright 2013 Ranjan Kumar <[email protected]>
4  * Copyright 2013 Kyungwan Han <[email protected]>
5  *
6  * No Standard.
7  *
8  * TODO: two passes so we can auto-size the columns?
9 
10 USE_PMAP(NEWTOY(pmap, "<1pqx", TOYFLAG_USR|TOYFLAG_BIN))
11 
12 config PMAP
13   bool "pmap"
14   default y
15   help
16     usage: pmap [-pqx] PID...
17 
18     Report the memory map of a process or processes.
19 
20     -p	Show full paths
21     -q	Do not show header or footer
22     -x	Show the extended format
23 */
24 
25 #define FOR_pmap
26 #include "toys.h"
27 
pmap_main(void)28 void pmap_main(void)
29 {
30   char **optargs, *line = 0;
31   size_t len = 0;
32 
33   for (optargs = toys.optargs; *optargs; optargs++) {
34     long long start, end, pss, tpss=0, dirty, tdirty=0, swap, tswap=0, total=0;
35     char *name = 0, *k = "K"+FLAG(x), mode[5];
36     pid_t pid = atolx(*optargs);
37     int extras = 0, off, count;
38     FILE *fp;
39 
40     sprintf(toybuf, "/proc/%u/cmdline", pid);
41     if (!(name = readfile(toybuf, 0, 0))) {
42       error_msg("no %s", toybuf);
43       continue;
44     }
45     xprintf("%d: %s\n", pid, name);
46     free(name);
47 
48     // Only bother scanning the more verbose smaps file in -x mode.
49     sprintf(toybuf, "/proc/%u/%smaps", pid, "s"+!FLAG(x));
50     if (!(fp = fopen(toybuf, "r"))) {
51       error_msg("no %s", toybuf);
52       continue;
53     }
54 
55     if (FLAG(x) && !FLAG(q))
56       xprintf("Address%*cKbytes     PSS   Dirty    Swap Mode  Mapping\n",
57           (int)(sizeof(long)*2)-5, ' ');
58 
59     while (getline(&line, &len, fp) > 0) {
60       count = sscanf(line, "%llx-%llx %4s %*s %*s %*s %n", &start, &end, mode,
61           &off);
62       if (count == 3) {
63         name = line[off] ? line+off : "  [anon]\n";
64         if (mode[3] == 'p') mode[3] = '-';
65         total += end = (end-start)/1024;
66         printf("%0*llx % *lld%s ", (int)(2*sizeof(long)), start, 6+FLAG(x),
67             end, k);
68         if (FLAG(x)) {
69           strcpy(toybuf, name);
70           name = toybuf;
71           continue;
72         }
73       } else {
74         if (sscanf(line, "Pss: %lld", &pss) ||
75             sscanf(line, "Private_Dirty: %lld", &dirty) ||
76             sscanf(line, "Swap: %lld", &swap)) extras++;
77         if (extras==3) {
78           printf("% 7lld %7lld %7lld ", pss, dirty, swap);
79           tpss += pss;
80           tdirty += dirty;
81           tswap += swap;
82           extras = 0;
83         } else continue;
84       }
85 
86       xprintf("%s- %s%s", mode, *name == '[' ? "  " : "",
87               FLAG(p) ? name : basename(name));
88     }
89 
90     if (!FLAG(q)) {
91       if (FLAG(x)) {
92         xprintf("----------------  ------  ------  ------  ------\n" +
93             ((sizeof(long)==4)?8:0));
94       }
95       printf("total% *lld%s", 2*(int)(sizeof(long)+1)+FLAG(x), total, k);
96       if (FLAG(x)) printf("% 8lld% 8lld% 8lld", tpss, tdirty, tswap);
97       xputc('\n');
98     }
99 
100     fclose(fp);
101   }
102   free(line);
103 }
104