map_info.c revision 501edd29b823ce1301d2effdd3a9e4b6e2b20b76
1501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown/* 2501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown * Copyright (C) 2011 The Android Open Source Project 3501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown * 4501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown * Licensed under the Apache License, Version 2.0 (the "License"); 5501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown * you may not use this file except in compliance with the License. 6501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown * You may obtain a copy of the License at 7501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown * 8501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown * http://www.apache.org/licenses/LICENSE-2.0 9501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown * 10501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown * Unless required by applicable law or agreed to in writing, software 11501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown * distributed under the License is distributed on an "AS IS" BASIS, 12501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown * See the License for the specific language governing permissions and 14501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown * limitations under the License. 15501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown */ 16501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown 17501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown#define LOG_TAG "Corkscrew" 18501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown//#define LOG_NDEBUG 0 19501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown 20501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown#include <corkscrew/map_info.h> 21501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown 22501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown#include <ctype.h> 23501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown#include <stdio.h> 24501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown#include <string.h> 25501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown#include <limits.h> 26501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown#include <pthread.h> 27501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown#include <unistd.h> 28501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown#include <cutils/log.h> 29501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown 30501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown// 6f000000-6f01e000 rwxp 00000000 00:0c 16389419 /system/lib/libcomposer.so\n 31501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown// 012345678901234567890123456789012345678901234567890123456789 32501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown// 0 1 2 3 4 5 33501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brownstatic map_info_t* parse_maps_line(const char* line) 34501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown{ 35501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown unsigned long int start; 36501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown unsigned long int end; 37501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown char permissions[5]; 38501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown int name_pos; 39501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown if (sscanf(line, "%lx-%lx %4s %*x %*x:%*x %*d%n", &start, &end, 40501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown permissions, &name_pos) != 3) { 41501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown return NULL; 42501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown } 43501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown 44501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown while (isspace(line[name_pos])) { 45501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown name_pos += 1; 46501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown } 47501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown const char* name = line + name_pos; 48501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown size_t name_len = strlen(name); 49501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown if (name_len && name[name_len - 1] == '\n') { 50501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown name_len -= 1; 51501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown } 52501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown 53501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown map_info_t* mi = calloc(1, sizeof(map_info_t) + name_len + 1); 54501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown if (mi) { 55501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown mi->start = start; 56501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown mi->end = end; 57501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown mi->is_executable = strlen(permissions) == 4 && permissions[2] == 'x'; 58501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown mi->data = NULL; 59501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown memcpy(mi->name, name, name_len); 60501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown mi->name[name_len] = '\0'; 61501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown } 62501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown return mi; 63501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown} 64501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown 65501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brownmap_info_t* load_map_info_list(pid_t tid) { 66501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown char path[PATH_MAX]; 67501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown char line[1024]; 68501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown FILE* fp; 69501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown map_info_t* milist = NULL; 70501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown 71501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown snprintf(path, PATH_MAX, "/proc/%d/maps", tid); 72501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown fp = fopen(path, "r"); 73501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown if (fp) { 74501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown while(fgets(line, sizeof(line), fp)) { 75501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown map_info_t* mi = parse_maps_line(line); 76501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown if (mi) { 77501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown mi->next = milist; 78501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown milist = mi; 79501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown } 80501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown } 81501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown fclose(fp); 82501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown } 83501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown return milist; 84501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown} 85501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown 86501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brownvoid free_map_info_list(map_info_t* milist) { 87501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown while (milist) { 88501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown map_info_t* next = milist->next; 89501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown free(milist); 90501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown milist = next; 91501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown } 92501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown} 93501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown 94501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brownconst map_info_t* find_map_info(const map_info_t* milist, uintptr_t addr) { 95501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown const map_info_t* mi = milist; 96501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown while (mi && !(addr >= mi->start && addr < mi->end)) { 97501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown mi = mi->next; 98501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown } 99501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown return mi; 100501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown} 101501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown 102501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brownstatic pthread_once_t g_my_milist_once = PTHREAD_ONCE_INIT; 103501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brownstatic map_info_t* g_my_milist = NULL; 104501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown 105501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brownstatic void init_my_milist_once() { 106501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown g_my_milist = load_map_info_list(getpid()); 107501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown} 108501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown 109501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brownconst map_info_t* my_map_info_list() { 110501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown pthread_once(&g_my_milist_once, init_my_milist_once); 111501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown return g_my_milist; 112501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown} 113