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 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 59 60 StackFrame* StackwalkerARM64::GetContextFrame() { 61 if (!context_) { 62 BPLOG(ERROR) << "Can't get context frame without context"; 63 return NULL; 64 } 65 66 StackFrameARM64* frame = new StackFrameARM64(); 67 68 // The instruction pointer is stored directly in a register (x32), so pull it 69 // straight out of the CPU context structure. 70 frame->context = *context_; 71 frame->context_validity = context_frame_validity_; 72 frame->trust = StackFrame::FRAME_TRUST_CONTEXT; 73 frame->instruction = frame->context.iregs[MD_CONTEXT_ARM64_REG_PC]; 74 75 return frame; 76 } 77 78 StackFrameARM64* StackwalkerARM64::GetCallerByCFIFrameInfo( 79 const vector<StackFrame*> &frames, 80 CFIFrameInfo* cfi_frame_info) { 81 StackFrameARM64* last_frame = static_cast<StackFrameARM64*>(frames.back()); 82 83 static const char* register_names[] = { 84 "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7", 85 "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", 86 "x16", "x17", "x18", "x19", "x20", "x21", "x22", "x23", 87 "x24", "x25", "x26", "x27", "x28", "x29", "x30", "sp", 88 "pc", NULL 89 }; 90 91 // Populate a dictionary with the valid register values in last_frame. 92 CFIFrameInfo::RegisterValueMap<uint64_t> callee_registers; 93 for (int i = 0; register_names[i]; i++) { 94 if (last_frame->context_validity & StackFrameARM64::RegisterValidFlag(i)) 95 callee_registers[register_names[i]] = last_frame->context.iregs[i]; 96 } 97 98 // Use the STACK CFI data to recover the caller's register values. 99 CFIFrameInfo::RegisterValueMap<uint64_t> caller_registers; 100 if (!cfi_frame_info->FindCallerRegs(callee_registers, *memory_, 101 &caller_registers)) { 102 return NULL; 103 } 104 // Construct a new stack frame given the values the CFI recovered. 105 scoped_ptr<StackFrameARM64> frame(new StackFrameARM64()); 106 for (int i = 0; register_names[i]; i++) { 107 CFIFrameInfo::RegisterValueMap<uint64_t>::iterator entry = 108 caller_registers.find(register_names[i]); 109 if (entry != caller_registers.end()) { 110 // We recovered the value of this register; fill the context with the 111 // value from caller_registers. 112 frame->context_validity |= StackFrameARM64::RegisterValidFlag(i); 113 frame->context.iregs[i] = entry->second; 114 } else if (19 <= i && i <= 29 && (last_frame->context_validity & 115 StackFrameARM64::RegisterValidFlag(i))) { 116 // If the STACK CFI data doesn't mention some callee-saves register, and 117 // it is valid in the callee, assume the callee has not yet changed it. 118 // Registers r19 through r29 are callee-saves, according to the Procedure 119 // Call Standard for the ARM AARCH64 Architecture, which the Linux ABI 120 // follows. 121 frame->context_validity |= StackFrameARM64::RegisterValidFlag(i); 122 frame->context.iregs[i] = last_frame->context.iregs[i]; 123 } 124 } 125 // If the CFI doesn't recover the PC explicitly, then use .ra. 126 if (!(frame->context_validity & StackFrameARM64::CONTEXT_VALID_PC)) { 127 CFIFrameInfo::RegisterValueMap<uint64_t>::iterator entry = 128 caller_registers.find(".ra"); 129 if (entry != caller_registers.end()) { 130 frame->context_validity |= StackFrameARM64::CONTEXT_VALID_PC; 131 frame->context.iregs[MD_CONTEXT_ARM64_REG_PC] = entry->second; 132 } 133 } 134 // If the CFI doesn't recover the SP explicitly, then use .cfa. 135 if (!(frame->context_validity & StackFrameARM64::CONTEXT_VALID_SP)) { 136 CFIFrameInfo::RegisterValueMap<uint64_t>::iterator entry = 137 caller_registers.find(".cfa"); 138 if (entry != caller_registers.end()) { 139 frame->context_validity |= StackFrameARM64::CONTEXT_VALID_SP; 140 frame->context.iregs[MD_CONTEXT_ARM64_REG_SP] = entry->second; 141 } 142 } 143 144 // If we didn't recover the PC and the SP, then the frame isn't very useful. 145 static const uint64_t essentials = (StackFrameARM64::CONTEXT_VALID_SP 146 | StackFrameARM64::CONTEXT_VALID_PC); 147 if ((frame->context_validity & essentials) != essentials) 148 return NULL; 149 150 frame->trust = StackFrame::FRAME_TRUST_CFI; 151 return frame.release(); 152 } 153 154 StackFrameARM64* StackwalkerARM64::GetCallerByStackScan( 155 const vector<StackFrame*> &frames) { 156 StackFrameARM64* last_frame = static_cast<StackFrameARM64*>(frames.back()); 157 uint64_t last_sp = last_frame->context.iregs[MD_CONTEXT_ARM64_REG_SP]; 158 uint64_t caller_sp, caller_pc; 159 160 if (!ScanForReturnAddress(last_sp, &caller_sp, &caller_pc, 161 frames.size() == 1 /* is_context_frame */)) { 162 // No plausible return address was found. 163 return NULL; 164 } 165 166 // ScanForReturnAddress found a reasonable return address. Advance 167 // %sp to the location above the one where the return address was 168 // found. 169 caller_sp += 8; 170 171 // Create a new stack frame (ownership will be transferred to the caller) 172 // and fill it in. 173 StackFrameARM64* frame = new StackFrameARM64(); 174 175 frame->trust = StackFrame::FRAME_TRUST_SCAN; 176 frame->context = last_frame->context; 177 frame->context.iregs[MD_CONTEXT_ARM64_REG_PC] = caller_pc; 178 frame->context.iregs[MD_CONTEXT_ARM64_REG_SP] = caller_sp; 179 frame->context_validity = StackFrameARM64::CONTEXT_VALID_PC | 180 StackFrameARM64::CONTEXT_VALID_SP; 181 182 return frame; 183 } 184 185 StackFrameARM64* StackwalkerARM64::GetCallerByFramePointer( 186 const vector<StackFrame*> &frames) { 187 StackFrameARM64* last_frame = static_cast<StackFrameARM64*>(frames.back()); 188 189 uint64_t last_fp = last_frame->context.iregs[MD_CONTEXT_ARM64_REG_FP]; 190 191 uint64_t caller_fp = 0; 192 if (last_fp && !memory_->GetMemoryAtAddress(last_fp, &caller_fp)) { 193 BPLOG(ERROR) << "Unable to read caller_fp from last_fp: 0x" 194 << std::hex << last_fp; 195 return NULL; 196 } 197 198 uint64_t caller_lr = 0; 199 if (last_fp && !memory_->GetMemoryAtAddress(last_fp + 8, &caller_lr)) { 200 BPLOG(ERROR) << "Unable to read caller_lr from last_fp + 8: 0x" 201 << std::hex << (last_fp + 8); 202 return NULL; 203 } 204 205 uint64_t caller_sp = last_fp ? last_fp + 16 : 206 last_frame->context.iregs[MD_CONTEXT_ARM64_REG_SP]; 207 208 // Create a new stack frame (ownership will be transferred to the caller) 209 // and fill it in. 210 StackFrameARM64* frame = new StackFrameARM64(); 211 212 frame->trust = StackFrame::FRAME_TRUST_FP; 213 frame->context = last_frame->context; 214 frame->context.iregs[MD_CONTEXT_ARM64_REG_FP] = caller_fp; 215 frame->context.iregs[MD_CONTEXT_ARM64_REG_SP] = caller_sp; 216 frame->context.iregs[MD_CONTEXT_ARM64_REG_PC] = 217 last_frame->context.iregs[MD_CONTEXT_ARM64_REG_LR]; 218 frame->context.iregs[MD_CONTEXT_ARM64_REG_LR] = caller_lr; 219 frame->context_validity = StackFrameARM64::CONTEXT_VALID_PC | 220 StackFrameARM64::CONTEXT_VALID_LR | 221 StackFrameARM64::CONTEXT_VALID_FP | 222 StackFrameARM64::CONTEXT_VALID_SP; 223 return frame; 224 } 225 226 StackFrame* StackwalkerARM64::GetCallerFrame(const CallStack* stack, 227 bool stack_scan_allowed) { 228 if (!memory_ || !stack) { 229 BPLOG(ERROR) << "Can't get caller frame without memory or stack"; 230 return NULL; 231 } 232 233 const vector<StackFrame*> &frames = *stack->frames(); 234 StackFrameARM64* last_frame = static_cast<StackFrameARM64*>(frames.back()); 235 scoped_ptr<StackFrameARM64> frame; 236 237 // See if there is DWARF call frame information covering this address. 238 scoped_ptr<CFIFrameInfo> cfi_frame_info( 239 frame_symbolizer_->FindCFIFrameInfo(last_frame)); 240 if (cfi_frame_info.get()) 241 frame.reset(GetCallerByCFIFrameInfo(frames, cfi_frame_info.get())); 242 243 // If CFI failed, or there wasn't CFI available, fall back to frame pointer. 244 if (!frame.get()) 245 frame.reset(GetCallerByFramePointer(frames)); 246 247 // If everything failed, fall back to stack scanning. 248 if (stack_scan_allowed && !frame.get()) 249 frame.reset(GetCallerByStackScan(frames)); 250 251 // If nothing worked, tell the caller. 252 if (!frame.get()) 253 return NULL; 254 255 // An instruction address of zero marks the end of the stack. 256 if (frame->context.iregs[MD_CONTEXT_ARM64_REG_PC] == 0) 257 return NULL; 258 259 // If the new stack pointer is at a lower address than the old, then 260 // that's clearly incorrect. Treat this as end-of-stack to enforce 261 // progress and avoid infinite loops. 262 if (frame->context.iregs[MD_CONTEXT_ARM64_REG_SP] 263 < last_frame->context.iregs[MD_CONTEXT_ARM64_REG_SP]) 264 return NULL; 265 266 // The new frame's context's PC is the return address, which is one 267 // instruction past the instruction that caused us to arrive at the callee. 268 // ARM64 instructions have a uniform 4-byte encoding, so subtracting 4 off 269 // the return address gets back to the beginning of the call instruction. 270 // Callers that require the exact return address value may access 271 // frame->context.iregs[MD_CONTEXT_ARM64_REG_PC]. 272 frame->instruction = frame->context.iregs[MD_CONTEXT_ARM64_REG_PC] - 4; 273 274 return frame.release(); 275 } 276 277 278 } // namespace google_breakpad 279