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 49 namespace google_breakpad { 50 51 StackFrameSymbolizer::StackFrameSymbolizer( 52 SymbolSupplier* supplier, 53 SourceLineResolverInterface* resolver) : supplier_(supplier), 54 resolver_(resolver) { } 55 56 StackFrameSymbolizer::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 128 WindowsFrameInfo* StackFrameSymbolizer::FindWindowsFrameInfo( 129 const StackFrame* frame) { 130 return resolver_ ? resolver_->FindWindowsFrameInfo(frame) : NULL; 131 } 132 133 CFIFrameInfo* StackFrameSymbolizer::FindCFIFrameInfo( 134 const StackFrame* frame) { 135 return resolver_ ? resolver_->FindCFIFrameInfo(frame) : NULL; 136 } 137 138 } // namespace google_breakpad 139