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