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/SBCommandInterpreterRunOptions.h"
13 #include "lldb/API/SBCommandReturnObject.h"
14 #include "lldb/API/SBDebugger.h"
15 #include "lldb/API/SBFile.h"
16 #include "lldb/API/SBHostOS.h"
17 #include "lldb/API/SBLanguageRuntime.h"
18 #include "lldb/API/SBReproducer.h"
19 #include "lldb/API/SBStream.h"
20 #include "lldb/API/SBStringList.h"
21 
22 #include "llvm/ADT/StringRef.h"
23 #include "llvm/Support/Format.h"
24 #include "llvm/Support/InitLLVM.h"
25 #include "llvm/Support/Path.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   bool go_interactive = true;
592   if ((commands_data != nullptr) && (commands_size != 0u)) {
593     FILE *commands_file =
594         PrepareCommandsForSourcing(commands_data, commands_size);
595 
596     if (commands_file == nullptr) {
597       // We should have already printed an error in PrepareCommandsForSourcing.
598       exit(1);
599     }
600 
601     m_debugger.SetInputFileHandle(commands_file, true);
602 
603     // Set the debugger into Sync mode when running the command file. Otherwise
604     // command files that run the target won't run in a sensible way.
605     bool old_async = m_debugger.GetAsync();
606     m_debugger.SetAsync(false);
607 
608     SBCommandInterpreterRunOptions options;
609     options.SetAutoHandleEvents(true);
610     options.SetSpawnThread(false);
611     options.SetStopOnError(true);
612     options.SetStopOnCrash(m_option_data.m_batch);
613 
614     SBCommandInterpreterRunResult results =
615         m_debugger.RunCommandInterpreter(options);
616     if (results.GetResult() == lldb::eCommandInterpreterResultQuitRequested)
617       go_interactive = false;
618     if (m_option_data.m_batch &&
619         results.GetResult() != lldb::eCommandInterpreterResultInferiorCrash)
620       go_interactive = false;
621 
622     if (m_option_data.m_batch &&
623         results.GetResult() == lldb::eCommandInterpreterResultInferiorCrash &&
624         !m_option_data.m_after_crash_commands.empty()) {
625       SBStream crash_commands_stream;
626       WriteCommandsForSourcing(eCommandPlacementAfterCrash,
627                                crash_commands_stream);
628       const char *crash_commands_data = crash_commands_stream.GetData();
629       const size_t crash_commands_size = crash_commands_stream.GetSize();
630       commands_file =
631           PrepareCommandsForSourcing(crash_commands_data, crash_commands_size);
632       if (commands_file != nullptr) {
633         m_debugger.SetInputFileHandle(commands_file, true);
634         SBCommandInterpreterRunResult local_results =
635             m_debugger.RunCommandInterpreter(options);
636         if (local_results.GetResult() ==
637             lldb::eCommandInterpreterResultQuitRequested)
638           go_interactive = false;
639       }
640     }
641     m_debugger.SetAsync(old_async);
642   }
643 
644   // Now set the input file handle to STDIN and run the command interpreter
645   // again in interactive mode or repl mode and let the debugger take ownership
646   // of stdin.
647   if (go_interactive) {
648     m_debugger.SetInputFileHandle(stdin, true);
649 
650     if (m_option_data.m_repl) {
651       const char *repl_options = nullptr;
652       if (!m_option_data.m_repl_options.empty())
653         repl_options = m_option_data.m_repl_options.c_str();
654       SBError error(
655           m_debugger.RunREPL(m_option_data.m_repl_lang, repl_options));
656       if (error.Fail()) {
657         const char *error_cstr = error.GetCString();
658         if ((error_cstr != nullptr) && (error_cstr[0] != 0))
659           WithColor::error() << error_cstr << '\n';
660         else
661           WithColor::error() << error.GetError() << '\n';
662       }
663     } else {
664       m_debugger.RunCommandInterpreter(handle_events, spawn_thread);
665     }
666   }
667 
668   reset_stdin_termios();
669   fclose(stdin);
670 
671   int exit_code = sb_interpreter.GetQuitStatus();
672   SBDebugger::Destroy(m_debugger);
673   return exit_code;
674 }
675 
676 void Driver::ResizeWindow(unsigned short col) {
677   GetDebugger().SetTerminalWidth(col);
678 }
679 
680 void sigwinch_handler(int signo) {
681   struct winsize window_size;
682   if ((isatty(STDIN_FILENO) != 0) &&
683       ::ioctl(STDIN_FILENO, TIOCGWINSZ, &window_size) == 0) {
684     if ((window_size.ws_col > 0) && g_driver != nullptr) {
685       g_driver->ResizeWindow(window_size.ws_col);
686     }
687   }
688 }
689 
690 void sigint_handler(int signo) {
691 #ifdef _WIN32 // Restore handler as it is not persistent on Windows
692   signal(SIGINT, sigint_handler);
693 #endif
694   static std::atomic_flag g_interrupt_sent = ATOMIC_FLAG_INIT;
695   if (g_driver != nullptr) {
696     if (!g_interrupt_sent.test_and_set()) {
697       g_driver->GetDebugger().DispatchInputInterrupt();
698       g_interrupt_sent.clear();
699       return;
700     }
701   }
702 
703   _exit(signo);
704 }
705 
706 void sigtstp_handler(int signo) {
707   if (g_driver != nullptr)
708     g_driver->GetDebugger().SaveInputTerminalState();
709 
710   signal(signo, SIG_DFL);
711   kill(getpid(), signo);
712   signal(signo, sigtstp_handler);
713 }
714 
715 void sigcont_handler(int signo) {
716   if (g_driver != nullptr)
717     g_driver->GetDebugger().RestoreInputTerminalState();
718 
719   signal(signo, SIG_DFL);
720   kill(getpid(), signo);
721   signal(signo, sigcont_handler);
722 }
723 
724 void reproducer_handler(void *argv0) {
725   if (SBReproducer::Generate()) {
726     auto exe = static_cast<const char *>(argv0);
727     llvm::outs() << "********************\n";
728     llvm::outs() << "Crash reproducer for ";
729     llvm::outs() << lldb::SBDebugger::GetVersionString() << '\n';
730     llvm::outs() << '\n';
731     llvm::outs() << "Reproducer written to '" << SBReproducer::GetPath()
732                  << "'\n";
733     llvm::outs() << '\n';
734     llvm::outs() << "Before attaching the reproducer to a bug report:\n";
735     llvm::outs() << " - Look at the directory to ensure you're willing to "
736                     "share its content.\n";
737     llvm::outs()
738         << " - Make sure the reproducer works by replaying the reproducer.\n";
739     llvm::outs() << '\n';
740     llvm::outs() << "Replay the reproducer with the following command:\n";
741     llvm::outs() << exe << " -replay " << SBReproducer::GetPath() << "\n";
742     llvm::outs() << "********************\n";
743   }
744 }
745 
746 static void printHelp(LLDBOptTable &table, llvm::StringRef tool_name) {
747   std::string usage_str = tool_name.str() + " [options]";
748   table.PrintHelp(llvm::outs(), usage_str.c_str(), "LLDB", false);
749 
750   std::string examples = R"___(
751 EXAMPLES:
752   The debugger can be started in several modes.
753 
754   Passing an executable as a positional argument prepares lldb to debug the
755   given executable. Arguments passed after -- are considered arguments to the
756   debugged executable.
757 
758     lldb --arch x86_64 /path/to/program -- --arch arvm7
759 
760   Passing one of the attach options causes lldb to immediately attach to the
761   given process.
762 
763     lldb -p <pid>
764     lldb -n <process-name>
765 
766   Passing --repl starts lldb in REPL mode.
767 
768     lldb -r
769 
770   Passing --core causes lldb to debug the core file.
771 
772     lldb -c /path/to/core
773 
774   Command options can be combined with these modes and cause lldb to run the
775   specified commands before or after events, like loading the file or crashing,
776   in the order provided on the command line.
777 
778     lldb -O 'settings set stop-disassembly-count 20' -o 'run' -o 'bt'
779     lldb -S /source/before/file -s /source/after/file
780     lldb -K /source/before/crash -k /source/after/crash
781 
782   Note: In REPL mode no file is loaded, so commands specified to run after
783   loading the file (via -o or -s) will be ignored.)___";
784   llvm::outs() << examples << '\n';
785 }
786 
787 llvm::Optional<int> InitializeReproducer(opt::InputArgList &input_args) {
788   if (auto *replay_path = input_args.getLastArg(OPT_replay)) {
789     const bool skip_version_check = input_args.hasArg(OPT_skip_version_check);
790     if (const char *error =
791             SBReproducer::Replay(replay_path->getValue(), skip_version_check)) {
792       WithColor::error() << "reproducer replay failed: " << error << '\n';
793       return 1;
794     }
795     return 0;
796   }
797 
798   bool capture = input_args.hasArg(OPT_capture);
799   bool auto_generate = input_args.hasArg(OPT_auto_generate);
800   auto *capture_path = input_args.getLastArg(OPT_capture_path);
801 
802   if (auto_generate && !capture) {
803     WithColor::warning()
804         << "-reproducer-auto-generate specified without -capture\n";
805   }
806 
807   if (capture || capture_path) {
808     if (capture_path) {
809       if (!capture)
810         WithColor::warning() << "-capture-path specified without -capture\n";
811       if (const char *error = SBReproducer::Capture(capture_path->getValue())) {
812         WithColor::error() << "reproducer capture failed: " << error << '\n';
813         return 1;
814       }
815     } else {
816       const char *error = SBReproducer::Capture();
817       if (error) {
818         WithColor::error() << "reproducer capture failed: " << error << '\n';
819         return 1;
820       }
821     }
822     if (auto_generate)
823       SBReproducer::SetAutoGenerate(true);
824   }
825 
826   return llvm::None;
827 }
828 
829 int main(int argc, char const *argv[]) {
830   // Setup LLVM signal handlers and make sure we call llvm_shutdown() on
831   // destruction.
832   llvm::InitLLVM IL(argc, argv, /*InstallPipeSignalExitHandler=*/false);
833 
834   // Parse arguments.
835   LLDBOptTable T;
836   unsigned MAI;
837   unsigned MAC;
838   ArrayRef<const char *> arg_arr = makeArrayRef(argv + 1, argc - 1);
839   opt::InputArgList input_args = T.ParseArgs(arg_arr, MAI, MAC);
840 
841   if (input_args.hasArg(OPT_help)) {
842     printHelp(T, llvm::sys::path::filename(argv[0]));
843     return 0;
844   }
845 
846   for (auto *arg : input_args.filtered(OPT_UNKNOWN)) {
847     WithColor::warning() << "ignoring unknown option: " << arg->getSpelling()
848                          << '\n';
849   }
850 
851   if (auto exit_code = InitializeReproducer(input_args)) {
852     return *exit_code;
853   }
854 
855   // Register the reproducer signal handler.
856   llvm::sys::AddSignalHandler(reproducer_handler, const_cast<char *>(argv[0]));
857 
858   SBError error = SBDebugger::InitializeWithErrorHandling();
859   if (error.Fail()) {
860     WithColor::error() << "initialization failed: " << error.GetCString()
861                        << '\n';
862     return 1;
863   }
864   SBHostOS::ThreadCreated("<lldb.driver.main-thread>");
865 
866   signal(SIGINT, sigint_handler);
867 #if !defined(_MSC_VER)
868   signal(SIGPIPE, SIG_IGN);
869   signal(SIGWINCH, sigwinch_handler);
870   signal(SIGTSTP, sigtstp_handler);
871   signal(SIGCONT, sigcont_handler);
872 #endif
873 
874   int exit_code = 0;
875   // Create a scope for driver so that the driver object will destroy itself
876   // before SBDebugger::Terminate() is called.
877   {
878     Driver driver;
879 
880     bool exiting = false;
881     SBError error(driver.ProcessArgs(input_args, exiting));
882     if (error.Fail()) {
883       exit_code = 1;
884       if (const char *error_cstr = error.GetCString())
885         WithColor::error() << error_cstr << '\n';
886     } else if (!exiting) {
887       exit_code = driver.MainLoop();
888     }
889   }
890 
891   SBDebugger::Terminate();
892   return exit_code;
893 }
894