| /* pmap.c - Reports the memory map of a process or processes. |
| * |
| * Copyright 2013 Ranjan Kumar <ranjankumar.bth@gmail.com> |
| * Copyright 2013 Kyungwan Han <asura321@gmail.com> |
| * |
| * No Standard. |
| |
| USE_PMAP(NEWTOY(pmap, "<1xq", TOYFLAG_BIN)) |
| |
| config PMAP |
| bool "pmap" |
| default y |
| help |
| usage: pmap [-xq] [pids...] |
| |
| Reports the memory map of a process or processes. |
| |
| -x Show the extended format. |
| -q Do not display some header/footer lines. |
| */ |
| |
| #define FOR_pmap |
| #include "toys.h" |
| |
| void pmap_main(void) |
| { |
| char **optargs; |
| |
| for (optargs = toys.optargs; *optargs; optargs++) { |
| pid_t pid = atolx(*optargs); |
| FILE *fp; |
| char *line, *oldline = 0, *name = 0, |
| *k = (toys.optflags & FLAG_x) ? "" : "K"; |
| size_t len; |
| long long start, end, pss, tpss = 0, dirty, tdirty = 0, swap, tswap = 0, |
| total = 0; |
| int xx = 0; |
| |
| snprintf(toybuf, sizeof(toybuf), "/proc/%u/cmdline", pid); |
| line = readfile(toybuf, 0, 0); |
| if (!line) error_msg("No %lu", (long)pid); |
| xprintf("%u: %s\n", (int)pid, line); |
| free(line); |
| |
| // Header |
| // Only use the more verbose file in -x mode |
| sprintf(toybuf, "/proc/%u/%smaps", pid, |
| (toys.optflags & FLAG_x) ? "s" : ""); |
| if (!(fp = fopen(toybuf, "r"))) { |
| error_msg("No %ld\n", (long)pid); |
| return; |
| } |
| |
| if ((toys.optflags & (FLAG_q|FLAG_x)) == FLAG_x) |
| xprintf("Address%*cKbytes PSS Dirty Swap Mode Mapping\n", |
| (int)(sizeof(long)*2)-4, ' '); |
| |
| // Loop through mappings |
| for (;;) { |
| int off, count; |
| |
| line = 0; |
| if (0 >= getline(&line, &len, fp)) break; |
| count = sscanf(line, "%llx-%llx %s %*s %*s %*s %n", |
| &start, &end, toybuf, &off); |
| |
| if (count == 3) { |
| name = line[off] ? line+off : " [anon]\n"; |
| if (toybuf[3] == 'p') toybuf[3] = '-'; |
| total += end = (end-start)/1024; |
| printf("%0*llx % *lld%s ", (int)(2*sizeof(long)), start, |
| 6+!!(toys.optflags & FLAG_x), end, k); |
| if (toys.optflags & FLAG_x) { |
| oldline = line; |
| continue; |
| } |
| } else { |
| if (0<sscanf(line, "Pss: %lld", &pss) |
| || 0<sscanf(line, "Private_Dirty: %lld", &dirty) |
| || 0<sscanf(line, "Swap: %lld", &swap)) xx++; |
| free(line); |
| if (xx<3) continue; |
| line = oldline; |
| name = basename(name); |
| xx = 0; |
| printf("% 7lld %7lld %7lld ", pss, dirty, swap); |
| tpss += pss; |
| tdirty += dirty; |
| tswap += swap; |
| } |
| |
| xprintf("%s- %s%s", toybuf, line[off]=='[' ? " " : "", name); |
| |
| free(line); |
| line = 0; |
| } |
| |
| // Trailer |
| if (!(toys.optflags & FLAG_q)) { |
| int x = !!(toys.optflags & FLAG_x); |
| if (x) { |
| memset(toybuf, '-', 16); |
| xprintf("%.*s ------ ------ ------ ------\n", (int)(sizeof(long)*2), |
| toybuf); |
| } |
| printf("total% *lld%s", 2*(int)(sizeof(long)+1)+x, total, k); |
| if (x) printf("% 8lld% 8lld% 8lld", tpss, tdirty, tswap); |
| xputc('\n'); |
| } |
| |
| fclose(fp); |
| } |
| } |