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 54 namespace google_breakpad { 55 56 class CallStack; 57 class DumpContext; 58 class StackFrameSymbolizer; 59 60 using std::set; 61 using std::vector; 62 63 class Stackwalker { 64 public: ~Stackwalker()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_with_corrupt_symbols| will be populated with pointers to the 74 // modules which have corrupt symbols. |modules_without_symbols| and 75 // |modules_with_corrupt_symbols| DO NOT take ownership of the code modules. 76 // The lifetime of these code modules is the same as the lifetime of the 77 // CodeModules passed to the StackWalker constructor (which currently 78 // happens to be the lifetime of the Breakpad's ProcessingState object). 79 // There is a check for duplicate modules so no duplicates are expected. 80 bool Walk(CallStack* stack, 81 vector<const CodeModule*>* modules_without_symbols, 82 vector<const CodeModule*>* modules_with_corrupt_symbols); 83 84 // Returns a new concrete subclass suitable for the CPU that a stack was 85 // generated on, according to the CPU type indicated by the context 86 // argument. If no suitable concrete subclass exists, returns NULL. 87 static Stackwalker* StackwalkerForCPU( 88 const SystemInfo* system_info, 89 DumpContext* context, 90 MemoryRegion* memory, 91 const CodeModules* modules, 92 const CodeModules* unloaded_modules, 93 StackFrameSymbolizer* resolver_helper); 94 95 set_max_frames(uint32_t max_frames)96 static void set_max_frames(uint32_t max_frames) { 97 max_frames_ = max_frames; 98 max_frames_set_ = true; 99 } max_frames()100 static uint32_t max_frames() { return max_frames_; } 101 set_max_frames_scanned(uint32_t max_frames_scanned)102 static void set_max_frames_scanned(uint32_t max_frames_scanned) { 103 max_frames_scanned_ = max_frames_scanned; 104 } 105 106 protected: 107 // system_info identifies the operating system, NULL or empty if unknown. 108 // memory identifies a MemoryRegion that provides the stack memory 109 // for the stack to walk. modules, if non-NULL, is a CodeModules 110 // object that is used to look up which code module each stack frame is 111 // associated with. frame_symbolizer is a StackFrameSymbolizer object that 112 // encapsulates the logic of how source line resolver interacts with symbol 113 // supplier to symbolize stack frame and look up caller frame information 114 // (see stack_frame_symbolizer.h). 115 // frame_symbolizer MUST NOT be NULL (asserted). 116 Stackwalker(const SystemInfo* system_info, 117 MemoryRegion* memory, 118 const CodeModules* modules, 119 StackFrameSymbolizer* frame_symbolizer); 120 121 // This can be used to filter out potential return addresses when 122 // the stack walker resorts to stack scanning. 123 // Returns true if any of: 124 // * This address is within a loaded module, but we don't have symbols 125 // for that module. 126 // * This address is within a loaded module for which we have symbols, 127 // and falls inside a function in that module. 128 // Returns false otherwise. 129 bool InstructionAddressSeemsValid(uint64_t address) const; 130 131 // Checks whether we should stop the stack trace. 132 // (either we reached the end-of-stack or we detected a 133 // broken callstack invariant) 134 bool TerminateWalk(uint64_t caller_ip, 135 uint64_t caller_sp, 136 uint64_t callee_sp, 137 bool first_unwind) const; 138 139 // The default number of words to search through on the stack 140 // for a return address. 141 static const int kRASearchWords; 142 143 template<typename InstructionType> ScanForReturnAddress(InstructionType location_start,InstructionType * location_found,InstructionType * ip_found,bool is_context_frame)144 bool ScanForReturnAddress(InstructionType location_start, 145 InstructionType* location_found, 146 InstructionType* ip_found, 147 bool is_context_frame) { 148 // When searching for the caller of the context frame, 149 // allow the scanner to look farther down the stack. 150 const int search_words = is_context_frame ? 151 kRASearchWords * 4 : 152 kRASearchWords; 153 154 return ScanForReturnAddress(location_start, location_found, ip_found, 155 search_words); 156 } 157 158 // Scan the stack starting at location_start, looking for an address 159 // that looks like a valid instruction pointer. Addresses must 160 // 1) be contained in the current stack memory 161 // 2) pass the checks in InstructionAddressSeemsValid 162 // 163 // Returns true if a valid-looking instruction pointer was found. 164 // When returning true, sets location_found to the address at which 165 // the value was found, and ip_found to the value contained at that 166 // location in memory. 167 template<typename InstructionType> ScanForReturnAddress(InstructionType location_start,InstructionType * location_found,InstructionType * ip_found,int searchwords)168 bool ScanForReturnAddress(InstructionType location_start, 169 InstructionType* location_found, 170 InstructionType* ip_found, 171 int searchwords) { 172 for (InstructionType location = location_start; 173 location <= location_start + searchwords * sizeof(InstructionType); 174 location += sizeof(InstructionType)) { 175 InstructionType ip; 176 if (!memory_->GetMemoryAtAddress(location, &ip)) 177 break; 178 179 if (modules_ && modules_->GetModuleForAddress(ip) && 180 InstructionAddressSeemsValid(ip)) { 181 *ip_found = ip; 182 *location_found = location; 183 return true; 184 } 185 } 186 // nothing found 187 return false; 188 } 189 190 // Information about the system that produced the minidump. Subclasses 191 // and the SymbolSupplier may find this information useful. 192 const SystemInfo* system_info_; 193 194 // The stack memory to walk. Subclasses will require this region to 195 // get information from the stack. 196 MemoryRegion* memory_; 197 198 // A list of modules, for populating each StackFrame's module information. 199 // This field is optional and may be NULL. 200 const CodeModules* modules_; 201 202 // A list of unloaded modules, for populating frames which aren't matched 203 // to any loaded modules. 204 // This field is optional and may be NULL. 205 const CodeModules* unloaded_modules_; 206 207 protected: 208 // The StackFrameSymbolizer implementation. 209 StackFrameSymbolizer* frame_symbolizer_; 210 211 private: 212 // Obtains the context frame, the innermost called procedure in a stack 213 // trace. Returns NULL on failure. GetContextFrame allocates a new 214 // StackFrame (or StackFrame subclass), ownership of which is taken by 215 // the caller. 216 virtual StackFrame* GetContextFrame() = 0; 217 218 // Obtains a caller frame. Each call to GetCallerFrame should return the 219 // frame that called the last frame returned by GetContextFrame or 220 // GetCallerFrame. To aid this purpose, stack contains the CallStack 221 // made of frames that have already been walked. GetCallerFrame should 222 // return NULL on failure or when there are no more caller frames (when 223 // the end of the stack has been reached). GetCallerFrame allocates a new 224 // StackFrame (or StackFrame subclass), ownership of which is taken by 225 // the caller. |stack_scan_allowed| controls whether stack scanning is 226 // an allowable frame-recovery method, since it is desirable to be able to 227 // disable stack scanning in performance-critical use cases. 228 // 229 // CONSIDER: a way to differentiate between: 230 // - full stack traces 231 // - explicitly truncated traces (max_frames_) 232 // - stopping after max scanned frames 233 // - failed stack walk (breaking one of the stack walk invariants) 234 // 235 virtual StackFrame* GetCallerFrame(const CallStack* stack, 236 bool stack_scan_allowed) = 0; 237 238 // The maximum number of frames Stackwalker will walk through. 239 // This defaults to 1024 to prevent infinite loops. 240 static uint32_t max_frames_; 241 242 // Keep track of whether max_frames_ has been set by the user, since 243 // it affects whether or not an error message is printed in the case 244 // where an unwind got stopped by the limit. 245 static bool max_frames_set_; 246 247 // The maximum number of stack-scanned and otherwise untrustworthy 248 // frames allowed. Stack-scanning can be expensive, so the option to 249 // disable or limit it is helpful in cases where unwind performance is 250 // important. This defaults to 1024, the same as max_frames_. 251 static uint32_t max_frames_scanned_; 252 }; 253 254 } // namespace google_breakpad 255 256 257 #endif // GOOGLE_BREAKPAD_PROCESSOR_STACKWALKER_H__ 258