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 <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_*.
     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 
     74   bool IsReadable(uintptr_t pc) { return GetFlags(pc) & PROT_READ; }
     75   bool IsWritable(uintptr_t pc) { return GetFlags(pc) & PROT_WRITE; }
     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.
     81   virtual void LockIterator() {}
     82   virtual void UnlockIterator() {}
     83 
     84   typedef std::deque<backtrace_map_t>::iterator iterator;
     85   iterator begin() { return maps_.begin(); }
     86   iterator end() { return maps_.end(); }
     87 
     88   typedef std::deque<backtrace_map_t>::const_iterator const_iterator;
     89   const_iterator begin() const { return maps_.begin(); }
     90   const_iterator end() const { return maps_.end(); }
     91 
     92   virtual bool Build();
     93 
     94   static inline bool IsValid(const backtrace_map_t& map) {
     95     return map.end > 0;
     96   }
     97 
     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:
    117   explicit ScopedBacktraceMapIteratorLock(BacktraceMap* map) : map_(map) {
    118     map->LockIterator();
    119   }
    120 
    121   ~ScopedBacktraceMapIteratorLock() {
    122     map_->UnlockIterator();
    123   }
    124 
    125 private:
    126   BacktraceMap* map_;
    127 };
    128 
    129 #endif // _BACKTRACE_BACKTRACE_MAP_H
    130