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