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 FILE *commands_file = 596 PrepareCommandsForSourcing(commands_data, commands_size); 597 598 if (commands_file == nullptr) { 599 // We should have already printed an error in PrepareCommandsForSourcing. 600 exit(1); 601 } 602 603 m_debugger.SetInputFileHandle(commands_file, true); 604 605 // Set the debugger into Sync mode when running the command file. 606 // Otherwise command files 607 // that run the target won't run in a sensible way. 608 bool old_async = m_debugger.GetAsync(); 609 m_debugger.SetAsync(false); 610 int num_errors = 0; 611 612 SBCommandInterpreterRunOptions options; 613 options.SetStopOnError(true); 614 if (m_option_data.m_batch) 615 options.SetStopOnCrash(true); 616 617 m_debugger.RunCommandInterpreter(handle_events, spawn_thread, options, 618 num_errors, quit_requested, 619 stopped_for_crash); 620 621 if (m_option_data.m_batch && stopped_for_crash && 622 !m_option_data.m_after_crash_commands.empty()) { 623 SBStream crash_commands_stream; 624 WriteCommandsForSourcing(eCommandPlacementAfterCrash, 625 crash_commands_stream); 626 const char *crash_commands_data = crash_commands_stream.GetData(); 627 const size_t crash_commands_size = crash_commands_stream.GetSize(); 628 commands_file = 629 PrepareCommandsForSourcing(crash_commands_data, crash_commands_size); 630 if (commands_file != nullptr) { 631 bool local_quit_requested; 632 bool local_stopped_for_crash; 633 m_debugger.SetInputFileHandle(commands_file, true); 634 635 m_debugger.RunCommandInterpreter(handle_events, spawn_thread, options, 636 num_errors, local_quit_requested, 637 local_stopped_for_crash); 638 if (local_quit_requested) 639 quit_requested = true; 640 } 641 } 642 m_debugger.SetAsync(old_async); 643 } 644 645 // Now set the input file handle to STDIN and run the command 646 // interpreter again in interactive mode or repl mode and let the debugger 647 // take ownership of stdin 648 649 bool go_interactive = true; 650 if (quit_requested) 651 go_interactive = false; 652 else if (m_option_data.m_batch && !stopped_for_crash) 653 go_interactive = false; 654 655 if (go_interactive) { 656 m_debugger.SetInputFileHandle(stdin, true); 657 658 if (m_option_data.m_repl) { 659 const char *repl_options = nullptr; 660 if (!m_option_data.m_repl_options.empty()) 661 repl_options = m_option_data.m_repl_options.c_str(); 662 SBError error( 663 m_debugger.RunREPL(m_option_data.m_repl_lang, repl_options)); 664 if (error.Fail()) { 665 const char *error_cstr = error.GetCString(); 666 if ((error_cstr != nullptr) && (error_cstr[0] != 0)) 667 WithColor::error() << error_cstr << '\n'; 668 else 669 WithColor::error() << error.GetError() << '\n'; 670 } 671 } else { 672 m_debugger.RunCommandInterpreter(handle_events, spawn_thread); 673 } 674 } 675 676 reset_stdin_termios(); 677 fclose(stdin); 678 679 int exit_code = sb_interpreter.GetQuitStatus(); 680 SBDebugger::Destroy(m_debugger); 681 return exit_code; 682 } 683 684 void Driver::ResizeWindow(unsigned short col) { 685 GetDebugger().SetTerminalWidth(col); 686 } 687 688 void sigwinch_handler(int signo) { 689 struct winsize window_size; 690 if ((isatty(STDIN_FILENO) != 0) && 691 ::ioctl(STDIN_FILENO, TIOCGWINSZ, &window_size) == 0) { 692 if ((window_size.ws_col > 0) && g_driver != nullptr) { 693 g_driver->ResizeWindow(window_size.ws_col); 694 } 695 } 696 } 697 698 void sigint_handler(int signo) { 699 #ifdef _WIN32 // Restore handler as it is not persistent on Windows 700 signal(SIGINT, sigint_handler); 701 #endif 702 static std::atomic_flag g_interrupt_sent = ATOMIC_FLAG_INIT; 703 if (g_driver != nullptr) { 704 if (!g_interrupt_sent.test_and_set()) { 705 g_driver->GetDebugger().DispatchInputInterrupt(); 706 g_interrupt_sent.clear(); 707 return; 708 } 709 } 710 711 _exit(signo); 712 } 713 714 void sigtstp_handler(int signo) { 715 if (g_driver != nullptr) 716 g_driver->GetDebugger().SaveInputTerminalState(); 717 718 signal(signo, SIG_DFL); 719 kill(getpid(), signo); 720 signal(signo, sigtstp_handler); 721 } 722 723 void sigcont_handler(int signo) { 724 if (g_driver != nullptr) 725 g_driver->GetDebugger().RestoreInputTerminalState(); 726 727 signal(signo, SIG_DFL); 728 kill(getpid(), signo); 729 signal(signo, sigcont_handler); 730 } 731 732 void reproducer_handler(void *argv0) { 733 if (SBReproducer::Generate()) { 734 auto exe = static_cast<const char *>(argv0); 735 llvm::outs() << "********************\n"; 736 llvm::outs() << "Crash reproducer for "; 737 llvm::outs() << lldb::SBDebugger::GetVersionString() << '\n'; 738 llvm::outs() << '\n'; 739 llvm::outs() << "Reproducer written to '" << SBReproducer::GetPath() 740 << "'\n"; 741 llvm::outs() << '\n'; 742 llvm::outs() << "Before attaching the reproducer to a bug report:\n"; 743 llvm::outs() << " - Look at the directory to ensure you're willing to " 744 "share its content.\n"; 745 llvm::outs() 746 << " - Make sure the reproducer works by replaying the reproducer.\n"; 747 llvm::outs() << '\n'; 748 llvm::outs() << "Replay the reproducer with the following command:\n"; 749 llvm::outs() << exe << " -replay " << SBReproducer::GetPath() << "\n"; 750 llvm::outs() << "********************\n"; 751 } 752 } 753 754 static void printHelp(LLDBOptTable &table, llvm::StringRef tool_name) { 755 std::string usage_str = tool_name.str() + " [options]"; 756 table.PrintHelp(llvm::outs(), usage_str.c_str(), "LLDB", false); 757 758 std::string examples = R"___( 759 EXAMPLES: 760 The debugger can be started in several modes. 761 762 Passing an executable as a positional argument prepares lldb to debug the 763 given executable. Arguments passed after -- are considered arguments to the 764 debugged executable. 765 766 lldb --arch x86_64 /path/to/program -- --arch arvm7 767 768 Passing one of the attach options causes lldb to immediately attach to the 769 given process. 770 771 lldb -p <pid> 772 lldb -n <process-name> 773 774 Passing --repl starts lldb in REPL mode. 775 776 lldb -r 777 778 Passing --core causes lldb to debug the core file. 779 780 lldb -c /path/to/core 781 782 Command options can be combined with these modes and cause lldb to run the 783 specified commands before or after events, like loading the file or crashing, 784 in the order provided on the command line. 785 786 lldb -O 'settings set stop-disassembly-count 20' -o 'run' -o 'bt' 787 lldb -S /source/before/file -s /source/after/file 788 lldb -K /source/before/crash -k /source/after/crash 789 790 Note: In REPL mode no file is loaded, so commands specified to run after 791 loading the file (via -o or -s) will be ignored.)___"; 792 llvm::outs() << examples << '\n'; 793 } 794 795 llvm::Optional<int> InitializeReproducer(opt::InputArgList &input_args) { 796 if (auto *replay_path = input_args.getLastArg(OPT_replay)) { 797 const bool skip_version_check = input_args.hasArg(OPT_skip_version_check); 798 if (const char *error = 799 SBReproducer::Replay(replay_path->getValue(), skip_version_check)) { 800 WithColor::error() << "reproducer replay failed: " << error << '\n'; 801 return 1; 802 } 803 return 0; 804 } 805 806 bool capture = input_args.hasArg(OPT_capture); 807 bool auto_generate = input_args.hasArg(OPT_auto_generate); 808 auto *capture_path = input_args.getLastArg(OPT_capture_path); 809 810 if (auto_generate && !capture) { 811 WithColor::warning() 812 << "-reproducer-auto-generate specified without -capture\n"; 813 } 814 815 if (capture || capture_path) { 816 if (capture_path) { 817 if (!capture) 818 WithColor::warning() << "-capture-path specified without -capture\n"; 819 if (const char *error = SBReproducer::Capture(capture_path->getValue())) { 820 WithColor::error() << "reproducer capture failed: " << error << '\n'; 821 return 1; 822 } 823 } else { 824 const char *error = SBReproducer::Capture(); 825 if (error) { 826 WithColor::error() << "reproducer capture failed: " << error << '\n'; 827 return 1; 828 } 829 } 830 if (auto_generate) 831 SBReproducer::SetAutoGenerate(true); 832 } 833 834 return llvm::None; 835 } 836 837 int main(int argc, char const *argv[]) { 838 // Setup LLVM signal handlers and make sure we call llvm_shutdown() on 839 // destruction. 840 llvm::InitLLVM IL(argc, argv, /*InstallPipeSignalExitHandler=*/false); 841 842 // Parse arguments. 843 LLDBOptTable T; 844 unsigned MAI; 845 unsigned MAC; 846 ArrayRef<const char *> arg_arr = makeArrayRef(argv + 1, argc - 1); 847 opt::InputArgList input_args = T.ParseArgs(arg_arr, MAI, MAC); 848 849 if (input_args.hasArg(OPT_help)) { 850 printHelp(T, llvm::sys::path::filename(argv[0])); 851 return 0; 852 } 853 854 for (auto *arg : input_args.filtered(OPT_UNKNOWN)) { 855 WithColor::warning() << "ignoring unknown option: " << arg->getSpelling() 856 << '\n'; 857 } 858 859 if (auto exit_code = InitializeReproducer(input_args)) { 860 return *exit_code; 861 } 862 863 // Register the reproducer signal handler. 864 llvm::sys::AddSignalHandler(reproducer_handler, const_cast<char *>(argv[0])); 865 866 SBError error = SBDebugger::InitializeWithErrorHandling(); 867 if (error.Fail()) { 868 WithColor::error() << "initialization failed: " << error.GetCString() 869 << '\n'; 870 return 1; 871 } 872 SBHostOS::ThreadCreated("<lldb.driver.main-thread>"); 873 874 signal(SIGINT, sigint_handler); 875 #if !defined(_MSC_VER) 876 signal(SIGPIPE, SIG_IGN); 877 signal(SIGWINCH, sigwinch_handler); 878 signal(SIGTSTP, sigtstp_handler); 879 signal(SIGCONT, sigcont_handler); 880 #endif 881 882 int exit_code = 0; 883 // Create a scope for driver so that the driver object will destroy itself 884 // before SBDebugger::Terminate() is called. 885 { 886 Driver driver; 887 888 bool exiting = false; 889 SBError error(driver.ProcessArgs(input_args, exiting)); 890 if (error.Fail()) { 891 exit_code = 1; 892 if (const char *error_cstr = error.GetCString()) 893 WithColor::error() << error_cstr << '\n'; 894 } else if (!exiting) { 895 exit_code = driver.MainLoop(); 896 } 897 } 898 899 SBDebugger::Terminate(); 900 return exit_code; 901 } 902