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/SBHostOS.h"
15 #include "lldb/API/SBLanguageRuntime.h"
16 #include "lldb/API/SBReproducer.h"
17 #include "lldb/API/SBStream.h"
18 #include "lldb/API/SBStringList.h"
19 
20 #include "llvm/ADT/StringRef.h"
21 #include "llvm/Support/ConvertUTF.h"
22 #include "llvm/Support/Format.h"
23 #include "llvm/Support/Path.h"
24 #include "llvm/Support/PrettyStackTrace.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   }
233 
234   if (auto *arg = args.getLastArg(OPT_file)) {
235     auto arg_value = arg->getValue();
236     SBFileSpec file(arg_value);
237     if (file.Exists()) {
238       m_option_data.m_args.emplace_back(arg_value);
239     } else if (file.ResolveExecutableLocation()) {
240       char path[PATH_MAX];
241       file.GetPath(path, sizeof(path));
242       m_option_data.m_args.emplace_back(path);
243     } else {
244       error.SetErrorStringWithFormat(
245           "file specified in --file (-f) option doesn't exist: '%s'",
246           arg_value);
247       return error;
248     }
249   }
250 
251   if (auto *arg = args.getLastArg(OPT_arch)) {
252     auto arg_value = arg->getValue();
253     if (!lldb::SBDebugger::SetDefaultArchitecture(arg_value)) {
254       error.SetErrorStringWithFormat(
255           "invalid architecture in the -a or --arch option: '%s'", arg_value);
256       return error;
257     }
258   }
259 
260   if (auto *arg = args.getLastArg(OPT_script_language)) {
261     auto arg_value = arg->getValue();
262     m_debugger.SetScriptLanguage(m_debugger.GetScriptingLanguage(arg_value));
263   }
264 
265   if (args.hasArg(OPT_no_use_colors)) {
266     m_option_data.m_debug_mode = true;
267   }
268 
269   if (args.hasArg(OPT_no_use_colors)) {
270     m_debugger.SetUseColor(false);
271   }
272 
273   if (args.hasArg(OPT_source_quietly)) {
274     m_option_data.m_source_quietly = true;
275   }
276 
277   if (auto *arg = args.getLastArg(OPT_attach_name)) {
278     auto arg_value = arg->getValue();
279     m_option_data.m_process_name = arg_value;
280   }
281 
282   if (args.hasArg(OPT_wait_for)) {
283     m_option_data.m_wait_for = true;
284   }
285 
286   if (auto *arg = args.getLastArg(OPT_attach_pid)) {
287     auto arg_value = arg->getValue();
288     char *remainder;
289     m_option_data.m_process_pid = strtol(arg_value, &remainder, 0);
290     if (remainder == arg_value || *remainder != '\0') {
291       error.SetErrorStringWithFormat(
292           "Could not convert process PID: \"%s\" into a pid.", arg_value);
293       return error;
294     }
295   }
296 
297   if (auto *arg = args.getLastArg(OPT_repl_language)) {
298     auto arg_value = arg->getValue();
299     m_option_data.m_repl_lang =
300         SBLanguageRuntime::GetLanguageTypeFromString(arg_value);
301     if (m_option_data.m_repl_lang == eLanguageTypeUnknown) {
302       error.SetErrorStringWithFormat("Unrecognized language name: \"%s\"",
303                                      arg_value);
304       return error;
305     }
306   }
307 
308   if (args.hasArg(OPT_repl)) {
309     m_option_data.m_repl = true;
310   }
311 
312   if (auto *arg = args.getLastArg(OPT_repl_)) {
313     m_option_data.m_repl = true;
314     if (auto arg_value = arg->getValue())
315       m_option_data.m_repl_options = arg_value;
316   }
317 
318   // We need to process the options below together as their relative order
319   // matters.
320   for (auto *arg : args.filtered(OPT_source_on_crash, OPT_one_line_on_crash,
321                                  OPT_source, OPT_source_before_file,
322                                  OPT_one_line, OPT_one_line_before_file)) {
323     auto arg_value = arg->getValue();
324     if (arg->getOption().matches(OPT_source_on_crash)) {
325       m_option_data.AddInitialCommand(arg_value, eCommandPlacementAfterCrash,
326                                       true, error);
327       if (error.Fail())
328         return error;
329     }
330 
331     if (arg->getOption().matches(OPT_one_line_on_crash)) {
332       m_option_data.AddInitialCommand(arg_value, eCommandPlacementAfterCrash,
333                                       false, error);
334       if (error.Fail())
335         return error;
336     }
337 
338     if (arg->getOption().matches(OPT_source)) {
339       m_option_data.AddInitialCommand(arg_value, eCommandPlacementAfterFile,
340                                       true, error);
341       if (error.Fail())
342         return error;
343     }
344 
345     if (arg->getOption().matches(OPT_source_before_file)) {
346       m_option_data.AddInitialCommand(arg_value, eCommandPlacementBeforeFile,
347                                       true, error);
348       if (error.Fail())
349         return error;
350     }
351 
352     if (arg->getOption().matches(OPT_one_line)) {
353       m_option_data.AddInitialCommand(arg_value, eCommandPlacementAfterFile,
354                                       false, error);
355       if (error.Fail())
356         return error;
357     }
358 
359     if (arg->getOption().matches(OPT_one_line_before_file)) {
360       m_option_data.AddInitialCommand(arg_value, eCommandPlacementBeforeFile,
361                                       false, error);
362       if (error.Fail())
363         return error;
364     }
365   }
366 
367   if (m_option_data.m_process_name.empty() &&
368       m_option_data.m_process_pid == LLDB_INVALID_PROCESS_ID) {
369 
370     // If the option data args array is empty that means the file was not
371     // specified with -f and we need to get it from the input args.
372     if (m_option_data.m_args.empty()) {
373       if (auto *arg = args.getLastArgNoClaim(OPT_INPUT)) {
374         m_option_data.m_args.push_back(arg->getAsString((args)));
375       }
376     }
377 
378     // Any argument following -- is an argument for the inferior.
379     if (auto *arg = args.getLastArgNoClaim(OPT_REM)) {
380       for (auto value : arg->getValues())
381         m_option_data.m_args.emplace_back(value);
382     }
383   } else if (args.getLastArgNoClaim() != nullptr) {
384     WithColor::warning() << "program arguments are ignored when attaching.\n";
385   }
386 
387   if (m_option_data.m_print_version) {
388     llvm::outs() << lldb::SBDebugger::GetVersionString() << '\n';
389     exiting = true;
390     return error;
391   }
392 
393   if (m_option_data.m_print_python_path) {
394     SBFileSpec python_file_spec = SBHostOS::GetLLDBPythonPath();
395     if (python_file_spec.IsValid()) {
396       char python_path[PATH_MAX];
397       size_t num_chars = python_file_spec.GetPath(python_path, PATH_MAX);
398       if (num_chars < PATH_MAX) {
399         llvm::outs() << python_path << '\n';
400       } else
401         llvm::outs() << "<PATH TOO LONG>\n";
402     } else
403       llvm::outs() << "<COULD NOT FIND PATH>\n";
404     exiting = true;
405     return error;
406   }
407 
408   return error;
409 }
410 
411 static inline int OpenPipe(int fds[2], std::size_t size) {
412 #ifdef _WIN32
413   return _pipe(fds, size, O_BINARY);
414 #else
415   (void)size;
416   return pipe(fds);
417 #endif
418 }
419 
420 static ::FILE *PrepareCommandsForSourcing(const char *commands_data,
421                                           size_t commands_size) {
422   enum PIPES { READ, WRITE }; // Indexes for the read and write fds
423   int fds[2] = {-1, -1};
424 
425   if (OpenPipe(fds, commands_size) != 0) {
426     WithColor::error()
427         << "can't create pipe file descriptors for LLDB commands\n";
428     return nullptr;
429   }
430 
431   ssize_t nrwr = write(fds[WRITE], commands_data, commands_size);
432   if (size_t(nrwr) != commands_size) {
433     WithColor::error()
434         << format(
435                "write(%i, %p, %" PRIu64
436                ") failed (errno = %i) when trying to open LLDB commands pipe",
437                fds[WRITE], static_cast<const void *>(commands_data),
438                static_cast<uint64_t>(commands_size), errno)
439         << '\n';
440     llvm::sys::Process::SafelyCloseFileDescriptor(fds[READ]);
441     llvm::sys::Process::SafelyCloseFileDescriptor(fds[WRITE]);
442     return nullptr;
443   }
444 
445   // Close the write end of the pipe, so that the command interpreter will exit
446   // when it consumes all the data.
447   llvm::sys::Process::SafelyCloseFileDescriptor(fds[WRITE]);
448 
449   // Open the read file descriptor as a FILE * that we can return as an input
450   // handle.
451   ::FILE *commands_file = fdopen(fds[READ], "rb");
452   if (commands_file == nullptr) {
453     WithColor::error() << format("fdopen(%i, \"rb\") failed (errno = %i) "
454                                  "when trying to open LLDB commands pipe",
455                                  fds[READ], errno)
456                        << '\n';
457     llvm::sys::Process::SafelyCloseFileDescriptor(fds[READ]);
458     return nullptr;
459   }
460 
461   // 'commands_file' now owns the read descriptor.
462   return commands_file;
463 }
464 
465 std::string EscapeString(std::string arg) {
466   std::string::size_type pos = 0;
467   while ((pos = arg.find_first_of("\"\\", pos)) != std::string::npos) {
468     arg.insert(pos, 1, '\\');
469     pos += 2;
470   }
471   return '"' + arg + '"';
472 }
473 
474 int Driver::MainLoop() {
475   if (::tcgetattr(STDIN_FILENO, &g_old_stdin_termios) == 0) {
476     g_old_stdin_termios_is_valid = true;
477     atexit(reset_stdin_termios);
478   }
479 
480 #ifndef _MSC_VER
481   // Disabling stdin buffering with MSVC's 2015 CRT exposes a bug in fgets
482   // which causes it to miss newlines depending on whether there have been an
483   // odd or even number of characters.  Bug has been reported to MS via Connect.
484   ::setbuf(stdin, nullptr);
485 #endif
486   ::setbuf(stdout, nullptr);
487 
488   m_debugger.SetErrorFileHandle(stderr, false);
489   m_debugger.SetOutputFileHandle(stdout, false);
490   // Don't take ownership of STDIN yet...
491   m_debugger.SetInputFileHandle(stdin, false);
492 
493   m_debugger.SetUseExternalEditor(m_option_data.m_use_external_editor);
494 
495   struct winsize window_size;
496   if ((isatty(STDIN_FILENO) != 0) &&
497       ::ioctl(STDIN_FILENO, TIOCGWINSZ, &window_size) == 0) {
498     if (window_size.ws_col > 0)
499       m_debugger.SetTerminalWidth(window_size.ws_col);
500   }
501 
502   SBCommandInterpreter sb_interpreter = m_debugger.GetCommandInterpreter();
503 
504   // Before we handle any options from the command line, we parse the
505   // .lldbinit file in the user's home directory.
506   SBCommandReturnObject result;
507   sb_interpreter.SourceInitFileInHomeDirectory(result);
508   if (m_option_data.m_debug_mode) {
509     result.PutError(m_debugger.GetErrorFileHandle());
510     result.PutOutput(m_debugger.GetOutputFileHandle());
511   }
512 
513   // Source the local .lldbinit file if it exists and we're allowed to source.
514   // Here we want to always print the return object because it contains the
515   // warning and instructions to load local lldbinit files.
516   sb_interpreter.SourceInitFileInCurrentWorkingDirectory(result);
517   result.PutError(m_debugger.GetErrorFileHandle());
518   result.PutOutput(m_debugger.GetOutputFileHandle());
519 
520   // We allow the user to specify an exit code when calling quit which we will
521   // return when exiting.
522   m_debugger.GetCommandInterpreter().AllowExitCodeOnQuit(true);
523 
524   // Now we handle options we got from the command line
525   SBStream commands_stream;
526 
527   // First source in the commands specified to be run before the file arguments
528   // are processed.
529   WriteCommandsForSourcing(eCommandPlacementBeforeFile, commands_stream);
530 
531   // If we're not in --repl mode, add the commands to process the file
532   // arguments, and the commands specified to run afterwards.
533   if (!m_option_data.m_repl) {
534     const size_t num_args = m_option_data.m_args.size();
535     if (num_args > 0) {
536       char arch_name[64];
537       if (lldb::SBDebugger::GetDefaultArchitecture(arch_name,
538                                                    sizeof(arch_name)))
539         commands_stream.Printf("target create --arch=%s %s", arch_name,
540                                EscapeString(m_option_data.m_args[0]).c_str());
541       else
542         commands_stream.Printf("target create %s",
543                                EscapeString(m_option_data.m_args[0]).c_str());
544 
545       if (!m_option_data.m_core_file.empty()) {
546         commands_stream.Printf(" --core %s",
547                                EscapeString(m_option_data.m_core_file).c_str());
548       }
549       commands_stream.Printf("\n");
550 
551       if (num_args > 1) {
552         commands_stream.Printf("settings set -- target.run-args ");
553         for (size_t arg_idx = 1; arg_idx < num_args; ++arg_idx)
554           commands_stream.Printf(
555               " %s", EscapeString(m_option_data.m_args[arg_idx]).c_str());
556         commands_stream.Printf("\n");
557       }
558     } else if (!m_option_data.m_core_file.empty()) {
559       commands_stream.Printf("target create --core %s\n",
560                              EscapeString(m_option_data.m_core_file).c_str());
561     } else if (!m_option_data.m_process_name.empty()) {
562       commands_stream.Printf(
563           "process attach --name %s",
564           EscapeString(m_option_data.m_process_name).c_str());
565 
566       if (m_option_data.m_wait_for)
567         commands_stream.Printf(" --waitfor");
568 
569       commands_stream.Printf("\n");
570 
571     } else if (LLDB_INVALID_PROCESS_ID != m_option_data.m_process_pid) {
572       commands_stream.Printf("process attach --pid %" PRIu64 "\n",
573                              m_option_data.m_process_pid);
574     }
575 
576     WriteCommandsForSourcing(eCommandPlacementAfterFile, commands_stream);
577   } else if (!m_option_data.m_after_file_commands.empty()) {
578     // We're in repl mode and after-file-load commands were specified.
579     WithColor::warning() << "commands specified to run after file load (via -o "
580                             "or -s) are ignored in REPL mode.\n";
581   }
582 
583   if (m_option_data.m_debug_mode) {
584     result.PutError(m_debugger.GetErrorFileHandle());
585     result.PutOutput(m_debugger.GetOutputFileHandle());
586   }
587 
588   const bool handle_events = true;
589   const bool spawn_thread = false;
590 
591   // Check if we have any data in the commands stream, and if so, save it to a
592   // temp file
593   // so we can then run the command interpreter using the file contents.
594   const char *commands_data = commands_stream.GetData();
595   const size_t commands_size = commands_stream.GetSize();
596 
597   // The command file might have requested that we quit, this variable will
598   // track that.
599   bool quit_requested = false;
600   bool stopped_for_crash = false;
601   if ((commands_data != nullptr) && (commands_size != 0u)) {
602     bool success = true;
603     FILE *commands_file =
604         PrepareCommandsForSourcing(commands_data, commands_size);
605     if (commands_file != nullptr) {
606       m_debugger.SetInputFileHandle(commands_file, true);
607 
608       // Set the debugger into Sync mode when running the command file.
609       // Otherwise command files
610       // that run the target won't run in a sensible way.
611       bool old_async = m_debugger.GetAsync();
612       m_debugger.SetAsync(false);
613       int num_errors = 0;
614 
615       SBCommandInterpreterRunOptions options;
616       options.SetStopOnError(true);
617       if (m_option_data.m_batch)
618         options.SetStopOnCrash(true);
619 
620       m_debugger.RunCommandInterpreter(handle_events, spawn_thread, options,
621                                        num_errors, quit_requested,
622                                        stopped_for_crash);
623 
624       if (m_option_data.m_batch && stopped_for_crash &&
625           !m_option_data.m_after_crash_commands.empty()) {
626         SBStream crash_commands_stream;
627         WriteCommandsForSourcing(eCommandPlacementAfterCrash,
628                                  crash_commands_stream);
629         const char *crash_commands_data = crash_commands_stream.GetData();
630         const size_t crash_commands_size = crash_commands_stream.GetSize();
631         commands_file = PrepareCommandsForSourcing(crash_commands_data,
632                                                    crash_commands_size);
633         if (commands_file != nullptr) {
634           bool local_quit_requested;
635           bool local_stopped_for_crash;
636           m_debugger.SetInputFileHandle(commands_file, true);
637 
638           m_debugger.RunCommandInterpreter(handle_events, spawn_thread, options,
639                                            num_errors, local_quit_requested,
640                                            local_stopped_for_crash);
641           if (local_quit_requested)
642             quit_requested = true;
643         }
644       }
645       m_debugger.SetAsync(old_async);
646     } else
647       success = false;
648 
649     // Something went wrong with command pipe
650     if (!success) {
651       exit(1);
652     }
653   }
654 
655   // Now set the input file handle to STDIN and run the command
656   // interpreter again in interactive mode or repl mode and let the debugger
657   // take ownership of stdin
658 
659   bool go_interactive = true;
660   if (quit_requested)
661     go_interactive = false;
662   else if (m_option_data.m_batch && !stopped_for_crash)
663     go_interactive = false;
664 
665   if (go_interactive) {
666     m_debugger.SetInputFileHandle(stdin, true);
667 
668     if (m_option_data.m_repl) {
669       const char *repl_options = nullptr;
670       if (!m_option_data.m_repl_options.empty())
671         repl_options = m_option_data.m_repl_options.c_str();
672       SBError error(
673           m_debugger.RunREPL(m_option_data.m_repl_lang, repl_options));
674       if (error.Fail()) {
675         const char *error_cstr = error.GetCString();
676         if ((error_cstr != nullptr) && (error_cstr[0] != 0))
677           WithColor::error() << error_cstr << '\n';
678         else
679           WithColor::error() << error.GetError() << '\n';
680       }
681     } else {
682       m_debugger.RunCommandInterpreter(handle_events, spawn_thread);
683     }
684   }
685 
686   reset_stdin_termios();
687   fclose(stdin);
688 
689   int exit_code = sb_interpreter.GetQuitStatus();
690   SBDebugger::Destroy(m_debugger);
691   return exit_code;
692 }
693 
694 void Driver::ResizeWindow(unsigned short col) {
695   GetDebugger().SetTerminalWidth(col);
696 }
697 
698 void sigwinch_handler(int signo) {
699   struct winsize window_size;
700   if ((isatty(STDIN_FILENO) != 0) &&
701       ::ioctl(STDIN_FILENO, TIOCGWINSZ, &window_size) == 0) {
702     if ((window_size.ws_col > 0) && g_driver != nullptr) {
703       g_driver->ResizeWindow(window_size.ws_col);
704     }
705   }
706 }
707 
708 void sigint_handler(int signo) {
709   static std::atomic_flag g_interrupt_sent = ATOMIC_FLAG_INIT;
710   if (g_driver != nullptr) {
711     if (!g_interrupt_sent.test_and_set()) {
712       g_driver->GetDebugger().DispatchInputInterrupt();
713       g_interrupt_sent.clear();
714       return;
715     }
716   }
717 
718   _exit(signo);
719 }
720 
721 void sigtstp_handler(int signo) {
722   if (g_driver != nullptr)
723     g_driver->GetDebugger().SaveInputTerminalState();
724 
725   signal(signo, SIG_DFL);
726   kill(getpid(), signo);
727   signal(signo, sigtstp_handler);
728 }
729 
730 void sigcont_handler(int signo) {
731   if (g_driver != nullptr)
732     g_driver->GetDebugger().RestoreInputTerminalState();
733 
734   signal(signo, SIG_DFL);
735   kill(getpid(), signo);
736   signal(signo, sigcont_handler);
737 }
738 
739 static void printHelp(LLDBOptTable &table, llvm::StringRef tool_name) {
740   std::string usage_str = tool_name.str() + "options";
741   table.PrintHelp(llvm::outs(), usage_str.c_str(), "LLDB", false);
742 
743   std::string examples = R"___(
744 EXAMPLES:
745   The debugger can be started in several modes.
746 
747   Passing an executable as a positional argument prepares lldb to debug the
748   given executable. Arguments passed after -- are considered arguments to the
749   debugged executable.
750 
751     lldb --arch x86_64 /path/to/program -- --arch arvm7
752 
753   Passing one of the attach options causes lldb to immediately attach to the
754   given process.
755 
756     lldb -p <pid>
757     lldb -n <process-name>
758 
759   Passing --repl starts lldb in REPL mode.
760 
761     lldb -r
762 
763   Passing --core causes lldb to debug the core file.
764 
765     lldb -c /path/to/core
766 
767   Command options can be combined with these modes and cause lldb to run the
768   specified commands before or after events, like loading the file or crashing,
769   in the order provided on the command line.
770 
771     lldb -O 'settings set stop-disassembly-count 20' -o 'run' -o 'bt'
772     lldb -S /source/before/file -s /source/after/file
773     lldb -K /source/before/crash -k /source/after/crash
774 
775   Note: In REPL mode no file is loaded, so commands specified to run after
776   loading the file (via -o or -s) will be ignored.
777   )___";
778   llvm::outs() << examples;
779 }
780 
781 llvm::Optional<int> InitializeReproducer(opt::InputArgList &input_args) {
782   if (auto *replay_path = input_args.getLastArg(OPT_replay)) {
783     if (const char *error = SBReproducer::Replay(replay_path->getValue())) {
784       WithColor::error() << "reproducer replay failed: " << error << '\n';
785       return 1;
786     }
787     return 0;
788   }
789 
790   bool capture = input_args.hasArg(OPT_capture);
791   auto *capture_path = input_args.getLastArg(OPT_capture_path);
792 
793   if (capture || capture_path) {
794     if (capture_path) {
795       if (!capture)
796         WithColor::warning() << "-capture-path specified without -capture\n";
797       if (const char *error = SBReproducer::Capture(capture_path->getValue())) {
798         WithColor::error() << "reproducer capture failed: " << error << '\n';
799         return 1;
800       }
801     } else {
802       const char *error = SBReproducer::Capture();
803       if (error) {
804         WithColor::error() << "reproducer capture failed: " << error << '\n';
805         return 1;
806       }
807     }
808   }
809 
810   return llvm::None;
811 }
812 
813 int
814 #ifdef _MSC_VER
815 wmain(int argc, wchar_t const *wargv[])
816 #else
817 main(int argc, char const *argv[])
818 #endif
819 {
820 #ifdef _MSC_VER
821   // Convert wide arguments to UTF-8
822   std::vector<std::string> argvStrings(argc);
823   std::vector<const char *> argvPointers(argc);
824   for (int i = 0; i != argc; ++i) {
825     llvm::convertWideToUTF8(wargv[i], argvStrings[i]);
826     argvPointers[i] = argvStrings[i].c_str();
827   }
828   const char **argv = argvPointers.data();
829 #endif
830 
831   // Print stack trace on crash.
832   llvm::StringRef ToolName = llvm::sys::path::filename(argv[0]);
833   llvm::sys::PrintStackTraceOnErrorSignal(ToolName);
834   llvm::PrettyStackTraceProgram X(argc, argv);
835 
836   // Parse arguments.
837   LLDBOptTable T;
838   unsigned MAI;
839   unsigned MAC;
840   ArrayRef<const char *> arg_arr = makeArrayRef(argv + 1, argc - 1);
841   opt::InputArgList input_args = T.ParseArgs(arg_arr, MAI, MAC);
842 
843   if (input_args.hasArg(OPT_help)) {
844     printHelp(T, ToolName);
845     return 0;
846   }
847 
848   for (auto *arg : input_args.filtered(OPT_UNKNOWN)) {
849     WithColor::warning() << "ignoring unknown option: " << arg->getSpelling()
850                          << '\n';
851   }
852 
853   if (auto exit_code = InitializeReproducer(input_args)) {
854     return *exit_code;
855   }
856 
857   SBError error = SBDebugger::InitializeWithErrorHandling();
858   if (error.Fail()) {
859     WithColor::error() << "initialization failed: " << error.GetCString()
860                        << '\n';
861     return 1;
862   }
863   SBHostOS::ThreadCreated("<lldb.driver.main-thread>");
864 
865   signal(SIGINT, sigint_handler);
866 #if !defined(_MSC_VER)
867   signal(SIGPIPE, SIG_IGN);
868   signal(SIGWINCH, sigwinch_handler);
869   signal(SIGTSTP, sigtstp_handler);
870   signal(SIGCONT, sigcont_handler);
871 #endif
872 
873   int exit_code = 0;
874   // Create a scope for driver so that the driver object will destroy itself
875   // before SBDebugger::Terminate() is called.
876   {
877     Driver driver;
878 
879     bool exiting = false;
880     SBError error(driver.ProcessArgs(input_args, exiting));
881     if (error.Fail()) {
882       exit_code = 1;
883       if (const char *error_cstr = error.GetCString())
884         WithColor::error() << error_cstr << '\n';
885     } else if (!exiting) {
886       exit_code = driver.MainLoop();
887     }
888   }
889 
890   SBDebugger::Terminate();
891   return exit_code;
892 }
893