1// Copyright (c) 2012 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// Implementation of StackFrameSymbolizer, which encapsulates the logic of how 31// SourceLineResolverInterface interacts with SymbolSupplier to fill source 32// line information in a stack frame, and also looks up WindowsFrameInfo or 33// CFIFrameInfo for a stack frame. 34 35#include "google_breakpad/processor/stack_frame_symbolizer.h" 36 37#include <assert.h> 38 39#include "common/scoped_ptr.h" 40#include "google_breakpad/processor/code_module.h" 41#include "google_breakpad/processor/code_modules.h" 42#include "google_breakpad/processor/source_line_resolver_interface.h" 43#include "google_breakpad/processor/stack_frame.h" 44#include "google_breakpad/processor/symbol_supplier.h" 45#include "google_breakpad/processor/system_info.h" 46#include "processor/linked_ptr.h" 47#include "processor/logging.h" 48 49namespace google_breakpad { 50 51StackFrameSymbolizer::StackFrameSymbolizer( 52 SymbolSupplier* supplier, 53 SourceLineResolverInterface* resolver) : supplier_(supplier), 54 resolver_(resolver) { } 55 56StackFrameSymbolizer::SymbolizerResult StackFrameSymbolizer::FillSourceLineInfo( 57 const CodeModules* modules, 58 const SystemInfo* system_info, 59 StackFrame* frame) { 60 assert(frame); 61 62 if (!modules) return kError; 63 const CodeModule* module = modules->GetModuleForAddress(frame->instruction); 64 if (!module) return kError; 65 frame->module = module; 66 67 if (!resolver_) return kError; // no resolver. 68 // If module is known to have missing symbol file, return. 69 if (no_symbol_modules_.find(module->code_file()) != 70 no_symbol_modules_.end()) { 71 return kError; 72 } 73 74 // If module is already loaded, go ahead to fill source line info and return. 75 if (resolver_->HasModule(frame->module)) { 76 resolver_->FillSourceLineInfo(frame); 77 return resolver_->IsModuleCorrupt(frame->module) ? 78 kWarningCorruptSymbols : kNoError; 79 } 80 81 // Module needs to fetch symbol file. First check to see if supplier exists. 82 if (!supplier_) { 83 return kError; 84 } 85 86 // Start fetching symbol from supplier. 87 string symbol_file; 88 char* symbol_data = NULL; 89 size_t symbol_data_size; 90 SymbolSupplier::SymbolResult symbol_result = supplier_->GetCStringSymbolData( 91 module, system_info, &symbol_file, &symbol_data, &symbol_data_size); 92 93 switch (symbol_result) { 94 case SymbolSupplier::FOUND: { 95 bool load_success = resolver_->LoadModuleUsingMemoryBuffer( 96 frame->module, 97 symbol_data, 98 symbol_data_size); 99 if (resolver_->ShouldDeleteMemoryBufferAfterLoadModule()) { 100 supplier_->FreeSymbolData(module); 101 } 102 103 if (load_success) { 104 resolver_->FillSourceLineInfo(frame); 105 return resolver_->IsModuleCorrupt(frame->module) ? 106 kWarningCorruptSymbols : kNoError; 107 } else { 108 BPLOG(ERROR) << "Failed to load symbol file in resolver."; 109 no_symbol_modules_.insert(module->code_file()); 110 return kError; 111 } 112 } 113 114 case SymbolSupplier::NOT_FOUND: 115 no_symbol_modules_.insert(module->code_file()); 116 return kError; 117 118 case SymbolSupplier::INTERRUPT: 119 return kInterrupt; 120 121 default: 122 BPLOG(ERROR) << "Unknown SymbolResult enum: " << symbol_result; 123 return kError; 124 } 125 return kError; 126} 127 128WindowsFrameInfo* StackFrameSymbolizer::FindWindowsFrameInfo( 129 const StackFrame* frame) { 130 return resolver_ ? resolver_->FindWindowsFrameInfo(frame) : NULL; 131} 132 133CFIFrameInfo* StackFrameSymbolizer::FindCFIFrameInfo( 134 const StackFrame* frame) { 135 return resolver_ ? resolver_->FindCFIFrameInfo(frame) : NULL; 136} 137 138} // namespace google_breakpad 139