146756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris/* 246756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris * Copyright (C) 2014 The Android Open Source Project 346756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris * 446756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris * Licensed under the Apache License, Version 2.0 (the "License"); 546756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris * you may not use this file except in compliance with the License. 646756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris * You may obtain a copy of the License at 746756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris * 846756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris * http://www.apache.org/licenses/LICENSE-2.0 946756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris * 1046756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris * Unless required by applicable law or agreed to in writing, software 1146756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris * distributed under the License is distributed on an "AS IS" BASIS, 1246756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1346756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris * See the License for the specific language governing permissions and 1446756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris * limitations under the License. 1546756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris */ 1646756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris 1746756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris#ifndef _BACKTRACE_BACKTRACE_MAP_H 1846756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris#define _BACKTRACE_BACKTRACE_MAP_H 1946756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris 2046756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris#include <stdint.h> 21ac2fe7eb81789274ab98573d0c4b0866bed1f254Dan Albert#include <sys/types.h> 2234a4f0b8c75e2c5a347e04454423cf55c5406075Elliott Hughes#ifdef _WIN32 230dbce4564bd697bc2603f6c05ac47b81977cd41fChristopher Ferris// MINGW does not define these constants. 240dbce4564bd697bc2603f6c05ac47b81977cd41fChristopher Ferris#define PROT_NONE 0 250dbce4564bd697bc2603f6c05ac47b81977cd41fChristopher Ferris#define PROT_READ 0x1 260dbce4564bd697bc2603f6c05ac47b81977cd41fChristopher Ferris#define PROT_WRITE 0x2 270dbce4564bd697bc2603f6c05ac47b81977cd41fChristopher Ferris#define PROT_EXEC 0x4 280dbce4564bd697bc2603f6c05ac47b81977cd41fChristopher Ferris#else 2946756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris#include <sys/mman.h> 300dbce4564bd697bc2603f6c05ac47b81977cd41fChristopher Ferris#endif 3146756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris 32df2906186b6952c57b1f662bfef0b65c9f8c2e0dChristopher Ferris#include <deque> 3346756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris#include <string> 349e402bb20cb868577e5588d8323363411655291bYabin Cui#include <vector> 3546756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris 36f5e568e653d0dd6bccc86d1a60db5a2573f75f0eChristopher Ferris// Special flag to indicate a map is in /dev/. However, a map in 37f5e568e653d0dd6bccc86d1a60db5a2573f75f0eChristopher Ferris// /dev/ashmem/... does not set this flag. 38f5e568e653d0dd6bccc86d1a60db5a2573f75f0eChristopher Ferrisstatic constexpr int PROT_DEVICE_MAP = 0x8000; 39f5e568e653d0dd6bccc86d1a60db5a2573f75f0eChristopher Ferris 4046756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferrisstruct backtrace_map_t { 41862fe029190b6d8344889988fb85526e64b2f4b7Christopher Ferris uintptr_t start = 0; 42862fe029190b6d8344889988fb85526e64b2f4b7Christopher Ferris uintptr_t end = 0; 43862fe029190b6d8344889988fb85526e64b2f4b7Christopher Ferris uintptr_t offset = 0; 4496722b0fa48524e03659c0a3d579f8ef4f1641baChristopher Ferris uintptr_t load_bias = 0; 45862fe029190b6d8344889988fb85526e64b2f4b7Christopher Ferris int flags = 0; 4646756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris std::string name; 4746756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris}; 4846756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris 4946756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferrisclass BacktraceMap { 5046756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferrispublic: 51dda47b786835ef3689f06e24650eb65176e2dc5eChristopher Ferris // If uncached is true, then parse the current process map as of the call. 52dda47b786835ef3689f06e24650eb65176e2dc5eChristopher Ferris // Passing a map created with uncached set to true to Backtrace::Create() 53dda47b786835ef3689f06e24650eb65176e2dc5eChristopher Ferris // is unsupported. 54dda47b786835ef3689f06e24650eb65176e2dc5eChristopher Ferris static BacktraceMap* Create(pid_t pid, bool uncached = false); 55df2906186b6952c57b1f662bfef0b65c9f8c2e0dChristopher Ferris 569e402bb20cb868577e5588d8323363411655291bYabin Cui static BacktraceMap* Create(pid_t pid, const std::vector<backtrace_map_t>& maps); 579e402bb20cb868577e5588d8323363411655291bYabin Cui 5846756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris virtual ~BacktraceMap(); 5946756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris 6012385e3ad085aa1ac06c26529b32b688503a9fcfChristopher Ferris // Fill in the map data structure for the given address. 6112385e3ad085aa1ac06c26529b32b688503a9fcfChristopher Ferris virtual void FillIn(uintptr_t addr, backtrace_map_t* map); 6246756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris 6346756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris // The flags returned are the same flags as used by the mmap call. 6446756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris // The values are PROT_*. 6546756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris int GetFlags(uintptr_t pc) { 6612385e3ad085aa1ac06c26529b32b688503a9fcfChristopher Ferris backtrace_map_t map; 6712385e3ad085aa1ac06c26529b32b688503a9fcfChristopher Ferris FillIn(pc, &map); 6812385e3ad085aa1ac06c26529b32b688503a9fcfChristopher Ferris if (IsValid(map)) { 6912385e3ad085aa1ac06c26529b32b688503a9fcfChristopher Ferris return map.flags; 7046756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris } 7146756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris return PROT_NONE; 7246756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris } 7346756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris 7446756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris bool IsReadable(uintptr_t pc) { return GetFlags(pc) & PROT_READ; } 7546756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris bool IsWritable(uintptr_t pc) { return GetFlags(pc) & PROT_WRITE; } 7646756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris bool IsExecutable(uintptr_t pc) { return GetFlags(pc) & PROT_EXEC; } 7746756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris 783a14004c7f521cf2ca6dfea182fa7441e77c97e7Christopher Ferris // In order to use the iterators on this object, a caller must 793a14004c7f521cf2ca6dfea182fa7441e77c97e7Christopher Ferris // call the LockIterator and UnlockIterator function to guarantee 803a14004c7f521cf2ca6dfea182fa7441e77c97e7Christopher Ferris // that the data does not change while it's being used. 813a14004c7f521cf2ca6dfea182fa7441e77c97e7Christopher Ferris virtual void LockIterator() {} 823a14004c7f521cf2ca6dfea182fa7441e77c97e7Christopher Ferris virtual void UnlockIterator() {} 833a14004c7f521cf2ca6dfea182fa7441e77c97e7Christopher Ferris 84df2906186b6952c57b1f662bfef0b65c9f8c2e0dChristopher Ferris typedef std::deque<backtrace_map_t>::iterator iterator; 8546756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris iterator begin() { return maps_.begin(); } 8646756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris iterator end() { return maps_.end(); } 8746756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris 88df2906186b6952c57b1f662bfef0b65c9f8c2e0dChristopher Ferris typedef std::deque<backtrace_map_t>::const_iterator const_iterator; 8946756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris const_iterator begin() const { return maps_.begin(); } 9046756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris const_iterator end() const { return maps_.end(); } 9146756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris 92bab3354ede1d651a6655457339a6f3d446eb90abElliott Hughes size_t size() const { return maps_.size(); } 93bab3354ede1d651a6655457339a6f3d446eb90abElliott Hughes 9446756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris virtual bool Build(); 9546756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris 9612385e3ad085aa1ac06c26529b32b688503a9fcfChristopher Ferris static inline bool IsValid(const backtrace_map_t& map) { 9712385e3ad085aa1ac06c26529b32b688503a9fcfChristopher Ferris return map.end > 0; 9812385e3ad085aa1ac06c26529b32b688503a9fcfChristopher Ferris } 9912385e3ad085aa1ac06c26529b32b688503a9fcfChristopher Ferris 10046756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferrisprotected: 101df2906186b6952c57b1f662bfef0b65c9f8c2e0dChristopher Ferris BacktraceMap(pid_t pid); 102df2906186b6952c57b1f662bfef0b65c9f8c2e0dChristopher Ferris 10346756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris virtual bool ParseLine(const char* line, backtrace_map_t* map); 10446756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris 105df2906186b6952c57b1f662bfef0b65c9f8c2e0dChristopher Ferris std::deque<backtrace_map_t> maps_; 10646756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris pid_t pid_; 10746756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris}; 10846756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris 1093a14004c7f521cf2ca6dfea182fa7441e77c97e7Christopher Ferrisclass ScopedBacktraceMapIteratorLock { 1103a14004c7f521cf2ca6dfea182fa7441e77c97e7Christopher Ferrispublic: 1113a14004c7f521cf2ca6dfea182fa7441e77c97e7Christopher Ferris explicit ScopedBacktraceMapIteratorLock(BacktraceMap* map) : map_(map) { 1123a14004c7f521cf2ca6dfea182fa7441e77c97e7Christopher Ferris map->LockIterator(); 1133a14004c7f521cf2ca6dfea182fa7441e77c97e7Christopher Ferris } 1143a14004c7f521cf2ca6dfea182fa7441e77c97e7Christopher Ferris 1153a14004c7f521cf2ca6dfea182fa7441e77c97e7Christopher Ferris ~ScopedBacktraceMapIteratorLock() { 1163a14004c7f521cf2ca6dfea182fa7441e77c97e7Christopher Ferris map_->UnlockIterator(); 1173a14004c7f521cf2ca6dfea182fa7441e77c97e7Christopher Ferris } 1183a14004c7f521cf2ca6dfea182fa7441e77c97e7Christopher Ferris 1193a14004c7f521cf2ca6dfea182fa7441e77c97e7Christopher Ferrisprivate: 1203a14004c7f521cf2ca6dfea182fa7441e77c97e7Christopher Ferris BacktraceMap* map_; 1213a14004c7f521cf2ca6dfea182fa7441e77c97e7Christopher Ferris}; 1223a14004c7f521cf2ca6dfea182fa7441e77c97e7Christopher Ferris 12346756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris#endif // _BACKTRACE_BACKTRACE_MAP_H 124