llvm.org GIT mirror llvm / f77c43d
Reinstate r269992 (reverting r270267), but restricted to cases where glibc is the C standard library implementation in use. This works around a glibc bug in the backtrace() function where it fails to produce a backtrace on x86_64 if libgcc / libunwind is statically linked. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@270276 91177308-0d34-0410-b5e6-96231b3b80d8 Richard Smith 4 years ago
2 changed file(s) with 60 addition(s) and 4 deletion(s). Raw diff Collapse all Expand all
143143 # function checks
144144 check_symbol_exists(arc4random "stdlib.h" HAVE_DECL_ARC4RANDOM)
145145 check_symbol_exists(backtrace "execinfo.h" HAVE_BACKTRACE)
146 check_symbol_exists(_Unwind_Backtrace "unwind.h" HAVE_UNWIND_BACKTRACE)
146147 check_symbol_exists(getpagesize unistd.h HAVE_GETPAGESIZE)
147148 check_symbol_exists(getrusage sys/resource.h HAVE_GETRUSAGE)
148149 check_symbol_exists(setrlimit sys/resource.h HAVE_SETRLIMIT)
4545 #endif
4646 #if HAVE_LINK_H
4747 #include
48 #endif
49 #if HAVE_UNWIND_BACKTRACE
50 // FIXME: We should be able to use for any target that has an
51 // _Unwind_Backtrace function, but on FreeBSD the configure test passes
52 // despite the function not existing, and on Android, conflicts
53 // with .
54 #ifdef __GLIBC__
55 #include
56 #else
57 #undef HAVE_UNWIND_BACKTRACE
58 #endif
4859 #endif
4960
5061 using namespace llvm;
339350 }
340351 #endif // defined(HAVE_BACKTRACE) && defined(ENABLE_BACKTRACES) && ...
341352
353 #if defined(ENABLE_BACKTRACES) && defined(HAVE_UNWIND_BACKTRACE)
354 static int unwindBacktrace(void **StackTrace, int MaxEntries) {
355 if (MaxEntries < 0)
356 return 0;
357
358 // Skip the first frame ('unwindBacktrace' itself).
359 int Entries = -1;
360
361 auto HandleFrame = [&](_Unwind_Context *Context) -> _Unwind_Reason_Code {
362 // Apparently we need to detect reaching the end of the stack ourselves.
363 void *IP = (void *)_Unwind_GetIP(Context);
364 if (!IP)
365 return _URC_END_OF_STACK;
366
367 assert(Entries < MaxEntries && "recursively called after END_OF_STACK?");
368 if (Entries >= 0)
369 StackTrace[Entries] = IP;
370
371 if (++Entries == MaxEntries)
372 return _URC_END_OF_STACK;
373 return _URC_NO_REASON;
374 };
375
376 _Unwind_Backtrace(
377 [](_Unwind_Context *Context, void *Handler) {
378 return (*static_cast(Handler))(Context);
379 },
380 static_cast(&HandleFrame));
381 return std::max(Entries, 0);
382 }
383 #endif
384
342385 // PrintStackTrace - In the case of a program crash or fault, print out a stack
343386 // trace so that the user has an indication of why and where we died.
344387 //
345388 // On glibc systems we have the 'backtrace' function, which works nicely, but
346389 // doesn't demangle symbols.
347390 void llvm::sys::PrintStackTrace(raw_ostream &OS) {
348 #if defined(HAVE_BACKTRACE) && defined(ENABLE_BACKTRACES)
349 static void* StackTrace[256];
391 #if defined(ENABLE_BACKTRACES)
392 static void *StackTrace[256];
393 int depth = 0;
394 #if defined(HAVE_BACKTRACE)
350395 // Use backtrace() to output a backtrace on Linux systems with glibc.
351 int depth = backtrace(StackTrace,
396 if (!depth)
397 depth = backtrace(StackTrace, static_cast(array_lengthof(StackTrace)));
398 #endif
399 #if defined(HAVE_UNWIND_BACKTRACE)
400 // Try _Unwind_Backtrace() if backtrace() failed.
401 if (!depth)
402 depth = unwindBacktrace(StackTrace,
352403 static_cast(array_lengthof(StackTrace)));
404 #endif
405 if (!depth)
406 return;
407
353408 if (printSymbolizedStackTrace(StackTrace, depth, OS))
354409 return;
355410 #if HAVE_DLFCN_H && __GNUG__
399454 }
400455 OS << '\n';
401456 }
402 #else
457 #elif defined(HAVE_BACKTRACE)
403458 backtrace_symbols_fd(StackTrace, depth, STDERR_FILENO);
404459 #endif
405460 #endif