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