stackwalker.h revision 0e8d72222af5c46f57f1d12149da7a6ce68e63d8
1// Copyright (c) 2010 Google Inc. 2// All rights reserved. 3// 4// Redistribution and use in source and binary forms, with or without 5// modification, are permitted provided that the following conditions are 6// met: 7// 8// * Redistributions of source code must retain the above copyright 9// notice, this list of conditions and the following disclaimer. 10// * Redistributions in binary form must reproduce the above 11// copyright notice, this list of conditions and the following disclaimer 12// in the documentation and/or other materials provided with the 13// distribution. 14// * Neither the name of Google Inc. nor the names of its 15// contributors may be used to endorse or promote products derived from 16// this software without specific prior written permission. 17// 18// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 30// stackwalker.h: Generic stackwalker. 31// 32// The Stackwalker class is an abstract base class providing common generic 33// methods that apply to stacks from all systems. Specific implementations 34// will extend this class by providing GetContextFrame and GetCallerFrame 35// methods to fill in system-specific data in a StackFrame structure. 36// Stackwalker assembles these StackFrame strucutres into a CallStack. 37// 38// Author: Mark Mentovai 39 40 41#ifndef GOOGLE_BREAKPAD_PROCESSOR_STACKWALKER_H__ 42#define GOOGLE_BREAKPAD_PROCESSOR_STACKWALKER_H__ 43 44#include <set> 45#include <string> 46#include <vector> 47 48#include "common/using_std_string.h" 49#include "google_breakpad/common/breakpad_types.h" 50#include "google_breakpad/processor/code_modules.h" 51#include "google_breakpad/processor/memory_region.h" 52#include "google_breakpad/processor/stack_frame_symbolizer.h" 53 54namespace google_breakpad { 55 56class CallStack; 57class MinidumpContext; 58class StackFrameSymbolizer; 59 60using std::set; 61using std::vector; 62 63class Stackwalker { 64 public: 65 virtual ~Stackwalker() {} 66 67 // Populates the given CallStack by calling GetContextFrame and 68 // GetCallerFrame. The frames are further processed to fill all available 69 // data. Returns true if the stackwalk completed, or false if it was 70 // interrupted by SymbolSupplier::GetSymbolFile(). 71 // Upon return, modules_without_symbols will be populated with pointers to 72 // the code modules (CodeModule*) that DON'T have symbols. 73 // modules_without_symbols DOES NOT take ownership of the code modules. 74 // The lifetime of these code modules is the same as the lifetime of the 75 // CodeModules passed to the StackWalker constructor (which currently 76 // happens to be the lifetime of the Breakpad's ProcessingState object). 77 // There is a check for duplicate modules so no duplicates are expected. 78 bool Walk(CallStack* stack, 79 vector<const CodeModule*>* modules_without_symbols); 80 81 // Returns a new concrete subclass suitable for the CPU that a stack was 82 // generated on, according to the CPU type indicated by the context 83 // argument. If no suitable concrete subclass exists, returns NULL. 84 static Stackwalker* StackwalkerForCPU( 85 const SystemInfo* system_info, 86 MinidumpContext* context, 87 MemoryRegion* memory, 88 const CodeModules* modules, 89 StackFrameSymbolizer* resolver_helper); 90 91 static void set_max_frames(uint32_t max_frames) { 92 max_frames_ = max_frames; 93 max_frames_set_ = true; 94 } 95 static uint32_t max_frames() { return max_frames_; } 96 97 protected: 98 // system_info identifies the operating system, NULL or empty if unknown. 99 // memory identifies a MemoryRegion that provides the stack memory 100 // for the stack to walk. modules, if non-NULL, is a CodeModules 101 // object that is used to look up which code module each stack frame is 102 // associated with. frame_symbolizer is a StackFrameSymbolizer object that 103 // encapsulates the logic of how source line resolver interacts with symbol 104 // supplier to symbolize stack frame and look up caller frame information 105 // (see stack_frame_symbolizer.h). 106 // frame_symbolizer MUST NOT be NULL (asserted). 107 Stackwalker(const SystemInfo* system_info, 108 MemoryRegion* memory, 109 const CodeModules* modules, 110 StackFrameSymbolizer* frame_symbolizer); 111 112 // This can be used to filter out potential return addresses when 113 // the stack walker resorts to stack scanning. 114 // Returns true if any of: 115 // * This address is within a loaded module, but we don't have symbols 116 // for that module. 117 // * This address is within a loaded module for which we have symbols, 118 // and falls inside a function in that module. 119 // Returns false otherwise. 120 bool InstructionAddressSeemsValid(uint64_t address); 121 122 // The default number of words to search through on the stack 123 // for a return address. 124 static const int kRASearchWords; 125 126 template<typename InstructionType> 127 bool ScanForReturnAddress(InstructionType location_start, 128 InstructionType* location_found, 129 InstructionType* ip_found) { 130 return ScanForReturnAddress(location_start, location_found, ip_found, 131 kRASearchWords); 132 } 133 134 // Scan the stack starting at location_start, looking for an address 135 // that looks like a valid instruction pointer. Addresses must 136 // 1) be contained in the current stack memory 137 // 2) pass the checks in InstructionAddressSeemsValid 138 // 139 // Returns true if a valid-looking instruction pointer was found. 140 // When returning true, sets location_found to the address at which 141 // the value was found, and ip_found to the value contained at that 142 // location in memory. 143 template<typename InstructionType> 144 bool ScanForReturnAddress(InstructionType location_start, 145 InstructionType* location_found, 146 InstructionType* ip_found, 147 int searchwords) { 148 for (InstructionType location = location_start; 149 location <= location_start + searchwords * sizeof(InstructionType); 150 location += sizeof(InstructionType)) { 151 InstructionType ip; 152 if (!memory_->GetMemoryAtAddress(location, &ip)) 153 break; 154 155 if (modules_ && modules_->GetModuleForAddress(ip) && 156 InstructionAddressSeemsValid(ip)) { 157 *ip_found = ip; 158 *location_found = location; 159 return true; 160 } 161 } 162 // nothing found 163 return false; 164 } 165 166 // Information about the system that produced the minidump. Subclasses 167 // and the SymbolSupplier may find this information useful. 168 const SystemInfo* system_info_; 169 170 // The stack memory to walk. Subclasses will require this region to 171 // get information from the stack. 172 MemoryRegion* memory_; 173 174 // A list of modules, for populating each StackFrame's module information. 175 // This field is optional and may be NULL. 176 const CodeModules* modules_; 177 178 protected: 179 // The StackFrameSymbolizer implementation. 180 StackFrameSymbolizer* frame_symbolizer_; 181 182 private: 183 // Obtains the context frame, the innermost called procedure in a stack 184 // trace. Returns NULL on failure. GetContextFrame allocates a new 185 // StackFrame (or StackFrame subclass), ownership of which is taken by 186 // the caller. 187 virtual StackFrame* GetContextFrame() = 0; 188 189 // Obtains a caller frame. Each call to GetCallerFrame should return the 190 // frame that called the last frame returned by GetContextFrame or 191 // GetCallerFrame. To aid this purpose, stack contains the CallStack 192 // made of frames that have already been walked. GetCallerFrame should 193 // return NULL on failure or when there are no more caller frames (when 194 // the end of the stack has been reached). GetCallerFrame allocates a new 195 // StackFrame (or StackFrame subclass), ownership of which is taken by 196 // the caller. 197 virtual StackFrame* GetCallerFrame(const CallStack* stack) = 0; 198 199 // The maximum number of frames Stackwalker will walk through. 200 // This defaults to 1024 to prevent infinite loops. 201 static uint32_t max_frames_; 202 203 // Keep track of whether max_frames_ has been set by the user, since 204 // it affects whether or not an error message is printed in the case 205 // where an unwind got stopped by the limit. 206 static bool max_frames_set_; 207}; 208 209} // namespace google_breakpad 210 211 212#endif // GOOGLE_BREAKPAD_PROCESSOR_STACKWALKER_H__ 213