summaryrefslogtreecommitdiff
path: root/lldb/tools/driver/Driver.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lldb/tools/driver/Driver.cpp')
-rw-r--r--lldb/tools/driver/Driver.cpp61
1 files changed, 36 insertions, 25 deletions
diff --git a/lldb/tools/driver/Driver.cpp b/lldb/tools/driver/Driver.cpp
index 6ab2bd93659f..73874389aa1b 100644
--- a/lldb/tools/driver/Driver.cpp
+++ b/lldb/tools/driver/Driver.cpp
@@ -22,7 +22,6 @@
#include "llvm/Support/Format.h"
#include "llvm/Support/InitLLVM.h"
#include "llvm/Support/Path.h"
-#include "llvm/Support/PrettyStackTrace.h"
#include "llvm/Support/Process.h"
#include "llvm/Support/Signals.h"
#include "llvm/Support/WithColor.h"
@@ -733,8 +732,30 @@ void sigcont_handler(int signo) {
signal(signo, sigcont_handler);
}
+void reproducer_handler(void *argv0) {
+ if (SBReproducer::Generate()) {
+ auto exe = static_cast<const char *>(argv0);
+ llvm::outs() << "********************\n";
+ llvm::outs() << "Crash reproducer for ";
+ llvm::outs() << lldb::SBDebugger::GetVersionString() << '\n';
+ llvm::outs() << '\n';
+ llvm::outs() << "Reproducer written to '" << SBReproducer::GetPath()
+ << "'\n";
+ llvm::outs() << '\n';
+ llvm::outs() << "Before attaching the reproducer to a bug report:\n";
+ llvm::outs() << " - Look at the directory to ensure you're willing to "
+ "share its content.\n";
+ llvm::outs()
+ << " - Make sure the reproducer works by replaying the reproducer.\n";
+ llvm::outs() << '\n';
+ llvm::outs() << "Replay the reproducer with the following command:\n";
+ llvm::outs() << exe << " -replay " << SBReproducer::GetPath() << "\n";
+ llvm::outs() << "********************\n";
+ }
+}
+
static void printHelp(LLDBOptTable &table, llvm::StringRef tool_name) {
- std::string usage_str = tool_name.str() + "options";
+ std::string usage_str = tool_name.str() + " [options]";
table.PrintHelp(llvm::outs(), usage_str.c_str(), "LLDB", false);
std::string examples = R"___(
@@ -770,14 +791,15 @@ EXAMPLES:
lldb -K /source/before/crash -k /source/after/crash
Note: In REPL mode no file is loaded, so commands specified to run after
- loading the file (via -o or -s) will be ignored.
- )___";
- llvm::outs() << examples;
+ loading the file (via -o or -s) will be ignored.)___";
+ llvm::outs() << examples << '\n';
}
llvm::Optional<int> InitializeReproducer(opt::InputArgList &input_args) {
if (auto *replay_path = input_args.getLastArg(OPT_replay)) {
- if (const char *error = SBReproducer::Replay(replay_path->getValue())) {
+ const bool skip_version_check = input_args.hasArg(OPT_skip_version_check);
+ if (const char *error =
+ SBReproducer::Replay(replay_path->getValue(), skip_version_check)) {
WithColor::error() << "reproducer replay failed: " << error << '\n';
return 1;
}
@@ -807,14 +829,10 @@ llvm::Optional<int> InitializeReproducer(opt::InputArgList &input_args) {
return llvm::None;
}
-int main(int argc, char const *argv[])
-{
- llvm::InitLLVM IL(argc, argv);
-
- // Print stack trace on crash.
- llvm::StringRef ToolName = llvm::sys::path::filename(argv[0]);
- llvm::sys::PrintStackTraceOnErrorSignal(ToolName);
- llvm::PrettyStackTraceProgram X(argc, argv);
+int main(int argc, char const *argv[]) {
+ // Setup LLVM signal handlers and make sure we call llvm_shutdown() on
+ // destruction.
+ llvm::InitLLVM IL(argc, argv, /*InstallPipeSignalExitHandler=*/false);
// Parse arguments.
LLDBOptTable T;
@@ -824,7 +842,7 @@ int main(int argc, char const *argv[])
opt::InputArgList input_args = T.ParseArgs(arg_arr, MAI, MAC);
if (input_args.hasArg(OPT_help)) {
- printHelp(T, ToolName);
+ printHelp(T, llvm::sys::path::filename(argv[0]));
return 0;
}
@@ -837,6 +855,9 @@ int main(int argc, char const *argv[])
return *exit_code;
}
+ // Register the reproducer signal handler.
+ llvm::sys::AddSignalHandler(reproducer_handler, const_cast<char *>(argv[0]));
+
SBError error = SBDebugger::InitializeWithErrorHandling();
if (error.Fail()) {
WithColor::error() << "initialization failed: " << error.GetCString()
@@ -853,16 +874,6 @@ int main(int argc, char const *argv[])
signal(SIGCONT, sigcont_handler);
#endif
- // Occasionally, during test teardown, LLDB writes to a closed pipe.
- // Sometimes the communication is inherently unreliable, so LLDB tries to
- // avoid being killed due to SIGPIPE. However, LLVM's default SIGPIPE behavior
- // is to exit with IO_ERR. Opt LLDB out of that.
- //
- // We don't disable LLVM's signal handling entirely because we still want
- // pretty stack traces, and file cleanup (for when, say, the clang embedded
- // in LLDB leaves behind temporary objects).
- llvm::sys::SetPipeSignalFunction(nullptr);
-
int exit_code = 0;
// Create a scope for driver so that the driver object will destroy itself
// before SBDebugger::Terminate() is called.