1 /*
2  * Copyright (C) 2014 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef _BACKTRACE_BACKTRACE_MAP_H
18 #define _BACKTRACE_BACKTRACE_MAP_H
19 
20 #include <stdint.h>
21 #include <sys/types.h>
22 #ifdef _WIN32
23 // MINGW does not define these constants.
24 #define PROT_NONE 0
25 #define PROT_READ 0x1
26 #define PROT_WRITE 0x2
27 #define PROT_EXEC 0x4
28 #else
29 #include <sys/mman.h>
30 #endif
31 
32 #include <deque>
33 #include <string>
34 #include <vector>
35 
36 // Special flag to indicate a map is in /dev/. However, a map in
37 // /dev/ashmem/... does not set this flag.
38 static constexpr int PROT_DEVICE_MAP = 0x8000;
39 
40 struct backtrace_map_t {
41   uintptr_t start = 0;
42   uintptr_t end = 0;
43   uintptr_t offset = 0;
44   uintptr_t load_base = 0;
45   int flags = 0;
46   std::string name;
47 };
48 
49 class BacktraceMap {
50 public:
51   // If uncached is true, then parse the current process map as of the call.
52   // Passing a map created with uncached set to true to Backtrace::Create()
53   // is unsupported.
54   static BacktraceMap* Create(pid_t pid, bool uncached = false);
55 
56   static BacktraceMap* Create(pid_t pid, const std::vector<backtrace_map_t>& maps);
57 
58   virtual ~BacktraceMap();
59 
60   // Fill in the map data structure for the given address.
61   virtual void FillIn(uintptr_t addr, backtrace_map_t* map);
62 
63   // The flags returned are the same flags as used by the mmap call.
64   // The values are PROT_*.
GetFlags(uintptr_t pc)65   int GetFlags(uintptr_t pc) {
66     backtrace_map_t map;
67     FillIn(pc, &map);
68     if (IsValid(map)) {
69       return map.flags;
70     }
71     return PROT_NONE;
72   }
73 
IsReadable(uintptr_t pc)74   bool IsReadable(uintptr_t pc) { return GetFlags(pc) & PROT_READ; }
IsWritable(uintptr_t pc)75   bool IsWritable(uintptr_t pc) { return GetFlags(pc) & PROT_WRITE; }
IsExecutable(uintptr_t pc)76   bool IsExecutable(uintptr_t pc) { return GetFlags(pc) & PROT_EXEC; }
77 
78   // In order to use the iterators on this object, a caller must
79   // call the LockIterator and UnlockIterator function to guarantee
80   // that the data does not change while it's being used.
LockIterator()81   virtual void LockIterator() {}
UnlockIterator()82   virtual void UnlockIterator() {}
83 
84   typedef std::deque<backtrace_map_t>::iterator iterator;
begin()85   iterator begin() { return maps_.begin(); }
end()86   iterator end() { return maps_.end(); }
87 
88   typedef std::deque<backtrace_map_t>::const_iterator const_iterator;
begin()89   const_iterator begin() const { return maps_.begin(); }
end()90   const_iterator end() const { return maps_.end(); }
91 
92   virtual bool Build();
93 
IsValid(const backtrace_map_t & map)94   static inline bool IsValid(const backtrace_map_t& map) {
95     return map.end > 0;
96   }
97 
GetRelativePc(const backtrace_map_t & map,uintptr_t pc)98   static uintptr_t GetRelativePc(const backtrace_map_t& map, uintptr_t pc) {
99     if (IsValid(map)) {
100       return pc - map.start + map.load_base;
101     } else {
102       return pc;
103     }
104   }
105 
106 protected:
107   BacktraceMap(pid_t pid);
108 
109   virtual bool ParseLine(const char* line, backtrace_map_t* map);
110 
111   std::deque<backtrace_map_t> maps_;
112   pid_t pid_;
113 };
114 
115 class ScopedBacktraceMapIteratorLock {
116 public:
ScopedBacktraceMapIteratorLock(BacktraceMap * map)117   explicit ScopedBacktraceMapIteratorLock(BacktraceMap* map) : map_(map) {
118     map->LockIterator();
119   }
120 
~ScopedBacktraceMapIteratorLock()121   ~ScopedBacktraceMapIteratorLock() {
122     map_->UnlockIterator();
123   }
124 
125 private:
126   BacktraceMap* map_;
127 };
128 
129 #endif // _BACKTRACE_BACKTRACE_MAP_H
130