1#include <stdio.h>
2#include <string.h>
3#include <stdlib.h>
4
5#include "mapinfo.h"
6
7extern void *__real_malloc(size_t size);
8extern void __real_free(void *ptr);
9
10#if 0
11    while (p <= end) {
12         data = ptrace(PTRACE_PEEKTEXT, pid, (void*)p, NULL);
13         _LOG(tfd, (sp_depth > 2) || only_in_tombstone,
14              "    %08x  %08x  %s\n", p, data,
15              map_to_name(map, data, ""));
16         p += 4;
17    }
18#endif
19
20// 6f000000-6f01e000 rwxp 00000000 00:0c 16389419   /system/lib/libcomposer.so
21// 012345678901234567890123456789012345678901234567890123456789
22// 0         1         2         3         4         5
23
24static mapinfo *parse_maps_line(char *line)
25{
26    mapinfo *mi;
27    int len = strlen(line);
28
29    if(len < 1) return 0;
30    line[--len] = 0;
31
32    if(len < 50) return 0;
33    if(line[20] != 'x') return 0;
34
35    mi = __real_malloc(sizeof(mapinfo) + (len - 47));
36    if(mi == 0) return 0;
37
38    mi->start = strtoul(line, 0, 16);
39    mi->end = strtoul(line + 9, 0, 16);
40    /* To be filled in parse_elf_info if the mapped section starts with
41     * elf_header
42     */
43    mi->next = 0;
44    strcpy(mi->name, line + 49);
45
46    return mi;
47}
48
49mapinfo *init_mapinfo(int pid)
50{
51    struct mapinfo *milist = NULL;
52    char data[1024];
53    sprintf(data, "/proc/%d/maps", pid);
54    FILE *fp = fopen(data, "r");
55    if(fp) {
56        while(fgets(data, sizeof(data), fp)) {
57            mapinfo *mi = parse_maps_line(data);
58            if(mi) {
59                mi->next = milist;
60                milist = mi;
61            }
62        }
63        fclose(fp);
64    }
65
66    return milist;
67}
68
69void deinit_mapinfo(mapinfo *mi)
70{
71   mapinfo *del;
72   while(mi) {
73       del = mi;
74       mi = mi->next;
75       __real_free(del);
76   }
77}
78
79/* Map a pc address to the name of the containing ELF file */
80const char *map_to_name(mapinfo *mi, unsigned pc, const char* def)
81{
82    while(mi) {
83        if((pc >= mi->start) && (pc < mi->end)){
84            return mi->name;
85        }
86        mi = mi->next;
87    }
88    return def;
89}
90
91/* Find the containing map info for the pc */
92const mapinfo *pc_to_mapinfo(mapinfo *mi, unsigned pc, unsigned *rel_pc)
93{
94    *rel_pc = pc;
95    while(mi) {
96        if((pc >= mi->start) && (pc < mi->end)){
97            // Only calculate the relative offset for shared libraries
98            if (strstr(mi->name, ".so")) {
99                *rel_pc -= mi->start;
100            }
101            return mi;
102        }
103        mi = mi->next;
104    }
105    return NULL;
106}
107