1 //===-- Driver.cpp ----------------------------------------------*- C++ -*-===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 #include "Driver.h"
11
12 #include "lldb/API/SBCommandInterpreter.h"
13 #include "lldb/API/SBCommandReturnObject.h"
14 #include "lldb/API/SBDebugger.h"
15 #include "lldb/API/SBHostOS.h"
16 #include "lldb/API/SBLanguageRuntime.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:
LLDBOptTable()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.
reset_stdin_termios()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
Driver()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
~Driver()113 Driver::~Driver() { g_driver = nullptr; }
114
AddLocalLLDBInit()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
AddInitialCommand(std::string command,CommandPlacement placement,bool is_file,SBError & error)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
GetFilename() const165 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
GetCrashLogFilename() const171 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
GetScriptLanguage() const177 lldb::ScriptLanguage Driver::GetScriptLanguage() const {
178 return m_option_data.m_script_lang;
179 }
180
WriteCommandsForSourcing(CommandPlacement placement,SBStream & strm)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
GetDebugMode() const238 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.
ProcessArgs(const opt::InputArgList & args,bool & exiting)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
PrepareCommandsForSourcing(const char * commands_data,size_t commands_size,int fds[2])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
CleanupAfterCommandSourcing(int fds[2])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
EscapeString(std::string arg)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
MainLoop()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
ResizeWindow(unsigned short col)768 void Driver::ResizeWindow(unsigned short col) {
769 GetDebugger().SetTerminalWidth(col);
770 }
771
sigwinch_handler(int signo)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
sigint_handler(int signo)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
sigtstp_handler(int signo)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
sigcont_handler(int signo)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
printHelp(LLDBOptTable & table,llvm::StringRef tool_name)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
wmain(int argc,wchar_t const * wargv[])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 SBInitializerOptions options;
893
894 if (auto *arg = input_args.getLastArg(OPT_capture)) {
895 auto arg_value = arg->getValue();
896 options.SetReproducerPath(arg_value);
897 options.SetCaptureReproducer(true);
898 }
899
900 if (auto *arg = input_args.getLastArg(OPT_replay)) {
901 auto arg_value = arg->getValue();
902 options.SetReplayReproducer(true);
903 options.SetReproducerPath(arg_value);
904 }
905
906 SBError error = SBDebugger::Initialize(options);
907 if (error.Fail()) {
908 WithColor::error() << "initialization failed: " << error.GetCString()
909 << '\n';
910 return 1;
911 }
912
913 SBHostOS::ThreadCreated("<lldb.driver.main-thread>");
914
915 signal(SIGINT, sigint_handler);
916 #if !defined(_MSC_VER)
917 signal(SIGPIPE, SIG_IGN);
918 signal(SIGWINCH, sigwinch_handler);
919 signal(SIGTSTP, sigtstp_handler);
920 signal(SIGCONT, sigcont_handler);
921 #endif
922
923 int exit_code = 0;
924 // Create a scope for driver so that the driver object will destroy itself
925 // before SBDebugger::Terminate() is called.
926 {
927 Driver driver;
928
929 bool exiting = false;
930 SBError error(driver.ProcessArgs(input_args, exiting));
931 if (error.Fail()) {
932 exit_code = 1;
933 if (const char *error_cstr = error.GetCString())
934 WithColor::error() << error_cstr << '\n';
935 } else if (!exiting) {
936 exit_code = driver.MainLoop();
937 }
938 }
939
940 SBDebugger::Terminate();
941 return exit_code;
942 }
943