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