Home | History | Annotate | Download | only in backtrace
      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 <iterator>
     34 #include <string>
     35 #include <vector>
     36 
     37 // Forward declaration.
     38 struct backtrace_stackinfo_t;
     39 
     40 // Special flag to indicate a map is in /dev/. However, a map in
     41 // /dev/ashmem/... does not set this flag.
     42 static constexpr int PROT_DEVICE_MAP = 0x8000;
     43 
     44 struct backtrace_map_t {
     45   uint64_t start = 0;
     46   uint64_t end = 0;
     47   uint64_t offset = 0;
     48   uint64_t load_bias = 0;
     49   int flags = 0;
     50   std::string name;
     51 
     52   // Returns `name` if non-empty, or `<anonymous:0x...>` otherwise.
     53   std::string Name() const;
     54 };
     55 
     56 namespace unwindstack {
     57 class Memory;
     58 }
     59 
     60 class BacktraceMap {
     61 public:
     62   // If uncached is true, then parse the current process map as of the call.
     63   // Passing a map created with uncached set to true to Backtrace::Create()
     64   // is unsupported.
     65   static BacktraceMap* Create(pid_t pid, bool uncached = false);
     66 
     67   static BacktraceMap* CreateOffline(pid_t pid, const std::vector<backtrace_map_t>& maps);
     68 
     69   virtual ~BacktraceMap();
     70 
     71   class iterator : public std::iterator<std::bidirectional_iterator_tag, backtrace_map_t*> {
     72    public:
     73     iterator(BacktraceMap* map, size_t index) : map_(map), index_(index) {}
     74 
     75     iterator& operator++() {
     76       index_++;
     77       return *this;
     78     }
     79     iterator& operator++(int increment) {
     80       index_ += increment;
     81       return *this;
     82     }
     83     iterator& operator--() {
     84       index_--;
     85       return *this;
     86     }
     87     iterator& operator--(int decrement) {
     88       index_ -= decrement;
     89       return *this;
     90     }
     91 
     92     bool operator==(const iterator& rhs) { return this->index_ == rhs.index_; }
     93     bool operator!=(const iterator& rhs) { return this->index_ != rhs.index_; }
     94 
     95     const backtrace_map_t* operator*() {
     96       if (index_ >= map_->size()) {
     97         return nullptr;
     98       }
     99       backtrace_map_t* map = &map_->maps_[index_];
    100       if (map->load_bias == static_cast<uint64_t>(-1)) {
    101         map->load_bias = map_->GetLoadBias(index_);
    102       }
    103       return map;
    104     }
    105 
    106    private:
    107     BacktraceMap* map_ = nullptr;
    108     size_t index_ = 0;
    109   };
    110 
    111   iterator begin() { return iterator(this, 0); }
    112   iterator end() { return iterator(this, maps_.size()); }
    113 
    114   // Fill in the map data structure for the given address.
    115   virtual void FillIn(uint64_t addr, backtrace_map_t* map);
    116 
    117   // Only supported with the new unwinder.
    118   virtual std::string GetFunctionName(uint64_t /*pc*/, uint64_t* /*offset*/) { return ""; }
    119   virtual std::shared_ptr<unwindstack::Memory> GetProcessMemory() { return nullptr; }
    120 
    121   // The flags returned are the same flags as used by the mmap call.
    122   // The values are PROT_*.
    123   int GetFlags(uint64_t pc) {
    124     backtrace_map_t map;
    125     FillIn(pc, &map);
    126     if (IsValid(map)) {
    127       return map.flags;
    128     }
    129     return PROT_NONE;
    130   }
    131 
    132   bool IsReadable(uint64_t pc) { return GetFlags(pc) & PROT_READ; }
    133   bool IsWritable(uint64_t pc) { return GetFlags(pc) & PROT_WRITE; }
    134   bool IsExecutable(uint64_t pc) { return GetFlags(pc) & PROT_EXEC; }
    135 
    136   // In order to use the iterators on this object, a caller must
    137   // call the LockIterator and UnlockIterator function to guarantee
    138   // that the data does not change while it's being used.
    139   virtual void LockIterator() {}
    140   virtual void UnlockIterator() {}
    141 
    142   size_t size() const { return maps_.size(); }
    143 
    144   virtual bool Build();
    145 
    146   static inline bool IsValid(const backtrace_map_t& map) {
    147     return map.end > 0;
    148   }
    149 
    150   void SetSuffixesToIgnore(std::vector<std::string> suffixes) {
    151     suffixes_to_ignore_.insert(suffixes_to_ignore_.end(), suffixes.begin(), suffixes.end());
    152   }
    153 
    154   const std::vector<std::string>& GetSuffixesToIgnore() { return suffixes_to_ignore_; }
    155 
    156   // Disabling the resolving of names results in the function name being
    157   // set to an empty string and the function offset being set to zero
    158   // in the frame data when unwinding.
    159   void SetResolveNames(bool resolve) { resolve_names_ = resolve; }
    160 
    161   bool ResolveNames() { return resolve_names_; }
    162 
    163  protected:
    164   BacktraceMap(pid_t pid);
    165 
    166   virtual uint64_t GetLoadBias(size_t /* index */) { return 0; }
    167 
    168   virtual bool ParseLine(const char* line, backtrace_map_t* map);
    169 
    170   pid_t pid_;
    171   std::deque<backtrace_map_t> maps_;
    172   std::vector<std::string> suffixes_to_ignore_;
    173   bool resolve_names_ = true;
    174 };
    175 
    176 class ScopedBacktraceMapIteratorLock {
    177 public:
    178   explicit ScopedBacktraceMapIteratorLock(BacktraceMap* map) : map_(map) {
    179     map->LockIterator();
    180   }
    181 
    182   ~ScopedBacktraceMapIteratorLock() {
    183     map_->UnlockIterator();
    184   }
    185 
    186 private:
    187   BacktraceMap* map_;
    188 };
    189 
    190 #endif // _BACKTRACE_BACKTRACE_MAP_H
    191