showmap.c revision 42ec73551a7ed4798de53cb8ed3b34fa964dde98
1e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project#include <stdio.h>
2e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project#include <stdlib.h>
3e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project#include <math.h>
4e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project#include <string.h>
5e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project#include <errno.h>
6e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project#include <unistd.h>
7e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project#include <fcntl.h>
8e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
9e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project#include <ctype.h>
10e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project#include <stddef.h>
11e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
12e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projecttypedef struct mapinfo mapinfo;
13e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
14e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projectstruct mapinfo {
15e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    mapinfo *next;
16e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    unsigned start;
17e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    unsigned end;
18e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    unsigned size;
19e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    unsigned rss;
20e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    unsigned pss;
21e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    unsigned shared_clean;
22e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    unsigned shared_dirty;
23e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    unsigned private_clean;
24e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    unsigned private_dirty;
25f95601708a46c098582eb836fe25889866858ad9Jeff Brown    int is_bss;
2642ec73551a7ed4798de53cb8ed3b34fa964dde98Dianne Hackborn    int count;
27e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    char name[1];
28e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project};
29e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
30f95601708a46c098582eb836fe25889866858ad9Jeff Brownstatic int is_library(const char *name) {
31f95601708a46c098582eb836fe25889866858ad9Jeff Brown    int len = strlen(name);
32f95601708a46c098582eb836fe25889866858ad9Jeff Brown    return len >= 4 && name[0] == '/'
33f95601708a46c098582eb836fe25889866858ad9Jeff Brown            && name[len - 3] == '.' && name[len - 2] == 's' && name[len - 1] == 'o';
34f95601708a46c098582eb836fe25889866858ad9Jeff Brown}
35f95601708a46c098582eb836fe25889866858ad9Jeff Brown
36e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project// 6f000000-6f01e000 rwxp 00000000 00:0c 16389419   /android/lib/libcomposer.so
37e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project// 012345678901234567890123456789012345678901234567890123456789
38e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project// 0         1         2         3         4         5
39e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
40f95601708a46c098582eb836fe25889866858ad9Jeff Brownstatic int parse_header(const char* line, const mapinfo* prev, mapinfo** mi) {
41fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root    unsigned long start;
42fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root    unsigned long end;
43fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root    char name[128];
44f95601708a46c098582eb836fe25889866858ad9Jeff Brown    int name_pos;
45f95601708a46c098582eb836fe25889866858ad9Jeff Brown    int is_bss = 0;
46fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root
47f95601708a46c098582eb836fe25889866858ad9Jeff Brown    if (sscanf(line, "%lx-%lx %*s %*x %*x:%*x %*d%n", &start, &end, &name_pos) != 2) {
48f95601708a46c098582eb836fe25889866858ad9Jeff Brown        *mi = NULL;
49f95601708a46c098582eb836fe25889866858ad9Jeff Brown        return -1;
50f95601708a46c098582eb836fe25889866858ad9Jeff Brown    }
51fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root
52f95601708a46c098582eb836fe25889866858ad9Jeff Brown    while (isspace(line[name_pos])) {
53f95601708a46c098582eb836fe25889866858ad9Jeff Brown        name_pos += 1;
54fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root    }
55fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root
56f95601708a46c098582eb836fe25889866858ad9Jeff Brown    if (line[name_pos]) {
57f95601708a46c098582eb836fe25889866858ad9Jeff Brown        strlcpy(name, line + name_pos, sizeof(name));
58f95601708a46c098582eb836fe25889866858ad9Jeff Brown    } else {
59fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root        if ((start >= 0x10000000) && (start < 0x40000000)) {
60fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root            strlcpy(name, "[stack]", sizeof(name));
61f95601708a46c098582eb836fe25889866858ad9Jeff Brown        } else if (prev && start == prev->end && is_library(prev->name)) {
62f95601708a46c098582eb836fe25889866858ad9Jeff Brown            // anonymous mappings immediately adjacent to shared libraries
63f95601708a46c098582eb836fe25889866858ad9Jeff Brown            // usually correspond to the library BSS segment, so we use the
64f95601708a46c098582eb836fe25889866858ad9Jeff Brown            // library's own name
65f95601708a46c098582eb836fe25889866858ad9Jeff Brown            strlcpy(name, prev->name, sizeof(name));
66f95601708a46c098582eb836fe25889866858ad9Jeff Brown            is_bss = 1;
67fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root        } else {
68fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root            strlcpy(name, "[anon]", sizeof(name));
69fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root        }
70fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root    }
71fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root
72fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root    const int name_size = strlen(name) + 1;
73fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root    struct mapinfo* info = calloc(1, sizeof(mapinfo) + name_size);
74fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root    if (info == NULL) {
75f95601708a46c098582eb836fe25889866858ad9Jeff Brown        fprintf(stderr, "out of memory\n");
76f95601708a46c098582eb836fe25889866858ad9Jeff Brown        exit(1);
77fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root    }
78fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root
79fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root    info->start = start;
80fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root    info->end = end;
81f95601708a46c098582eb836fe25889866858ad9Jeff Brown    info->is_bss = is_bss;
8242ec73551a7ed4798de53cb8ed3b34fa964dde98Dianne Hackborn    info->count = 1;
83fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root    strlcpy(info->name, name, name_size);
84fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root
85fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root    *mi = info;
86fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root    return 0;
87fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root}
88fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root
89f95601708a46c098582eb836fe25889866858ad9Jeff Brownstatic int parse_field(mapinfo* mi, const char* line) {
90fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root    char field[64];
91fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root    int size;
92fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root
93fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root    if (sscanf(line, "%63s %d kB", field, &size) != 2) {
94fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root        return -1;
95fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root    }
96fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root
97fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root    if (!strcmp(field, "Size:")) {
98fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root        mi->size = size;
99fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root    } else if (!strcmp(field, "Rss:")) {
100fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root        mi->rss = size;
101fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root    } else if (!strcmp(field, "Pss:")) {
102fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root        mi->pss = size;
103fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root    } else if (!strcmp(field, "Shared_Clean:")) {
104fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root        mi->shared_clean = size;
105fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root    } else if (!strcmp(field, "Shared_Dirty:")) {
106fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root        mi->shared_dirty = size;
107fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root    } else if (!strcmp(field, "Private_Clean:")) {
108fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root        mi->private_clean = size;
109fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root    } else if (!strcmp(field, "Private_Dirty:")) {
110fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root        mi->private_dirty = size;
111fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root    }
112fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root
113fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root    return 0;
114fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root}
115fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root
116f95601708a46c098582eb836fe25889866858ad9Jeff Brownstatic int order_before(const mapinfo *a, const mapinfo *b, int sort_by_address) {
117f95601708a46c098582eb836fe25889866858ad9Jeff Brown    if (sort_by_address) {
118f95601708a46c098582eb836fe25889866858ad9Jeff Brown        return a->start < b->start
119f95601708a46c098582eb836fe25889866858ad9Jeff Brown                || (a->start == b->start && a->end < b->end);
120f95601708a46c098582eb836fe25889866858ad9Jeff Brown    } else {
121f95601708a46c098582eb836fe25889866858ad9Jeff Brown        return strcmp(a->name, b->name) < 0;
122f95601708a46c098582eb836fe25889866858ad9Jeff Brown    }
123f95601708a46c098582eb836fe25889866858ad9Jeff Brown}
124f95601708a46c098582eb836fe25889866858ad9Jeff Brown
125f95601708a46c098582eb836fe25889866858ad9Jeff Brownstatic void enqueue_map(mapinfo **head, mapinfo *map, int sort_by_address, int coalesce_by_name) {
126f95601708a46c098582eb836fe25889866858ad9Jeff Brown    mapinfo *prev = NULL;
127f95601708a46c098582eb836fe25889866858ad9Jeff Brown    mapinfo *current = *head;
128f95601708a46c098582eb836fe25889866858ad9Jeff Brown
129f95601708a46c098582eb836fe25889866858ad9Jeff Brown    if (!map) {
130f95601708a46c098582eb836fe25889866858ad9Jeff Brown        return;
131f95601708a46c098582eb836fe25889866858ad9Jeff Brown    }
132f95601708a46c098582eb836fe25889866858ad9Jeff Brown
133f95601708a46c098582eb836fe25889866858ad9Jeff Brown    for (;;) {
134f95601708a46c098582eb836fe25889866858ad9Jeff Brown        if (current && coalesce_by_name && !strcmp(map->name, current->name)) {
135f95601708a46c098582eb836fe25889866858ad9Jeff Brown            current->size += map->size;
136f95601708a46c098582eb836fe25889866858ad9Jeff Brown            current->rss += map->rss;
137f95601708a46c098582eb836fe25889866858ad9Jeff Brown            current->pss += map->pss;
138f95601708a46c098582eb836fe25889866858ad9Jeff Brown            current->shared_clean += map->shared_clean;
139f95601708a46c098582eb836fe25889866858ad9Jeff Brown            current->shared_dirty += map->shared_dirty;
140f95601708a46c098582eb836fe25889866858ad9Jeff Brown            current->private_clean += map->private_clean;
141f95601708a46c098582eb836fe25889866858ad9Jeff Brown            current->private_dirty += map->private_dirty;
142f95601708a46c098582eb836fe25889866858ad9Jeff Brown            current->is_bss &= map->is_bss;
14342ec73551a7ed4798de53cb8ed3b34fa964dde98Dianne Hackborn            current->count++;
144f95601708a46c098582eb836fe25889866858ad9Jeff Brown            free(map);
145f95601708a46c098582eb836fe25889866858ad9Jeff Brown            break;
146f95601708a46c098582eb836fe25889866858ad9Jeff Brown        }
147f95601708a46c098582eb836fe25889866858ad9Jeff Brown
148f95601708a46c098582eb836fe25889866858ad9Jeff Brown        if (!current || order_before(map, current, sort_by_address)) {
149f95601708a46c098582eb836fe25889866858ad9Jeff Brown            if (prev) {
150f95601708a46c098582eb836fe25889866858ad9Jeff Brown                prev->next = map;
151f95601708a46c098582eb836fe25889866858ad9Jeff Brown            } else {
152f95601708a46c098582eb836fe25889866858ad9Jeff Brown                *head = map;
153f95601708a46c098582eb836fe25889866858ad9Jeff Brown            }
154f95601708a46c098582eb836fe25889866858ad9Jeff Brown            map->next = current;
155f95601708a46c098582eb836fe25889866858ad9Jeff Brown            break;
156f95601708a46c098582eb836fe25889866858ad9Jeff Brown        }
157f95601708a46c098582eb836fe25889866858ad9Jeff Brown
158f95601708a46c098582eb836fe25889866858ad9Jeff Brown        prev = current;
159f95601708a46c098582eb836fe25889866858ad9Jeff Brown        current = current->next;
160f95601708a46c098582eb836fe25889866858ad9Jeff Brown    }
161f95601708a46c098582eb836fe25889866858ad9Jeff Brown}
162f95601708a46c098582eb836fe25889866858ad9Jeff Brown
163f95601708a46c098582eb836fe25889866858ad9Jeff Brownstatic mapinfo *load_maps(int pid, int sort_by_address, int coalesce_by_name)
164e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project{
165f95601708a46c098582eb836fe25889866858ad9Jeff Brown    char fn[128];
166f95601708a46c098582eb836fe25889866858ad9Jeff Brown    FILE *fp;
167e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    char line[1024];
168f95601708a46c098582eb836fe25889866858ad9Jeff Brown    mapinfo *head = NULL;
169fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root    mapinfo *current = NULL;
170e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    int len;
171f95601708a46c098582eb836fe25889866858ad9Jeff Brown
172f95601708a46c098582eb836fe25889866858ad9Jeff Brown    snprintf(fn, sizeof(fn), "/proc/%d/smaps", pid);
173f95601708a46c098582eb836fe25889866858ad9Jeff Brown    fp = fopen(fn, "r");
174f95601708a46c098582eb836fe25889866858ad9Jeff Brown    if (fp == 0) {
175f95601708a46c098582eb836fe25889866858ad9Jeff Brown        fprintf(stderr, "cannot open /proc/%d/smaps: %s\n", pid, strerror(errno));
176f95601708a46c098582eb836fe25889866858ad9Jeff Brown        return NULL;
177f95601708a46c098582eb836fe25889866858ad9Jeff Brown    }
178e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
179fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root    while (fgets(line, sizeof(line), fp) != 0) {
180f95601708a46c098582eb836fe25889866858ad9Jeff Brown        len = strlen(line);
181f95601708a46c098582eb836fe25889866858ad9Jeff Brown        if (line[len - 1] == '\n') {
182f95601708a46c098582eb836fe25889866858ad9Jeff Brown            line[--len] = 0;
183fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root        }
184fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root
185f95601708a46c098582eb836fe25889866858ad9Jeff Brown        if (current != NULL && !parse_field(current, line)) {
186f95601708a46c098582eb836fe25889866858ad9Jeff Brown            continue;
187fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root        }
188e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
189f95601708a46c098582eb836fe25889866858ad9Jeff Brown        mapinfo *next;
190f95601708a46c098582eb836fe25889866858ad9Jeff Brown        if (!parse_header(line, current, &next)) {
191f95601708a46c098582eb836fe25889866858ad9Jeff Brown            enqueue_map(&head, current, sort_by_address, coalesce_by_name);
192fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root            current = next;
193fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root            continue;
194fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root        }
195e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
196f95601708a46c098582eb836fe25889866858ad9Jeff Brown        fprintf(stderr, "warning: could not parse map info line: %s\n", line);
197fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root    }
198e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
199f95601708a46c098582eb836fe25889866858ad9Jeff Brown    enqueue_map(&head, current, sort_by_address, coalesce_by_name);
200e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
201fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root    fclose(fp);
202fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root
203f95601708a46c098582eb836fe25889866858ad9Jeff Brown    if (!head) {
204fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root        fprintf(stderr, "could not read /proc/%d/smaps\n", pid);
205fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root        return NULL;
206fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root    }
207fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root
208f95601708a46c098582eb836fe25889866858ad9Jeff Brown    return head;
209e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project}
210e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
211e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projectstatic int verbose = 0;
212e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projectstatic int terse = 0;
213e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projectstatic int addresses = 0;
214e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
21542ec73551a7ed4798de53cb8ed3b34fa964dde98Dianne Hackbornstatic void print_header()
21642ec73551a7ed4798de53cb8ed3b34fa964dde98Dianne Hackborn{
21742ec73551a7ed4798de53cb8ed3b34fa964dde98Dianne Hackborn    if (addresses) {
21842ec73551a7ed4798de53cb8ed3b34fa964dde98Dianne Hackborn        printf("   start      end ");
21942ec73551a7ed4798de53cb8ed3b34fa964dde98Dianne Hackborn    }
22042ec73551a7ed4798de53cb8ed3b34fa964dde98Dianne Hackborn    printf(" virtual                     shared   shared  private  private\n");
22142ec73551a7ed4798de53cb8ed3b34fa964dde98Dianne Hackborn
22242ec73551a7ed4798de53cb8ed3b34fa964dde98Dianne Hackborn    if (addresses) {
22342ec73551a7ed4798de53cb8ed3b34fa964dde98Dianne Hackborn        printf("    addr     addr ");
22442ec73551a7ed4798de53cb8ed3b34fa964dde98Dianne Hackborn    }
22542ec73551a7ed4798de53cb8ed3b34fa964dde98Dianne Hackborn    printf("    size      RSS      PSS    clean    dirty    clean    dirty ");
22642ec73551a7ed4798de53cb8ed3b34fa964dde98Dianne Hackborn    if (!verbose && !addresses) {
22742ec73551a7ed4798de53cb8ed3b34fa964dde98Dianne Hackborn        printf("   # ");
22842ec73551a7ed4798de53cb8ed3b34fa964dde98Dianne Hackborn    }
22942ec73551a7ed4798de53cb8ed3b34fa964dde98Dianne Hackborn    printf("object\n");
23042ec73551a7ed4798de53cb8ed3b34fa964dde98Dianne Hackborn}
23142ec73551a7ed4798de53cb8ed3b34fa964dde98Dianne Hackborn
23242ec73551a7ed4798de53cb8ed3b34fa964dde98Dianne Hackbornstatic void print_divider()
23342ec73551a7ed4798de53cb8ed3b34fa964dde98Dianne Hackborn{
23442ec73551a7ed4798de53cb8ed3b34fa964dde98Dianne Hackborn    if (addresses) {
23542ec73551a7ed4798de53cb8ed3b34fa964dde98Dianne Hackborn        printf("-------- -------- ");
23642ec73551a7ed4798de53cb8ed3b34fa964dde98Dianne Hackborn    }
23742ec73551a7ed4798de53cb8ed3b34fa964dde98Dianne Hackborn    printf("-------- -------- -------- -------- -------- -------- -------- ");
23842ec73551a7ed4798de53cb8ed3b34fa964dde98Dianne Hackborn    if (!verbose && !addresses) {
23942ec73551a7ed4798de53cb8ed3b34fa964dde98Dianne Hackborn        printf("---- ");
24042ec73551a7ed4798de53cb8ed3b34fa964dde98Dianne Hackborn    }
24142ec73551a7ed4798de53cb8ed3b34fa964dde98Dianne Hackborn    printf("------------------------------\n");
24242ec73551a7ed4798de53cb8ed3b34fa964dde98Dianne Hackborn}
24342ec73551a7ed4798de53cb8ed3b34fa964dde98Dianne Hackborn
244f95601708a46c098582eb836fe25889866858ad9Jeff Brownstatic int show_map(int pid)
245e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project{
246e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    mapinfo *milist;
247e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    mapinfo *mi;
248e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    unsigned shared_dirty = 0;
249e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    unsigned shared_clean = 0;
250e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    unsigned private_dirty = 0;
251e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    unsigned private_clean = 0;
252e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    unsigned rss = 0;
253e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    unsigned pss = 0;
254e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    unsigned size = 0;
25542ec73551a7ed4798de53cb8ed3b34fa964dde98Dianne Hackborn    unsigned count = 0;
256f95601708a46c098582eb836fe25889866858ad9Jeff Brown
257f95601708a46c098582eb836fe25889866858ad9Jeff Brown    milist = load_maps(pid, addresses, !verbose && !addresses);
258fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root    if (milist == NULL) {
259e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        return 1;
260e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    }
261e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
26242ec73551a7ed4798de53cb8ed3b34fa964dde98Dianne Hackborn    print_header();
26342ec73551a7ed4798de53cb8ed3b34fa964dde98Dianne Hackborn    print_divider();
264fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root
265fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root    for (mi = milist; mi;) {
266fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root        mapinfo* last = mi;
267fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root
268e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        shared_clean += mi->shared_clean;
269e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        shared_dirty += mi->shared_dirty;
270e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        private_clean += mi->private_clean;
271e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        private_dirty += mi->private_dirty;
272e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        rss += mi->rss;
273e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        pss += mi->pss;
274e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        size += mi->size;
27542ec73551a7ed4798de53cb8ed3b34fa964dde98Dianne Hackborn        count += mi->count;
276e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
277fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root        if (terse && !mi->private_dirty) {
278fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root            goto out;
279fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root        }
280e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
281fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root        if (addresses) {
282f95601708a46c098582eb836fe25889866858ad9Jeff Brown            printf("%08x %08x ", mi->start, mi->end);
283e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        }
28442ec73551a7ed4798de53cb8ed3b34fa964dde98Dianne Hackborn        printf("%8d %8d %8d %8d %8d %8d %8d ", mi->size,
285f95601708a46c098582eb836fe25889866858ad9Jeff Brown               mi->rss,
286f95601708a46c098582eb836fe25889866858ad9Jeff Brown               mi->pss,
287f95601708a46c098582eb836fe25889866858ad9Jeff Brown               mi->shared_clean, mi->shared_dirty,
28842ec73551a7ed4798de53cb8ed3b34fa964dde98Dianne Hackborn               mi->private_clean, mi->private_dirty);
28942ec73551a7ed4798de53cb8ed3b34fa964dde98Dianne Hackborn        if (!verbose && !addresses) {
29042ec73551a7ed4798de53cb8ed3b34fa964dde98Dianne Hackborn            printf("%4d ", mi->count);
29142ec73551a7ed4798de53cb8ed3b34fa964dde98Dianne Hackborn        }
29242ec73551a7ed4798de53cb8ed3b34fa964dde98Dianne Hackborn        printf("%s%s\n", mi->name, mi->is_bss ? " [bss]" : "");
293fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root
294fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Rootout:
295fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root        mi = mi->next;
296fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root        free(last);
297e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    }
298fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root
29942ec73551a7ed4798de53cb8ed3b34fa964dde98Dianne Hackborn    print_divider();
30042ec73551a7ed4798de53cb8ed3b34fa964dde98Dianne Hackborn    print_header();
30142ec73551a7ed4798de53cb8ed3b34fa964dde98Dianne Hackborn    print_divider();
302f95601708a46c098582eb836fe25889866858ad9Jeff Brown
303f95601708a46c098582eb836fe25889866858ad9Jeff Brown    if (addresses) {
304f95601708a46c098582eb836fe25889866858ad9Jeff Brown        printf("                  ");
305f95601708a46c098582eb836fe25889866858ad9Jeff Brown    }
30642ec73551a7ed4798de53cb8ed3b34fa964dde98Dianne Hackborn    printf("%8d %8d %8d %8d %8d %8d %8d ", size,
307f95601708a46c098582eb836fe25889866858ad9Jeff Brown            rss, pss,
308f95601708a46c098582eb836fe25889866858ad9Jeff Brown            shared_clean, shared_dirty,
309f95601708a46c098582eb836fe25889866858ad9Jeff Brown            private_clean, private_dirty);
31042ec73551a7ed4798de53cb8ed3b34fa964dde98Dianne Hackborn    if (!verbose && !addresses) {
31142ec73551a7ed4798de53cb8ed3b34fa964dde98Dianne Hackborn        printf("%4d ", count);
31242ec73551a7ed4798de53cb8ed3b34fa964dde98Dianne Hackborn    }
31342ec73551a7ed4798de53cb8ed3b34fa964dde98Dianne Hackborn    printf("TOTAL\n");
314fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root
315e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    return 0;
316e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project}
317e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
318e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projectint main(int argc, char *argv[])
319e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project{
320e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    int usage = 1;
321f95601708a46c098582eb836fe25889866858ad9Jeff Brown    int result = 0;
322f95601708a46c098582eb836fe25889866858ad9Jeff Brown    int pid;
323f95601708a46c098582eb836fe25889866858ad9Jeff Brown    char *arg;
324f95601708a46c098582eb836fe25889866858ad9Jeff Brown    char *argend;
325f95601708a46c098582eb836fe25889866858ad9Jeff Brown
326fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root    for (argc--, argv++; argc > 0; argc--, argv++) {
327f95601708a46c098582eb836fe25889866858ad9Jeff Brown        arg = argv[0];
328f95601708a46c098582eb836fe25889866858ad9Jeff Brown        if (!strcmp(arg,"-v")) {
329e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project            verbose = 1;
330e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project            continue;
331e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        }
332f95601708a46c098582eb836fe25889866858ad9Jeff Brown        if (!strcmp(arg,"-t")) {
333e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project            terse = 1;
334e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project            continue;
335e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        }
336f95601708a46c098582eb836fe25889866858ad9Jeff Brown        if (!strcmp(arg,"-a")) {
337e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project            addresses = 1;
338e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project            continue;
339e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        }
340f95601708a46c098582eb836fe25889866858ad9Jeff Brown        if (argc != 1) {
341f95601708a46c098582eb836fe25889866858ad9Jeff Brown            fprintf(stderr, "too many arguments\n");
342f95601708a46c098582eb836fe25889866858ad9Jeff Brown            break;
343f95601708a46c098582eb836fe25889866858ad9Jeff Brown        }
344f95601708a46c098582eb836fe25889866858ad9Jeff Brown        pid = strtol(arg, &argend, 10);
345f95601708a46c098582eb836fe25889866858ad9Jeff Brown        if (*arg && !*argend) {
346f95601708a46c098582eb836fe25889866858ad9Jeff Brown            usage = 0;
347f95601708a46c098582eb836fe25889866858ad9Jeff Brown            if (show_map(pid)) {
348f95601708a46c098582eb836fe25889866858ad9Jeff Brown                result = 1;
349f95601708a46c098582eb836fe25889866858ad9Jeff Brown            }
350f95601708a46c098582eb836fe25889866858ad9Jeff Brown            break;
351f95601708a46c098582eb836fe25889866858ad9Jeff Brown        }
352f95601708a46c098582eb836fe25889866858ad9Jeff Brown        fprintf(stderr, "unrecognized argument: %s\n", arg);
353f95601708a46c098582eb836fe25889866858ad9Jeff Brown        break;
354e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    }
355e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
356fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root    if (usage) {
357e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        fprintf(stderr,
358e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project                "showmap [-t] [-v] [-c] <pid>\n"
359e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project                "        -t = terse (show only items with private pages)\n"
360f95601708a46c098582eb836fe25889866858ad9Jeff Brown                "        -v = verbose (don't coalesce maps with the same name)\n"
361e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project                "        -a = addresses (show virtual memory map)\n"
362e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project                );
363f95601708a46c098582eb836fe25889866858ad9Jeff Brown        result = 1;
364e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    }
365e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
366f95601708a46c098582eb836fe25889866858ad9Jeff Brown    return result;
367e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project}
368