xref: /aosp_15_r20/external/mesa3d/include/android_stub/backtrace/BacktraceMap.h (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1*61046927SAndroid Build Coastguard Worker /*
2*61046927SAndroid Build Coastguard Worker  * Copyright (C) 2014 The Android Open Source Project
3*61046927SAndroid Build Coastguard Worker  *
4*61046927SAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*61046927SAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*61046927SAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*61046927SAndroid Build Coastguard Worker  *
8*61046927SAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*61046927SAndroid Build Coastguard Worker  *
10*61046927SAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*61046927SAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*61046927SAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*61046927SAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*61046927SAndroid Build Coastguard Worker  * limitations under the License.
15*61046927SAndroid Build Coastguard Worker  */
16*61046927SAndroid Build Coastguard Worker 
17*61046927SAndroid Build Coastguard Worker #ifndef _BACKTRACE_BACKTRACE_MAP_H
18*61046927SAndroid Build Coastguard Worker #define _BACKTRACE_BACKTRACE_MAP_H
19*61046927SAndroid Build Coastguard Worker 
20*61046927SAndroid Build Coastguard Worker #include <stdint.h>
21*61046927SAndroid Build Coastguard Worker #include <sys/types.h>
22*61046927SAndroid Build Coastguard Worker #ifdef _WIN32
23*61046927SAndroid Build Coastguard Worker // MINGW does not define these constants.
24*61046927SAndroid Build Coastguard Worker #define PROT_NONE 0
25*61046927SAndroid Build Coastguard Worker #define PROT_READ 0x1
26*61046927SAndroid Build Coastguard Worker #define PROT_WRITE 0x2
27*61046927SAndroid Build Coastguard Worker #define PROT_EXEC 0x4
28*61046927SAndroid Build Coastguard Worker #else
29*61046927SAndroid Build Coastguard Worker #include <sys/mman.h>
30*61046927SAndroid Build Coastguard Worker #endif
31*61046927SAndroid Build Coastguard Worker 
32*61046927SAndroid Build Coastguard Worker #include <deque>
33*61046927SAndroid Build Coastguard Worker #include <iterator>
34*61046927SAndroid Build Coastguard Worker #include <memory>
35*61046927SAndroid Build Coastguard Worker #include <string>
36*61046927SAndroid Build Coastguard Worker #include <vector>
37*61046927SAndroid Build Coastguard Worker 
38*61046927SAndroid Build Coastguard Worker // Forward declaration.
39*61046927SAndroid Build Coastguard Worker struct backtrace_stackinfo_t;
40*61046927SAndroid Build Coastguard Worker 
41*61046927SAndroid Build Coastguard Worker // Special flag to indicate a map is in /dev/. However, a map in
42*61046927SAndroid Build Coastguard Worker // /dev/ashmem/... does not set this flag.
43*61046927SAndroid Build Coastguard Worker static constexpr int PROT_DEVICE_MAP = 0x8000;
44*61046927SAndroid Build Coastguard Worker // Special flag to indicate that this map represents an elf file
45*61046927SAndroid Build Coastguard Worker // created by ART for use with the gdb jit debug interface.
46*61046927SAndroid Build Coastguard Worker // This should only ever appear in offline maps data.
47*61046927SAndroid Build Coastguard Worker static constexpr int PROT_JIT_SYMFILE_MAP = 0x4000;
48*61046927SAndroid Build Coastguard Worker 
49*61046927SAndroid Build Coastguard Worker struct backtrace_map_t {
50*61046927SAndroid Build Coastguard Worker   uint64_t start = 0;
51*61046927SAndroid Build Coastguard Worker   uint64_t end = 0;
52*61046927SAndroid Build Coastguard Worker   uint64_t offset = 0;
53*61046927SAndroid Build Coastguard Worker   uint64_t load_bias = 0;
54*61046927SAndroid Build Coastguard Worker   int flags = 0;
55*61046927SAndroid Build Coastguard Worker   std::string name;
56*61046927SAndroid Build Coastguard Worker 
57*61046927SAndroid Build Coastguard Worker   // Returns `name` if non-empty, or `<anonymous:0x...>` otherwise.
58*61046927SAndroid Build Coastguard Worker   std::string Name() const;
59*61046927SAndroid Build Coastguard Worker };
60*61046927SAndroid Build Coastguard Worker 
61*61046927SAndroid Build Coastguard Worker namespace unwindstack {
62*61046927SAndroid Build Coastguard Worker class Memory;
63*61046927SAndroid Build Coastguard Worker }
64*61046927SAndroid Build Coastguard Worker 
65*61046927SAndroid Build Coastguard Worker class BacktraceMap {
66*61046927SAndroid Build Coastguard Worker public:
67*61046927SAndroid Build Coastguard Worker   // If uncached is true, then parse the current process map as of the call.
68*61046927SAndroid Build Coastguard Worker   // Passing a map created with uncached set to true to Backtrace::Create()
69*61046927SAndroid Build Coastguard Worker   // is unsupported.
70*61046927SAndroid Build Coastguard Worker   static BacktraceMap* Create(pid_t pid, bool uncached = false);
71*61046927SAndroid Build Coastguard Worker 
72*61046927SAndroid Build Coastguard Worker   virtual ~BacktraceMap();
73*61046927SAndroid Build Coastguard Worker 
74*61046927SAndroid Build Coastguard Worker   class iterator : public std::iterator<std::bidirectional_iterator_tag, backtrace_map_t*> {
75*61046927SAndroid Build Coastguard Worker    public:
iterator(BacktraceMap * map,size_t index)76*61046927SAndroid Build Coastguard Worker     iterator(BacktraceMap* map, size_t index) : map_(map), index_(index) {}
77*61046927SAndroid Build Coastguard Worker 
78*61046927SAndroid Build Coastguard Worker     iterator& operator++() {
79*61046927SAndroid Build Coastguard Worker       index_++;
80*61046927SAndroid Build Coastguard Worker       return *this;
81*61046927SAndroid Build Coastguard Worker     }
82*61046927SAndroid Build Coastguard Worker     const iterator operator++(int increment) {
83*61046927SAndroid Build Coastguard Worker       index_ += increment;
84*61046927SAndroid Build Coastguard Worker       return *this;
85*61046927SAndroid Build Coastguard Worker     }
86*61046927SAndroid Build Coastguard Worker     iterator& operator--() {
87*61046927SAndroid Build Coastguard Worker       index_--;
88*61046927SAndroid Build Coastguard Worker       return *this;
89*61046927SAndroid Build Coastguard Worker     }
90*61046927SAndroid Build Coastguard Worker     const iterator operator--(int decrement) {
91*61046927SAndroid Build Coastguard Worker       index_ -= decrement;
92*61046927SAndroid Build Coastguard Worker       return *this;
93*61046927SAndroid Build Coastguard Worker     }
94*61046927SAndroid Build Coastguard Worker 
95*61046927SAndroid Build Coastguard Worker     bool operator==(const iterator& rhs) { return this->index_ == rhs.index_; }
96*61046927SAndroid Build Coastguard Worker     bool operator!=(const iterator& rhs) { return this->index_ != rhs.index_; }
97*61046927SAndroid Build Coastguard Worker 
98*61046927SAndroid Build Coastguard Worker     const backtrace_map_t* operator*() {
99*61046927SAndroid Build Coastguard Worker       if (index_ >= map_->size()) {
100*61046927SAndroid Build Coastguard Worker         return nullptr;
101*61046927SAndroid Build Coastguard Worker       }
102*61046927SAndroid Build Coastguard Worker       backtrace_map_t* map = &map_->maps_[index_];
103*61046927SAndroid Build Coastguard Worker       if (map->load_bias == static_cast<uint64_t>(-1)) {
104*61046927SAndroid Build Coastguard Worker         map->load_bias = map_->GetLoadBias(index_);
105*61046927SAndroid Build Coastguard Worker       }
106*61046927SAndroid Build Coastguard Worker       return map;
107*61046927SAndroid Build Coastguard Worker     }
108*61046927SAndroid Build Coastguard Worker 
109*61046927SAndroid Build Coastguard Worker    private:
110*61046927SAndroid Build Coastguard Worker     BacktraceMap* map_ = nullptr;
111*61046927SAndroid Build Coastguard Worker     size_t index_ = 0;
112*61046927SAndroid Build Coastguard Worker   };
113*61046927SAndroid Build Coastguard Worker 
begin()114*61046927SAndroid Build Coastguard Worker   iterator begin() { return iterator(this, 0); }
end()115*61046927SAndroid Build Coastguard Worker   iterator end() { return iterator(this, maps_.size()); }
116*61046927SAndroid Build Coastguard Worker 
117*61046927SAndroid Build Coastguard Worker   // Fill in the map data structure for the given address.
118*61046927SAndroid Build Coastguard Worker   virtual void FillIn(uint64_t addr, backtrace_map_t* map);
119*61046927SAndroid Build Coastguard Worker 
120*61046927SAndroid Build Coastguard Worker   // Only supported with the new unwinder.
GetFunctionName(uint64_t,uint64_t *)121*61046927SAndroid Build Coastguard Worker   virtual std::string GetFunctionName(uint64_t /*pc*/, uint64_t* /*offset*/) { return ""; }
GetProcessMemory()122*61046927SAndroid Build Coastguard Worker   virtual std::shared_ptr<unwindstack::Memory> GetProcessMemory() { return nullptr; }
123*61046927SAndroid Build Coastguard Worker 
124*61046927SAndroid Build Coastguard Worker   // The flags returned are the same flags as used by the mmap call.
125*61046927SAndroid Build Coastguard Worker   // The values are PROT_*.
GetFlags(uint64_t pc)126*61046927SAndroid Build Coastguard Worker   int GetFlags(uint64_t pc) {
127*61046927SAndroid Build Coastguard Worker     backtrace_map_t map;
128*61046927SAndroid Build Coastguard Worker     FillIn(pc, &map);
129*61046927SAndroid Build Coastguard Worker     if (IsValid(map)) {
130*61046927SAndroid Build Coastguard Worker       return map.flags;
131*61046927SAndroid Build Coastguard Worker     }
132*61046927SAndroid Build Coastguard Worker     return PROT_NONE;
133*61046927SAndroid Build Coastguard Worker   }
134*61046927SAndroid Build Coastguard Worker 
IsReadable(uint64_t pc)135*61046927SAndroid Build Coastguard Worker   bool IsReadable(uint64_t pc) { return GetFlags(pc) & PROT_READ; }
IsWritable(uint64_t pc)136*61046927SAndroid Build Coastguard Worker   bool IsWritable(uint64_t pc) { return GetFlags(pc) & PROT_WRITE; }
IsExecutable(uint64_t pc)137*61046927SAndroid Build Coastguard Worker   bool IsExecutable(uint64_t pc) { return GetFlags(pc) & PROT_EXEC; }
138*61046927SAndroid Build Coastguard Worker 
139*61046927SAndroid Build Coastguard Worker   // In order to use the iterators on this object, a caller must
140*61046927SAndroid Build Coastguard Worker   // call the LockIterator and UnlockIterator function to guarantee
141*61046927SAndroid Build Coastguard Worker   // that the data does not change while it's being used.
LockIterator()142*61046927SAndroid Build Coastguard Worker   virtual void LockIterator() {}
UnlockIterator()143*61046927SAndroid Build Coastguard Worker   virtual void UnlockIterator() {}
144*61046927SAndroid Build Coastguard Worker 
size()145*61046927SAndroid Build Coastguard Worker   size_t size() const { return maps_.size(); }
146*61046927SAndroid Build Coastguard Worker 
147*61046927SAndroid Build Coastguard Worker   virtual bool Build();
148*61046927SAndroid Build Coastguard Worker 
IsValid(const backtrace_map_t & map)149*61046927SAndroid Build Coastguard Worker   static inline bool IsValid(const backtrace_map_t& map) {
150*61046927SAndroid Build Coastguard Worker     return map.end > 0;
151*61046927SAndroid Build Coastguard Worker   }
152*61046927SAndroid Build Coastguard Worker 
SetSuffixesToIgnore(std::vector<std::string> suffixes)153*61046927SAndroid Build Coastguard Worker   void SetSuffixesToIgnore(std::vector<std::string> suffixes) {
154*61046927SAndroid Build Coastguard Worker     suffixes_to_ignore_.insert(suffixes_to_ignore_.end(), suffixes.begin(), suffixes.end());
155*61046927SAndroid Build Coastguard Worker   }
156*61046927SAndroid Build Coastguard Worker 
GetSuffixesToIgnore()157*61046927SAndroid Build Coastguard Worker   const std::vector<std::string>& GetSuffixesToIgnore() { return suffixes_to_ignore_; }
158*61046927SAndroid Build Coastguard Worker 
159*61046927SAndroid Build Coastguard Worker   // Disabling the resolving of names results in the function name being
160*61046927SAndroid Build Coastguard Worker   // set to an empty string and the function offset being set to zero
161*61046927SAndroid Build Coastguard Worker   // in the frame data when unwinding.
SetResolveNames(bool resolve)162*61046927SAndroid Build Coastguard Worker   void SetResolveNames(bool resolve) { resolve_names_ = resolve; }
163*61046927SAndroid Build Coastguard Worker 
ResolveNames()164*61046927SAndroid Build Coastguard Worker   bool ResolveNames() { return resolve_names_; }
165*61046927SAndroid Build Coastguard Worker 
166*61046927SAndroid Build Coastguard Worker  protected:
167*61046927SAndroid Build Coastguard Worker   BacktraceMap(pid_t pid);
168*61046927SAndroid Build Coastguard Worker 
GetLoadBias(size_t)169*61046927SAndroid Build Coastguard Worker   virtual uint64_t GetLoadBias(size_t /* index */) { return 0; }
170*61046927SAndroid Build Coastguard Worker 
171*61046927SAndroid Build Coastguard Worker   pid_t pid_;
172*61046927SAndroid Build Coastguard Worker   std::deque<backtrace_map_t> maps_;
173*61046927SAndroid Build Coastguard Worker   std::vector<std::string> suffixes_to_ignore_;
174*61046927SAndroid Build Coastguard Worker   bool resolve_names_ = true;
175*61046927SAndroid Build Coastguard Worker };
176*61046927SAndroid Build Coastguard Worker 
177*61046927SAndroid Build Coastguard Worker class ScopedBacktraceMapIteratorLock {
178*61046927SAndroid Build Coastguard Worker public:
ScopedBacktraceMapIteratorLock(BacktraceMap * map)179*61046927SAndroid Build Coastguard Worker   explicit ScopedBacktraceMapIteratorLock(BacktraceMap* map) : map_(map) {
180*61046927SAndroid Build Coastguard Worker     map->LockIterator();
181*61046927SAndroid Build Coastguard Worker   }
182*61046927SAndroid Build Coastguard Worker 
~ScopedBacktraceMapIteratorLock()183*61046927SAndroid Build Coastguard Worker   ~ScopedBacktraceMapIteratorLock() {
184*61046927SAndroid Build Coastguard Worker     map_->UnlockIterator();
185*61046927SAndroid Build Coastguard Worker   }
186*61046927SAndroid Build Coastguard Worker 
187*61046927SAndroid Build Coastguard Worker private:
188*61046927SAndroid Build Coastguard Worker   BacktraceMap* map_;
189*61046927SAndroid Build Coastguard Worker };
190*61046927SAndroid Build Coastguard Worker 
191*61046927SAndroid Build Coastguard Worker #endif // _BACKTRACE_BACKTRACE_MAP_H
192