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