1e1dd3c287ba836281de0197670018bd9bbfbd62bIliyan Malchev/*
2e1dd3c287ba836281de0197670018bd9bbfbd62bIliyan Malchev * Copyright (C) 2012 The Android Open Source Project
3e1dd3c287ba836281de0197670018bd9bbfbd62bIliyan Malchev * All rights reserved.
4e1dd3c287ba836281de0197670018bd9bbfbd62bIliyan Malchev *
5e1dd3c287ba836281de0197670018bd9bbfbd62bIliyan Malchev * Redistribution and use in source and binary forms, with or without
6e1dd3c287ba836281de0197670018bd9bbfbd62bIliyan Malchev * modification, are permitted provided that the following conditions
7e1dd3c287ba836281de0197670018bd9bbfbd62bIliyan Malchev * are met:
8e1dd3c287ba836281de0197670018bd9bbfbd62bIliyan Malchev *  * Redistributions of source code must retain the above copyright
9e1dd3c287ba836281de0197670018bd9bbfbd62bIliyan Malchev *    notice, this list of conditions and the following disclaimer.
10e1dd3c287ba836281de0197670018bd9bbfbd62bIliyan Malchev *  * Redistributions in binary form must reproduce the above copyright
11e1dd3c287ba836281de0197670018bd9bbfbd62bIliyan Malchev *    notice, this list of conditions and the following disclaimer in
12e1dd3c287ba836281de0197670018bd9bbfbd62bIliyan Malchev *    the documentation and/or other materials provided with the
13e1dd3c287ba836281de0197670018bd9bbfbd62bIliyan Malchev *    distribution.
14e1dd3c287ba836281de0197670018bd9bbfbd62bIliyan Malchev *
15e1dd3c287ba836281de0197670018bd9bbfbd62bIliyan Malchev * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16e1dd3c287ba836281de0197670018bd9bbfbd62bIliyan Malchev * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17e1dd3c287ba836281de0197670018bd9bbfbd62bIliyan Malchev * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
18e1dd3c287ba836281de0197670018bd9bbfbd62bIliyan Malchev * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
19e1dd3c287ba836281de0197670018bd9bbfbd62bIliyan Malchev * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20e1dd3c287ba836281de0197670018bd9bbfbd62bIliyan Malchev * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21e1dd3c287ba836281de0197670018bd9bbfbd62bIliyan Malchev * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
22e1dd3c287ba836281de0197670018bd9bbfbd62bIliyan Malchev * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23e1dd3c287ba836281de0197670018bd9bbfbd62bIliyan Malchev * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24e1dd3c287ba836281de0197670018bd9bbfbd62bIliyan Malchev * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
25e1dd3c287ba836281de0197670018bd9bbfbd62bIliyan Malchev * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26e1dd3c287ba836281de0197670018bd9bbfbd62bIliyan Malchev * SUCH DAMAGE.
27e1dd3c287ba836281de0197670018bd9bbfbd62bIliyan Malchev */
28e1dd3c287ba836281de0197670018bd9bbfbd62bIliyan Malchev
29e1dd3c287ba836281de0197670018bd9bbfbd62bIliyan Malchev#include <stdio.h>
30e1dd3c287ba836281de0197670018bd9bbfbd62bIliyan Malchev#include <string.h>
31e1dd3c287ba836281de0197670018bd9bbfbd62bIliyan Malchev#include <stdlib.h>
32e1dd3c287ba836281de0197670018bd9bbfbd62bIliyan Malchev
33e1dd3c287ba836281de0197670018bd9bbfbd62bIliyan Malchev#include "dlmalloc.h"
34e1dd3c287ba836281de0197670018bd9bbfbd62bIliyan Malchev#include "malloc_debug_check_mapinfo.h"
35e1dd3c287ba836281de0197670018bd9bbfbd62bIliyan Malchev
36e1dd3c287ba836281de0197670018bd9bbfbd62bIliyan Malchev// 6f000000-6f01e000 rwxp 00000000 00:0c 16389419   /system/lib/libcomposer.so
37e1dd3c287ba836281de0197670018bd9bbfbd62bIliyan Malchev// 012345678901234567890123456789012345678901234567890123456789
38e1dd3c287ba836281de0197670018bd9bbfbd62bIliyan Malchev// 0         1         2         3         4         5
39e1dd3c287ba836281de0197670018bd9bbfbd62bIliyan Malchev
40c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughesstatic mapinfo* parse_maps_line(char* line) {
41e1dd3c287ba836281de0197670018bd9bbfbd62bIliyan Malchev    int len = strlen(line);
42e1dd3c287ba836281de0197670018bd9bbfbd62bIliyan Malchev
43c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughes    if (len < 1) return 0;
44e1dd3c287ba836281de0197670018bd9bbfbd62bIliyan Malchev    line[--len] = 0;
45e1dd3c287ba836281de0197670018bd9bbfbd62bIliyan Malchev
46c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughes    if (len < 50) return 0;
47c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughes    if (line[20] != 'x') return 0;
48e1dd3c287ba836281de0197670018bd9bbfbd62bIliyan Malchev
49c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughes    mapinfo* mi = static_cast<mapinfo*>(dlmalloc(sizeof(mapinfo) + (len - 47)));
50c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughes    if (mi == 0) return 0;
51e1dd3c287ba836281de0197670018bd9bbfbd62bIliyan Malchev
52e1dd3c287ba836281de0197670018bd9bbfbd62bIliyan Malchev    mi->start = strtoul(line, 0, 16);
53e1dd3c287ba836281de0197670018bd9bbfbd62bIliyan Malchev    mi->end = strtoul(line + 9, 0, 16);
54e1dd3c287ba836281de0197670018bd9bbfbd62bIliyan Malchev    /* To be filled in parse_elf_info if the mapped section starts with
55e1dd3c287ba836281de0197670018bd9bbfbd62bIliyan Malchev     * elf_header
56e1dd3c287ba836281de0197670018bd9bbfbd62bIliyan Malchev     */
57e1dd3c287ba836281de0197670018bd9bbfbd62bIliyan Malchev    mi->next = 0;
58e1dd3c287ba836281de0197670018bd9bbfbd62bIliyan Malchev    strcpy(mi->name, line + 49);
59e1dd3c287ba836281de0197670018bd9bbfbd62bIliyan Malchev
60e1dd3c287ba836281de0197670018bd9bbfbd62bIliyan Malchev    return mi;
61e1dd3c287ba836281de0197670018bd9bbfbd62bIliyan Malchev}
62e1dd3c287ba836281de0197670018bd9bbfbd62bIliyan Malchev
63e1dd3c287ba836281de0197670018bd9bbfbd62bIliyan Malchev__LIBC_HIDDEN__
64c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughesmapinfo *init_mapinfo(int pid) {
65e1dd3c287ba836281de0197670018bd9bbfbd62bIliyan Malchev    struct mapinfo *milist = NULL;
66c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughes    char data[1024]; // Used to read lines as well as to construct the filename.
67c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughes    snprintf(data, sizeof(data), "/proc/%d/maps", pid);
68e1dd3c287ba836281de0197670018bd9bbfbd62bIliyan Malchev    FILE *fp = fopen(data, "r");
69c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughes    if (fp) {
70c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughes        while (fgets(data, sizeof(data), fp)) {
71e1dd3c287ba836281de0197670018bd9bbfbd62bIliyan Malchev            mapinfo *mi = parse_maps_line(data);
72c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughes            if (mi) {
73e1dd3c287ba836281de0197670018bd9bbfbd62bIliyan Malchev                mi->next = milist;
74e1dd3c287ba836281de0197670018bd9bbfbd62bIliyan Malchev                milist = mi;
75e1dd3c287ba836281de0197670018bd9bbfbd62bIliyan Malchev            }
76e1dd3c287ba836281de0197670018bd9bbfbd62bIliyan Malchev        }
77e1dd3c287ba836281de0197670018bd9bbfbd62bIliyan Malchev        fclose(fp);
78e1dd3c287ba836281de0197670018bd9bbfbd62bIliyan Malchev    }
79e1dd3c287ba836281de0197670018bd9bbfbd62bIliyan Malchev
80e1dd3c287ba836281de0197670018bd9bbfbd62bIliyan Malchev    return milist;
81e1dd3c287ba836281de0197670018bd9bbfbd62bIliyan Malchev}
82e1dd3c287ba836281de0197670018bd9bbfbd62bIliyan Malchev
83e1dd3c287ba836281de0197670018bd9bbfbd62bIliyan Malchev__LIBC_HIDDEN__
84c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughesvoid deinit_mapinfo(mapinfo *mi) {
85c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughes    mapinfo *del;
86c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughes    while (mi) {
87c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughes        del = mi;
88c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughes        mi = mi->next;
89c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughes        dlfree(del);
90c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughes    }
91e1dd3c287ba836281de0197670018bd9bbfbd62bIliyan Malchev}
92e1dd3c287ba836281de0197670018bd9bbfbd62bIliyan Malchev
93e1dd3c287ba836281de0197670018bd9bbfbd62bIliyan Malchev/* Map a pc address to the name of the containing ELF file */
94e1dd3c287ba836281de0197670018bd9bbfbd62bIliyan Malchev__LIBC_HIDDEN__
95c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughesconst char *map_to_name(mapinfo *mi, unsigned pc, const char* def) {
96c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughes    while (mi) {
97c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughes        if ((pc >= mi->start) && (pc < mi->end)) {
98e1dd3c287ba836281de0197670018bd9bbfbd62bIliyan Malchev            return mi->name;
99e1dd3c287ba836281de0197670018bd9bbfbd62bIliyan Malchev        }
100e1dd3c287ba836281de0197670018bd9bbfbd62bIliyan Malchev        mi = mi->next;
101e1dd3c287ba836281de0197670018bd9bbfbd62bIliyan Malchev    }
102e1dd3c287ba836281de0197670018bd9bbfbd62bIliyan Malchev    return def;
103e1dd3c287ba836281de0197670018bd9bbfbd62bIliyan Malchev}
104e1dd3c287ba836281de0197670018bd9bbfbd62bIliyan Malchev
105e1dd3c287ba836281de0197670018bd9bbfbd62bIliyan Malchev/* Find the containing map info for the pc */
106e1dd3c287ba836281de0197670018bd9bbfbd62bIliyan Malchev__LIBC_HIDDEN__
107c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughesconst mapinfo *pc_to_mapinfo(mapinfo *mi, unsigned pc, unsigned *rel_pc) {
108e1dd3c287ba836281de0197670018bd9bbfbd62bIliyan Malchev    *rel_pc = pc;
109c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughes    while (mi) {
110c4d1fecc105063e68a5090a6900b63d1b9a24287Elliott Hughes        if ((pc >= mi->start) && (pc < mi->end)) {
111e1dd3c287ba836281de0197670018bd9bbfbd62bIliyan Malchev            // Only calculate the relative offset for shared libraries
112e1dd3c287ba836281de0197670018bd9bbfbd62bIliyan Malchev            if (strstr(mi->name, ".so")) {
113e1dd3c287ba836281de0197670018bd9bbfbd62bIliyan Malchev                *rel_pc -= mi->start;
114e1dd3c287ba836281de0197670018bd9bbfbd62bIliyan Malchev            }
115e1dd3c287ba836281de0197670018bd9bbfbd62bIliyan Malchev            return mi;
116e1dd3c287ba836281de0197670018bd9bbfbd62bIliyan Malchev        }
117e1dd3c287ba836281de0197670018bd9bbfbd62bIliyan Malchev        mi = mi->next;
118e1dd3c287ba836281de0197670018bd9bbfbd62bIliyan Malchev    }
119e1dd3c287ba836281de0197670018bd9bbfbd62bIliyan Malchev    return NULL;
120e1dd3c287ba836281de0197670018bd9bbfbd62bIliyan Malchev}
121