1ddbe8c3fcb3d8272129fd17ee3b06611f7df8185Elliott Hughes#include <ctype.h>
2ddbe8c3fcb3d8272129fd17ee3b06611f7df8185Elliott Hughes#include <errno.h>
3ddbe8c3fcb3d8272129fd17ee3b06611f7df8185Elliott Hughes#include <fcntl.h>
4ddbe8c3fcb3d8272129fd17ee3b06611f7df8185Elliott Hughes#include <math.h>
5ddbe8c3fcb3d8272129fd17ee3b06611f7df8185Elliott Hughes#include <stddef.h>
6e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project#include <stdio.h>
7e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project#include <stdlib.h>
8e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project#include <string.h>
9e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project#include <unistd.h>
10e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
11e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projectstruct mapinfo {
12e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    mapinfo *next;
13e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    unsigned start;
14e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    unsigned end;
15e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    unsigned size;
16e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    unsigned rss;
17e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    unsigned pss;
18e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    unsigned shared_clean;
19e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    unsigned shared_dirty;
20e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    unsigned private_clean;
21e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    unsigned private_dirty;
2250173c39ec48135e0b629d4e59bf59c554d17773Martijn Coenen    unsigned swap;
23f95601708a46c098582eb836fe25889866858ad9Jeff Brown    int is_bss;
2442ec73551a7ed4798de53cb8ed3b34fa964dde98Dianne Hackborn    int count;
25e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    char name[1];
26e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project};
27e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
28a5aa8f9583aec9fcfba38161cb31b6ae2b588313Felipe Lemestatic bool verbose = false;
29a5aa8f9583aec9fcfba38161cb31b6ae2b588313Felipe Lemestatic bool terse = false;
30a5aa8f9583aec9fcfba38161cb31b6ae2b588313Felipe Lemestatic bool addresses = false;
31a5aa8f9583aec9fcfba38161cb31b6ae2b588313Felipe Lemestatic bool quiet = false;
32a5aa8f9583aec9fcfba38161cb31b6ae2b588313Felipe Leme
33f95601708a46c098582eb836fe25889866858ad9Jeff Brownstatic int is_library(const char *name) {
34f95601708a46c098582eb836fe25889866858ad9Jeff Brown    int len = strlen(name);
35f95601708a46c098582eb836fe25889866858ad9Jeff Brown    return len >= 4 && name[0] == '/'
36f95601708a46c098582eb836fe25889866858ad9Jeff Brown            && name[len - 3] == '.' && name[len - 2] == 's' && name[len - 1] == 'o';
37f95601708a46c098582eb836fe25889866858ad9Jeff Brown}
38f95601708a46c098582eb836fe25889866858ad9Jeff Brown
39e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project// 6f000000-6f01e000 rwxp 00000000 00:0c 16389419   /android/lib/libcomposer.so
40e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project// 012345678901234567890123456789012345678901234567890123456789
41e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project// 0         1         2         3         4         5
42e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
43f95601708a46c098582eb836fe25889866858ad9Jeff Brownstatic int parse_header(const char* line, const mapinfo* prev, mapinfo** mi) {
44fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root    unsigned long start;
45fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root    unsigned long end;
46fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root    char name[128];
47f95601708a46c098582eb836fe25889866858ad9Jeff Brown    int name_pos;
48f95601708a46c098582eb836fe25889866858ad9Jeff Brown    int is_bss = 0;
49fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root
50f95601708a46c098582eb836fe25889866858ad9Jeff Brown    if (sscanf(line, "%lx-%lx %*s %*x %*x:%*x %*d%n", &start, &end, &name_pos) != 2) {
51f95601708a46c098582eb836fe25889866858ad9Jeff Brown        *mi = NULL;
52f95601708a46c098582eb836fe25889866858ad9Jeff Brown        return -1;
53f95601708a46c098582eb836fe25889866858ad9Jeff Brown    }
54fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root
55f95601708a46c098582eb836fe25889866858ad9Jeff Brown    while (isspace(line[name_pos])) {
56f95601708a46c098582eb836fe25889866858ad9Jeff Brown        name_pos += 1;
57fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root    }
58fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root
59f95601708a46c098582eb836fe25889866858ad9Jeff Brown    if (line[name_pos]) {
60f95601708a46c098582eb836fe25889866858ad9Jeff Brown        strlcpy(name, line + name_pos, sizeof(name));
61f95601708a46c098582eb836fe25889866858ad9Jeff Brown    } else {
62d3cb030b4df7fd8fbdfa503840740592fc7061a3Nick Kralevich        if (prev && start == prev->end && is_library(prev->name)) {
63f95601708a46c098582eb836fe25889866858ad9Jeff Brown            // anonymous mappings immediately adjacent to shared libraries
64f95601708a46c098582eb836fe25889866858ad9Jeff Brown            // usually correspond to the library BSS segment, so we use the
65f95601708a46c098582eb836fe25889866858ad9Jeff Brown            // library's own name
66f95601708a46c098582eb836fe25889866858ad9Jeff Brown            strlcpy(name, prev->name, sizeof(name));
67f95601708a46c098582eb836fe25889866858ad9Jeff Brown            is_bss = 1;
68fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root        } else {
69fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root            strlcpy(name, "[anon]", sizeof(name));
70fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root        }
71fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root    }
72fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root
73fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root    const int name_size = strlen(name) + 1;
74ddbe8c3fcb3d8272129fd17ee3b06611f7df8185Elliott Hughes    struct mapinfo* info = reinterpret_cast<mapinfo*>(calloc(1, sizeof(mapinfo) + name_size));
75fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root    if (info == NULL) {
76f95601708a46c098582eb836fe25889866858ad9Jeff Brown        fprintf(stderr, "out of memory\n");
77f95601708a46c098582eb836fe25889866858ad9Jeff Brown        exit(1);
78fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root    }
79fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root
80fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root    info->start = start;
81fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root    info->end = end;
82f95601708a46c098582eb836fe25889866858ad9Jeff Brown    info->is_bss = is_bss;
8342ec73551a7ed4798de53cb8ed3b34fa964dde98Dianne Hackborn    info->count = 1;
84fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root    strlcpy(info->name, name, name_size);
85fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root
86fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root    *mi = info;
87fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root    return 0;
88fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root}
89fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root
90f95601708a46c098582eb836fe25889866858ad9Jeff Brownstatic int parse_field(mapinfo* mi, const char* line) {
91fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root    char field[64];
929a213e07f1e1f083bc56dbe707e0ec2af3990b43Jeff Brown    int len;
939a213e07f1e1f083bc56dbe707e0ec2af3990b43Jeff Brown
949a213e07f1e1f083bc56dbe707e0ec2af3990b43Jeff Brown    if (sscanf(line, "%63s %n", field, &len) == 1
959a213e07f1e1f083bc56dbe707e0ec2af3990b43Jeff Brown            && *field && field[strlen(field) - 1] == ':') {
969a213e07f1e1f083bc56dbe707e0ec2af3990b43Jeff Brown        int size;
979a213e07f1e1f083bc56dbe707e0ec2af3990b43Jeff Brown        if (sscanf(line + len, "%d kB", &size) == 1) {
989a213e07f1e1f083bc56dbe707e0ec2af3990b43Jeff Brown            if (!strcmp(field, "Size:")) {
999a213e07f1e1f083bc56dbe707e0ec2af3990b43Jeff Brown                mi->size = size;
1009a213e07f1e1f083bc56dbe707e0ec2af3990b43Jeff Brown            } else if (!strcmp(field, "Rss:")) {
1019a213e07f1e1f083bc56dbe707e0ec2af3990b43Jeff Brown                mi->rss = size;
1029a213e07f1e1f083bc56dbe707e0ec2af3990b43Jeff Brown            } else if (!strcmp(field, "Pss:")) {
1039a213e07f1e1f083bc56dbe707e0ec2af3990b43Jeff Brown                mi->pss = size;
1049a213e07f1e1f083bc56dbe707e0ec2af3990b43Jeff Brown            } else if (!strcmp(field, "Shared_Clean:")) {
1059a213e07f1e1f083bc56dbe707e0ec2af3990b43Jeff Brown                mi->shared_clean = size;
1069a213e07f1e1f083bc56dbe707e0ec2af3990b43Jeff Brown            } else if (!strcmp(field, "Shared_Dirty:")) {
1079a213e07f1e1f083bc56dbe707e0ec2af3990b43Jeff Brown                mi->shared_dirty = size;
1089a213e07f1e1f083bc56dbe707e0ec2af3990b43Jeff Brown            } else if (!strcmp(field, "Private_Clean:")) {
1099a213e07f1e1f083bc56dbe707e0ec2af3990b43Jeff Brown                mi->private_clean = size;
1109a213e07f1e1f083bc56dbe707e0ec2af3990b43Jeff Brown            } else if (!strcmp(field, "Private_Dirty:")) {
1119a213e07f1e1f083bc56dbe707e0ec2af3990b43Jeff Brown                mi->private_dirty = size;
11250173c39ec48135e0b629d4e59bf59c554d17773Martijn Coenen            } else if (!strcmp(field, "Swap:")) {
11350173c39ec48135e0b629d4e59bf59c554d17773Martijn Coenen                mi->swap = size;
1149a213e07f1e1f083bc56dbe707e0ec2af3990b43Jeff Brown            }
1159a213e07f1e1f083bc56dbe707e0ec2af3990b43Jeff Brown        }
1169a213e07f1e1f083bc56dbe707e0ec2af3990b43Jeff Brown        return 0;
117fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root    }
1189a213e07f1e1f083bc56dbe707e0ec2af3990b43Jeff Brown    return -1;
119fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root}
120fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root
121f95601708a46c098582eb836fe25889866858ad9Jeff Brownstatic int order_before(const mapinfo *a, const mapinfo *b, int sort_by_address) {
122f95601708a46c098582eb836fe25889866858ad9Jeff Brown    if (sort_by_address) {
123f95601708a46c098582eb836fe25889866858ad9Jeff Brown        return a->start < b->start
124f95601708a46c098582eb836fe25889866858ad9Jeff Brown                || (a->start == b->start && a->end < b->end);
125f95601708a46c098582eb836fe25889866858ad9Jeff Brown    } else {
126f95601708a46c098582eb836fe25889866858ad9Jeff Brown        return strcmp(a->name, b->name) < 0;
127f95601708a46c098582eb836fe25889866858ad9Jeff Brown    }
128f95601708a46c098582eb836fe25889866858ad9Jeff Brown}
129f95601708a46c098582eb836fe25889866858ad9Jeff Brown
130f95601708a46c098582eb836fe25889866858ad9Jeff Brownstatic void enqueue_map(mapinfo **head, mapinfo *map, int sort_by_address, int coalesce_by_name) {
131f95601708a46c098582eb836fe25889866858ad9Jeff Brown    mapinfo *prev = NULL;
132f95601708a46c098582eb836fe25889866858ad9Jeff Brown    mapinfo *current = *head;
133f95601708a46c098582eb836fe25889866858ad9Jeff Brown
134f95601708a46c098582eb836fe25889866858ad9Jeff Brown    if (!map) {
135f95601708a46c098582eb836fe25889866858ad9Jeff Brown        return;
136f95601708a46c098582eb836fe25889866858ad9Jeff Brown    }
137f95601708a46c098582eb836fe25889866858ad9Jeff Brown
138f95601708a46c098582eb836fe25889866858ad9Jeff Brown    for (;;) {
139f95601708a46c098582eb836fe25889866858ad9Jeff Brown        if (current && coalesce_by_name && !strcmp(map->name, current->name)) {
140f95601708a46c098582eb836fe25889866858ad9Jeff Brown            current->size += map->size;
141f95601708a46c098582eb836fe25889866858ad9Jeff Brown            current->rss += map->rss;
142f95601708a46c098582eb836fe25889866858ad9Jeff Brown            current->pss += map->pss;
143f95601708a46c098582eb836fe25889866858ad9Jeff Brown            current->shared_clean += map->shared_clean;
144f95601708a46c098582eb836fe25889866858ad9Jeff Brown            current->shared_dirty += map->shared_dirty;
145f95601708a46c098582eb836fe25889866858ad9Jeff Brown            current->private_clean += map->private_clean;
146f95601708a46c098582eb836fe25889866858ad9Jeff Brown            current->private_dirty += map->private_dirty;
14750173c39ec48135e0b629d4e59bf59c554d17773Martijn Coenen            current->swap += map->swap;
148f95601708a46c098582eb836fe25889866858ad9Jeff Brown            current->is_bss &= map->is_bss;
14942ec73551a7ed4798de53cb8ed3b34fa964dde98Dianne Hackborn            current->count++;
150f95601708a46c098582eb836fe25889866858ad9Jeff Brown            free(map);
151f95601708a46c098582eb836fe25889866858ad9Jeff Brown            break;
152f95601708a46c098582eb836fe25889866858ad9Jeff Brown        }
153f95601708a46c098582eb836fe25889866858ad9Jeff Brown
154f95601708a46c098582eb836fe25889866858ad9Jeff Brown        if (!current || order_before(map, current, sort_by_address)) {
155f95601708a46c098582eb836fe25889866858ad9Jeff Brown            if (prev) {
156f95601708a46c098582eb836fe25889866858ad9Jeff Brown                prev->next = map;
157f95601708a46c098582eb836fe25889866858ad9Jeff Brown            } else {
158f95601708a46c098582eb836fe25889866858ad9Jeff Brown                *head = map;
159f95601708a46c098582eb836fe25889866858ad9Jeff Brown            }
160f95601708a46c098582eb836fe25889866858ad9Jeff Brown            map->next = current;
161f95601708a46c098582eb836fe25889866858ad9Jeff Brown            break;
162f95601708a46c098582eb836fe25889866858ad9Jeff Brown        }
163f95601708a46c098582eb836fe25889866858ad9Jeff Brown
164f95601708a46c098582eb836fe25889866858ad9Jeff Brown        prev = current;
165f95601708a46c098582eb836fe25889866858ad9Jeff Brown        current = current->next;
166f95601708a46c098582eb836fe25889866858ad9Jeff Brown    }
167f95601708a46c098582eb836fe25889866858ad9Jeff Brown}
168f95601708a46c098582eb836fe25889866858ad9Jeff Brown
169f95601708a46c098582eb836fe25889866858ad9Jeff Brownstatic mapinfo *load_maps(int pid, int sort_by_address, int coalesce_by_name)
170e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project{
171f95601708a46c098582eb836fe25889866858ad9Jeff Brown    char fn[128];
172f95601708a46c098582eb836fe25889866858ad9Jeff Brown    FILE *fp;
173e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    char line[1024];
174f95601708a46c098582eb836fe25889866858ad9Jeff Brown    mapinfo *head = NULL;
175fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root    mapinfo *current = NULL;
176e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    int len;
177f95601708a46c098582eb836fe25889866858ad9Jeff Brown
178f95601708a46c098582eb836fe25889866858ad9Jeff Brown    snprintf(fn, sizeof(fn), "/proc/%d/smaps", pid);
179f95601708a46c098582eb836fe25889866858ad9Jeff Brown    fp = fopen(fn, "r");
180f95601708a46c098582eb836fe25889866858ad9Jeff Brown    if (fp == 0) {
181a5aa8f9583aec9fcfba38161cb31b6ae2b588313Felipe Leme        if (!quiet) fprintf(stderr, "cannot open /proc/%d/smaps: %s\n", pid, strerror(errno));
182f95601708a46c098582eb836fe25889866858ad9Jeff Brown        return NULL;
183f95601708a46c098582eb836fe25889866858ad9Jeff Brown    }
184e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
185fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root    while (fgets(line, sizeof(line), fp) != 0) {
186f95601708a46c098582eb836fe25889866858ad9Jeff Brown        len = strlen(line);
187f95601708a46c098582eb836fe25889866858ad9Jeff Brown        if (line[len - 1] == '\n') {
188f95601708a46c098582eb836fe25889866858ad9Jeff Brown            line[--len] = 0;
189fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root        }
190fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root
191f95601708a46c098582eb836fe25889866858ad9Jeff Brown        if (current != NULL && !parse_field(current, line)) {
192f95601708a46c098582eb836fe25889866858ad9Jeff Brown            continue;
193fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root        }
194e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
195f95601708a46c098582eb836fe25889866858ad9Jeff Brown        mapinfo *next;
196f95601708a46c098582eb836fe25889866858ad9Jeff Brown        if (!parse_header(line, current, &next)) {
197f95601708a46c098582eb836fe25889866858ad9Jeff Brown            enqueue_map(&head, current, sort_by_address, coalesce_by_name);
198fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root            current = next;
199fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root            continue;
200fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root        }
201e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
202f95601708a46c098582eb836fe25889866858ad9Jeff Brown        fprintf(stderr, "warning: could not parse map info line: %s\n", line);
203fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root    }
204e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
205f95601708a46c098582eb836fe25889866858ad9Jeff Brown    enqueue_map(&head, current, sort_by_address, coalesce_by_name);
206e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
207fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root    fclose(fp);
208fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root
209f95601708a46c098582eb836fe25889866858ad9Jeff Brown    if (!head) {
210a5aa8f9583aec9fcfba38161cb31b6ae2b588313Felipe Leme        if (!quiet) fprintf(stderr, "could not read /proc/%d/smaps\n", pid);
211fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root        return NULL;
212fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root    }
213fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root
214f95601708a46c098582eb836fe25889866858ad9Jeff Brown    return head;
215e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project}
216e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
21742ec73551a7ed4798de53cb8ed3b34fa964dde98Dianne Hackbornstatic void print_header()
21842ec73551a7ed4798de53cb8ed3b34fa964dde98Dianne Hackborn{
219ddbe8c3fcb3d8272129fd17ee3b06611f7df8185Elliott Hughes    const char *addr1 = addresses ? "   start      end " : "";
220ddbe8c3fcb3d8272129fd17ee3b06611f7df8185Elliott Hughes    const char *addr2 = addresses ? "    addr     addr " : "";
22142ec73551a7ed4798de53cb8ed3b34fa964dde98Dianne Hackborn
222ddbe8c3fcb3d8272129fd17ee3b06611f7df8185Elliott Hughes    printf("%s virtual                     shared   shared  private  private\n", addr1);
223ddbe8c3fcb3d8272129fd17ee3b06611f7df8185Elliott Hughes    printf("%s    size      RSS      PSS    clean    dirty    clean    dirty     swap ", addr2);
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    }
23550173c39ec48135e0b629d4e59bf59c554d17773Martijn Coenen    printf("-------- -------- -------- -------- -------- -------- -------- -------- ");
23642ec73551a7ed4798de53cb8ed3b34fa964dde98Dianne Hackborn    if (!verbose && !addresses) {
23742ec73551a7ed4798de53cb8ed3b34fa964dde98Dianne Hackborn        printf("---- ");
23842ec73551a7ed4798de53cb8ed3b34fa964dde98Dianne Hackborn    }
23942ec73551a7ed4798de53cb8ed3b34fa964dde98Dianne Hackborn    printf("------------------------------\n");
24042ec73551a7ed4798de53cb8ed3b34fa964dde98Dianne Hackborn}
24142ec73551a7ed4798de53cb8ed3b34fa964dde98Dianne Hackborn
242ddbe8c3fcb3d8272129fd17ee3b06611f7df8185Elliott Hughesstatic void print_mi(mapinfo *mi, bool total)
243ddbe8c3fcb3d8272129fd17ee3b06611f7df8185Elliott Hughes{
244ddbe8c3fcb3d8272129fd17ee3b06611f7df8185Elliott Hughes    if (addresses) {
245ddbe8c3fcb3d8272129fd17ee3b06611f7df8185Elliott Hughes        if (total) {
246ddbe8c3fcb3d8272129fd17ee3b06611f7df8185Elliott Hughes            printf("                  ");
247ddbe8c3fcb3d8272129fd17ee3b06611f7df8185Elliott Hughes        } else {
248ddbe8c3fcb3d8272129fd17ee3b06611f7df8185Elliott Hughes            printf("%08x %08x ", mi->start, mi->end);
249ddbe8c3fcb3d8272129fd17ee3b06611f7df8185Elliott Hughes        }
250ddbe8c3fcb3d8272129fd17ee3b06611f7df8185Elliott Hughes    }
251ddbe8c3fcb3d8272129fd17ee3b06611f7df8185Elliott Hughes    printf("%8d %8d %8d %8d %8d %8d %8d %8d ", mi->size,
252ddbe8c3fcb3d8272129fd17ee3b06611f7df8185Elliott Hughes           mi->rss,
253ddbe8c3fcb3d8272129fd17ee3b06611f7df8185Elliott Hughes           mi->pss,
254ddbe8c3fcb3d8272129fd17ee3b06611f7df8185Elliott Hughes           mi->shared_clean, mi->shared_dirty,
255ddbe8c3fcb3d8272129fd17ee3b06611f7df8185Elliott Hughes           mi->private_clean, mi->private_dirty, mi->swap);
256ddbe8c3fcb3d8272129fd17ee3b06611f7df8185Elliott Hughes    if (!verbose && !addresses) {
257ddbe8c3fcb3d8272129fd17ee3b06611f7df8185Elliott Hughes        printf("%4d ", mi->count);
258ddbe8c3fcb3d8272129fd17ee3b06611f7df8185Elliott Hughes    }
259ddbe8c3fcb3d8272129fd17ee3b06611f7df8185Elliott Hughes}
260ddbe8c3fcb3d8272129fd17ee3b06611f7df8185Elliott Hughes
261f95601708a46c098582eb836fe25889866858ad9Jeff Brownstatic int show_map(int pid)
262e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project{
263ddbe8c3fcb3d8272129fd17ee3b06611f7df8185Elliott Hughes    mapinfo total;
264ddbe8c3fcb3d8272129fd17ee3b06611f7df8185Elliott Hughes    memset(&total, 0, sizeof(total));
265ddbe8c3fcb3d8272129fd17ee3b06611f7df8185Elliott Hughes
266ddbe8c3fcb3d8272129fd17ee3b06611f7df8185Elliott Hughes    mapinfo *milist = load_maps(pid, addresses, !verbose && !addresses);
267fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root    if (milist == NULL) {
268a5aa8f9583aec9fcfba38161cb31b6ae2b588313Felipe Leme        return quiet ? 0 : 1;
269e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    }
270e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
27142ec73551a7ed4798de53cb8ed3b34fa964dde98Dianne Hackborn    print_header();
27242ec73551a7ed4798de53cb8ed3b34fa964dde98Dianne Hackborn    print_divider();
273fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root
274ddbe8c3fcb3d8272129fd17ee3b06611f7df8185Elliott Hughes    for (mapinfo *mi = milist; mi;) {
275fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root        mapinfo* last = mi;
276fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root
277ddbe8c3fcb3d8272129fd17ee3b06611f7df8185Elliott Hughes        total.shared_clean += mi->shared_clean;
278ddbe8c3fcb3d8272129fd17ee3b06611f7df8185Elliott Hughes        total.shared_dirty += mi->shared_dirty;
279ddbe8c3fcb3d8272129fd17ee3b06611f7df8185Elliott Hughes        total.private_clean += mi->private_clean;
280ddbe8c3fcb3d8272129fd17ee3b06611f7df8185Elliott Hughes        total.private_dirty += mi->private_dirty;
281ddbe8c3fcb3d8272129fd17ee3b06611f7df8185Elliott Hughes        total.swap += mi->swap;
282ddbe8c3fcb3d8272129fd17ee3b06611f7df8185Elliott Hughes        total.rss += mi->rss;
283ddbe8c3fcb3d8272129fd17ee3b06611f7df8185Elliott Hughes        total.pss += mi->pss;
284ddbe8c3fcb3d8272129fd17ee3b06611f7df8185Elliott Hughes        total.size += mi->size;
285ddbe8c3fcb3d8272129fd17ee3b06611f7df8185Elliott Hughes        total.count += mi->count;
286a5aa8f9583aec9fcfba38161cb31b6ae2b588313Felipe Leme
287fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root        if (terse && !mi->private_dirty) {
288fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root            goto out;
289fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root        }
290e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
291ddbe8c3fcb3d8272129fd17ee3b06611f7df8185Elliott Hughes        print_mi(mi, false);
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
303ddbe8c3fcb3d8272129fd17ee3b06611f7df8185Elliott Hughes    print_mi(&total, true);
30442ec73551a7ed4798de53cb8ed3b34fa964dde98Dianne Hackborn    printf("TOTAL\n");
305fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root
306e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    return 0;
307e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project}
308e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
309e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projectint main(int argc, char *argv[])
310e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project{
311e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    int usage = 1;
312f95601708a46c098582eb836fe25889866858ad9Jeff Brown    int result = 0;
313f95601708a46c098582eb836fe25889866858ad9Jeff Brown    int pid;
314f95601708a46c098582eb836fe25889866858ad9Jeff Brown    char *arg;
315f95601708a46c098582eb836fe25889866858ad9Jeff Brown    char *argend;
316f95601708a46c098582eb836fe25889866858ad9Jeff Brown
31780cb15504324667c9934ff350afff48881613393JP Abgrall    signal(SIGPIPE, SIG_IGN);
318fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root    for (argc--, argv++; argc > 0; argc--, argv++) {
319f95601708a46c098582eb836fe25889866858ad9Jeff Brown        arg = argv[0];
320f95601708a46c098582eb836fe25889866858ad9Jeff Brown        if (!strcmp(arg,"-v")) {
321ddbe8c3fcb3d8272129fd17ee3b06611f7df8185Elliott Hughes            verbose = true;
322e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project            continue;
323e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        }
324f95601708a46c098582eb836fe25889866858ad9Jeff Brown        if (!strcmp(arg,"-t")) {
325ddbe8c3fcb3d8272129fd17ee3b06611f7df8185Elliott Hughes            terse = true;
326e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project            continue;
327e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        }
328f95601708a46c098582eb836fe25889866858ad9Jeff Brown        if (!strcmp(arg,"-a")) {
329ddbe8c3fcb3d8272129fd17ee3b06611f7df8185Elliott Hughes            addresses = true;
330e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project            continue;
331e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        }
332a5aa8f9583aec9fcfba38161cb31b6ae2b588313Felipe Leme        if (!strcmp(arg,"-q")) {
333a5aa8f9583aec9fcfba38161cb31b6ae2b588313Felipe Leme            quiet = true;
334a5aa8f9583aec9fcfba38161cb31b6ae2b588313Felipe Leme            continue;
335a5aa8f9583aec9fcfba38161cb31b6ae2b588313Felipe Leme        }
336f95601708a46c098582eb836fe25889866858ad9Jeff Brown        if (argc != 1) {
337f95601708a46c098582eb836fe25889866858ad9Jeff Brown            fprintf(stderr, "too many arguments\n");
338f95601708a46c098582eb836fe25889866858ad9Jeff Brown            break;
339f95601708a46c098582eb836fe25889866858ad9Jeff Brown        }
340f95601708a46c098582eb836fe25889866858ad9Jeff Brown        pid = strtol(arg, &argend, 10);
341f95601708a46c098582eb836fe25889866858ad9Jeff Brown        if (*arg && !*argend) {
342f95601708a46c098582eb836fe25889866858ad9Jeff Brown            usage = 0;
343f95601708a46c098582eb836fe25889866858ad9Jeff Brown            if (show_map(pid)) {
344f95601708a46c098582eb836fe25889866858ad9Jeff Brown                result = 1;
345f95601708a46c098582eb836fe25889866858ad9Jeff Brown            }
346f95601708a46c098582eb836fe25889866858ad9Jeff Brown            break;
347f95601708a46c098582eb836fe25889866858ad9Jeff Brown        }
348f95601708a46c098582eb836fe25889866858ad9Jeff Brown        fprintf(stderr, "unrecognized argument: %s\n", arg);
349f95601708a46c098582eb836fe25889866858ad9Jeff Brown        break;
350e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    }
351e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
352fda77ea946fa4c58775d5ff63895cf9d41d3b568Kenny Root    if (usage) {
353e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        fprintf(stderr,
354a5aa8f9583aec9fcfba38161cb31b6ae2b588313Felipe Leme                "showmap [-t] [-v] [-c] [-q] <pid>\n"
355e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project                "        -t = terse (show only items with private pages)\n"
356f95601708a46c098582eb836fe25889866858ad9Jeff Brown                "        -v = verbose (don't coalesce maps with the same name)\n"
357e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project                "        -a = addresses (show virtual memory map)\n"
358a5aa8f9583aec9fcfba38161cb31b6ae2b588313Felipe Leme                "        -q = quiet (don't show error if map could not be read)\n"
359e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project                );
360f95601708a46c098582eb836fe25889866858ad9Jeff Brown        result = 1;
361e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    }
362e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
363f95601708a46c098582eb836fe25889866858ad9Jeff Brown    return result;
364e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project}
365