stackwalker.cc revision 97d392dc4b60f0099cd7ad8c8a5f06581a532392
17daf246e4baf0837e25429668cc23e92b6afe3b3mmentovai// Copyright (c) 2006, Google Inc.
27daf246e4baf0837e25429668cc23e92b6afe3b3mmentovai// All rights reserved.
3213800d30c11612cb0457c94d7233813a22d83d5mmentovai//
47daf246e4baf0837e25429668cc23e92b6afe3b3mmentovai// Redistribution and use in source and binary forms, with or without
57daf246e4baf0837e25429668cc23e92b6afe3b3mmentovai// modification, are permitted provided that the following conditions are
67daf246e4baf0837e25429668cc23e92b6afe3b3mmentovai// met:
7213800d30c11612cb0457c94d7233813a22d83d5mmentovai//
87daf246e4baf0837e25429668cc23e92b6afe3b3mmentovai//     * Redistributions of source code must retain the above copyright
97daf246e4baf0837e25429668cc23e92b6afe3b3mmentovai// notice, this list of conditions and the following disclaimer.
107daf246e4baf0837e25429668cc23e92b6afe3b3mmentovai//     * Redistributions in binary form must reproduce the above
117daf246e4baf0837e25429668cc23e92b6afe3b3mmentovai// copyright notice, this list of conditions and the following disclaimer
127daf246e4baf0837e25429668cc23e92b6afe3b3mmentovai// in the documentation and/or other materials provided with the
137daf246e4baf0837e25429668cc23e92b6afe3b3mmentovai// distribution.
147daf246e4baf0837e25429668cc23e92b6afe3b3mmentovai//     * Neither the name of Google Inc. nor the names of its
157daf246e4baf0837e25429668cc23e92b6afe3b3mmentovai// contributors may be used to endorse or promote products derived from
167daf246e4baf0837e25429668cc23e92b6afe3b3mmentovai// this software without specific prior written permission.
17213800d30c11612cb0457c94d7233813a22d83d5mmentovai//
187daf246e4baf0837e25429668cc23e92b6afe3b3mmentovai// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
197daf246e4baf0837e25429668cc23e92b6afe3b3mmentovai// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
207daf246e4baf0837e25429668cc23e92b6afe3b3mmentovai// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
217daf246e4baf0837e25429668cc23e92b6afe3b3mmentovai// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
227daf246e4baf0837e25429668cc23e92b6afe3b3mmentovai// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
237daf246e4baf0837e25429668cc23e92b6afe3b3mmentovai// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
247daf246e4baf0837e25429668cc23e92b6afe3b3mmentovai// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
257daf246e4baf0837e25429668cc23e92b6afe3b3mmentovai// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
267daf246e4baf0837e25429668cc23e92b6afe3b3mmentovai// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
277daf246e4baf0837e25429668cc23e92b6afe3b3mmentovai// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
287daf246e4baf0837e25429668cc23e92b6afe3b3mmentovai// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29213800d30c11612cb0457c94d7233813a22d83d5mmentovai
30213800d30c11612cb0457c94d7233813a22d83d5mmentovai// stackwalker.cc: Generic stackwalker.
31213800d30c11612cb0457c94d7233813a22d83d5mmentovai//
32213800d30c11612cb0457c94d7233813a22d83d5mmentovai// See stackwalker.h for documentation.
33213800d30c11612cb0457c94d7233813a22d83d5mmentovai//
34213800d30c11612cb0457c94d7233813a22d83d5mmentovai// Author: Mark Mentovai
35213800d30c11612cb0457c94d7233813a22d83d5mmentovai
36213800d30c11612cb0457c94d7233813a22d83d5mmentovai
37f33b8d2d07a057fdd667c2e0db629ba7cbc37cc3bryner#include <cassert>
38f33b8d2d07a057fdd667c2e0db629ba7cbc37cc3bryner
39fe82bf24a93d9d3affd614aaa23f2f018a733d8emmentovai#include "google_airbag/processor/stackwalker.h"
40fe82bf24a93d9d3affd614aaa23f2f018a733d8emmentovai#include "google_airbag/processor/call_stack.h"
41db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai#include "google_airbag/processor/code_module.h"
42db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai#include "google_airbag/processor/code_modules.h"
43fe82bf24a93d9d3affd614aaa23f2f018a733d8emmentovai#include "google_airbag/processor/minidump.h"
44fd38d48e6d5e56cb66b0fa0f7e25f840a83dac5cbryner#include "google_airbag/processor/source_line_resolver_interface.h"
45fe82bf24a93d9d3affd614aaa23f2f018a733d8emmentovai#include "google_airbag/processor/stack_frame.h"
46fe82bf24a93d9d3affd614aaa23f2f018a733d8emmentovai#include "google_airbag/processor/symbol_supplier.h"
47d119a921ea611dc38cfcb7411759ddf2c688603fmmentovai#include "processor/linked_ptr.h"
482466d8e993a800a17e00deda2f3a27e0505140e1mmentovai#include "processor/scoped_ptr.h"
49d119a921ea611dc38cfcb7411759ddf2c688603fmmentovai#include "processor/stack_frame_info.h"
50960e5277ee489960c40c50c6222606200419302ammentovai#include "processor/stackwalker_ppc.h"
51960e5277ee489960c40c50c6222606200419302ammentovai#include "processor/stackwalker_x86.h"
52213800d30c11612cb0457c94d7233813a22d83d5mmentovai
53213800d30c11612cb0457c94d7233813a22d83d5mmentovainamespace google_airbag {
54213800d30c11612cb0457c94d7233813a22d83d5mmentovai
55213800d30c11612cb0457c94d7233813a22d83d5mmentovai
5697d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovaiStackwalker::Stackwalker(const SystemInfo *system_info,
5797d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai                         MemoryRegion *memory,
5897d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai                         const CodeModules *modules,
59fd38d48e6d5e56cb66b0fa0f7e25f840a83dac5cbryner                         SymbolSupplier *supplier,
60fd38d48e6d5e56cb66b0fa0f7e25f840a83dac5cbryner                         SourceLineResolverInterface *resolver)
6197d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai    : system_info_(system_info),
6297d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai      memory_(memory),
63fd38d48e6d5e56cb66b0fa0f7e25f840a83dac5cbryner      modules_(modules),
64fd38d48e6d5e56cb66b0fa0f7e25f840a83dac5cbryner      supplier_(supplier),
65fd38d48e6d5e56cb66b0fa0f7e25f840a83dac5cbryner      resolver_(resolver) {
66213800d30c11612cb0457c94d7233813a22d83d5mmentovai}
67213800d30c11612cb0457c94d7233813a22d83d5mmentovai
68213800d30c11612cb0457c94d7233813a22d83d5mmentovai
69f33b8d2d07a057fdd667c2e0db629ba7cbc37cc3brynerbool Stackwalker::Walk(CallStack *stack) {
70f33b8d2d07a057fdd667c2e0db629ba7cbc37cc3bryner  assert(stack);
71f33b8d2d07a057fdd667c2e0db629ba7cbc37cc3bryner  stack->Clear();
72d119a921ea611dc38cfcb7411759ddf2c688603fmmentovai
73d119a921ea611dc38cfcb7411759ddf2c688603fmmentovai  // stack_frame_info parallels the CallStack.  The vector is passed to the
74d119a921ea611dc38cfcb7411759ddf2c688603fmmentovai  // GetCallerFrame function.  It contains information that may be helpful
75d119a921ea611dc38cfcb7411759ddf2c688603fmmentovai  // for stackwalking.
76d119a921ea611dc38cfcb7411759ddf2c688603fmmentovai  vector< linked_ptr<StackFrameInfo> > stack_frame_info;
77d119a921ea611dc38cfcb7411759ddf2c688603fmmentovai
78213800d30c11612cb0457c94d7233813a22d83d5mmentovai  // Begin with the context frame, and keep getting callers until there are
79213800d30c11612cb0457c94d7233813a22d83d5mmentovai  // no more.
80213800d30c11612cb0457c94d7233813a22d83d5mmentovai
81246f4068280b5b191303ff13671e43a0522987demmentovai  // Take ownership of the pointer returned by GetContextFrame.
822466d8e993a800a17e00deda2f3a27e0505140e1mmentovai  scoped_ptr<StackFrame> frame(GetContextFrame());
83246f4068280b5b191303ff13671e43a0522987demmentovai
84246f4068280b5b191303ff13671e43a0522987demmentovai  while (frame.get()) {
85213800d30c11612cb0457c94d7233813a22d83d5mmentovai    // frame already contains a good frame with properly set instruction and
86213800d30c11612cb0457c94d7233813a22d83d5mmentovai    // frame_pointer fields.  The frame structure comes from either the
87213800d30c11612cb0457c94d7233813a22d83d5mmentovai    // context frame (above) or a caller frame (below).
88213800d30c11612cb0457c94d7233813a22d83d5mmentovai
89d119a921ea611dc38cfcb7411759ddf2c688603fmmentovai    linked_ptr<StackFrameInfo> frame_info;
90246f4068280b5b191303ff13671e43a0522987demmentovai
91213800d30c11612cb0457c94d7233813a22d83d5mmentovai    // Resolve the module information, if a module map was provided.
92213800d30c11612cb0457c94d7233813a22d83d5mmentovai    if (modules_) {
93db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai      const CodeModule *module =
94213800d30c11612cb0457c94d7233813a22d83d5mmentovai          modules_->GetModuleForAddress(frame->instruction);
95213800d30c11612cb0457c94d7233813a22d83d5mmentovai      if (module) {
96db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai        frame->module = module;
97fd38d48e6d5e56cb66b0fa0f7e25f840a83dac5cbryner        if (resolver_ &&
98fd38d48e6d5e56cb66b0fa0f7e25f840a83dac5cbryner            !resolver_->HasModule(frame->module->code_file()) &&
99fd38d48e6d5e56cb66b0fa0f7e25f840a83dac5cbryner            supplier_) {
100f33b8d2d07a057fdd667c2e0db629ba7cbc37cc3bryner          string symbol_file;
101f33b8d2d07a057fdd667c2e0db629ba7cbc37cc3bryner          SymbolSupplier::SymbolResult symbol_result =
10297d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai              supplier_->GetSymbolFile(module, system_info_, &symbol_file);
103f33b8d2d07a057fdd667c2e0db629ba7cbc37cc3bryner
104f33b8d2d07a057fdd667c2e0db629ba7cbc37cc3bryner          switch (symbol_result) {
105f33b8d2d07a057fdd667c2e0db629ba7cbc37cc3bryner            case SymbolSupplier::FOUND:
106fd38d48e6d5e56cb66b0fa0f7e25f840a83dac5cbryner              resolver_->LoadModule(frame->module->code_file(), symbol_file);
107f33b8d2d07a057fdd667c2e0db629ba7cbc37cc3bryner              break;
108f33b8d2d07a057fdd667c2e0db629ba7cbc37cc3bryner            case SymbolSupplier::NOT_FOUND:
109f33b8d2d07a057fdd667c2e0db629ba7cbc37cc3bryner              break;  // nothing to do
110f33b8d2d07a057fdd667c2e0db629ba7cbc37cc3bryner            case SymbolSupplier::INTERRUPT:
111f33b8d2d07a057fdd667c2e0db629ba7cbc37cc3bryner              return false;
112d5e66382d10b1570d75e924410d58b47857fe799bryner          }
113d5e66382d10b1570d75e924410d58b47857fe799bryner        }
114fd38d48e6d5e56cb66b0fa0f7e25f840a83dac5cbryner        frame_info.reset(resolver_->FillSourceLineInfo(frame.get()));
115213800d30c11612cb0457c94d7233813a22d83d5mmentovai      }
116213800d30c11612cb0457c94d7233813a22d83d5mmentovai    }
117213800d30c11612cb0457c94d7233813a22d83d5mmentovai
118246f4068280b5b191303ff13671e43a0522987demmentovai    // Add the frame to the call stack.  Relinquish the ownership claim
119246f4068280b5b191303ff13671e43a0522987demmentovai    // over the frame, because the stack now owns it.
120246f4068280b5b191303ff13671e43a0522987demmentovai    stack->frames_.push_back(frame.release());
121213800d30c11612cb0457c94d7233813a22d83d5mmentovai
122d119a921ea611dc38cfcb7411759ddf2c688603fmmentovai    // Add the frame info to the parallel stack.
123d119a921ea611dc38cfcb7411759ddf2c688603fmmentovai    stack_frame_info.push_back(frame_info);
124d119a921ea611dc38cfcb7411759ddf2c688603fmmentovai    frame_info.reset(NULL);
125213800d30c11612cb0457c94d7233813a22d83d5mmentovai
126246f4068280b5b191303ff13671e43a0522987demmentovai    // Get the next frame and take ownership.
127f33b8d2d07a057fdd667c2e0db629ba7cbc37cc3bryner    frame.reset(GetCallerFrame(stack, stack_frame_info));
128213800d30c11612cb0457c94d7233813a22d83d5mmentovai  }
129d119a921ea611dc38cfcb7411759ddf2c688603fmmentovai
130f33b8d2d07a057fdd667c2e0db629ba7cbc37cc3bryner  return true;
131213800d30c11612cb0457c94d7233813a22d83d5mmentovai}
132213800d30c11612cb0457c94d7233813a22d83d5mmentovai
133213800d30c11612cb0457c94d7233813a22d83d5mmentovai
134960e5277ee489960c40c50c6222606200419302ammentovai// static
135fd38d48e6d5e56cb66b0fa0f7e25f840a83dac5cbrynerStackwalker* Stackwalker::StackwalkerForCPU(
13697d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai    const SystemInfo *system_info,
137fd38d48e6d5e56cb66b0fa0f7e25f840a83dac5cbryner    MinidumpContext *context,
138fd38d48e6d5e56cb66b0fa0f7e25f840a83dac5cbryner    MemoryRegion *memory,
139fd38d48e6d5e56cb66b0fa0f7e25f840a83dac5cbryner    const CodeModules *modules,
140fd38d48e6d5e56cb66b0fa0f7e25f840a83dac5cbryner    SymbolSupplier *supplier,
141fd38d48e6d5e56cb66b0fa0f7e25f840a83dac5cbryner    SourceLineResolverInterface *resolver) {
142960e5277ee489960c40c50c6222606200419302ammentovai  Stackwalker *cpu_stackwalker = NULL;
143960e5277ee489960c40c50c6222606200419302ammentovai
144960e5277ee489960c40c50c6222606200419302ammentovai  u_int32_t cpu = context->GetContextCPU();
145960e5277ee489960c40c50c6222606200419302ammentovai  switch (cpu) {
146960e5277ee489960c40c50c6222606200419302ammentovai    case MD_CONTEXT_X86:
14797d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai      cpu_stackwalker = new StackwalkerX86(system_info,
14897d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai                                           context->GetContextX86(),
149fd38d48e6d5e56cb66b0fa0f7e25f840a83dac5cbryner                                           memory, modules, supplier,
150fd38d48e6d5e56cb66b0fa0f7e25f840a83dac5cbryner                                           resolver);
151960e5277ee489960c40c50c6222606200419302ammentovai      break;
152960e5277ee489960c40c50c6222606200419302ammentovai
153960e5277ee489960c40c50c6222606200419302ammentovai    case MD_CONTEXT_PPC:
15497d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai      cpu_stackwalker = new StackwalkerPPC(system_info,
15597d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai                                           context->GetContextPPC(),
156fd38d48e6d5e56cb66b0fa0f7e25f840a83dac5cbryner                                           memory, modules, supplier,
157fd38d48e6d5e56cb66b0fa0f7e25f840a83dac5cbryner                                           resolver);
158960e5277ee489960c40c50c6222606200419302ammentovai      break;
159960e5277ee489960c40c50c6222606200419302ammentovai  }
160960e5277ee489960c40c50c6222606200419302ammentovai
161960e5277ee489960c40c50c6222606200419302ammentovai  return cpu_stackwalker;
162960e5277ee489960c40c50c6222606200419302ammentovai}
163960e5277ee489960c40c50c6222606200419302ammentovai
164960e5277ee489960c40c50c6222606200419302ammentovai
16580e98391dc7ff361355e72c24c0fb222518bcdfcmmentovai}  // namespace google_airbag
166