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 StackFrameSymbolizer* resolver_helper); 93 set_max_frames(uint32_t max_frames)94 static void set_max_frames(uint32_t max_frames) { 95 max_frames_ = max_frames; 96 max_frames_set_ = true; 97 } max_frames()98 static uint32_t max_frames() { return max_frames_; } 99 set_max_frames_scanned(uint32_t max_frames_scanned)100 static void set_max_frames_scanned(uint32_t max_frames_scanned) { 101 max_frames_scanned_ = max_frames_scanned; 102 } 103 104 protected: 105 // system_info identifies the operating system, NULL or empty if unknown. 106 // memory identifies a MemoryRegion that provides the stack memory 107 // for the stack to walk. modules, if non-NULL, is a CodeModules 108 // object that is used to look up which code module each stack frame is 109 // associated with. frame_symbolizer is a StackFrameSymbolizer object that 110 // encapsulates the logic of how source line resolver interacts with symbol 111 // supplier to symbolize stack frame and look up caller frame information 112 // (see stack_frame_symbolizer.h). 113 // frame_symbolizer MUST NOT be NULL (asserted). 114 Stackwalker(const SystemInfo* system_info, 115 MemoryRegion* memory, 116 const CodeModules* modules, 117 StackFrameSymbolizer* frame_symbolizer); 118 119 // This can be used to filter out potential return addresses when 120 // the stack walker resorts to stack scanning. 121 // Returns true if any of: 122 // * This address is within a loaded module, but we don't have symbols 123 // for that module. 124 // * This address is within a loaded module for which we have symbols, 125 // and falls inside a function in that module. 126 // Returns false otherwise. 127 bool InstructionAddressSeemsValid(uint64_t address); 128 129 // The default number of words to search through on the stack 130 // for a return address. 131 static const int kRASearchWords; 132 133 template<typename InstructionType> ScanForReturnAddress(InstructionType location_start,InstructionType * location_found,InstructionType * ip_found,bool is_context_frame)134 bool ScanForReturnAddress(InstructionType location_start, 135 InstructionType* location_found, 136 InstructionType* ip_found, 137 bool is_context_frame) { 138 // When searching for the caller of the context frame, 139 // allow the scanner to look farther down the stack. 140 const int search_words = is_context_frame ? 141 kRASearchWords * 4 : 142 kRASearchWords; 143 144 return ScanForReturnAddress(location_start, location_found, ip_found, 145 search_words); 146 } 147 148 // Scan the stack starting at location_start, looking for an address 149 // that looks like a valid instruction pointer. Addresses must 150 // 1) be contained in the current stack memory 151 // 2) pass the checks in InstructionAddressSeemsValid 152 // 153 // Returns true if a valid-looking instruction pointer was found. 154 // When returning true, sets location_found to the address at which 155 // the value was found, and ip_found to the value contained at that 156 // location in memory. 157 template<typename InstructionType> ScanForReturnAddress(InstructionType location_start,InstructionType * location_found,InstructionType * ip_found,int searchwords)158 bool ScanForReturnAddress(InstructionType location_start, 159 InstructionType* location_found, 160 InstructionType* ip_found, 161 int searchwords) { 162 for (InstructionType location = location_start; 163 location <= location_start + searchwords * sizeof(InstructionType); 164 location += sizeof(InstructionType)) { 165 InstructionType ip; 166 if (!memory_->GetMemoryAtAddress(location, &ip)) 167 break; 168 169 if (modules_ && modules_->GetModuleForAddress(ip) && 170 InstructionAddressSeemsValid(ip)) { 171 *ip_found = ip; 172 *location_found = location; 173 return true; 174 } 175 } 176 // nothing found 177 return false; 178 } 179 180 // Information about the system that produced the minidump. Subclasses 181 // and the SymbolSupplier may find this information useful. 182 const SystemInfo* system_info_; 183 184 // The stack memory to walk. Subclasses will require this region to 185 // get information from the stack. 186 MemoryRegion* memory_; 187 188 // A list of modules, for populating each StackFrame's module information. 189 // This field is optional and may be NULL. 190 const CodeModules* modules_; 191 192 protected: 193 // The StackFrameSymbolizer implementation. 194 StackFrameSymbolizer* frame_symbolizer_; 195 196 private: 197 // Obtains the context frame, the innermost called procedure in a stack 198 // trace. Returns NULL on failure. GetContextFrame allocates a new 199 // StackFrame (or StackFrame subclass), ownership of which is taken by 200 // the caller. 201 virtual StackFrame* GetContextFrame() = 0; 202 203 // Obtains a caller frame. Each call to GetCallerFrame should return the 204 // frame that called the last frame returned by GetContextFrame or 205 // GetCallerFrame. To aid this purpose, stack contains the CallStack 206 // made of frames that have already been walked. GetCallerFrame should 207 // return NULL on failure or when there are no more caller frames (when 208 // the end of the stack has been reached). GetCallerFrame allocates a new 209 // StackFrame (or StackFrame subclass), ownership of which is taken by 210 // the caller. |stack_scan_allowed| controls whether stack scanning is 211 // an allowable frame-recovery method, since it is desirable to be able to 212 // disable stack scanning in performance-critical use cases. 213 virtual StackFrame* GetCallerFrame(const CallStack* stack, 214 bool stack_scan_allowed) = 0; 215 216 // The maximum number of frames Stackwalker will walk through. 217 // This defaults to 1024 to prevent infinite loops. 218 static uint32_t max_frames_; 219 220 // Keep track of whether max_frames_ has been set by the user, since 221 // it affects whether or not an error message is printed in the case 222 // where an unwind got stopped by the limit. 223 static bool max_frames_set_; 224 225 // The maximum number of stack-scanned and otherwise untrustworthy 226 // frames allowed. Stack-scanning can be expensive, so the option to 227 // disable or limit it is helpful in cases where unwind performance is 228 // important. This defaults to 1024, the same as max_frames_. 229 static uint32_t max_frames_scanned_; 230 }; 231 232 } // namespace google_breakpad 233 234 235 #endif // GOOGLE_BREAKPAD_PROCESSOR_STACKWALKER_H__ 236