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 <clocale>
35 #include <csignal>
36 #include <string>
37 #include <thread>
38 #include <utility>
39 
40 #include <climits>
41 #include <cstdio>
42 #include <cstdlib>
43 #include <cstring>
44 #include <fcntl.h>
45 
46 // Includes for pipe()
47 #if defined(_WIN32)
48 #include <fcntl.h>
49 #include <io.h>
50 #else
51 #include <unistd.h>
52 #endif
53 
54 #if !defined(__APPLE__)
55 #include "llvm/Support/DataTypes.h"
56 #endif
57 
58 using namespace lldb;
59 using namespace llvm;
60 
61 namespace {
62 enum ID {
63   OPT_INVALID = 0, // This is not an option ID.
64 #define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM,  \
65                HELPTEXT, METAVAR, VALUES)                                      \
66   OPT_##ID,
67 #include "Options.inc"
68 #undef OPTION
69 };
70 
71 #define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE;
72 #include "Options.inc"
73 #undef PREFIX
74 
75 const opt::OptTable::Info InfoTable[] = {
76 #define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM,  \
77                HELPTEXT, METAVAR, VALUES)                                      \
78   {                                                                            \
79       PREFIX,      NAME,      HELPTEXT,                                        \
80       METAVAR,     OPT_##ID,  opt::Option::KIND##Class,                        \
81       PARAM,       FLAGS,     OPT_##GROUP,                                     \
82       OPT_##ALIAS, ALIASARGS, VALUES},
83 #include "Options.inc"
84 #undef OPTION
85 };
86 
87 class LLDBOptTable : public opt::OptTable {
88 public:
89   LLDBOptTable() : OptTable(InfoTable) {}
90 };
91 } // namespace
92 
93 static void reset_stdin_termios();
94 static bool g_old_stdin_termios_is_valid = false;
95 static struct termios g_old_stdin_termios;
96 
97 static Driver *g_driver = nullptr;
98 
99 // In the Driver::MainLoop, we change the terminal settings.  This function is
100 // added as an atexit handler to make sure we clean them up.
101 static void reset_stdin_termios() {
102   if (g_old_stdin_termios_is_valid) {
103     g_old_stdin_termios_is_valid = false;
104     ::tcsetattr(STDIN_FILENO, TCSANOW, &g_old_stdin_termios);
105   }
106 }
107 
108 Driver::Driver()
109     : SBBroadcaster("Driver"), m_debugger(SBDebugger::Create(false)) {
110   // We want to be able to handle CTRL+D in the terminal to have it terminate
111   // certain input
112   m_debugger.SetCloseInputOnEOF(false);
113   g_driver = this;
114 }
115 
116 Driver::~Driver() {
117   SBDebugger::Destroy(m_debugger);
118   g_driver = nullptr;
119 }
120 
121 void Driver::OptionData::AddInitialCommand(std::string command,
122                                            CommandPlacement placement,
123                                            bool is_file, SBError &error) {
124   std::vector<InitialCmdEntry> *command_set;
125   switch (placement) {
126   case eCommandPlacementBeforeFile:
127     command_set = &(m_initial_commands);
128     break;
129   case eCommandPlacementAfterFile:
130     command_set = &(m_after_file_commands);
131     break;
132   case eCommandPlacementAfterCrash:
133     command_set = &(m_after_crash_commands);
134     break;
135   }
136 
137   if (is_file) {
138     SBFileSpec file(command.c_str());
139     if (file.Exists())
140       command_set->push_back(InitialCmdEntry(command, is_file));
141     else if (file.ResolveExecutableLocation()) {
142       char final_path[PATH_MAX];
143       file.GetPath(final_path, sizeof(final_path));
144       command_set->push_back(InitialCmdEntry(final_path, is_file));
145     } else
146       error.SetErrorStringWithFormat(
147           "file specified in --source (-s) option doesn't exist: '%s'",
148           command.c_str());
149   } else
150     command_set->push_back(InitialCmdEntry(command, is_file));
151 }
152 
153 void Driver::WriteCommandsForSourcing(CommandPlacement placement,
154                                       SBStream &strm) {
155   std::vector<OptionData::InitialCmdEntry> *command_set;
156   switch (placement) {
157   case eCommandPlacementBeforeFile:
158     command_set = &m_option_data.m_initial_commands;
159     break;
160   case eCommandPlacementAfterFile:
161     command_set = &m_option_data.m_after_file_commands;
162     break;
163   case eCommandPlacementAfterCrash:
164     command_set = &m_option_data.m_after_crash_commands;
165     break;
166   }
167 
168   for (const auto &command_entry : *command_set) {
169     const char *command = command_entry.contents.c_str();
170     if (command_entry.is_file) {
171       bool source_quietly =
172           m_option_data.m_source_quietly || command_entry.source_quietly;
173       strm.Printf("command source -s %i '%s'\n",
174                   static_cast<int>(source_quietly), command);
175     } else
176       strm.Printf("%s\n", command);
177   }
178 }
179 
180 // Check the arguments that were passed to this program to make sure they are
181 // valid and to get their argument values (if any).  Return a boolean value
182 // indicating whether or not to start up the full debugger (i.e. the Command
183 // Interpreter) or not.  Return FALSE if the arguments were invalid OR if the
184 // user only wanted help or version information.
185 SBError Driver::ProcessArgs(const opt::InputArgList &args, bool &exiting) {
186   SBError error;
187 
188   // This is kind of a pain, but since we make the debugger in the Driver's
189   // constructor, we can't know at that point whether we should read in init
190   // files yet.  So we don't read them in in the Driver constructor, then set
191   // the flags back to "read them in" here, and then if we see the "-n" flag,
192   // we'll turn it off again.  Finally we have to read them in by hand later in
193   // the main loop.
194   m_debugger.SkipLLDBInitFiles(false);
195   m_debugger.SkipAppInitFiles(false);
196 
197   if (args.hasArg(OPT_version)) {
198     m_option_data.m_print_version = true;
199   }
200 
201   if (args.hasArg(OPT_python_path)) {
202     m_option_data.m_print_python_path = true;
203   }
204 
205   if (args.hasArg(OPT_batch)) {
206     m_option_data.m_batch = true;
207   }
208 
209   if (auto *arg = args.getLastArg(OPT_core)) {
210     auto arg_value = arg->getValue();
211     SBFileSpec file(arg_value);
212     if (!file.Exists()) {
213       error.SetErrorStringWithFormat(
214           "file specified in --core (-c) option doesn't exist: '%s'",
215           arg_value);
216       return error;
217     }
218     m_option_data.m_core_file = arg_value;
219   }
220 
221   if (args.hasArg(OPT_editor)) {
222     m_option_data.m_use_external_editor = true;
223   }
224 
225   if (args.hasArg(OPT_no_lldbinit)) {
226     m_debugger.SkipLLDBInitFiles(true);
227     m_debugger.SkipAppInitFiles(true);
228   }
229 
230   if (args.hasArg(OPT_local_lldbinit)) {
231     lldb::SBDebugger::SetInternalVariable("target.load-cwd-lldbinit", "true",
232                                           m_debugger.GetInstanceName());
233   }
234 
235   if (args.hasArg(OPT_no_use_colors)) {
236     m_debugger.SetUseColor(false);
237     m_option_data.m_debug_mode = true;
238   }
239 
240   if (auto *arg = args.getLastArg(OPT_file)) {
241     auto arg_value = arg->getValue();
242     SBFileSpec file(arg_value);
243     if (file.Exists()) {
244       m_option_data.m_args.emplace_back(arg_value);
245     } else if (file.ResolveExecutableLocation()) {
246       char path[PATH_MAX];
247       file.GetPath(path, sizeof(path));
248       m_option_data.m_args.emplace_back(path);
249     } else {
250       error.SetErrorStringWithFormat(
251           "file specified in --file (-f) option doesn't exist: '%s'",
252           arg_value);
253       return error;
254     }
255   }
256 
257   if (auto *arg = args.getLastArg(OPT_arch)) {
258     auto arg_value = arg->getValue();
259     if (!lldb::SBDebugger::SetDefaultArchitecture(arg_value)) {
260       error.SetErrorStringWithFormat(
261           "invalid architecture in the -a or --arch option: '%s'", arg_value);
262       return error;
263     }
264   }
265 
266   if (auto *arg = args.getLastArg(OPT_script_language)) {
267     auto arg_value = arg->getValue();
268     m_debugger.SetScriptLanguage(m_debugger.GetScriptingLanguage(arg_value));
269   }
270 
271   if (args.hasArg(OPT_source_quietly)) {
272     m_option_data.m_source_quietly = true;
273   }
274 
275   if (auto *arg = args.getLastArg(OPT_attach_name)) {
276     auto arg_value = arg->getValue();
277     m_option_data.m_process_name = arg_value;
278   }
279 
280   if (args.hasArg(OPT_wait_for)) {
281     m_option_data.m_wait_for = true;
282   }
283 
284   if (auto *arg = args.getLastArg(OPT_attach_pid)) {
285     auto arg_value = arg->getValue();
286     char *remainder;
287     m_option_data.m_process_pid = strtol(arg_value, &remainder, 0);
288     if (remainder == arg_value || *remainder != '\0') {
289       error.SetErrorStringWithFormat(
290           "Could not convert process PID: \"%s\" into a pid.", arg_value);
291       return error;
292     }
293   }
294 
295   if (auto *arg = args.getLastArg(OPT_repl_language)) {
296     auto arg_value = arg->getValue();
297     m_option_data.m_repl_lang =
298         SBLanguageRuntime::GetLanguageTypeFromString(arg_value);
299     if (m_option_data.m_repl_lang == eLanguageTypeUnknown) {
300       error.SetErrorStringWithFormat("Unrecognized language name: \"%s\"",
301                                      arg_value);
302       return error;
303     }
304   }
305 
306   if (args.hasArg(OPT_repl)) {
307     m_option_data.m_repl = true;
308   }
309 
310   if (auto *arg = args.getLastArg(OPT_repl_)) {
311     m_option_data.m_repl = true;
312     if (auto arg_value = arg->getValue())
313       m_option_data.m_repl_options = arg_value;
314   }
315 
316   // We need to process the options below together as their relative order
317   // matters.
318   for (auto *arg : args.filtered(OPT_source_on_crash, OPT_one_line_on_crash,
319                                  OPT_source, OPT_source_before_file,
320                                  OPT_one_line, OPT_one_line_before_file)) {
321     auto arg_value = arg->getValue();
322     if (arg->getOption().matches(OPT_source_on_crash)) {
323       m_option_data.AddInitialCommand(arg_value, eCommandPlacementAfterCrash,
324                                       true, error);
325       if (error.Fail())
326         return error;
327     }
328 
329     if (arg->getOption().matches(OPT_one_line_on_crash)) {
330       m_option_data.AddInitialCommand(arg_value, eCommandPlacementAfterCrash,
331                                       false, error);
332       if (error.Fail())
333         return error;
334     }
335 
336     if (arg->getOption().matches(OPT_source)) {
337       m_option_data.AddInitialCommand(arg_value, eCommandPlacementAfterFile,
338                                       true, error);
339       if (error.Fail())
340         return error;
341     }
342 
343     if (arg->getOption().matches(OPT_source_before_file)) {
344       m_option_data.AddInitialCommand(arg_value, eCommandPlacementBeforeFile,
345                                       true, error);
346       if (error.Fail())
347         return error;
348     }
349 
350     if (arg->getOption().matches(OPT_one_line)) {
351       m_option_data.AddInitialCommand(arg_value, eCommandPlacementAfterFile,
352                                       false, error);
353       if (error.Fail())
354         return error;
355     }
356 
357     if (arg->getOption().matches(OPT_one_line_before_file)) {
358       m_option_data.AddInitialCommand(arg_value, eCommandPlacementBeforeFile,
359                                       false, error);
360       if (error.Fail())
361         return error;
362     }
363   }
364 
365   if (m_option_data.m_process_name.empty() &&
366       m_option_data.m_process_pid == LLDB_INVALID_PROCESS_ID) {
367 
368     for (auto *arg : args.filtered(OPT_INPUT))
369       m_option_data.m_args.push_back(arg->getAsString((args)));
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   // REPL init file or the default file in the user's home directory.
499   SBCommandReturnObject result;
500   sb_interpreter.SourceInitFileInHomeDirectory(result, m_option_data.m_repl);
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   bool go_interactive = true;
591   if ((commands_data != nullptr) && (commands_size != 0u)) {
592     FILE *commands_file =
593         PrepareCommandsForSourcing(commands_data, commands_size);
594 
595     if (commands_file == nullptr) {
596       // We should have already printed an error in PrepareCommandsForSourcing.
597       return 1;
598     }
599 
600     m_debugger.SetInputFileHandle(commands_file, true);
601 
602     // Set the debugger into Sync mode when running the command file. Otherwise
603     // command files that run the target won't run in a sensible way.
604     bool old_async = m_debugger.GetAsync();
605     m_debugger.SetAsync(false);
606 
607     SBCommandInterpreterRunOptions options;
608     options.SetAutoHandleEvents(true);
609     options.SetSpawnThread(false);
610     options.SetStopOnError(true);
611     options.SetStopOnCrash(m_option_data.m_batch);
612     options.SetEchoCommands(!m_option_data.m_source_quietly);
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     // When running in batch mode and stopped because of an error, exit with a
623     // non-zero exit status.
624     if (m_option_data.m_batch &&
625         results.GetResult() == lldb::eCommandInterpreterResultCommandError)
626       return 1;
627 
628     if (m_option_data.m_batch &&
629         results.GetResult() == lldb::eCommandInterpreterResultInferiorCrash &&
630         !m_option_data.m_after_crash_commands.empty()) {
631       SBStream crash_commands_stream;
632       WriteCommandsForSourcing(eCommandPlacementAfterCrash,
633                                crash_commands_stream);
634       const char *crash_commands_data = crash_commands_stream.GetData();
635       const size_t crash_commands_size = crash_commands_stream.GetSize();
636       commands_file =
637           PrepareCommandsForSourcing(crash_commands_data, crash_commands_size);
638       if (commands_file != nullptr) {
639         m_debugger.SetInputFileHandle(commands_file, true);
640         SBCommandInterpreterRunResult local_results =
641             m_debugger.RunCommandInterpreter(options);
642         if (local_results.GetResult() ==
643             lldb::eCommandInterpreterResultQuitRequested)
644           go_interactive = false;
645 
646         // When running in batch mode and an error occurred while sourcing
647         // the crash commands, exit with a non-zero exit status.
648         if (m_option_data.m_batch &&
649             local_results.GetResult() ==
650                 lldb::eCommandInterpreterResultCommandError)
651           return 1;
652       }
653     }
654     m_debugger.SetAsync(old_async);
655   }
656 
657   // Now set the input file handle to STDIN and run the command interpreter
658   // again in interactive mode or repl mode and let the debugger take ownership
659   // of stdin.
660   if (go_interactive) {
661     m_debugger.SetInputFileHandle(stdin, true);
662 
663     if (m_option_data.m_repl) {
664       const char *repl_options = nullptr;
665       if (!m_option_data.m_repl_options.empty())
666         repl_options = m_option_data.m_repl_options.c_str();
667       SBError error(
668           m_debugger.RunREPL(m_option_data.m_repl_lang, repl_options));
669       if (error.Fail()) {
670         const char *error_cstr = error.GetCString();
671         if ((error_cstr != nullptr) && (error_cstr[0] != 0))
672           WithColor::error() << error_cstr << '\n';
673         else
674           WithColor::error() << error.GetError() << '\n';
675       }
676     } else {
677       m_debugger.RunCommandInterpreter(handle_events, spawn_thread);
678     }
679   }
680 
681   reset_stdin_termios();
682   fclose(stdin);
683 
684   return sb_interpreter.GetQuitStatus();
685 }
686 
687 void Driver::ResizeWindow(unsigned short col) {
688   GetDebugger().SetTerminalWidth(col);
689 }
690 
691 void sigwinch_handler(int signo) {
692   struct winsize window_size;
693   if ((isatty(STDIN_FILENO) != 0) &&
694       ::ioctl(STDIN_FILENO, TIOCGWINSZ, &window_size) == 0) {
695     if ((window_size.ws_col > 0) && g_driver != nullptr) {
696       g_driver->ResizeWindow(window_size.ws_col);
697     }
698   }
699 }
700 
701 void sigint_handler(int signo) {
702 #ifdef _WIN32 // Restore handler as it is not persistent on Windows
703   signal(SIGINT, sigint_handler);
704 #endif
705   static std::atomic_flag g_interrupt_sent = ATOMIC_FLAG_INIT;
706   if (g_driver != nullptr) {
707     if (!g_interrupt_sent.test_and_set()) {
708       g_driver->GetDebugger().DispatchInputInterrupt();
709       g_interrupt_sent.clear();
710       return;
711     }
712   }
713 
714   _exit(signo);
715 }
716 
717 void sigtstp_handler(int signo) {
718   if (g_driver != nullptr)
719     g_driver->GetDebugger().SaveInputTerminalState();
720 
721   signal(signo, SIG_DFL);
722   kill(getpid(), signo);
723   signal(signo, sigtstp_handler);
724 }
725 
726 void sigcont_handler(int signo) {
727   if (g_driver != nullptr)
728     g_driver->GetDebugger().RestoreInputTerminalState();
729 
730   signal(signo, SIG_DFL);
731   kill(getpid(), signo);
732   signal(signo, sigcont_handler);
733 }
734 
735 void reproducer_handler(void *finalize_cmd) {
736   if (SBReproducer::Generate()) {
737     int result = std::system(static_cast<const char *>(finalize_cmd));
738     (void)result;
739     fflush(stdout);
740   }
741 }
742 
743 static void printHelp(LLDBOptTable &table, llvm::StringRef tool_name) {
744   std::string usage_str = tool_name.str() + " [options]";
745   table.printHelp(llvm::outs(), usage_str.c_str(), "LLDB", false);
746 
747   std::string examples = R"___(
748 EXAMPLES:
749   The debugger can be started in several modes.
750 
751   Passing an executable as a positional argument prepares lldb to debug the
752   given executable. To disambiguate between arguments passed to lldb and
753   arguments passed to the debugged executable, arguments starting with a - must
754   be passed after --.
755 
756     lldb --arch x86_64 /path/to/program program argument -- --arch armv7
757 
758   For convenience, passing the executable after -- is also supported.
759 
760     lldb --arch x86_64 -- /path/to/program program argument --arch armv7
761 
762   Passing one of the attach options causes lldb to immediately attach to the
763   given process.
764 
765     lldb -p <pid>
766     lldb -n <process-name>
767 
768   Passing --repl starts lldb in REPL mode.
769 
770     lldb -r
771 
772   Passing --core causes lldb to debug the core file.
773 
774     lldb -c /path/to/core
775 
776   Command options can be combined with these modes and cause lldb to run the
777   specified commands before or after events, like loading the file or crashing,
778   in the order provided on the command line.
779 
780     lldb -O 'settings set stop-disassembly-count 20' -o 'run' -o 'bt'
781     lldb -S /source/before/file -s /source/after/file
782     lldb -K /source/before/crash -k /source/after/crash
783 
784   Note: In REPL mode no file is loaded, so commands specified to run after
785   loading the file (via -o or -s) will be ignored.)___";
786   llvm::outs() << examples << '\n';
787 }
788 
789 static llvm::Optional<int> InitializeReproducer(llvm::StringRef argv0,
790                                                 opt::InputArgList &input_args) {
791   if (auto *finalize_path = input_args.getLastArg(OPT_reproducer_finalize)) {
792     if (const char *error = SBReproducer::Finalize(finalize_path->getValue())) {
793       WithColor::error() << "reproducer finalization failed: " << error << '\n';
794       return 1;
795     }
796 
797     llvm::outs() << "********************\n";
798     llvm::outs() << "Crash reproducer for ";
799     llvm::outs() << lldb::SBDebugger::GetVersionString() << '\n';
800     llvm::outs() << '\n';
801     llvm::outs() << "Reproducer written to '" << SBReproducer::GetPath()
802                  << "'\n";
803     llvm::outs() << '\n';
804     llvm::outs() << "Before attaching the reproducer to a bug report:\n";
805     llvm::outs() << " - Look at the directory to ensure you're willing to "
806                     "share its content.\n";
807     llvm::outs()
808         << " - Make sure the reproducer works by replaying the reproducer.\n";
809     llvm::outs() << '\n';
810     llvm::outs() << "Replay the reproducer with the following command:\n";
811     llvm::outs() << argv0 << " -replay " << finalize_path->getValue() << "\n";
812     llvm::outs() << "********************\n";
813     return 0;
814   }
815 
816   if (auto *replay_path = input_args.getLastArg(OPT_replay)) {
817     SBReplayOptions replay_options;
818     replay_options.SetCheckVersion(!input_args.hasArg(OPT_no_version_check));
819     replay_options.SetVerify(!input_args.hasArg(OPT_no_verification));
820     if (const char *error =
821             SBReproducer::Replay(replay_path->getValue(), replay_options)) {
822       WithColor::error() << "reproducer replay failed: " << error << '\n';
823       return 1;
824     }
825     return 0;
826   }
827 
828   bool capture = input_args.hasArg(OPT_capture);
829   bool generate_on_exit = input_args.hasArg(OPT_generate_on_exit);
830   auto *capture_path = input_args.getLastArg(OPT_capture_path);
831 
832   if (generate_on_exit && !capture) {
833     WithColor::warning()
834         << "-reproducer-generate-on-exit specified without -capture\n";
835   }
836 
837   if (capture || capture_path) {
838     if (capture_path) {
839       if (!capture)
840         WithColor::warning() << "-capture-path specified without -capture\n";
841       if (const char *error = SBReproducer::Capture(capture_path->getValue())) {
842         WithColor::error() << "reproducer capture failed: " << error << '\n';
843         return 1;
844       }
845     } else {
846       const char *error = SBReproducer::Capture();
847       if (error) {
848         WithColor::error() << "reproducer capture failed: " << error << '\n';
849         return 1;
850       }
851     }
852     if (generate_on_exit)
853       SBReproducer::SetAutoGenerate(true);
854 
855     // Register the reproducer signal handler.
856     if (!input_args.hasArg(OPT_no_generate_on_signal)) {
857       if (const char *reproducer_path = SBReproducer::GetPath()) {
858         static std::string *finalize_cmd = new std::string(argv0);
859         finalize_cmd->append(" --reproducer-finalize '");
860         finalize_cmd->append(reproducer_path);
861         finalize_cmd->append("'");
862         llvm::sys::AddSignalHandler(reproducer_handler,
863                                     const_cast<char *>(finalize_cmd->c_str()));
864       }
865     }
866   }
867 
868   return llvm::None;
869 }
870 
871 int main(int argc, char const *argv[]) {
872   // Editline uses for example iswprint which is dependent on LC_CTYPE.
873   std::setlocale(LC_ALL, "");
874   std::setlocale(LC_CTYPE, "");
875 
876   // Setup LLVM signal handlers and make sure we call llvm_shutdown() on
877   // destruction.
878   llvm::InitLLVM IL(argc, argv, /*InstallPipeSignalExitHandler=*/false);
879 
880   // Parse arguments.
881   LLDBOptTable T;
882   unsigned MissingArgIndex;
883   unsigned MissingArgCount;
884   ArrayRef<const char *> arg_arr = makeArrayRef(argv + 1, argc - 1);
885   opt::InputArgList input_args =
886       T.ParseArgs(arg_arr, MissingArgIndex, MissingArgCount);
887   llvm::StringRef argv0 = llvm::sys::path::filename(argv[0]);
888 
889   if (input_args.hasArg(OPT_help)) {
890     printHelp(T, argv0);
891     return 0;
892   }
893 
894   // Check for missing argument error.
895   if (MissingArgCount) {
896     WithColor::error() << "argument to '"
897                        << input_args.getArgString(MissingArgIndex)
898                        << "' is missing\n";
899   }
900   // Error out on unknown options.
901   if (input_args.hasArg(OPT_UNKNOWN)) {
902     for (auto *arg : input_args.filtered(OPT_UNKNOWN)) {
903       WithColor::error() << "unknown option: " << arg->getSpelling() << '\n';
904     }
905   }
906   if (MissingArgCount || input_args.hasArg(OPT_UNKNOWN)) {
907     llvm::errs() << "Use '" << argv0
908                  << " --help' for a complete list of options.\n";
909     return 1;
910   }
911 
912   if (auto exit_code = InitializeReproducer(argv[0], input_args)) {
913     return *exit_code;
914   }
915 
916   SBError error = SBDebugger::InitializeWithErrorHandling();
917   if (error.Fail()) {
918     WithColor::error() << "initialization failed: " << error.GetCString()
919                        << '\n';
920     return 1;
921   }
922   SBHostOS::ThreadCreated("<lldb.driver.main-thread>");
923 
924   signal(SIGINT, sigint_handler);
925 #if !defined(_MSC_VER)
926   signal(SIGPIPE, SIG_IGN);
927   signal(SIGWINCH, sigwinch_handler);
928   signal(SIGTSTP, sigtstp_handler);
929   signal(SIGCONT, sigcont_handler);
930 #endif
931 
932   int exit_code = 0;
933   // Create a scope for driver so that the driver object will destroy itself
934   // before SBDebugger::Terminate() is called.
935   {
936     Driver driver;
937 
938     bool exiting = false;
939     SBError error(driver.ProcessArgs(input_args, exiting));
940     if (error.Fail()) {
941       exit_code = 1;
942       if (const char *error_cstr = error.GetCString())
943         WithColor::error() << error_cstr << '\n';
944     } else if (!exiting) {
945       exit_code = driver.MainLoop();
946     }
947   }
948 
949   SBDebugger::Terminate();
950   return exit_code;
951 }
952