debug_mapinfo.cpp revision c701e5b3357b6484572d46f29c5d1e51063dfcbb
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
40static 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