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