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