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