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