stackwalker.cc revision 246f4068280b5b191303ff13671e43a0522987de
1// Copyright (c) 2006, 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.cc: Generic stackwalker.
31//
32// See stackwalker.h for documentation.
33//
34// Author: Mark Mentovai
35
36
37#include <memory>
38
39#include "processor/stackwalker.h"
40#include "google/call_stack.h"
41#include "google/stack_frame.h"
42#include "google/symbol_supplier.h"
43#include "processor/minidump.h"
44#include "processor/source_line_resolver.h"
45#include "processor/stackwalker_ppc.h"
46#include "processor/stackwalker_x86.h"
47
48namespace google_airbag {
49
50using std::auto_ptr;
51
52
53Stackwalker::Stackwalker(MemoryRegion *memory, MinidumpModuleList *modules,
54                         SymbolSupplier *supplier)
55    : memory_(memory), stack_frame_info_(), modules_(modules),
56      supplier_(supplier) {
57}
58
59
60void Stackwalker::Walk(CallStack *stack) {
61  stack_frame_info_.clear();
62  SourceLineResolver resolver;
63
64  // Begin with the context frame, and keep getting callers until there are
65  // no more.
66
67  // Take ownership of the pointer returned by GetContextFrame.
68  auto_ptr<StackFrame> frame(GetContextFrame());
69
70  while (frame.get()) {
71    // frame already contains a good frame with properly set instruction and
72    // frame_pointer fields.  The frame structure comes from either the
73    // context frame (above) or a caller frame (below).
74
75    StackFrameInfo frame_info;
76
77    // Resolve the module information, if a module map was provided.
78    if (modules_) {
79      MinidumpModule *module =
80          modules_->GetModuleForAddress(frame->instruction);
81      if (module) {
82        frame->module_name = *(module->GetName());
83        frame->module_base = module->base_address();
84        if (!resolver.HasModule(frame->module_name) && supplier_) {
85          string symbol_file = supplier_->GetSymbolFile(module);
86          if (!symbol_file.empty()) {
87            resolver.LoadModule(frame->module_name, symbol_file);
88          }
89        }
90        resolver.FillSourceLineInfo(frame.get(), &frame_info);
91      }
92    }
93
94    // Add the frame to the call stack.  Relinquish the ownership claim
95    // over the frame, because the stack now owns it.
96    stack->frames_.push_back(frame.release());
97
98    // Copy the frame info.
99    stack_frame_info_.push_back(frame_info);
100    frame_info.Clear();
101
102    // Get the next frame and take ownership.
103    frame.reset(GetCallerFrame(stack));
104  }
105}
106
107
108// static
109Stackwalker* Stackwalker::StackwalkerForCPU(MinidumpContext *context,
110                                            MemoryRegion *memory,
111                                            MinidumpModuleList *modules,
112                                            SymbolSupplier *supplier) {
113  Stackwalker *cpu_stackwalker = NULL;
114
115  u_int32_t cpu = context->GetContextCPU();
116  switch (cpu) {
117    case MD_CONTEXT_X86:
118      cpu_stackwalker = new StackwalkerX86(context->GetContextX86(),
119                                           memory, modules, supplier);
120      break;
121
122    case MD_CONTEXT_PPC:
123      cpu_stackwalker = new StackwalkerPPC(context->GetContextPPC(),
124                                           memory, modules, supplier);
125      break;
126  }
127
128  return cpu_stackwalker;
129}
130
131
132} // namespace google_airbag
133