toolkit/crashreporter/google-breakpad/src/processor/stackwalker.cc

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 // Copyright (c) 2010 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.
    30 // stackwalker.cc: Generic stackwalker.
    31 //
    32 // See stackwalker.h for documentation.
    33 //
    34 // Author: Mark Mentovai
    36 #include "google_breakpad/processor/stackwalker.h"
    38 #include <assert.h>
    40 #include "common/scoped_ptr.h"
    41 #include "google_breakpad/processor/call_stack.h"
    42 #include "google_breakpad/processor/code_module.h"
    43 #include "google_breakpad/processor/code_modules.h"
    44 #include "google_breakpad/processor/minidump.h"
    45 #include "google_breakpad/processor/stack_frame.h"
    46 #include "google_breakpad/processor/stack_frame_symbolizer.h"
    47 #include "google_breakpad/processor/system_info.h"
    48 #include "processor/linked_ptr.h"
    49 #include "common/logging.h"
    50 #include "processor/stackwalker_ppc.h"
    51 #include "processor/stackwalker_sparc.h"
    52 #include "processor/stackwalker_x86.h"
    53 #include "processor/stackwalker_amd64.h"
    54 #include "processor/stackwalker_arm.h"
    56 namespace google_breakpad {
    58 const int Stackwalker::kRASearchWords = 30;
    60 uint32_t Stackwalker::max_frames_ = 1024;
    61 bool Stackwalker::max_frames_set_ = false;
    63 uint32_t Stackwalker::max_frames_scanned_ = 1024;
    65 Stackwalker::Stackwalker(const SystemInfo* system_info,
    66                          MemoryRegion* memory,
    67                          const CodeModules* modules,
    68                          StackFrameSymbolizer* frame_symbolizer)
    69     : system_info_(system_info),
    70       memory_(memory),
    71       modules_(modules),
    72       frame_symbolizer_(frame_symbolizer) {
    73   assert(frame_symbolizer_);
    74 }
    77 bool Stackwalker::Walk(CallStack* stack,
    78                        vector<const CodeModule*>* modules_without_symbols) {
    79   BPLOG_IF(ERROR, !stack) << "Stackwalker::Walk requires |stack|";
    80   assert(stack);
    81   stack->Clear();
    83   BPLOG_IF(ERROR, !modules_without_symbols) << "Stackwalker::Walk requires "
    84                                             << "|modules_without_symbols|";
    85   assert(modules_without_symbols);
    87   // Begin with the context frame, and keep getting callers until there are
    88   // no more.
    90   // Keep track of the number of scanned or otherwise dubious frames seen
    91   // so far, as the caller may have set a limit.
    92   uint32_t n_scanned_frames = 0;
    94   // Take ownership of the pointer returned by GetContextFrame.
    95   scoped_ptr<StackFrame> frame(GetContextFrame());
    97   while (frame.get()) {
    98     // frame already contains a good frame with properly set instruction and
    99     // frame_pointer fields.  The frame structure comes from either the
   100     // context frame (above) or a caller frame (below).
   102     // Resolve the module information, if a module map was provided.
   103     StackFrameSymbolizer::SymbolizerResult symbolizer_result =
   104         frame_symbolizer_->FillSourceLineInfo(modules_, system_info_,
   105                                              frame.get());
   106     if (symbolizer_result == StackFrameSymbolizer::kInterrupt) {
   107       BPLOG(INFO) << "Stack walk is interrupted.";
   108       return false;
   109     }
   111     // Keep track of modules that have no symbols.
   112     if (symbolizer_result == StackFrameSymbolizer::kError &&
   113         frame->module != NULL) {
   114       bool found = false;
   115       vector<const CodeModule*>::iterator iter;
   116       for (iter = modules_without_symbols->begin();
   117            iter != modules_without_symbols->end();
   118            ++iter) {
   119         if (*iter == frame->module) {
   120           found = true;
   121           break;
   122         }
   123       }
   124       if (!found) {
   125         BPLOG(INFO) << "Couldn't load symbols for: "
   126                     << frame->module->debug_file() << "|"
   127                     << frame->module->debug_identifier();
   128         modules_without_symbols->push_back(frame->module);
   129       }
   130     }
   132     // Keep track of the number of dubious frames so far.
   133     switch (frame.get()->trust) {
   134        case StackFrame::FRAME_TRUST_NONE:
   135        case StackFrame::FRAME_TRUST_SCAN:
   136        case StackFrame::FRAME_TRUST_CFI_SCAN:
   137          n_scanned_frames++;
   138          break;
   139       default:
   140         break;
   141     }
   143     // Add the frame to the call stack.  Relinquish the ownership claim
   144     // over the frame, because the stack now owns it.
   145     stack->frames_.push_back(frame.release());
   146     if (stack->frames_.size() > max_frames_) {
   147       // Only emit an error message in the case where the limit that we
   148       // reached is the default limit, not set by the user.
   149       if (!max_frames_set_)
   150         BPLOG(ERROR) << "The stack is over " << max_frames_ << " frames.";
   151       break;
   152     }
   154     // Get the next frame and take ownership.
   155     bool stack_scan_allowed = n_scanned_frames < max_frames_scanned_;
   156     frame.reset(GetCallerFrame(stack, stack_scan_allowed));
   157   }
   159   return true;
   160 }
   163 // static
   164 Stackwalker* Stackwalker::StackwalkerForCPU(
   165     const SystemInfo* system_info,
   166     MinidumpContext* context,
   167     MemoryRegion* memory,
   168     const CodeModules* modules,
   169     StackFrameSymbolizer* frame_symbolizer) {
   170   if (!context) {
   171     BPLOG(ERROR) << "Can't choose a stackwalker implementation without context";
   172     return NULL;
   173   }
   175   Stackwalker* cpu_stackwalker = NULL;
   177   uint32_t cpu = context->GetContextCPU();
   178   switch (cpu) {
   179     case MD_CONTEXT_X86:
   180       cpu_stackwalker = new StackwalkerX86(system_info,
   181                                            context->GetContextX86(),
   182                                            memory, modules, frame_symbolizer);
   183       break;
   185     case MD_CONTEXT_PPC:
   186       cpu_stackwalker = new StackwalkerPPC(system_info,
   187                                            context->GetContextPPC(),
   188                                            memory, modules, frame_symbolizer);
   189       break;
   191     case MD_CONTEXT_AMD64:
   192       cpu_stackwalker = new StackwalkerAMD64(system_info,
   193                                              context->GetContextAMD64(),
   194                                              memory, modules, frame_symbolizer);
   195       break;
   197     case MD_CONTEXT_SPARC:
   198       cpu_stackwalker = new StackwalkerSPARC(system_info,
   199                                              context->GetContextSPARC(),
   200                                              memory, modules, frame_symbolizer);
   201       break;
   203     case MD_CONTEXT_ARM:
   204       int fp_register = -1;
   205       if (system_info->os_short == "ios")
   206         fp_register = MD_CONTEXT_ARM_REG_IOS_FP;
   207       cpu_stackwalker = new StackwalkerARM(system_info,
   208                                            context->GetContextARM(),
   209                                            fp_register, memory, modules,
   210                                            frame_symbolizer);
   211       break;
   212   }
   214   BPLOG_IF(ERROR, !cpu_stackwalker) << "Unknown CPU type " << HexString(cpu) <<
   215                                        ", can't choose a stackwalker "
   216                                        "implementation";
   217   return cpu_stackwalker;
   218 }
   220 bool Stackwalker::InstructionAddressSeemsValid(uint64_t address) {
   221   StackFrame frame;
   222   frame.instruction = address;
   223   StackFrameSymbolizer::SymbolizerResult symbolizer_result =
   224       frame_symbolizer_->FillSourceLineInfo(modules_, system_info_, &frame);
   226   if (!frame.module) {
   227     // not inside any loaded module
   228     return false;
   229   }
   231   if (!frame_symbolizer_->HasImplementation()) {
   232     // No valid implementation to symbolize stack frame, but the address is
   233     // within a known module.
   234     return true;
   235   }
   237   if (symbolizer_result != StackFrameSymbolizer::kNoError) {
   238     // Some error occurred during symbolization, but the address is within a
   239     // known module
   240     return true;
   241   }
   243   return !frame.function_name.empty();
   244 }
   246 }  // namespace google_breakpad

mercurial