xref: /aosp_15_r20/external/google-breakpad/src/google_breakpad/processor/stackwalker.h (revision 9712c20fc9bbfbac4935993a2ca0b3958c5adad2)
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