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