michael@0: // Copyright (c) 2012 Google Inc. michael@0: // All rights reserved. michael@0: // michael@0: // Redistribution and use in source and binary forms, with or without michael@0: // modification, are permitted provided that the following conditions are michael@0: // met: michael@0: // michael@0: // * Redistributions of source code must retain the above copyright michael@0: // notice, this list of conditions and the following disclaimer. michael@0: // * Redistributions in binary form must reproduce the above michael@0: // copyright notice, this list of conditions and the following disclaimer michael@0: // in the documentation and/or other materials provided with the michael@0: // distribution. michael@0: // * Neither the name of Google Inc. nor the names of its michael@0: // contributors may be used to endorse or promote products derived from michael@0: // this software without specific prior written permission. michael@0: // michael@0: // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS michael@0: // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT michael@0: // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR michael@0: // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT michael@0: // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, michael@0: // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT michael@0: // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, michael@0: // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY michael@0: // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT michael@0: // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE michael@0: // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. michael@0: michael@0: // Implementation of StackFrameSymbolizer, which encapsulates the logic of how michael@0: // SourceLineResolverInterface interacts with SymbolSupplier to fill source michael@0: // line information in a stack frame, and also looks up WindowsFrameInfo or michael@0: // CFIFrameInfo for a stack frame. michael@0: michael@0: #include "google_breakpad/processor/stack_frame_symbolizer.h" michael@0: michael@0: #include michael@0: michael@0: #include "common/scoped_ptr.h" michael@0: #include "google_breakpad/processor/code_module.h" michael@0: #include "google_breakpad/processor/code_modules.h" michael@0: #include "google_breakpad/processor/source_line_resolver_interface.h" michael@0: #include "google_breakpad/processor/stack_frame.h" michael@0: #include "google_breakpad/processor/symbol_supplier.h" michael@0: #include "google_breakpad/processor/system_info.h" michael@0: #include "processor/linked_ptr.h" michael@0: #include "common/logging.h" michael@0: michael@0: namespace google_breakpad { michael@0: michael@0: StackFrameSymbolizer::StackFrameSymbolizer( michael@0: SymbolSupplier* supplier, michael@0: SourceLineResolverInterface* resolver) : supplier_(supplier), michael@0: resolver_(resolver) { } michael@0: michael@0: StackFrameSymbolizer::SymbolizerResult StackFrameSymbolizer::FillSourceLineInfo( michael@0: const CodeModules* modules, michael@0: const SystemInfo* system_info, michael@0: StackFrame* frame) { michael@0: assert(frame); michael@0: michael@0: if (!modules) return kError; michael@0: const CodeModule* module = modules->GetModuleForAddress(frame->instruction); michael@0: if (!module) return kError; michael@0: frame->module = module; michael@0: michael@0: if (!resolver_) return kError; // no resolver. michael@0: // If module is known to have missing symbol file, return. michael@0: if (no_symbol_modules_.find(module->code_file()) != michael@0: no_symbol_modules_.end()) { michael@0: return kError; michael@0: } michael@0: michael@0: // If module is already loaded, go ahead to fill source line info and return. michael@0: if (resolver_->HasModule(frame->module)) { michael@0: resolver_->FillSourceLineInfo(frame); michael@0: return kNoError; michael@0: } michael@0: michael@0: // Module needs to fetch symbol file. First check to see if supplier exists. michael@0: if (!supplier_) { michael@0: return kError; michael@0: } michael@0: michael@0: // Start fetching symbol from supplier. michael@0: string symbol_file; michael@0: char* symbol_data = NULL; michael@0: SymbolSupplier::SymbolResult symbol_result = supplier_->GetCStringSymbolData( michael@0: module, system_info, &symbol_file, &symbol_data); michael@0: michael@0: switch (symbol_result) { michael@0: case SymbolSupplier::FOUND: { michael@0: bool load_success = resolver_->LoadModuleUsingMemoryBuffer(frame->module, michael@0: symbol_data); michael@0: if (resolver_->ShouldDeleteMemoryBufferAfterLoadModule()) { michael@0: supplier_->FreeSymbolData(module); michael@0: } michael@0: michael@0: if (load_success) { michael@0: resolver_->FillSourceLineInfo(frame); michael@0: return kNoError; michael@0: } else { michael@0: BPLOG(ERROR) << "Failed to load symbol file in resolver."; michael@0: no_symbol_modules_.insert(module->code_file()); michael@0: return kError; michael@0: } michael@0: } michael@0: michael@0: case SymbolSupplier::NOT_FOUND: michael@0: no_symbol_modules_.insert(module->code_file()); michael@0: return kError; michael@0: michael@0: case SymbolSupplier::INTERRUPT: michael@0: return kInterrupt; michael@0: michael@0: default: michael@0: BPLOG(ERROR) << "Unknown SymbolResult enum: " << symbol_result; michael@0: return kError; michael@0: } michael@0: return kError; michael@0: } michael@0: michael@0: WindowsFrameInfo* StackFrameSymbolizer::FindWindowsFrameInfo( michael@0: const StackFrame* frame) { michael@0: return resolver_ ? resolver_->FindWindowsFrameInfo(frame) : NULL; michael@0: } michael@0: michael@0: CFIFrameInfo* StackFrameSymbolizer::FindCFIFrameInfo( michael@0: const StackFrame* frame) { michael@0: return resolver_ ? resolver_->FindCFIFrameInfo(frame) : NULL; michael@0: } michael@0: michael@0: } // namespace google_breakpad