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