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>
220dbce4564bd697bc2603f6c05ac47b81977cd41fChristopher Ferris#ifdef USE_MINGW
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>
3446756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris
3546756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferrisstruct backtrace_map_t {
3621bd040effcfc48e8794558c91bbfdc159a98f00Christopher Ferris  uintptr_t start = 0;
3721bd040effcfc48e8794558c91bbfdc159a98f00Christopher Ferris  uintptr_t end = 0;
3821bd040effcfc48e8794558c91bbfdc159a98f00Christopher Ferris  uintptr_t offset = 0;
3921bd040effcfc48e8794558c91bbfdc159a98f00Christopher Ferris  uintptr_t load_base = 0;
4021bd040effcfc48e8794558c91bbfdc159a98f00Christopher Ferris  int flags = 0;
4146756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris  std::string name;
4246756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris};
4346756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris
4446756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferrisclass BacktraceMap {
4546756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferrispublic:
46dda47b786835ef3689f06e24650eb65176e2dc5eChristopher Ferris  // If uncached is true, then parse the current process map as of the call.
47dda47b786835ef3689f06e24650eb65176e2dc5eChristopher Ferris  // Passing a map created with uncached set to true to Backtrace::Create()
48dda47b786835ef3689f06e24650eb65176e2dc5eChristopher Ferris  // is unsupported.
49dda47b786835ef3689f06e24650eb65176e2dc5eChristopher Ferris  static BacktraceMap* Create(pid_t pid, bool uncached = false);
50df2906186b6952c57b1f662bfef0b65c9f8c2e0dChristopher Ferris
5146756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris  virtual ~BacktraceMap();
5246756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris
5312385e3ad085aa1ac06c26529b32b688503a9fcfChristopher Ferris  // Fill in the map data structure for the given address.
5412385e3ad085aa1ac06c26529b32b688503a9fcfChristopher Ferris  virtual void FillIn(uintptr_t addr, backtrace_map_t* map);
5546756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris
5646756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris  // The flags returned are the same flags as used by the mmap call.
5746756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris  // The values are PROT_*.
5846756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris  int GetFlags(uintptr_t pc) {
5912385e3ad085aa1ac06c26529b32b688503a9fcfChristopher Ferris    backtrace_map_t map;
6012385e3ad085aa1ac06c26529b32b688503a9fcfChristopher Ferris    FillIn(pc, &map);
6112385e3ad085aa1ac06c26529b32b688503a9fcfChristopher Ferris    if (IsValid(map)) {
6212385e3ad085aa1ac06c26529b32b688503a9fcfChristopher Ferris      return map.flags;
6346756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris    }
6446756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris    return PROT_NONE;
6546756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris  }
6646756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris
6746756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris  bool IsReadable(uintptr_t pc) { return GetFlags(pc) & PROT_READ; }
6846756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris  bool IsWritable(uintptr_t pc) { return GetFlags(pc) & PROT_WRITE; }
6946756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris  bool IsExecutable(uintptr_t pc) { return GetFlags(pc) & PROT_EXEC; }
7046756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris
71df2906186b6952c57b1f662bfef0b65c9f8c2e0dChristopher Ferris  typedef std::deque<backtrace_map_t>::iterator iterator;
7246756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris  iterator begin() { return maps_.begin(); }
7346756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris  iterator end() { return maps_.end(); }
7446756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris
75df2906186b6952c57b1f662bfef0b65c9f8c2e0dChristopher Ferris  typedef std::deque<backtrace_map_t>::const_iterator const_iterator;
7646756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris  const_iterator begin() const { return maps_.begin(); }
7746756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris  const_iterator end() const { return maps_.end(); }
7846756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris
7946756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris  virtual bool Build();
8046756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris
8112385e3ad085aa1ac06c26529b32b688503a9fcfChristopher Ferris  static inline bool IsValid(const backtrace_map_t& map) {
8212385e3ad085aa1ac06c26529b32b688503a9fcfChristopher Ferris    return map.end > 0;
8312385e3ad085aa1ac06c26529b32b688503a9fcfChristopher Ferris  }
8412385e3ad085aa1ac06c26529b32b688503a9fcfChristopher Ferris
85329ed7dae49eba09bdf865dd999d1a7e73bb9687Christopher Ferris  static uintptr_t GetRelativePc(const backtrace_map_t& map, uintptr_t pc) {
86329ed7dae49eba09bdf865dd999d1a7e73bb9687Christopher Ferris    if (IsValid(map)) {
87329ed7dae49eba09bdf865dd999d1a7e73bb9687Christopher Ferris      return pc - map.start + map.load_base;
88329ed7dae49eba09bdf865dd999d1a7e73bb9687Christopher Ferris    } else {
89329ed7dae49eba09bdf865dd999d1a7e73bb9687Christopher Ferris      return pc;
90329ed7dae49eba09bdf865dd999d1a7e73bb9687Christopher Ferris    }
91329ed7dae49eba09bdf865dd999d1a7e73bb9687Christopher Ferris  }
92329ed7dae49eba09bdf865dd999d1a7e73bb9687Christopher Ferris
9346756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferrisprotected:
94df2906186b6952c57b1f662bfef0b65c9f8c2e0dChristopher Ferris  BacktraceMap(pid_t pid);
95df2906186b6952c57b1f662bfef0b65c9f8c2e0dChristopher Ferris
9646756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris  virtual bool ParseLine(const char* line, backtrace_map_t* map);
9746756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris
98df2906186b6952c57b1f662bfef0b65c9f8c2e0dChristopher Ferris  std::deque<backtrace_map_t> maps_;
9946756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris  pid_t pid_;
10046756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris};
10146756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris
10246756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris#endif // _BACKTRACE_BACKTRACE_MAP_H
103