2004-08-30 03:22:48 +08:00
|
|
|
//===- Signals.cpp - Signal Handling support --------------------*- C++ -*-===//
|
2005-04-22 06:55:34 +08:00
|
|
|
//
|
2019-01-19 16:50:56 +08:00
|
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
2005-04-22 06:55:34 +08:00
|
|
|
//
|
2004-08-30 03:22:48 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
|
|
|
// This file defines some helpful functions for dealing with the possibility of
|
2011-04-15 13:18:47 +08:00
|
|
|
// Unix signals occurring while your program is running.
|
2004-08-30 03:22:48 +08:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2017-06-06 19:49:48 +08:00
|
|
|
#include "llvm/Support/Signals.h"
|
2015-11-05 09:07:54 +08:00
|
|
|
#include "llvm/ADT/STLExtras.h"
|
|
|
|
#include "llvm/ADT/StringRef.h"
|
2018-04-30 22:59:11 +08:00
|
|
|
#include "llvm/Config/llvm-config.h"
|
2015-11-05 09:07:54 +08:00
|
|
|
#include "llvm/Support/ErrorOr.h"
|
|
|
|
#include "llvm/Support/FileSystem.h"
|
|
|
|
#include "llvm/Support/FileUtilities.h"
|
|
|
|
#include "llvm/Support/Format.h"
|
2018-12-19 02:13:13 +08:00
|
|
|
#include "llvm/Support/FormatVariadic.h"
|
|
|
|
#include "llvm/Support/FormatAdapters.h"
|
2015-07-23 03:01:14 +08:00
|
|
|
#include "llvm/Support/ManagedStatic.h"
|
2015-11-05 09:07:54 +08:00
|
|
|
#include "llvm/Support/MemoryBuffer.h"
|
|
|
|
#include "llvm/Support/Mutex.h"
|
|
|
|
#include "llvm/Support/Program.h"
|
|
|
|
#include "llvm/Support/StringSaver.h"
|
|
|
|
#include "llvm/Support/raw_ostream.h"
|
bugpoint: disabling symbolication of bugpoint-executed programs
Initial implementation - needs similar work/testing for other tools
bugpoint invokes (llc, lli I think, maybe more).
Alternatively (as suggested by chandlerc@) an environment variable could
be used. This would allow the option to pass transparently through user
scripts, pass to compilers if they happened to be LLVM-ish, etc.
I worry a bit about using cl::opt in the crash handling code - LLVM
might crash early, perhaps before the cl::opt is properly initialized?
Or at least before arguments have been parsed?
- should be OK since it defaults to "pretty", so if the crash is very
early in opt parsing, etc, then crash reports will still be symbolized.
I shyed away from doing this with an environment variable when I
realized that would require copying the existing environment and
appending the env variable of interest. But it seems there's no existing
LLVM API for accessing the environment (even the Support tests for
process launching have their own ifdefs for getting the environment). It
could be added, but seemed like a higher bar/untested codepath to
actually add environment variables.
Most importantly, this reduces the runtime of test/BugPoint/metadata.ll
in a split-dwarf Debug build from 1m34s to 6.5s by avoiding a lot of
symbolication. (this wasn't a problem for non-split-dwarf builds only
because the executable was too large to map into memory (due to bugpoint
setting a 400MB memory (including address space - not sure why? Going to
remove that) limit on the child process) so symbolication would fail
fast & wouldn't spend all that time parsing DWARF, etc)
Reviewers: chandlerc, dannyb
Differential Revision: https://reviews.llvm.org/D33804
llvm-svn: 305056
2017-06-09 15:29:03 +08:00
|
|
|
#include "llvm/Support/Options.h"
|
2015-07-23 03:01:14 +08:00
|
|
|
#include <vector>
|
2004-08-30 03:22:48 +08:00
|
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//=== WARNING: Implementation here must contain only TRULY operating system
|
2005-04-22 06:55:34 +08:00
|
|
|
//=== independent code.
|
2004-08-30 03:22:48 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
bugpoint: disabling symbolication of bugpoint-executed programs
Initial implementation - needs similar work/testing for other tools
bugpoint invokes (llc, lli I think, maybe more).
Alternatively (as suggested by chandlerc@) an environment variable could
be used. This would allow the option to pass transparently through user
scripts, pass to compilers if they happened to be LLVM-ish, etc.
I worry a bit about using cl::opt in the crash handling code - LLVM
might crash early, perhaps before the cl::opt is properly initialized?
Or at least before arguments have been parsed?
- should be OK since it defaults to "pretty", so if the crash is very
early in opt parsing, etc, then crash reports will still be symbolized.
I shyed away from doing this with an environment variable when I
realized that would require copying the existing environment and
appending the env variable of interest. But it seems there's no existing
LLVM API for accessing the environment (even the Support tests for
process launching have their own ifdefs for getting the environment). It
could be added, but seemed like a higher bar/untested codepath to
actually add environment variables.
Most importantly, this reduces the runtime of test/BugPoint/metadata.ll
in a split-dwarf Debug build from 1m34s to 6.5s by avoiding a lot of
symbolication. (this wasn't a problem for non-split-dwarf builds only
because the executable was too large to map into memory (due to bugpoint
setting a 400MB memory (including address space - not sure why? Going to
remove that) limit on the child process) so symbolication would fail
fast & wouldn't spend all that time parsing DWARF, etc)
Reviewers: chandlerc, dannyb
Differential Revision: https://reviews.llvm.org/D33804
llvm-svn: 305056
2017-06-09 15:29:03 +08:00
|
|
|
using namespace llvm;
|
|
|
|
|
Signal handling should be signal-safe
Summary:
Before this patch, signal handling wasn't signal safe. This leads to real-world
crashes. It used ManagedStatic inside of signals, this can allocate and can lead
to unexpected state when a signal occurs during llvm_shutdown (because
llvm_shutdown destroys the ManagedStatic). It also used cl::opt without custom
backing storage. Some de-allocation was performed as well. Acquiring a lock in a
signal handler is also a great way to deadlock.
We can't just disable signals on llvm_shutdown because the signals might do
useful work during that shutdown. We also can't just disable llvm_shutdown for
programs (instead of library uses of clang) because we'd have to then mark the
pointers as not leaked and make sure all the ManagedStatic uses are OK to leak
and remain so.
Move all of the code to lock-free datastructures instead, and avoid having any
of them in an inconsistent state. I'm not trying to be fancy, I'm not using any
explicit memory order because this code isn't hot. The only purpose of the
atomics is to guarantee that a signal firing on the same or a different thread
doesn't see an inconsistent state and crash. In some cases we might miss some
state (for example, we might fail to delete a temporary file), but that's fine.
Note that I haven't touched any of the backtrace support despite it not
technically being totally signal-safe. When that code is called we know
something bad is up and we don't expect to continue execution, so calling
something that e.g. sets errno is the least of our problems.
A similar patch should be applied to lib/Support/Windows/Signals.inc, but that
can be done separately.
Fix r332428 which I reverted in r332429. I originally used double-wide CAS
because I was lazy, but some platforms use a runtime function for that which
thankfully failed to link (it would have been bad for signal handlers
otherwise). I use a separate flag to guard the data instead.
<rdar://problem/28010281>
Reviewers: dexonsmith
Subscribers: steven_wu, llvm-commits
llvm-svn: 332496
2018-05-17 01:25:35 +08:00
|
|
|
// Use explicit storage to avoid accessing cl::opt in a signal handler.
|
|
|
|
static bool DisableSymbolicationFlag = false;
|
|
|
|
static cl::opt<bool, true>
|
bugpoint: disabling symbolication of bugpoint-executed programs
Initial implementation - needs similar work/testing for other tools
bugpoint invokes (llc, lli I think, maybe more).
Alternatively (as suggested by chandlerc@) an environment variable could
be used. This would allow the option to pass transparently through user
scripts, pass to compilers if they happened to be LLVM-ish, etc.
I worry a bit about using cl::opt in the crash handling code - LLVM
might crash early, perhaps before the cl::opt is properly initialized?
Or at least before arguments have been parsed?
- should be OK since it defaults to "pretty", so if the crash is very
early in opt parsing, etc, then crash reports will still be symbolized.
I shyed away from doing this with an environment variable when I
realized that would require copying the existing environment and
appending the env variable of interest. But it seems there's no existing
LLVM API for accessing the environment (even the Support tests for
process launching have their own ifdefs for getting the environment). It
could be added, but seemed like a higher bar/untested codepath to
actually add environment variables.
Most importantly, this reduces the runtime of test/BugPoint/metadata.ll
in a split-dwarf Debug build from 1m34s to 6.5s by avoiding a lot of
symbolication. (this wasn't a problem for non-split-dwarf builds only
because the executable was too large to map into memory (due to bugpoint
setting a 400MB memory (including address space - not sure why? Going to
remove that) limit on the child process) so symbolication would fail
fast & wouldn't spend all that time parsing DWARF, etc)
Reviewers: chandlerc, dannyb
Differential Revision: https://reviews.llvm.org/D33804
llvm-svn: 305056
2017-06-09 15:29:03 +08:00
|
|
|
DisableSymbolication("disable-symbolication",
|
|
|
|
cl::desc("Disable symbolizing crash backtraces."),
|
Signal handling should be signal-safe
Summary:
Before this patch, signal handling wasn't signal safe. This leads to real-world
crashes. It used ManagedStatic inside of signals, this can allocate and can lead
to unexpected state when a signal occurs during llvm_shutdown (because
llvm_shutdown destroys the ManagedStatic). It also used cl::opt without custom
backing storage. Some de-allocation was performed as well. Acquiring a lock in a
signal handler is also a great way to deadlock.
We can't just disable signals on llvm_shutdown because the signals might do
useful work during that shutdown. We also can't just disable llvm_shutdown for
programs (instead of library uses of clang) because we'd have to then mark the
pointers as not leaked and make sure all the ManagedStatic uses are OK to leak
and remain so.
Move all of the code to lock-free datastructures instead, and avoid having any
of them in an inconsistent state. I'm not trying to be fancy, I'm not using any
explicit memory order because this code isn't hot. The only purpose of the
atomics is to guarantee that a signal firing on the same or a different thread
doesn't see an inconsistent state and crash. In some cases we might miss some
state (for example, we might fail to delete a temporary file), but that's fine.
Note that I haven't touched any of the backtrace support despite it not
technically being totally signal-safe. When that code is called we know
something bad is up and we don't expect to continue execution, so calling
something that e.g. sets errno is the least of our problems.
A similar patch should be applied to lib/Support/Windows/Signals.inc, but that
can be done separately.
Fix r332428 which I reverted in r332429. I originally used double-wide CAS
because I was lazy, but some platforms use a runtime function for that which
thankfully failed to link (it would have been bad for signal handlers
otherwise). I use a separate flag to guard the data instead.
<rdar://problem/28010281>
Reviewers: dexonsmith
Subscribers: steven_wu, llvm-commits
llvm-svn: 332496
2018-05-17 01:25:35 +08:00
|
|
|
cl::location(DisableSymbolicationFlag), cl::Hidden);
|
bugpoint: disabling symbolication of bugpoint-executed programs
Initial implementation - needs similar work/testing for other tools
bugpoint invokes (llc, lli I think, maybe more).
Alternatively (as suggested by chandlerc@) an environment variable could
be used. This would allow the option to pass transparently through user
scripts, pass to compilers if they happened to be LLVM-ish, etc.
I worry a bit about using cl::opt in the crash handling code - LLVM
might crash early, perhaps before the cl::opt is properly initialized?
Or at least before arguments have been parsed?
- should be OK since it defaults to "pretty", so if the crash is very
early in opt parsing, etc, then crash reports will still be symbolized.
I shyed away from doing this with an environment variable when I
realized that would require copying the existing environment and
appending the env variable of interest. But it seems there's no existing
LLVM API for accessing the environment (even the Support tests for
process launching have their own ifdefs for getting the environment). It
could be added, but seemed like a higher bar/untested codepath to
actually add environment variables.
Most importantly, this reduces the runtime of test/BugPoint/metadata.ll
in a split-dwarf Debug build from 1m34s to 6.5s by avoiding a lot of
symbolication. (this wasn't a problem for non-split-dwarf builds only
because the executable was too large to map into memory (due to bugpoint
setting a 400MB memory (including address space - not sure why? Going to
remove that) limit on the child process) so symbolication would fail
fast & wouldn't spend all that time parsing DWARF, etc)
Reviewers: chandlerc, dannyb
Differential Revision: https://reviews.llvm.org/D33804
llvm-svn: 305056
2017-06-09 15:29:03 +08:00
|
|
|
|
Signal handling should be signal-safe
Summary:
Before this patch, signal handling wasn't signal safe. This leads to real-world
crashes. It used ManagedStatic inside of signals, this can allocate and can lead
to unexpected state when a signal occurs during llvm_shutdown (because
llvm_shutdown destroys the ManagedStatic). It also used cl::opt without custom
backing storage. Some de-allocation was performed as well. Acquiring a lock in a
signal handler is also a great way to deadlock.
We can't just disable signals on llvm_shutdown because the signals might do
useful work during that shutdown. We also can't just disable llvm_shutdown for
programs (instead of library uses of clang) because we'd have to then mark the
pointers as not leaked and make sure all the ManagedStatic uses are OK to leak
and remain so.
Move all of the code to lock-free datastructures instead, and avoid having any
of them in an inconsistent state. I'm not trying to be fancy, I'm not using any
explicit memory order because this code isn't hot. The only purpose of the
atomics is to guarantee that a signal firing on the same or a different thread
doesn't see an inconsistent state and crash. In some cases we might miss some
state (for example, we might fail to delete a temporary file), but that's fine.
Note that I haven't touched any of the backtrace support despite it not
technically being totally signal-safe. When that code is called we know
something bad is up and we don't expect to continue execution, so calling
something that e.g. sets errno is the least of our problems.
A similar patch should be applied to lib/Support/Windows/Signals.inc, but that
can be done separately.
Fix r332428 which I reverted in r332429. I originally used double-wide CAS
because I was lazy, but some platforms use a runtime function for that which
thankfully failed to link (it would have been bad for signal handlers
otherwise). I use a separate flag to guard the data instead.
<rdar://problem/28010281>
Reviewers: dexonsmith
Subscribers: steven_wu, llvm-commits
llvm-svn: 332496
2018-05-17 01:25:35 +08:00
|
|
|
// Callbacks to run in signal handler must be lock-free because a signal handler
|
|
|
|
// could be running as we add new callbacks. We don't add unbounded numbers of
|
|
|
|
// callbacks, an array is therefore sufficient.
|
|
|
|
struct CallbackAndCookie {
|
|
|
|
sys::SignalHandlerCallback Callback;
|
|
|
|
void *Cookie;
|
|
|
|
enum class Status { Empty, Initializing, Initialized, Executing };
|
|
|
|
std::atomic<Status> Flag;
|
|
|
|
};
|
|
|
|
static constexpr size_t MaxSignalHandlerCallbacks = 8;
|
|
|
|
static CallbackAndCookie CallBacksToRun[MaxSignalHandlerCallbacks];
|
|
|
|
|
|
|
|
// Signal-safe.
|
2018-05-16 12:36:37 +08:00
|
|
|
void sys::RunSignalHandlers() {
|
Signal handling should be signal-safe
Summary:
Before this patch, signal handling wasn't signal safe. This leads to real-world
crashes. It used ManagedStatic inside of signals, this can allocate and can lead
to unexpected state when a signal occurs during llvm_shutdown (because
llvm_shutdown destroys the ManagedStatic). It also used cl::opt without custom
backing storage. Some de-allocation was performed as well. Acquiring a lock in a
signal handler is also a great way to deadlock.
We can't just disable signals on llvm_shutdown because the signals might do
useful work during that shutdown. We also can't just disable llvm_shutdown for
programs (instead of library uses of clang) because we'd have to then mark the
pointers as not leaked and make sure all the ManagedStatic uses are OK to leak
and remain so.
Move all of the code to lock-free datastructures instead, and avoid having any
of them in an inconsistent state. I'm not trying to be fancy, I'm not using any
explicit memory order because this code isn't hot. The only purpose of the
atomics is to guarantee that a signal firing on the same or a different thread
doesn't see an inconsistent state and crash. In some cases we might miss some
state (for example, we might fail to delete a temporary file), but that's fine.
Note that I haven't touched any of the backtrace support despite it not
technically being totally signal-safe. When that code is called we know
something bad is up and we don't expect to continue execution, so calling
something that e.g. sets errno is the least of our problems.
A similar patch should be applied to lib/Support/Windows/Signals.inc, but that
can be done separately.
Fix r332428 which I reverted in r332429. I originally used double-wide CAS
because I was lazy, but some platforms use a runtime function for that which
thankfully failed to link (it would have been bad for signal handlers
otherwise). I use a separate flag to guard the data instead.
<rdar://problem/28010281>
Reviewers: dexonsmith
Subscribers: steven_wu, llvm-commits
llvm-svn: 332496
2018-05-17 01:25:35 +08:00
|
|
|
for (size_t I = 0; I < MaxSignalHandlerCallbacks; ++I) {
|
|
|
|
auto &RunMe = CallBacksToRun[I];
|
|
|
|
auto Expected = CallbackAndCookie::Status::Initialized;
|
|
|
|
auto Desired = CallbackAndCookie::Status::Executing;
|
|
|
|
if (!RunMe.Flag.compare_exchange_strong(Expected, Desired))
|
|
|
|
continue;
|
|
|
|
(*RunMe.Callback)(RunMe.Cookie);
|
|
|
|
RunMe.Callback = nullptr;
|
|
|
|
RunMe.Cookie = nullptr;
|
|
|
|
RunMe.Flag.store(CallbackAndCookie::Status::Empty);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Signal-safe.
|
|
|
|
static void insertSignalHandler(sys::SignalHandlerCallback FnPtr,
|
|
|
|
void *Cookie) {
|
|
|
|
for (size_t I = 0; I < MaxSignalHandlerCallbacks; ++I) {
|
|
|
|
auto &SetMe = CallBacksToRun[I];
|
|
|
|
auto Expected = CallbackAndCookie::Status::Empty;
|
|
|
|
auto Desired = CallbackAndCookie::Status::Initializing;
|
|
|
|
if (!SetMe.Flag.compare_exchange_strong(Expected, Desired))
|
|
|
|
continue;
|
|
|
|
SetMe.Callback = FnPtr;
|
|
|
|
SetMe.Cookie = Cookie;
|
|
|
|
SetMe.Flag.store(CallbackAndCookie::Status::Initialized);
|
2018-05-16 12:36:37 +08:00
|
|
|
return;
|
Signal handling should be signal-safe
Summary:
Before this patch, signal handling wasn't signal safe. This leads to real-world
crashes. It used ManagedStatic inside of signals, this can allocate and can lead
to unexpected state when a signal occurs during llvm_shutdown (because
llvm_shutdown destroys the ManagedStatic). It also used cl::opt without custom
backing storage. Some de-allocation was performed as well. Acquiring a lock in a
signal handler is also a great way to deadlock.
We can't just disable signals on llvm_shutdown because the signals might do
useful work during that shutdown. We also can't just disable llvm_shutdown for
programs (instead of library uses of clang) because we'd have to then mark the
pointers as not leaked and make sure all the ManagedStatic uses are OK to leak
and remain so.
Move all of the code to lock-free datastructures instead, and avoid having any
of them in an inconsistent state. I'm not trying to be fancy, I'm not using any
explicit memory order because this code isn't hot. The only purpose of the
atomics is to guarantee that a signal firing on the same or a different thread
doesn't see an inconsistent state and crash. In some cases we might miss some
state (for example, we might fail to delete a temporary file), but that's fine.
Note that I haven't touched any of the backtrace support despite it not
technically being totally signal-safe. When that code is called we know
something bad is up and we don't expect to continue execution, so calling
something that e.g. sets errno is the least of our problems.
A similar patch should be applied to lib/Support/Windows/Signals.inc, but that
can be done separately.
Fix r332428 which I reverted in r332429. I originally used double-wide CAS
because I was lazy, but some platforms use a runtime function for that which
thankfully failed to link (it would have been bad for signal handlers
otherwise). I use a separate flag to guard the data instead.
<rdar://problem/28010281>
Reviewers: dexonsmith
Subscribers: steven_wu, llvm-commits
llvm-svn: 332496
2018-05-17 01:25:35 +08:00
|
|
|
}
|
|
|
|
report_fatal_error("too many signal callbacks already registered");
|
2015-07-23 03:01:14 +08:00
|
|
|
}
|
2015-11-05 09:07:54 +08:00
|
|
|
|
|
|
|
static bool findModulesAndOffsets(void **StackTrace, int Depth,
|
|
|
|
const char **Modules, intptr_t *Offsets,
|
|
|
|
const char *MainExecutableName,
|
|
|
|
StringSaver &StrPool);
|
|
|
|
|
|
|
|
/// Format a pointer value as hexadecimal. Zero pad it out so its always the
|
|
|
|
/// same width.
|
|
|
|
static FormattedNumber format_ptr(void *PC) {
|
|
|
|
// Each byte is two hex digits plus 2 for the 0x prefix.
|
|
|
|
unsigned PtrWidth = 2 + 2 * sizeof(void *);
|
|
|
|
return format_hex((uint64_t)PC, PtrWidth);
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Helper that launches llvm-symbolizer and symbolizes a backtrace.
|
2018-05-06 04:14:38 +08:00
|
|
|
LLVM_ATTRIBUTE_USED
|
|
|
|
static bool printSymbolizedStackTrace(StringRef Argv0, void **StackTrace,
|
|
|
|
int Depth, llvm::raw_ostream &OS) {
|
Signal handling should be signal-safe
Summary:
Before this patch, signal handling wasn't signal safe. This leads to real-world
crashes. It used ManagedStatic inside of signals, this can allocate and can lead
to unexpected state when a signal occurs during llvm_shutdown (because
llvm_shutdown destroys the ManagedStatic). It also used cl::opt without custom
backing storage. Some de-allocation was performed as well. Acquiring a lock in a
signal handler is also a great way to deadlock.
We can't just disable signals on llvm_shutdown because the signals might do
useful work during that shutdown. We also can't just disable llvm_shutdown for
programs (instead of library uses of clang) because we'd have to then mark the
pointers as not leaked and make sure all the ManagedStatic uses are OK to leak
and remain so.
Move all of the code to lock-free datastructures instead, and avoid having any
of them in an inconsistent state. I'm not trying to be fancy, I'm not using any
explicit memory order because this code isn't hot. The only purpose of the
atomics is to guarantee that a signal firing on the same or a different thread
doesn't see an inconsistent state and crash. In some cases we might miss some
state (for example, we might fail to delete a temporary file), but that's fine.
Note that I haven't touched any of the backtrace support despite it not
technically being totally signal-safe. When that code is called we know
something bad is up and we don't expect to continue execution, so calling
something that e.g. sets errno is the least of our problems.
A similar patch should be applied to lib/Support/Windows/Signals.inc, but that
can be done separately.
Fix r332428 which I reverted in r332429. I originally used double-wide CAS
because I was lazy, but some platforms use a runtime function for that which
thankfully failed to link (it would have been bad for signal handlers
otherwise). I use a separate flag to guard the data instead.
<rdar://problem/28010281>
Reviewers: dexonsmith
Subscribers: steven_wu, llvm-commits
llvm-svn: 332496
2018-05-17 01:25:35 +08:00
|
|
|
if (DisableSymbolicationFlag)
|
bugpoint: disabling symbolication of bugpoint-executed programs
Initial implementation - needs similar work/testing for other tools
bugpoint invokes (llc, lli I think, maybe more).
Alternatively (as suggested by chandlerc@) an environment variable could
be used. This would allow the option to pass transparently through user
scripts, pass to compilers if they happened to be LLVM-ish, etc.
I worry a bit about using cl::opt in the crash handling code - LLVM
might crash early, perhaps before the cl::opt is properly initialized?
Or at least before arguments have been parsed?
- should be OK since it defaults to "pretty", so if the crash is very
early in opt parsing, etc, then crash reports will still be symbolized.
I shyed away from doing this with an environment variable when I
realized that would require copying the existing environment and
appending the env variable of interest. But it seems there's no existing
LLVM API for accessing the environment (even the Support tests for
process launching have their own ifdefs for getting the environment). It
could be added, but seemed like a higher bar/untested codepath to
actually add environment variables.
Most importantly, this reduces the runtime of test/BugPoint/metadata.ll
in a split-dwarf Debug build from 1m34s to 6.5s by avoiding a lot of
symbolication. (this wasn't a problem for non-split-dwarf builds only
because the executable was too large to map into memory (due to bugpoint
setting a 400MB memory (including address space - not sure why? Going to
remove that) limit on the child process) so symbolication would fail
fast & wouldn't spend all that time parsing DWARF, etc)
Reviewers: chandlerc, dannyb
Differential Revision: https://reviews.llvm.org/D33804
llvm-svn: 305056
2017-06-09 15:29:03 +08:00
|
|
|
return false;
|
|
|
|
|
2016-06-09 08:53:21 +08:00
|
|
|
// Don't recursively invoke the llvm-symbolizer binary.
|
|
|
|
if (Argv0.find("llvm-symbolizer") != std::string::npos)
|
|
|
|
return false;
|
|
|
|
|
2015-11-05 09:07:54 +08:00
|
|
|
// FIXME: Subtract necessary number from StackTrace entries to turn return addresses
|
|
|
|
// into actual instruction addresses.
|
2016-06-09 08:53:21 +08:00
|
|
|
// Use llvm-symbolizer tool to symbolize the stack traces. First look for it
|
|
|
|
// alongside our binary, then in $PATH.
|
|
|
|
ErrorOr<std::string> LLVMSymbolizerPathOrErr = std::error_code();
|
|
|
|
if (!Argv0.empty()) {
|
|
|
|
StringRef Parent = llvm::sys::path::parent_path(Argv0);
|
|
|
|
if (!Parent.empty())
|
|
|
|
LLVMSymbolizerPathOrErr = sys::findProgramByName("llvm-symbolizer", Parent);
|
|
|
|
}
|
|
|
|
if (!LLVMSymbolizerPathOrErr)
|
|
|
|
LLVMSymbolizerPathOrErr = sys::findProgramByName("llvm-symbolizer");
|
2015-11-05 09:07:54 +08:00
|
|
|
if (!LLVMSymbolizerPathOrErr)
|
|
|
|
return false;
|
|
|
|
const std::string &LLVMSymbolizerPath = *LLVMSymbolizerPathOrErr;
|
|
|
|
|
2016-06-09 08:53:21 +08:00
|
|
|
// If we don't know argv0 or the address of main() at this point, try
|
|
|
|
// to guess it anyway (it's possible on some platforms).
|
|
|
|
std::string MainExecutableName =
|
2019-04-16 06:07:56 +08:00
|
|
|
sys::fs::exists(Argv0) ? (std::string)Argv0
|
|
|
|
: sys::fs::getMainExecutable(nullptr, nullptr);
|
2015-11-05 09:07:54 +08:00
|
|
|
BumpPtrAllocator Allocator;
|
|
|
|
StringSaver StrPool(Allocator);
|
|
|
|
std::vector<const char *> Modules(Depth, nullptr);
|
|
|
|
std::vector<intptr_t> Offsets(Depth, 0);
|
|
|
|
if (!findModulesAndOffsets(StackTrace, Depth, Modules.data(), Offsets.data(),
|
|
|
|
MainExecutableName.c_str(), StrPool))
|
|
|
|
return false;
|
|
|
|
int InputFD;
|
|
|
|
SmallString<32> InputFile, OutputFile;
|
|
|
|
sys::fs::createTemporaryFile("symbolizer-input", "", InputFD, InputFile);
|
|
|
|
sys::fs::createTemporaryFile("symbolizer-output", "", OutputFile);
|
|
|
|
FileRemover InputRemover(InputFile.c_str());
|
|
|
|
FileRemover OutputRemover(OutputFile.c_str());
|
|
|
|
|
|
|
|
{
|
|
|
|
raw_fd_ostream Input(InputFD, true);
|
|
|
|
for (int i = 0; i < Depth; i++) {
|
|
|
|
if (Modules[i])
|
|
|
|
Input << Modules[i] << " " << (void*)Offsets[i] << "\n";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-06-13 01:43:52 +08:00
|
|
|
Optional<StringRef> Redirects[] = {StringRef(InputFile),
|
2018-12-19 02:23:36 +08:00
|
|
|
StringRef(OutputFile), StringRef("")};
|
2018-06-13 01:43:52 +08:00
|
|
|
StringRef Args[] = {"llvm-symbolizer", "--functions=linkage", "--inlining",
|
2018-04-29 08:45:03 +08:00
|
|
|
#ifdef _WIN32
|
2018-06-13 01:43:52 +08:00
|
|
|
// Pass --relative-address on Windows so that we don't
|
|
|
|
// have to add ImageBase from PE file.
|
|
|
|
// FIXME: Make this the default for llvm-symbolizer.
|
|
|
|
"--relative-address",
|
2015-11-05 09:07:54 +08:00
|
|
|
#endif
|
2018-06-13 01:43:52 +08:00
|
|
|
"--demangle"};
|
2015-11-05 09:07:54 +08:00
|
|
|
int RunResult =
|
2018-06-13 01:43:52 +08:00
|
|
|
sys::ExecuteAndWait(LLVMSymbolizerPath, Args, None, Redirects);
|
2015-11-05 09:07:54 +08:00
|
|
|
if (RunResult != 0)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// This report format is based on the sanitizer stack trace printer. See
|
|
|
|
// sanitizer_stacktrace_printer.cc in compiler-rt.
|
|
|
|
auto OutputBuf = MemoryBuffer::getFile(OutputFile.c_str());
|
|
|
|
if (!OutputBuf)
|
|
|
|
return false;
|
|
|
|
StringRef Output = OutputBuf.get()->getBuffer();
|
|
|
|
SmallVector<StringRef, 32> Lines;
|
|
|
|
Output.split(Lines, "\n");
|
|
|
|
auto CurLine = Lines.begin();
|
|
|
|
int frame_no = 0;
|
|
|
|
for (int i = 0; i < Depth; i++) {
|
2018-12-19 02:13:13 +08:00
|
|
|
auto PrintLineHeader = [&]() {
|
|
|
|
OS << right_justify(formatv("#{0}", frame_no++).str(),
|
|
|
|
std::log10(Depth) + 2)
|
|
|
|
<< ' ' << format_ptr(StackTrace[i]) << ' ';
|
|
|
|
};
|
2015-11-05 09:07:54 +08:00
|
|
|
if (!Modules[i]) {
|
2018-12-19 02:13:13 +08:00
|
|
|
PrintLineHeader();
|
|
|
|
OS << '\n';
|
2015-11-05 09:07:54 +08:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
// Read pairs of lines (function name and file/line info) until we
|
|
|
|
// encounter empty line.
|
|
|
|
for (;;) {
|
|
|
|
if (CurLine == Lines.end())
|
|
|
|
return false;
|
|
|
|
StringRef FunctionName = *CurLine++;
|
|
|
|
if (FunctionName.empty())
|
|
|
|
break;
|
2018-12-19 02:13:13 +08:00
|
|
|
PrintLineHeader();
|
2015-11-05 09:07:54 +08:00
|
|
|
if (!FunctionName.startswith("??"))
|
|
|
|
OS << FunctionName << ' ';
|
|
|
|
if (CurLine == Lines.end())
|
|
|
|
return false;
|
|
|
|
StringRef FileLineInfo = *CurLine++;
|
|
|
|
if (!FileLineInfo.startswith("??"))
|
|
|
|
OS << FileLineInfo;
|
|
|
|
else
|
|
|
|
OS << "(" << Modules[i] << '+' << format_hex(Offsets[i], 0) << ")";
|
|
|
|
OS << "\n";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2004-08-30 03:22:48 +08:00
|
|
|
// Include the platform-specific parts of this class.
|
2004-12-27 14:16:11 +08:00
|
|
|
#ifdef LLVM_ON_UNIX
|
2005-01-10 07:29:00 +08:00
|
|
|
#include "Unix/Signals.inc"
|
2004-12-27 14:16:11 +08:00
|
|
|
#endif
|
2018-04-29 08:45:03 +08:00
|
|
|
#ifdef _WIN32
|
2010-11-30 02:16:10 +08:00
|
|
|
#include "Windows/Signals.inc"
|
2004-12-27 14:16:11 +08:00
|
|
|
#endif
|