|
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. |
|
29 |
|
30 // stackwalker_ppc.cc: ppc-specific stackwalker. |
|
31 // |
|
32 // See stackwalker_ppc.h for documentation. |
|
33 // |
|
34 // Author: Mark Mentovai |
|
35 |
|
36 |
|
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" |
|
42 |
|
43 namespace google_breakpad { |
|
44 |
|
45 |
|
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 } |
|
63 |
|
64 |
|
65 StackFrame* StackwalkerPPC::GetContextFrame() { |
|
66 if (!context_) { |
|
67 BPLOG(ERROR) << "Can't get context frame without context"; |
|
68 return NULL; |
|
69 } |
|
70 |
|
71 StackFramePPC* frame = new StackFramePPC(); |
|
72 |
|
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; |
|
79 |
|
80 return frame; |
|
81 } |
|
82 |
|
83 |
|
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 } |
|
90 |
|
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. |
|
99 |
|
100 StackFramePPC* last_frame = static_cast<StackFramePPC*>( |
|
101 stack->frames()->back()); |
|
102 |
|
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 } |
|
112 |
|
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 } |
|
123 |
|
124 StackFramePPC* frame = new StackFramePPC(); |
|
125 |
|
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; |
|
132 |
|
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; |
|
141 |
|
142 return frame; |
|
143 } |
|
144 |
|
145 |
|
146 } // namespace google_breakpad |