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