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