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