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