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