xref: /freebsd/contrib/llvm-project/lldb/tools/driver/Driver.cpp (revision 9dba64be9536c28e4800e06512b7f29b43ade345)
1 //===-- Driver.cpp ----------------------------------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "Driver.h"
10 
11 #include "lldb/API/SBCommandInterpreter.h"
12 #include "lldb/API/SBCommandReturnObject.h"
13 #include "lldb/API/SBDebugger.h"
14 #include "lldb/API/SBFile.h"
15 #include "lldb/API/SBHostOS.h"
16 #include "lldb/API/SBLanguageRuntime.h"
17 #include "lldb/API/SBReproducer.h"
18 #include "lldb/API/SBStream.h"
19 #include "lldb/API/SBStringList.h"
20 
21 #include "llvm/ADT/StringRef.h"
22 #include "llvm/Support/Format.h"
23 #include "llvm/Support/InitLLVM.h"
24 #include "llvm/Support/Path.h"
25 #include "llvm/Support/PrettyStackTrace.h"
26 #include "llvm/Support/Process.h"
27 #include "llvm/Support/Signals.h"
28 #include "llvm/Support/WithColor.h"
29 #include "llvm/Support/raw_ostream.h"
30 
31 #include <algorithm>
32 #include <atomic>
33 #include <bitset>
34 #include <csignal>
35 #include <string>
36 #include <thread>
37 #include <utility>
38 
39 #include <fcntl.h>
40 #include <limits.h>
41 #include <stdio.h>
42 #include <stdlib.h>
43 #include <string.h>
44 
45 // Includes for pipe()
46 #if defined(_WIN32)
47 #include <fcntl.h>
48 #include <io.h>
49 #else
50 #include <unistd.h>
51 #endif
52 
53 #if !defined(__APPLE__)
54 #include "llvm/Support/DataTypes.h"
55 #endif
56 
57 using namespace lldb;
58 using namespace llvm;
59 
60 namespace {
61 enum ID {
62   OPT_INVALID = 0, // This is not an option ID.
63 #define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM,  \
64                HELPTEXT, METAVAR, VALUES)                                      \
65   OPT_##ID,
66 #include "Options.inc"
67 #undef OPTION
68 };
69 
70 #define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE;
71 #include "Options.inc"
72 #undef PREFIX
73 
74 const opt::OptTable::Info InfoTable[] = {
75 #define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM,  \
76                HELPTEXT, METAVAR, VALUES)                                      \
77   {                                                                            \
78       PREFIX,      NAME,      HELPTEXT,                                        \
79       METAVAR,     OPT_##ID,  opt::Option::KIND##Class,                        \
80       PARAM,       FLAGS,     OPT_##GROUP,                                     \
81       OPT_##ALIAS, ALIASARGS, VALUES},
82 #include "Options.inc"
83 #undef OPTION
84 };
85 
86 class LLDBOptTable : public opt::OptTable {
87 public:
88   LLDBOptTable() : OptTable(InfoTable) {}
89 };
90 } // namespace
91 
92 static void reset_stdin_termios();
93 static bool g_old_stdin_termios_is_valid = false;
94 static struct termios g_old_stdin_termios;
95 
96 static Driver *g_driver = nullptr;
97 
98 // In the Driver::MainLoop, we change the terminal settings.  This function is
99 // added as an atexit handler to make sure we clean them up.
100 static void reset_stdin_termios() {
101   if (g_old_stdin_termios_is_valid) {
102     g_old_stdin_termios_is_valid = false;
103     ::tcsetattr(STDIN_FILENO, TCSANOW, &g_old_stdin_termios);
104   }
105 }
106 
107 Driver::Driver()
108     : SBBroadcaster("Driver"), m_debugger(SBDebugger::Create(false)) {
109   // We want to be able to handle CTRL+D in the terminal to have it terminate
110   // certain input
111   m_debugger.SetCloseInputOnEOF(false);
112   g_driver = this;
113 }
114 
115 Driver::~Driver() { g_driver = nullptr; }
116 
117 void Driver::OptionData::AddInitialCommand(std::string command,
118                                            CommandPlacement placement,
119                                            bool is_file, SBError &error) {
120   std::vector<InitialCmdEntry> *command_set;
121   switch (placement) {
122   case eCommandPlacementBeforeFile:
123     command_set = &(m_initial_commands);
124     break;
125   case eCommandPlacementAfterFile:
126     command_set = &(m_after_file_commands);
127     break;
128   case eCommandPlacementAfterCrash:
129     command_set = &(m_after_crash_commands);
130     break;
131   }
132 
133   if (is_file) {
134     SBFileSpec file(command.c_str());
135     if (file.Exists())
136       command_set->push_back(InitialCmdEntry(command, is_file));
137     else if (file.ResolveExecutableLocation()) {
138       char final_path[PATH_MAX];
139       file.GetPath(final_path, sizeof(final_path));
140       command_set->push_back(InitialCmdEntry(final_path, is_file));
141     } else
142       error.SetErrorStringWithFormat(
143           "file specified in --source (-s) option doesn't exist: '%s'",
144           command.c_str());
145   } else
146     command_set->push_back(InitialCmdEntry(command, is_file));
147 }
148 
149 void Driver::WriteCommandsForSourcing(CommandPlacement placement,
150                                       SBStream &strm) {
151   std::vector<OptionData::InitialCmdEntry> *command_set;
152   switch (placement) {
153   case eCommandPlacementBeforeFile:
154     command_set = &m_option_data.m_initial_commands;
155     break;
156   case eCommandPlacementAfterFile:
157     command_set = &m_option_data.m_after_file_commands;
158     break;
159   case eCommandPlacementAfterCrash:
160     command_set = &m_option_data.m_after_crash_commands;
161     break;
162   }
163 
164   for (const auto &command_entry : *command_set) {
165     const char *command = command_entry.contents.c_str();
166     if (command_entry.is_file) {
167       bool source_quietly =
168           m_option_data.m_source_quietly || command_entry.source_quietly;
169       strm.Printf("command source -s %i '%s'\n",
170                   static_cast<int>(source_quietly), command);
171     } else
172       strm.Printf("%s\n", command);
173   }
174 }
175 
176 // Check the arguments that were passed to this program to make sure they are
177 // valid and to get their argument values (if any).  Return a boolean value
178 // indicating whether or not to start up the full debugger (i.e. the Command
179 // Interpreter) or not.  Return FALSE if the arguments were invalid OR if the
180 // user only wanted help or version information.
181 SBError Driver::ProcessArgs(const opt::InputArgList &args, bool &exiting) {
182   SBError error;
183 
184   // This is kind of a pain, but since we make the debugger in the Driver's
185   // constructor, we can't know at that point whether we should read in init
186   // files yet.  So we don't read them in in the Driver constructor, then set
187   // the flags back to "read them in" here, and then if we see the "-n" flag,
188   // we'll turn it off again.  Finally we have to read them in by hand later in
189   // the main loop.
190   m_debugger.SkipLLDBInitFiles(false);
191   m_debugger.SkipAppInitFiles(false);
192 
193   if (args.hasArg(OPT_version)) {
194     m_option_data.m_print_version = true;
195   }
196 
197   if (args.hasArg(OPT_python_path)) {
198     m_option_data.m_print_python_path = true;
199   }
200 
201   if (args.hasArg(OPT_batch)) {
202     m_option_data.m_batch = true;
203   }
204 
205   if (auto *arg = args.getLastArg(OPT_core)) {
206     auto arg_value = arg->getValue();
207     SBFileSpec file(arg_value);
208     if (!file.Exists()) {
209       error.SetErrorStringWithFormat(
210           "file specified in --core (-c) option doesn't exist: '%s'",
211           arg_value);
212       return error;
213     }
214     m_option_data.m_core_file = arg_value;
215   }
216 
217   if (args.hasArg(OPT_editor)) {
218     m_option_data.m_use_external_editor = true;
219   }
220 
221   if (args.hasArg(OPT_no_lldbinit)) {
222     m_debugger.SkipLLDBInitFiles(true);
223     m_debugger.SkipAppInitFiles(true);
224   }
225 
226   if (args.hasArg(OPT_local_lldbinit)) {
227     lldb::SBDebugger::SetInternalVariable("target.load-cwd-lldbinit", "true",
228                                           m_debugger.GetInstanceName());
229   }
230 
231   if (args.hasArg(OPT_no_use_colors)) {
232     m_debugger.SetUseColor(false);
233     m_option_data.m_debug_mode = true;
234   }
235 
236   if (auto *arg = args.getLastArg(OPT_file)) {
237     auto arg_value = arg->getValue();
238     SBFileSpec file(arg_value);
239     if (file.Exists()) {
240       m_option_data.m_args.emplace_back(arg_value);
241     } else if (file.ResolveExecutableLocation()) {
242       char path[PATH_MAX];
243       file.GetPath(path, sizeof(path));
244       m_option_data.m_args.emplace_back(path);
245     } else {
246       error.SetErrorStringWithFormat(
247           "file specified in --file (-f) option doesn't exist: '%s'",
248           arg_value);
249       return error;
250     }
251   }
252 
253   if (auto *arg = args.getLastArg(OPT_arch)) {
254     auto arg_value = arg->getValue();
255     if (!lldb::SBDebugger::SetDefaultArchitecture(arg_value)) {
256       error.SetErrorStringWithFormat(
257           "invalid architecture in the -a or --arch option: '%s'", arg_value);
258       return error;
259     }
260   }
261 
262   if (auto *arg = args.getLastArg(OPT_script_language)) {
263     auto arg_value = arg->getValue();
264     m_debugger.SetScriptLanguage(m_debugger.GetScriptingLanguage(arg_value));
265   }
266 
267   if (args.hasArg(OPT_source_quietly)) {
268     m_option_data.m_source_quietly = true;
269   }
270 
271   if (auto *arg = args.getLastArg(OPT_attach_name)) {
272     auto arg_value = arg->getValue();
273     m_option_data.m_process_name = arg_value;
274   }
275 
276   if (args.hasArg(OPT_wait_for)) {
277     m_option_data.m_wait_for = true;
278   }
279 
280   if (auto *arg = args.getLastArg(OPT_attach_pid)) {
281     auto arg_value = arg->getValue();
282     char *remainder;
283     m_option_data.m_process_pid = strtol(arg_value, &remainder, 0);
284     if (remainder == arg_value || *remainder != '\0') {
285       error.SetErrorStringWithFormat(
286           "Could not convert process PID: \"%s\" into a pid.", arg_value);
287       return error;
288     }
289   }
290 
291   if (auto *arg = args.getLastArg(OPT_repl_language)) {
292     auto arg_value = arg->getValue();
293     m_option_data.m_repl_lang =
294         SBLanguageRuntime::GetLanguageTypeFromString(arg_value);
295     if (m_option_data.m_repl_lang == eLanguageTypeUnknown) {
296       error.SetErrorStringWithFormat("Unrecognized language name: \"%s\"",
297                                      arg_value);
298       return error;
299     }
300   }
301 
302   if (args.hasArg(OPT_repl)) {
303     m_option_data.m_repl = true;
304   }
305 
306   if (auto *arg = args.getLastArg(OPT_repl_)) {
307     m_option_data.m_repl = true;
308     if (auto arg_value = arg->getValue())
309       m_option_data.m_repl_options = arg_value;
310   }
311 
312   // We need to process the options below together as their relative order
313   // matters.
314   for (auto *arg : args.filtered(OPT_source_on_crash, OPT_one_line_on_crash,
315                                  OPT_source, OPT_source_before_file,
316                                  OPT_one_line, OPT_one_line_before_file)) {
317     auto arg_value = arg->getValue();
318     if (arg->getOption().matches(OPT_source_on_crash)) {
319       m_option_data.AddInitialCommand(arg_value, eCommandPlacementAfterCrash,
320                                       true, error);
321       if (error.Fail())
322         return error;
323     }
324 
325     if (arg->getOption().matches(OPT_one_line_on_crash)) {
326       m_option_data.AddInitialCommand(arg_value, eCommandPlacementAfterCrash,
327                                       false, error);
328       if (error.Fail())
329         return error;
330     }
331 
332     if (arg->getOption().matches(OPT_source)) {
333       m_option_data.AddInitialCommand(arg_value, eCommandPlacementAfterFile,
334                                       true, error);
335       if (error.Fail())
336         return error;
337     }
338 
339     if (arg->getOption().matches(OPT_source_before_file)) {
340       m_option_data.AddInitialCommand(arg_value, eCommandPlacementBeforeFile,
341                                       true, error);
342       if (error.Fail())
343         return error;
344     }
345 
346     if (arg->getOption().matches(OPT_one_line)) {
347       m_option_data.AddInitialCommand(arg_value, eCommandPlacementAfterFile,
348                                       false, error);
349       if (error.Fail())
350         return error;
351     }
352 
353     if (arg->getOption().matches(OPT_one_line_before_file)) {
354       m_option_data.AddInitialCommand(arg_value, eCommandPlacementBeforeFile,
355                                       false, error);
356       if (error.Fail())
357         return error;
358     }
359   }
360 
361   if (m_option_data.m_process_name.empty() &&
362       m_option_data.m_process_pid == LLDB_INVALID_PROCESS_ID) {
363 
364     // If the option data args array is empty that means the file was not
365     // specified with -f and we need to get it from the input args.
366     if (m_option_data.m_args.empty()) {
367       if (auto *arg = args.getLastArgNoClaim(OPT_INPUT)) {
368         m_option_data.m_args.push_back(arg->getAsString((args)));
369       }
370     }
371 
372     // Any argument following -- is an argument for the inferior.
373     if (auto *arg = args.getLastArgNoClaim(OPT_REM)) {
374       for (auto value : arg->getValues())
375         m_option_data.m_args.emplace_back(value);
376     }
377   } else if (args.getLastArgNoClaim() != nullptr) {
378     WithColor::warning() << "program arguments are ignored when attaching.\n";
379   }
380 
381   if (m_option_data.m_print_version) {
382     llvm::outs() << lldb::SBDebugger::GetVersionString() << '\n';
383     exiting = true;
384     return error;
385   }
386 
387   if (m_option_data.m_print_python_path) {
388     SBFileSpec python_file_spec = SBHostOS::GetLLDBPythonPath();
389     if (python_file_spec.IsValid()) {
390       char python_path[PATH_MAX];
391       size_t num_chars = python_file_spec.GetPath(python_path, PATH_MAX);
392       if (num_chars < PATH_MAX) {
393         llvm::outs() << python_path << '\n';
394       } else
395         llvm::outs() << "<PATH TOO LONG>\n";
396     } else
397       llvm::outs() << "<COULD NOT FIND PATH>\n";
398     exiting = true;
399     return error;
400   }
401 
402   return error;
403 }
404 
405 static inline int OpenPipe(int fds[2], std::size_t size) {
406 #ifdef _WIN32
407   return _pipe(fds, size, O_BINARY);
408 #else
409   (void)size;
410   return pipe(fds);
411 #endif
412 }
413 
414 static ::FILE *PrepareCommandsForSourcing(const char *commands_data,
415                                           size_t commands_size) {
416   enum PIPES { READ, WRITE }; // Indexes for the read and write fds
417   int fds[2] = {-1, -1};
418 
419   if (OpenPipe(fds, commands_size) != 0) {
420     WithColor::error()
421         << "can't create pipe file descriptors for LLDB commands\n";
422     return nullptr;
423   }
424 
425   ssize_t nrwr = write(fds[WRITE], commands_data, commands_size);
426   if (size_t(nrwr) != commands_size) {
427     WithColor::error()
428         << format(
429                "write(%i, %p, %" PRIu64
430                ") failed (errno = %i) when trying to open LLDB commands pipe",
431                fds[WRITE], static_cast<const void *>(commands_data),
432                static_cast<uint64_t>(commands_size), errno)
433         << '\n';
434     llvm::sys::Process::SafelyCloseFileDescriptor(fds[READ]);
435     llvm::sys::Process::SafelyCloseFileDescriptor(fds[WRITE]);
436     return nullptr;
437   }
438 
439   // Close the write end of the pipe, so that the command interpreter will exit
440   // when it consumes all the data.
441   llvm::sys::Process::SafelyCloseFileDescriptor(fds[WRITE]);
442 
443   // Open the read file descriptor as a FILE * that we can return as an input
444   // handle.
445   ::FILE *commands_file = fdopen(fds[READ], "rb");
446   if (commands_file == nullptr) {
447     WithColor::error() << format("fdopen(%i, \"rb\") failed (errno = %i) "
448                                  "when trying to open LLDB commands pipe",
449                                  fds[READ], errno)
450                        << '\n';
451     llvm::sys::Process::SafelyCloseFileDescriptor(fds[READ]);
452     return nullptr;
453   }
454 
455   // 'commands_file' now owns the read descriptor.
456   return commands_file;
457 }
458 
459 std::string EscapeString(std::string arg) {
460   std::string::size_type pos = 0;
461   while ((pos = arg.find_first_of("\"\\", pos)) != std::string::npos) {
462     arg.insert(pos, 1, '\\');
463     pos += 2;
464   }
465   return '"' + arg + '"';
466 }
467 
468 int Driver::MainLoop() {
469   if (::tcgetattr(STDIN_FILENO, &g_old_stdin_termios) == 0) {
470     g_old_stdin_termios_is_valid = true;
471     atexit(reset_stdin_termios);
472   }
473 
474 #ifndef _MSC_VER
475   // Disabling stdin buffering with MSVC's 2015 CRT exposes a bug in fgets
476   // which causes it to miss newlines depending on whether there have been an
477   // odd or even number of characters.  Bug has been reported to MS via Connect.
478   ::setbuf(stdin, nullptr);
479 #endif
480   ::setbuf(stdout, nullptr);
481 
482   m_debugger.SetErrorFileHandle(stderr, false);
483   m_debugger.SetOutputFileHandle(stdout, false);
484   // Don't take ownership of STDIN yet...
485   m_debugger.SetInputFileHandle(stdin, false);
486 
487   m_debugger.SetUseExternalEditor(m_option_data.m_use_external_editor);
488 
489   struct winsize window_size;
490   if ((isatty(STDIN_FILENO) != 0) &&
491       ::ioctl(STDIN_FILENO, TIOCGWINSZ, &window_size) == 0) {
492     if (window_size.ws_col > 0)
493       m_debugger.SetTerminalWidth(window_size.ws_col);
494   }
495 
496   SBCommandInterpreter sb_interpreter = m_debugger.GetCommandInterpreter();
497 
498   // Before we handle any options from the command line, we parse the
499   // .lldbinit file in the user's home directory.
500   SBCommandReturnObject result;
501   sb_interpreter.SourceInitFileInHomeDirectory(result);
502   if (m_option_data.m_debug_mode) {
503     result.PutError(m_debugger.GetErrorFile());
504     result.PutOutput(m_debugger.GetOutputFile());
505   }
506 
507   // Source the local .lldbinit file if it exists and we're allowed to source.
508   // Here we want to always print the return object because it contains the
509   // warning and instructions to load local lldbinit files.
510   sb_interpreter.SourceInitFileInCurrentWorkingDirectory(result);
511   result.PutError(m_debugger.GetErrorFile());
512   result.PutOutput(m_debugger.GetOutputFile());
513 
514   // We allow the user to specify an exit code when calling quit which we will
515   // return when exiting.
516   m_debugger.GetCommandInterpreter().AllowExitCodeOnQuit(true);
517 
518   // Now we handle options we got from the command line
519   SBStream commands_stream;
520 
521   // First source in the commands specified to be run before the file arguments
522   // are processed.
523   WriteCommandsForSourcing(eCommandPlacementBeforeFile, commands_stream);
524 
525   // If we're not in --repl mode, add the commands to process the file
526   // arguments, and the commands specified to run afterwards.
527   if (!m_option_data.m_repl) {
528     const size_t num_args = m_option_data.m_args.size();
529     if (num_args > 0) {
530       char arch_name[64];
531       if (lldb::SBDebugger::GetDefaultArchitecture(arch_name,
532                                                    sizeof(arch_name)))
533         commands_stream.Printf("target create --arch=%s %s", arch_name,
534                                EscapeString(m_option_data.m_args[0]).c_str());
535       else
536         commands_stream.Printf("target create %s",
537                                EscapeString(m_option_data.m_args[0]).c_str());
538 
539       if (!m_option_data.m_core_file.empty()) {
540         commands_stream.Printf(" --core %s",
541                                EscapeString(m_option_data.m_core_file).c_str());
542       }
543       commands_stream.Printf("\n");
544 
545       if (num_args > 1) {
546         commands_stream.Printf("settings set -- target.run-args ");
547         for (size_t arg_idx = 1; arg_idx < num_args; ++arg_idx)
548           commands_stream.Printf(
549               " %s", EscapeString(m_option_data.m_args[arg_idx]).c_str());
550         commands_stream.Printf("\n");
551       }
552     } else if (!m_option_data.m_core_file.empty()) {
553       commands_stream.Printf("target create --core %s\n",
554                              EscapeString(m_option_data.m_core_file).c_str());
555     } else if (!m_option_data.m_process_name.empty()) {
556       commands_stream.Printf(
557           "process attach --name %s",
558           EscapeString(m_option_data.m_process_name).c_str());
559 
560       if (m_option_data.m_wait_for)
561         commands_stream.Printf(" --waitfor");
562 
563       commands_stream.Printf("\n");
564 
565     } else if (LLDB_INVALID_PROCESS_ID != m_option_data.m_process_pid) {
566       commands_stream.Printf("process attach --pid %" PRIu64 "\n",
567                              m_option_data.m_process_pid);
568     }
569 
570     WriteCommandsForSourcing(eCommandPlacementAfterFile, commands_stream);
571   } else if (!m_option_data.m_after_file_commands.empty()) {
572     // We're in repl mode and after-file-load commands were specified.
573     WithColor::warning() << "commands specified to run after file load (via -o "
574                             "or -s) are ignored in REPL mode.\n";
575   }
576 
577   if (m_option_data.m_debug_mode) {
578     result.PutError(m_debugger.GetErrorFile());
579     result.PutOutput(m_debugger.GetOutputFile());
580   }
581 
582   const bool handle_events = true;
583   const bool spawn_thread = false;
584 
585   // Check if we have any data in the commands stream, and if so, save it to a
586   // temp file
587   // so we can then run the command interpreter using the file contents.
588   const char *commands_data = commands_stream.GetData();
589   const size_t commands_size = commands_stream.GetSize();
590 
591   // The command file might have requested that we quit, this variable will
592   // track that.
593   bool quit_requested = false;
594   bool stopped_for_crash = false;
595   if ((commands_data != nullptr) && (commands_size != 0u)) {
596     bool success = true;
597     FILE *commands_file =
598         PrepareCommandsForSourcing(commands_data, commands_size);
599     if (commands_file != nullptr) {
600       m_debugger.SetInputFileHandle(commands_file, true);
601 
602       // Set the debugger into Sync mode when running the command file.
603       // Otherwise command files
604       // that run the target won't run in a sensible way.
605       bool old_async = m_debugger.GetAsync();
606       m_debugger.SetAsync(false);
607       int num_errors = 0;
608 
609       SBCommandInterpreterRunOptions options;
610       options.SetStopOnError(true);
611       if (m_option_data.m_batch)
612         options.SetStopOnCrash(true);
613 
614       m_debugger.RunCommandInterpreter(handle_events, spawn_thread, options,
615                                        num_errors, quit_requested,
616                                        stopped_for_crash);
617 
618       if (m_option_data.m_batch && stopped_for_crash &&
619           !m_option_data.m_after_crash_commands.empty()) {
620         SBStream crash_commands_stream;
621         WriteCommandsForSourcing(eCommandPlacementAfterCrash,
622                                  crash_commands_stream);
623         const char *crash_commands_data = crash_commands_stream.GetData();
624         const size_t crash_commands_size = crash_commands_stream.GetSize();
625         commands_file = PrepareCommandsForSourcing(crash_commands_data,
626                                                    crash_commands_size);
627         if (commands_file != nullptr) {
628           bool local_quit_requested;
629           bool local_stopped_for_crash;
630           m_debugger.SetInputFileHandle(commands_file, true);
631 
632           m_debugger.RunCommandInterpreter(handle_events, spawn_thread, options,
633                                            num_errors, local_quit_requested,
634                                            local_stopped_for_crash);
635           if (local_quit_requested)
636             quit_requested = true;
637         }
638       }
639       m_debugger.SetAsync(old_async);
640     } else
641       success = false;
642 
643     // Something went wrong with command pipe
644     if (!success) {
645       exit(1);
646     }
647   }
648 
649   // Now set the input file handle to STDIN and run the command
650   // interpreter again in interactive mode or repl mode and let the debugger
651   // take ownership of stdin
652 
653   bool go_interactive = true;
654   if (quit_requested)
655     go_interactive = false;
656   else if (m_option_data.m_batch && !stopped_for_crash)
657     go_interactive = false;
658 
659   if (go_interactive) {
660     m_debugger.SetInputFileHandle(stdin, true);
661 
662     if (m_option_data.m_repl) {
663       const char *repl_options = nullptr;
664       if (!m_option_data.m_repl_options.empty())
665         repl_options = m_option_data.m_repl_options.c_str();
666       SBError error(
667           m_debugger.RunREPL(m_option_data.m_repl_lang, repl_options));
668       if (error.Fail()) {
669         const char *error_cstr = error.GetCString();
670         if ((error_cstr != nullptr) && (error_cstr[0] != 0))
671           WithColor::error() << error_cstr << '\n';
672         else
673           WithColor::error() << error.GetError() << '\n';
674       }
675     } else {
676       m_debugger.RunCommandInterpreter(handle_events, spawn_thread);
677     }
678   }
679 
680   reset_stdin_termios();
681   fclose(stdin);
682 
683   int exit_code = sb_interpreter.GetQuitStatus();
684   SBDebugger::Destroy(m_debugger);
685   return exit_code;
686 }
687 
688 void Driver::ResizeWindow(unsigned short col) {
689   GetDebugger().SetTerminalWidth(col);
690 }
691 
692 void sigwinch_handler(int signo) {
693   struct winsize window_size;
694   if ((isatty(STDIN_FILENO) != 0) &&
695       ::ioctl(STDIN_FILENO, TIOCGWINSZ, &window_size) == 0) {
696     if ((window_size.ws_col > 0) && g_driver != nullptr) {
697       g_driver->ResizeWindow(window_size.ws_col);
698     }
699   }
700 }
701 
702 void sigint_handler(int signo) {
703 #ifdef _WIN32 // Restore handler as it is not persistent on Windows
704   signal(SIGINT, sigint_handler);
705 #endif
706   static std::atomic_flag g_interrupt_sent = ATOMIC_FLAG_INIT;
707   if (g_driver != nullptr) {
708     if (!g_interrupt_sent.test_and_set()) {
709       g_driver->GetDebugger().DispatchInputInterrupt();
710       g_interrupt_sent.clear();
711       return;
712     }
713   }
714 
715   _exit(signo);
716 }
717 
718 void sigtstp_handler(int signo) {
719   if (g_driver != nullptr)
720     g_driver->GetDebugger().SaveInputTerminalState();
721 
722   signal(signo, SIG_DFL);
723   kill(getpid(), signo);
724   signal(signo, sigtstp_handler);
725 }
726 
727 void sigcont_handler(int signo) {
728   if (g_driver != nullptr)
729     g_driver->GetDebugger().RestoreInputTerminalState();
730 
731   signal(signo, SIG_DFL);
732   kill(getpid(), signo);
733   signal(signo, sigcont_handler);
734 }
735 
736 static void printHelp(LLDBOptTable &table, llvm::StringRef tool_name) {
737   std::string usage_str = tool_name.str() + "options";
738   table.PrintHelp(llvm::outs(), usage_str.c_str(), "LLDB", false);
739 
740   std::string examples = R"___(
741 EXAMPLES:
742   The debugger can be started in several modes.
743 
744   Passing an executable as a positional argument prepares lldb to debug the
745   given executable. Arguments passed after -- are considered arguments to the
746   debugged executable.
747 
748     lldb --arch x86_64 /path/to/program -- --arch arvm7
749 
750   Passing one of the attach options causes lldb to immediately attach to the
751   given process.
752 
753     lldb -p <pid>
754     lldb -n <process-name>
755 
756   Passing --repl starts lldb in REPL mode.
757 
758     lldb -r
759 
760   Passing --core causes lldb to debug the core file.
761 
762     lldb -c /path/to/core
763 
764   Command options can be combined with these modes and cause lldb to run the
765   specified commands before or after events, like loading the file or crashing,
766   in the order provided on the command line.
767 
768     lldb -O 'settings set stop-disassembly-count 20' -o 'run' -o 'bt'
769     lldb -S /source/before/file -s /source/after/file
770     lldb -K /source/before/crash -k /source/after/crash
771 
772   Note: In REPL mode no file is loaded, so commands specified to run after
773   loading the file (via -o or -s) will be ignored.
774   )___";
775   llvm::outs() << examples;
776 }
777 
778 llvm::Optional<int> InitializeReproducer(opt::InputArgList &input_args) {
779   if (auto *replay_path = input_args.getLastArg(OPT_replay)) {
780     if (const char *error = SBReproducer::Replay(replay_path->getValue())) {
781       WithColor::error() << "reproducer replay failed: " << error << '\n';
782       return 1;
783     }
784     return 0;
785   }
786 
787   bool capture = input_args.hasArg(OPT_capture);
788   auto *capture_path = input_args.getLastArg(OPT_capture_path);
789 
790   if (capture || capture_path) {
791     if (capture_path) {
792       if (!capture)
793         WithColor::warning() << "-capture-path specified without -capture\n";
794       if (const char *error = SBReproducer::Capture(capture_path->getValue())) {
795         WithColor::error() << "reproducer capture failed: " << error << '\n';
796         return 1;
797       }
798     } else {
799       const char *error = SBReproducer::Capture();
800       if (error) {
801         WithColor::error() << "reproducer capture failed: " << error << '\n';
802         return 1;
803       }
804     }
805   }
806 
807   return llvm::None;
808 }
809 
810 int main(int argc, char const *argv[])
811 {
812   llvm::InitLLVM IL(argc, argv);
813 
814   // Print stack trace on crash.
815   llvm::StringRef ToolName = llvm::sys::path::filename(argv[0]);
816   llvm::sys::PrintStackTraceOnErrorSignal(ToolName);
817   llvm::PrettyStackTraceProgram X(argc, argv);
818 
819   // Parse arguments.
820   LLDBOptTable T;
821   unsigned MAI;
822   unsigned MAC;
823   ArrayRef<const char *> arg_arr = makeArrayRef(argv + 1, argc - 1);
824   opt::InputArgList input_args = T.ParseArgs(arg_arr, MAI, MAC);
825 
826   if (input_args.hasArg(OPT_help)) {
827     printHelp(T, ToolName);
828     return 0;
829   }
830 
831   for (auto *arg : input_args.filtered(OPT_UNKNOWN)) {
832     WithColor::warning() << "ignoring unknown option: " << arg->getSpelling()
833                          << '\n';
834   }
835 
836   if (auto exit_code = InitializeReproducer(input_args)) {
837     return *exit_code;
838   }
839 
840   SBError error = SBDebugger::InitializeWithErrorHandling();
841   if (error.Fail()) {
842     WithColor::error() << "initialization failed: " << error.GetCString()
843                        << '\n';
844     return 1;
845   }
846   SBHostOS::ThreadCreated("<lldb.driver.main-thread>");
847 
848   signal(SIGINT, sigint_handler);
849 #if !defined(_MSC_VER)
850   signal(SIGPIPE, SIG_IGN);
851   signal(SIGWINCH, sigwinch_handler);
852   signal(SIGTSTP, sigtstp_handler);
853   signal(SIGCONT, sigcont_handler);
854 #endif
855 
856   // Occasionally, during test teardown, LLDB writes to a closed pipe.
857   // Sometimes the communication is inherently unreliable, so LLDB tries to
858   // avoid being killed due to SIGPIPE. However, LLVM's default SIGPIPE behavior
859   // is to exit with IO_ERR. Opt LLDB out of that.
860   //
861   // We don't disable LLVM's signal handling entirely because we still want
862   // pretty stack traces, and file cleanup (for when, say, the clang embedded
863   // in LLDB leaves behind temporary objects).
864   llvm::sys::SetPipeSignalFunction(nullptr);
865 
866   int exit_code = 0;
867   // Create a scope for driver so that the driver object will destroy itself
868   // before SBDebugger::Terminate() is called.
869   {
870     Driver driver;
871 
872     bool exiting = false;
873     SBError error(driver.ProcessArgs(input_args, exiting));
874     if (error.Fail()) {
875       exit_code = 1;
876       if (const char *error_cstr = error.GetCString())
877         WithColor::error() << error_cstr << '\n';
878     } else if (!exiting) {
879       exit_code = driver.MainLoop();
880     }
881   }
882 
883   SBDebugger::Terminate();
884   return exit_code;
885 }
886