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