• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2012 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "base/debug/stack_trace.h"
6 
7 #include <string.h>
8 
9 #include <algorithm>
10 #include <sstream>
11 #include <utility>
12 
13 #include "base/check_op.h"
14 #include "base/debug/debugging_buildflags.h"
15 #include "build/build_config.h"
16 #include "build/config/compiler/compiler_buildflags.h"
17 
18 #if BUILDFLAG(CAN_UNWIND_WITH_FRAME_POINTERS)
19 #include <optional>
20 
21 #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_ANDROID)
22 #include <pthread.h>
23 
24 #include "base/process/process_handle.h"
25 #include "base/threading/platform_thread.h"
26 #endif
27 
28 #if BUILDFLAG(IS_APPLE)
29 #include <pthread.h>
30 #endif
31 
32 #if (BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)) && defined(__GLIBC__)
33 extern "C" void* __libc_stack_end;
34 #endif
35 
36 #endif  // BUILDFLAG(CAN_UNWIND_WITH_FRAME_POINTERS)
37 
38 namespace base {
39 namespace debug {
40 
41 namespace {
42 
43 #if BUILDFLAG(CAN_UNWIND_WITH_FRAME_POINTERS)
44 
45 #if defined(__arm__) && defined(__GNUC__) && !defined(__clang__)
46 // GCC and LLVM generate slightly different frames on ARM, see
47 // https://llvm.org/bugs/show_bug.cgi?id=18505 - LLVM generates
48 // x86-compatible frame, while GCC needs adjustment.
49 constexpr size_t kStackFrameAdjustment = sizeof(uintptr_t);
50 #else
51 constexpr size_t kStackFrameAdjustment = 0;
52 #endif
53 
54 // On Arm-v8.3+ systems with pointer authentication codes (PAC), signature bits
55 // are set in the top bits of the pointer, which confuses test assertions.
56 // Because the signature size can vary based on the system configuration, use
57 // the xpaclri instruction to remove the signature.
StripPointerAuthenticationBits(uintptr_t ptr)58 static uintptr_t StripPointerAuthenticationBits(uintptr_t ptr) {
59 #if defined(ARCH_CPU_ARM64)
60   // A single Chromium binary currently spans all Arm systems (including those
61   // with and without pointer authentication). xpaclri is used here because it's
62   // in the HINT space and treated as a no-op on older Arm cores (unlike the
63   // more generic xpaci which has a new encoding). The downside is that ptr has
64   // to be moved to x30 to use this instruction. TODO(richard.townsend@arm.com):
65   // replace with an intrinsic once that is available.
66   register uintptr_t x30 __asm("x30") = ptr;
67   asm("xpaclri" : "+r"(x30));
68   return x30;
69 #else
70   // No-op on other platforms.
71   return ptr;
72 #endif
73 }
74 
GetNextStackFrame(uintptr_t fp)75 uintptr_t GetNextStackFrame(uintptr_t fp) {
76   const uintptr_t* fp_addr = reinterpret_cast<const uintptr_t*>(fp);
77   // SAFETY: `fp` is the address of an array of pointers. The first element
78   // is the next stack frame, the second element is the PC.
79   UNSAFE_BUFFERS({
80     MSAN_UNPOISON(&fp_addr[0], sizeof(uintptr_t));
81     return fp_addr[0] - kStackFrameAdjustment;
82   })
83 }
84 
GetStackFramePC(uintptr_t fp)85 uintptr_t GetStackFramePC(uintptr_t fp) {
86   const uintptr_t* fp_addr = reinterpret_cast<const uintptr_t*>(fp);
87   // SAFETY: `fp` is the address of an array of pointers. The first element
88   // is the next stack frame, the second element is the PC.
89   UNSAFE_BUFFERS({
90     MSAN_UNPOISON(&fp_addr[1], sizeof(uintptr_t));
91     return StripPointerAuthenticationBits(fp_addr[1]);
92   })
93 }
94 
IsStackFrameValid(uintptr_t fp,uintptr_t prev_fp,uintptr_t stack_end)95 bool IsStackFrameValid(uintptr_t fp, uintptr_t prev_fp, uintptr_t stack_end) {
96   // With the stack growing downwards, older stack frame must be
97   // at a greater address that the current one.
98   if (fp <= prev_fp) return false;
99 
100   // Assume huge stack frames are bogus.
101   if (fp - prev_fp > 100000) return false;
102 
103   // Check alignment.
104   if (fp & (sizeof(uintptr_t) - 1)) return false;
105 
106   if (stack_end) {
107     // Both fp[0] and fp[1] must be within the stack.
108     if (fp > stack_end - 2 * sizeof(uintptr_t)) return false;
109 
110     // Additional check to filter out false positives.
111     if (GetStackFramePC(fp) < 32768) return false;
112   }
113 
114   return true;
115 }
116 
117 // ScanStackForNextFrame() scans the stack for a valid frame to allow unwinding
118 // past system libraries. Only supported on Linux where system libraries are
119 // usually in the middle of the trace:
120 //
121 //   TraceStackFramePointers
122 //   <more frames from Chrome>
123 //   base::WorkSourceDispatch   <-- unwinding stops (next frame is invalid),
124 //   g_main_context_dispatch        ScanStackForNextFrame() is called
125 //   <more frames from glib>
126 //   g_main_context_iteration
127 //   base::MessagePumpGlib::Run <-- ScanStackForNextFrame() finds valid frame,
128 //   base::RunLoop::Run             unwinding resumes
129 //   <more frames from Chrome>
130 //   __libc_start_main
131 //
132 // ScanStackForNextFrame() returns 0 if it couldn't find a valid frame
133 // (or if stack scanning is not supported on the current platform).
ScanStackForNextFrame(uintptr_t fp,uintptr_t stack_end)134 uintptr_t ScanStackForNextFrame(uintptr_t fp, uintptr_t stack_end) {
135   // Enough to resume almost all prematurely terminated traces.
136   constexpr size_t kMaxStackScanArea = 8192;
137 
138   if (!stack_end) {
139     // Too dangerous to scan without knowing where the stack ends.
140     return 0;
141   }
142 
143   fp += sizeof(uintptr_t);  // current frame is known to be invalid
144   uintptr_t last_fp_to_scan = std::min(fp + kMaxStackScanArea, stack_end) -
145                                   sizeof(uintptr_t);
146   for (;fp <= last_fp_to_scan; fp += sizeof(uintptr_t)) {
147     uintptr_t next_fp = GetNextStackFrame(fp);
148     if (IsStackFrameValid(next_fp, fp, stack_end)) {
149       // Check two frames deep. Since stack frame is just a pointer to
150       // a higher address on the stack, it's relatively easy to find
151       // something that looks like one. However two linked frames are
152       // far less likely to be bogus.
153       uintptr_t next2_fp = GetNextStackFrame(next_fp);
154       if (IsStackFrameValid(next2_fp, next_fp, stack_end)) {
155         return fp;
156       }
157     }
158   }
159 
160   return 0;
161 }
162 
163 // Links stack frame |fp| to |parent_fp|, so that during stack unwinding
164 // TraceStackFramePointers() visits |parent_fp| after visiting |fp|.
165 // Both frame pointers must come from __builtin_frame_address().
166 // Returns previous stack frame |fp| was linked to.
LinkStackFrames(void * fpp,void * parent_fp)167 void* LinkStackFrames(void* fpp, void* parent_fp) {
168   uintptr_t fp = reinterpret_cast<uintptr_t>(fpp) - kStackFrameAdjustment;
169   void* prev_parent_fp = reinterpret_cast<void**>(fp)[0];
170   reinterpret_cast<void**>(fp)[0] = parent_fp;
171   return prev_parent_fp;
172 }
173 
174 #endif  // BUILDFLAG(CAN_UNWIND_WITH_FRAME_POINTERS)
175 
176 // A message to be emitted in place of a symbolized stack trace. Ordinarily used
177 // in death test child processes to inform a developer that they may rerun a
178 // failing test with a switch to prevent the test launcher from suppressing
179 // stacks in such processes.
180 std::string* g_stack_trace_message = nullptr;
181 
182 // True if an OverrideStackTraceOutputForTesting instance is alive to force
183 // or prevent generation of symbolized stack traces despite a suppression
184 // message having been set (or not).
185 OverrideStackTraceOutputForTesting::Mode g_override_suppression =
186     OverrideStackTraceOutputForTesting::Mode::kUnset;
187 
188 }  // namespace
189 
190 #if BUILDFLAG(CAN_UNWIND_WITH_FRAME_POINTERS)
GetStackEnd()191 uintptr_t GetStackEnd() {
192 #if BUILDFLAG(IS_ANDROID)
193   // Bionic reads proc/maps on every call to pthread_getattr_np() when called
194   // from the main thread. So we need to cache end of stack in that case to get
195   // acceptable performance.
196   // For all other threads pthread_getattr_np() is fast enough as it just reads
197   // values from its pthread_t argument.
198   static uintptr_t main_stack_end = 0;
199 
200   bool is_main_thread = GetCurrentProcId() == PlatformThread::CurrentId();
201   if (is_main_thread && main_stack_end) {
202     return main_stack_end;
203   }
204 
205   uintptr_t stack_begin = 0;
206   size_t stack_size = 0;
207   pthread_attr_t attributes;
208   int error = pthread_getattr_np(pthread_self(), &attributes);
209   if (!error) {
210     error = pthread_attr_getstack(
211         &attributes, reinterpret_cast<void**>(&stack_begin), &stack_size);
212     pthread_attr_destroy(&attributes);
213   }
214   DCHECK(!error);
215 
216   uintptr_t stack_end = stack_begin + stack_size;
217   if (is_main_thread) {
218     main_stack_end = stack_end;
219   }
220   return stack_end;  // 0 in case of error
221 #elif BUILDFLAG(IS_APPLE)
222   // No easy way to get end of the stack for non-main threads,
223   // see crbug.com/617730.
224   return reinterpret_cast<uintptr_t>(pthread_get_stackaddr_np(pthread_self()));
225 #else
226 
227 #if (BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)) && defined(__GLIBC__)
228   if (GetCurrentProcId() == PlatformThread::CurrentId()) {
229     // For the main thread we have a shortcut.
230     return reinterpret_cast<uintptr_t>(__libc_stack_end);
231   }
232 #endif
233 
234   // Don't know how to get end of the stack.
235   return 0;
236 #endif
237 }
238 #endif  // BUILDFLAG(CAN_UNWIND_WITH_FRAME_POINTERS)
239 
StackTrace()240 StackTrace::StackTrace() : StackTrace(std::size(trace_)) {}
241 
StackTrace(size_t count)242 StackTrace::StackTrace(size_t count)
243     : count_(ShouldSuppressOutput()
244                  ? 0
245                  : CollectStackTrace(base::span(trace_).first(
246                        std::min(count, std::size(trace_))))) {}
247 
StackTrace(span<const void * const> trace)248 StackTrace::StackTrace(span<const void* const> trace)
249     : count_(std::min(trace.size(), std::size(trace_))) {
250   if (count_) {
251     base::span(trace_).copy_prefix_from(trace.first(count_));
252   }
253 }
254 
255 // static
WillSymbolizeToStreamForTesting()256 bool StackTrace::WillSymbolizeToStreamForTesting() {
257 #if BUILDFLAG(SYMBOL_LEVEL) == 0
258   // Symbols are not expected to be reliable when gn args specifies
259   // symbol_level=0.
260   return false;
261 #elif defined(__UCLIBC__) || defined(_AIX)
262   // StackTrace::OutputToStream() is not implemented under uclibc, nor AIX.
263   // See https://crbug.com/706728
264   return false;
265 #elif defined(OFFICIAL_BUILD) && \
266     ((BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_APPLE)) || BUILDFLAG(IS_FUCHSIA))
267   // On some platforms stack traces require an extra data table that bloats our
268   // binaries, so they're turned off for official builds.
269   return false;
270 #elif defined(OFFICIAL_BUILD) && BUILDFLAG(IS_APPLE)
271   // Official Mac OS X builds contain enough information to unwind the stack,
272   // but not enough to symbolize the output.
273   return false;
274 #elif BUILDFLAG(IS_FUCHSIA) || BUILDFLAG(IS_ANDROID)
275   // Under Fuchsia and Android, StackTrace emits executable build-Ids and
276   // address offsets which are symbolized on the test host system, rather than
277   // being symbolized in-process.
278   return false;
279 #elif BUILDFLAG(PRINT_UNSYMBOLIZED_STACK_TRACES)
280   // Typically set in sanitizer configurations (ASan, TSan, MSan), which emit
281   // unsymbolized stacks and rely on an external script for symbolization.
282   return false;
283 #else
284   return true;
285 #endif
286 }
287 
Print() const288 void StackTrace::Print() const {
289   PrintWithPrefix({});
290 }
291 
PrintWithPrefix(cstring_view prefix_string) const292 void StackTrace::PrintWithPrefix(cstring_view prefix_string) const {
293   if (!count_ || ShouldSuppressOutput()) {
294     if (g_stack_trace_message) {
295       PrintMessageWithPrefix(prefix_string, *g_stack_trace_message);
296     }
297     return;
298   }
299   PrintWithPrefixImpl(prefix_string);
300 }
301 
OutputToStream(std::ostream * os) const302 void StackTrace::OutputToStream(std::ostream* os) const {
303   OutputToStreamWithPrefix(os, {});
304 }
305 
OutputToStreamWithPrefix(std::ostream * os,cstring_view prefix_string) const306 void StackTrace::OutputToStreamWithPrefix(std::ostream* os,
307                                           cstring_view prefix_string) const {
308   if (!count_ || ShouldSuppressOutput()) {
309     if (g_stack_trace_message) {
310       (*os) << prefix_string << *g_stack_trace_message;
311     }
312     return;
313   }
314   OutputToStreamWithPrefixImpl(os, prefix_string);
315 }
316 
ToString() const317 std::string StackTrace::ToString() const {
318   return ToStringWithPrefix({});
319 }
320 
ToStringWithPrefix(cstring_view prefix_string) const321 std::string StackTrace::ToStringWithPrefix(cstring_view prefix_string) const {
322   std::stringstream stream;
323 #if !defined(__UCLIBC__) && !defined(_AIX)
324   OutputToStreamWithPrefix(&stream, prefix_string);
325 #endif
326   return stream.str();
327 }
328 
329 // static
SuppressStackTracesWithMessageForTesting(std::string message)330 void StackTrace::SuppressStackTracesWithMessageForTesting(std::string message) {
331   delete std::exchange(
332       g_stack_trace_message,
333       (message.empty() ? nullptr : new std::string(std::move(message))));
334 }
335 
336 // static
ShouldSuppressOutput()337 bool StackTrace::ShouldSuppressOutput() {
338   using Mode = OverrideStackTraceOutputForTesting::Mode;
339   // Do not generate stack traces if a suppression message has been provided,
340   // unless an OverrideStackTraceOutputForTesting instance is alive.
341   return g_override_suppression != Mode::kUnset
342              ? (g_override_suppression == Mode::kSuppressOutput)
343              : (g_stack_trace_message != nullptr);
344 }
345 
operator <<(std::ostream & os,const StackTrace & s)346 std::ostream& operator<<(std::ostream& os, const StackTrace& s) {
347 #if !defined(__UCLIBC__) && !defined(_AIX)
348   s.OutputToStream(&os);
349 #else
350   os << "StackTrace::OutputToStream not implemented.";
351 #endif
352   return os;
353 }
354 
OverrideStackTraceOutputForTesting(Mode mode)355 OverrideStackTraceOutputForTesting::OverrideStackTraceOutputForTesting(
356     Mode mode) {
357   CHECK_NE(mode, Mode::kUnset);
358   CHECK_EQ(g_override_suppression, Mode::kUnset);  // Nesting not supported.
359   g_override_suppression = mode;
360 }
361 
~OverrideStackTraceOutputForTesting()362 OverrideStackTraceOutputForTesting::~OverrideStackTraceOutputForTesting() {
363   CHECK_NE(g_override_suppression, Mode::kUnset);  // Nesting not supported.
364   g_override_suppression = Mode::kUnset;
365 }
366 
367 #if BUILDFLAG(CAN_UNWIND_WITH_FRAME_POINTERS)
368 
369 struct AddressRange {
370   uintptr_t start;
371   uintptr_t end;
372 };
373 
IsWithinRange(uintptr_t address,const AddressRange & range)374 bool IsWithinRange(uintptr_t address, const AddressRange& range) {
375   return address >= range.start && address <= range.end;
376 }
377 
TraceStackFramePointers(span<const void * > out_trace,size_t skip_initial,bool enable_scanning)378 NOINLINE size_t TraceStackFramePointers(span<const void*> out_trace,
379                                         size_t skip_initial,
380                                         bool enable_scanning) {
381   // Since the stack frame contains the return address (meaning the
382   // address of the next instruction in relation to the caller), it
383   // is necessary to decrement the size of the call instruction, in
384   // order to obtain the address to the call instruction.
385 #if defined(ARCH_CPU_ARM64)
386   static constexpr uintptr_t kCallInstructionSize = 4;
387 #else
388   // For all other ARCH, the call stack may be sightly off by 1 instruction
389   static constexpr uintptr_t kCallInstructionSize = 0;
390 #endif
391 
392   uintptr_t fp = reinterpret_cast<uintptr_t>(__builtin_frame_address(0)) -
393                  kStackFrameAdjustment;
394   uintptr_t stack_end = GetStackEnd();
395   size_t depth = 0;
396   while (depth < out_trace.size()) {
397     uintptr_t pc = GetStackFramePC(fp);
398     if (skip_initial != 0) {
399       skip_initial--;
400     } else {
401       out_trace[depth++] =
402           reinterpret_cast<const void*>(pc - kCallInstructionSize);
403     }
404 
405     uintptr_t next_fp = GetNextStackFrame(fp);
406     if (IsStackFrameValid(next_fp, fp, stack_end)) {
407       fp = next_fp;
408       continue;
409     }
410 
411     if (!enable_scanning) {
412       break;
413     }
414 
415     next_fp = ScanStackForNextFrame(fp, stack_end);
416     if (next_fp) {
417       fp = next_fp;
418     } else {
419       break;
420     }
421   }
422 
423   return depth;
424 }
425 
ScopedStackFrameLinker(void * fp,void * parent_fp)426 ScopedStackFrameLinker::ScopedStackFrameLinker(void* fp, void* parent_fp)
427     : fp_(fp),
428       parent_fp_(parent_fp),
429       original_parent_fp_(LinkStackFrames(fp, parent_fp)) {}
430 
~ScopedStackFrameLinker()431 ScopedStackFrameLinker::~ScopedStackFrameLinker() {
432   void* previous_parent_fp = LinkStackFrames(fp_, original_parent_fp_);
433   CHECK_EQ(parent_fp_, previous_parent_fp)
434       << "Stack frame's parent pointer has changed!";
435 }
436 
437 #endif  // BUILDFLAG(CAN_UNWIND_WITH_FRAME_POINTERS)
438 
439 }  // namespace debug
440 }  // namespace base
441