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 <clocale> 35 #include <csignal> 36 #include <string> 37 #include <thread> 38 #include <utility> 39 40 #include <climits> 41 #include <cstdio> 42 #include <cstdlib> 43 #include <cstring> 44 #include <fcntl.h> 45 46 // Includes for pipe() 47 #if defined(_WIN32) 48 #include <fcntl.h> 49 #include <io.h> 50 #else 51 #include <unistd.h> 52 #endif 53 54 #if !defined(__APPLE__) 55 #include "llvm/Support/DataTypes.h" 56 #endif 57 58 using namespace lldb; 59 using namespace llvm; 60 61 namespace { 62 enum ID { 63 OPT_INVALID = 0, // This is not an option ID. 64 #define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \ 65 HELPTEXT, METAVAR, VALUES) \ 66 OPT_##ID, 67 #include "Options.inc" 68 #undef OPTION 69 }; 70 71 #define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE; 72 #include "Options.inc" 73 #undef PREFIX 74 75 const opt::OptTable::Info InfoTable[] = { 76 #define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \ 77 HELPTEXT, METAVAR, VALUES) \ 78 { \ 79 PREFIX, NAME, HELPTEXT, \ 80 METAVAR, OPT_##ID, opt::Option::KIND##Class, \ 81 PARAM, FLAGS, OPT_##GROUP, \ 82 OPT_##ALIAS, ALIASARGS, VALUES}, 83 #include "Options.inc" 84 #undef OPTION 85 }; 86 87 class LLDBOptTable : public opt::OptTable { 88 public: 89 LLDBOptTable() : OptTable(InfoTable) {} 90 }; 91 } // namespace 92 93 static void reset_stdin_termios(); 94 static bool g_old_stdin_termios_is_valid = false; 95 static struct termios g_old_stdin_termios; 96 97 static Driver *g_driver = nullptr; 98 99 // In the Driver::MainLoop, we change the terminal settings. This function is 100 // added as an atexit handler to make sure we clean them up. 101 static void reset_stdin_termios() { 102 if (g_old_stdin_termios_is_valid) { 103 g_old_stdin_termios_is_valid = false; 104 ::tcsetattr(STDIN_FILENO, TCSANOW, &g_old_stdin_termios); 105 } 106 } 107 108 Driver::Driver() 109 : SBBroadcaster("Driver"), m_debugger(SBDebugger::Create(false)) { 110 // We want to be able to handle CTRL+D in the terminal to have it terminate 111 // certain input 112 m_debugger.SetCloseInputOnEOF(false); 113 g_driver = this; 114 } 115 116 Driver::~Driver() { 117 SBDebugger::Destroy(m_debugger); 118 g_driver = nullptr; 119 } 120 121 void Driver::OptionData::AddInitialCommand(std::string command, 122 CommandPlacement placement, 123 bool is_file, SBError &error) { 124 std::vector<InitialCmdEntry> *command_set; 125 switch (placement) { 126 case eCommandPlacementBeforeFile: 127 command_set = &(m_initial_commands); 128 break; 129 case eCommandPlacementAfterFile: 130 command_set = &(m_after_file_commands); 131 break; 132 case eCommandPlacementAfterCrash: 133 command_set = &(m_after_crash_commands); 134 break; 135 } 136 137 if (is_file) { 138 SBFileSpec file(command.c_str()); 139 if (file.Exists()) 140 command_set->push_back(InitialCmdEntry(command, is_file)); 141 else if (file.ResolveExecutableLocation()) { 142 char final_path[PATH_MAX]; 143 file.GetPath(final_path, sizeof(final_path)); 144 command_set->push_back(InitialCmdEntry(final_path, is_file)); 145 } else 146 error.SetErrorStringWithFormat( 147 "file specified in --source (-s) option doesn't exist: '%s'", 148 command.c_str()); 149 } else 150 command_set->push_back(InitialCmdEntry(command, is_file)); 151 } 152 153 void Driver::WriteCommandsForSourcing(CommandPlacement placement, 154 SBStream &strm) { 155 std::vector<OptionData::InitialCmdEntry> *command_set; 156 switch (placement) { 157 case eCommandPlacementBeforeFile: 158 command_set = &m_option_data.m_initial_commands; 159 break; 160 case eCommandPlacementAfterFile: 161 command_set = &m_option_data.m_after_file_commands; 162 break; 163 case eCommandPlacementAfterCrash: 164 command_set = &m_option_data.m_after_crash_commands; 165 break; 166 } 167 168 for (const auto &command_entry : *command_set) { 169 const char *command = command_entry.contents.c_str(); 170 if (command_entry.is_file) { 171 bool source_quietly = 172 m_option_data.m_source_quietly || command_entry.source_quietly; 173 strm.Printf("command source -s %i '%s'\n", 174 static_cast<int>(source_quietly), command); 175 } else 176 strm.Printf("%s\n", command); 177 } 178 } 179 180 // Check the arguments that were passed to this program to make sure they are 181 // valid and to get their argument values (if any). Return a boolean value 182 // indicating whether or not to start up the full debugger (i.e. the Command 183 // Interpreter) or not. Return FALSE if the arguments were invalid OR if the 184 // user only wanted help or version information. 185 SBError Driver::ProcessArgs(const opt::InputArgList &args, bool &exiting) { 186 SBError error; 187 188 // This is kind of a pain, but since we make the debugger in the Driver's 189 // constructor, we can't know at that point whether we should read in init 190 // files yet. So we don't read them in in the Driver constructor, then set 191 // the flags back to "read them in" here, and then if we see the "-n" flag, 192 // we'll turn it off again. Finally we have to read them in by hand later in 193 // the main loop. 194 m_debugger.SkipLLDBInitFiles(false); 195 m_debugger.SkipAppInitFiles(false); 196 197 if (args.hasArg(OPT_version)) { 198 m_option_data.m_print_version = true; 199 } 200 201 if (args.hasArg(OPT_python_path)) { 202 m_option_data.m_print_python_path = true; 203 } 204 205 if (args.hasArg(OPT_batch)) { 206 m_option_data.m_batch = true; 207 } 208 209 if (auto *arg = args.getLastArg(OPT_core)) { 210 auto arg_value = arg->getValue(); 211 SBFileSpec file(arg_value); 212 if (!file.Exists()) { 213 error.SetErrorStringWithFormat( 214 "file specified in --core (-c) option doesn't exist: '%s'", 215 arg_value); 216 return error; 217 } 218 m_option_data.m_core_file = arg_value; 219 } 220 221 if (args.hasArg(OPT_editor)) { 222 m_option_data.m_use_external_editor = true; 223 } 224 225 if (args.hasArg(OPT_no_lldbinit)) { 226 m_debugger.SkipLLDBInitFiles(true); 227 m_debugger.SkipAppInitFiles(true); 228 } 229 230 if (args.hasArg(OPT_local_lldbinit)) { 231 lldb::SBDebugger::SetInternalVariable("target.load-cwd-lldbinit", "true", 232 m_debugger.GetInstanceName()); 233 } 234 235 if (args.hasArg(OPT_no_use_colors)) { 236 m_debugger.SetUseColor(false); 237 m_option_data.m_debug_mode = true; 238 } 239 240 if (auto *arg = args.getLastArg(OPT_file)) { 241 auto arg_value = arg->getValue(); 242 SBFileSpec file(arg_value); 243 if (file.Exists()) { 244 m_option_data.m_args.emplace_back(arg_value); 245 } else if (file.ResolveExecutableLocation()) { 246 char path[PATH_MAX]; 247 file.GetPath(path, sizeof(path)); 248 m_option_data.m_args.emplace_back(path); 249 } else { 250 error.SetErrorStringWithFormat( 251 "file specified in --file (-f) option doesn't exist: '%s'", 252 arg_value); 253 return error; 254 } 255 } 256 257 if (auto *arg = args.getLastArg(OPT_arch)) { 258 auto arg_value = arg->getValue(); 259 if (!lldb::SBDebugger::SetDefaultArchitecture(arg_value)) { 260 error.SetErrorStringWithFormat( 261 "invalid architecture in the -a or --arch option: '%s'", arg_value); 262 return error; 263 } 264 } 265 266 if (auto *arg = args.getLastArg(OPT_script_language)) { 267 auto arg_value = arg->getValue(); 268 m_debugger.SetScriptLanguage(m_debugger.GetScriptingLanguage(arg_value)); 269 } 270 271 if (args.hasArg(OPT_source_quietly)) { 272 m_option_data.m_source_quietly = true; 273 } 274 275 if (auto *arg = args.getLastArg(OPT_attach_name)) { 276 auto arg_value = arg->getValue(); 277 m_option_data.m_process_name = arg_value; 278 } 279 280 if (args.hasArg(OPT_wait_for)) { 281 m_option_data.m_wait_for = true; 282 } 283 284 if (auto *arg = args.getLastArg(OPT_attach_pid)) { 285 auto arg_value = arg->getValue(); 286 char *remainder; 287 m_option_data.m_process_pid = strtol(arg_value, &remainder, 0); 288 if (remainder == arg_value || *remainder != '\0') { 289 error.SetErrorStringWithFormat( 290 "Could not convert process PID: \"%s\" into a pid.", arg_value); 291 return error; 292 } 293 } 294 295 if (auto *arg = args.getLastArg(OPT_repl_language)) { 296 auto arg_value = arg->getValue(); 297 m_option_data.m_repl_lang = 298 SBLanguageRuntime::GetLanguageTypeFromString(arg_value); 299 if (m_option_data.m_repl_lang == eLanguageTypeUnknown) { 300 error.SetErrorStringWithFormat("Unrecognized language name: \"%s\"", 301 arg_value); 302 return error; 303 } 304 } 305 306 if (args.hasArg(OPT_repl)) { 307 m_option_data.m_repl = true; 308 } 309 310 if (auto *arg = args.getLastArg(OPT_repl_)) { 311 m_option_data.m_repl = true; 312 if (auto arg_value = arg->getValue()) 313 m_option_data.m_repl_options = arg_value; 314 } 315 316 // We need to process the options below together as their relative order 317 // matters. 318 for (auto *arg : args.filtered(OPT_source_on_crash, OPT_one_line_on_crash, 319 OPT_source, OPT_source_before_file, 320 OPT_one_line, OPT_one_line_before_file)) { 321 auto arg_value = arg->getValue(); 322 if (arg->getOption().matches(OPT_source_on_crash)) { 323 m_option_data.AddInitialCommand(arg_value, eCommandPlacementAfterCrash, 324 true, error); 325 if (error.Fail()) 326 return error; 327 } 328 329 if (arg->getOption().matches(OPT_one_line_on_crash)) { 330 m_option_data.AddInitialCommand(arg_value, eCommandPlacementAfterCrash, 331 false, error); 332 if (error.Fail()) 333 return error; 334 } 335 336 if (arg->getOption().matches(OPT_source)) { 337 m_option_data.AddInitialCommand(arg_value, eCommandPlacementAfterFile, 338 true, error); 339 if (error.Fail()) 340 return error; 341 } 342 343 if (arg->getOption().matches(OPT_source_before_file)) { 344 m_option_data.AddInitialCommand(arg_value, eCommandPlacementBeforeFile, 345 true, error); 346 if (error.Fail()) 347 return error; 348 } 349 350 if (arg->getOption().matches(OPT_one_line)) { 351 m_option_data.AddInitialCommand(arg_value, eCommandPlacementAfterFile, 352 false, error); 353 if (error.Fail()) 354 return error; 355 } 356 357 if (arg->getOption().matches(OPT_one_line_before_file)) { 358 m_option_data.AddInitialCommand(arg_value, eCommandPlacementBeforeFile, 359 false, error); 360 if (error.Fail()) 361 return error; 362 } 363 } 364 365 if (m_option_data.m_process_name.empty() && 366 m_option_data.m_process_pid == LLDB_INVALID_PROCESS_ID) { 367 368 for (auto *arg : args.filtered(OPT_INPUT)) 369 m_option_data.m_args.push_back(arg->getAsString((args))); 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 // REPL init file or the default file in the user's home directory. 499 SBCommandReturnObject result; 500 sb_interpreter.SourceInitFileInHomeDirectory(result, m_option_data.m_repl); 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 bool go_interactive = true; 591 if ((commands_data != nullptr) && (commands_size != 0u)) { 592 FILE *commands_file = 593 PrepareCommandsForSourcing(commands_data, commands_size); 594 595 if (commands_file == nullptr) { 596 // We should have already printed an error in PrepareCommandsForSourcing. 597 return 1; 598 } 599 600 m_debugger.SetInputFileHandle(commands_file, true); 601 602 // Set the debugger into Sync mode when running the command file. Otherwise 603 // command files that run the target won't run in a sensible way. 604 bool old_async = m_debugger.GetAsync(); 605 m_debugger.SetAsync(false); 606 607 SBCommandInterpreterRunOptions options; 608 options.SetAutoHandleEvents(true); 609 options.SetSpawnThread(false); 610 options.SetStopOnError(true); 611 options.SetStopOnCrash(m_option_data.m_batch); 612 options.SetEchoCommands(!m_option_data.m_source_quietly); 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 return 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 return 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 return sb_interpreter.GetQuitStatus(); 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 *finalize_cmd) { 736 if (SBReproducer::Generate()) { 737 int result = std::system(static_cast<const char *>(finalize_cmd)); 738 (void)result; 739 fflush(stdout); 740 } 741 } 742 743 static void printHelp(LLDBOptTable &table, llvm::StringRef tool_name) { 744 std::string usage_str = tool_name.str() + " [options]"; 745 table.printHelp(llvm::outs(), usage_str.c_str(), "LLDB", false); 746 747 std::string examples = R"___( 748 EXAMPLES: 749 The debugger can be started in several modes. 750 751 Passing an executable as a positional argument prepares lldb to debug the 752 given executable. To disambiguate between arguments passed to lldb and 753 arguments passed to the debugged executable, arguments starting with a - must 754 be passed after --. 755 756 lldb --arch x86_64 /path/to/program program argument -- --arch armv7 757 758 For convenience, passing the executable after -- is also supported. 759 760 lldb --arch x86_64 -- /path/to/program program argument --arch armv7 761 762 Passing one of the attach options causes lldb to immediately attach to the 763 given process. 764 765 lldb -p <pid> 766 lldb -n <process-name> 767 768 Passing --repl starts lldb in REPL mode. 769 770 lldb -r 771 772 Passing --core causes lldb to debug the core file. 773 774 lldb -c /path/to/core 775 776 Command options can be combined with these modes and cause lldb to run the 777 specified commands before or after events, like loading the file or crashing, 778 in the order provided on the command line. 779 780 lldb -O 'settings set stop-disassembly-count 20' -o 'run' -o 'bt' 781 lldb -S /source/before/file -s /source/after/file 782 lldb -K /source/before/crash -k /source/after/crash 783 784 Note: In REPL mode no file is loaded, so commands specified to run after 785 loading the file (via -o or -s) will be ignored.)___"; 786 llvm::outs() << examples << '\n'; 787 } 788 789 static llvm::Optional<int> InitializeReproducer(llvm::StringRef argv0, 790 opt::InputArgList &input_args) { 791 if (auto *finalize_path = input_args.getLastArg(OPT_reproducer_finalize)) { 792 if (const char *error = SBReproducer::Finalize(finalize_path->getValue())) { 793 WithColor::error() << "reproducer finalization failed: " << error << '\n'; 794 return 1; 795 } 796 797 llvm::outs() << "********************\n"; 798 llvm::outs() << "Crash reproducer for "; 799 llvm::outs() << lldb::SBDebugger::GetVersionString() << '\n'; 800 llvm::outs() << '\n'; 801 llvm::outs() << "Reproducer written to '" << SBReproducer::GetPath() 802 << "'\n"; 803 llvm::outs() << '\n'; 804 llvm::outs() << "Before attaching the reproducer to a bug report:\n"; 805 llvm::outs() << " - Look at the directory to ensure you're willing to " 806 "share its content.\n"; 807 llvm::outs() 808 << " - Make sure the reproducer works by replaying the reproducer.\n"; 809 llvm::outs() << '\n'; 810 llvm::outs() << "Replay the reproducer with the following command:\n"; 811 llvm::outs() << argv0 << " -replay " << finalize_path->getValue() << "\n"; 812 llvm::outs() << "********************\n"; 813 return 0; 814 } 815 816 if (auto *replay_path = input_args.getLastArg(OPT_replay)) { 817 SBReplayOptions replay_options; 818 replay_options.SetCheckVersion(!input_args.hasArg(OPT_no_version_check)); 819 replay_options.SetVerify(!input_args.hasArg(OPT_no_verification)); 820 if (const char *error = 821 SBReproducer::Replay(replay_path->getValue(), replay_options)) { 822 WithColor::error() << "reproducer replay failed: " << error << '\n'; 823 return 1; 824 } 825 return 0; 826 } 827 828 bool capture = input_args.hasArg(OPT_capture); 829 bool generate_on_exit = input_args.hasArg(OPT_generate_on_exit); 830 auto *capture_path = input_args.getLastArg(OPT_capture_path); 831 832 if (generate_on_exit && !capture) { 833 WithColor::warning() 834 << "-reproducer-generate-on-exit specified without -capture\n"; 835 } 836 837 if (capture || capture_path) { 838 if (capture_path) { 839 if (!capture) 840 WithColor::warning() << "-capture-path specified without -capture\n"; 841 if (const char *error = SBReproducer::Capture(capture_path->getValue())) { 842 WithColor::error() << "reproducer capture failed: " << error << '\n'; 843 return 1; 844 } 845 } else { 846 const char *error = SBReproducer::Capture(); 847 if (error) { 848 WithColor::error() << "reproducer capture failed: " << error << '\n'; 849 return 1; 850 } 851 } 852 if (generate_on_exit) 853 SBReproducer::SetAutoGenerate(true); 854 855 // Register the reproducer signal handler. 856 if (!input_args.hasArg(OPT_no_generate_on_signal)) { 857 if (const char *reproducer_path = SBReproducer::GetPath()) { 858 static std::string *finalize_cmd = new std::string(argv0); 859 finalize_cmd->append(" --reproducer-finalize '"); 860 finalize_cmd->append(reproducer_path); 861 finalize_cmd->append("'"); 862 llvm::sys::AddSignalHandler(reproducer_handler, 863 const_cast<char *>(finalize_cmd->c_str())); 864 } 865 } 866 } 867 868 return llvm::None; 869 } 870 871 int main(int argc, char const *argv[]) { 872 // Editline uses for example iswprint which is dependent on LC_CTYPE. 873 std::setlocale(LC_ALL, ""); 874 std::setlocale(LC_CTYPE, ""); 875 876 // Setup LLVM signal handlers and make sure we call llvm_shutdown() on 877 // destruction. 878 llvm::InitLLVM IL(argc, argv, /*InstallPipeSignalExitHandler=*/false); 879 880 // Parse arguments. 881 LLDBOptTable T; 882 unsigned MissingArgIndex; 883 unsigned MissingArgCount; 884 ArrayRef<const char *> arg_arr = makeArrayRef(argv + 1, argc - 1); 885 opt::InputArgList input_args = 886 T.ParseArgs(arg_arr, MissingArgIndex, MissingArgCount); 887 llvm::StringRef argv0 = llvm::sys::path::filename(argv[0]); 888 889 if (input_args.hasArg(OPT_help)) { 890 printHelp(T, argv0); 891 return 0; 892 } 893 894 // Check for missing argument error. 895 if (MissingArgCount) { 896 WithColor::error() << "argument to '" 897 << input_args.getArgString(MissingArgIndex) 898 << "' is missing\n"; 899 } 900 // Error out on unknown options. 901 if (input_args.hasArg(OPT_UNKNOWN)) { 902 for (auto *arg : input_args.filtered(OPT_UNKNOWN)) { 903 WithColor::error() << "unknown option: " << arg->getSpelling() << '\n'; 904 } 905 } 906 if (MissingArgCount || input_args.hasArg(OPT_UNKNOWN)) { 907 llvm::errs() << "Use '" << argv0 908 << " --help' for a complete list of options.\n"; 909 return 1; 910 } 911 912 if (auto exit_code = InitializeReproducer(argv[0], input_args)) { 913 return *exit_code; 914 } 915 916 SBError error = SBDebugger::InitializeWithErrorHandling(); 917 if (error.Fail()) { 918 WithColor::error() << "initialization failed: " << error.GetCString() 919 << '\n'; 920 return 1; 921 } 922 SBHostOS::ThreadCreated("<lldb.driver.main-thread>"); 923 924 signal(SIGINT, sigint_handler); 925 #if !defined(_MSC_VER) 926 signal(SIGPIPE, SIG_IGN); 927 signal(SIGWINCH, sigwinch_handler); 928 signal(SIGTSTP, sigtstp_handler); 929 signal(SIGCONT, sigcont_handler); 930 #endif 931 932 int exit_code = 0; 933 // Create a scope for driver so that the driver object will destroy itself 934 // before SBDebugger::Terminate() is called. 935 { 936 Driver driver; 937 938 bool exiting = false; 939 SBError error(driver.ProcessArgs(input_args, exiting)); 940 if (error.Fail()) { 941 exit_code = 1; 942 if (const char *error_cstr = error.GetCString()) 943 WithColor::error() << error_cstr << '\n'; 944 } else if (!exiting) { 945 exit_code = driver.MainLoop(); 946 } 947 } 948 949 SBDebugger::Terminate(); 950 return exit_code; 951 } 952