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: |
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 | |
96 | static void set_max_frames(uint32_t max_frames) { |
97 | max_frames_ = max_frames; |
98 | max_frames_set_ = true; |
99 | } |
100 | static uint32_t max_frames() { return max_frames_; } |
101 | |
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> |
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> |
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 | // The return address points to the instruction after a call. If the |
180 | // caller was a no return function, this might point past the end of the |
181 | // function. Subtract one from the instruction pointer so it points into |
182 | // the call instruction instead. |
183 | if (modules_ && modules_->GetModuleForAddress(ip - 1) && |
184 | InstructionAddressSeemsValid(ip - 1)) { |
185 | *ip_found = ip; |
186 | *location_found = location; |
187 | return true; |
188 | } |
189 | } |
190 | // nothing found |
191 | return false; |
192 | } |
193 | |
194 | // Information about the system that produced the minidump. Subclasses |
195 | // and the SymbolSupplier may find this information useful. |
196 | const SystemInfo* system_info_; |
197 | |
198 | // The stack memory to walk. Subclasses will require this region to |
199 | // get information from the stack. |
200 | MemoryRegion* memory_; |
201 | |
202 | // A list of modules, for populating each StackFrame's module information. |
203 | // This field is optional and may be NULL. |
204 | const CodeModules* modules_; |
205 | |
206 | // A list of unloaded modules, for populating frames which aren't matched |
207 | // to any loaded modules. |
208 | // This field is optional and may be NULL. |
209 | const CodeModules* unloaded_modules_; |
210 | |
211 | protected: |
212 | // The StackFrameSymbolizer implementation. |
213 | StackFrameSymbolizer* frame_symbolizer_; |
214 | |
215 | private: |
216 | // Obtains the context frame, the innermost called procedure in a stack |
217 | // trace. Returns NULL on failure. GetContextFrame allocates a new |
218 | // StackFrame (or StackFrame subclass), ownership of which is taken by |
219 | // the caller. |
220 | virtual StackFrame* GetContextFrame() = 0; |
221 | |
222 | // Obtains a caller frame. Each call to GetCallerFrame should return the |
223 | // frame that called the last frame returned by GetContextFrame or |
224 | // GetCallerFrame. To aid this purpose, stack contains the CallStack |
225 | // made of frames that have already been walked. GetCallerFrame should |
226 | // return NULL on failure or when there are no more caller frames (when |
227 | // the end of the stack has been reached). GetCallerFrame allocates a new |
228 | // StackFrame (or StackFrame subclass), ownership of which is taken by |
229 | // the caller. |stack_scan_allowed| controls whether stack scanning is |
230 | // an allowable frame-recovery method, since it is desirable to be able to |
231 | // disable stack scanning in performance-critical use cases. |
232 | // |
233 | // CONSIDER: a way to differentiate between: |
234 | // - full stack traces |
235 | // - explicitly truncated traces (max_frames_) |
236 | // - stopping after max scanned frames |
237 | // - failed stack walk (breaking one of the stack walk invariants) |
238 | // |
239 | virtual StackFrame* GetCallerFrame(const CallStack* stack, |
240 | bool stack_scan_allowed) = 0; |
241 | |
242 | // The maximum number of frames Stackwalker will walk through. |
243 | // This defaults to 1024 to prevent infinite loops. |
244 | static uint32_t max_frames_; |
245 | |
246 | // Keep track of whether max_frames_ has been set by the user, since |
247 | // it affects whether or not an error message is printed in the case |
248 | // where an unwind got stopped by the limit. |
249 | static bool max_frames_set_; |
250 | |
251 | // The maximum number of stack-scanned and otherwise untrustworthy |
252 | // frames allowed. Stack-scanning can be expensive, so the option to |
253 | // disable or limit it is helpful in cases where unwind performance is |
254 | // important. This defaults to 1024, the same as max_frames_. |
255 | static uint32_t max_frames_scanned_; |
256 | }; |
257 | |
258 | } // namespace google_breakpad |
259 | |
260 | |
261 | #endif // GOOGLE_BREAKPAD_PROCESSOR_STACKWALKER_H__ |
262 | |