10f66f451Sopenharmony_ci/* pmap.c - Reports the memory map of a process or processes.
20f66f451Sopenharmony_ci *
30f66f451Sopenharmony_ci * Copyright 2013 Ranjan Kumar <ranjankumar.bth@gmail.com>
40f66f451Sopenharmony_ci * Copyright 2013 Kyungwan Han <asura321@gmail.com>
50f66f451Sopenharmony_ci *
60f66f451Sopenharmony_ci * No Standard.
70f66f451Sopenharmony_ci
80f66f451Sopenharmony_ciUSE_PMAP(NEWTOY(pmap, "<1xq", TOYFLAG_USR|TOYFLAG_BIN))
90f66f451Sopenharmony_ci
100f66f451Sopenharmony_ciconfig PMAP
110f66f451Sopenharmony_ci  bool "pmap"
120f66f451Sopenharmony_ci  default y
130f66f451Sopenharmony_ci  help
140f66f451Sopenharmony_ci    usage: pmap [-xq] [pids...]
150f66f451Sopenharmony_ci
160f66f451Sopenharmony_ci    Report the memory map of a process or processes.
170f66f451Sopenharmony_ci
180f66f451Sopenharmony_ci    -x	Show the extended format
190f66f451Sopenharmony_ci    -q	Do not display some header/footer lines
200f66f451Sopenharmony_ci*/
210f66f451Sopenharmony_ci
220f66f451Sopenharmony_ci#define FOR_pmap
230f66f451Sopenharmony_ci#include "toys.h"
240f66f451Sopenharmony_ci
250f66f451Sopenharmony_civoid pmap_main(void)
260f66f451Sopenharmony_ci{
270f66f451Sopenharmony_ci  char **optargs;
280f66f451Sopenharmony_ci
290f66f451Sopenharmony_ci  for (optargs = toys.optargs; *optargs; optargs++) {
300f66f451Sopenharmony_ci    pid_t pid = atolx(*optargs);
310f66f451Sopenharmony_ci    FILE *fp;
320f66f451Sopenharmony_ci    char *line, *oldline = 0, *name = 0,
330f66f451Sopenharmony_ci         *k = (toys.optflags & FLAG_x) ? "" : "K";
340f66f451Sopenharmony_ci    size_t len;
350f66f451Sopenharmony_ci    long long start, end, pss, tpss = 0, dirty, tdirty = 0, swap, tswap = 0,
360f66f451Sopenharmony_ci              total = 0;
370f66f451Sopenharmony_ci    int xx = 0;
380f66f451Sopenharmony_ci
390f66f451Sopenharmony_ci    snprintf(toybuf, sizeof(toybuf), "/proc/%u/cmdline", pid);
400f66f451Sopenharmony_ci    line = readfile(toybuf, 0, 0);
410f66f451Sopenharmony_ci    if (!line) error_msg("No %lu", (long)pid);
420f66f451Sopenharmony_ci    xprintf("%u: %s\n", (int)pid, line);
430f66f451Sopenharmony_ci    free(line);
440f66f451Sopenharmony_ci
450f66f451Sopenharmony_ci    // Header
460f66f451Sopenharmony_ci    // Only use the more verbose file in -x mode
470f66f451Sopenharmony_ci    sprintf(toybuf, "/proc/%u/%smaps", pid,
480f66f451Sopenharmony_ci      (toys.optflags & FLAG_x) ? "s" : "");
490f66f451Sopenharmony_ci    if (!(fp = fopen(toybuf, "r"))) {
500f66f451Sopenharmony_ci      error_msg("No %ld\n", (long)pid);
510f66f451Sopenharmony_ci      return;
520f66f451Sopenharmony_ci    }
530f66f451Sopenharmony_ci
540f66f451Sopenharmony_ci    if ((toys.optflags & (FLAG_q|FLAG_x)) == FLAG_x)
550f66f451Sopenharmony_ci      xprintf("Address%*cKbytes     PSS   Dirty    Swap  Mode  Mapping\n",
560f66f451Sopenharmony_ci        (int)(sizeof(long)*2)-4, ' ');
570f66f451Sopenharmony_ci
580f66f451Sopenharmony_ci    // Loop through mappings
590f66f451Sopenharmony_ci    for (;;) {
600f66f451Sopenharmony_ci      int off, count;
610f66f451Sopenharmony_ci
620f66f451Sopenharmony_ci      line = 0;
630f66f451Sopenharmony_ci      if (0 >= getline(&line, &len, fp)) break;
640f66f451Sopenharmony_ci      count = sscanf(line, "%llx-%llx %s %*s %*s %*s %n",
650f66f451Sopenharmony_ci        &start, &end, toybuf, &off);
660f66f451Sopenharmony_ci
670f66f451Sopenharmony_ci      if (count == 3) {
680f66f451Sopenharmony_ci        name = line[off] ? line+off : "  [anon]\n";
690f66f451Sopenharmony_ci        if (toybuf[3] == 'p') toybuf[3] = '-';
700f66f451Sopenharmony_ci        total += end = (end-start)/1024;
710f66f451Sopenharmony_ci        printf("%0*llx % *lld%s ", (int)(2*sizeof(long)), start,
720f66f451Sopenharmony_ci          6+!!(toys.optflags & FLAG_x), end, k);
730f66f451Sopenharmony_ci        if (toys.optflags & FLAG_x) {
740f66f451Sopenharmony_ci          oldline = line;
750f66f451Sopenharmony_ci          continue;
760f66f451Sopenharmony_ci        }
770f66f451Sopenharmony_ci      } else {
780f66f451Sopenharmony_ci        if (0<sscanf(line, "Pss: %lld", &pss)
790f66f451Sopenharmony_ci            || 0<sscanf(line, "Private_Dirty: %lld", &dirty)
800f66f451Sopenharmony_ci            || 0<sscanf(line, "Swap: %lld", &swap)) xx++;
810f66f451Sopenharmony_ci        free(line);
820f66f451Sopenharmony_ci        if (xx<3) continue;
830f66f451Sopenharmony_ci        line = oldline;
840f66f451Sopenharmony_ci        name = basename(name);
850f66f451Sopenharmony_ci        xx = 0;
860f66f451Sopenharmony_ci        printf("% 7lld %7lld %7lld ", pss, dirty, swap);
870f66f451Sopenharmony_ci        tpss += pss;
880f66f451Sopenharmony_ci        tdirty += dirty;
890f66f451Sopenharmony_ci        tswap += swap;
900f66f451Sopenharmony_ci      }
910f66f451Sopenharmony_ci
920f66f451Sopenharmony_ci      xprintf("%s-  %s%s", toybuf, line[off]=='[' ? "  " : "", name);
930f66f451Sopenharmony_ci
940f66f451Sopenharmony_ci      free(line);
950f66f451Sopenharmony_ci      line = 0;
960f66f451Sopenharmony_ci    }
970f66f451Sopenharmony_ci
980f66f451Sopenharmony_ci    // Trailer
990f66f451Sopenharmony_ci    if (!(toys.optflags & FLAG_q)) {
1000f66f451Sopenharmony_ci      int x = !!(toys.optflags & FLAG_x);
1010f66f451Sopenharmony_ci      if (x) {
1020f66f451Sopenharmony_ci        memset(toybuf, '-', 16);
1030f66f451Sopenharmony_ci        xprintf("%.*s  ------  ------  ------  ------\n", (int)(sizeof(long)*2),
1040f66f451Sopenharmony_ci          toybuf);
1050f66f451Sopenharmony_ci      }
1060f66f451Sopenharmony_ci      printf("total% *lld%s", 2*(int)(sizeof(long)+1)+x, total, k);
1070f66f451Sopenharmony_ci      if (x) printf("% 8lld% 8lld% 8lld", tpss, tdirty, tswap);
1080f66f451Sopenharmony_ci      xputc('\n');
1090f66f451Sopenharmony_ci    }
1100f66f451Sopenharmony_ci
1110f66f451Sopenharmony_ci    fclose(fp);
1120f66f451Sopenharmony_ci  }
1130f66f451Sopenharmony_ci}
114