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