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 {
59d3cb030b4df7fd8fbdfa503840740592fc7061a3Nick Kralevich        if (prev && start == prev->end && is_library(prev->name)) {
60f95601708a46c098582eb836fe25889866858ad9Jeff Brown            // anonymous mappings immediately adjacent to shared libraries
61f95601708a46c098582eb836fe25889866858ad9Jeff Brown            // usually correspond to the library BSS segment, so we use the
62f95601708a46c098582eb836fe25889866858ad9Jeff Brown            // library's own name
63f95601708a46c098582eb836fe25889866858ad9Jeff Brown            strlcpy(name, prev->name, sizeof(name));
64f95601708a46c098582eb836fe25889866858ad9Jeff Brown            is_bss = 1;
65fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root        } else {
66fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root            strlcpy(name, "[anon]", sizeof(name));
67fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root        }
68fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root    }
69fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root
70fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root    const int name_size = strlen(name) + 1;
71fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root    struct mapinfo* info = calloc(1, sizeof(mapinfo) + name_size);
72fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root    if (info == NULL) {
73f95601708a46c098582eb836fe25889866858ad9Jeff Brown        fprintf(stderr, "out of memory\n");
74f95601708a46c098582eb836fe25889866858ad9Jeff Brown        exit(1);
75fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root    }
76fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root
77fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root    info->start = start;
78fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root    info->end = end;
79f95601708a46c098582eb836fe25889866858ad9Jeff Brown    info->is_bss = is_bss;
8042ec73551a7ed4798de53cb8ed3b34fa964dde98Dianne Hackborn    info->count = 1;
81fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root    strlcpy(info->name, name, name_size);
82fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root
83fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root    *mi = info;
84fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root    return 0;
85fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root}
86fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root
87f95601708a46c098582eb836fe25889866858ad9Jeff Brownstatic int parse_field(mapinfo* mi, const char* line) {
88fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root    char field[64];
89fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root    int size;
90fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root
91fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root    if (sscanf(line, "%63s %d kB", field, &size) != 2) {
92fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root        return -1;
93fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root    }
94fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root
95fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root    if (!strcmp(field, "Size:")) {
96fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root        mi->size = size;
97fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root    } else if (!strcmp(field, "Rss:")) {
98fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root        mi->rss = size;
99fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root    } else if (!strcmp(field, "Pss:")) {
100fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root        mi->pss = size;
101fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root    } else if (!strcmp(field, "Shared_Clean:")) {
102fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root        mi->shared_clean = size;
103fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root    } else if (!strcmp(field, "Shared_Dirty:")) {
104fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root        mi->shared_dirty = size;
105fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root    } else if (!strcmp(field, "Private_Clean:")) {
106fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root        mi->private_clean = size;
107fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root    } else if (!strcmp(field, "Private_Dirty:")) {
108fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root        mi->private_dirty = size;
109fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root    }
110fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root
111fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root    return 0;
112fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root}
113fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root
114f95601708a46c098582eb836fe25889866858ad9Jeff Brownstatic int order_before(const mapinfo *a, const mapinfo *b, int sort_by_address) {
115f95601708a46c098582eb836fe25889866858ad9Jeff Brown    if (sort_by_address) {
116f95601708a46c098582eb836fe25889866858ad9Jeff Brown        return a->start < b->start
117f95601708a46c098582eb836fe25889866858ad9Jeff Brown                || (a->start == b->start && a->end < b->end);
118f95601708a46c098582eb836fe25889866858ad9Jeff Brown    } else {
119f95601708a46c098582eb836fe25889866858ad9Jeff Brown        return strcmp(a->name, b->name) < 0;
120f95601708a46c098582eb836fe25889866858ad9Jeff Brown    }
121f95601708a46c098582eb836fe25889866858ad9Jeff Brown}
122f95601708a46c098582eb836fe25889866858ad9Jeff Brown
123f95601708a46c098582eb836fe25889866858ad9Jeff Brownstatic void enqueue_map(mapinfo **head, mapinfo *map, int sort_by_address, int coalesce_by_name) {
124f95601708a46c098582eb836fe25889866858ad9Jeff Brown    mapinfo *prev = NULL;
125f95601708a46c098582eb836fe25889866858ad9Jeff Brown    mapinfo *current = *head;
126f95601708a46c098582eb836fe25889866858ad9Jeff Brown
127f95601708a46c098582eb836fe25889866858ad9Jeff Brown    if (!map) {
128f95601708a46c098582eb836fe25889866858ad9Jeff Brown        return;
129f95601708a46c098582eb836fe25889866858ad9Jeff Brown    }
130f95601708a46c098582eb836fe25889866858ad9Jeff Brown
131f95601708a46c098582eb836fe25889866858ad9Jeff Brown    for (;;) {
132f95601708a46c098582eb836fe25889866858ad9Jeff Brown        if (current && coalesce_by_name && !strcmp(map->name, current->name)) {
133f95601708a46c098582eb836fe25889866858ad9Jeff Brown            current->size += map->size;
134f95601708a46c098582eb836fe25889866858ad9Jeff Brown            current->rss += map->rss;
135f95601708a46c098582eb836fe25889866858ad9Jeff Brown            current->pss += map->pss;
136f95601708a46c098582eb836fe25889866858ad9Jeff Brown            current->shared_clean += map->shared_clean;
137f95601708a46c098582eb836fe25889866858ad9Jeff Brown            current->shared_dirty += map->shared_dirty;
138f95601708a46c098582eb836fe25889866858ad9Jeff Brown            current->private_clean += map->private_clean;
139f95601708a46c098582eb836fe25889866858ad9Jeff Brown            current->private_dirty += map->private_dirty;
140f95601708a46c098582eb836fe25889866858ad9Jeff Brown            current->is_bss &= map->is_bss;
14142ec73551a7ed4798de53cb8ed3b34fa964dde98Dianne Hackborn            current->count++;
142f95601708a46c098582eb836fe25889866858ad9Jeff Brown            free(map);
143f95601708a46c098582eb836fe25889866858ad9Jeff Brown            break;
144f95601708a46c098582eb836fe25889866858ad9Jeff Brown        }
145f95601708a46c098582eb836fe25889866858ad9Jeff Brown
146f95601708a46c098582eb836fe25889866858ad9Jeff Brown        if (!current || order_before(map, current, sort_by_address)) {
147f95601708a46c098582eb836fe25889866858ad9Jeff Brown            if (prev) {
148f95601708a46c098582eb836fe25889866858ad9Jeff Brown                prev->next = map;
149f95601708a46c098582eb836fe25889866858ad9Jeff Brown            } else {
150f95601708a46c098582eb836fe25889866858ad9Jeff Brown                *head = map;
151f95601708a46c098582eb836fe25889866858ad9Jeff Brown            }
152f95601708a46c098582eb836fe25889866858ad9Jeff Brown            map->next = current;
153f95601708a46c098582eb836fe25889866858ad9Jeff Brown            break;
154f95601708a46c098582eb836fe25889866858ad9Jeff Brown        }
155f95601708a46c098582eb836fe25889866858ad9Jeff Brown
156f95601708a46c098582eb836fe25889866858ad9Jeff Brown        prev = current;
157f95601708a46c098582eb836fe25889866858ad9Jeff Brown        current = current->next;
158f95601708a46c098582eb836fe25889866858ad9Jeff Brown    }
159f95601708a46c098582eb836fe25889866858ad9Jeff Brown}
160f95601708a46c098582eb836fe25889866858ad9Jeff Brown
161f95601708a46c098582eb836fe25889866858ad9Jeff Brownstatic mapinfo *load_maps(int pid, int sort_by_address, int coalesce_by_name)
162e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project{
163f95601708a46c098582eb836fe25889866858ad9Jeff Brown    char fn[128];
164f95601708a46c098582eb836fe25889866858ad9Jeff Brown    FILE *fp;
165e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    char line[1024];
166f95601708a46c098582eb836fe25889866858ad9Jeff Brown    mapinfo *head = NULL;
167fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root    mapinfo *current = NULL;
168e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    int len;
169f95601708a46c098582eb836fe25889866858ad9Jeff Brown
170f95601708a46c098582eb836fe25889866858ad9Jeff Brown    snprintf(fn, sizeof(fn), "/proc/%d/smaps", pid);
171f95601708a46c098582eb836fe25889866858ad9Jeff Brown    fp = fopen(fn, "r");
172f95601708a46c098582eb836fe25889866858ad9Jeff Brown    if (fp == 0) {
173f95601708a46c098582eb836fe25889866858ad9Jeff Brown        fprintf(stderr, "cannot open /proc/%d/smaps: %s\n", pid, strerror(errno));
174f95601708a46c098582eb836fe25889866858ad9Jeff Brown        return NULL;
175f95601708a46c098582eb836fe25889866858ad9Jeff Brown    }
176e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
177fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root    while (fgets(line, sizeof(line), fp) != 0) {
178f95601708a46c098582eb836fe25889866858ad9Jeff Brown        len = strlen(line);
179f95601708a46c098582eb836fe25889866858ad9Jeff Brown        if (line[len - 1] == '\n') {
180f95601708a46c098582eb836fe25889866858ad9Jeff Brown            line[--len] = 0;
181fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root        }
182fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root
183f95601708a46c098582eb836fe25889866858ad9Jeff Brown        if (current != NULL && !parse_field(current, line)) {
184f95601708a46c098582eb836fe25889866858ad9Jeff Brown            continue;
185fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root        }
186e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
187f95601708a46c098582eb836fe25889866858ad9Jeff Brown        mapinfo *next;
188f95601708a46c098582eb836fe25889866858ad9Jeff Brown        if (!parse_header(line, current, &next)) {
189f95601708a46c098582eb836fe25889866858ad9Jeff Brown            enqueue_map(&head, current, sort_by_address, coalesce_by_name);
190fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root            current = next;
191fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root            continue;
192fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root        }
193e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
194f95601708a46c098582eb836fe25889866858ad9Jeff Brown        fprintf(stderr, "warning: could not parse map info line: %s\n", line);
195fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root    }
196e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
197f95601708a46c098582eb836fe25889866858ad9Jeff Brown    enqueue_map(&head, current, sort_by_address, coalesce_by_name);
198e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
199fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root    fclose(fp);
200fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root
201f95601708a46c098582eb836fe25889866858ad9Jeff Brown    if (!head) {
202fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root        fprintf(stderr, "could not read /proc/%d/smaps\n", pid);
203fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root        return NULL;
204fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root    }
205fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root
206f95601708a46c098582eb836fe25889866858ad9Jeff Brown    return head;
207e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project}
208e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
209e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projectstatic int verbose = 0;
210e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projectstatic int terse = 0;
211e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projectstatic int addresses = 0;
212e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
21342ec73551a7ed4798de53cb8ed3b34fa964dde98Dianne Hackbornstatic void print_header()
21442ec73551a7ed4798de53cb8ed3b34fa964dde98Dianne Hackborn{
21542ec73551a7ed4798de53cb8ed3b34fa964dde98Dianne Hackborn    if (addresses) {
21642ec73551a7ed4798de53cb8ed3b34fa964dde98Dianne Hackborn        printf("   start      end ");
21742ec73551a7ed4798de53cb8ed3b34fa964dde98Dianne Hackborn    }
21842ec73551a7ed4798de53cb8ed3b34fa964dde98Dianne Hackborn    printf(" virtual                     shared   shared  private  private\n");
21942ec73551a7ed4798de53cb8ed3b34fa964dde98Dianne Hackborn
22042ec73551a7ed4798de53cb8ed3b34fa964dde98Dianne Hackborn    if (addresses) {
22142ec73551a7ed4798de53cb8ed3b34fa964dde98Dianne Hackborn        printf("    addr     addr ");
22242ec73551a7ed4798de53cb8ed3b34fa964dde98Dianne Hackborn    }
22342ec73551a7ed4798de53cb8ed3b34fa964dde98Dianne Hackborn    printf("    size      RSS      PSS    clean    dirty    clean    dirty ");
22442ec73551a7ed4798de53cb8ed3b34fa964dde98Dianne Hackborn    if (!verbose && !addresses) {
22542ec73551a7ed4798de53cb8ed3b34fa964dde98Dianne Hackborn        printf("   # ");
22642ec73551a7ed4798de53cb8ed3b34fa964dde98Dianne Hackborn    }
22742ec73551a7ed4798de53cb8ed3b34fa964dde98Dianne Hackborn    printf("object\n");
22842ec73551a7ed4798de53cb8ed3b34fa964dde98Dianne Hackborn}
22942ec73551a7ed4798de53cb8ed3b34fa964dde98Dianne Hackborn
23042ec73551a7ed4798de53cb8ed3b34fa964dde98Dianne Hackbornstatic void print_divider()
23142ec73551a7ed4798de53cb8ed3b34fa964dde98Dianne Hackborn{
23242ec73551a7ed4798de53cb8ed3b34fa964dde98Dianne Hackborn    if (addresses) {
23342ec73551a7ed4798de53cb8ed3b34fa964dde98Dianne Hackborn        printf("-------- -------- ");
23442ec73551a7ed4798de53cb8ed3b34fa964dde98Dianne Hackborn    }
23542ec73551a7ed4798de53cb8ed3b34fa964dde98Dianne Hackborn    printf("-------- -------- -------- -------- -------- -------- -------- ");
23642ec73551a7ed4798de53cb8ed3b34fa964dde98Dianne Hackborn    if (!verbose && !addresses) {
23742ec73551a7ed4798de53cb8ed3b34fa964dde98Dianne Hackborn        printf("---- ");
23842ec73551a7ed4798de53cb8ed3b34fa964dde98Dianne Hackborn    }
23942ec73551a7ed4798de53cb8ed3b34fa964dde98Dianne Hackborn    printf("------------------------------\n");
24042ec73551a7ed4798de53cb8ed3b34fa964dde98Dianne Hackborn}
24142ec73551a7ed4798de53cb8ed3b34fa964dde98Dianne Hackborn
242f95601708a46c098582eb836fe25889866858ad9Jeff Brownstatic int show_map(int pid)
243e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project{
244e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    mapinfo *milist;
245e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    mapinfo *mi;
246e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    unsigned shared_dirty = 0;
247e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    unsigned shared_clean = 0;
248e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    unsigned private_dirty = 0;
249e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    unsigned private_clean = 0;
250e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    unsigned rss = 0;
251e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    unsigned pss = 0;
252e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    unsigned size = 0;
25342ec73551a7ed4798de53cb8ed3b34fa964dde98Dianne Hackborn    unsigned count = 0;
254f95601708a46c098582eb836fe25889866858ad9Jeff Brown
255f95601708a46c098582eb836fe25889866858ad9Jeff Brown    milist = load_maps(pid, addresses, !verbose && !addresses);
256fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root    if (milist == NULL) {
257e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        return 1;
258e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    }
259e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
26042ec73551a7ed4798de53cb8ed3b34fa964dde98Dianne Hackborn    print_header();
26142ec73551a7ed4798de53cb8ed3b34fa964dde98Dianne Hackborn    print_divider();
262fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root
263fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root    for (mi = milist; mi;) {
264fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root        mapinfo* last = mi;
265fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root
266e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        shared_clean += mi->shared_clean;
267e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        shared_dirty += mi->shared_dirty;
268e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        private_clean += mi->private_clean;
269e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        private_dirty += mi->private_dirty;
270e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        rss += mi->rss;
271e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        pss += mi->pss;
272e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        size += mi->size;
27342ec73551a7ed4798de53cb8ed3b34fa964dde98Dianne Hackborn        count += mi->count;
274e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
275fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root        if (terse && !mi->private_dirty) {
276fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root            goto out;
277fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root        }
278e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
279fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root        if (addresses) {
280f95601708a46c098582eb836fe25889866858ad9Jeff Brown            printf("%08x %08x ", mi->start, mi->end);
281e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        }
28242ec73551a7ed4798de53cb8ed3b34fa964dde98Dianne Hackborn        printf("%8d %8d %8d %8d %8d %8d %8d ", mi->size,
283f95601708a46c098582eb836fe25889866858ad9Jeff Brown               mi->rss,
284f95601708a46c098582eb836fe25889866858ad9Jeff Brown               mi->pss,
285f95601708a46c098582eb836fe25889866858ad9Jeff Brown               mi->shared_clean, mi->shared_dirty,
28642ec73551a7ed4798de53cb8ed3b34fa964dde98Dianne Hackborn               mi->private_clean, mi->private_dirty);
28742ec73551a7ed4798de53cb8ed3b34fa964dde98Dianne Hackborn        if (!verbose && !addresses) {
28842ec73551a7ed4798de53cb8ed3b34fa964dde98Dianne Hackborn            printf("%4d ", mi->count);
28942ec73551a7ed4798de53cb8ed3b34fa964dde98Dianne Hackborn        }
29042ec73551a7ed4798de53cb8ed3b34fa964dde98Dianne Hackborn        printf("%s%s\n", mi->name, mi->is_bss ? " [bss]" : "");
291fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root
292fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Rootout:
293fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root        mi = mi->next;
294fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root        free(last);
295e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    }
296fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root
29742ec73551a7ed4798de53cb8ed3b34fa964dde98Dianne Hackborn    print_divider();
29842ec73551a7ed4798de53cb8ed3b34fa964dde98Dianne Hackborn    print_header();
29942ec73551a7ed4798de53cb8ed3b34fa964dde98Dianne Hackborn    print_divider();
300f95601708a46c098582eb836fe25889866858ad9Jeff Brown
301f95601708a46c098582eb836fe25889866858ad9Jeff Brown    if (addresses) {
302f95601708a46c098582eb836fe25889866858ad9Jeff Brown        printf("                  ");
303f95601708a46c098582eb836fe25889866858ad9Jeff Brown    }
30442ec73551a7ed4798de53cb8ed3b34fa964dde98Dianne Hackborn    printf("%8d %8d %8d %8d %8d %8d %8d ", size,
305f95601708a46c098582eb836fe25889866858ad9Jeff Brown            rss, pss,
306f95601708a46c098582eb836fe25889866858ad9Jeff Brown            shared_clean, shared_dirty,
307f95601708a46c098582eb836fe25889866858ad9Jeff Brown            private_clean, private_dirty);
30842ec73551a7ed4798de53cb8ed3b34fa964dde98Dianne Hackborn    if (!verbose && !addresses) {
30942ec73551a7ed4798de53cb8ed3b34fa964dde98Dianne Hackborn        printf("%4d ", count);
31042ec73551a7ed4798de53cb8ed3b34fa964dde98Dianne Hackborn    }
31142ec73551a7ed4798de53cb8ed3b34fa964dde98Dianne Hackborn    printf("TOTAL\n");
312fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root
313e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    return 0;
314e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project}
315e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
316e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projectint main(int argc, char *argv[])
317e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project{
318e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    int usage = 1;
319f95601708a46c098582eb836fe25889866858ad9Jeff Brown    int result = 0;
320f95601708a46c098582eb836fe25889866858ad9Jeff Brown    int pid;
321f95601708a46c098582eb836fe25889866858ad9Jeff Brown    char *arg;
322f95601708a46c098582eb836fe25889866858ad9Jeff Brown    char *argend;
323f95601708a46c098582eb836fe25889866858ad9Jeff Brown
32480cb15504324667c9934ff350afff48881613393JP Abgrall    signal(SIGPIPE, SIG_IGN);
325fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root    for (argc--, argv++; argc > 0; argc--, argv++) {
326f95601708a46c098582eb836fe25889866858ad9Jeff Brown        arg = argv[0];
327f95601708a46c098582eb836fe25889866858ad9Jeff Brown        if (!strcmp(arg,"-v")) {
328e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project            verbose = 1;
329e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project            continue;
330e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        }
331f95601708a46c098582eb836fe25889866858ad9Jeff Brown        if (!strcmp(arg,"-t")) {
332e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project            terse = 1;
333e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project            continue;
334e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        }
335f95601708a46c098582eb836fe25889866858ad9Jeff Brown        if (!strcmp(arg,"-a")) {
336e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project            addresses = 1;
337e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project            continue;
338e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        }
339f95601708a46c098582eb836fe25889866858ad9Jeff Brown        if (argc != 1) {
340f95601708a46c098582eb836fe25889866858ad9Jeff Brown            fprintf(stderr, "too many arguments\n");
341f95601708a46c098582eb836fe25889866858ad9Jeff Brown            break;
342f95601708a46c098582eb836fe25889866858ad9Jeff Brown        }
343f95601708a46c098582eb836fe25889866858ad9Jeff Brown        pid = strtol(arg, &argend, 10);
344f95601708a46c098582eb836fe25889866858ad9Jeff Brown        if (*arg && !*argend) {
345f95601708a46c098582eb836fe25889866858ad9Jeff Brown            usage = 0;
346f95601708a46c098582eb836fe25889866858ad9Jeff Brown            if (show_map(pid)) {
347f95601708a46c098582eb836fe25889866858ad9Jeff Brown                result = 1;
348f95601708a46c098582eb836fe25889866858ad9Jeff Brown            }
349f95601708a46c098582eb836fe25889866858ad9Jeff Brown            break;
350f95601708a46c098582eb836fe25889866858ad9Jeff Brown        }
351f95601708a46c098582eb836fe25889866858ad9Jeff Brown        fprintf(stderr, "unrecognized argument: %s\n", arg);
352f95601708a46c098582eb836fe25889866858ad9Jeff Brown        break;
353e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    }
354e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
355fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root    if (usage) {
356e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        fprintf(stderr,
357e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project                "showmap [-t] [-v] [-c] <pid>\n"
358e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project                "        -t = terse (show only items with private pages)\n"
359f95601708a46c098582eb836fe25889866858ad9Jeff Brown                "        -v = verbose (don't coalesce maps with the same name)\n"
360e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project                "        -a = addresses (show virtual memory map)\n"
361e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project                );
362f95601708a46c098582eb836fe25889866858ad9Jeff Brown        result = 1;
363e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    }
364e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
365f95601708a46c098582eb836fe25889866858ad9Jeff Brown    return result;
366e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project}
367