toolkit/crashreporter/google-breakpad/src/processor/stackwalker_ppc.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_ppc.cc: ppc-specific stackwalker.
    31 //
    32 // See stackwalker_ppc.h for documentation.
    33 //
    34 // Author: Mark Mentovai
    37 #include "processor/stackwalker_ppc.h"
    38 #include "google_breakpad/processor/call_stack.h"
    39 #include "google_breakpad/processor/memory_region.h"
    40 #include "google_breakpad/processor/stack_frame_cpu.h"
    41 #include "common/logging.h"
    43 namespace google_breakpad {
    46 StackwalkerPPC::StackwalkerPPC(const SystemInfo* system_info,
    47                                const MDRawContextPPC* context,
    48                                MemoryRegion* memory,
    49                                const CodeModules* modules,
    50                                StackFrameSymbolizer* resolver_helper)
    51     : Stackwalker(system_info, memory, modules, resolver_helper),
    52       context_(context) {
    53   if (memory_ && memory_->GetBase() + memory_->GetSize() - 1 > 0xffffffff) {
    54     // This implementation only covers 32-bit ppc CPUs.  The limits of the
    55     // supplied stack are invalid.  Mark memory_ = NULL, which will cause
    56     // stackwalking to fail.
    57     BPLOG(ERROR) << "Memory out of range for stackwalking: " <<
    58                     HexString(memory_->GetBase()) << "+" <<
    59                     HexString(memory_->GetSize());
    60     memory_ = NULL;
    61   }
    62 }
    65 StackFrame* StackwalkerPPC::GetContextFrame() {
    66   if (!context_) {
    67     BPLOG(ERROR) << "Can't get context frame without context";
    68     return NULL;
    69   }
    71   StackFramePPC* frame = new StackFramePPC();
    73   // The instruction pointer is stored directly in a register, so pull it
    74   // straight out of the CPU context structure.
    75   frame->context = *context_;
    76   frame->context_validity = StackFramePPC::CONTEXT_VALID_ALL;
    77   frame->trust = StackFrame::FRAME_TRUST_CONTEXT;
    78   frame->instruction = frame->context.srr0;
    80   return frame;
    81 }
    84 StackFrame* StackwalkerPPC::GetCallerFrame(const CallStack* stack,
    85                                            bool stack_scan_allowed) {
    86   if (!memory_ || !stack) {
    87     BPLOG(ERROR) << "Can't get caller frame without memory or stack";
    88     return NULL;
    89   }
    91   // The instruction pointers for previous frames are saved on the stack.
    92   // The typical ppc calling convention is for the called procedure to store
    93   // its return address in the calling procedure's stack frame at 8(%r1),
    94   // and to allocate its own stack frame by decrementing %r1 (the stack
    95   // pointer) and saving the old value of %r1 at 0(%r1).  Because the ppc has
    96   // no hardware stack, there is no distinction between the stack pointer and
    97   // frame pointer, and what is typically thought of as the frame pointer on
    98   // an x86 is usually referred to as the stack pointer on a ppc.
   100   StackFramePPC* last_frame = static_cast<StackFramePPC*>(
   101       stack->frames()->back());
   103   // A caller frame must reside higher in memory than its callee frames.
   104   // Anything else is an error, or an indication that we've reached the
   105   // end of the stack.
   106   uint32_t stack_pointer;
   107   if (!memory_->GetMemoryAtAddress(last_frame->context.gpr[1],
   108                                    &stack_pointer) ||
   109       stack_pointer <= last_frame->context.gpr[1]) {
   110     return NULL;
   111   }
   113   // Mac OS X/Darwin gives 1 as the return address from the bottom-most
   114   // frame in a stack (a thread's entry point).  I haven't found any
   115   // documentation on this, but 0 or 1 would be bogus return addresses,
   116   // so check for them here and return false (end of stack) when they're
   117   // hit to avoid having a phantom frame.
   118   uint32_t instruction;
   119   if (!memory_->GetMemoryAtAddress(stack_pointer + 8, &instruction) ||
   120       instruction <= 1) {
   121     return NULL;
   122   }
   124   StackFramePPC* frame = new StackFramePPC();
   126   frame->context = last_frame->context;
   127   frame->context.srr0 = instruction;
   128   frame->context.gpr[1] = stack_pointer;
   129   frame->context_validity = StackFramePPC::CONTEXT_VALID_SRR0 |
   130                             StackFramePPC::CONTEXT_VALID_GPR1;
   131   frame->trust = StackFrame::FRAME_TRUST_FP;
   133   // frame->context.srr0 is the return address, which is one instruction
   134   // past the branch that caused us to arrive at the callee.  Set
   135   // frame_ppc->instruction to four less than that.  Since all ppc
   136   // instructions are 4 bytes wide, this is the address of the branch
   137   // instruction.  This allows source line information to match up with the
   138   // line that contains a function call.  Callers that require the exact
   139   // return address value may access the context.srr0 field of StackFramePPC.
   140   frame->instruction = frame->context.srr0 - 4;
   142   return frame;
   143 }
   146 }  // namespace google_breakpad

mercurial