1 // Copyright (c) 2010 Google Inc.
2 // All rights reserved.
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are
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
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.
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.
30 // stackwalker.h: Generic stackwalker.
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.
38 // Author: Mark Mentovai
41 #ifndef GOOGLE_BREAKPAD_PROCESSOR_STACKWALKER_H__
42 #define GOOGLE_BREAKPAD_PROCESSOR_STACKWALKER_H__
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"
54 namespace google_breakpad {
58 class StackFrameSymbolizer;
65 virtual ~Stackwalker() {}
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);
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,
91 const CodeModules* modules,
92 StackFrameSymbolizer* resolver_helper);
94 static void set_max_frames(uint32_t max_frames) {
95 max_frames_ = max_frames;
96 max_frames_set_ = true;
98 static uint32_t max_frames() { return max_frames_; }
100 static void set_max_frames_scanned(uint32_t max_frames_scanned) {
101 max_frames_scanned_ = max_frames_scanned;
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);
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
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);
129 // The default number of words to search through on the stack
130 // for a return address.
131 static const int kRASearchWords;
133 template<typename InstructionType>
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 ?
144 return ScanForReturnAddress(location_start, location_found, ip_found,
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
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>
158 bool ScanForReturnAddress(InstructionType location_start,
159 InstructionType* location_found,
160 InstructionType* ip_found,
162 for (InstructionType location = location_start;
163 location <= location_start + searchwords * sizeof(InstructionType);
164 location += sizeof(InstructionType)) {
166 if (!memory_->GetMemoryAtAddress(location, &ip))
169 if (modules_ && modules_->GetModuleForAddress(ip) &&
170 InstructionAddressSeemsValid(ip)) {
172 *location_found = location;
180 // Information about the system that produced the minidump. Subclasses
181 // and the SymbolSupplier may find this information useful.
182 const SystemInfo* system_info_;
184 // The stack memory to walk. Subclasses will require this region to
185 // get information from the stack.
186 MemoryRegion* memory_;
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_;
193 // The StackFrameSymbolizer implementation.
194 StackFrameSymbolizer* frame_symbolizer_;
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
201 virtual StackFrame* GetContextFrame() = 0;
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;
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_;
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_;
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_;
232 } // namespace google_breakpad
235 #endif // GOOGLE_BREAKPAD_PROCESSOR_STACKWALKER_H__