1 /* 2 * Copyright (C) 2012 The Android Open Source Project 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * * Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * * Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in 12 * the documentation and/or other materials provided with the 13 * distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 16 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 17 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 18 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 19 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 22 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 25 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29 #include <ctype.h> 30 #include <inttypes.h> 31 #include <stdio.h> 32 #include <string.h> 33 #include <stdlib.h> 34 35 #include "debug_mapinfo.h" 36 #include "malloc_debug_disable.h" 37 38 // Format of /proc/<PID>/maps: 39 // 6f000000-6f01e000 rwxp 00000000 00:0c 16389419 /system/lib/libcomposer.so 40 static mapinfo_t* parse_maps_line(char* line) { 41 uintptr_t start; 42 uintptr_t end; 43 int name_pos; 44 if (sscanf(line, "%" PRIxPTR "-%" PRIxPTR " %*4s %*x %*x:%*x %*d%n", &start, 45 &end, &name_pos) < 2) { 46 return NULL; 47 } 48 49 while (isspace(line[name_pos])) { 50 name_pos += 1; 51 } 52 const char* name = line + name_pos; 53 size_t name_len = strlen(name); 54 if (name_len && name[name_len - 1] == '\n') { 55 name_len -= 1; 56 } 57 58 mapinfo_t* mi = reinterpret_cast<mapinfo_t*>(calloc(1, sizeof(mapinfo_t) + name_len + 1)); 59 if (mi) { 60 mi->start = start; 61 mi->end = end; 62 memcpy(mi->name, name, name_len); 63 mi->name[name_len] = '\0'; 64 } 65 return mi; 66 } 67 68 __LIBC_HIDDEN__ mapinfo_t* mapinfo_create(pid_t pid) { 69 ScopedDisableDebugCalls disable; 70 71 struct mapinfo_t* milist = NULL; 72 char data[1024]; // Used to read lines as well as to construct the filename. 73 snprintf(data, sizeof(data), "/proc/%d/maps", pid); 74 FILE* fp = fopen(data, "r"); 75 if (fp != NULL) { 76 while (fgets(data, sizeof(data), fp) != NULL) { 77 mapinfo_t* mi = parse_maps_line(data); 78 if (mi) { 79 mi->next = milist; 80 milist = mi; 81 } 82 } 83 fclose(fp); 84 } 85 return milist; 86 } 87 88 __LIBC_HIDDEN__ void mapinfo_destroy(mapinfo_t* mi) { 89 ScopedDisableDebugCalls disable; 90 91 while (mi != NULL) { 92 mapinfo_t* del = mi; 93 mi = mi->next; 94 free(del); 95 } 96 } 97 98 // Find the containing map info for the PC. 99 __LIBC_HIDDEN__ const mapinfo_t* mapinfo_find(mapinfo_t* mi, uintptr_t pc, uintptr_t* rel_pc) { 100 for (; mi != NULL; mi = mi->next) { 101 if ((pc >= mi->start) && (pc < mi->end)) { 102 *rel_pc = pc - mi->start; 103 return mi; 104 } 105 } 106 *rel_pc = pc; 107 return NULL; 108 } 109