15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2011, Google Inc.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// All rights reserved.
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Redistribution and use in source and binary forms, with or without
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// modification, are permitted provided that the following conditions are
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// met:
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//     * Redistributions of source code must retain the above copyright
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// notice, this list of conditions and the following disclaimer.
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//     * Redistributions in binary form must reproduce the above
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// copyright notice, this list of conditions and the following disclaimer
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// in the documentation and/or other materials provided with the
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// distribution.
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//     * Neither the name of Google Inc. nor the names of its
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// contributors may be used to endorse or promote products derived from
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// this software without specific prior written permission.
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ---
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Author: Doug Kwan
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This is inspired by Craig Silverstein's PowerPC stacktrace code.
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef BASE_STACKTRACE_ARM_INL_H_
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define BASE_STACKTRACE_ARM_INL_H_
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Note: this file is included into stacktrace.cc more than once.
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Anything that should only be defined once should be here:
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stdint.h>   // for uintptr_t
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/basictypes.h"  // for NULL
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <gperftools/stacktrace.h>
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// WARNING:
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This only works if all your code is in either ARM or THUMB mode.  With
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// interworking, the frame pointer of the caller can either be in r11 (ARM
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// mode) or r7 (THUMB mode).  A callee only saves the frame pointer of its
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// mode in a fixed location on its stack frame.  If the caller is a different
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// mode, there is no easy way to find the frame pointer.  It can either be
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// still in the designated register or saved on stack along with other callee
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// saved registers.
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Given a pointer to a stack frame, locate and return the calling
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// stackframe, or return NULL if no stackframe can be found. Perform sanity
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// checks (the strictness of which is controlled by the boolean parameter
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// "STRICT_UNWINDING") to reduce the chance that a bad pointer is returned.
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<bool STRICT_UNWINDING>
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void **NextStackFrame(void **old_sp) {
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void **new_sp = (void**) old_sp[-1];
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Check that the transition from frame pointer old_sp to frame
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // pointer new_sp isn't clearly bogus
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (STRICT_UNWINDING) {
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // With the stack growing downwards, older stack frame must be
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // at a greater address that the current one.
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (new_sp <= old_sp) return NULL;
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Assume stack frames larger than 100,000 bytes are bogus.
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ((uintptr_t)new_sp - (uintptr_t)old_sp > 100000) return NULL;
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // In the non-strict mode, allow discontiguous stack frames.
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // (alternate-signal-stacks for example).
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (new_sp == old_sp) return NULL;
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // And allow frames upto about 1MB.
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ((new_sp > old_sp)
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        && ((uintptr_t)new_sp - (uintptr_t)old_sp > 1000000)) return NULL;
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if ((uintptr_t)new_sp & (sizeof(void *) - 1)) return NULL;
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return new_sp;
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This ensures that GetStackTrace stes up the Link Register properly.
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef __GNUC__
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void StacktraceArmDummyFunction() __attribute__((noinline));
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void StacktraceArmDummyFunction() { __asm__ volatile(""); }
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# error StacktraceArmDummyFunction() needs to be ported to this platform.
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // BASE_STACKTRACE_ARM_INL_H_
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Note: this part of the file is included several times.
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Do not put globals below.
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The following 4 functions are generated from the code below:
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   GetStack{Trace,Frames}()
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   GetStack{Trace,Frames}WithContext()
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// These functions take the following args:
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   void** result: the stack-trace, as an array
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   int* sizes: the size of each stack frame, as an array
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//               (GetStackFrames* only)
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   int max_depth: the size of the result (and sizes) array(s)
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   int skip_count: how many stack pointers to skip before storing in result
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   void* ucp: a ucontext_t* (GetStack{Trace,Frames}WithContext only)
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int GET_STACK_TRACE_OR_FRAMES {
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef __GNUC__
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void **sp = reinterpret_cast<void**>(__builtin_frame_address(0));
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# error reading stack point not yet supported on this platform.
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // On ARM, the return address is stored in the link register (r14).
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This is not saved on the stack frame of a leaf function.  To
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // simplify code that reads return addresses, we call a dummy
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // function so that the return address of this function is also
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // stored in the stack frame.  This works at least for gcc.
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  StacktraceArmDummyFunction();
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int n = 0;
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (sp && n < max_depth) {
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // The GetStackFrames routine is called when we are in some
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // informational context (the failure signal handler for example).
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Use the non-strict unwinding rules to produce a stack trace
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // that is as complete as possible (even if it contains a few bogus
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // entries in some rare cases).
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void **next_sp = NextStackFrame<IS_STACK_FRAMES == 0>(sp);
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (skip_count > 0) {
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      skip_count--;
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      result[n] = *sp;
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if IS_STACK_FRAMES
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (next_sp > sp) {
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        sizes[n] = (uintptr_t)next_sp - (uintptr_t)sp;
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // A frame-size of 0 is used to indicate unknown frame size.
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        sizes[n] = 0;
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      n++;
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sp = next_sp;
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return n;
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
146