12 typedef struct mapinfo mapinfo;
21 unsigned shared_clean;
22 unsigned shared_dirty;
23 unsigned private_clean;
24 unsigned private_dirty;
28 // 6f000000-6f01e000 rwxp 00000000 00:0c 16389419 /android/lib/libcomposer.so
29 // 012345678901234567890123456789012345678901234567890123456789
32 mapinfo *read_mapinfo(FILE *fp)
42 if(fgets(line, 1024, fp) == 0) return 0;
48 mi = calloc(1, sizeof(mapinfo) + len + 16);
51 mi->start = strtoul(line, 0, 16);
52 mi->end = strtoul(line + 9, 0, 16);
55 if((mi->start >= 0x10000000) && (mi->start < 0x40000000)) {
56 strcpy(mi->name, "[stack]");
57 } else if(mi->start > 0x50000000) {
58 strcpy(mi->name, "[lib_bss]");
60 strcpy(mi->name, "[anon]");
63 strcpy(mi->name, line + 49);
66 if(fgets(line, 1024, fp) == 0) goto oops;
67 if(sscanf(line, "Size: %d kB", &mi->size) != 1) goto oops;
68 if(fgets(line, 1024, fp) == 0) goto oops;
69 if(sscanf(line, "Rss: %d kB", &mi->rss) != 1) goto oops;
70 if(fgets(line, 1024, fp) == 0) goto oops;
71 if(sscanf(line, "Pss: %d kB", &mi->pss) == 1)
72 if(fgets(line, 1024, fp) == 0) goto oops;
73 if(sscanf(line, "Shared_Clean: %d kB", &mi->shared_clean) != 1) goto oops;
74 if(fgets(line, 1024, fp) == 0) goto oops;
75 if(sscanf(line, "Shared_Dirty: %d kB", &mi->shared_dirty) != 1) goto oops;
76 if(fgets(line, 1024, fp) == 0) goto oops;
77 if(sscanf(line, "Private_Clean: %d kB", &mi->private_clean) != 1) goto oops;
78 if(fgets(line, 1024, fp) == 0) goto oops;
79 if(sscanf(line, "Private_Dirty: %d kB", &mi->private_dirty) != 1) goto oops;
81 if(fgets(line, 1024, fp) == 0) goto oops; // Referenced
82 if(fgets(line, 1024, fp) == 0) goto oops; // Swap
83 if(fgets(line, 1024, fp) == 0) goto oops; // KernelPageSize
84 if(fgets(line, 1024, fp) == 0) goto oops; // MMUPageSize
93 fprintf(stderr, "WARNING: Format of /proc/<pid>/smaps has changed!\n");
99 mapinfo *load_maps(int pid, int verbose)
106 sprintf(tmp, "/proc/%d/smaps", pid);
107 fp = fopen(tmp, "r");
108 if(fp == 0) return 0;
110 while((mi = read_mapinfo(fp)) != 0) {
111 /* if not verbose, coalesce mappings from the same entity */
112 if(!verbose && milist) {
113 if((!strcmp(mi->name, milist->name) && (mi->name[0] != '['))
114 || !strcmp(mi->name,"[lib_bss]")) {
115 milist->size += mi->size;
116 milist->rss += mi->rss;
117 milist->pss += mi->pss;
118 milist->shared_clean += mi->shared_clean;
119 milist->shared_dirty += mi->shared_dirty;
120 milist->private_clean += mi->private_clean;
121 milist->private_dirty += mi->private_dirty;
122 milist->end = mi->end;
136 static int verbose = 0;
137 static int terse = 0;
138 static int addresses = 0;
140 int show_map(int pid)
144 unsigned shared_dirty = 0;
145 unsigned shared_clean = 0;
146 unsigned private_dirty = 0;
147 unsigned private_clean = 0;
152 milist = load_maps(pid, verbose);
154 fprintf(stderr,"cannot get /proc/smaps for pid %d\n", pid);
159 printf("start end shared private object\n");
160 printf("-------- -------- -------- -------- ------------------------------\n");
162 printf("virtual shared shared private private\n");
163 printf("size RSS PSS clean dirty clean dirty object\n");
164 printf("-------- -------- -------- -------- -------- -------- -------- ------------------------------\n");
166 for(mi = milist; mi; mi = mi->next){
167 shared_clean += mi->shared_clean;
168 shared_dirty += mi->shared_dirty;
169 private_clean += mi->private_clean;
170 private_dirty += mi->private_dirty;
175 if(terse && !mi->private_dirty) continue;
178 printf("%08x %08x %8d %8d %s\n", mi->start, mi->end,
179 mi->shared_clean + mi->shared_dirty,
180 mi->private_clean + mi->private_dirty,
183 printf("%8d %8d %8d %8d %8d %8d %8d %s\n", mi->size,
186 mi->shared_clean, mi->shared_dirty,
187 mi->private_clean, mi->private_dirty,
192 printf("-------- -------- -------- -------- ------------------------------\n");
193 printf(" %8d %8d TOTAL\n",
194 shared_dirty + shared_clean,
195 private_dirty + private_clean);
197 printf("-------- -------- -------- -------- -------- -------- -------- ------------------------------\n");
198 printf("%8d %8d %8d %8d %8d %8d %8d TOTAL\n", size,
200 shared_clean, shared_dirty,
201 private_clean, private_dirty);
206 int main(int argc, char *argv[])
210 for(argc--, argv++; argc > 0; argc--, argv++) {
211 if(!strcmp(argv[0],"-v")) {
215 if(!strcmp(argv[0],"-t")) {
219 if(!strcmp(argv[0],"-a")) {
223 show_map(atoi(argv[0]));
229 "showmap [-t] [-v] [-c] <pid>\n"
230 " -t = terse (show only items with private pages)\n"
231 " -v = verbose (don't coalesce adjacant maps)\n"
232 " -a = addresses (show virtual memory map)\n"