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