1e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project/*
2e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project
3e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project *
4e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
5e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project * you may not use this file except in compliance with the License.
6e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project * You may obtain a copy of the License at
7e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project *
8e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
9e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project *
10e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
11e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
12e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project * See the License for the specific language governing permissions and
14e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project * limitations under the License.
15e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project */
16e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
17e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project#include <errno.h>
18e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project#include <fcntl.h>
19e2998ffe6f494f06b25aca372c1d35cd47390b98Colin Cross#include <inttypes.h>
20e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project#include <stdio.h>
21e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project#include <stdlib.h>
22e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project#include <string.h>
23e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project#include <unistd.h>
24e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
25e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project#include <pagemap/pagemap.h>
26e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
27e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project#include "pm_map.h"
28e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
29e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projectstatic int read_maps(pm_process_t *proc);
30e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
31e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project#define MAX_FILENAME 64
32e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
33e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projectint pm_process_create(pm_kernel_t *ker, pid_t pid, pm_process_t **proc_out) {
34e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    pm_process_t *proc;
35e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    char filename[MAX_FILENAME];
36e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    int error;
37e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
38e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    if (!ker || !proc_out)
39e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        return -1;
40e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
41e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    proc = calloc(1, sizeof(*proc));
42e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    if (!proc)
43e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        return errno;
44e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
45e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    proc->ker = ker;
46e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    proc->pid = pid;
47e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
48e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    error = snprintf(filename, MAX_FILENAME, "/proc/%d/pagemap", pid);
49e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    if (error < 0 || error >= MAX_FILENAME) {
50e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        error = (error < 0) ? (errno) : (-1);
51e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        free(proc);
52e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        return error;
53e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    }
54e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
55e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    proc->pagemap_fd = open(filename, O_RDONLY);
56e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    if (proc->pagemap_fd < 0) {
57e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        error = errno;
58e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        free(proc);
59e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        return error;
60e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    }
61e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
62e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    error = read_maps(proc);
63e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    if (error) {
64e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        free(proc);
65e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        return error;
66e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    }
67e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
68e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    *proc_out = proc;
69e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
70e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    return 0;
71e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project}
72e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
73931563e96d9ff65d7d2a4642c8f26fb19e47be47Colin Crossint pm_process_usage_flags(pm_process_t *proc, pm_memusage_t *usage_out,
74931563e96d9ff65d7d2a4642c8f26fb19e47be47Colin Cross                        uint64_t flags_mask, uint64_t required_flags)
75931563e96d9ff65d7d2a4642c8f26fb19e47be47Colin Cross{
76e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    pm_memusage_t usage, map_usage;
77e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    int error;
78e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    int i;
79e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
80e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    if (!proc || !usage_out)
81e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        return -1;
82e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
83e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    pm_memusage_zero(&usage);
84e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
85e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    for (i = 0; i < proc->num_maps; i++) {
86931563e96d9ff65d7d2a4642c8f26fb19e47be47Colin Cross        error = pm_map_usage_flags(proc->maps[i], &map_usage, flags_mask,
87931563e96d9ff65d7d2a4642c8f26fb19e47be47Colin Cross                                   required_flags);
88e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        if (error) return error;
89e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
90e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        pm_memusage_add(&usage, &map_usage);
91e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    }
92e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
93e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    memcpy(usage_out, &usage, sizeof(pm_memusage_t));
94e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
95e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    return 0;
96931563e96d9ff65d7d2a4642c8f26fb19e47be47Colin Cross
97931563e96d9ff65d7d2a4642c8f26fb19e47be47Colin Cross}
98931563e96d9ff65d7d2a4642c8f26fb19e47be47Colin Cross
99931563e96d9ff65d7d2a4642c8f26fb19e47be47Colin Crossint pm_process_usage(pm_process_t *proc, pm_memusage_t *usage_out) {
100931563e96d9ff65d7d2a4642c8f26fb19e47be47Colin Cross    return pm_process_usage_flags(proc, usage_out, 0, 0);
101e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project}
102e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
103e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projectint pm_process_pagemap_range(pm_process_t *proc,
104e2998ffe6f494f06b25aca372c1d35cd47390b98Colin Cross                             uint64_t low, uint64_t high,
105e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project                             uint64_t **range_out, size_t *len) {
106e2998ffe6f494f06b25aca372c1d35cd47390b98Colin Cross    uint64_t firstpage;
107e2998ffe6f494f06b25aca372c1d35cd47390b98Colin Cross    uint64_t numpages;
108e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    uint64_t *range;
109e2998ffe6f494f06b25aca372c1d35cd47390b98Colin Cross    off64_t off;
110e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    int error;
111e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
112bac600309b1aed0d55bee8c32c5031ba889ee517Colin Cross    if (!proc || (low > high) || !range_out || !len)
113e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        return -1;
114e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
115bac600309b1aed0d55bee8c32c5031ba889ee517Colin Cross    if (low == high) {
116bac600309b1aed0d55bee8c32c5031ba889ee517Colin Cross        *range_out = NULL;
117bac600309b1aed0d55bee8c32c5031ba889ee517Colin Cross        *len = 0;
118bac600309b1aed0d55bee8c32c5031ba889ee517Colin Cross        return 0;
119bac600309b1aed0d55bee8c32c5031ba889ee517Colin Cross    }
120bac600309b1aed0d55bee8c32c5031ba889ee517Colin Cross
121e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    firstpage = low / proc->ker->pagesize;
122e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    numpages = (high - low) / proc->ker->pagesize;
123e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
124e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    range = malloc(numpages * sizeof(uint64_t));
125e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    if (!range)
126e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        return errno;
127e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
128e2998ffe6f494f06b25aca372c1d35cd47390b98Colin Cross    off = lseek64(proc->pagemap_fd, firstpage * sizeof(uint64_t), SEEK_SET);
129e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    if (off == (off_t)-1) {
130e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        error = errno;
131e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        free(range);
132e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        return error;
133e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    }
134e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    error = read(proc->pagemap_fd, (char*)range, numpages * sizeof(uint64_t));
1356620157c0f583c4c7a59d1d595589dbb2b3ae4b5Colin Cross    if (error == 0) {
1366620157c0f583c4c7a59d1d595589dbb2b3ae4b5Colin Cross        /* EOF, mapping is not in userspace mapping range (probably vectors) */
1376620157c0f583c4c7a59d1d595589dbb2b3ae4b5Colin Cross        *len = 0;
1386620157c0f583c4c7a59d1d595589dbb2b3ae4b5Colin Cross        free(range);
1396620157c0f583c4c7a59d1d595589dbb2b3ae4b5Colin Cross        *range_out = NULL;
1406620157c0f583c4c7a59d1d595589dbb2b3ae4b5Colin Cross        return 0;
14176e6cb55fed01824e44306aa0485a3f8f122b228Selim Gurun    } else if (error < 0 || (error > 0 && error < (int)(numpages * sizeof(uint64_t)))) {
142e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        error = (error < 0) ? errno : -1;
143e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        free(range);
144e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        return error;
145e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    }
146e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
147e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    *range_out = range;
148e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    *len = numpages;
149e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
150e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    return 0;
151e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project}
152e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
153e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projectint pm_process_maps(pm_process_t *proc, pm_map_t ***maps_out, size_t *len) {
154e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    pm_map_t **maps;
155e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
156e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    if (!proc || !maps_out || !len)
157e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        return -1;
158e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
159e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    if (proc->num_maps) {
160e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        maps = malloc(proc->num_maps * sizeof(pm_map_t*));
161e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        if (!maps)
162e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project            return errno;
163e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
164e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        memcpy(maps, proc->maps, proc->num_maps * sizeof(pm_map_t*));
165e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
166e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        *maps_out = maps;
167e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    } else {
168e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        *maps_out = NULL;
169e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    }
170e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    *len = proc->num_maps;
171e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
172e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    return 0;
173e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project}
174e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
175e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projectint pm_process_workingset(pm_process_t *proc,
176e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project                          pm_memusage_t *ws_out, int reset) {
177e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    pm_memusage_t ws, map_ws;
178e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    char filename[MAX_FILENAME];
179e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    int fd;
180e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    int i, j;
181e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    int error;
182e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
183e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    if (!proc)
184e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        return -1;
185e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
186e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    if (ws_out) {
187e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        pm_memusage_zero(&ws);
188e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        for (i = 0; i < proc->num_maps; i++) {
189e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project            error = pm_map_workingset(proc->maps[i], &map_ws);
190e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project            if (error) return error;
191e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
192e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project            pm_memusage_add(&ws, &map_ws);
193e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        }
194e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
195e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        memcpy(ws_out, &ws, sizeof(ws));
196e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    }
197e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
198e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    if (reset) {
199e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        error = snprintf(filename, MAX_FILENAME, "/proc/%d/clear_refs",
200e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project                         proc->pid);
201e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        if (error < 0 || error >= MAX_FILENAME) {
202e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project            return (error < 0) ? (errno) : (-1);
203e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        }
204e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
205e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        fd = open(filename, O_WRONLY);
206e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        if (fd < 0)
207e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project            return errno;
208e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
209e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        write(fd, "1\n", strlen("1\n"));
210e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
211e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        close(fd);
212e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    }
213e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
214e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    return 0;
215e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project}
216e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
217e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projectint pm_process_destroy(pm_process_t *proc) {
218d3fa8e5f889cd8fdcc9029af421ca755bd20ac1eCarton He    int i;
219d3fa8e5f889cd8fdcc9029af421ca755bd20ac1eCarton He
220e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    if (!proc)
221e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        return -1;
222e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
223d3fa8e5f889cd8fdcc9029af421ca755bd20ac1eCarton He    for (i = 0; i < proc->num_maps; i++) {
224d3fa8e5f889cd8fdcc9029af421ca755bd20ac1eCarton He        pm_map_destroy(proc->maps[i]);
225d3fa8e5f889cd8fdcc9029af421ca755bd20ac1eCarton He    }
226e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    free(proc->maps);
227e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    close(proc->pagemap_fd);
228e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    free(proc);
229e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
230e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    return 0;
231e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project}
232e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
233e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project#define INITIAL_MAPS 10
23476e6cb55fed01824e44306aa0485a3f8f122b228Selim Gurun#define MAX_LINE 1024
235e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project#define MAX_PERMS 5
236e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
237e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project/*
238e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project * #define FOO 123
239e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project * S(FOO) => "123"
240e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project */
241e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project#define _S(n) #n
242e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project#define S(n) _S(n)
243e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
244e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projectstatic int read_maps(pm_process_t *proc) {
245e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    char filename[MAX_FILENAME];
246e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    char line[MAX_LINE], name[MAX_LINE], perms[MAX_PERMS];
247e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    FILE *maps_f;
248e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    pm_map_t *map, **maps, **new_maps;
249e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    int maps_count, maps_size;
250e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    int error;
251e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
252e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    if (!proc)
253e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        return -1;
254e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
255e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    maps = calloc(INITIAL_MAPS, sizeof(pm_map_t*));
256e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    if (!maps)
257e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        return errno;
258e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    maps_count = 0; maps_size = INITIAL_MAPS;
259e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
260e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    error = snprintf(filename, MAX_FILENAME, "/proc/%d/maps", proc->pid);
261e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    if (error < 0 || error >= MAX_FILENAME)
262e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        return (error < 0) ? (errno) : (-1);
263e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
264e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    maps_f = fopen(filename, "r");
265e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    if (!maps_f)
266e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        return errno;
267e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
268e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    while (fgets(line, MAX_LINE, maps_f)) {
269e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        if (maps_count >= maps_size) {
270e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project            new_maps = realloc(maps, 2 * maps_size * sizeof(pm_map_t*));
271e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project            if (!new_maps) {
272e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project                error = errno;
273e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project                free(maps);
274e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project                fclose(maps_f);
275e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project                return error;
276e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project            }
277e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project            maps = new_maps;
278e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project            maps_size *= 2;
279e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        }
280e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
281e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        maps[maps_count] = map = calloc(1, sizeof(*map));
282e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
283e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        map->proc = proc;
284e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
2855d461218f8c38dadf831ccc52ac6e5153687cf17Colin Cross        name[0] = '\0';
286e2998ffe6f494f06b25aca372c1d35cd47390b98Colin Cross        sscanf(line, "%" SCNx64 "-%" SCNx64 " %s %" SCNx64 " %*s %*d %" S(MAX_LINE) "s",
287e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project               &map->start, &map->end, perms, &map->offset, name);
288e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
289e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        map->name = malloc(strlen(name) + 1);
290e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        if (!map->name) {
291e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project            error = errno;
292e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project            for (; maps_count > 0; maps_count--)
293e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project                pm_map_destroy(maps[maps_count]);
294e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project            free(maps);
295e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project            return error;
296e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        }
297e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        strcpy(map->name, name);
298e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        if (perms[0] == 'r') map->flags |= PM_MAP_READ;
299e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        if (perms[1] == 'w') map->flags |= PM_MAP_WRITE;
300e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        if (perms[2] == 'x') map->flags |= PM_MAP_EXEC;
301e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
302e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        maps_count++;
303e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    }
304e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
305e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    fclose(maps_f);
306e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
307e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    new_maps = realloc(maps, maps_count * sizeof(pm_map_t*));
308e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    if (maps_count && !new_maps) {
309e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        error = errno;
310e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        free(maps);
311e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        return error;
312e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    }
313e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
314e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    proc->maps = new_maps;
315e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    proc->num_maps = maps_count;
316e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
317e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    return 0;
318e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project}
319