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