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() { 116 SBDebugger::Destroy(m_debugger); 117 g_driver = nullptr; 118 } 119 120 void Driver::OptionData::AddInitialCommand(std::string command, 121 CommandPlacement placement, 122 bool is_file, SBError &error) { 123 std::vector<InitialCmdEntry> *command_set; 124 switch (placement) { 125 case eCommandPlacementBeforeFile: 126 command_set = &(m_initial_commands); 127 break; 128 case eCommandPlacementAfterFile: 129 command_set = &(m_after_file_commands); 130 break; 131 case eCommandPlacementAfterCrash: 132 command_set = &(m_after_crash_commands); 133 break; 134 } 135 136 if (is_file) { 137 SBFileSpec file(command.c_str()); 138 if (file.Exists()) 139 command_set->push_back(InitialCmdEntry(command, is_file)); 140 else if (file.ResolveExecutableLocation()) { 141 char final_path[PATH_MAX]; 142 file.GetPath(final_path, sizeof(final_path)); 143 command_set->push_back(InitialCmdEntry(final_path, is_file)); 144 } else 145 error.SetErrorStringWithFormat( 146 "file specified in --source (-s) option doesn't exist: '%s'", 147 command.c_str()); 148 } else 149 command_set->push_back(InitialCmdEntry(command, is_file)); 150 } 151 152 void Driver::WriteCommandsForSourcing(CommandPlacement placement, 153 SBStream &strm) { 154 std::vector<OptionData::InitialCmdEntry> *command_set; 155 switch (placement) { 156 case eCommandPlacementBeforeFile: 157 command_set = &m_option_data.m_initial_commands; 158 break; 159 case eCommandPlacementAfterFile: 160 command_set = &m_option_data.m_after_file_commands; 161 break; 162 case eCommandPlacementAfterCrash: 163 command_set = &m_option_data.m_after_crash_commands; 164 break; 165 } 166 167 for (const auto &command_entry : *command_set) { 168 const char *command = command_entry.contents.c_str(); 169 if (command_entry.is_file) { 170 bool source_quietly = 171 m_option_data.m_source_quietly || command_entry.source_quietly; 172 strm.Printf("command source -s %i '%s'\n", 173 static_cast<int>(source_quietly), command); 174 } else 175 strm.Printf("%s\n", command); 176 } 177 } 178 179 // Check the arguments that were passed to this program to make sure they are 180 // valid and to get their argument values (if any). Return a boolean value 181 // indicating whether or not to start up the full debugger (i.e. the Command 182 // Interpreter) or not. Return FALSE if the arguments were invalid OR if the 183 // user only wanted help or version information. 184 SBError Driver::ProcessArgs(const opt::InputArgList &args, bool &exiting) { 185 SBError error; 186 187 // This is kind of a pain, but since we make the debugger in the Driver's 188 // constructor, we can't know at that point whether we should read in init 189 // files yet. So we don't read them in in the Driver constructor, then set 190 // the flags back to "read them in" here, and then if we see the "-n" flag, 191 // we'll turn it off again. Finally we have to read them in by hand later in 192 // the main loop. 193 m_debugger.SkipLLDBInitFiles(false); 194 m_debugger.SkipAppInitFiles(false); 195 196 if (args.hasArg(OPT_version)) { 197 m_option_data.m_print_version = true; 198 } 199 200 if (args.hasArg(OPT_python_path)) { 201 m_option_data.m_print_python_path = true; 202 } 203 204 if (args.hasArg(OPT_batch)) { 205 m_option_data.m_batch = true; 206 } 207 208 if (auto *arg = args.getLastArg(OPT_core)) { 209 auto arg_value = arg->getValue(); 210 SBFileSpec file(arg_value); 211 if (!file.Exists()) { 212 error.SetErrorStringWithFormat( 213 "file specified in --core (-c) option doesn't exist: '%s'", 214 arg_value); 215 return error; 216 } 217 m_option_data.m_core_file = arg_value; 218 } 219 220 if (args.hasArg(OPT_editor)) { 221 m_option_data.m_use_external_editor = true; 222 } 223 224 if (args.hasArg(OPT_no_lldbinit)) { 225 m_debugger.SkipLLDBInitFiles(true); 226 m_debugger.SkipAppInitFiles(true); 227 } 228 229 if (args.hasArg(OPT_local_lldbinit)) { 230 lldb::SBDebugger::SetInternalVariable("target.load-cwd-lldbinit", "true", 231 m_debugger.GetInstanceName()); 232 } 233 234 if (args.hasArg(OPT_no_use_colors)) { 235 m_debugger.SetUseColor(false); 236 m_option_data.m_debug_mode = true; 237 } 238 239 if (auto *arg = args.getLastArg(OPT_file)) { 240 auto arg_value = arg->getValue(); 241 SBFileSpec file(arg_value); 242 if (file.Exists()) { 243 m_option_data.m_args.emplace_back(arg_value); 244 } else if (file.ResolveExecutableLocation()) { 245 char path[PATH_MAX]; 246 file.GetPath(path, sizeof(path)); 247 m_option_data.m_args.emplace_back(path); 248 } else { 249 error.SetErrorStringWithFormat( 250 "file specified in --file (-f) option doesn't exist: '%s'", 251 arg_value); 252 return error; 253 } 254 } 255 256 if (auto *arg = args.getLastArg(OPT_arch)) { 257 auto arg_value = arg->getValue(); 258 if (!lldb::SBDebugger::SetDefaultArchitecture(arg_value)) { 259 error.SetErrorStringWithFormat( 260 "invalid architecture in the -a or --arch option: '%s'", arg_value); 261 return error; 262 } 263 } 264 265 if (auto *arg = args.getLastArg(OPT_script_language)) { 266 auto arg_value = arg->getValue(); 267 m_debugger.SetScriptLanguage(m_debugger.GetScriptingLanguage(arg_value)); 268 } 269 270 if (args.hasArg(OPT_source_quietly)) { 271 m_option_data.m_source_quietly = true; 272 } 273 274 if (auto *arg = args.getLastArg(OPT_attach_name)) { 275 auto arg_value = arg->getValue(); 276 m_option_data.m_process_name = arg_value; 277 } 278 279 if (args.hasArg(OPT_wait_for)) { 280 m_option_data.m_wait_for = true; 281 } 282 283 if (auto *arg = args.getLastArg(OPT_attach_pid)) { 284 auto arg_value = arg->getValue(); 285 char *remainder; 286 m_option_data.m_process_pid = strtol(arg_value, &remainder, 0); 287 if (remainder == arg_value || *remainder != '\0') { 288 error.SetErrorStringWithFormat( 289 "Could not convert process PID: \"%s\" into a pid.", arg_value); 290 return error; 291 } 292 } 293 294 if (auto *arg = args.getLastArg(OPT_repl_language)) { 295 auto arg_value = arg->getValue(); 296 m_option_data.m_repl_lang = 297 SBLanguageRuntime::GetLanguageTypeFromString(arg_value); 298 if (m_option_data.m_repl_lang == eLanguageTypeUnknown) { 299 error.SetErrorStringWithFormat("Unrecognized language name: \"%s\"", 300 arg_value); 301 return error; 302 } 303 } 304 305 if (args.hasArg(OPT_repl)) { 306 m_option_data.m_repl = true; 307 } 308 309 if (auto *arg = args.getLastArg(OPT_repl_)) { 310 m_option_data.m_repl = true; 311 if (auto arg_value = arg->getValue()) 312 m_option_data.m_repl_options = arg_value; 313 } 314 315 // We need to process the options below together as their relative order 316 // matters. 317 for (auto *arg : args.filtered(OPT_source_on_crash, OPT_one_line_on_crash, 318 OPT_source, OPT_source_before_file, 319 OPT_one_line, OPT_one_line_before_file)) { 320 auto arg_value = arg->getValue(); 321 if (arg->getOption().matches(OPT_source_on_crash)) { 322 m_option_data.AddInitialCommand(arg_value, eCommandPlacementAfterCrash, 323 true, error); 324 if (error.Fail()) 325 return error; 326 } 327 328 if (arg->getOption().matches(OPT_one_line_on_crash)) { 329 m_option_data.AddInitialCommand(arg_value, eCommandPlacementAfterCrash, 330 false, error); 331 if (error.Fail()) 332 return error; 333 } 334 335 if (arg->getOption().matches(OPT_source)) { 336 m_option_data.AddInitialCommand(arg_value, eCommandPlacementAfterFile, 337 true, error); 338 if (error.Fail()) 339 return error; 340 } 341 342 if (arg->getOption().matches(OPT_source_before_file)) { 343 m_option_data.AddInitialCommand(arg_value, eCommandPlacementBeforeFile, 344 true, error); 345 if (error.Fail()) 346 return error; 347 } 348 349 if (arg->getOption().matches(OPT_one_line)) { 350 m_option_data.AddInitialCommand(arg_value, eCommandPlacementAfterFile, 351 false, error); 352 if (error.Fail()) 353 return error; 354 } 355 356 if (arg->getOption().matches(OPT_one_line_before_file)) { 357 m_option_data.AddInitialCommand(arg_value, eCommandPlacementBeforeFile, 358 false, error); 359 if (error.Fail()) 360 return error; 361 } 362 } 363 364 if (m_option_data.m_process_name.empty() && 365 m_option_data.m_process_pid == LLDB_INVALID_PROCESS_ID) { 366 367 for (auto *arg : args.filtered(OPT_INPUT)) 368 m_option_data.m_args.push_back(arg->getAsString((args))); 369 370 // Any argument following -- is an argument for the inferior. 371 if (auto *arg = args.getLastArgNoClaim(OPT_REM)) { 372 for (auto value : arg->getValues()) 373 m_option_data.m_args.emplace_back(value); 374 } 375 } else if (args.getLastArgNoClaim() != nullptr) { 376 WithColor::warning() << "program arguments are ignored when attaching.\n"; 377 } 378 379 if (m_option_data.m_print_version) { 380 llvm::outs() << lldb::SBDebugger::GetVersionString() << '\n'; 381 exiting = true; 382 return error; 383 } 384 385 if (m_option_data.m_print_python_path) { 386 SBFileSpec python_file_spec = SBHostOS::GetLLDBPythonPath(); 387 if (python_file_spec.IsValid()) { 388 char python_path[PATH_MAX]; 389 size_t num_chars = python_file_spec.GetPath(python_path, PATH_MAX); 390 if (num_chars < PATH_MAX) { 391 llvm::outs() << python_path << '\n'; 392 } else 393 llvm::outs() << "<PATH TOO LONG>\n"; 394 } else 395 llvm::outs() << "<COULD NOT FIND PATH>\n"; 396 exiting = true; 397 return error; 398 } 399 400 return error; 401 } 402 403 static inline int OpenPipe(int fds[2], std::size_t size) { 404 #ifdef _WIN32 405 return _pipe(fds, size, O_BINARY); 406 #else 407 (void)size; 408 return pipe(fds); 409 #endif 410 } 411 412 static ::FILE *PrepareCommandsForSourcing(const char *commands_data, 413 size_t commands_size) { 414 enum PIPES { READ, WRITE }; // Indexes for the read and write fds 415 int fds[2] = {-1, -1}; 416 417 if (OpenPipe(fds, commands_size) != 0) { 418 WithColor::error() 419 << "can't create pipe file descriptors for LLDB commands\n"; 420 return nullptr; 421 } 422 423 ssize_t nrwr = write(fds[WRITE], commands_data, commands_size); 424 if (size_t(nrwr) != commands_size) { 425 WithColor::error() 426 << format( 427 "write(%i, %p, %" PRIu64 428 ") failed (errno = %i) when trying to open LLDB commands pipe", 429 fds[WRITE], static_cast<const void *>(commands_data), 430 static_cast<uint64_t>(commands_size), errno) 431 << '\n'; 432 llvm::sys::Process::SafelyCloseFileDescriptor(fds[READ]); 433 llvm::sys::Process::SafelyCloseFileDescriptor(fds[WRITE]); 434 return nullptr; 435 } 436 437 // Close the write end of the pipe, so that the command interpreter will exit 438 // when it consumes all the data. 439 llvm::sys::Process::SafelyCloseFileDescriptor(fds[WRITE]); 440 441 // Open the read file descriptor as a FILE * that we can return as an input 442 // handle. 443 ::FILE *commands_file = fdopen(fds[READ], "rb"); 444 if (commands_file == nullptr) { 445 WithColor::error() << format("fdopen(%i, \"rb\") failed (errno = %i) " 446 "when trying to open LLDB commands pipe", 447 fds[READ], errno) 448 << '\n'; 449 llvm::sys::Process::SafelyCloseFileDescriptor(fds[READ]); 450 return nullptr; 451 } 452 453 // 'commands_file' now owns the read descriptor. 454 return commands_file; 455 } 456 457 std::string EscapeString(std::string arg) { 458 std::string::size_type pos = 0; 459 while ((pos = arg.find_first_of("\"\\", pos)) != std::string::npos) { 460 arg.insert(pos, 1, '\\'); 461 pos += 2; 462 } 463 return '"' + arg + '"'; 464 } 465 466 int Driver::MainLoop() { 467 if (::tcgetattr(STDIN_FILENO, &g_old_stdin_termios) == 0) { 468 g_old_stdin_termios_is_valid = true; 469 atexit(reset_stdin_termios); 470 } 471 472 #ifndef _MSC_VER 473 // Disabling stdin buffering with MSVC's 2015 CRT exposes a bug in fgets 474 // which causes it to miss newlines depending on whether there have been an 475 // odd or even number of characters. Bug has been reported to MS via Connect. 476 ::setbuf(stdin, nullptr); 477 #endif 478 ::setbuf(stdout, nullptr); 479 480 m_debugger.SetErrorFileHandle(stderr, false); 481 m_debugger.SetOutputFileHandle(stdout, false); 482 // Don't take ownership of STDIN yet... 483 m_debugger.SetInputFileHandle(stdin, false); 484 485 m_debugger.SetUseExternalEditor(m_option_data.m_use_external_editor); 486 487 struct winsize window_size; 488 if ((isatty(STDIN_FILENO) != 0) && 489 ::ioctl(STDIN_FILENO, TIOCGWINSZ, &window_size) == 0) { 490 if (window_size.ws_col > 0) 491 m_debugger.SetTerminalWidth(window_size.ws_col); 492 } 493 494 SBCommandInterpreter sb_interpreter = m_debugger.GetCommandInterpreter(); 495 496 // Before we handle any options from the command line, we parse the 497 // REPL init file or the default file in the user's home directory. 498 SBCommandReturnObject result; 499 sb_interpreter.SourceInitFileInHomeDirectory(result, m_option_data.m_repl); 500 if (m_option_data.m_debug_mode) { 501 result.PutError(m_debugger.GetErrorFile()); 502 result.PutOutput(m_debugger.GetOutputFile()); 503 } 504 505 // Source the local .lldbinit file if it exists and we're allowed to source. 506 // Here we want to always print the return object because it contains the 507 // warning and instructions to load local lldbinit files. 508 sb_interpreter.SourceInitFileInCurrentWorkingDirectory(result); 509 result.PutError(m_debugger.GetErrorFile()); 510 result.PutOutput(m_debugger.GetOutputFile()); 511 512 // We allow the user to specify an exit code when calling quit which we will 513 // return when exiting. 514 m_debugger.GetCommandInterpreter().AllowExitCodeOnQuit(true); 515 516 // Now we handle options we got from the command line 517 SBStream commands_stream; 518 519 // First source in the commands specified to be run before the file arguments 520 // are processed. 521 WriteCommandsForSourcing(eCommandPlacementBeforeFile, commands_stream); 522 523 // If we're not in --repl mode, add the commands to process the file 524 // arguments, and the commands specified to run afterwards. 525 if (!m_option_data.m_repl) { 526 const size_t num_args = m_option_data.m_args.size(); 527 if (num_args > 0) { 528 char arch_name[64]; 529 if (lldb::SBDebugger::GetDefaultArchitecture(arch_name, 530 sizeof(arch_name))) 531 commands_stream.Printf("target create --arch=%s %s", arch_name, 532 EscapeString(m_option_data.m_args[0]).c_str()); 533 else 534 commands_stream.Printf("target create %s", 535 EscapeString(m_option_data.m_args[0]).c_str()); 536 537 if (!m_option_data.m_core_file.empty()) { 538 commands_stream.Printf(" --core %s", 539 EscapeString(m_option_data.m_core_file).c_str()); 540 } 541 commands_stream.Printf("\n"); 542 543 if (num_args > 1) { 544 commands_stream.Printf("settings set -- target.run-args "); 545 for (size_t arg_idx = 1; arg_idx < num_args; ++arg_idx) 546 commands_stream.Printf( 547 " %s", EscapeString(m_option_data.m_args[arg_idx]).c_str()); 548 commands_stream.Printf("\n"); 549 } 550 } else if (!m_option_data.m_core_file.empty()) { 551 commands_stream.Printf("target create --core %s\n", 552 EscapeString(m_option_data.m_core_file).c_str()); 553 } else if (!m_option_data.m_process_name.empty()) { 554 commands_stream.Printf( 555 "process attach --name %s", 556 EscapeString(m_option_data.m_process_name).c_str()); 557 558 if (m_option_data.m_wait_for) 559 commands_stream.Printf(" --waitfor"); 560 561 commands_stream.Printf("\n"); 562 563 } else if (LLDB_INVALID_PROCESS_ID != m_option_data.m_process_pid) { 564 commands_stream.Printf("process attach --pid %" PRIu64 "\n", 565 m_option_data.m_process_pid); 566 } 567 568 WriteCommandsForSourcing(eCommandPlacementAfterFile, commands_stream); 569 } else if (!m_option_data.m_after_file_commands.empty()) { 570 // We're in repl mode and after-file-load commands were specified. 571 WithColor::warning() << "commands specified to run after file load (via -o " 572 "or -s) are ignored in REPL mode.\n"; 573 } 574 575 if (m_option_data.m_debug_mode) { 576 result.PutError(m_debugger.GetErrorFile()); 577 result.PutOutput(m_debugger.GetOutputFile()); 578 } 579 580 const bool handle_events = true; 581 const bool spawn_thread = false; 582 583 // Check if we have any data in the commands stream, and if so, save it to a 584 // temp file 585 // so we can then run the command interpreter using the file contents. 586 const char *commands_data = commands_stream.GetData(); 587 const size_t commands_size = commands_stream.GetSize(); 588 589 bool go_interactive = true; 590 if ((commands_data != nullptr) && (commands_size != 0u)) { 591 FILE *commands_file = 592 PrepareCommandsForSourcing(commands_data, commands_size); 593 594 if (commands_file == nullptr) { 595 // We should have already printed an error in PrepareCommandsForSourcing. 596 return 1; 597 } 598 599 m_debugger.SetInputFileHandle(commands_file, true); 600 601 // Set the debugger into Sync mode when running the command file. Otherwise 602 // command files that run the target won't run in a sensible way. 603 bool old_async = m_debugger.GetAsync(); 604 m_debugger.SetAsync(false); 605 606 SBCommandInterpreterRunOptions options; 607 options.SetAutoHandleEvents(true); 608 options.SetSpawnThread(false); 609 options.SetStopOnError(true); 610 options.SetStopOnCrash(m_option_data.m_batch); 611 612 SBCommandInterpreterRunResult results = 613 m_debugger.RunCommandInterpreter(options); 614 if (results.GetResult() == lldb::eCommandInterpreterResultQuitRequested) 615 go_interactive = false; 616 if (m_option_data.m_batch && 617 results.GetResult() != lldb::eCommandInterpreterResultInferiorCrash) 618 go_interactive = false; 619 620 // When running in batch mode and stopped because of an error, exit with a 621 // non-zero exit status. 622 if (m_option_data.m_batch && 623 results.GetResult() == lldb::eCommandInterpreterResultCommandError) 624 return 1; 625 626 if (m_option_data.m_batch && 627 results.GetResult() == lldb::eCommandInterpreterResultInferiorCrash && 628 !m_option_data.m_after_crash_commands.empty()) { 629 SBStream crash_commands_stream; 630 WriteCommandsForSourcing(eCommandPlacementAfterCrash, 631 crash_commands_stream); 632 const char *crash_commands_data = crash_commands_stream.GetData(); 633 const size_t crash_commands_size = crash_commands_stream.GetSize(); 634 commands_file = 635 PrepareCommandsForSourcing(crash_commands_data, crash_commands_size); 636 if (commands_file != nullptr) { 637 m_debugger.SetInputFileHandle(commands_file, true); 638 SBCommandInterpreterRunResult local_results = 639 m_debugger.RunCommandInterpreter(options); 640 if (local_results.GetResult() == 641 lldb::eCommandInterpreterResultQuitRequested) 642 go_interactive = false; 643 644 // When running in batch mode and an error occurred while sourcing 645 // the crash commands, exit with a non-zero exit status. 646 if (m_option_data.m_batch && 647 local_results.GetResult() == 648 lldb::eCommandInterpreterResultCommandError) 649 return 1; 650 } 651 } 652 m_debugger.SetAsync(old_async); 653 } 654 655 // Now set the input file handle to STDIN and run the command interpreter 656 // again in interactive mode or repl mode and let the debugger take ownership 657 // of stdin. 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 return sb_interpreter.GetQuitStatus(); 683 } 684 685 void Driver::ResizeWindow(unsigned short col) { 686 GetDebugger().SetTerminalWidth(col); 687 } 688 689 void sigwinch_handler(int signo) { 690 struct winsize window_size; 691 if ((isatty(STDIN_FILENO) != 0) && 692 ::ioctl(STDIN_FILENO, TIOCGWINSZ, &window_size) == 0) { 693 if ((window_size.ws_col > 0) && g_driver != nullptr) { 694 g_driver->ResizeWindow(window_size.ws_col); 695 } 696 } 697 } 698 699 void sigint_handler(int signo) { 700 #ifdef _WIN32 // Restore handler as it is not persistent on Windows 701 signal(SIGINT, sigint_handler); 702 #endif 703 static std::atomic_flag g_interrupt_sent = ATOMIC_FLAG_INIT; 704 if (g_driver != nullptr) { 705 if (!g_interrupt_sent.test_and_set()) { 706 g_driver->GetDebugger().DispatchInputInterrupt(); 707 g_interrupt_sent.clear(); 708 return; 709 } 710 } 711 712 _exit(signo); 713 } 714 715 void sigtstp_handler(int signo) { 716 if (g_driver != nullptr) 717 g_driver->GetDebugger().SaveInputTerminalState(); 718 719 signal(signo, SIG_DFL); 720 kill(getpid(), signo); 721 signal(signo, sigtstp_handler); 722 } 723 724 void sigcont_handler(int signo) { 725 if (g_driver != nullptr) 726 g_driver->GetDebugger().RestoreInputTerminalState(); 727 728 signal(signo, SIG_DFL); 729 kill(getpid(), signo); 730 signal(signo, sigcont_handler); 731 } 732 733 void reproducer_handler(void *finalize_cmd) { 734 if (SBReproducer::Generate()) { 735 int result = std::system(static_cast<const char *>(finalize_cmd)); 736 (void)result; 737 fflush(stdout); 738 } 739 } 740 741 static void printHelp(LLDBOptTable &table, llvm::StringRef tool_name) { 742 std::string usage_str = tool_name.str() + " [options]"; 743 table.PrintHelp(llvm::outs(), usage_str.c_str(), "LLDB", false); 744 745 std::string examples = R"___( 746 EXAMPLES: 747 The debugger can be started in several modes. 748 749 Passing an executable as a positional argument prepares lldb to debug the 750 given executable. To disambiguate between arguments passed to lldb and 751 arguments passed to the debugged executable, arguments starting with a - must 752 be passed after --. 753 754 lldb --arch x86_64 /path/to/program program argument -- --arch armv7 755 756 For convenience, passing the executable after -- is also supported. 757 758 lldb --arch x86_64 -- /path/to/program program argument --arch armv7 759 760 Passing one of the attach options causes lldb to immediately attach to the 761 given process. 762 763 lldb -p <pid> 764 lldb -n <process-name> 765 766 Passing --repl starts lldb in REPL mode. 767 768 lldb -r 769 770 Passing --core causes lldb to debug the core file. 771 772 lldb -c /path/to/core 773 774 Command options can be combined with these modes and cause lldb to run the 775 specified commands before or after events, like loading the file or crashing, 776 in the order provided on the command line. 777 778 lldb -O 'settings set stop-disassembly-count 20' -o 'run' -o 'bt' 779 lldb -S /source/before/file -s /source/after/file 780 lldb -K /source/before/crash -k /source/after/crash 781 782 Note: In REPL mode no file is loaded, so commands specified to run after 783 loading the file (via -o or -s) will be ignored.)___"; 784 llvm::outs() << examples << '\n'; 785 } 786 787 llvm::Optional<int> InitializeReproducer(llvm::StringRef argv0, 788 opt::InputArgList &input_args) { 789 if (auto *finalize_path = input_args.getLastArg(OPT_reproducer_finalize)) { 790 if (const char *error = SBReproducer::Finalize(finalize_path->getValue())) { 791 WithColor::error() << "reproducer finalization failed: " << error << '\n'; 792 return 1; 793 } 794 795 llvm::outs() << "********************\n"; 796 llvm::outs() << "Crash reproducer for "; 797 llvm::outs() << lldb::SBDebugger::GetVersionString() << '\n'; 798 llvm::outs() << '\n'; 799 llvm::outs() << "Reproducer written to '" << SBReproducer::GetPath() 800 << "'\n"; 801 llvm::outs() << '\n'; 802 llvm::outs() << "Before attaching the reproducer to a bug report:\n"; 803 llvm::outs() << " - Look at the directory to ensure you're willing to " 804 "share its content.\n"; 805 llvm::outs() 806 << " - Make sure the reproducer works by replaying the reproducer.\n"; 807 llvm::outs() << '\n'; 808 llvm::outs() << "Replay the reproducer with the following command:\n"; 809 llvm::outs() << argv0 << " -replay " << finalize_path->getValue() << "\n"; 810 llvm::outs() << "********************\n"; 811 return 0; 812 } 813 814 if (auto *replay_path = input_args.getLastArg(OPT_replay)) { 815 SBReplayOptions replay_options; 816 replay_options.SetCheckVersion(!input_args.hasArg(OPT_no_version_check)); 817 replay_options.SetVerify(!input_args.hasArg(OPT_no_verification)); 818 if (const char *error = 819 SBReproducer::Replay(replay_path->getValue(), replay_options)) { 820 WithColor::error() << "reproducer replay failed: " << error << '\n'; 821 return 1; 822 } 823 return 0; 824 } 825 826 bool capture = input_args.hasArg(OPT_capture); 827 bool generate_on_exit = input_args.hasArg(OPT_generate_on_exit); 828 auto *capture_path = input_args.getLastArg(OPT_capture_path); 829 830 if (generate_on_exit && !capture) { 831 WithColor::warning() 832 << "-reproducer-generate-on-exit specified without -capture\n"; 833 } 834 835 if (capture || capture_path) { 836 if (capture_path) { 837 if (!capture) 838 WithColor::warning() << "-capture-path specified without -capture\n"; 839 if (const char *error = SBReproducer::Capture(capture_path->getValue())) { 840 WithColor::error() << "reproducer capture failed: " << error << '\n'; 841 return 1; 842 } 843 } else { 844 const char *error = SBReproducer::Capture(); 845 if (error) { 846 WithColor::error() << "reproducer capture failed: " << error << '\n'; 847 return 1; 848 } 849 } 850 if (generate_on_exit) 851 SBReproducer::SetAutoGenerate(true); 852 853 // Register the reproducer signal handler. 854 if (!input_args.hasArg(OPT_no_generate_on_signal)) { 855 if (const char *reproducer_path = SBReproducer::GetPath()) { 856 // Leaking the string on purpose. 857 std::string *finalize_cmd = new std::string(argv0); 858 finalize_cmd->append(" --reproducer-finalize '"); 859 finalize_cmd->append(reproducer_path); 860 finalize_cmd->append("'"); 861 llvm::sys::AddSignalHandler(reproducer_handler, 862 const_cast<char *>(finalize_cmd->c_str())); 863 } 864 } 865 } 866 867 return llvm::None; 868 } 869 870 int main(int argc, char const *argv[]) { 871 // Setup LLVM signal handlers and make sure we call llvm_shutdown() on 872 // destruction. 873 llvm::InitLLVM IL(argc, argv, /*InstallPipeSignalExitHandler=*/false); 874 875 // Parse arguments. 876 LLDBOptTable T; 877 unsigned MissingArgIndex; 878 unsigned MissingArgCount; 879 ArrayRef<const char *> arg_arr = makeArrayRef(argv + 1, argc - 1); 880 opt::InputArgList input_args = 881 T.ParseArgs(arg_arr, MissingArgIndex, MissingArgCount); 882 llvm::StringRef argv0 = llvm::sys::path::filename(argv[0]); 883 884 if (input_args.hasArg(OPT_help)) { 885 printHelp(T, argv0); 886 return 0; 887 } 888 889 // Check for missing argument error. 890 if (MissingArgCount) { 891 WithColor::error() << "argument to '" 892 << input_args.getArgString(MissingArgIndex) 893 << "' is missing\n"; 894 } 895 // Error out on unknown options. 896 if (input_args.hasArg(OPT_UNKNOWN)) { 897 for (auto *arg : input_args.filtered(OPT_UNKNOWN)) { 898 WithColor::error() << "unknown option: " << arg->getSpelling() << '\n'; 899 } 900 } 901 if (MissingArgCount || input_args.hasArg(OPT_UNKNOWN)) { 902 llvm::errs() << "Use '" << argv0 903 << " --help' for a complete list of options.\n"; 904 return 1; 905 } 906 907 if (auto exit_code = InitializeReproducer(argv[0], input_args)) { 908 return *exit_code; 909 } 910 911 SBError error = SBDebugger::InitializeWithErrorHandling(); 912 if (error.Fail()) { 913 WithColor::error() << "initialization failed: " << error.GetCString() 914 << '\n'; 915 return 1; 916 } 917 SBHostOS::ThreadCreated("<lldb.driver.main-thread>"); 918 919 signal(SIGINT, sigint_handler); 920 #if !defined(_MSC_VER) 921 signal(SIGPIPE, SIG_IGN); 922 signal(SIGWINCH, sigwinch_handler); 923 signal(SIGTSTP, sigtstp_handler); 924 signal(SIGCONT, sigcont_handler); 925 #endif 926 927 int exit_code = 0; 928 // Create a scope for driver so that the driver object will destroy itself 929 // before SBDebugger::Terminate() is called. 930 { 931 Driver driver; 932 933 bool exiting = false; 934 SBError error(driver.ProcessArgs(input_args, exiting)); 935 if (error.Fail()) { 936 exit_code = 1; 937 if (const char *error_cstr = error.GetCString()) 938 WithColor::error() << error_cstr << '\n'; 939 } else if (!exiting) { 940 exit_code = driver.MainLoop(); 941 } 942 } 943 944 SBDebugger::Terminate(); 945 return exit_code; 946 } 947