17ec681f3Smrg/*
27ec681f3Smrg * Copyright (C) 2014 The Android Open Source Project
37ec681f3Smrg *
47ec681f3Smrg * Licensed under the Apache License, Version 2.0 (the "License");
57ec681f3Smrg * you may not use this file except in compliance with the License.
67ec681f3Smrg * You may obtain a copy of the License at
77ec681f3Smrg *
87ec681f3Smrg *      http://www.apache.org/licenses/LICENSE-2.0
97ec681f3Smrg *
107ec681f3Smrg * Unless required by applicable law or agreed to in writing, software
117ec681f3Smrg * distributed under the License is distributed on an "AS IS" BASIS,
127ec681f3Smrg * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
137ec681f3Smrg * See the License for the specific language governing permissions and
147ec681f3Smrg * limitations under the License.
157ec681f3Smrg */
167ec681f3Smrg
177ec681f3Smrg#ifndef _BACKTRACE_BACKTRACE_MAP_H
187ec681f3Smrg#define _BACKTRACE_BACKTRACE_MAP_H
197ec681f3Smrg
207ec681f3Smrg#include <stdint.h>
217ec681f3Smrg#include <sys/types.h>
227ec681f3Smrg#ifdef _WIN32
237ec681f3Smrg// MINGW does not define these constants.
247ec681f3Smrg#define PROT_NONE 0
257ec681f3Smrg#define PROT_READ 0x1
267ec681f3Smrg#define PROT_WRITE 0x2
277ec681f3Smrg#define PROT_EXEC 0x4
287ec681f3Smrg#else
297ec681f3Smrg#include <sys/mman.h>
307ec681f3Smrg#endif
317ec681f3Smrg
327ec681f3Smrg#include <deque>
337ec681f3Smrg#include <iterator>
347ec681f3Smrg#include <memory>
357ec681f3Smrg#include <string>
367ec681f3Smrg#include <vector>
377ec681f3Smrg
387ec681f3Smrg// Forward declaration.
397ec681f3Smrgstruct backtrace_stackinfo_t;
407ec681f3Smrg
417ec681f3Smrg// Special flag to indicate a map is in /dev/. However, a map in
427ec681f3Smrg// /dev/ashmem/... does not set this flag.
437ec681f3Smrgstatic constexpr int PROT_DEVICE_MAP = 0x8000;
447ec681f3Smrg// Special flag to indicate that this map represents an elf file
457ec681f3Smrg// created by ART for use with the gdb jit debug interface.
467ec681f3Smrg// This should only ever appear in offline maps data.
477ec681f3Smrgstatic constexpr int PROT_JIT_SYMFILE_MAP = 0x4000;
487ec681f3Smrg
497ec681f3Smrgstruct backtrace_map_t {
507ec681f3Smrg  uint64_t start = 0;
517ec681f3Smrg  uint64_t end = 0;
527ec681f3Smrg  uint64_t offset = 0;
537ec681f3Smrg  uint64_t load_bias = 0;
547ec681f3Smrg  int flags = 0;
557ec681f3Smrg  std::string name;
567ec681f3Smrg
577ec681f3Smrg  // Returns `name` if non-empty, or `<anonymous:0x...>` otherwise.
587ec681f3Smrg  std::string Name() const;
597ec681f3Smrg};
607ec681f3Smrg
617ec681f3Smrgnamespace unwindstack {
627ec681f3Smrgclass Memory;
637ec681f3Smrg}
647ec681f3Smrg
657ec681f3Smrgclass BacktraceMap {
667ec681f3Smrgpublic:
677ec681f3Smrg  // If uncached is true, then parse the current process map as of the call.
687ec681f3Smrg  // Passing a map created with uncached set to true to Backtrace::Create()
697ec681f3Smrg  // is unsupported.
707ec681f3Smrg  static BacktraceMap* Create(pid_t pid, bool uncached = false);
717ec681f3Smrg
727ec681f3Smrg  virtual ~BacktraceMap();
737ec681f3Smrg
747ec681f3Smrg  class iterator : public std::iterator<std::bidirectional_iterator_tag, backtrace_map_t*> {
757ec681f3Smrg   public:
767ec681f3Smrg    iterator(BacktraceMap* map, size_t index) : map_(map), index_(index) {}
777ec681f3Smrg
787ec681f3Smrg    iterator& operator++() {
797ec681f3Smrg      index_++;
807ec681f3Smrg      return *this;
817ec681f3Smrg    }
827ec681f3Smrg    const iterator operator++(int increment) {
837ec681f3Smrg      index_ += increment;
847ec681f3Smrg      return *this;
857ec681f3Smrg    }
867ec681f3Smrg    iterator& operator--() {
877ec681f3Smrg      index_--;
887ec681f3Smrg      return *this;
897ec681f3Smrg    }
907ec681f3Smrg    const iterator operator--(int decrement) {
917ec681f3Smrg      index_ -= decrement;
927ec681f3Smrg      return *this;
937ec681f3Smrg    }
947ec681f3Smrg
957ec681f3Smrg    bool operator==(const iterator& rhs) { return this->index_ == rhs.index_; }
967ec681f3Smrg    bool operator!=(const iterator& rhs) { return this->index_ != rhs.index_; }
977ec681f3Smrg
987ec681f3Smrg    const backtrace_map_t* operator*() {
997ec681f3Smrg      if (index_ >= map_->size()) {
1007ec681f3Smrg        return nullptr;
1017ec681f3Smrg      }
1027ec681f3Smrg      backtrace_map_t* map = &map_->maps_[index_];
1037ec681f3Smrg      if (map->load_bias == static_cast<uint64_t>(-1)) {
1047ec681f3Smrg        map->load_bias = map_->GetLoadBias(index_);
1057ec681f3Smrg      }
1067ec681f3Smrg      return map;
1077ec681f3Smrg    }
1087ec681f3Smrg
1097ec681f3Smrg   private:
1107ec681f3Smrg    BacktraceMap* map_ = nullptr;
1117ec681f3Smrg    size_t index_ = 0;
1127ec681f3Smrg  };
1137ec681f3Smrg
1147ec681f3Smrg  iterator begin() { return iterator(this, 0); }
1157ec681f3Smrg  iterator end() { return iterator(this, maps_.size()); }
1167ec681f3Smrg
1177ec681f3Smrg  // Fill in the map data structure for the given address.
1187ec681f3Smrg  virtual void FillIn(uint64_t addr, backtrace_map_t* map);
1197ec681f3Smrg
1207ec681f3Smrg  // Only supported with the new unwinder.
1217ec681f3Smrg  virtual std::string GetFunctionName(uint64_t /*pc*/, uint64_t* /*offset*/) { return ""; }
1227ec681f3Smrg  virtual std::shared_ptr<unwindstack::Memory> GetProcessMemory() { return nullptr; }
1237ec681f3Smrg
1247ec681f3Smrg  // The flags returned are the same flags as used by the mmap call.
1257ec681f3Smrg  // The values are PROT_*.
1267ec681f3Smrg  int GetFlags(uint64_t pc) {
1277ec681f3Smrg    backtrace_map_t map;
1287ec681f3Smrg    FillIn(pc, &map);
1297ec681f3Smrg    if (IsValid(map)) {
1307ec681f3Smrg      return map.flags;
1317ec681f3Smrg    }
1327ec681f3Smrg    return PROT_NONE;
1337ec681f3Smrg  }
1347ec681f3Smrg
1357ec681f3Smrg  bool IsReadable(uint64_t pc) { return GetFlags(pc) & PROT_READ; }
1367ec681f3Smrg  bool IsWritable(uint64_t pc) { return GetFlags(pc) & PROT_WRITE; }
1377ec681f3Smrg  bool IsExecutable(uint64_t pc) { return GetFlags(pc) & PROT_EXEC; }
1387ec681f3Smrg
1397ec681f3Smrg  // In order to use the iterators on this object, a caller must
1407ec681f3Smrg  // call the LockIterator and UnlockIterator function to guarantee
1417ec681f3Smrg  // that the data does not change while it's being used.
1427ec681f3Smrg  virtual void LockIterator() {}
1437ec681f3Smrg  virtual void UnlockIterator() {}
1447ec681f3Smrg
1457ec681f3Smrg  size_t size() const { return maps_.size(); }
1467ec681f3Smrg
1477ec681f3Smrg  virtual bool Build();
1487ec681f3Smrg
1497ec681f3Smrg  static inline bool IsValid(const backtrace_map_t& map) {
1507ec681f3Smrg    return map.end > 0;
1517ec681f3Smrg  }
1527ec681f3Smrg
1537ec681f3Smrg  void SetSuffixesToIgnore(std::vector<std::string> suffixes) {
1547ec681f3Smrg    suffixes_to_ignore_.insert(suffixes_to_ignore_.end(), suffixes.begin(), suffixes.end());
1557ec681f3Smrg  }
1567ec681f3Smrg
1577ec681f3Smrg  const std::vector<std::string>& GetSuffixesToIgnore() { return suffixes_to_ignore_; }
1587ec681f3Smrg
1597ec681f3Smrg  // Disabling the resolving of names results in the function name being
1607ec681f3Smrg  // set to an empty string and the function offset being set to zero
1617ec681f3Smrg  // in the frame data when unwinding.
1627ec681f3Smrg  void SetResolveNames(bool resolve) { resolve_names_ = resolve; }
1637ec681f3Smrg
1647ec681f3Smrg  bool ResolveNames() { return resolve_names_; }
1657ec681f3Smrg
1667ec681f3Smrg protected:
1677ec681f3Smrg  BacktraceMap(pid_t pid);
1687ec681f3Smrg
1697ec681f3Smrg  virtual uint64_t GetLoadBias(size_t /* index */) { return 0; }
1707ec681f3Smrg
1717ec681f3Smrg  pid_t pid_;
1727ec681f3Smrg  std::deque<backtrace_map_t> maps_;
1737ec681f3Smrg  std::vector<std::string> suffixes_to_ignore_;
1747ec681f3Smrg  bool resolve_names_ = true;
1757ec681f3Smrg};
1767ec681f3Smrg
1777ec681f3Smrgclass ScopedBacktraceMapIteratorLock {
1787ec681f3Smrgpublic:
1797ec681f3Smrg  explicit ScopedBacktraceMapIteratorLock(BacktraceMap* map) : map_(map) {
1807ec681f3Smrg    map->LockIterator();
1817ec681f3Smrg  }
1827ec681f3Smrg
1837ec681f3Smrg  ~ScopedBacktraceMapIteratorLock() {
1847ec681f3Smrg    map_->UnlockIterator();
1857ec681f3Smrg  }
1867ec681f3Smrg
1877ec681f3Smrgprivate:
1887ec681f3Smrg  BacktraceMap* map_;
1897ec681f3Smrg};
1907ec681f3Smrg
1917ec681f3Smrg#endif // _BACKTRACE_BACKTRACE_MAP_H
192