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