1 // Copyright (c) 2013 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_arm64.cc: arm64-specific stackwalker.
31 //
32 // See stackwalker_arm64.h for documentation.
33 //
34 // Author: Mark Mentovai, Ted Mielczarek, Jim Blandy, Colin Blundell
35
36 #include <vector>
37
38 #include "common/scoped_ptr.h"
39 #include "google_breakpad/processor/call_stack.h"
40 #include "google_breakpad/processor/memory_region.h"
41 #include "google_breakpad/processor/source_line_resolver_interface.h"
42 #include "google_breakpad/processor/stack_frame_cpu.h"
43 #include "processor/cfi_frame_info.h"
44 #include "processor/logging.h"
45 #include "processor/stackwalker_arm64.h"
46
47 namespace google_breakpad {
48
49
StackwalkerARM64(const SystemInfo * system_info,const MDRawContextARM64 * context,MemoryRegion * memory,const CodeModules * modules,StackFrameSymbolizer * resolver_helper)50 StackwalkerARM64::StackwalkerARM64(const SystemInfo* system_info,
51 const MDRawContextARM64* context,
52 MemoryRegion* memory,
53 const CodeModules* modules,
54 StackFrameSymbolizer* resolver_helper)
55 : Stackwalker(system_info, memory, modules, resolver_helper),
56 context_(context),
57 context_frame_validity_(StackFrameARM64::CONTEXT_VALID_ALL),
58 address_range_mask_(0xffffffffffffffff) {
59 if (modules && modules->module_count() > 0) {
60 // ARM64 supports storing pointer authentication codes in the upper bits of
61 // a pointer. Make a best guess at the range of valid addresses based on the
62 // range of loaded modules.
63 const CodeModule *high_module =
64 modules->GetModuleAtSequence(modules->module_count() - 1);
65 uint64_t mask = high_module->base_address() + high_module->size();
66 mask |= mask >> 1;
67 mask |= mask >> 2;
68 mask |= mask >> 4;
69 mask |= mask >> 8;
70 mask |= mask >> 16;
71 mask |= mask >> 32;
72 address_range_mask_ = mask;
73 }
74 }
75
PtrauthStrip(uint64_t ptr)76 uint64_t StackwalkerARM64::PtrauthStrip(uint64_t ptr) {
77 uint64_t stripped = ptr & address_range_mask_;
78 return modules_ && modules_->GetModuleForAddress(stripped) ? stripped : ptr;
79 }
80
GetContextFrame()81 StackFrame* StackwalkerARM64::GetContextFrame() {
82 if (!context_) {
83 BPLOG(ERROR) << "Can't get context frame without context";
84 return NULL;
85 }
86
87 StackFrameARM64* frame = new StackFrameARM64();
88
89 // The instruction pointer is stored directly in a register (x32), so pull it
90 // straight out of the CPU context structure.
91 frame->context = *context_;
92 frame->context_validity = context_frame_validity_;
93 frame->trust = StackFrame::FRAME_TRUST_CONTEXT;
94 frame->instruction = frame->context.iregs[MD_CONTEXT_ARM64_REG_PC];
95 frame->context.iregs[MD_CONTEXT_ARM64_REG_LR] =
96 PtrauthStrip(frame->context.iregs[MD_CONTEXT_ARM64_REG_LR]);
97
98 return frame;
99 }
100
GetCallerByCFIFrameInfo(const vector<StackFrame * > & frames,CFIFrameInfo * cfi_frame_info)101 StackFrameARM64* StackwalkerARM64::GetCallerByCFIFrameInfo(
102 const vector<StackFrame*> &frames,
103 CFIFrameInfo* cfi_frame_info) {
104 StackFrameARM64* last_frame = static_cast<StackFrameARM64*>(frames.back());
105
106 static const char* register_names[] = {
107 "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7",
108 "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15",
109 "x16", "x17", "x18", "x19", "x20", "x21", "x22", "x23",
110 "x24", "x25", "x26", "x27", "x28", "x29", "x30", "sp",
111 "pc", NULL
112 };
113
114 // Populate a dictionary with the valid register values in last_frame.
115 CFIFrameInfo::RegisterValueMap<uint64_t> callee_registers;
116 for (int i = 0; register_names[i]; i++) {
117 if (last_frame->context_validity & StackFrameARM64::RegisterValidFlag(i))
118 callee_registers[register_names[i]] = last_frame->context.iregs[i];
119 }
120
121 // Use the STACK CFI data to recover the caller's register values.
122 CFIFrameInfo::RegisterValueMap<uint64_t> caller_registers;
123 if (!cfi_frame_info->FindCallerRegs(callee_registers, *memory_,
124 &caller_registers)) {
125 return NULL;
126 }
127 // Construct a new stack frame given the values the CFI recovered.
128 scoped_ptr<StackFrameARM64> frame(new StackFrameARM64());
129 for (int i = 0; register_names[i]; i++) {
130 CFIFrameInfo::RegisterValueMap<uint64_t>::iterator entry =
131 caller_registers.find(register_names[i]);
132 if (entry != caller_registers.end()) {
133 // We recovered the value of this register; fill the context with the
134 // value from caller_registers.
135 frame->context_validity |= StackFrameARM64::RegisterValidFlag(i);
136 frame->context.iregs[i] = entry->second;
137 } else if (19 <= i && i <= 29 && (last_frame->context_validity &
138 StackFrameARM64::RegisterValidFlag(i))) {
139 // If the STACK CFI data doesn't mention some callee-saves register, and
140 // it is valid in the callee, assume the callee has not yet changed it.
141 // Registers r19 through r29 are callee-saves, according to the Procedure
142 // Call Standard for the ARM AARCH64 Architecture, which the Linux ABI
143 // follows.
144 frame->context_validity |= StackFrameARM64::RegisterValidFlag(i);
145 frame->context.iregs[i] = last_frame->context.iregs[i];
146 }
147 }
148 // If the CFI doesn't recover the PC explicitly, then use .ra.
149 if (!(frame->context_validity & StackFrameARM64::CONTEXT_VALID_PC)) {
150 CFIFrameInfo::RegisterValueMap<uint64_t>::iterator entry =
151 caller_registers.find(".ra");
152 if (entry != caller_registers.end()) {
153 frame->context_validity |= StackFrameARM64::CONTEXT_VALID_PC;
154 frame->context.iregs[MD_CONTEXT_ARM64_REG_PC] = entry->second;
155 }
156 }
157 // If the CFI doesn't recover the SP explicitly, then use .cfa.
158 if (!(frame->context_validity & StackFrameARM64::CONTEXT_VALID_SP)) {
159 CFIFrameInfo::RegisterValueMap<uint64_t>::iterator entry =
160 caller_registers.find(".cfa");
161 if (entry != caller_registers.end()) {
162 frame->context_validity |= StackFrameARM64::CONTEXT_VALID_SP;
163 frame->context.iregs[MD_CONTEXT_ARM64_REG_SP] = entry->second;
164 }
165 }
166
167 // If we didn't recover the PC and the SP, then the frame isn't very useful.
168 static const uint64_t essentials = (StackFrameARM64::CONTEXT_VALID_SP
169 | StackFrameARM64::CONTEXT_VALID_PC);
170 if ((frame->context_validity & essentials) != essentials)
171 return NULL;
172
173 frame->trust = StackFrame::FRAME_TRUST_CFI;
174 return frame.release();
175 }
176
GetCallerByStackScan(const vector<StackFrame * > & frames)177 StackFrameARM64* StackwalkerARM64::GetCallerByStackScan(
178 const vector<StackFrame*> &frames) {
179 StackFrameARM64* last_frame = static_cast<StackFrameARM64*>(frames.back());
180 uint64_t last_sp = last_frame->context.iregs[MD_CONTEXT_ARM64_REG_SP];
181 uint64_t caller_sp, caller_pc;
182
183 if (!ScanForReturnAddress(last_sp, &caller_sp, &caller_pc,
184 frames.size() == 1 /* is_context_frame */)) {
185 // No plausible return address was found.
186 return NULL;
187 }
188
189 // ScanForReturnAddress found a reasonable return address. Advance
190 // %sp to the location above the one where the return address was
191 // found.
192 caller_sp += 8;
193
194 // Create a new stack frame (ownership will be transferred to the caller)
195 // and fill it in.
196 StackFrameARM64* frame = new StackFrameARM64();
197
198 frame->trust = StackFrame::FRAME_TRUST_SCAN;
199 frame->context = last_frame->context;
200 frame->context.iregs[MD_CONTEXT_ARM64_REG_PC] = caller_pc;
201 frame->context.iregs[MD_CONTEXT_ARM64_REG_SP] = caller_sp;
202 frame->context_validity = StackFrameARM64::CONTEXT_VALID_PC |
203 StackFrameARM64::CONTEXT_VALID_SP;
204
205 return frame;
206 }
207
GetCallerByFramePointer(const vector<StackFrame * > & frames)208 StackFrameARM64* StackwalkerARM64::GetCallerByFramePointer(
209 const vector<StackFrame*> &frames) {
210 StackFrameARM64* last_frame = static_cast<StackFrameARM64*>(frames.back());
211 if (!(last_frame->context_validity & StackFrameARM64::CONTEXT_VALID_LR)) {
212 CorrectRegLRByFramePointer(frames, last_frame);
213 }
214
215 uint64_t last_fp = last_frame->context.iregs[MD_CONTEXT_ARM64_REG_FP];
216
217 uint64_t caller_fp = 0;
218 if (last_fp && !memory_->GetMemoryAtAddress(last_fp, &caller_fp)) {
219 BPLOG(ERROR) << "Unable to read caller_fp from last_fp: 0x"
220 << std::hex << last_fp;
221 return NULL;
222 }
223
224 uint64_t caller_lr = 0;
225 if (last_fp && !memory_->GetMemoryAtAddress(last_fp + 8, &caller_lr)) {
226 BPLOG(ERROR) << "Unable to read caller_lr from last_fp + 8: 0x"
227 << std::hex << (last_fp + 8);
228 return NULL;
229 }
230
231 caller_lr = PtrauthStrip(caller_lr);
232
233 uint64_t caller_sp = last_fp ? last_fp + 16 :
234 last_frame->context.iregs[MD_CONTEXT_ARM64_REG_SP];
235
236 // Create a new stack frame (ownership will be transferred to the caller)
237 // and fill it in.
238 StackFrameARM64* frame = new StackFrameARM64();
239
240 frame->trust = StackFrame::FRAME_TRUST_FP;
241 frame->context = last_frame->context;
242 frame->context.iregs[MD_CONTEXT_ARM64_REG_FP] = caller_fp;
243 frame->context.iregs[MD_CONTEXT_ARM64_REG_SP] = caller_sp;
244 frame->context.iregs[MD_CONTEXT_ARM64_REG_PC] =
245 last_frame->context.iregs[MD_CONTEXT_ARM64_REG_LR];
246 frame->context.iregs[MD_CONTEXT_ARM64_REG_LR] = caller_lr;
247 frame->context_validity = StackFrameARM64::CONTEXT_VALID_PC |
248 StackFrameARM64::CONTEXT_VALID_LR |
249 StackFrameARM64::CONTEXT_VALID_FP |
250 StackFrameARM64::CONTEXT_VALID_SP;
251 return frame;
252 }
253
CorrectRegLRByFramePointer(const vector<StackFrame * > & frames,StackFrameARM64 * last_frame)254 void StackwalkerARM64::CorrectRegLRByFramePointer(
255 const vector<StackFrame*>& frames,
256 StackFrameARM64* last_frame) {
257 // Need at least two frames to correct and
258 // register $FP should always be greater than register $SP.
259 if (frames.size() < 2 || !last_frame ||
260 last_frame->context.iregs[MD_CONTEXT_ARM64_REG_FP] <=
261 last_frame->context.iregs[MD_CONTEXT_ARM64_REG_SP])
262 return;
263
264 StackFrameARM64* last_last_frame =
265 static_cast<StackFrameARM64*>(*(frames.end() - 2));
266 uint64_t last_last_fp =
267 last_last_frame->context.iregs[MD_CONTEXT_ARM64_REG_FP];
268
269 uint64_t last_fp = 0;
270 if (last_last_fp && !memory_->GetMemoryAtAddress(last_last_fp, &last_fp)) {
271 BPLOG(ERROR) << "Unable to read last_fp from last_last_fp: 0x"
272 << std::hex << last_last_fp;
273 return;
274 }
275 // Give up if STACK CFI doesn't agree with frame pointer.
276 if (last_frame->context.iregs[MD_CONTEXT_ARM64_REG_FP] != last_fp)
277 return;
278
279 uint64_t last_lr = 0;
280 if (last_last_fp && !memory_->GetMemoryAtAddress(last_last_fp + 8, &last_lr)) {
281 BPLOG(ERROR) << "Unable to read last_lr from (last_last_fp + 8): 0x"
282 << std::hex << (last_last_fp + 8);
283 return;
284 }
285 last_lr = PtrauthStrip(last_lr);
286
287 last_frame->context.iregs[MD_CONTEXT_ARM64_REG_LR] = last_lr;
288 }
289
GetCallerFrame(const CallStack * stack,bool stack_scan_allowed)290 StackFrame* StackwalkerARM64::GetCallerFrame(const CallStack* stack,
291 bool stack_scan_allowed) {
292 if (!memory_ || !stack) {
293 BPLOG(ERROR) << "Can't get caller frame without memory or stack";
294 return NULL;
295 }
296
297 const vector<StackFrame*> &frames = *stack->frames();
298 StackFrameARM64* last_frame = static_cast<StackFrameARM64*>(frames.back());
299 scoped_ptr<StackFrameARM64> frame;
300
301 // See if there is DWARF call frame information covering this address.
302 scoped_ptr<CFIFrameInfo> cfi_frame_info(
303 frame_symbolizer_->FindCFIFrameInfo(last_frame));
304 if (cfi_frame_info.get())
305 frame.reset(GetCallerByCFIFrameInfo(frames, cfi_frame_info.get()));
306
307 // If CFI failed, or there wasn't CFI available, fall back to frame pointer.
308 if (!frame.get())
309 frame.reset(GetCallerByFramePointer(frames));
310
311 // If everything failed, fall back to stack scanning.
312 if (stack_scan_allowed && !frame.get())
313 frame.reset(GetCallerByStackScan(frames));
314
315 // If nothing worked, tell the caller.
316 if (!frame.get())
317 return NULL;
318
319 // Should we terminate the stack walk? (end-of-stack or broken invariant)
320 if (TerminateWalk(frame->context.iregs[MD_CONTEXT_ARM64_REG_PC],
321 frame->context.iregs[MD_CONTEXT_ARM64_REG_SP],
322 last_frame->context.iregs[MD_CONTEXT_ARM64_REG_SP],
323 frames.size() == 1)) {
324 return NULL;
325 }
326
327 // The new frame's context's PC is the return address, which is one
328 // instruction past the instruction that caused us to arrive at the callee.
329 // ARM64 instructions have a uniform 4-byte encoding, so subtracting 4 off
330 // the return address gets back to the beginning of the call instruction.
331 // Callers that require the exact return address value may access
332 // frame->context.iregs[MD_CONTEXT_ARM64_REG_PC].
333 frame->instruction = frame->context.iregs[MD_CONTEXT_ARM64_REG_PC] - 4;
334
335 return frame.release();
336 }
337
338
339 } // namespace google_breakpad
340