From 50e9b3f9c7e9198257d0398bf14c8ddad70527cb Mon Sep 17 00:00:00 2001 From: Peter Dillinger Date: Sun, 5 Mar 2023 08:21:57 -0800 Subject: [PATCH] Default print stack traces with GDB on Linux (#11272) Summary: On Linux systems using full ASLR, including CircleCI, the old backtrace()+addr2line stack traces are pretty useless, as seen in some failures under ASSERT_STATUS_CHECKED=1 LIB_MODE=static. Use gdb by default for stack traces under Linux. More detail in code comments. Pull Request resolved: https://github.com/facebook/rocksdb/pull/11272 Test Plan: manual testing locally and on CircleCI with ssh Reviewed By: anand1976 Differential Revision: D43786211 Pulled By: pdillinger fbshipit-source-id: f8c7c77f774b504fbdf7c786ff2430cbc8f5b939 --- port/stack_trace.cc | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/port/stack_trace.cc b/port/stack_trace.cc index 51d136b04..ad648d3bc 100644 --- a/port/stack_trace.cc +++ b/port/stack_trace.cc @@ -141,20 +141,30 @@ void PrintStack(void* frames[], int num_frames) { } void PrintStack(int first_frames_to_skip) { -#if defined(ROCKSDB_DLL) && defined(OS_LINUX) - // LIB_MODE=shared build produces mediocre information from the above - // backtrace+addr2line stack trace method. Try to use GDB in that case, but - // only on Linux where we know how to attach to a particular thread. - bool linux_dll = true; + // Default to getting stack traces with GDB, at least on Linux where we + // know how to attach to a particular thread. + // + // * Address space layout randomization (ASLR) interferes with getting good + // stack information from backtrace+addr2line. This is more likely to show + // up with LIB_MODE=shared builds (when kernel.randomize_va_space >= 1) + // but can also show up with LIB_MODE=static builds ((when + // kernel.randomize_va_space == 2). + // * It doesn't appear easy to detect when ASLR is in use. + // * With DEBUG_LEVEL < 2, backtrace() can skip frames that are not skipped + // in GDB. +#if defined(OS_LINUX) + // Default true, override with ROCKSDB_BACKTRACE_STACK=1 + bool gdb_stack_trace = getenv("ROCKSDB_BACKTRACE_STACK") == nullptr; #else - bool linux_dll = false; + // Default false, override with ROCKSDB_GDB_STACK=1 + bool gdb_stack_trace = getenv("ROCKSDB_GDB_STACK") != nullptr; #endif // Also support invoking interactive debugger on stack trace, with this // envvar set to non-empty char* debug_env = getenv("ROCKSDB_DEBUG"); bool debug = debug_env != nullptr && strlen(debug_env) > 0; - if (linux_dll || debug) { + if (gdb_stack_trace || debug) { // Allow ouside debugger to attach, even with Yama security restrictions #ifdef PR_SET_PTRACER_ANY (void)prctl(PR_SET_PTRACER, PR_SET_PTRACER_ANY, 0, 0, 0);