xref: /aosp_15_r20/external/abseil-cpp/absl/debugging/internal/stacktrace_x86-inl.inc (revision 9356374a3709195abf420251b3e825997ff56c0f)
1*9356374aSAndroid Build Coastguard Worker// Copyright 2017 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// Produce stack trace
16*9356374aSAndroid Build Coastguard Worker
17*9356374aSAndroid Build Coastguard Worker#ifndef ABSL_DEBUGGING_INTERNAL_STACKTRACE_X86_INL_INC_
18*9356374aSAndroid Build Coastguard Worker#define ABSL_DEBUGGING_INTERNAL_STACKTRACE_X86_INL_INC_
19*9356374aSAndroid Build Coastguard Worker
20*9356374aSAndroid Build Coastguard Worker#if defined(__linux__) && (defined(__i386__) || defined(__x86_64__))
21*9356374aSAndroid Build Coastguard Worker#include <ucontext.h>  // for ucontext_t
22*9356374aSAndroid Build Coastguard Worker#endif
23*9356374aSAndroid Build Coastguard Worker
24*9356374aSAndroid Build Coastguard Worker#if !defined(_WIN32)
25*9356374aSAndroid Build Coastguard Worker#include <unistd.h>
26*9356374aSAndroid Build Coastguard Worker#endif
27*9356374aSAndroid Build Coastguard Worker
28*9356374aSAndroid Build Coastguard Worker#include <cassert>
29*9356374aSAndroid Build Coastguard Worker#include <cstdint>
30*9356374aSAndroid Build Coastguard Worker#include <limits>
31*9356374aSAndroid Build Coastguard Worker
32*9356374aSAndroid Build Coastguard Worker#include "absl/base/attributes.h"
33*9356374aSAndroid Build Coastguard Worker#include "absl/base/macros.h"
34*9356374aSAndroid Build Coastguard Worker#include "absl/base/port.h"
35*9356374aSAndroid Build Coastguard Worker#include "absl/debugging/internal/address_is_readable.h"
36*9356374aSAndroid Build Coastguard Worker#include "absl/debugging/internal/vdso_support.h"  // a no-op on non-elf or non-glibc systems
37*9356374aSAndroid Build Coastguard Worker#include "absl/debugging/stacktrace.h"
38*9356374aSAndroid Build Coastguard Worker
39*9356374aSAndroid Build Coastguard Workerusing absl::debugging_internal::AddressIsReadable;
40*9356374aSAndroid Build Coastguard Worker
41*9356374aSAndroid Build Coastguard Worker#if defined(__linux__) && defined(__i386__)
42*9356374aSAndroid Build Coastguard Worker// Count "push %reg" instructions in VDSO __kernel_vsyscall(),
43*9356374aSAndroid Build Coastguard Worker// preceding "syscall" or "sysenter".
44*9356374aSAndroid Build Coastguard Worker// If __kernel_vsyscall uses frame pointer, answer 0.
45*9356374aSAndroid Build Coastguard Worker//
46*9356374aSAndroid Build Coastguard Worker// kMaxBytes tells how many instruction bytes of __kernel_vsyscall
47*9356374aSAndroid Build Coastguard Worker// to analyze before giving up. Up to kMaxBytes+1 bytes of
48*9356374aSAndroid Build Coastguard Worker// instructions could be accessed.
49*9356374aSAndroid Build Coastguard Worker//
50*9356374aSAndroid Build Coastguard Worker// Here are known __kernel_vsyscall instruction sequences:
51*9356374aSAndroid Build Coastguard Worker//
52*9356374aSAndroid Build Coastguard Worker// SYSENTER (linux-2.6.26/arch/x86/vdso/vdso32/sysenter.S).
53*9356374aSAndroid Build Coastguard Worker// Used on Intel.
54*9356374aSAndroid Build Coastguard Worker//  0xffffe400 <__kernel_vsyscall+0>:       push   %ecx
55*9356374aSAndroid Build Coastguard Worker//  0xffffe401 <__kernel_vsyscall+1>:       push   %edx
56*9356374aSAndroid Build Coastguard Worker//  0xffffe402 <__kernel_vsyscall+2>:       push   %ebp
57*9356374aSAndroid Build Coastguard Worker//  0xffffe403 <__kernel_vsyscall+3>:       mov    %esp,%ebp
58*9356374aSAndroid Build Coastguard Worker//  0xffffe405 <__kernel_vsyscall+5>:       sysenter
59*9356374aSAndroid Build Coastguard Worker//
60*9356374aSAndroid Build Coastguard Worker// SYSCALL (see linux-2.6.26/arch/x86/vdso/vdso32/syscall.S).
61*9356374aSAndroid Build Coastguard Worker// Used on AMD.
62*9356374aSAndroid Build Coastguard Worker//  0xffffe400 <__kernel_vsyscall+0>:       push   %ebp
63*9356374aSAndroid Build Coastguard Worker//  0xffffe401 <__kernel_vsyscall+1>:       mov    %ecx,%ebp
64*9356374aSAndroid Build Coastguard Worker//  0xffffe403 <__kernel_vsyscall+3>:       syscall
65*9356374aSAndroid Build Coastguard Worker//
66*9356374aSAndroid Build Coastguard Worker
67*9356374aSAndroid Build Coastguard Worker// The sequence below isn't actually expected in Google fleet,
68*9356374aSAndroid Build Coastguard Worker// here only for completeness. Remove this comment from OSS release.
69*9356374aSAndroid Build Coastguard Worker
70*9356374aSAndroid Build Coastguard Worker// i386 (see linux-2.6.26/arch/x86/vdso/vdso32/int80.S)
71*9356374aSAndroid Build Coastguard Worker//  0xffffe400 <__kernel_vsyscall+0>:       int $0x80
72*9356374aSAndroid Build Coastguard Worker//  0xffffe401 <__kernel_vsyscall+1>:       ret
73*9356374aSAndroid Build Coastguard Worker//
74*9356374aSAndroid Build Coastguard Workerstatic const int kMaxBytes = 10;
75*9356374aSAndroid Build Coastguard Worker
76*9356374aSAndroid Build Coastguard Worker// We use assert()s instead of DCHECK()s -- this is too low level
77*9356374aSAndroid Build Coastguard Worker// for DCHECK().
78*9356374aSAndroid Build Coastguard Worker
79*9356374aSAndroid Build Coastguard Workerstatic int CountPushInstructions(const unsigned char *const addr) {
80*9356374aSAndroid Build Coastguard Worker  int result = 0;
81*9356374aSAndroid Build Coastguard Worker  for (int i = 0; i < kMaxBytes; ++i) {
82*9356374aSAndroid Build Coastguard Worker    if (addr[i] == 0x89) {
83*9356374aSAndroid Build Coastguard Worker      // "mov reg,reg"
84*9356374aSAndroid Build Coastguard Worker      if (addr[i + 1] == 0xE5) {
85*9356374aSAndroid Build Coastguard Worker        // Found "mov %esp,%ebp".
86*9356374aSAndroid Build Coastguard Worker        return 0;
87*9356374aSAndroid Build Coastguard Worker      }
88*9356374aSAndroid Build Coastguard Worker      ++i;  // Skip register encoding byte.
89*9356374aSAndroid Build Coastguard Worker    } else if (addr[i] == 0x0F &&
90*9356374aSAndroid Build Coastguard Worker               (addr[i + 1] == 0x34 || addr[i + 1] == 0x05)) {
91*9356374aSAndroid Build Coastguard Worker      // Found "sysenter" or "syscall".
92*9356374aSAndroid Build Coastguard Worker      return result;
93*9356374aSAndroid Build Coastguard Worker    } else if ((addr[i] & 0xF0) == 0x50) {
94*9356374aSAndroid Build Coastguard Worker      // Found "push %reg".
95*9356374aSAndroid Build Coastguard Worker      ++result;
96*9356374aSAndroid Build Coastguard Worker    } else if (addr[i] == 0xCD && addr[i + 1] == 0x80) {
97*9356374aSAndroid Build Coastguard Worker      // Found "int $0x80"
98*9356374aSAndroid Build Coastguard Worker      assert(result == 0);
99*9356374aSAndroid Build Coastguard Worker      return 0;
100*9356374aSAndroid Build Coastguard Worker    } else {
101*9356374aSAndroid Build Coastguard Worker      // Unexpected instruction.
102*9356374aSAndroid Build Coastguard Worker      assert(false && "unexpected instruction in __kernel_vsyscall");
103*9356374aSAndroid Build Coastguard Worker      return 0;
104*9356374aSAndroid Build Coastguard Worker    }
105*9356374aSAndroid Build Coastguard Worker  }
106*9356374aSAndroid Build Coastguard Worker  // Unexpected: didn't find SYSENTER or SYSCALL in
107*9356374aSAndroid Build Coastguard Worker  // [__kernel_vsyscall, __kernel_vsyscall + kMaxBytes) interval.
108*9356374aSAndroid Build Coastguard Worker  assert(false && "did not find SYSENTER or SYSCALL in __kernel_vsyscall");
109*9356374aSAndroid Build Coastguard Worker  return 0;
110*9356374aSAndroid Build Coastguard Worker}
111*9356374aSAndroid Build Coastguard Worker#endif
112*9356374aSAndroid Build Coastguard Worker
113*9356374aSAndroid Build Coastguard Worker// Assume stack frames larger than 100,000 bytes are bogus.
114*9356374aSAndroid Build Coastguard Workerstatic const int kMaxFrameBytes = 100000;
115*9356374aSAndroid Build Coastguard Worker// Stack end to use when we don't know the actual stack end
116*9356374aSAndroid Build Coastguard Worker// (effectively just the end of address space).
117*9356374aSAndroid Build Coastguard Workerconstexpr uintptr_t kUnknownStackEnd =
118*9356374aSAndroid Build Coastguard Worker    std::numeric_limits<size_t>::max() - sizeof(void *);
119*9356374aSAndroid Build Coastguard Worker
120*9356374aSAndroid Build Coastguard Worker// Returns the stack frame pointer from signal context, 0 if unknown.
121*9356374aSAndroid Build Coastguard Worker// vuc is a ucontext_t *.  We use void* to avoid the use
122*9356374aSAndroid Build Coastguard Worker// of ucontext_t on non-POSIX systems.
123*9356374aSAndroid Build Coastguard Workerstatic uintptr_t GetFP(const void *vuc) {
124*9356374aSAndroid Build Coastguard Worker#if !defined(__linux__)
125*9356374aSAndroid Build Coastguard Worker  static_cast<void>(vuc);  // Avoid an unused argument compiler warning.
126*9356374aSAndroid Build Coastguard Worker#else
127*9356374aSAndroid Build Coastguard Worker  if (vuc != nullptr) {
128*9356374aSAndroid Build Coastguard Worker    auto *uc = reinterpret_cast<const ucontext_t *>(vuc);
129*9356374aSAndroid Build Coastguard Worker#if defined(__i386__)
130*9356374aSAndroid Build Coastguard Worker    const auto bp = uc->uc_mcontext.gregs[REG_EBP];
131*9356374aSAndroid Build Coastguard Worker    const auto sp = uc->uc_mcontext.gregs[REG_ESP];
132*9356374aSAndroid Build Coastguard Worker#elif defined(__x86_64__)
133*9356374aSAndroid Build Coastguard Worker    const auto bp = uc->uc_mcontext.gregs[REG_RBP];
134*9356374aSAndroid Build Coastguard Worker    const auto sp = uc->uc_mcontext.gregs[REG_RSP];
135*9356374aSAndroid Build Coastguard Worker#else
136*9356374aSAndroid Build Coastguard Worker    const uintptr_t bp = 0;
137*9356374aSAndroid Build Coastguard Worker    const uintptr_t sp = 0;
138*9356374aSAndroid Build Coastguard Worker#endif
139*9356374aSAndroid Build Coastguard Worker    // Sanity-check that the base pointer is valid. It's possible that some
140*9356374aSAndroid Build Coastguard Worker    // code in the process is compiled with --copt=-fomit-frame-pointer or
141*9356374aSAndroid Build Coastguard Worker    // --copt=-momit-leaf-frame-pointer.
142*9356374aSAndroid Build Coastguard Worker    //
143*9356374aSAndroid Build Coastguard Worker    // TODO(bcmills): -momit-leaf-frame-pointer is currently the default
144*9356374aSAndroid Build Coastguard Worker    // behavior when building with clang.  Talk to the C++ toolchain team about
145*9356374aSAndroid Build Coastguard Worker    // fixing that.
146*9356374aSAndroid Build Coastguard Worker    if (bp >= sp && bp - sp <= kMaxFrameBytes)
147*9356374aSAndroid Build Coastguard Worker      return static_cast<uintptr_t>(bp);
148*9356374aSAndroid Build Coastguard Worker
149*9356374aSAndroid Build Coastguard Worker    // If bp isn't a plausible frame pointer, return the stack pointer instead.
150*9356374aSAndroid Build Coastguard Worker    // If we're lucky, it points to the start of a stack frame; otherwise, we'll
151*9356374aSAndroid Build Coastguard Worker    // get one frame of garbage in the stack trace and fail the sanity check on
152*9356374aSAndroid Build Coastguard Worker    // the next iteration.
153*9356374aSAndroid Build Coastguard Worker    return static_cast<uintptr_t>(sp);
154*9356374aSAndroid Build Coastguard Worker  }
155*9356374aSAndroid Build Coastguard Worker#endif
156*9356374aSAndroid Build Coastguard Worker  return 0;
157*9356374aSAndroid Build Coastguard Worker}
158*9356374aSAndroid Build Coastguard Worker
159*9356374aSAndroid Build Coastguard Worker// Given a pointer to a stack frame, locate and return the calling
160*9356374aSAndroid Build Coastguard Worker// stackframe, or return null if no stackframe can be found. Perform sanity
161*9356374aSAndroid Build Coastguard Worker// checks (the strictness of which is controlled by the boolean parameter
162*9356374aSAndroid Build Coastguard Worker// "STRICT_UNWINDING") to reduce the chance that a bad pointer is returned.
163*9356374aSAndroid Build Coastguard Workertemplate <bool STRICT_UNWINDING, bool WITH_CONTEXT>
164*9356374aSAndroid Build Coastguard WorkerABSL_ATTRIBUTE_NO_SANITIZE_ADDRESS  // May read random elements from stack.
165*9356374aSAndroid Build Coastguard WorkerABSL_ATTRIBUTE_NO_SANITIZE_MEMORY   // May read random elements from stack.
166*9356374aSAndroid Build Coastguard Workerstatic void **NextStackFrame(void **old_fp, const void *uc,
167*9356374aSAndroid Build Coastguard Worker                             size_t stack_low, size_t stack_high) {
168*9356374aSAndroid Build Coastguard Worker  void **new_fp = (void **)*old_fp;
169*9356374aSAndroid Build Coastguard Worker
170*9356374aSAndroid Build Coastguard Worker#if defined(__linux__) && defined(__i386__)
171*9356374aSAndroid Build Coastguard Worker  if (WITH_CONTEXT && uc != nullptr) {
172*9356374aSAndroid Build Coastguard Worker    // How many "push %reg" instructions are there at __kernel_vsyscall?
173*9356374aSAndroid Build Coastguard Worker    // This is constant for a given kernel and processor, so compute
174*9356374aSAndroid Build Coastguard Worker    // it only once.
175*9356374aSAndroid Build Coastguard Worker    static int num_push_instructions = -1;  // Sentinel: not computed yet.
176*9356374aSAndroid Build Coastguard Worker    // Initialize with sentinel value: __kernel_rt_sigreturn can not possibly
177*9356374aSAndroid Build Coastguard Worker    // be there.
178*9356374aSAndroid Build Coastguard Worker    static const unsigned char *kernel_rt_sigreturn_address = nullptr;
179*9356374aSAndroid Build Coastguard Worker    static const unsigned char *kernel_vsyscall_address = nullptr;
180*9356374aSAndroid Build Coastguard Worker    if (num_push_instructions == -1) {
181*9356374aSAndroid Build Coastguard Worker#ifdef ABSL_HAVE_VDSO_SUPPORT
182*9356374aSAndroid Build Coastguard Worker      absl::debugging_internal::VDSOSupport vdso;
183*9356374aSAndroid Build Coastguard Worker      if (vdso.IsPresent()) {
184*9356374aSAndroid Build Coastguard Worker        absl::debugging_internal::VDSOSupport::SymbolInfo
185*9356374aSAndroid Build Coastguard Worker            rt_sigreturn_symbol_info;
186*9356374aSAndroid Build Coastguard Worker        absl::debugging_internal::VDSOSupport::SymbolInfo vsyscall_symbol_info;
187*9356374aSAndroid Build Coastguard Worker        if (!vdso.LookupSymbol("__kernel_rt_sigreturn", "LINUX_2.5", STT_FUNC,
188*9356374aSAndroid Build Coastguard Worker                               &rt_sigreturn_symbol_info) ||
189*9356374aSAndroid Build Coastguard Worker            !vdso.LookupSymbol("__kernel_vsyscall", "LINUX_2.5", STT_FUNC,
190*9356374aSAndroid Build Coastguard Worker                               &vsyscall_symbol_info) ||
191*9356374aSAndroid Build Coastguard Worker            rt_sigreturn_symbol_info.address == nullptr ||
192*9356374aSAndroid Build Coastguard Worker            vsyscall_symbol_info.address == nullptr) {
193*9356374aSAndroid Build Coastguard Worker          // Unexpected: 32-bit VDSO is present, yet one of the expected
194*9356374aSAndroid Build Coastguard Worker          // symbols is missing or null.
195*9356374aSAndroid Build Coastguard Worker          assert(false && "VDSO is present, but doesn't have expected symbols");
196*9356374aSAndroid Build Coastguard Worker          num_push_instructions = 0;
197*9356374aSAndroid Build Coastguard Worker        } else {
198*9356374aSAndroid Build Coastguard Worker          kernel_rt_sigreturn_address =
199*9356374aSAndroid Build Coastguard Worker              reinterpret_cast<const unsigned char *>(
200*9356374aSAndroid Build Coastguard Worker                  rt_sigreturn_symbol_info.address);
201*9356374aSAndroid Build Coastguard Worker          kernel_vsyscall_address =
202*9356374aSAndroid Build Coastguard Worker              reinterpret_cast<const unsigned char *>(
203*9356374aSAndroid Build Coastguard Worker                  vsyscall_symbol_info.address);
204*9356374aSAndroid Build Coastguard Worker          num_push_instructions =
205*9356374aSAndroid Build Coastguard Worker              CountPushInstructions(kernel_vsyscall_address);
206*9356374aSAndroid Build Coastguard Worker        }
207*9356374aSAndroid Build Coastguard Worker      } else {
208*9356374aSAndroid Build Coastguard Worker        num_push_instructions = 0;
209*9356374aSAndroid Build Coastguard Worker      }
210*9356374aSAndroid Build Coastguard Worker#else  // ABSL_HAVE_VDSO_SUPPORT
211*9356374aSAndroid Build Coastguard Worker      num_push_instructions = 0;
212*9356374aSAndroid Build Coastguard Worker#endif  // ABSL_HAVE_VDSO_SUPPORT
213*9356374aSAndroid Build Coastguard Worker    }
214*9356374aSAndroid Build Coastguard Worker    if (num_push_instructions != 0 && kernel_rt_sigreturn_address != nullptr &&
215*9356374aSAndroid Build Coastguard Worker        old_fp[1] == kernel_rt_sigreturn_address) {
216*9356374aSAndroid Build Coastguard Worker      const ucontext_t *ucv = static_cast<const ucontext_t *>(uc);
217*9356374aSAndroid Build Coastguard Worker      // This kernel does not use frame pointer in its VDSO code,
218*9356374aSAndroid Build Coastguard Worker      // and so %ebp is not suitable for unwinding.
219*9356374aSAndroid Build Coastguard Worker      void **const reg_ebp =
220*9356374aSAndroid Build Coastguard Worker          reinterpret_cast<void **>(ucv->uc_mcontext.gregs[REG_EBP]);
221*9356374aSAndroid Build Coastguard Worker      const unsigned char *const reg_eip =
222*9356374aSAndroid Build Coastguard Worker          reinterpret_cast<unsigned char *>(ucv->uc_mcontext.gregs[REG_EIP]);
223*9356374aSAndroid Build Coastguard Worker      if (new_fp == reg_ebp && kernel_vsyscall_address <= reg_eip &&
224*9356374aSAndroid Build Coastguard Worker          reg_eip - kernel_vsyscall_address < kMaxBytes) {
225*9356374aSAndroid Build Coastguard Worker        // We "stepped up" to __kernel_vsyscall, but %ebp is not usable.
226*9356374aSAndroid Build Coastguard Worker        // Restore from 'ucv' instead.
227*9356374aSAndroid Build Coastguard Worker        void **const reg_esp =
228*9356374aSAndroid Build Coastguard Worker            reinterpret_cast<void **>(ucv->uc_mcontext.gregs[REG_ESP]);
229*9356374aSAndroid Build Coastguard Worker        // Check that alleged %esp is not null and is reasonably aligned.
230*9356374aSAndroid Build Coastguard Worker        if (reg_esp &&
231*9356374aSAndroid Build Coastguard Worker            ((uintptr_t)reg_esp & (sizeof(reg_esp) - 1)) == 0) {
232*9356374aSAndroid Build Coastguard Worker          // Check that alleged %esp is actually readable. This is to prevent
233*9356374aSAndroid Build Coastguard Worker          // "double fault" in case we hit the first fault due to e.g. stack
234*9356374aSAndroid Build Coastguard Worker          // corruption.
235*9356374aSAndroid Build Coastguard Worker          void *const reg_esp2 = reg_esp[num_push_instructions - 1];
236*9356374aSAndroid Build Coastguard Worker          if (AddressIsReadable(reg_esp2)) {
237*9356374aSAndroid Build Coastguard Worker            // Alleged %esp is readable, use it for further unwinding.
238*9356374aSAndroid Build Coastguard Worker            new_fp = reinterpret_cast<void **>(reg_esp2);
239*9356374aSAndroid Build Coastguard Worker          }
240*9356374aSAndroid Build Coastguard Worker        }
241*9356374aSAndroid Build Coastguard Worker      }
242*9356374aSAndroid Build Coastguard Worker    }
243*9356374aSAndroid Build Coastguard Worker  }
244*9356374aSAndroid Build Coastguard Worker#endif
245*9356374aSAndroid Build Coastguard Worker
246*9356374aSAndroid Build Coastguard Worker  const uintptr_t old_fp_u = reinterpret_cast<uintptr_t>(old_fp);
247*9356374aSAndroid Build Coastguard Worker  const uintptr_t new_fp_u = reinterpret_cast<uintptr_t>(new_fp);
248*9356374aSAndroid Build Coastguard Worker
249*9356374aSAndroid Build Coastguard Worker  // Check that the transition from frame pointer old_fp to frame
250*9356374aSAndroid Build Coastguard Worker  // pointer new_fp isn't clearly bogus.  Skip the checks if new_fp
251*9356374aSAndroid Build Coastguard Worker  // matches the signal context, so that we don't skip out early when
252*9356374aSAndroid Build Coastguard Worker  // using an alternate signal stack.
253*9356374aSAndroid Build Coastguard Worker  //
254*9356374aSAndroid Build Coastguard Worker  // TODO(bcmills): The GetFP call should be completely unnecessary when
255*9356374aSAndroid Build Coastguard Worker  // ENABLE_COMBINED_UNWINDER is set (because we should be back in the thread's
256*9356374aSAndroid Build Coastguard Worker  // stack by this point), but it is empirically still needed (e.g. when the
257*9356374aSAndroid Build Coastguard Worker  // stack includes a call to abort).  unw_get_reg returns UNW_EBADREG for some
258*9356374aSAndroid Build Coastguard Worker  // frames.  Figure out why GetValidFrameAddr and/or libunwind isn't doing what
259*9356374aSAndroid Build Coastguard Worker  // it's supposed to.
260*9356374aSAndroid Build Coastguard Worker  if (STRICT_UNWINDING &&
261*9356374aSAndroid Build Coastguard Worker      (!WITH_CONTEXT || uc == nullptr || new_fp_u != GetFP(uc))) {
262*9356374aSAndroid Build Coastguard Worker    // With the stack growing downwards, older stack frame must be
263*9356374aSAndroid Build Coastguard Worker    // at a greater address that the current one.
264*9356374aSAndroid Build Coastguard Worker    if (new_fp_u <= old_fp_u) return nullptr;
265*9356374aSAndroid Build Coastguard Worker
266*9356374aSAndroid Build Coastguard Worker    // If we get a very large frame size, it may be an indication that we
267*9356374aSAndroid Build Coastguard Worker    // guessed frame pointers incorrectly and now risk a paging fault
268*9356374aSAndroid Build Coastguard Worker    // dereferencing a wrong frame pointer. Or maybe not because large frames
269*9356374aSAndroid Build Coastguard Worker    // are possible as well. The main stack is assumed to be readable,
270*9356374aSAndroid Build Coastguard Worker    // so we assume the large frame is legit if we know the real stack bounds
271*9356374aSAndroid Build Coastguard Worker    // and are within the stack.
272*9356374aSAndroid Build Coastguard Worker    if (new_fp_u - old_fp_u > kMaxFrameBytes) {
273*9356374aSAndroid Build Coastguard Worker      if (stack_high < kUnknownStackEnd &&
274*9356374aSAndroid Build Coastguard Worker          static_cast<size_t>(getpagesize()) < stack_low) {
275*9356374aSAndroid Build Coastguard Worker        // Stack bounds are known.
276*9356374aSAndroid Build Coastguard Worker        if (!(stack_low < new_fp_u && new_fp_u <= stack_high)) {
277*9356374aSAndroid Build Coastguard Worker          // new_fp_u is not within the known stack.
278*9356374aSAndroid Build Coastguard Worker          return nullptr;
279*9356374aSAndroid Build Coastguard Worker        }
280*9356374aSAndroid Build Coastguard Worker      } else {
281*9356374aSAndroid Build Coastguard Worker        // Stack bounds are unknown, prefer truncated stack to possible crash.
282*9356374aSAndroid Build Coastguard Worker        return nullptr;
283*9356374aSAndroid Build Coastguard Worker      }
284*9356374aSAndroid Build Coastguard Worker    }
285*9356374aSAndroid Build Coastguard Worker    if (stack_low < old_fp_u && old_fp_u <= stack_high) {
286*9356374aSAndroid Build Coastguard Worker      // Old BP was in the expected stack region...
287*9356374aSAndroid Build Coastguard Worker      if (!(stack_low < new_fp_u && new_fp_u <= stack_high)) {
288*9356374aSAndroid Build Coastguard Worker        // ... but new BP is outside of expected stack region.
289*9356374aSAndroid Build Coastguard Worker        // It is most likely bogus.
290*9356374aSAndroid Build Coastguard Worker        return nullptr;
291*9356374aSAndroid Build Coastguard Worker      }
292*9356374aSAndroid Build Coastguard Worker    } else {
293*9356374aSAndroid Build Coastguard Worker      // We may be here if we are executing in a co-routine with a
294*9356374aSAndroid Build Coastguard Worker      // separate stack. We can't do safety checks in this case.
295*9356374aSAndroid Build Coastguard Worker    }
296*9356374aSAndroid Build Coastguard Worker  } else {
297*9356374aSAndroid Build Coastguard Worker    if (new_fp == nullptr) return nullptr;  // skip AddressIsReadable() below
298*9356374aSAndroid Build Coastguard Worker    // In the non-strict mode, allow discontiguous stack frames.
299*9356374aSAndroid Build Coastguard Worker    // (alternate-signal-stacks for example).
300*9356374aSAndroid Build Coastguard Worker    if (new_fp == old_fp) return nullptr;
301*9356374aSAndroid Build Coastguard Worker  }
302*9356374aSAndroid Build Coastguard Worker
303*9356374aSAndroid Build Coastguard Worker  if (new_fp_u & (sizeof(void *) - 1)) return nullptr;
304*9356374aSAndroid Build Coastguard Worker#ifdef __i386__
305*9356374aSAndroid Build Coastguard Worker  // On 32-bit machines, the stack pointer can be very close to
306*9356374aSAndroid Build Coastguard Worker  // 0xffffffff, so we explicitly check for a pointer into the
307*9356374aSAndroid Build Coastguard Worker  // last two pages in the address space
308*9356374aSAndroid Build Coastguard Worker  if (new_fp_u >= 0xffffe000) return nullptr;
309*9356374aSAndroid Build Coastguard Worker#endif
310*9356374aSAndroid Build Coastguard Worker#if !defined(_WIN32)
311*9356374aSAndroid Build Coastguard Worker  if (!STRICT_UNWINDING) {
312*9356374aSAndroid Build Coastguard Worker    // Lax sanity checks cause a crash in 32-bit tcmalloc/crash_reason_test
313*9356374aSAndroid Build Coastguard Worker    // on AMD-based machines with VDSO-enabled kernels.
314*9356374aSAndroid Build Coastguard Worker    // Make an extra sanity check to insure new_fp is readable.
315*9356374aSAndroid Build Coastguard Worker    // Note: NextStackFrame<false>() is only called while the program
316*9356374aSAndroid Build Coastguard Worker    //       is already on its last leg, so it's ok to be slow here.
317*9356374aSAndroid Build Coastguard Worker
318*9356374aSAndroid Build Coastguard Worker    if (!AddressIsReadable(new_fp)) {
319*9356374aSAndroid Build Coastguard Worker      return nullptr;
320*9356374aSAndroid Build Coastguard Worker    }
321*9356374aSAndroid Build Coastguard Worker  }
322*9356374aSAndroid Build Coastguard Worker#endif
323*9356374aSAndroid Build Coastguard Worker  return new_fp;
324*9356374aSAndroid Build Coastguard Worker}
325*9356374aSAndroid Build Coastguard Worker
326*9356374aSAndroid Build Coastguard Workertemplate <bool IS_STACK_FRAMES, bool IS_WITH_CONTEXT>
327*9356374aSAndroid Build Coastguard WorkerABSL_ATTRIBUTE_NO_SANITIZE_ADDRESS  // May read random elements from stack.
328*9356374aSAndroid Build Coastguard WorkerABSL_ATTRIBUTE_NO_SANITIZE_MEMORY   // May read random elements from stack.
329*9356374aSAndroid Build Coastguard WorkerABSL_ATTRIBUTE_NOINLINE
330*9356374aSAndroid Build Coastguard Workerstatic int UnwindImpl(void **result, int *sizes, int max_depth, int skip_count,
331*9356374aSAndroid Build Coastguard Worker                      const void *ucp, int *min_dropped_frames) {
332*9356374aSAndroid Build Coastguard Worker  int n = 0;
333*9356374aSAndroid Build Coastguard Worker  void **fp = reinterpret_cast<void **>(__builtin_frame_address(0));
334*9356374aSAndroid Build Coastguard Worker
335*9356374aSAndroid Build Coastguard Worker  // Assume that the first page is not stack.
336*9356374aSAndroid Build Coastguard Worker  size_t stack_low = static_cast<size_t>(getpagesize());
337*9356374aSAndroid Build Coastguard Worker  size_t stack_high = kUnknownStackEnd;
338*9356374aSAndroid Build Coastguard Worker
339*9356374aSAndroid Build Coastguard Worker  while (fp && n < max_depth) {
340*9356374aSAndroid Build Coastguard Worker    if (*(fp + 1) == reinterpret_cast<void *>(0)) {
341*9356374aSAndroid Build Coastguard Worker      // In 64-bit code, we often see a frame that
342*9356374aSAndroid Build Coastguard Worker      // points to itself and has a return address of 0.
343*9356374aSAndroid Build Coastguard Worker      break;
344*9356374aSAndroid Build Coastguard Worker    }
345*9356374aSAndroid Build Coastguard Worker    void **next_fp = NextStackFrame<!IS_STACK_FRAMES, IS_WITH_CONTEXT>(
346*9356374aSAndroid Build Coastguard Worker        fp, ucp, stack_low, stack_high);
347*9356374aSAndroid Build Coastguard Worker    if (skip_count > 0) {
348*9356374aSAndroid Build Coastguard Worker      skip_count--;
349*9356374aSAndroid Build Coastguard Worker    } else {
350*9356374aSAndroid Build Coastguard Worker      result[n] = *(fp + 1);
351*9356374aSAndroid Build Coastguard Worker      if (IS_STACK_FRAMES) {
352*9356374aSAndroid Build Coastguard Worker        if (next_fp > fp) {
353*9356374aSAndroid Build Coastguard Worker          sizes[n] = static_cast<int>(
354*9356374aSAndroid Build Coastguard Worker              reinterpret_cast<uintptr_t>(next_fp) -
355*9356374aSAndroid Build Coastguard Worker              reinterpret_cast<uintptr_t>(fp));
356*9356374aSAndroid Build Coastguard Worker        } else {
357*9356374aSAndroid Build Coastguard Worker          // A frame-size of 0 is used to indicate unknown frame size.
358*9356374aSAndroid Build Coastguard Worker          sizes[n] = 0;
359*9356374aSAndroid Build Coastguard Worker        }
360*9356374aSAndroid Build Coastguard Worker      }
361*9356374aSAndroid Build Coastguard Worker      n++;
362*9356374aSAndroid Build Coastguard Worker    }
363*9356374aSAndroid Build Coastguard Worker    fp = next_fp;
364*9356374aSAndroid Build Coastguard Worker  }
365*9356374aSAndroid Build Coastguard Worker  if (min_dropped_frames != nullptr) {
366*9356374aSAndroid Build Coastguard Worker    // Implementation detail: we clamp the max of frames we are willing to
367*9356374aSAndroid Build Coastguard Worker    // count, so as not to spend too much time in the loop below.
368*9356374aSAndroid Build Coastguard Worker    const int kMaxUnwind = 1000;
369*9356374aSAndroid Build Coastguard Worker    int num_dropped_frames = 0;
370*9356374aSAndroid Build Coastguard Worker    for (int j = 0; fp != nullptr && j < kMaxUnwind; j++) {
371*9356374aSAndroid Build Coastguard Worker      if (skip_count > 0) {
372*9356374aSAndroid Build Coastguard Worker        skip_count--;
373*9356374aSAndroid Build Coastguard Worker      } else {
374*9356374aSAndroid Build Coastguard Worker        num_dropped_frames++;
375*9356374aSAndroid Build Coastguard Worker      }
376*9356374aSAndroid Build Coastguard Worker      fp = NextStackFrame<!IS_STACK_FRAMES, IS_WITH_CONTEXT>(fp, ucp, stack_low,
377*9356374aSAndroid Build Coastguard Worker                                                             stack_high);
378*9356374aSAndroid Build Coastguard Worker    }
379*9356374aSAndroid Build Coastguard Worker    *min_dropped_frames = num_dropped_frames;
380*9356374aSAndroid Build Coastguard Worker  }
381*9356374aSAndroid Build Coastguard Worker  return n;
382*9356374aSAndroid Build Coastguard Worker}
383*9356374aSAndroid Build Coastguard Worker
384*9356374aSAndroid Build Coastguard Workernamespace absl {
385*9356374aSAndroid Build Coastguard WorkerABSL_NAMESPACE_BEGIN
386*9356374aSAndroid Build Coastguard Workernamespace debugging_internal {
387*9356374aSAndroid Build Coastguard Workerbool StackTraceWorksForTest() {
388*9356374aSAndroid Build Coastguard Worker  return true;
389*9356374aSAndroid Build Coastguard Worker}
390*9356374aSAndroid Build Coastguard Worker}  // namespace debugging_internal
391*9356374aSAndroid Build Coastguard WorkerABSL_NAMESPACE_END
392*9356374aSAndroid Build Coastguard Worker}  // namespace absl
393*9356374aSAndroid Build Coastguard Worker
394*9356374aSAndroid Build Coastguard Worker#endif  // ABSL_DEBUGGING_INTERNAL_STACKTRACE_X86_INL_INC_
395