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