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 613 SBCommandInterpreterRunResult results = 614 m_debugger.RunCommandInterpreter(options); 615 if (results.GetResult() == lldb::eCommandInterpreterResultQuitRequested) 616 go_interactive = false; 617 if (m_option_data.m_batch && 618 results.GetResult() != lldb::eCommandInterpreterResultInferiorCrash) 619 go_interactive = false; 620 621 // When running in batch mode and stopped because of an error, exit with a 622 // non-zero exit status. 623 if (m_option_data.m_batch && 624 results.GetResult() == lldb::eCommandInterpreterResultCommandError) 625 return 1; 626 627 if (m_option_data.m_batch && 628 results.GetResult() == lldb::eCommandInterpreterResultInferiorCrash && 629 !m_option_data.m_after_crash_commands.empty()) { 630 SBStream crash_commands_stream; 631 WriteCommandsForSourcing(eCommandPlacementAfterCrash, 632 crash_commands_stream); 633 const char *crash_commands_data = crash_commands_stream.GetData(); 634 const size_t crash_commands_size = crash_commands_stream.GetSize(); 635 commands_file = 636 PrepareCommandsForSourcing(crash_commands_data, crash_commands_size); 637 if (commands_file != nullptr) { 638 m_debugger.SetInputFileHandle(commands_file, true); 639 SBCommandInterpreterRunResult local_results = 640 m_debugger.RunCommandInterpreter(options); 641 if (local_results.GetResult() == 642 lldb::eCommandInterpreterResultQuitRequested) 643 go_interactive = false; 644 645 // When running in batch mode and an error occurred while sourcing 646 // the crash commands, exit with a non-zero exit status. 647 if (m_option_data.m_batch && 648 local_results.GetResult() == 649 lldb::eCommandInterpreterResultCommandError) 650 return 1; 651 } 652 } 653 m_debugger.SetAsync(old_async); 654 } 655 656 // Now set the input file handle to STDIN and run the command interpreter 657 // again in interactive mode or repl mode and let the debugger take ownership 658 // of stdin. 659 if (go_interactive) { 660 m_debugger.SetInputFileHandle(stdin, true); 661 662 if (m_option_data.m_repl) { 663 const char *repl_options = nullptr; 664 if (!m_option_data.m_repl_options.empty()) 665 repl_options = m_option_data.m_repl_options.c_str(); 666 SBError error( 667 m_debugger.RunREPL(m_option_data.m_repl_lang, repl_options)); 668 if (error.Fail()) { 669 const char *error_cstr = error.GetCString(); 670 if ((error_cstr != nullptr) && (error_cstr[0] != 0)) 671 WithColor::error() << error_cstr << '\n'; 672 else 673 WithColor::error() << error.GetError() << '\n'; 674 } 675 } else { 676 m_debugger.RunCommandInterpreter(handle_events, spawn_thread); 677 } 678 } 679 680 reset_stdin_termios(); 681 fclose(stdin); 682 683 return sb_interpreter.GetQuitStatus(); 684 } 685 686 void Driver::ResizeWindow(unsigned short col) { 687 GetDebugger().SetTerminalWidth(col); 688 } 689 690 void sigwinch_handler(int signo) { 691 struct winsize window_size; 692 if ((isatty(STDIN_FILENO) != 0) && 693 ::ioctl(STDIN_FILENO, TIOCGWINSZ, &window_size) == 0) { 694 if ((window_size.ws_col > 0) && g_driver != nullptr) { 695 g_driver->ResizeWindow(window_size.ws_col); 696 } 697 } 698 } 699 700 void sigint_handler(int signo) { 701 #ifdef _WIN32 // Restore handler as it is not persistent on Windows 702 signal(SIGINT, sigint_handler); 703 #endif 704 static std::atomic_flag g_interrupt_sent = ATOMIC_FLAG_INIT; 705 if (g_driver != nullptr) { 706 if (!g_interrupt_sent.test_and_set()) { 707 g_driver->GetDebugger().DispatchInputInterrupt(); 708 g_interrupt_sent.clear(); 709 return; 710 } 711 } 712 713 _exit(signo); 714 } 715 716 void sigtstp_handler(int signo) { 717 if (g_driver != nullptr) 718 g_driver->GetDebugger().SaveInputTerminalState(); 719 720 signal(signo, SIG_DFL); 721 kill(getpid(), signo); 722 signal(signo, sigtstp_handler); 723 } 724 725 void sigcont_handler(int signo) { 726 if (g_driver != nullptr) 727 g_driver->GetDebugger().RestoreInputTerminalState(); 728 729 signal(signo, SIG_DFL); 730 kill(getpid(), signo); 731 signal(signo, sigcont_handler); 732 } 733 734 void reproducer_handler(void *finalize_cmd) { 735 if (SBReproducer::Generate()) { 736 int result = std::system(static_cast<const char *>(finalize_cmd)); 737 (void)result; 738 fflush(stdout); 739 } 740 } 741 742 static void printHelp(LLDBOptTable &table, llvm::StringRef tool_name) { 743 std::string usage_str = tool_name.str() + " [options]"; 744 table.printHelp(llvm::outs(), usage_str.c_str(), "LLDB", false); 745 746 std::string examples = R"___( 747 EXAMPLES: 748 The debugger can be started in several modes. 749 750 Passing an executable as a positional argument prepares lldb to debug the 751 given executable. To disambiguate between arguments passed to lldb and 752 arguments passed to the debugged executable, arguments starting with a - must 753 be passed after --. 754 755 lldb --arch x86_64 /path/to/program program argument -- --arch armv7 756 757 For convenience, passing the executable after -- is also supported. 758 759 lldb --arch x86_64 -- /path/to/program program argument --arch armv7 760 761 Passing one of the attach options causes lldb to immediately attach to the 762 given process. 763 764 lldb -p <pid> 765 lldb -n <process-name> 766 767 Passing --repl starts lldb in REPL mode. 768 769 lldb -r 770 771 Passing --core causes lldb to debug the core file. 772 773 lldb -c /path/to/core 774 775 Command options can be combined with these modes and cause lldb to run the 776 specified commands before or after events, like loading the file or crashing, 777 in the order provided on the command line. 778 779 lldb -O 'settings set stop-disassembly-count 20' -o 'run' -o 'bt' 780 lldb -S /source/before/file -s /source/after/file 781 lldb -K /source/before/crash -k /source/after/crash 782 783 Note: In REPL mode no file is loaded, so commands specified to run after 784 loading the file (via -o or -s) will be ignored.)___"; 785 llvm::outs() << examples << '\n'; 786 } 787 788 static llvm::Optional<int> InitializeReproducer(llvm::StringRef argv0, 789 opt::InputArgList &input_args) { 790 if (auto *finalize_path = input_args.getLastArg(OPT_reproducer_finalize)) { 791 if (const char *error = SBReproducer::Finalize(finalize_path->getValue())) { 792 WithColor::error() << "reproducer finalization failed: " << error << '\n'; 793 return 1; 794 } 795 796 llvm::outs() << "********************\n"; 797 llvm::outs() << "Crash reproducer for "; 798 llvm::outs() << lldb::SBDebugger::GetVersionString() << '\n'; 799 llvm::outs() << '\n'; 800 llvm::outs() << "Reproducer written to '" << SBReproducer::GetPath() 801 << "'\n"; 802 llvm::outs() << '\n'; 803 llvm::outs() << "Before attaching the reproducer to a bug report:\n"; 804 llvm::outs() << " - Look at the directory to ensure you're willing to " 805 "share its content.\n"; 806 llvm::outs() 807 << " - Make sure the reproducer works by replaying the reproducer.\n"; 808 llvm::outs() << '\n'; 809 llvm::outs() << "Replay the reproducer with the following command:\n"; 810 llvm::outs() << argv0 << " -replay " << finalize_path->getValue() << "\n"; 811 llvm::outs() << "********************\n"; 812 return 0; 813 } 814 815 if (auto *replay_path = input_args.getLastArg(OPT_replay)) { 816 SBReplayOptions replay_options; 817 replay_options.SetCheckVersion(!input_args.hasArg(OPT_no_version_check)); 818 replay_options.SetVerify(!input_args.hasArg(OPT_no_verification)); 819 if (const char *error = 820 SBReproducer::Replay(replay_path->getValue(), replay_options)) { 821 WithColor::error() << "reproducer replay failed: " << error << '\n'; 822 return 1; 823 } 824 return 0; 825 } 826 827 bool capture = input_args.hasArg(OPT_capture); 828 bool generate_on_exit = input_args.hasArg(OPT_generate_on_exit); 829 auto *capture_path = input_args.getLastArg(OPT_capture_path); 830 831 if (generate_on_exit && !capture) { 832 WithColor::warning() 833 << "-reproducer-generate-on-exit specified without -capture\n"; 834 } 835 836 if (capture || capture_path) { 837 if (capture_path) { 838 if (!capture) 839 WithColor::warning() << "-capture-path specified without -capture\n"; 840 if (const char *error = SBReproducer::Capture(capture_path->getValue())) { 841 WithColor::error() << "reproducer capture failed: " << error << '\n'; 842 return 1; 843 } 844 } else { 845 const char *error = SBReproducer::Capture(); 846 if (error) { 847 WithColor::error() << "reproducer capture failed: " << error << '\n'; 848 return 1; 849 } 850 } 851 if (generate_on_exit) 852 SBReproducer::SetAutoGenerate(true); 853 854 // Register the reproducer signal handler. 855 if (!input_args.hasArg(OPT_no_generate_on_signal)) { 856 if (const char *reproducer_path = SBReproducer::GetPath()) { 857 static 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 // Editline uses for example iswprint which is dependent on LC_CTYPE. 872 std::setlocale(LC_ALL, ""); 873 std::setlocale(LC_CTYPE, ""); 874 875 // Setup LLVM signal handlers and make sure we call llvm_shutdown() on 876 // destruction. 877 llvm::InitLLVM IL(argc, argv, /*InstallPipeSignalExitHandler=*/false); 878 879 // Parse arguments. 880 LLDBOptTable T; 881 unsigned MissingArgIndex; 882 unsigned MissingArgCount; 883 ArrayRef<const char *> arg_arr = makeArrayRef(argv + 1, argc - 1); 884 opt::InputArgList input_args = 885 T.ParseArgs(arg_arr, MissingArgIndex, MissingArgCount); 886 llvm::StringRef argv0 = llvm::sys::path::filename(argv[0]); 887 888 if (input_args.hasArg(OPT_help)) { 889 printHelp(T, argv0); 890 return 0; 891 } 892 893 // Check for missing argument error. 894 if (MissingArgCount) { 895 WithColor::error() << "argument to '" 896 << input_args.getArgString(MissingArgIndex) 897 << "' is missing\n"; 898 } 899 // Error out on unknown options. 900 if (input_args.hasArg(OPT_UNKNOWN)) { 901 for (auto *arg : input_args.filtered(OPT_UNKNOWN)) { 902 WithColor::error() << "unknown option: " << arg->getSpelling() << '\n'; 903 } 904 } 905 if (MissingArgCount || input_args.hasArg(OPT_UNKNOWN)) { 906 llvm::errs() << "Use '" << argv0 907 << " --help' for a complete list of options.\n"; 908 return 1; 909 } 910 911 if (auto exit_code = InitializeReproducer(argv[0], input_args)) { 912 return *exit_code; 913 } 914 915 SBError error = SBDebugger::InitializeWithErrorHandling(); 916 if (error.Fail()) { 917 WithColor::error() << "initialization failed: " << error.GetCString() 918 << '\n'; 919 return 1; 920 } 921 SBHostOS::ThreadCreated("<lldb.driver.main-thread>"); 922 923 signal(SIGINT, sigint_handler); 924 #if !defined(_MSC_VER) 925 signal(SIGPIPE, SIG_IGN); 926 signal(SIGWINCH, sigwinch_handler); 927 signal(SIGTSTP, sigtstp_handler); 928 signal(SIGCONT, sigcont_handler); 929 #endif 930 931 int exit_code = 0; 932 // Create a scope for driver so that the driver object will destroy itself 933 // before SBDebugger::Terminate() is called. 934 { 935 Driver driver; 936 937 bool exiting = false; 938 SBError error(driver.ProcessArgs(input_args, exiting)); 939 if (error.Fail()) { 940 exit_code = 1; 941 if (const char *error_cstr = error.GetCString()) 942 WithColor::error() << error_cstr << '\n'; 943 } else if (!exiting) { 944 exit_code = driver.MainLoop(); 945 } 946 } 947 948 SBDebugger::Terminate(); 949 return exit_code; 950 } 951