/ src / processor / stack_frame_symbolizer.cc
stack_frame_symbolizer.cc
  1  // Copyright 2012 Google LLC
  2  //
  3  // Redistribution and use in source and binary forms, with or without
  4  // modification, are permitted provided that the following conditions are
  5  // met:
  6  //
  7  //     * Redistributions of source code must retain the above copyright
  8  // notice, this list of conditions and the following disclaimer.
  9  //     * Redistributions in binary form must reproduce the above
 10  // copyright notice, this list of conditions and the following disclaimer
 11  // in the documentation and/or other materials provided with the
 12  // distribution.
 13  //     * Neither the name of Google LLC nor the names of its
 14  // contributors may be used to endorse or promote products derived from
 15  // this software without specific prior written permission.
 16  //
 17  // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 18  // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 19  // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 20  // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 21  // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 22  // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 23  // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 24  // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 25  // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 26  // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 27  // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 28  
 29  // Implementation of StackFrameSymbolizer, which encapsulates the logic of how
 30  // SourceLineResolverInterface interacts with SymbolSupplier to fill source
 31  // line information in a stack frame, and also looks up WindowsFrameInfo or
 32  // CFIFrameInfo for a stack frame.
 33  
 34  #ifdef HAVE_CONFIG_H
 35  #include <config.h>  // Must come first
 36  #endif
 37  
 38  #include "google_breakpad/processor/stack_frame_symbolizer.h"
 39  
 40  #include <assert.h>
 41  
 42  #include "common/scoped_ptr.h"
 43  #include "google_breakpad/processor/code_module.h"
 44  #include "google_breakpad/processor/code_modules.h"
 45  #include "google_breakpad/processor/source_line_resolver_interface.h"
 46  #include "google_breakpad/processor/stack_frame.h"
 47  #include "google_breakpad/processor/symbol_supplier.h"
 48  #include "google_breakpad/processor/system_info.h"
 49  #include "processor/linked_ptr.h"
 50  #include "processor/logging.h"
 51  
 52  namespace google_breakpad {
 53  
 54  StackFrameSymbolizer::StackFrameSymbolizer(
 55      SymbolSupplier* supplier,
 56      SourceLineResolverInterface* resolver) : supplier_(supplier),
 57                                               resolver_(resolver) { }
 58  
 59  StackFrameSymbolizer::SymbolizerResult StackFrameSymbolizer::FillSourceLineInfo(
 60      const CodeModules* modules,
 61      const CodeModules* unloaded_modules,
 62      const SystemInfo* system_info,
 63      StackFrame* frame,
 64      std::deque<std::unique_ptr<StackFrame>>* inlined_frames) {
 65    assert(frame);
 66  
 67    const CodeModule* module = NULL;
 68    if (modules) {
 69      module = modules->GetModuleForAddress(frame->instruction);
 70    }
 71    if (!module && unloaded_modules) {
 72      module = unloaded_modules->GetModuleForAddress(frame->instruction);
 73    }
 74  
 75    if (!module) return kError;
 76    frame->module = module;
 77  
 78    if (!resolver_) return kError;  // no resolver.
 79    // If module is known to have missing symbol file, return.
 80    if (no_symbol_modules_.find(module->code_file()) !=
 81        no_symbol_modules_.end()) {
 82      return kError;
 83    }
 84  
 85    // If module is already loaded, go ahead to fill source line info and return.
 86    if (resolver_->HasModule(frame->module)) {
 87      resolver_->FillSourceLineInfo(frame, inlined_frames);
 88      return resolver_->IsModuleCorrupt(frame->module) ?
 89          kWarningCorruptSymbols : kNoError;
 90    }
 91  
 92    // Module needs to fetch symbol file. First check to see if supplier exists.
 93    if (!supplier_) {
 94      return kError;
 95    }
 96  
 97    // Start fetching symbol from supplier.
 98    string symbol_file;
 99    char* symbol_data = NULL;
100    size_t symbol_data_size;
101    SymbolSupplier::SymbolResult symbol_result = supplier_->GetCStringSymbolData(
102        module, system_info, &symbol_file, &symbol_data, &symbol_data_size);
103  
104    switch (symbol_result) {
105      case SymbolSupplier::FOUND: {
106        bool load_success = resolver_->LoadModuleUsingMemoryBuffer(
107            frame->module,
108            symbol_data,
109            symbol_data_size);
110        if (resolver_->ShouldDeleteMemoryBufferAfterLoadModule()) {
111          supplier_->FreeSymbolData(module);
112        }
113  
114        if (load_success) {
115          resolver_->FillSourceLineInfo(frame, inlined_frames);
116          return resolver_->IsModuleCorrupt(frame->module) ?
117              kWarningCorruptSymbols : kNoError;
118        } else {
119          BPLOG(ERROR) << "Failed to load symbol file in resolver.";
120          no_symbol_modules_.insert(module->code_file());
121          return kError;
122        }
123      }
124  
125      case SymbolSupplier::NOT_FOUND:
126        no_symbol_modules_.insert(module->code_file());
127        return kError;
128  
129      case SymbolSupplier::INTERRUPT:
130        return kInterrupt;
131  
132      default:
133        BPLOG(ERROR) << "Unknown SymbolResult enum: " << symbol_result;
134        return kError;
135    }
136    return kError;
137  }
138  
139  WindowsFrameInfo* StackFrameSymbolizer::FindWindowsFrameInfo(
140      const StackFrame* frame) {
141    return resolver_ ? resolver_->FindWindowsFrameInfo(frame) : NULL;
142  }
143  
144  CFIFrameInfo* StackFrameSymbolizer::FindCFIFrameInfo(
145      const StackFrame* frame) {
146    return resolver_ ? resolver_->FindCFIFrameInfo(frame) : NULL;
147  }
148  
149  }  // namespace google_breakpad