183e085b7a331c96237cf8e814f97b3ef4c36a70fjimblandy// Copyright (c) 2010 Google Inc. 2960e5277ee489960c40c50c6222606200419302ammentovai// All rights reserved. 3960e5277ee489960c40c50c6222606200419302ammentovai// 4960e5277ee489960c40c50c6222606200419302ammentovai// Redistribution and use in source and binary forms, with or without 5960e5277ee489960c40c50c6222606200419302ammentovai// modification, are permitted provided that the following conditions are 6960e5277ee489960c40c50c6222606200419302ammentovai// met: 7960e5277ee489960c40c50c6222606200419302ammentovai// 8960e5277ee489960c40c50c6222606200419302ammentovai// * Redistributions of source code must retain the above copyright 9960e5277ee489960c40c50c6222606200419302ammentovai// notice, this list of conditions and the following disclaimer. 10960e5277ee489960c40c50c6222606200419302ammentovai// * Redistributions in binary form must reproduce the above 11960e5277ee489960c40c50c6222606200419302ammentovai// copyright notice, this list of conditions and the following disclaimer 12960e5277ee489960c40c50c6222606200419302ammentovai// in the documentation and/or other materials provided with the 13960e5277ee489960c40c50c6222606200419302ammentovai// distribution. 14960e5277ee489960c40c50c6222606200419302ammentovai// * Neither the name of Google Inc. nor the names of its 15960e5277ee489960c40c50c6222606200419302ammentovai// contributors may be used to endorse or promote products derived from 16960e5277ee489960c40c50c6222606200419302ammentovai// this software without specific prior written permission. 17960e5277ee489960c40c50c6222606200419302ammentovai// 18960e5277ee489960c40c50c6222606200419302ammentovai// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19960e5277ee489960c40c50c6222606200419302ammentovai// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20960e5277ee489960c40c50c6222606200419302ammentovai// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21960e5277ee489960c40c50c6222606200419302ammentovai// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22960e5277ee489960c40c50c6222606200419302ammentovai// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23960e5277ee489960c40c50c6222606200419302ammentovai// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24960e5277ee489960c40c50c6222606200419302ammentovai// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25960e5277ee489960c40c50c6222606200419302ammentovai// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26960e5277ee489960c40c50c6222606200419302ammentovai// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27960e5277ee489960c40c50c6222606200419302ammentovai// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28960e5277ee489960c40c50c6222606200419302ammentovai// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29960e5277ee489960c40c50c6222606200419302ammentovai 30960e5277ee489960c40c50c6222606200419302ammentovai// stackwalker_ppc.cc: ppc-specific stackwalker. 31960e5277ee489960c40c50c6222606200419302ammentovai// 32960e5277ee489960c40c50c6222606200419302ammentovai// See stackwalker_ppc.h for documentation. 33960e5277ee489960c40c50c6222606200419302ammentovai// 34960e5277ee489960c40c50c6222606200419302ammentovai// Author: Mark Mentovai 35960e5277ee489960c40c50c6222606200419302ammentovai 36960e5277ee489960c40c50c6222606200419302ammentovai 37960e5277ee489960c40c50c6222606200419302ammentovai#include "processor/stackwalker_ppc.h" 38e5dc60822e5938fea2ae892ccddb906641ba174emmentovai#include "google_breakpad/processor/call_stack.h" 39e5dc60822e5938fea2ae892ccddb906641ba174emmentovai#include "google_breakpad/processor/memory_region.h" 40e5dc60822e5938fea2ae892ccddb906641ba174emmentovai#include "google_breakpad/processor/stack_frame_cpu.h" 4165571f17edb82d122b5f6dc741bd7d4b9e315e1bmmentovai#include "processor/logging.h" 42960e5277ee489960c40c50c6222606200419302ammentovai 43e5dc60822e5938fea2ae892ccddb906641ba174emmentovainamespace google_breakpad { 44960e5277ee489960c40c50c6222606200419302ammentovai 45960e5277ee489960c40c50c6222606200419302ammentovai 469753aff85a9a20dbe294529b4184d9686ec42cddSiyangXie@gmail.comStackwalkerPPC::StackwalkerPPC(const SystemInfo* system_info, 479753aff85a9a20dbe294529b4184d9686ec42cddSiyangXie@gmail.com const MDRawContextPPC* context, 489753aff85a9a20dbe294529b4184d9686ec42cddSiyangXie@gmail.com MemoryRegion* memory, 499753aff85a9a20dbe294529b4184d9686ec42cddSiyangXie@gmail.com const CodeModules* modules, 509753aff85a9a20dbe294529b4184d9686ec42cddSiyangXie@gmail.com StackFrameSymbolizer* resolver_helper) 519753aff85a9a20dbe294529b4184d9686ec42cddSiyangXie@gmail.com : Stackwalker(system_info, memory, modules, resolver_helper), 52960e5277ee489960c40c50c6222606200419302ammentovai context_(context) { 53e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com if (memory_ && memory_->GetBase() + memory_->GetSize() - 1 > 0xffffffff) { 54960e5277ee489960c40c50c6222606200419302ammentovai // This implementation only covers 32-bit ppc CPUs. The limits of the 55960e5277ee489960c40c50c6222606200419302ammentovai // supplied stack are invalid. Mark memory_ = NULL, which will cause 56960e5277ee489960c40c50c6222606200419302ammentovai // stackwalking to fail. 5765571f17edb82d122b5f6dc741bd7d4b9e315e1bmmentovai BPLOG(ERROR) << "Memory out of range for stackwalking: " << 5865571f17edb82d122b5f6dc741bd7d4b9e315e1bmmentovai HexString(memory_->GetBase()) << "+" << 5965571f17edb82d122b5f6dc741bd7d4b9e315e1bmmentovai HexString(memory_->GetSize()); 60960e5277ee489960c40c50c6222606200419302ammentovai memory_ = NULL; 61960e5277ee489960c40c50c6222606200419302ammentovai } 62960e5277ee489960c40c50c6222606200419302ammentovai} 63960e5277ee489960c40c50c6222606200419302ammentovai 64960e5277ee489960c40c50c6222606200419302ammentovai 65246f4068280b5b191303ff13671e43a0522987demmentovaiStackFrame* StackwalkerPPC::GetContextFrame() { 66e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com if (!context_) { 67e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com BPLOG(ERROR) << "Can't get context frame without context"; 68246f4068280b5b191303ff13671e43a0522987demmentovai return NULL; 6965571f17edb82d122b5f6dc741bd7d4b9e315e1bmmentovai } 70960e5277ee489960c40c50c6222606200419302ammentovai 719753aff85a9a20dbe294529b4184d9686ec42cddSiyangXie@gmail.com StackFramePPC* frame = new StackFramePPC(); 72960e5277ee489960c40c50c6222606200419302ammentovai 73246f4068280b5b191303ff13671e43a0522987demmentovai // The instruction pointer is stored directly in a register, so pull it 74246f4068280b5b191303ff13671e43a0522987demmentovai // straight out of the CPU context structure. 75246f4068280b5b191303ff13671e43a0522987demmentovai frame->context = *context_; 76246f4068280b5b191303ff13671e43a0522987demmentovai frame->context_validity = StackFramePPC::CONTEXT_VALID_ALL; 778c33b3e9c95a67a9bb06c033d5d4c28d9a55168bted.mielczarek frame->trust = StackFrame::FRAME_TRUST_CONTEXT; 78246f4068280b5b191303ff13671e43a0522987demmentovai frame->instruction = frame->context.srr0; 79960e5277ee489960c40c50c6222606200419302ammentovai 80246f4068280b5b191303ff13671e43a0522987demmentovai return frame; 81246f4068280b5b191303ff13671e43a0522987demmentovai} 82960e5277ee489960c40c50c6222606200419302ammentovai 83960e5277ee489960c40c50c6222606200419302ammentovai 8442b91fbbf30f8a6d900d1fb97e96394dbb363890ted.mielczarek@gmail.comStackFrame* StackwalkerPPC::GetCallerFrame(const CallStack* stack, 8542b91fbbf30f8a6d900d1fb97e96394dbb363890ted.mielczarek@gmail.com bool stack_scan_allowed) { 8665571f17edb82d122b5f6dc741bd7d4b9e315e1bmmentovai if (!memory_ || !stack) { 8765571f17edb82d122b5f6dc741bd7d4b9e315e1bmmentovai BPLOG(ERROR) << "Can't get caller frame without memory or stack"; 88246f4068280b5b191303ff13671e43a0522987demmentovai return NULL; 8965571f17edb82d122b5f6dc741bd7d4b9e315e1bmmentovai } 90960e5277ee489960c40c50c6222606200419302ammentovai 91246f4068280b5b191303ff13671e43a0522987demmentovai // The instruction pointers for previous frames are saved on the stack. 92246f4068280b5b191303ff13671e43a0522987demmentovai // The typical ppc calling convention is for the called procedure to store 93246f4068280b5b191303ff13671e43a0522987demmentovai // its return address in the calling procedure's stack frame at 8(%r1), 94246f4068280b5b191303ff13671e43a0522987demmentovai // and to allocate its own stack frame by decrementing %r1 (the stack 95246f4068280b5b191303ff13671e43a0522987demmentovai // pointer) and saving the old value of %r1 at 0(%r1). Because the ppc has 96246f4068280b5b191303ff13671e43a0522987demmentovai // no hardware stack, there is no distinction between the stack pointer and 97246f4068280b5b191303ff13671e43a0522987demmentovai // frame pointer, and what is typically thought of as the frame pointer on 98246f4068280b5b191303ff13671e43a0522987demmentovai // an x86 is usually referred to as the stack pointer on a ppc. 99960e5277ee489960c40c50c6222606200419302ammentovai 1009753aff85a9a20dbe294529b4184d9686ec42cddSiyangXie@gmail.com StackFramePPC* last_frame = static_cast<StackFramePPC*>( 101246f4068280b5b191303ff13671e43a0522987demmentovai stack->frames()->back()); 102960e5277ee489960c40c50c6222606200419302ammentovai 103960e5277ee489960c40c50c6222606200419302ammentovai // A caller frame must reside higher in memory than its callee frames. 104960e5277ee489960c40c50c6222606200419302ammentovai // Anything else is an error, or an indication that we've reached the 105960e5277ee489960c40c50c6222606200419302ammentovai // end of the stack. 1066162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com uint32_t stack_pointer; 107246f4068280b5b191303ff13671e43a0522987demmentovai if (!memory_->GetMemoryAtAddress(last_frame->context.gpr[1], 108246f4068280b5b191303ff13671e43a0522987demmentovai &stack_pointer) || 109246f4068280b5b191303ff13671e43a0522987demmentovai stack_pointer <= last_frame->context.gpr[1]) { 110246f4068280b5b191303ff13671e43a0522987demmentovai return NULL; 111246f4068280b5b191303ff13671e43a0522987demmentovai } 112960e5277ee489960c40c50c6222606200419302ammentovai 113960e5277ee489960c40c50c6222606200419302ammentovai // Mac OS X/Darwin gives 1 as the return address from the bottom-most 114960e5277ee489960c40c50c6222606200419302ammentovai // frame in a stack (a thread's entry point). I haven't found any 115960e5277ee489960c40c50c6222606200419302ammentovai // documentation on this, but 0 or 1 would be bogus return addresses, 116960e5277ee489960c40c50c6222606200419302ammentovai // so check for them here and return false (end of stack) when they're 117960e5277ee489960c40c50c6222606200419302ammentovai // hit to avoid having a phantom frame. 1186162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com uint32_t instruction; 119246f4068280b5b191303ff13671e43a0522987demmentovai if (!memory_->GetMemoryAtAddress(stack_pointer + 8, &instruction) || 120246f4068280b5b191303ff13671e43a0522987demmentovai instruction <= 1) { 121246f4068280b5b191303ff13671e43a0522987demmentovai return NULL; 122246f4068280b5b191303ff13671e43a0522987demmentovai } 123246f4068280b5b191303ff13671e43a0522987demmentovai 1249753aff85a9a20dbe294529b4184d9686ec42cddSiyangXie@gmail.com StackFramePPC* frame = new StackFramePPC(); 125246f4068280b5b191303ff13671e43a0522987demmentovai 126246f4068280b5b191303ff13671e43a0522987demmentovai frame->context = last_frame->context; 127246f4068280b5b191303ff13671e43a0522987demmentovai frame->context.srr0 = instruction; 128246f4068280b5b191303ff13671e43a0522987demmentovai frame->context.gpr[1] = stack_pointer; 129246f4068280b5b191303ff13671e43a0522987demmentovai frame->context_validity = StackFramePPC::CONTEXT_VALID_SRR0 | 130246f4068280b5b191303ff13671e43a0522987demmentovai StackFramePPC::CONTEXT_VALID_GPR1; 1318c33b3e9c95a67a9bb06c033d5d4c28d9a55168bted.mielczarek frame->trust = StackFrame::FRAME_TRUST_FP; 132960e5277ee489960c40c50c6222606200419302ammentovai 133246f4068280b5b191303ff13671e43a0522987demmentovai // frame->context.srr0 is the return address, which is one instruction 134246f4068280b5b191303ff13671e43a0522987demmentovai // past the branch that caused us to arrive at the callee. Set 135246f4068280b5b191303ff13671e43a0522987demmentovai // frame_ppc->instruction to four less than that. Since all ppc 136246f4068280b5b191303ff13671e43a0522987demmentovai // instructions are 4 bytes wide, this is the address of the branch 137246f4068280b5b191303ff13671e43a0522987demmentovai // instruction. This allows source line information to match up with the 138246f4068280b5b191303ff13671e43a0522987demmentovai // line that contains a function call. Callers that require the exact 139246f4068280b5b191303ff13671e43a0522987demmentovai // return address value may access the context.srr0 field of StackFramePPC. 140246f4068280b5b191303ff13671e43a0522987demmentovai frame->instruction = frame->context.srr0 - 4; 141960e5277ee489960c40c50c6222606200419302ammentovai 142246f4068280b5b191303ff13671e43a0522987demmentovai return frame; 143960e5277ee489960c40c50c6222606200419302ammentovai} 144960e5277ee489960c40c50c6222606200419302ammentovai 145960e5277ee489960c40c50c6222606200419302ammentovai 146e5dc60822e5938fea2ae892ccddb906641ba174emmentovai} // namespace google_breakpad 147