1 //===-- Driver.cpp ----------------------------------------------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "Driver.h" 10 11 #include "lldb/API/SBCommandInterpreter.h" 12 #include "lldb/API/SBCommandInterpreterRunOptions.h" 13 #include "lldb/API/SBCommandReturnObject.h" 14 #include "lldb/API/SBDebugger.h" 15 #include "lldb/API/SBFile.h" 16 #include "lldb/API/SBHostOS.h" 17 #include "lldb/API/SBLanguageRuntime.h" 18 #include "lldb/API/SBReproducer.h" 19 #include "lldb/API/SBStream.h" 20 #include "lldb/API/SBStringList.h" 21 22 #include "llvm/ADT/StringRef.h" 23 #include "llvm/Support/Format.h" 24 #include "llvm/Support/InitLLVM.h" 25 #include "llvm/Support/Path.h" 26 #include "llvm/Support/Process.h" 27 #include "llvm/Support/Signals.h" 28 #include "llvm/Support/WithColor.h" 29 #include "llvm/Support/raw_ostream.h" 30 31 #include <algorithm> 32 #include <atomic> 33 #include <bitset> 34 #include <csignal> 35 #include <string> 36 #include <thread> 37 #include <utility> 38 39 #include <fcntl.h> 40 #include <limits.h> 41 #include <stdio.h> 42 #include <stdlib.h> 43 #include <string.h> 44 45 // Includes for pipe() 46 #if defined(_WIN32) 47 #include <fcntl.h> 48 #include <io.h> 49 #else 50 #include <unistd.h> 51 #endif 52 53 #if !defined(__APPLE__) 54 #include "llvm/Support/DataTypes.h" 55 #endif 56 57 using namespace lldb; 58 using namespace llvm; 59 60 namespace { 61 enum ID { 62 OPT_INVALID = 0, // This is not an option ID. 63 #define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \ 64 HELPTEXT, METAVAR, VALUES) \ 65 OPT_##ID, 66 #include "Options.inc" 67 #undef OPTION 68 }; 69 70 #define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE; 71 #include "Options.inc" 72 #undef PREFIX 73 74 const opt::OptTable::Info InfoTable[] = { 75 #define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \ 76 HELPTEXT, METAVAR, VALUES) \ 77 { \ 78 PREFIX, NAME, HELPTEXT, \ 79 METAVAR, OPT_##ID, opt::Option::KIND##Class, \ 80 PARAM, FLAGS, OPT_##GROUP, \ 81 OPT_##ALIAS, ALIASARGS, VALUES}, 82 #include "Options.inc" 83 #undef OPTION 84 }; 85 86 class LLDBOptTable : public opt::OptTable { 87 public: 88 LLDBOptTable() : OptTable(InfoTable) {} 89 }; 90 } // namespace 91 92 static void reset_stdin_termios(); 93 static bool g_old_stdin_termios_is_valid = false; 94 static struct termios g_old_stdin_termios; 95 96 static Driver *g_driver = nullptr; 97 98 // In the Driver::MainLoop, we change the terminal settings. This function is 99 // added as an atexit handler to make sure we clean them up. 100 static void reset_stdin_termios() { 101 if (g_old_stdin_termios_is_valid) { 102 g_old_stdin_termios_is_valid = false; 103 ::tcsetattr(STDIN_FILENO, TCSANOW, &g_old_stdin_termios); 104 } 105 } 106 107 Driver::Driver() 108 : SBBroadcaster("Driver"), m_debugger(SBDebugger::Create(false)) { 109 // We want to be able to handle CTRL+D in the terminal to have it terminate 110 // certain input 111 m_debugger.SetCloseInputOnEOF(false); 112 g_driver = this; 113 } 114 115 Driver::~Driver() { g_driver = nullptr; } 116 117 void Driver::OptionData::AddInitialCommand(std::string command, 118 CommandPlacement placement, 119 bool is_file, SBError &error) { 120 std::vector<InitialCmdEntry> *command_set; 121 switch (placement) { 122 case eCommandPlacementBeforeFile: 123 command_set = &(m_initial_commands); 124 break; 125 case eCommandPlacementAfterFile: 126 command_set = &(m_after_file_commands); 127 break; 128 case eCommandPlacementAfterCrash: 129 command_set = &(m_after_crash_commands); 130 break; 131 } 132 133 if (is_file) { 134 SBFileSpec file(command.c_str()); 135 if (file.Exists()) 136 command_set->push_back(InitialCmdEntry(command, is_file)); 137 else if (file.ResolveExecutableLocation()) { 138 char final_path[PATH_MAX]; 139 file.GetPath(final_path, sizeof(final_path)); 140 command_set->push_back(InitialCmdEntry(final_path, is_file)); 141 } else 142 error.SetErrorStringWithFormat( 143 "file specified in --source (-s) option doesn't exist: '%s'", 144 command.c_str()); 145 } else 146 command_set->push_back(InitialCmdEntry(command, is_file)); 147 } 148 149 void Driver::WriteCommandsForSourcing(CommandPlacement placement, 150 SBStream &strm) { 151 std::vector<OptionData::InitialCmdEntry> *command_set; 152 switch (placement) { 153 case eCommandPlacementBeforeFile: 154 command_set = &m_option_data.m_initial_commands; 155 break; 156 case eCommandPlacementAfterFile: 157 command_set = &m_option_data.m_after_file_commands; 158 break; 159 case eCommandPlacementAfterCrash: 160 command_set = &m_option_data.m_after_crash_commands; 161 break; 162 } 163 164 for (const auto &command_entry : *command_set) { 165 const char *command = command_entry.contents.c_str(); 166 if (command_entry.is_file) { 167 bool source_quietly = 168 m_option_data.m_source_quietly || command_entry.source_quietly; 169 strm.Printf("command source -s %i '%s'\n", 170 static_cast<int>(source_quietly), command); 171 } else 172 strm.Printf("%s\n", command); 173 } 174 } 175 176 // Check the arguments that were passed to this program to make sure they are 177 // valid and to get their argument values (if any). Return a boolean value 178 // indicating whether or not to start up the full debugger (i.e. the Command 179 // Interpreter) or not. Return FALSE if the arguments were invalid OR if the 180 // user only wanted help or version information. 181 SBError Driver::ProcessArgs(const opt::InputArgList &args, bool &exiting) { 182 SBError error; 183 184 // This is kind of a pain, but since we make the debugger in the Driver's 185 // constructor, we can't know at that point whether we should read in init 186 // files yet. So we don't read them in in the Driver constructor, then set 187 // the flags back to "read them in" here, and then if we see the "-n" flag, 188 // we'll turn it off again. Finally we have to read them in by hand later in 189 // the main loop. 190 m_debugger.SkipLLDBInitFiles(false); 191 m_debugger.SkipAppInitFiles(false); 192 193 if (args.hasArg(OPT_version)) { 194 m_option_data.m_print_version = true; 195 } 196 197 if (args.hasArg(OPT_python_path)) { 198 m_option_data.m_print_python_path = true; 199 } 200 201 if (args.hasArg(OPT_batch)) { 202 m_option_data.m_batch = true; 203 } 204 205 if (auto *arg = args.getLastArg(OPT_core)) { 206 auto arg_value = arg->getValue(); 207 SBFileSpec file(arg_value); 208 if (!file.Exists()) { 209 error.SetErrorStringWithFormat( 210 "file specified in --core (-c) option doesn't exist: '%s'", 211 arg_value); 212 return error; 213 } 214 m_option_data.m_core_file = arg_value; 215 } 216 217 if (args.hasArg(OPT_editor)) { 218 m_option_data.m_use_external_editor = true; 219 } 220 221 if (args.hasArg(OPT_no_lldbinit)) { 222 m_debugger.SkipLLDBInitFiles(true); 223 m_debugger.SkipAppInitFiles(true); 224 } 225 226 if (args.hasArg(OPT_local_lldbinit)) { 227 lldb::SBDebugger::SetInternalVariable("target.load-cwd-lldbinit", "true", 228 m_debugger.GetInstanceName()); 229 } 230 231 if (args.hasArg(OPT_no_use_colors)) { 232 m_debugger.SetUseColor(false); 233 m_option_data.m_debug_mode = true; 234 } 235 236 if (auto *arg = args.getLastArg(OPT_file)) { 237 auto arg_value = arg->getValue(); 238 SBFileSpec file(arg_value); 239 if (file.Exists()) { 240 m_option_data.m_args.emplace_back(arg_value); 241 } else if (file.ResolveExecutableLocation()) { 242 char path[PATH_MAX]; 243 file.GetPath(path, sizeof(path)); 244 m_option_data.m_args.emplace_back(path); 245 } else { 246 error.SetErrorStringWithFormat( 247 "file specified in --file (-f) option doesn't exist: '%s'", 248 arg_value); 249 return error; 250 } 251 } 252 253 if (auto *arg = args.getLastArg(OPT_arch)) { 254 auto arg_value = arg->getValue(); 255 if (!lldb::SBDebugger::SetDefaultArchitecture(arg_value)) { 256 error.SetErrorStringWithFormat( 257 "invalid architecture in the -a or --arch option: '%s'", arg_value); 258 return error; 259 } 260 } 261 262 if (auto *arg = args.getLastArg(OPT_script_language)) { 263 auto arg_value = arg->getValue(); 264 m_debugger.SetScriptLanguage(m_debugger.GetScriptingLanguage(arg_value)); 265 } 266 267 if (args.hasArg(OPT_source_quietly)) { 268 m_option_data.m_source_quietly = true; 269 } 270 271 if (auto *arg = args.getLastArg(OPT_attach_name)) { 272 auto arg_value = arg->getValue(); 273 m_option_data.m_process_name = arg_value; 274 } 275 276 if (args.hasArg(OPT_wait_for)) { 277 m_option_data.m_wait_for = true; 278 } 279 280 if (auto *arg = args.getLastArg(OPT_attach_pid)) { 281 auto arg_value = arg->getValue(); 282 char *remainder; 283 m_option_data.m_process_pid = strtol(arg_value, &remainder, 0); 284 if (remainder == arg_value || *remainder != '\0') { 285 error.SetErrorStringWithFormat( 286 "Could not convert process PID: \"%s\" into a pid.", arg_value); 287 return error; 288 } 289 } 290 291 if (auto *arg = args.getLastArg(OPT_repl_language)) { 292 auto arg_value = arg->getValue(); 293 m_option_data.m_repl_lang = 294 SBLanguageRuntime::GetLanguageTypeFromString(arg_value); 295 if (m_option_data.m_repl_lang == eLanguageTypeUnknown) { 296 error.SetErrorStringWithFormat("Unrecognized language name: \"%s\"", 297 arg_value); 298 return error; 299 } 300 } 301 302 if (args.hasArg(OPT_repl)) { 303 m_option_data.m_repl = true; 304 } 305 306 if (auto *arg = args.getLastArg(OPT_repl_)) { 307 m_option_data.m_repl = true; 308 if (auto arg_value = arg->getValue()) 309 m_option_data.m_repl_options = arg_value; 310 } 311 312 // We need to process the options below together as their relative order 313 // matters. 314 for (auto *arg : args.filtered(OPT_source_on_crash, OPT_one_line_on_crash, 315 OPT_source, OPT_source_before_file, 316 OPT_one_line, OPT_one_line_before_file)) { 317 auto arg_value = arg->getValue(); 318 if (arg->getOption().matches(OPT_source_on_crash)) { 319 m_option_data.AddInitialCommand(arg_value, eCommandPlacementAfterCrash, 320 true, error); 321 if (error.Fail()) 322 return error; 323 } 324 325 if (arg->getOption().matches(OPT_one_line_on_crash)) { 326 m_option_data.AddInitialCommand(arg_value, eCommandPlacementAfterCrash, 327 false, error); 328 if (error.Fail()) 329 return error; 330 } 331 332 if (arg->getOption().matches(OPT_source)) { 333 m_option_data.AddInitialCommand(arg_value, eCommandPlacementAfterFile, 334 true, error); 335 if (error.Fail()) 336 return error; 337 } 338 339 if (arg->getOption().matches(OPT_source_before_file)) { 340 m_option_data.AddInitialCommand(arg_value, eCommandPlacementBeforeFile, 341 true, error); 342 if (error.Fail()) 343 return error; 344 } 345 346 if (arg->getOption().matches(OPT_one_line)) { 347 m_option_data.AddInitialCommand(arg_value, eCommandPlacementAfterFile, 348 false, error); 349 if (error.Fail()) 350 return error; 351 } 352 353 if (arg->getOption().matches(OPT_one_line_before_file)) { 354 m_option_data.AddInitialCommand(arg_value, eCommandPlacementBeforeFile, 355 false, error); 356 if (error.Fail()) 357 return error; 358 } 359 } 360 361 if (m_option_data.m_process_name.empty() && 362 m_option_data.m_process_pid == LLDB_INVALID_PROCESS_ID) { 363 364 // If the option data args array is empty that means the file was not 365 // specified with -f and we need to get it from the input args. 366 if (m_option_data.m_args.empty()) { 367 if (auto *arg = args.getLastArgNoClaim(OPT_INPUT)) { 368 m_option_data.m_args.push_back(arg->getAsString((args))); 369 } 370 } 371 372 // Any argument following -- is an argument for the inferior. 373 if (auto *arg = args.getLastArgNoClaim(OPT_REM)) { 374 for (auto value : arg->getValues()) 375 m_option_data.m_args.emplace_back(value); 376 } 377 } else if (args.getLastArgNoClaim() != nullptr) { 378 WithColor::warning() << "program arguments are ignored when attaching.\n"; 379 } 380 381 if (m_option_data.m_print_version) { 382 llvm::outs() << lldb::SBDebugger::GetVersionString() << '\n'; 383 exiting = true; 384 return error; 385 } 386 387 if (m_option_data.m_print_python_path) { 388 SBFileSpec python_file_spec = SBHostOS::GetLLDBPythonPath(); 389 if (python_file_spec.IsValid()) { 390 char python_path[PATH_MAX]; 391 size_t num_chars = python_file_spec.GetPath(python_path, PATH_MAX); 392 if (num_chars < PATH_MAX) { 393 llvm::outs() << python_path << '\n'; 394 } else 395 llvm::outs() << "<PATH TOO LONG>\n"; 396 } else 397 llvm::outs() << "<COULD NOT FIND PATH>\n"; 398 exiting = true; 399 return error; 400 } 401 402 return error; 403 } 404 405 static inline int OpenPipe(int fds[2], std::size_t size) { 406 #ifdef _WIN32 407 return _pipe(fds, size, O_BINARY); 408 #else 409 (void)size; 410 return pipe(fds); 411 #endif 412 } 413 414 static ::FILE *PrepareCommandsForSourcing(const char *commands_data, 415 size_t commands_size) { 416 enum PIPES { READ, WRITE }; // Indexes for the read and write fds 417 int fds[2] = {-1, -1}; 418 419 if (OpenPipe(fds, commands_size) != 0) { 420 WithColor::error() 421 << "can't create pipe file descriptors for LLDB commands\n"; 422 return nullptr; 423 } 424 425 ssize_t nrwr = write(fds[WRITE], commands_data, commands_size); 426 if (size_t(nrwr) != commands_size) { 427 WithColor::error() 428 << format( 429 "write(%i, %p, %" PRIu64 430 ") failed (errno = %i) when trying to open LLDB commands pipe", 431 fds[WRITE], static_cast<const void *>(commands_data), 432 static_cast<uint64_t>(commands_size), errno) 433 << '\n'; 434 llvm::sys::Process::SafelyCloseFileDescriptor(fds[READ]); 435 llvm::sys::Process::SafelyCloseFileDescriptor(fds[WRITE]); 436 return nullptr; 437 } 438 439 // Close the write end of the pipe, so that the command interpreter will exit 440 // when it consumes all the data. 441 llvm::sys::Process::SafelyCloseFileDescriptor(fds[WRITE]); 442 443 // Open the read file descriptor as a FILE * that we can return as an input 444 // handle. 445 ::FILE *commands_file = fdopen(fds[READ], "rb"); 446 if (commands_file == nullptr) { 447 WithColor::error() << format("fdopen(%i, \"rb\") failed (errno = %i) " 448 "when trying to open LLDB commands pipe", 449 fds[READ], errno) 450 << '\n'; 451 llvm::sys::Process::SafelyCloseFileDescriptor(fds[READ]); 452 return nullptr; 453 } 454 455 // 'commands_file' now owns the read descriptor. 456 return commands_file; 457 } 458 459 std::string EscapeString(std::string arg) { 460 std::string::size_type pos = 0; 461 while ((pos = arg.find_first_of("\"\\", pos)) != std::string::npos) { 462 arg.insert(pos, 1, '\\'); 463 pos += 2; 464 } 465 return '"' + arg + '"'; 466 } 467 468 int Driver::MainLoop() { 469 if (::tcgetattr(STDIN_FILENO, &g_old_stdin_termios) == 0) { 470 g_old_stdin_termios_is_valid = true; 471 atexit(reset_stdin_termios); 472 } 473 474 #ifndef _MSC_VER 475 // Disabling stdin buffering with MSVC's 2015 CRT exposes a bug in fgets 476 // which causes it to miss newlines depending on whether there have been an 477 // odd or even number of characters. Bug has been reported to MS via Connect. 478 ::setbuf(stdin, nullptr); 479 #endif 480 ::setbuf(stdout, nullptr); 481 482 m_debugger.SetErrorFileHandle(stderr, false); 483 m_debugger.SetOutputFileHandle(stdout, false); 484 // Don't take ownership of STDIN yet... 485 m_debugger.SetInputFileHandle(stdin, false); 486 487 m_debugger.SetUseExternalEditor(m_option_data.m_use_external_editor); 488 489 struct winsize window_size; 490 if ((isatty(STDIN_FILENO) != 0) && 491 ::ioctl(STDIN_FILENO, TIOCGWINSZ, &window_size) == 0) { 492 if (window_size.ws_col > 0) 493 m_debugger.SetTerminalWidth(window_size.ws_col); 494 } 495 496 SBCommandInterpreter sb_interpreter = m_debugger.GetCommandInterpreter(); 497 498 // Before we handle any options from the command line, we parse the 499 // .lldbinit file in the user's home directory. 500 SBCommandReturnObject result; 501 sb_interpreter.SourceInitFileInHomeDirectory(result); 502 if (m_option_data.m_debug_mode) { 503 result.PutError(m_debugger.GetErrorFile()); 504 result.PutOutput(m_debugger.GetOutputFile()); 505 } 506 507 // Source the local .lldbinit file if it exists and we're allowed to source. 508 // Here we want to always print the return object because it contains the 509 // warning and instructions to load local lldbinit files. 510 sb_interpreter.SourceInitFileInCurrentWorkingDirectory(result); 511 result.PutError(m_debugger.GetErrorFile()); 512 result.PutOutput(m_debugger.GetOutputFile()); 513 514 // We allow the user to specify an exit code when calling quit which we will 515 // return when exiting. 516 m_debugger.GetCommandInterpreter().AllowExitCodeOnQuit(true); 517 518 // Now we handle options we got from the command line 519 SBStream commands_stream; 520 521 // First source in the commands specified to be run before the file arguments 522 // are processed. 523 WriteCommandsForSourcing(eCommandPlacementBeforeFile, commands_stream); 524 525 // If we're not in --repl mode, add the commands to process the file 526 // arguments, and the commands specified to run afterwards. 527 if (!m_option_data.m_repl) { 528 const size_t num_args = m_option_data.m_args.size(); 529 if (num_args > 0) { 530 char arch_name[64]; 531 if (lldb::SBDebugger::GetDefaultArchitecture(arch_name, 532 sizeof(arch_name))) 533 commands_stream.Printf("target create --arch=%s %s", arch_name, 534 EscapeString(m_option_data.m_args[0]).c_str()); 535 else 536 commands_stream.Printf("target create %s", 537 EscapeString(m_option_data.m_args[0]).c_str()); 538 539 if (!m_option_data.m_core_file.empty()) { 540 commands_stream.Printf(" --core %s", 541 EscapeString(m_option_data.m_core_file).c_str()); 542 } 543 commands_stream.Printf("\n"); 544 545 if (num_args > 1) { 546 commands_stream.Printf("settings set -- target.run-args "); 547 for (size_t arg_idx = 1; arg_idx < num_args; ++arg_idx) 548 commands_stream.Printf( 549 " %s", EscapeString(m_option_data.m_args[arg_idx]).c_str()); 550 commands_stream.Printf("\n"); 551 } 552 } else if (!m_option_data.m_core_file.empty()) { 553 commands_stream.Printf("target create --core %s\n", 554 EscapeString(m_option_data.m_core_file).c_str()); 555 } else if (!m_option_data.m_process_name.empty()) { 556 commands_stream.Printf( 557 "process attach --name %s", 558 EscapeString(m_option_data.m_process_name).c_str()); 559 560 if (m_option_data.m_wait_for) 561 commands_stream.Printf(" --waitfor"); 562 563 commands_stream.Printf("\n"); 564 565 } else if (LLDB_INVALID_PROCESS_ID != m_option_data.m_process_pid) { 566 commands_stream.Printf("process attach --pid %" PRIu64 "\n", 567 m_option_data.m_process_pid); 568 } 569 570 WriteCommandsForSourcing(eCommandPlacementAfterFile, commands_stream); 571 } else if (!m_option_data.m_after_file_commands.empty()) { 572 // We're in repl mode and after-file-load commands were specified. 573 WithColor::warning() << "commands specified to run after file load (via -o " 574 "or -s) are ignored in REPL mode.\n"; 575 } 576 577 if (m_option_data.m_debug_mode) { 578 result.PutError(m_debugger.GetErrorFile()); 579 result.PutOutput(m_debugger.GetOutputFile()); 580 } 581 582 const bool handle_events = true; 583 const bool spawn_thread = false; 584 585 // Check if we have any data in the commands stream, and if so, save it to a 586 // temp file 587 // so we can then run the command interpreter using the file contents. 588 const char *commands_data = commands_stream.GetData(); 589 const size_t commands_size = commands_stream.GetSize(); 590 591 bool go_interactive = true; 592 if ((commands_data != nullptr) && (commands_size != 0u)) { 593 FILE *commands_file = 594 PrepareCommandsForSourcing(commands_data, commands_size); 595 596 if (commands_file == nullptr) { 597 // We should have already printed an error in PrepareCommandsForSourcing. 598 exit(1); 599 } 600 601 m_debugger.SetInputFileHandle(commands_file, true); 602 603 // Set the debugger into Sync mode when running the command file. Otherwise 604 // command files that run the target won't run in a sensible way. 605 bool old_async = m_debugger.GetAsync(); 606 m_debugger.SetAsync(false); 607 608 SBCommandInterpreterRunOptions options; 609 options.SetAutoHandleEvents(true); 610 options.SetSpawnThread(false); 611 options.SetStopOnError(true); 612 options.SetStopOnCrash(m_option_data.m_batch); 613 614 SBCommandInterpreterRunResult results = 615 m_debugger.RunCommandInterpreter(options); 616 if (results.GetResult() == lldb::eCommandInterpreterResultQuitRequested) 617 go_interactive = false; 618 if (m_option_data.m_batch && 619 results.GetResult() != lldb::eCommandInterpreterResultInferiorCrash) 620 go_interactive = false; 621 622 if (m_option_data.m_batch && 623 results.GetResult() == lldb::eCommandInterpreterResultInferiorCrash && 624 !m_option_data.m_after_crash_commands.empty()) { 625 SBStream crash_commands_stream; 626 WriteCommandsForSourcing(eCommandPlacementAfterCrash, 627 crash_commands_stream); 628 const char *crash_commands_data = crash_commands_stream.GetData(); 629 const size_t crash_commands_size = crash_commands_stream.GetSize(); 630 commands_file = 631 PrepareCommandsForSourcing(crash_commands_data, crash_commands_size); 632 if (commands_file != nullptr) { 633 m_debugger.SetInputFileHandle(commands_file, true); 634 SBCommandInterpreterRunResult local_results = 635 m_debugger.RunCommandInterpreter(options); 636 if (local_results.GetResult() == 637 lldb::eCommandInterpreterResultQuitRequested) 638 go_interactive = false; 639 } 640 } 641 m_debugger.SetAsync(old_async); 642 } 643 644 // Now set the input file handle to STDIN and run the command interpreter 645 // again in interactive mode or repl mode and let the debugger take ownership 646 // of stdin. 647 if (go_interactive) { 648 m_debugger.SetInputFileHandle(stdin, true); 649 650 if (m_option_data.m_repl) { 651 const char *repl_options = nullptr; 652 if (!m_option_data.m_repl_options.empty()) 653 repl_options = m_option_data.m_repl_options.c_str(); 654 SBError error( 655 m_debugger.RunREPL(m_option_data.m_repl_lang, repl_options)); 656 if (error.Fail()) { 657 const char *error_cstr = error.GetCString(); 658 if ((error_cstr != nullptr) && (error_cstr[0] != 0)) 659 WithColor::error() << error_cstr << '\n'; 660 else 661 WithColor::error() << error.GetError() << '\n'; 662 } 663 } else { 664 m_debugger.RunCommandInterpreter(handle_events, spawn_thread); 665 } 666 } 667 668 reset_stdin_termios(); 669 fclose(stdin); 670 671 int exit_code = sb_interpreter.GetQuitStatus(); 672 SBDebugger::Destroy(m_debugger); 673 return exit_code; 674 } 675 676 void Driver::ResizeWindow(unsigned short col) { 677 GetDebugger().SetTerminalWidth(col); 678 } 679 680 void sigwinch_handler(int signo) { 681 struct winsize window_size; 682 if ((isatty(STDIN_FILENO) != 0) && 683 ::ioctl(STDIN_FILENO, TIOCGWINSZ, &window_size) == 0) { 684 if ((window_size.ws_col > 0) && g_driver != nullptr) { 685 g_driver->ResizeWindow(window_size.ws_col); 686 } 687 } 688 } 689 690 void sigint_handler(int signo) { 691 #ifdef _WIN32 // Restore handler as it is not persistent on Windows 692 signal(SIGINT, sigint_handler); 693 #endif 694 static std::atomic_flag g_interrupt_sent = ATOMIC_FLAG_INIT; 695 if (g_driver != nullptr) { 696 if (!g_interrupt_sent.test_and_set()) { 697 g_driver->GetDebugger().DispatchInputInterrupt(); 698 g_interrupt_sent.clear(); 699 return; 700 } 701 } 702 703 _exit(signo); 704 } 705 706 void sigtstp_handler(int signo) { 707 if (g_driver != nullptr) 708 g_driver->GetDebugger().SaveInputTerminalState(); 709 710 signal(signo, SIG_DFL); 711 kill(getpid(), signo); 712 signal(signo, sigtstp_handler); 713 } 714 715 void sigcont_handler(int signo) { 716 if (g_driver != nullptr) 717 g_driver->GetDebugger().RestoreInputTerminalState(); 718 719 signal(signo, SIG_DFL); 720 kill(getpid(), signo); 721 signal(signo, sigcont_handler); 722 } 723 724 void reproducer_handler(void *argv0) { 725 if (SBReproducer::Generate()) { 726 auto exe = static_cast<const char *>(argv0); 727 llvm::outs() << "********************\n"; 728 llvm::outs() << "Crash reproducer for "; 729 llvm::outs() << lldb::SBDebugger::GetVersionString() << '\n'; 730 llvm::outs() << '\n'; 731 llvm::outs() << "Reproducer written to '" << SBReproducer::GetPath() 732 << "'\n"; 733 llvm::outs() << '\n'; 734 llvm::outs() << "Before attaching the reproducer to a bug report:\n"; 735 llvm::outs() << " - Look at the directory to ensure you're willing to " 736 "share its content.\n"; 737 llvm::outs() 738 << " - Make sure the reproducer works by replaying the reproducer.\n"; 739 llvm::outs() << '\n'; 740 llvm::outs() << "Replay the reproducer with the following command:\n"; 741 llvm::outs() << exe << " -replay " << SBReproducer::GetPath() << "\n"; 742 llvm::outs() << "********************\n"; 743 } 744 } 745 746 static void printHelp(LLDBOptTable &table, llvm::StringRef tool_name) { 747 std::string usage_str = tool_name.str() + " [options]"; 748 table.PrintHelp(llvm::outs(), usage_str.c_str(), "LLDB", false); 749 750 std::string examples = R"___( 751 EXAMPLES: 752 The debugger can be started in several modes. 753 754 Passing an executable as a positional argument prepares lldb to debug the 755 given executable. Arguments passed after -- are considered arguments to the 756 debugged executable. 757 758 lldb --arch x86_64 /path/to/program -- --arch arvm7 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(opt::InputArgList &input_args) { 788 if (auto *replay_path = input_args.getLastArg(OPT_replay)) { 789 const bool skip_version_check = input_args.hasArg(OPT_skip_version_check); 790 if (const char *error = 791 SBReproducer::Replay(replay_path->getValue(), skip_version_check)) { 792 WithColor::error() << "reproducer replay failed: " << error << '\n'; 793 return 1; 794 } 795 return 0; 796 } 797 798 bool capture = input_args.hasArg(OPT_capture); 799 bool auto_generate = input_args.hasArg(OPT_auto_generate); 800 auto *capture_path = input_args.getLastArg(OPT_capture_path); 801 802 if (auto_generate && !capture) { 803 WithColor::warning() 804 << "-reproducer-auto-generate specified without -capture\n"; 805 } 806 807 if (capture || capture_path) { 808 if (capture_path) { 809 if (!capture) 810 WithColor::warning() << "-capture-path specified without -capture\n"; 811 if (const char *error = SBReproducer::Capture(capture_path->getValue())) { 812 WithColor::error() << "reproducer capture failed: " << error << '\n'; 813 return 1; 814 } 815 } else { 816 const char *error = SBReproducer::Capture(); 817 if (error) { 818 WithColor::error() << "reproducer capture failed: " << error << '\n'; 819 return 1; 820 } 821 } 822 if (auto_generate) 823 SBReproducer::SetAutoGenerate(true); 824 } 825 826 return llvm::None; 827 } 828 829 int main(int argc, char const *argv[]) { 830 // Setup LLVM signal handlers and make sure we call llvm_shutdown() on 831 // destruction. 832 llvm::InitLLVM IL(argc, argv, /*InstallPipeSignalExitHandler=*/false); 833 834 // Parse arguments. 835 LLDBOptTable T; 836 unsigned MAI; 837 unsigned MAC; 838 ArrayRef<const char *> arg_arr = makeArrayRef(argv + 1, argc - 1); 839 opt::InputArgList input_args = T.ParseArgs(arg_arr, MAI, MAC); 840 841 if (input_args.hasArg(OPT_help)) { 842 printHelp(T, llvm::sys::path::filename(argv[0])); 843 return 0; 844 } 845 846 for (auto *arg : input_args.filtered(OPT_UNKNOWN)) { 847 WithColor::warning() << "ignoring unknown option: " << arg->getSpelling() 848 << '\n'; 849 } 850 851 if (auto exit_code = InitializeReproducer(input_args)) { 852 return *exit_code; 853 } 854 855 // Register the reproducer signal handler. 856 llvm::sys::AddSignalHandler(reproducer_handler, const_cast<char *>(argv[0])); 857 858 SBError error = SBDebugger::InitializeWithErrorHandling(); 859 if (error.Fail()) { 860 WithColor::error() << "initialization failed: " << error.GetCString() 861 << '\n'; 862 return 1; 863 } 864 SBHostOS::ThreadCreated("<lldb.driver.main-thread>"); 865 866 signal(SIGINT, sigint_handler); 867 #if !defined(_MSC_VER) 868 signal(SIGPIPE, SIG_IGN); 869 signal(SIGWINCH, sigwinch_handler); 870 signal(SIGTSTP, sigtstp_handler); 871 signal(SIGCONT, sigcont_handler); 872 #endif 873 874 int exit_code = 0; 875 // Create a scope for driver so that the driver object will destroy itself 876 // before SBDebugger::Terminate() is called. 877 { 878 Driver driver; 879 880 bool exiting = false; 881 SBError error(driver.ProcessArgs(input_args, exiting)); 882 if (error.Fail()) { 883 exit_code = 1; 884 if (const char *error_cstr = error.GetCString()) 885 WithColor::error() << error_cstr << '\n'; 886 } else if (!exiting) { 887 exit_code = driver.MainLoop(); 888 } 889 } 890 891 SBDebugger::Terminate(); 892 return exit_code; 893 } 894