1*9356374aSAndroid Build Coastguard Worker// Copyright 2021 The Abseil Authors 2*9356374aSAndroid Build Coastguard Worker// 3*9356374aSAndroid Build Coastguard Worker// Licensed under the Apache License, Version 2.0 (the "License"); 4*9356374aSAndroid Build Coastguard Worker// you may not use this file except in compliance with the License. 5*9356374aSAndroid Build Coastguard Worker// You may obtain a copy of the License at 6*9356374aSAndroid Build Coastguard Worker// 7*9356374aSAndroid Build Coastguard Worker// https://www.apache.org/licenses/LICENSE-2.0 8*9356374aSAndroid Build Coastguard Worker// 9*9356374aSAndroid Build Coastguard Worker// Unless required by applicable law or agreed to in writing, software 10*9356374aSAndroid Build Coastguard Worker// distributed under the License is distributed on an "AS IS" BASIS, 11*9356374aSAndroid Build Coastguard Worker// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12*9356374aSAndroid Build Coastguard Worker// See the License for the specific language governing permissions and 13*9356374aSAndroid Build Coastguard Worker// limitations under the License. 14*9356374aSAndroid Build Coastguard Worker 15*9356374aSAndroid Build Coastguard Worker#ifndef ABSL_DEBUGGING_INTERNAL_STACKTRACE_RISCV_INL_H_ 16*9356374aSAndroid Build Coastguard Worker#define ABSL_DEBUGGING_INTERNAL_STACKTRACE_RISCV_INL_H_ 17*9356374aSAndroid Build Coastguard Worker 18*9356374aSAndroid Build Coastguard Worker// Generate stack trace for riscv 19*9356374aSAndroid Build Coastguard Worker 20*9356374aSAndroid Build Coastguard Worker#include <sys/ucontext.h> 21*9356374aSAndroid Build Coastguard Worker 22*9356374aSAndroid Build Coastguard Worker#include "absl/base/config.h" 23*9356374aSAndroid Build Coastguard Worker#if defined(__linux__) 24*9356374aSAndroid Build Coastguard Worker#include <sys/mman.h> 25*9356374aSAndroid Build Coastguard Worker#include <ucontext.h> 26*9356374aSAndroid Build Coastguard Worker#include <unistd.h> 27*9356374aSAndroid Build Coastguard Worker#endif 28*9356374aSAndroid Build Coastguard Worker 29*9356374aSAndroid Build Coastguard Worker#include <atomic> 30*9356374aSAndroid Build Coastguard Worker#include <cassert> 31*9356374aSAndroid Build Coastguard Worker#include <cstdint> 32*9356374aSAndroid Build Coastguard Worker#include <iostream> 33*9356374aSAndroid Build Coastguard Worker#include <limits> 34*9356374aSAndroid Build Coastguard Worker#include <utility> 35*9356374aSAndroid Build Coastguard Worker 36*9356374aSAndroid Build Coastguard Worker#include "absl/base/attributes.h" 37*9356374aSAndroid Build Coastguard Worker#include "absl/debugging/stacktrace.h" 38*9356374aSAndroid Build Coastguard Worker 39*9356374aSAndroid Build Coastguard Workerstatic const uintptr_t kUnknownFrameSize = 0; 40*9356374aSAndroid Build Coastguard Worker 41*9356374aSAndroid Build Coastguard Worker// Compute the size of a stack frame in [low..high). We assume that low < high. 42*9356374aSAndroid Build Coastguard Worker// Return size of kUnknownFrameSize. 43*9356374aSAndroid Build Coastguard Workertemplate <typename T> 44*9356374aSAndroid Build Coastguard Workerstatic inline uintptr_t ComputeStackFrameSize(const T *low, const T *high) { 45*9356374aSAndroid Build Coastguard Worker const char *low_char_ptr = reinterpret_cast<const char *>(low); 46*9356374aSAndroid Build Coastguard Worker const char *high_char_ptr = reinterpret_cast<const char *>(high); 47*9356374aSAndroid Build Coastguard Worker return low < high ? high_char_ptr - low_char_ptr : kUnknownFrameSize; 48*9356374aSAndroid Build Coastguard Worker} 49*9356374aSAndroid Build Coastguard Worker 50*9356374aSAndroid Build Coastguard Worker// Given a pointer to a stack frame, locate and return the calling stackframe, 51*9356374aSAndroid Build Coastguard Worker// or return null if no stackframe can be found. Perform sanity checks (the 52*9356374aSAndroid Build Coastguard Worker// strictness of which is controlled by the boolean parameter 53*9356374aSAndroid Build Coastguard Worker// "STRICT_UNWINDING") to reduce the chance that a bad pointer is returned. 54*9356374aSAndroid Build Coastguard Workertemplate <bool STRICT_UNWINDING, bool WITH_CONTEXT> 55*9356374aSAndroid Build Coastguard WorkerABSL_ATTRIBUTE_NO_SANITIZE_ADDRESS // May read random elements from stack. 56*9356374aSAndroid Build Coastguard WorkerABSL_ATTRIBUTE_NO_SANITIZE_MEMORY // May read random elements from stack. 57*9356374aSAndroid Build Coastguard Workerstatic void ** NextStackFrame(void **old_frame_pointer, const void *uc, 58*9356374aSAndroid Build Coastguard Worker const std::pair<size_t, size_t> range) { 59*9356374aSAndroid Build Coastguard Worker // . 60*9356374aSAndroid Build Coastguard Worker // . 61*9356374aSAndroid Build Coastguard Worker // . 62*9356374aSAndroid Build Coastguard Worker // +-> +----------------+ 63*9356374aSAndroid Build Coastguard Worker // | | return address | 64*9356374aSAndroid Build Coastguard Worker // | | previous fp | 65*9356374aSAndroid Build Coastguard Worker // | | ... | 66*9356374aSAndroid Build Coastguard Worker // | +----------------+ <-+ 67*9356374aSAndroid Build Coastguard Worker // | | return address | | 68*9356374aSAndroid Build Coastguard Worker // +---|- previous fp | | 69*9356374aSAndroid Build Coastguard Worker // | ... | | 70*9356374aSAndroid Build Coastguard Worker // $fp ->|----------------+ | 71*9356374aSAndroid Build Coastguard Worker // | return address | | 72*9356374aSAndroid Build Coastguard Worker // | previous fp -|---+ 73*9356374aSAndroid Build Coastguard Worker // $sp ->| ... | 74*9356374aSAndroid Build Coastguard Worker // +----------------+ 75*9356374aSAndroid Build Coastguard Worker void **new_frame_pointer = reinterpret_cast<void **>(old_frame_pointer[-2]); 76*9356374aSAndroid Build Coastguard Worker uintptr_t frame_pointer = reinterpret_cast<uintptr_t>(new_frame_pointer); 77*9356374aSAndroid Build Coastguard Worker 78*9356374aSAndroid Build Coastguard Worker // The RISCV ELF psABI mandates that the stack pointer is always 16-byte 79*9356374aSAndroid Build Coastguard Worker // aligned. 80*9356374aSAndroid Build Coastguard Worker // TODO(#1236) this doesn't hold for ILP32E which only mandates a 4-byte 81*9356374aSAndroid Build Coastguard Worker // alignment. 82*9356374aSAndroid Build Coastguard Worker if (frame_pointer & 15) 83*9356374aSAndroid Build Coastguard Worker return nullptr; 84*9356374aSAndroid Build Coastguard Worker 85*9356374aSAndroid Build Coastguard Worker // If the new frame pointer matches the signal context, avoid terminating 86*9356374aSAndroid Build Coastguard Worker // early to deal with alternate signal stacks. 87*9356374aSAndroid Build Coastguard Worker if (WITH_CONTEXT) 88*9356374aSAndroid Build Coastguard Worker if (const ucontext_t *ucv = static_cast<const ucontext_t *>(uc)) 89*9356374aSAndroid Build Coastguard Worker // RISCV ELF psABI has the frame pointer at x8/fp/s0. 90*9356374aSAndroid Build Coastguard Worker // -- RISCV psABI Table 18.2 91*9356374aSAndroid Build Coastguard Worker if (ucv->uc_mcontext.__gregs[8] == frame_pointer) 92*9356374aSAndroid Build Coastguard Worker return new_frame_pointer; 93*9356374aSAndroid Build Coastguard Worker 94*9356374aSAndroid Build Coastguard Worker // Check frame size. In strict mode, we assume frames to be under 100,000 95*9356374aSAndroid Build Coastguard Worker // bytes. In non-strict mode, we relax the limit to 1MB. 96*9356374aSAndroid Build Coastguard Worker const uintptr_t max_size = STRICT_UNWINDING ? 100000 : 1000000; 97*9356374aSAndroid Build Coastguard Worker const uintptr_t frame_size = 98*9356374aSAndroid Build Coastguard Worker ComputeStackFrameSize(old_frame_pointer, new_frame_pointer); 99*9356374aSAndroid Build Coastguard Worker if (frame_size == kUnknownFrameSize) { 100*9356374aSAndroid Build Coastguard Worker if (STRICT_UNWINDING) 101*9356374aSAndroid Build Coastguard Worker return nullptr; 102*9356374aSAndroid Build Coastguard Worker 103*9356374aSAndroid Build Coastguard Worker // In non-strict mode permit non-contiguous stacks (e.g. alternate signal 104*9356374aSAndroid Build Coastguard Worker // frame handling). 105*9356374aSAndroid Build Coastguard Worker if (reinterpret_cast<uintptr_t>(new_frame_pointer) < range.first || 106*9356374aSAndroid Build Coastguard Worker reinterpret_cast<uintptr_t>(new_frame_pointer) > range.second) 107*9356374aSAndroid Build Coastguard Worker return nullptr; 108*9356374aSAndroid Build Coastguard Worker } 109*9356374aSAndroid Build Coastguard Worker 110*9356374aSAndroid Build Coastguard Worker if (frame_size > max_size) 111*9356374aSAndroid Build Coastguard Worker return nullptr; 112*9356374aSAndroid Build Coastguard Worker 113*9356374aSAndroid Build Coastguard Worker return new_frame_pointer; 114*9356374aSAndroid Build Coastguard Worker} 115*9356374aSAndroid Build Coastguard Worker 116*9356374aSAndroid Build Coastguard Workertemplate <bool IS_STACK_FRAMES, bool IS_WITH_CONTEXT> 117*9356374aSAndroid Build Coastguard WorkerABSL_ATTRIBUTE_NO_SANITIZE_ADDRESS // May read random elements from stack. 118*9356374aSAndroid Build Coastguard WorkerABSL_ATTRIBUTE_NO_SANITIZE_MEMORY // May read random elements from stack. 119*9356374aSAndroid Build Coastguard Workerstatic int UnwindImpl(void **result, int *sizes, int max_depth, int skip_count, 120*9356374aSAndroid Build Coastguard Worker const void *ucp, int *min_dropped_frames) { 121*9356374aSAndroid Build Coastguard Worker // The `frame_pointer` that is computed here points to the top of the frame. 122*9356374aSAndroid Build Coastguard Worker // The two words preceding the address are the return address and the previous 123*9356374aSAndroid Build Coastguard Worker // frame pointer. 124*9356374aSAndroid Build Coastguard Worker#if defined(__GNUC__) 125*9356374aSAndroid Build Coastguard Worker void **frame_pointer = reinterpret_cast<void **>(__builtin_frame_address(0)); 126*9356374aSAndroid Build Coastguard Worker#else 127*9356374aSAndroid Build Coastguard Worker#error reading stack pointer not yet supported on this platform 128*9356374aSAndroid Build Coastguard Worker#endif 129*9356374aSAndroid Build Coastguard Worker 130*9356374aSAndroid Build Coastguard Worker std::pair<size_t, size_t> stack = { 131*9356374aSAndroid Build Coastguard Worker // assume that the first page is not the stack. 132*9356374aSAndroid Build Coastguard Worker static_cast<size_t>(sysconf(_SC_PAGESIZE)), 133*9356374aSAndroid Build Coastguard Worker std::numeric_limits<size_t>::max() - sizeof(void *) 134*9356374aSAndroid Build Coastguard Worker }; 135*9356374aSAndroid Build Coastguard Worker 136*9356374aSAndroid Build Coastguard Worker int n = 0; 137*9356374aSAndroid Build Coastguard Worker void *return_address = nullptr; 138*9356374aSAndroid Build Coastguard Worker while (frame_pointer && n < max_depth) { 139*9356374aSAndroid Build Coastguard Worker return_address = frame_pointer[-1]; 140*9356374aSAndroid Build Coastguard Worker 141*9356374aSAndroid Build Coastguard Worker // The absl::GetStackFrames routine is called when we are in some 142*9356374aSAndroid Build Coastguard Worker // informational context (the failure signal handler for example). Use the 143*9356374aSAndroid Build Coastguard Worker // non-strict unwinding rules to produce a stack trace that is as complete 144*9356374aSAndroid Build Coastguard Worker // as possible (even if it contains a few bogus entries in some rare cases). 145*9356374aSAndroid Build Coastguard Worker void **next_frame_pointer = 146*9356374aSAndroid Build Coastguard Worker NextStackFrame<!IS_STACK_FRAMES, IS_WITH_CONTEXT>(frame_pointer, ucp, 147*9356374aSAndroid Build Coastguard Worker stack); 148*9356374aSAndroid Build Coastguard Worker 149*9356374aSAndroid Build Coastguard Worker if (skip_count > 0) { 150*9356374aSAndroid Build Coastguard Worker skip_count--; 151*9356374aSAndroid Build Coastguard Worker } else { 152*9356374aSAndroid Build Coastguard Worker result[n] = return_address; 153*9356374aSAndroid Build Coastguard Worker if (IS_STACK_FRAMES) { 154*9356374aSAndroid Build Coastguard Worker sizes[n] = ComputeStackFrameSize(frame_pointer, next_frame_pointer); 155*9356374aSAndroid Build Coastguard Worker } 156*9356374aSAndroid Build Coastguard Worker n++; 157*9356374aSAndroid Build Coastguard Worker } 158*9356374aSAndroid Build Coastguard Worker 159*9356374aSAndroid Build Coastguard Worker frame_pointer = next_frame_pointer; 160*9356374aSAndroid Build Coastguard Worker } 161*9356374aSAndroid Build Coastguard Worker 162*9356374aSAndroid Build Coastguard Worker if (min_dropped_frames != nullptr) { 163*9356374aSAndroid Build Coastguard Worker // Implementation detail: we clamp the max of frames we are willing to 164*9356374aSAndroid Build Coastguard Worker // count, so as not to spend too much time in the loop below. 165*9356374aSAndroid Build Coastguard Worker const int kMaxUnwind = 200; 166*9356374aSAndroid Build Coastguard Worker int num_dropped_frames = 0; 167*9356374aSAndroid Build Coastguard Worker for (int j = 0; frame_pointer != nullptr && j < kMaxUnwind; j++) { 168*9356374aSAndroid Build Coastguard Worker if (skip_count > 0) { 169*9356374aSAndroid Build Coastguard Worker skip_count--; 170*9356374aSAndroid Build Coastguard Worker } else { 171*9356374aSAndroid Build Coastguard Worker num_dropped_frames++; 172*9356374aSAndroid Build Coastguard Worker } 173*9356374aSAndroid Build Coastguard Worker frame_pointer = 174*9356374aSAndroid Build Coastguard Worker NextStackFrame<!IS_STACK_FRAMES, IS_WITH_CONTEXT>(frame_pointer, ucp, 175*9356374aSAndroid Build Coastguard Worker stack); 176*9356374aSAndroid Build Coastguard Worker } 177*9356374aSAndroid Build Coastguard Worker *min_dropped_frames = num_dropped_frames; 178*9356374aSAndroid Build Coastguard Worker } 179*9356374aSAndroid Build Coastguard Worker 180*9356374aSAndroid Build Coastguard Worker return n; 181*9356374aSAndroid Build Coastguard Worker} 182*9356374aSAndroid Build Coastguard Worker 183*9356374aSAndroid Build Coastguard Workernamespace absl { 184*9356374aSAndroid Build Coastguard WorkerABSL_NAMESPACE_BEGIN 185*9356374aSAndroid Build Coastguard Workernamespace debugging_internal { 186*9356374aSAndroid Build Coastguard Workerbool StackTraceWorksForTest() { return true; } 187*9356374aSAndroid Build Coastguard Worker} // namespace debugging_internal 188*9356374aSAndroid Build Coastguard WorkerABSL_NAMESPACE_END 189*9356374aSAndroid Build Coastguard Worker} // namespace absl 190*9356374aSAndroid Build Coastguard Worker 191*9356374aSAndroid Build Coastguard Worker#endif 192