15449f746be3dc8578934a859a6a51a555fd88b49SiyangXie@gmail.com// Copyright (c) 2012 Google Inc.
25449f746be3dc8578934a859a6a51a555fd88b49SiyangXie@gmail.com// All rights reserved.
35449f746be3dc8578934a859a6a51a555fd88b49SiyangXie@gmail.com//
45449f746be3dc8578934a859a6a51a555fd88b49SiyangXie@gmail.com// Redistribution and use in source and binary forms, with or without
55449f746be3dc8578934a859a6a51a555fd88b49SiyangXie@gmail.com// modification, are permitted provided that the following conditions are
65449f746be3dc8578934a859a6a51a555fd88b49SiyangXie@gmail.com// met:
75449f746be3dc8578934a859a6a51a555fd88b49SiyangXie@gmail.com//
85449f746be3dc8578934a859a6a51a555fd88b49SiyangXie@gmail.com//     * Redistributions of source code must retain the above copyright
95449f746be3dc8578934a859a6a51a555fd88b49SiyangXie@gmail.com// notice, this list of conditions and the following disclaimer.
105449f746be3dc8578934a859a6a51a555fd88b49SiyangXie@gmail.com//     * Redistributions in binary form must reproduce the above
115449f746be3dc8578934a859a6a51a555fd88b49SiyangXie@gmail.com// copyright notice, this list of conditions and the following disclaimer
125449f746be3dc8578934a859a6a51a555fd88b49SiyangXie@gmail.com// in the documentation and/or other materials provided with the
135449f746be3dc8578934a859a6a51a555fd88b49SiyangXie@gmail.com// distribution.
145449f746be3dc8578934a859a6a51a555fd88b49SiyangXie@gmail.com//     * Neither the name of Google Inc. nor the names of its
155449f746be3dc8578934a859a6a51a555fd88b49SiyangXie@gmail.com// contributors may be used to endorse or promote products derived from
165449f746be3dc8578934a859a6a51a555fd88b49SiyangXie@gmail.com// this software without specific prior written permission.
175449f746be3dc8578934a859a6a51a555fd88b49SiyangXie@gmail.com//
185449f746be3dc8578934a859a6a51a555fd88b49SiyangXie@gmail.com// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
195449f746be3dc8578934a859a6a51a555fd88b49SiyangXie@gmail.com// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
205449f746be3dc8578934a859a6a51a555fd88b49SiyangXie@gmail.com// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
215449f746be3dc8578934a859a6a51a555fd88b49SiyangXie@gmail.com// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
225449f746be3dc8578934a859a6a51a555fd88b49SiyangXie@gmail.com// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
235449f746be3dc8578934a859a6a51a555fd88b49SiyangXie@gmail.com// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
245449f746be3dc8578934a859a6a51a555fd88b49SiyangXie@gmail.com// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
255449f746be3dc8578934a859a6a51a555fd88b49SiyangXie@gmail.com// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
265449f746be3dc8578934a859a6a51a555fd88b49SiyangXie@gmail.com// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
275449f746be3dc8578934a859a6a51a555fd88b49SiyangXie@gmail.com// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
285449f746be3dc8578934a859a6a51a555fd88b49SiyangXie@gmail.com// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
295449f746be3dc8578934a859a6a51a555fd88b49SiyangXie@gmail.com
305449f746be3dc8578934a859a6a51a555fd88b49SiyangXie@gmail.com// Implementation of StackFrameSymbolizer, which encapsulates the logic of how
315449f746be3dc8578934a859a6a51a555fd88b49SiyangXie@gmail.com// SourceLineResolverInterface interacts with SymbolSupplier to fill source
325449f746be3dc8578934a859a6a51a555fd88b49SiyangXie@gmail.com// line information in a stack frame, and also looks up WindowsFrameInfo or
335449f746be3dc8578934a859a6a51a555fd88b49SiyangXie@gmail.com// CFIFrameInfo for a stack frame.
345449f746be3dc8578934a859a6a51a555fd88b49SiyangXie@gmail.com
355449f746be3dc8578934a859a6a51a555fd88b49SiyangXie@gmail.com#include "google_breakpad/processor/stack_frame_symbolizer.h"
365449f746be3dc8578934a859a6a51a555fd88b49SiyangXie@gmail.com
375449f746be3dc8578934a859a6a51a555fd88b49SiyangXie@gmail.com#include <assert.h>
385449f746be3dc8578934a859a6a51a555fd88b49SiyangXie@gmail.com
392cc15ba4327831f917ff55b87e6d5fc3c7750085ted.mielczarek@gmail.com#include "common/scoped_ptr.h"
405449f746be3dc8578934a859a6a51a555fd88b49SiyangXie@gmail.com#include "google_breakpad/processor/code_module.h"
415449f746be3dc8578934a859a6a51a555fd88b49SiyangXie@gmail.com#include "google_breakpad/processor/code_modules.h"
425449f746be3dc8578934a859a6a51a555fd88b49SiyangXie@gmail.com#include "google_breakpad/processor/source_line_resolver_interface.h"
435449f746be3dc8578934a859a6a51a555fd88b49SiyangXie@gmail.com#include "google_breakpad/processor/stack_frame.h"
445449f746be3dc8578934a859a6a51a555fd88b49SiyangXie@gmail.com#include "google_breakpad/processor/symbol_supplier.h"
455449f746be3dc8578934a859a6a51a555fd88b49SiyangXie@gmail.com#include "google_breakpad/processor/system_info.h"
465449f746be3dc8578934a859a6a51a555fd88b49SiyangXie@gmail.com#include "processor/linked_ptr.h"
475449f746be3dc8578934a859a6a51a555fd88b49SiyangXie@gmail.com#include "processor/logging.h"
485449f746be3dc8578934a859a6a51a555fd88b49SiyangXie@gmail.com
495449f746be3dc8578934a859a6a51a555fd88b49SiyangXie@gmail.comnamespace google_breakpad {
505449f746be3dc8578934a859a6a51a555fd88b49SiyangXie@gmail.com
515449f746be3dc8578934a859a6a51a555fd88b49SiyangXie@gmail.comStackFrameSymbolizer::StackFrameSymbolizer(
525449f746be3dc8578934a859a6a51a555fd88b49SiyangXie@gmail.com    SymbolSupplier* supplier,
535449f746be3dc8578934a859a6a51a555fd88b49SiyangXie@gmail.com    SourceLineResolverInterface* resolver) : supplier_(supplier),
545449f746be3dc8578934a859a6a51a555fd88b49SiyangXie@gmail.com                                             resolver_(resolver) { }
555449f746be3dc8578934a859a6a51a555fd88b49SiyangXie@gmail.com
565449f746be3dc8578934a859a6a51a555fd88b49SiyangXie@gmail.comStackFrameSymbolizer::SymbolizerResult StackFrameSymbolizer::FillSourceLineInfo(
575449f746be3dc8578934a859a6a51a555fd88b49SiyangXie@gmail.com    const CodeModules* modules,
585449f746be3dc8578934a859a6a51a555fd88b49SiyangXie@gmail.com    const SystemInfo* system_info,
595449f746be3dc8578934a859a6a51a555fd88b49SiyangXie@gmail.com    StackFrame* frame) {
605449f746be3dc8578934a859a6a51a555fd88b49SiyangXie@gmail.com  assert(frame);
615449f746be3dc8578934a859a6a51a555fd88b49SiyangXie@gmail.com
62df4ee8ca5e8dbd4051883967191e0015b0f5d951ted.mielczarek@gmail.com  if (!modules) return kError;
635449f746be3dc8578934a859a6a51a555fd88b49SiyangXie@gmail.com  const CodeModule* module = modules->GetModuleForAddress(frame->instruction);
64df4ee8ca5e8dbd4051883967191e0015b0f5d951ted.mielczarek@gmail.com  if (!module) return kError;
655449f746be3dc8578934a859a6a51a555fd88b49SiyangXie@gmail.com  frame->module = module;
665449f746be3dc8578934a859a6a51a555fd88b49SiyangXie@gmail.com
67df4ee8ca5e8dbd4051883967191e0015b0f5d951ted.mielczarek@gmail.com  if (!resolver_) return kError;  // no resolver.
685449f746be3dc8578934a859a6a51a555fd88b49SiyangXie@gmail.com  // If module is known to have missing symbol file, return.
695449f746be3dc8578934a859a6a51a555fd88b49SiyangXie@gmail.com  if (no_symbol_modules_.find(module->code_file()) !=
705449f746be3dc8578934a859a6a51a555fd88b49SiyangXie@gmail.com      no_symbol_modules_.end()) {
71df4ee8ca5e8dbd4051883967191e0015b0f5d951ted.mielczarek@gmail.com    return kError;
725449f746be3dc8578934a859a6a51a555fd88b49SiyangXie@gmail.com  }
735449f746be3dc8578934a859a6a51a555fd88b49SiyangXie@gmail.com
745449f746be3dc8578934a859a6a51a555fd88b49SiyangXie@gmail.com  // If module is already loaded, go ahead to fill source line info and return.
755449f746be3dc8578934a859a6a51a555fd88b49SiyangXie@gmail.com  if (resolver_->HasModule(frame->module)) {
765449f746be3dc8578934a859a6a51a555fd88b49SiyangXie@gmail.com    resolver_->FillSourceLineInfo(frame);
772d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com    return resolver_->IsModuleCorrupt(frame->module) ?
782d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com        kWarningCorruptSymbols : kNoError;
795449f746be3dc8578934a859a6a51a555fd88b49SiyangXie@gmail.com  }
805449f746be3dc8578934a859a6a51a555fd88b49SiyangXie@gmail.com
815449f746be3dc8578934a859a6a51a555fd88b49SiyangXie@gmail.com  // Module needs to fetch symbol file. First check to see if supplier exists.
825449f746be3dc8578934a859a6a51a555fd88b49SiyangXie@gmail.com  if (!supplier_) {
83df4ee8ca5e8dbd4051883967191e0015b0f5d951ted.mielczarek@gmail.com    return kError;
845449f746be3dc8578934a859a6a51a555fd88b49SiyangXie@gmail.com  }
855449f746be3dc8578934a859a6a51a555fd88b49SiyangXie@gmail.com
865449f746be3dc8578934a859a6a51a555fd88b49SiyangXie@gmail.com  // Start fetching symbol from supplier.
875449f746be3dc8578934a859a6a51a555fd88b49SiyangXie@gmail.com  string symbol_file;
885449f746be3dc8578934a859a6a51a555fd88b49SiyangXie@gmail.com  char* symbol_data = NULL;
892d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com  size_t symbol_data_size;
905449f746be3dc8578934a859a6a51a555fd88b49SiyangXie@gmail.com  SymbolSupplier::SymbolResult symbol_result = supplier_->GetCStringSymbolData(
912d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com      module, system_info, &symbol_file, &symbol_data, &symbol_data_size);
925449f746be3dc8578934a859a6a51a555fd88b49SiyangXie@gmail.com
935449f746be3dc8578934a859a6a51a555fd88b49SiyangXie@gmail.com  switch (symbol_result) {
945449f746be3dc8578934a859a6a51a555fd88b49SiyangXie@gmail.com    case SymbolSupplier::FOUND: {
952d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com      bool load_success = resolver_->LoadModuleUsingMemoryBuffer(
962d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com          frame->module,
972d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com          symbol_data,
982d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com          symbol_data_size);
995449f746be3dc8578934a859a6a51a555fd88b49SiyangXie@gmail.com      if (resolver_->ShouldDeleteMemoryBufferAfterLoadModule()) {
1005449f746be3dc8578934a859a6a51a555fd88b49SiyangXie@gmail.com        supplier_->FreeSymbolData(module);
1015449f746be3dc8578934a859a6a51a555fd88b49SiyangXie@gmail.com      }
1025449f746be3dc8578934a859a6a51a555fd88b49SiyangXie@gmail.com
1035449f746be3dc8578934a859a6a51a555fd88b49SiyangXie@gmail.com      if (load_success) {
1045449f746be3dc8578934a859a6a51a555fd88b49SiyangXie@gmail.com        resolver_->FillSourceLineInfo(frame);
1052d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com        return resolver_->IsModuleCorrupt(frame->module) ?
1062d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com            kWarningCorruptSymbols : kNoError;
1075449f746be3dc8578934a859a6a51a555fd88b49SiyangXie@gmail.com      } else {
1085449f746be3dc8578934a859a6a51a555fd88b49SiyangXie@gmail.com        BPLOG(ERROR) << "Failed to load symbol file in resolver.";
1095449f746be3dc8578934a859a6a51a555fd88b49SiyangXie@gmail.com        no_symbol_modules_.insert(module->code_file());
110df4ee8ca5e8dbd4051883967191e0015b0f5d951ted.mielczarek@gmail.com        return kError;
1115449f746be3dc8578934a859a6a51a555fd88b49SiyangXie@gmail.com      }
1125449f746be3dc8578934a859a6a51a555fd88b49SiyangXie@gmail.com    }
1135449f746be3dc8578934a859a6a51a555fd88b49SiyangXie@gmail.com
1145449f746be3dc8578934a859a6a51a555fd88b49SiyangXie@gmail.com    case SymbolSupplier::NOT_FOUND:
1155449f746be3dc8578934a859a6a51a555fd88b49SiyangXie@gmail.com      no_symbol_modules_.insert(module->code_file());
116df4ee8ca5e8dbd4051883967191e0015b0f5d951ted.mielczarek@gmail.com      return kError;
1175449f746be3dc8578934a859a6a51a555fd88b49SiyangXie@gmail.com
1185449f746be3dc8578934a859a6a51a555fd88b49SiyangXie@gmail.com    case SymbolSupplier::INTERRUPT:
119df4ee8ca5e8dbd4051883967191e0015b0f5d951ted.mielczarek@gmail.com      return kInterrupt;
120bc76f34e15569a891c2f3e43435d7837813c0be9SiyangXie@gmail.com
121bc76f34e15569a891c2f3e43435d7837813c0be9SiyangXie@gmail.com    default:
122bc76f34e15569a891c2f3e43435d7837813c0be9SiyangXie@gmail.com      BPLOG(ERROR) << "Unknown SymbolResult enum: " << symbol_result;
123df4ee8ca5e8dbd4051883967191e0015b0f5d951ted.mielczarek@gmail.com      return kError;
1245449f746be3dc8578934a859a6a51a555fd88b49SiyangXie@gmail.com  }
125df4ee8ca5e8dbd4051883967191e0015b0f5d951ted.mielczarek@gmail.com  return kError;
1265449f746be3dc8578934a859a6a51a555fd88b49SiyangXie@gmail.com}
1275449f746be3dc8578934a859a6a51a555fd88b49SiyangXie@gmail.com
1285449f746be3dc8578934a859a6a51a555fd88b49SiyangXie@gmail.comWindowsFrameInfo* StackFrameSymbolizer::FindWindowsFrameInfo(
1295449f746be3dc8578934a859a6a51a555fd88b49SiyangXie@gmail.com    const StackFrame* frame) {
1305449f746be3dc8578934a859a6a51a555fd88b49SiyangXie@gmail.com  return resolver_ ? resolver_->FindWindowsFrameInfo(frame) : NULL;
1315449f746be3dc8578934a859a6a51a555fd88b49SiyangXie@gmail.com}
1325449f746be3dc8578934a859a6a51a555fd88b49SiyangXie@gmail.com
1335449f746be3dc8578934a859a6a51a555fd88b49SiyangXie@gmail.comCFIFrameInfo* StackFrameSymbolizer::FindCFIFrameInfo(
1345449f746be3dc8578934a859a6a51a555fd88b49SiyangXie@gmail.com    const StackFrame* frame) {
1355449f746be3dc8578934a859a6a51a555fd88b49SiyangXie@gmail.com  return resolver_ ? resolver_->FindCFIFrameInfo(frame) : NULL;
1365449f746be3dc8578934a859a6a51a555fd88b49SiyangXie@gmail.com}
1375449f746be3dc8578934a859a6a51a555fd88b49SiyangXie@gmail.com
1385449f746be3dc8578934a859a6a51a555fd88b49SiyangXie@gmail.com}  // namespace google_breakpad
139