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 for (auto *arg : args.filtered(OPT_INPUT)) 365 m_option_data.m_args.push_back(arg->getAsString((args))); 366 367 // Any argument following -- is an argument for the inferior. 368 if (auto *arg = args.getLastArgNoClaim(OPT_REM)) { 369 for (auto value : arg->getValues()) 370 m_option_data.m_args.emplace_back(value); 371 } 372 } else if (args.getLastArgNoClaim() != nullptr) { 373 WithColor::warning() << "program arguments are ignored when attaching.\n"; 374 } 375 376 if (m_option_data.m_print_version) { 377 llvm::outs() << lldb::SBDebugger::GetVersionString() << '\n'; 378 exiting = true; 379 return error; 380 } 381 382 if (m_option_data.m_print_python_path) { 383 SBFileSpec python_file_spec = SBHostOS::GetLLDBPythonPath(); 384 if (python_file_spec.IsValid()) { 385 char python_path[PATH_MAX]; 386 size_t num_chars = python_file_spec.GetPath(python_path, PATH_MAX); 387 if (num_chars < PATH_MAX) { 388 llvm::outs() << python_path << '\n'; 389 } else 390 llvm::outs() << "<PATH TOO LONG>\n"; 391 } else 392 llvm::outs() << "<COULD NOT FIND PATH>\n"; 393 exiting = true; 394 return error; 395 } 396 397 return error; 398 } 399 400 static inline int OpenPipe(int fds[2], std::size_t size) { 401 #ifdef _WIN32 402 return _pipe(fds, size, O_BINARY); 403 #else 404 (void)size; 405 return pipe(fds); 406 #endif 407 } 408 409 static ::FILE *PrepareCommandsForSourcing(const char *commands_data, 410 size_t commands_size) { 411 enum PIPES { READ, WRITE }; // Indexes for the read and write fds 412 int fds[2] = {-1, -1}; 413 414 if (OpenPipe(fds, commands_size) != 0) { 415 WithColor::error() 416 << "can't create pipe file descriptors for LLDB commands\n"; 417 return nullptr; 418 } 419 420 ssize_t nrwr = write(fds[WRITE], commands_data, commands_size); 421 if (size_t(nrwr) != commands_size) { 422 WithColor::error() 423 << format( 424 "write(%i, %p, %" PRIu64 425 ") failed (errno = %i) when trying to open LLDB commands pipe", 426 fds[WRITE], static_cast<const void *>(commands_data), 427 static_cast<uint64_t>(commands_size), errno) 428 << '\n'; 429 llvm::sys::Process::SafelyCloseFileDescriptor(fds[READ]); 430 llvm::sys::Process::SafelyCloseFileDescriptor(fds[WRITE]); 431 return nullptr; 432 } 433 434 // Close the write end of the pipe, so that the command interpreter will exit 435 // when it consumes all the data. 436 llvm::sys::Process::SafelyCloseFileDescriptor(fds[WRITE]); 437 438 // Open the read file descriptor as a FILE * that we can return as an input 439 // handle. 440 ::FILE *commands_file = fdopen(fds[READ], "rb"); 441 if (commands_file == nullptr) { 442 WithColor::error() << format("fdopen(%i, \"rb\") failed (errno = %i) " 443 "when trying to open LLDB commands pipe", 444 fds[READ], errno) 445 << '\n'; 446 llvm::sys::Process::SafelyCloseFileDescriptor(fds[READ]); 447 return nullptr; 448 } 449 450 // 'commands_file' now owns the read descriptor. 451 return commands_file; 452 } 453 454 std::string EscapeString(std::string arg) { 455 std::string::size_type pos = 0; 456 while ((pos = arg.find_first_of("\"\\", pos)) != std::string::npos) { 457 arg.insert(pos, 1, '\\'); 458 pos += 2; 459 } 460 return '"' + arg + '"'; 461 } 462 463 int Driver::MainLoop() { 464 if (::tcgetattr(STDIN_FILENO, &g_old_stdin_termios) == 0) { 465 g_old_stdin_termios_is_valid = true; 466 atexit(reset_stdin_termios); 467 } 468 469 #ifndef _MSC_VER 470 // Disabling stdin buffering with MSVC's 2015 CRT exposes a bug in fgets 471 // which causes it to miss newlines depending on whether there have been an 472 // odd or even number of characters. Bug has been reported to MS via Connect. 473 ::setbuf(stdin, nullptr); 474 #endif 475 ::setbuf(stdout, nullptr); 476 477 m_debugger.SetErrorFileHandle(stderr, false); 478 m_debugger.SetOutputFileHandle(stdout, false); 479 // Don't take ownership of STDIN yet... 480 m_debugger.SetInputFileHandle(stdin, false); 481 482 m_debugger.SetUseExternalEditor(m_option_data.m_use_external_editor); 483 484 struct winsize window_size; 485 if ((isatty(STDIN_FILENO) != 0) && 486 ::ioctl(STDIN_FILENO, TIOCGWINSZ, &window_size) == 0) { 487 if (window_size.ws_col > 0) 488 m_debugger.SetTerminalWidth(window_size.ws_col); 489 } 490 491 SBCommandInterpreter sb_interpreter = m_debugger.GetCommandInterpreter(); 492 493 // Before we handle any options from the command line, we parse the 494 // .lldbinit file in the user's home directory. 495 SBCommandReturnObject result; 496 sb_interpreter.SourceInitFileInHomeDirectory(result); 497 if (m_option_data.m_debug_mode) { 498 result.PutError(m_debugger.GetErrorFile()); 499 result.PutOutput(m_debugger.GetOutputFile()); 500 } 501 502 // Source the local .lldbinit file if it exists and we're allowed to source. 503 // Here we want to always print the return object because it contains the 504 // warning and instructions to load local lldbinit files. 505 sb_interpreter.SourceInitFileInCurrentWorkingDirectory(result); 506 result.PutError(m_debugger.GetErrorFile()); 507 result.PutOutput(m_debugger.GetOutputFile()); 508 509 // We allow the user to specify an exit code when calling quit which we will 510 // return when exiting. 511 m_debugger.GetCommandInterpreter().AllowExitCodeOnQuit(true); 512 513 // Now we handle options we got from the command line 514 SBStream commands_stream; 515 516 // First source in the commands specified to be run before the file arguments 517 // are processed. 518 WriteCommandsForSourcing(eCommandPlacementBeforeFile, commands_stream); 519 520 // If we're not in --repl mode, add the commands to process the file 521 // arguments, and the commands specified to run afterwards. 522 if (!m_option_data.m_repl) { 523 const size_t num_args = m_option_data.m_args.size(); 524 if (num_args > 0) { 525 char arch_name[64]; 526 if (lldb::SBDebugger::GetDefaultArchitecture(arch_name, 527 sizeof(arch_name))) 528 commands_stream.Printf("target create --arch=%s %s", arch_name, 529 EscapeString(m_option_data.m_args[0]).c_str()); 530 else 531 commands_stream.Printf("target create %s", 532 EscapeString(m_option_data.m_args[0]).c_str()); 533 534 if (!m_option_data.m_core_file.empty()) { 535 commands_stream.Printf(" --core %s", 536 EscapeString(m_option_data.m_core_file).c_str()); 537 } 538 commands_stream.Printf("\n"); 539 540 if (num_args > 1) { 541 commands_stream.Printf("settings set -- target.run-args "); 542 for (size_t arg_idx = 1; arg_idx < num_args; ++arg_idx) 543 commands_stream.Printf( 544 " %s", EscapeString(m_option_data.m_args[arg_idx]).c_str()); 545 commands_stream.Printf("\n"); 546 } 547 } else if (!m_option_data.m_core_file.empty()) { 548 commands_stream.Printf("target create --core %s\n", 549 EscapeString(m_option_data.m_core_file).c_str()); 550 } else if (!m_option_data.m_process_name.empty()) { 551 commands_stream.Printf( 552 "process attach --name %s", 553 EscapeString(m_option_data.m_process_name).c_str()); 554 555 if (m_option_data.m_wait_for) 556 commands_stream.Printf(" --waitfor"); 557 558 commands_stream.Printf("\n"); 559 560 } else if (LLDB_INVALID_PROCESS_ID != m_option_data.m_process_pid) { 561 commands_stream.Printf("process attach --pid %" PRIu64 "\n", 562 m_option_data.m_process_pid); 563 } 564 565 WriteCommandsForSourcing(eCommandPlacementAfterFile, commands_stream); 566 } else if (!m_option_data.m_after_file_commands.empty()) { 567 // We're in repl mode and after-file-load commands were specified. 568 WithColor::warning() << "commands specified to run after file load (via -o " 569 "or -s) are ignored in REPL mode.\n"; 570 } 571 572 if (m_option_data.m_debug_mode) { 573 result.PutError(m_debugger.GetErrorFile()); 574 result.PutOutput(m_debugger.GetOutputFile()); 575 } 576 577 const bool handle_events = true; 578 const bool spawn_thread = false; 579 580 // Check if we have any data in the commands stream, and if so, save it to a 581 // temp file 582 // so we can then run the command interpreter using the file contents. 583 const char *commands_data = commands_stream.GetData(); 584 const size_t commands_size = commands_stream.GetSize(); 585 586 bool go_interactive = true; 587 if ((commands_data != nullptr) && (commands_size != 0u)) { 588 FILE *commands_file = 589 PrepareCommandsForSourcing(commands_data, commands_size); 590 591 if (commands_file == nullptr) { 592 // We should have already printed an error in PrepareCommandsForSourcing. 593 exit(1); 594 } 595 596 m_debugger.SetInputFileHandle(commands_file, true); 597 598 // Set the debugger into Sync mode when running the command file. Otherwise 599 // command files that run the target won't run in a sensible way. 600 bool old_async = m_debugger.GetAsync(); 601 m_debugger.SetAsync(false); 602 603 SBCommandInterpreterRunOptions options; 604 options.SetAutoHandleEvents(true); 605 options.SetSpawnThread(false); 606 options.SetStopOnError(true); 607 options.SetStopOnCrash(m_option_data.m_batch); 608 609 SBCommandInterpreterRunResult results = 610 m_debugger.RunCommandInterpreter(options); 611 if (results.GetResult() == lldb::eCommandInterpreterResultQuitRequested) 612 go_interactive = false; 613 if (m_option_data.m_batch && 614 results.GetResult() != lldb::eCommandInterpreterResultInferiorCrash) 615 go_interactive = false; 616 617 // When running in batch mode and stopped because of an error, exit with a 618 // non-zero exit status. 619 if (m_option_data.m_batch && 620 results.GetResult() == lldb::eCommandInterpreterResultCommandError) 621 exit(1); 622 623 if (m_option_data.m_batch && 624 results.GetResult() == lldb::eCommandInterpreterResultInferiorCrash && 625 !m_option_data.m_after_crash_commands.empty()) { 626 SBStream crash_commands_stream; 627 WriteCommandsForSourcing(eCommandPlacementAfterCrash, 628 crash_commands_stream); 629 const char *crash_commands_data = crash_commands_stream.GetData(); 630 const size_t crash_commands_size = crash_commands_stream.GetSize(); 631 commands_file = 632 PrepareCommandsForSourcing(crash_commands_data, crash_commands_size); 633 if (commands_file != nullptr) { 634 m_debugger.SetInputFileHandle(commands_file, true); 635 SBCommandInterpreterRunResult local_results = 636 m_debugger.RunCommandInterpreter(options); 637 if (local_results.GetResult() == 638 lldb::eCommandInterpreterResultQuitRequested) 639 go_interactive = false; 640 641 // When running in batch mode and an error occurred while sourcing 642 // the crash commands, exit with a non-zero exit status. 643 if (m_option_data.m_batch && 644 local_results.GetResult() == 645 lldb::eCommandInterpreterResultCommandError) 646 exit(1); 647 } 648 } 649 m_debugger.SetAsync(old_async); 650 } 651 652 // Now set the input file handle to STDIN and run the command interpreter 653 // again in interactive mode or repl mode and let the debugger take ownership 654 // of stdin. 655 if (go_interactive) { 656 m_debugger.SetInputFileHandle(stdin, true); 657 658 if (m_option_data.m_repl) { 659 const char *repl_options = nullptr; 660 if (!m_option_data.m_repl_options.empty()) 661 repl_options = m_option_data.m_repl_options.c_str(); 662 SBError error( 663 m_debugger.RunREPL(m_option_data.m_repl_lang, repl_options)); 664 if (error.Fail()) { 665 const char *error_cstr = error.GetCString(); 666 if ((error_cstr != nullptr) && (error_cstr[0] != 0)) 667 WithColor::error() << error_cstr << '\n'; 668 else 669 WithColor::error() << error.GetError() << '\n'; 670 } 671 } else { 672 m_debugger.RunCommandInterpreter(handle_events, spawn_thread); 673 } 674 } 675 676 reset_stdin_termios(); 677 fclose(stdin); 678 679 int exit_code = sb_interpreter.GetQuitStatus(); 680 SBDebugger::Destroy(m_debugger); 681 return exit_code; 682 } 683 684 void Driver::ResizeWindow(unsigned short col) { 685 GetDebugger().SetTerminalWidth(col); 686 } 687 688 void sigwinch_handler(int signo) { 689 struct winsize window_size; 690 if ((isatty(STDIN_FILENO) != 0) && 691 ::ioctl(STDIN_FILENO, TIOCGWINSZ, &window_size) == 0) { 692 if ((window_size.ws_col > 0) && g_driver != nullptr) { 693 g_driver->ResizeWindow(window_size.ws_col); 694 } 695 } 696 } 697 698 void sigint_handler(int signo) { 699 #ifdef _WIN32 // Restore handler as it is not persistent on Windows 700 signal(SIGINT, sigint_handler); 701 #endif 702 static std::atomic_flag g_interrupt_sent = ATOMIC_FLAG_INIT; 703 if (g_driver != nullptr) { 704 if (!g_interrupt_sent.test_and_set()) { 705 g_driver->GetDebugger().DispatchInputInterrupt(); 706 g_interrupt_sent.clear(); 707 return; 708 } 709 } 710 711 _exit(signo); 712 } 713 714 void sigtstp_handler(int signo) { 715 if (g_driver != nullptr) 716 g_driver->GetDebugger().SaveInputTerminalState(); 717 718 signal(signo, SIG_DFL); 719 kill(getpid(), signo); 720 signal(signo, sigtstp_handler); 721 } 722 723 void sigcont_handler(int signo) { 724 if (g_driver != nullptr) 725 g_driver->GetDebugger().RestoreInputTerminalState(); 726 727 signal(signo, SIG_DFL); 728 kill(getpid(), signo); 729 signal(signo, sigcont_handler); 730 } 731 732 void reproducer_handler(void *argv0) { 733 if (SBReproducer::Generate()) { 734 auto exe = static_cast<const char *>(argv0); 735 llvm::outs() << "********************\n"; 736 llvm::outs() << "Crash reproducer for "; 737 llvm::outs() << lldb::SBDebugger::GetVersionString() << '\n'; 738 llvm::outs() << '\n'; 739 llvm::outs() << "Reproducer written to '" << SBReproducer::GetPath() 740 << "'\n"; 741 llvm::outs() << '\n'; 742 llvm::outs() << "Before attaching the reproducer to a bug report:\n"; 743 llvm::outs() << " - Look at the directory to ensure you're willing to " 744 "share its content.\n"; 745 llvm::outs() 746 << " - Make sure the reproducer works by replaying the reproducer.\n"; 747 llvm::outs() << '\n'; 748 llvm::outs() << "Replay the reproducer with the following command:\n"; 749 llvm::outs() << exe << " -replay " << SBReproducer::GetPath() << "\n"; 750 llvm::outs() << "********************\n"; 751 } 752 } 753 754 static void printHelp(LLDBOptTable &table, llvm::StringRef tool_name) { 755 std::string usage_str = tool_name.str() + " [options]"; 756 table.PrintHelp(llvm::outs(), usage_str.c_str(), "LLDB", false); 757 758 std::string examples = R"___( 759 EXAMPLES: 760 The debugger can be started in several modes. 761 762 Passing an executable as a positional argument prepares lldb to debug the 763 given executable. To disambiguate between arguments passed to lldb and 764 arguments passed to the debugged executable, arguments starting with a - must 765 be passed after --. 766 767 lldb --arch x86_64 /path/to/program program argument -- --arch arvm7 768 769 For convenience, passing the executable after -- is also supported. 770 771 lldb --arch x86_64 -- /path/to/program program argument --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(llvm::StringRef argv0, 801 opt::InputArgList &input_args) { 802 if (auto *replay_path = input_args.getLastArg(OPT_replay)) { 803 const bool no_version_check = input_args.hasArg(OPT_no_version_check); 804 if (const char *error = 805 SBReproducer::Replay(replay_path->getValue(), no_version_check)) { 806 WithColor::error() << "reproducer replay failed: " << error << '\n'; 807 return 1; 808 } 809 return 0; 810 } 811 812 bool capture = input_args.hasArg(OPT_capture); 813 bool generate_on_exit = input_args.hasArg(OPT_generate_on_exit); 814 auto *capture_path = input_args.getLastArg(OPT_capture_path); 815 816 if (generate_on_exit && !capture) { 817 WithColor::warning() 818 << "-reproducer-generate-on-exit specified without -capture\n"; 819 } 820 821 if (capture || capture_path) { 822 // Register the reproducer signal handler. 823 if (!input_args.hasArg(OPT_no_generate_on_signal)) { 824 llvm::sys::AddSignalHandler(reproducer_handler, 825 const_cast<char *>(argv0.data())); 826 } 827 828 if (capture_path) { 829 if (!capture) 830 WithColor::warning() << "-capture-path specified without -capture\n"; 831 if (const char *error = SBReproducer::Capture(capture_path->getValue())) { 832 WithColor::error() << "reproducer capture failed: " << error << '\n'; 833 return 1; 834 } 835 } else { 836 const char *error = SBReproducer::Capture(); 837 if (error) { 838 WithColor::error() << "reproducer capture failed: " << error << '\n'; 839 return 1; 840 } 841 } 842 if (generate_on_exit) 843 SBReproducer::SetAutoGenerate(true); 844 } 845 846 return llvm::None; 847 } 848 849 int main(int argc, char const *argv[]) { 850 // Setup LLVM signal handlers and make sure we call llvm_shutdown() on 851 // destruction. 852 llvm::InitLLVM IL(argc, argv, /*InstallPipeSignalExitHandler=*/false); 853 854 // Parse arguments. 855 LLDBOptTable T; 856 unsigned MAI; 857 unsigned MAC; 858 ArrayRef<const char *> arg_arr = makeArrayRef(argv + 1, argc - 1); 859 opt::InputArgList input_args = T.ParseArgs(arg_arr, MAI, MAC); 860 llvm::StringRef argv0 = llvm::sys::path::filename(argv[0]); 861 862 if (input_args.hasArg(OPT_help)) { 863 printHelp(T, argv0); 864 return 0; 865 } 866 867 // Error out on unknown options. 868 if (input_args.hasArg(OPT_UNKNOWN)) { 869 for (auto *arg : input_args.filtered(OPT_UNKNOWN)) { 870 WithColor::error() << "unknown option: " << arg->getSpelling() << '\n'; 871 } 872 llvm::errs() << "Use '" << argv0 873 << " --help' for a complete list of options.\n"; 874 return 1; 875 } 876 877 if (auto exit_code = InitializeReproducer(argv[0], input_args)) { 878 return *exit_code; 879 } 880 881 SBError error = SBDebugger::InitializeWithErrorHandling(); 882 if (error.Fail()) { 883 WithColor::error() << "initialization failed: " << error.GetCString() 884 << '\n'; 885 return 1; 886 } 887 SBHostOS::ThreadCreated("<lldb.driver.main-thread>"); 888 889 signal(SIGINT, sigint_handler); 890 #if !defined(_MSC_VER) 891 signal(SIGPIPE, SIG_IGN); 892 signal(SIGWINCH, sigwinch_handler); 893 signal(SIGTSTP, sigtstp_handler); 894 signal(SIGCONT, sigcont_handler); 895 #endif 896 897 int exit_code = 0; 898 // Create a scope for driver so that the driver object will destroy itself 899 // before SBDebugger::Terminate() is called. 900 { 901 Driver driver; 902 903 bool exiting = false; 904 SBError error(driver.ProcessArgs(input_args, exiting)); 905 if (error.Fail()) { 906 exit_code = 1; 907 if (const char *error_cstr = error.GetCString()) 908 WithColor::error() << error_cstr << '\n'; 909 } else if (!exiting) { 910 exit_code = driver.MainLoop(); 911 } 912 } 913 914 SBDebugger::Terminate(); 915 return exit_code; 916 } 917