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/SBStream.h" 19 #include "lldb/API/SBStringList.h" 20 #include "lldb/API/SBStructuredData.h" 21 #include "lldb/Host/Config.h" 22 #include "lldb/Host/MainLoop.h" 23 #include "lldb/Host/MainLoopBase.h" 24 #include "lldb/Utility/Status.h" 25 #include "llvm/ADT/StringRef.h" 26 #include "llvm/Support/Format.h" 27 #include "llvm/Support/InitLLVM.h" 28 #include "llvm/Support/Path.h" 29 #include "llvm/Support/Signals.h" 30 #include "llvm/Support/WithColor.h" 31 #include "llvm/Support/raw_ostream.h" 32 33 #include <algorithm> 34 #include <atomic> 35 #include <bitset> 36 #include <clocale> 37 #include <csignal> 38 #include <future> 39 #include <string> 40 #include <thread> 41 #include <utility> 42 43 #include <climits> 44 #include <cstdio> 45 #include <cstdlib> 46 #include <cstring> 47 #include <fcntl.h> 48 49 #if !defined(__APPLE__) 50 #include "llvm/Support/DataTypes.h" 51 #endif 52 53 using namespace lldb; 54 using namespace llvm; 55 using lldb_private::MainLoop; 56 using lldb_private::MainLoopBase; 57 using lldb_private::Status; 58 59 namespace { 60 using namespace llvm::opt; 61 62 enum ID { 63 OPT_INVALID = 0, // This is not an option ID. 64 #define OPTION(...) LLVM_MAKE_OPT_ID(__VA_ARGS__), 65 #include "Options.inc" 66 #undef OPTION 67 }; 68 69 #define OPTTABLE_STR_TABLE_CODE 70 #include "Options.inc" 71 #undef OPTTABLE_STR_TABLE_CODE 72 73 #define OPTTABLE_PREFIXES_TABLE_CODE 74 #include "Options.inc" 75 #undef OPTTABLE_PREFIXES_TABLE_CODE 76 77 static constexpr opt::OptTable::Info InfoTable[] = { 78 #define OPTION(...) LLVM_CONSTRUCT_OPT_INFO(__VA_ARGS__), 79 #include "Options.inc" 80 #undef OPTION 81 }; 82 83 class LLDBOptTable : public opt::GenericOptTable { 84 public: 85 LLDBOptTable() 86 : opt::GenericOptTable(OptionStrTable, OptionPrefixesTable, InfoTable) {} 87 }; 88 } // namespace 89 90 static void reset_stdin_termios(); 91 static bool g_old_stdin_termios_is_valid = false; 92 static struct termios g_old_stdin_termios; 93 94 static bool disable_color(const raw_ostream &OS) { return false; } 95 96 static Driver *g_driver = nullptr; 97 98 // In the Driver::MainLoop, we change the terminal settings. This function is 99 // added as an atexit handler to make sure we clean them up. 100 static void reset_stdin_termios() { 101 if (g_old_stdin_termios_is_valid) { 102 g_old_stdin_termios_is_valid = false; 103 ::tcsetattr(STDIN_FILENO, TCSANOW, &g_old_stdin_termios); 104 } 105 } 106 107 Driver::Driver() 108 : SBBroadcaster("Driver"), m_debugger(SBDebugger::Create(false)) { 109 // We want to be able to handle CTRL+D in the terminal to have it terminate 110 // certain input 111 m_debugger.SetCloseInputOnEOF(false); 112 g_driver = this; 113 } 114 115 Driver::~Driver() { 116 SBDebugger::Destroy(m_debugger); 117 g_driver = nullptr; 118 } 119 120 void Driver::OptionData::AddInitialCommand(std::string command, 121 CommandPlacement placement, 122 bool is_file, SBError &error) { 123 std::vector<InitialCmdEntry> *command_set; 124 switch (placement) { 125 case eCommandPlacementBeforeFile: 126 command_set = &(m_initial_commands); 127 break; 128 case eCommandPlacementAfterFile: 129 command_set = &(m_after_file_commands); 130 break; 131 case eCommandPlacementAfterCrash: 132 command_set = &(m_after_crash_commands); 133 break; 134 } 135 136 if (is_file) { 137 SBFileSpec file(command.c_str()); 138 if (file.Exists()) 139 command_set->push_back(InitialCmdEntry(command, is_file)); 140 else if (file.ResolveExecutableLocation()) { 141 char final_path[PATH_MAX]; 142 file.GetPath(final_path, sizeof(final_path)); 143 command_set->push_back(InitialCmdEntry(final_path, is_file)); 144 } else 145 error.SetErrorStringWithFormat( 146 "file specified in --source (-s) option doesn't exist: '%s'", 147 command.c_str()); 148 } else 149 command_set->push_back(InitialCmdEntry(command, is_file)); 150 } 151 152 void Driver::WriteCommandsForSourcing(CommandPlacement placement, 153 SBStream &strm) { 154 std::vector<OptionData::InitialCmdEntry> *command_set; 155 switch (placement) { 156 case eCommandPlacementBeforeFile: 157 command_set = &m_option_data.m_initial_commands; 158 break; 159 case eCommandPlacementAfterFile: 160 command_set = &m_option_data.m_after_file_commands; 161 break; 162 case eCommandPlacementAfterCrash: 163 command_set = &m_option_data.m_after_crash_commands; 164 break; 165 } 166 167 for (const auto &command_entry : *command_set) { 168 const char *command = command_entry.contents.c_str(); 169 if (command_entry.is_file) { 170 bool source_quietly = 171 m_option_data.m_source_quietly || command_entry.source_quietly; 172 strm.Printf("command source -s %i '%s'\n", 173 static_cast<int>(source_quietly), command); 174 } else 175 strm.Printf("%s\n", command); 176 } 177 } 178 179 // Check the arguments that were passed to this program to make sure they are 180 // valid and to get their argument values (if any). Return a boolean value 181 // indicating whether or not to start up the full debugger (i.e. the Command 182 // Interpreter) or not. Return FALSE if the arguments were invalid OR if the 183 // user only wanted help or version information. 184 SBError Driver::ProcessArgs(const opt::InputArgList &args, bool &exiting) { 185 SBError error; 186 187 // This is kind of a pain, but since we make the debugger in the Driver's 188 // constructor, we can't know at that point whether we should read in init 189 // files yet. So we don't read them in in the Driver constructor, then set 190 // the flags back to "read them in" here, and then if we see the "-n" flag, 191 // we'll turn it off again. Finally we have to read them in by hand later in 192 // the main loop. 193 m_debugger.SkipLLDBInitFiles(false); 194 m_debugger.SkipAppInitFiles(false); 195 196 if (args.hasArg(OPT_no_use_colors)) { 197 m_debugger.SetUseColor(false); 198 WithColor::setAutoDetectFunction(disable_color); 199 } 200 201 if (args.hasArg(OPT_version)) { 202 m_option_data.m_print_version = true; 203 } 204 205 if (args.hasArg(OPT_python_path)) { 206 m_option_data.m_print_python_path = true; 207 } 208 if (args.hasArg(OPT_print_script_interpreter_info)) { 209 m_option_data.m_print_script_interpreter_info = true; 210 } 211 212 if (args.hasArg(OPT_batch)) { 213 m_option_data.m_batch = true; 214 } 215 216 if (auto *arg = args.getLastArg(OPT_core)) { 217 auto *arg_value = arg->getValue(); 218 SBFileSpec file(arg_value); 219 if (!file.Exists()) { 220 error.SetErrorStringWithFormat( 221 "file specified in --core (-c) option doesn't exist: '%s'", 222 arg_value); 223 return error; 224 } 225 m_option_data.m_core_file = arg_value; 226 } 227 228 if (args.hasArg(OPT_editor)) { 229 m_option_data.m_use_external_editor = true; 230 } 231 232 if (args.hasArg(OPT_no_lldbinit)) { 233 m_debugger.SkipLLDBInitFiles(true); 234 m_debugger.SkipAppInitFiles(true); 235 } 236 237 if (args.hasArg(OPT_local_lldbinit)) { 238 lldb::SBDebugger::SetInternalVariable("target.load-cwd-lldbinit", "true", 239 m_debugger.GetInstanceName()); 240 } 241 242 if (auto *arg = args.getLastArg(OPT_file)) { 243 auto *arg_value = arg->getValue(); 244 SBFileSpec file(arg_value); 245 if (file.Exists()) { 246 m_option_data.m_args.emplace_back(arg_value); 247 } else if (file.ResolveExecutableLocation()) { 248 char path[PATH_MAX]; 249 file.GetPath(path, sizeof(path)); 250 m_option_data.m_args.emplace_back(path); 251 } else { 252 error.SetErrorStringWithFormat( 253 "file specified in --file (-f) option doesn't exist: '%s'", 254 arg_value); 255 return error; 256 } 257 } 258 259 if (auto *arg = args.getLastArg(OPT_arch)) { 260 auto *arg_value = arg->getValue(); 261 if (!lldb::SBDebugger::SetDefaultArchitecture(arg_value)) { 262 error.SetErrorStringWithFormat( 263 "invalid architecture in the -a or --arch option: '%s'", arg_value); 264 return error; 265 } 266 } 267 268 if (auto *arg = args.getLastArg(OPT_script_language)) { 269 auto *arg_value = arg->getValue(); 270 m_debugger.SetScriptLanguage(m_debugger.GetScriptingLanguage(arg_value)); 271 } 272 273 if (args.hasArg(OPT_source_quietly)) { 274 m_option_data.m_source_quietly = true; 275 } 276 277 if (auto *arg = args.getLastArg(OPT_attach_name)) { 278 auto *arg_value = arg->getValue(); 279 m_option_data.m_process_name = arg_value; 280 } 281 282 if (args.hasArg(OPT_wait_for)) { 283 if (!args.hasArg(OPT_attach_name)) { 284 error.SetErrorStringWithFormat( 285 "--wait-for requires a name (--attach-name)"); 286 return error; 287 } 288 289 m_option_data.m_wait_for = true; 290 } 291 292 if (auto *arg = args.getLastArg(OPT_attach_pid)) { 293 auto *arg_value = arg->getValue(); 294 char *remainder; 295 m_option_data.m_process_pid = strtol(arg_value, &remainder, 0); 296 if (remainder == arg_value || *remainder != '\0') { 297 error.SetErrorStringWithFormat( 298 "Could not convert process PID: \"%s\" into a pid.", arg_value); 299 return error; 300 } 301 } 302 303 if (auto *arg = args.getLastArg(OPT_repl_language)) { 304 auto *arg_value = arg->getValue(); 305 m_option_data.m_repl_lang = 306 SBLanguageRuntime::GetLanguageTypeFromString(arg_value); 307 if (m_option_data.m_repl_lang == eLanguageTypeUnknown) { 308 error.SetErrorStringWithFormat("Unrecognized language name: \"%s\"", 309 arg_value); 310 return error; 311 } 312 m_debugger.SetREPLLanguage(m_option_data.m_repl_lang); 313 } 314 315 if (args.hasArg(OPT_repl)) { 316 m_option_data.m_repl = true; 317 } 318 319 if (auto *arg = args.getLastArg(OPT_repl_)) { 320 m_option_data.m_repl = true; 321 if (auto *arg_value = arg->getValue()) 322 m_option_data.m_repl_options = arg_value; 323 } 324 325 // We need to process the options below together as their relative order 326 // matters. 327 for (auto *arg : args.filtered(OPT_source_on_crash, OPT_one_line_on_crash, 328 OPT_source, OPT_source_before_file, 329 OPT_one_line, OPT_one_line_before_file)) { 330 auto *arg_value = arg->getValue(); 331 if (arg->getOption().matches(OPT_source_on_crash)) { 332 m_option_data.AddInitialCommand(arg_value, eCommandPlacementAfterCrash, 333 true, error); 334 if (error.Fail()) 335 return error; 336 } 337 338 if (arg->getOption().matches(OPT_one_line_on_crash)) { 339 m_option_data.AddInitialCommand(arg_value, eCommandPlacementAfterCrash, 340 false, error); 341 if (error.Fail()) 342 return error; 343 } 344 345 if (arg->getOption().matches(OPT_source)) { 346 m_option_data.AddInitialCommand(arg_value, eCommandPlacementAfterFile, 347 true, error); 348 if (error.Fail()) 349 return error; 350 } 351 352 if (arg->getOption().matches(OPT_source_before_file)) { 353 m_option_data.AddInitialCommand(arg_value, eCommandPlacementBeforeFile, 354 true, error); 355 if (error.Fail()) 356 return error; 357 } 358 359 if (arg->getOption().matches(OPT_one_line)) { 360 m_option_data.AddInitialCommand(arg_value, eCommandPlacementAfterFile, 361 false, error); 362 if (error.Fail()) 363 return error; 364 } 365 366 if (arg->getOption().matches(OPT_one_line_before_file)) { 367 m_option_data.AddInitialCommand(arg_value, eCommandPlacementBeforeFile, 368 false, error); 369 if (error.Fail()) 370 return error; 371 } 372 } 373 374 if (m_option_data.m_process_name.empty() && 375 m_option_data.m_process_pid == LLDB_INVALID_PROCESS_ID) { 376 377 for (auto *arg : args.filtered(OPT_INPUT)) 378 m_option_data.m_args.push_back(arg->getAsString((args))); 379 380 // Any argument following -- is an argument for the inferior. 381 if (auto *arg = args.getLastArgNoClaim(OPT_REM)) { 382 for (auto *value : arg->getValues()) 383 m_option_data.m_args.emplace_back(value); 384 } 385 } else if (args.getLastArgNoClaim() != nullptr) { 386 WithColor::warning() << "program arguments are ignored when attaching.\n"; 387 } 388 389 if (m_option_data.m_print_version) { 390 llvm::outs() << lldb::SBDebugger::GetVersionString() << '\n'; 391 exiting = true; 392 return error; 393 } 394 395 if (m_option_data.m_print_python_path) { 396 SBFileSpec python_file_spec = SBHostOS::GetLLDBPythonPath(); 397 if (python_file_spec.IsValid()) { 398 char python_path[PATH_MAX]; 399 size_t num_chars = python_file_spec.GetPath(python_path, PATH_MAX); 400 if (num_chars < PATH_MAX) { 401 llvm::outs() << python_path << '\n'; 402 } else 403 llvm::outs() << "<PATH TOO LONG>\n"; 404 } else 405 llvm::outs() << "<COULD NOT FIND PATH>\n"; 406 exiting = true; 407 return error; 408 } 409 410 if (m_option_data.m_print_script_interpreter_info) { 411 SBStructuredData info = 412 m_debugger.GetScriptInterpreterInfo(m_debugger.GetScriptLanguage()); 413 if (!info) { 414 error.SetErrorString("no script interpreter."); 415 } else { 416 SBStream stream; 417 error = info.GetAsJSON(stream); 418 if (error.Success()) { 419 llvm::outs() << stream.GetData() << '\n'; 420 } 421 } 422 exiting = true; 423 return error; 424 } 425 426 return error; 427 } 428 429 std::string EscapeString(std::string arg) { 430 std::string::size_type pos = 0; 431 while ((pos = arg.find_first_of("\"\\", pos)) != std::string::npos) { 432 arg.insert(pos, 1, '\\'); 433 pos += 2; 434 } 435 return '"' + arg + '"'; 436 } 437 438 int Driver::MainLoop() { 439 if (::tcgetattr(STDIN_FILENO, &g_old_stdin_termios) == 0) { 440 g_old_stdin_termios_is_valid = true; 441 atexit(reset_stdin_termios); 442 } 443 444 #ifndef _MSC_VER 445 // Disabling stdin buffering with MSVC's 2015 CRT exposes a bug in fgets 446 // which causes it to miss newlines depending on whether there have been an 447 // odd or even number of characters. Bug has been reported to MS via Connect. 448 ::setbuf(stdin, nullptr); 449 #endif 450 ::setbuf(stdout, nullptr); 451 452 m_debugger.SetErrorFileHandle(stderr, false); 453 m_debugger.SetOutputFileHandle(stdout, false); 454 // Don't take ownership of STDIN yet... 455 m_debugger.SetInputFileHandle(stdin, false); 456 457 m_debugger.SetUseExternalEditor(m_option_data.m_use_external_editor); 458 m_debugger.SetShowInlineDiagnostics(true); 459 460 // Set the terminal dimensions. 461 UpdateWindowSize(); 462 463 SBCommandInterpreter sb_interpreter = m_debugger.GetCommandInterpreter(); 464 465 // Process lldbinit files before handling any options from the command line. 466 SBCommandReturnObject result; 467 sb_interpreter.SourceInitFileInGlobalDirectory(result); 468 sb_interpreter.SourceInitFileInHomeDirectory(result, m_option_data.m_repl); 469 470 // Source the local .lldbinit file if it exists and we're allowed to source. 471 // Here we want to always print the return object because it contains the 472 // warning and instructions to load local lldbinit files. 473 sb_interpreter.SourceInitFileInCurrentWorkingDirectory(result); 474 result.PutError(m_debugger.GetErrorFile()); 475 result.PutOutput(m_debugger.GetOutputFile()); 476 477 // We allow the user to specify an exit code when calling quit which we will 478 // return when exiting. 479 m_debugger.GetCommandInterpreter().AllowExitCodeOnQuit(true); 480 481 // Now we handle options we got from the command line 482 SBStream commands_stream; 483 484 // First source in the commands specified to be run before the file arguments 485 // are processed. 486 WriteCommandsForSourcing(eCommandPlacementBeforeFile, commands_stream); 487 488 // If we're not in --repl mode, add the commands to process the file 489 // arguments, and the commands specified to run afterwards. 490 if (!m_option_data.m_repl) { 491 const size_t num_args = m_option_data.m_args.size(); 492 if (num_args > 0) { 493 char arch_name[64]; 494 if (lldb::SBDebugger::GetDefaultArchitecture(arch_name, 495 sizeof(arch_name))) 496 commands_stream.Printf("target create --arch=%s %s", arch_name, 497 EscapeString(m_option_data.m_args[0]).c_str()); 498 else 499 commands_stream.Printf("target create %s", 500 EscapeString(m_option_data.m_args[0]).c_str()); 501 502 if (!m_option_data.m_core_file.empty()) { 503 commands_stream.Printf(" --core %s", 504 EscapeString(m_option_data.m_core_file).c_str()); 505 } 506 commands_stream.Printf("\n"); 507 508 if (num_args > 1) { 509 commands_stream.Printf("settings set -- target.run-args "); 510 for (size_t arg_idx = 1; arg_idx < num_args; ++arg_idx) 511 commands_stream.Printf( 512 " %s", EscapeString(m_option_data.m_args[arg_idx]).c_str()); 513 commands_stream.Printf("\n"); 514 } 515 } else if (!m_option_data.m_core_file.empty()) { 516 commands_stream.Printf("target create --core %s\n", 517 EscapeString(m_option_data.m_core_file).c_str()); 518 } else if (!m_option_data.m_process_name.empty()) { 519 commands_stream.Printf( 520 "process attach --name %s", 521 EscapeString(m_option_data.m_process_name).c_str()); 522 523 if (m_option_data.m_wait_for) 524 commands_stream.Printf(" --waitfor"); 525 526 commands_stream.Printf("\n"); 527 528 } else if (LLDB_INVALID_PROCESS_ID != m_option_data.m_process_pid) { 529 commands_stream.Printf("process attach --pid %" PRIu64 "\n", 530 m_option_data.m_process_pid); 531 } 532 533 WriteCommandsForSourcing(eCommandPlacementAfterFile, commands_stream); 534 } else if (!m_option_data.m_after_file_commands.empty()) { 535 // We're in repl mode and after-file-load commands were specified. 536 WithColor::warning() << "commands specified to run after file load (via -o " 537 "or -s) are ignored in REPL mode.\n"; 538 } 539 540 const bool handle_events = true; 541 const bool spawn_thread = false; 542 543 // Check if we have any data in the commands stream, and if so, save it to a 544 // temp file 545 // so we can then run the command interpreter using the file contents. 546 bool go_interactive = true; 547 if ((commands_stream.GetData() != nullptr) && 548 (commands_stream.GetSize() != 0u)) { 549 SBError error = m_debugger.SetInputString(commands_stream.GetData()); 550 if (error.Fail()) { 551 WithColor::error() << error.GetCString() << '\n'; 552 return 1; 553 } 554 555 // Set the debugger into Sync mode when running the command file. Otherwise 556 // command files that run the target won't run in a sensible way. 557 bool old_async = m_debugger.GetAsync(); 558 m_debugger.SetAsync(false); 559 560 SBCommandInterpreterRunOptions options; 561 options.SetAutoHandleEvents(true); 562 options.SetSpawnThread(false); 563 options.SetStopOnError(true); 564 options.SetStopOnCrash(m_option_data.m_batch); 565 options.SetEchoCommands(!m_option_data.m_source_quietly); 566 567 SBCommandInterpreterRunResult results = 568 m_debugger.RunCommandInterpreter(options); 569 if (results.GetResult() == lldb::eCommandInterpreterResultQuitRequested) 570 go_interactive = false; 571 if (m_option_data.m_batch && 572 results.GetResult() != lldb::eCommandInterpreterResultInferiorCrash) 573 go_interactive = false; 574 575 // When running in batch mode and stopped because of an error, exit with a 576 // non-zero exit status. 577 if (m_option_data.m_batch && 578 results.GetResult() == lldb::eCommandInterpreterResultCommandError) 579 return 1; 580 581 if (m_option_data.m_batch && 582 results.GetResult() == lldb::eCommandInterpreterResultInferiorCrash && 583 !m_option_data.m_after_crash_commands.empty()) { 584 SBStream crash_commands_stream; 585 WriteCommandsForSourcing(eCommandPlacementAfterCrash, 586 crash_commands_stream); 587 SBError error = 588 m_debugger.SetInputString(crash_commands_stream.GetData()); 589 if (error.Success()) { 590 SBCommandInterpreterRunResult local_results = 591 m_debugger.RunCommandInterpreter(options); 592 if (local_results.GetResult() == 593 lldb::eCommandInterpreterResultQuitRequested) 594 go_interactive = false; 595 596 // When running in batch mode and an error occurred while sourcing 597 // the crash commands, exit with a non-zero exit status. 598 if (m_option_data.m_batch && 599 local_results.GetResult() == 600 lldb::eCommandInterpreterResultCommandError) 601 return 1; 602 } 603 } 604 m_debugger.SetAsync(old_async); 605 } 606 607 // Now set the input file handle to STDIN and run the command interpreter 608 // again in interactive mode or repl mode and let the debugger take ownership 609 // of stdin. 610 if (go_interactive) { 611 m_debugger.SetInputFileHandle(stdin, true); 612 613 if (m_option_data.m_repl) { 614 const char *repl_options = nullptr; 615 if (!m_option_data.m_repl_options.empty()) 616 repl_options = m_option_data.m_repl_options.c_str(); 617 SBError error( 618 m_debugger.RunREPL(m_option_data.m_repl_lang, repl_options)); 619 if (error.Fail()) { 620 const char *error_cstr = error.GetCString(); 621 if ((error_cstr != nullptr) && (error_cstr[0] != 0)) 622 WithColor::error() << error_cstr << '\n'; 623 else 624 WithColor::error() << error.GetError() << '\n'; 625 } 626 } else { 627 m_debugger.RunCommandInterpreter(handle_events, spawn_thread); 628 } 629 } 630 631 reset_stdin_termios(); 632 fclose(stdin); 633 634 return sb_interpreter.GetQuitStatus(); 635 } 636 637 void Driver::UpdateWindowSize() { 638 struct winsize window_size; 639 if ((isatty(STDIN_FILENO) != 0) && 640 ::ioctl(STDIN_FILENO, TIOCGWINSZ, &window_size) == 0) { 641 if (window_size.ws_col > 0) 642 m_debugger.SetTerminalWidth(window_size.ws_col); 643 #ifndef _WIN32 644 if (window_size.ws_row > 0) 645 m_debugger.SetTerminalHeight(window_size.ws_row); 646 #endif 647 } 648 } 649 650 void sigint_handler(int signo) { 651 #ifdef _WIN32 652 // Restore handler as it is not persistent on Windows. 653 signal(SIGINT, sigint_handler); 654 #endif 655 656 static std::atomic_flag g_interrupt_sent = ATOMIC_FLAG_INIT; 657 if (g_driver != nullptr) { 658 if (!g_interrupt_sent.test_and_set()) { 659 g_driver->GetDebugger().DispatchInputInterrupt(); 660 g_interrupt_sent.clear(); 661 return; 662 } 663 } 664 665 _exit(signo); 666 } 667 668 static void printHelp(LLDBOptTable &table, llvm::StringRef tool_name) { 669 std::string usage_str = tool_name.str() + " [options]"; 670 table.printHelp(llvm::outs(), usage_str.c_str(), "LLDB", false); 671 672 std::string examples = R"___( 673 EXAMPLES: 674 The debugger can be started in several modes. 675 676 Passing an executable as a positional argument prepares lldb to debug the 677 given executable. To disambiguate between arguments passed to lldb and 678 arguments passed to the debugged executable, arguments starting with a - must 679 be passed after --. 680 681 lldb --arch x86_64 /path/to/program program argument -- --arch armv7 682 683 For convenience, passing the executable after -- is also supported. 684 685 lldb --arch x86_64 -- /path/to/program program argument --arch armv7 686 687 Passing one of the attach options causes lldb to immediately attach to the 688 given process. 689 690 lldb -p <pid> 691 lldb -n <process-name> 692 693 Passing --repl starts lldb in REPL mode. 694 695 lldb -r 696 697 Passing --core causes lldb to debug the core file. 698 699 lldb -c /path/to/core 700 701 Command options can be combined with these modes and cause lldb to run the 702 specified commands before or after events, like loading the file or crashing, 703 in the order provided on the command line. 704 705 lldb -O 'settings set stop-disassembly-count 20' -o 'run' -o 'bt' 706 lldb -S /source/before/file -s /source/after/file 707 lldb -K /source/before/crash -k /source/after/crash 708 709 Note: In REPL mode no file is loaded, so commands specified to run after 710 loading the file (via -o or -s) will be ignored.)___"; 711 llvm::outs() << examples << '\n'; 712 } 713 714 int main(int argc, char const *argv[]) { 715 // Editline uses for example iswprint which is dependent on LC_CTYPE. 716 std::setlocale(LC_ALL, ""); 717 std::setlocale(LC_CTYPE, ""); 718 719 // Setup LLVM signal handlers and make sure we call llvm_shutdown() on 720 // destruction. 721 llvm::InitLLVM IL(argc, argv, /*InstallPipeSignalExitHandler=*/false); 722 #if !defined(__APPLE__) 723 llvm::setBugReportMsg("PLEASE submit a bug report to " LLDB_BUG_REPORT_URL 724 " and include the crash backtrace.\n"); 725 #else 726 llvm::setBugReportMsg("PLEASE submit a bug report to " LLDB_BUG_REPORT_URL 727 " and include the crash report from " 728 "~/Library/Logs/DiagnosticReports/.\n"); 729 #endif 730 731 // Parse arguments. 732 LLDBOptTable T; 733 unsigned MissingArgIndex; 734 unsigned MissingArgCount; 735 ArrayRef<const char *> arg_arr = ArrayRef(argv + 1, argc - 1); 736 opt::InputArgList input_args = 737 T.ParseArgs(arg_arr, MissingArgIndex, MissingArgCount); 738 llvm::StringRef argv0 = llvm::sys::path::filename(argv[0]); 739 740 if (input_args.hasArg(OPT_help)) { 741 printHelp(T, argv0); 742 return 0; 743 } 744 745 // Check for missing argument error. 746 if (MissingArgCount) { 747 WithColor::error() << "argument to '" 748 << input_args.getArgString(MissingArgIndex) 749 << "' is missing\n"; 750 } 751 // Error out on unknown options. 752 if (input_args.hasArg(OPT_UNKNOWN)) { 753 for (auto *arg : input_args.filtered(OPT_UNKNOWN)) { 754 WithColor::error() << "unknown option: " << arg->getSpelling() << '\n'; 755 } 756 } 757 if (MissingArgCount || input_args.hasArg(OPT_UNKNOWN)) { 758 llvm::errs() << "Use '" << argv0 759 << " --help' for a complete list of options.\n"; 760 return 1; 761 } 762 763 SBError error = SBDebugger::InitializeWithErrorHandling(); 764 if (error.Fail()) { 765 WithColor::error() << "initialization failed: " << error.GetCString() 766 << '\n'; 767 return 1; 768 } 769 770 // Setup LLDB signal handlers once the debugger has been initialized. 771 SBDebugger::PrintDiagnosticsOnError(); 772 773 // FIXME: Migrate the SIGINT handler to be handled by the signal loop below. 774 signal(SIGINT, sigint_handler); 775 #if !defined(_WIN32) 776 signal(SIGPIPE, SIG_IGN); 777 778 // Handle signals in a MainLoop running on a separate thread. 779 MainLoop signal_loop; 780 Status signal_status; 781 782 auto sigwinch_handler = signal_loop.RegisterSignal( 783 SIGWINCH, 784 [&](MainLoopBase &) { 785 if (g_driver) 786 g_driver->UpdateWindowSize(); 787 }, 788 signal_status); 789 assert(sigwinch_handler && signal_status.Success()); 790 791 auto sigtstp_handler = signal_loop.RegisterSignal( 792 SIGTSTP, 793 [&](MainLoopBase &) { 794 if (g_driver) 795 g_driver->GetDebugger().SaveInputTerminalState(); 796 797 struct sigaction old_action; 798 struct sigaction new_action = {}; 799 new_action.sa_handler = SIG_DFL; 800 sigemptyset(&new_action.sa_mask); 801 sigaddset(&new_action.sa_mask, SIGTSTP); 802 803 int ret = sigaction(SIGTSTP, &new_action, &old_action); 804 UNUSED_IF_ASSERT_DISABLED(ret); 805 assert(ret == 0 && "sigaction failed"); 806 807 raise(SIGTSTP); 808 809 ret = sigaction(SIGTSTP, &old_action, nullptr); 810 UNUSED_IF_ASSERT_DISABLED(ret); 811 assert(ret == 0 && "sigaction failed"); 812 813 if (g_driver) 814 g_driver->GetDebugger().RestoreInputTerminalState(); 815 }, 816 signal_status); 817 assert(sigtstp_handler && signal_status.Success()); 818 819 std::thread signal_thread([&] { signal_loop.Run(); }); 820 #endif 821 822 int exit_code = 0; 823 // Create a scope for driver so that the driver object will destroy itself 824 // before SBDebugger::Terminate() is called. 825 { 826 Driver driver; 827 828 bool exiting = false; 829 SBError error(driver.ProcessArgs(input_args, exiting)); 830 if (error.Fail()) { 831 exit_code = 1; 832 if (const char *error_cstr = error.GetCString()) 833 WithColor::error() << error_cstr << '\n'; 834 } else if (!exiting) { 835 exit_code = driver.MainLoop(); 836 } 837 } 838 839 // When terminating the debugger we have to wait on all the background tasks 840 // to complete, which can take a while. Print a message when this takes longer 841 // than 1 second. 842 { 843 std::future<void> future = 844 std::async(std::launch::async, []() { SBDebugger::Terminate(); }); 845 846 if (future.wait_for(std::chrono::seconds(1)) == std::future_status::timeout) 847 fprintf(stderr, "Waiting for background tasks to complete...\n"); 848 849 future.wait(); 850 } 851 852 #if !defined(_WIN32) 853 signal_loop.AddPendingCallback( 854 [](MainLoopBase &loop) { loop.RequestTermination(); }); 855 signal_thread.join(); 856 #endif 857 858 return exit_code; 859 } 860