1 //===-- Driver.cpp ----------------------------------------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "Driver.h" 11 12 #include <getopt.h> 13 #include <libgen.h> 14 #include <sys/ioctl.h> 15 #include <termios.h> 16 #include <unistd.h> 17 #include <string.h> 18 #include <stdlib.h> 19 #include <limits.h> 20 #include <fcntl.h> 21 22 #include <string> 23 24 #include "IOChannel.h" 25 #include "lldb/API/SBCommandInterpreter.h" 26 #include "lldb/API/SBCommandReturnObject.h" 27 #include "lldb/API/SBCommunication.h" 28 #include "lldb/API/SBDebugger.h" 29 #include "lldb/API/SBEvent.h" 30 #include "lldb/API/SBHostOS.h" 31 #include "lldb/API/SBListener.h" 32 #include "lldb/API/SBStream.h" 33 #include "lldb/API/SBTarget.h" 34 #include "lldb/API/SBThread.h" 35 #include "lldb/API/SBProcess.h" 36 37 using namespace lldb; 38 39 static void reset_stdin_termios (); 40 static struct termios g_old_stdin_termios; 41 42 static char *g_debugger_name = (char *) ""; 43 static Driver *g_driver = NULL; 44 45 // In the Driver::MainLoop, we change the terminal settings. This function is 46 // added as an atexit handler to make sure we clean them up. 47 static void 48 reset_stdin_termios () 49 { 50 ::tcsetattr (STDIN_FILENO, TCSANOW, &g_old_stdin_termios); 51 } 52 53 typedef struct 54 { 55 uint32_t usage_mask; // Used to mark options that can be used together. If (1 << n & usage_mask) != 0 56 // then this option belongs to option set n. 57 bool required; // This option is required (in the current usage level) 58 const char * long_option; // Full name for this option. 59 char short_option; // Single character for this option. 60 int option_has_arg; // no_argument, required_argument or optional_argument 61 uint32_t completion_type; // Cookie the option class can use to do define the argument completion. 62 lldb::CommandArgumentType argument_type; // Type of argument this option takes 63 const char * usage_text; // Full text explaining what this options does and what (if any) argument to 64 // pass it. 65 } OptionDefinition; 66 67 #define LLDB_3_TO_5 LLDB_OPT_SET_3|LLDB_OPT_SET_4|LLDB_OPT_SET_5 68 #define LLDB_4_TO_5 LLDB_OPT_SET_4|LLDB_OPT_SET_5 69 70 static OptionDefinition g_options[] = 71 { 72 { LLDB_OPT_SET_1, true , "help" , 'h', no_argument , NULL, eArgTypeNone, 73 "Prints out the usage information for the LLDB debugger." }, 74 { LLDB_OPT_SET_2, true , "version" , 'v', no_argument , NULL, eArgTypeNone, 75 "Prints out the current version number of the LLDB debugger." }, 76 { LLDB_OPT_SET_3, true , "arch" , 'a', required_argument, NULL, eArgTypeArchitecture, 77 "Tells the debugger to use the specified architecture when starting and running the program. <architecture> must " 78 "be one of the architectures for which the program was compiled." }, 79 { LLDB_OPT_SET_3, true , "file" , 'f', required_argument, NULL, eArgTypeFilename, 80 "Tells the debugger to use the file <filename> as the program to be debugged." }, 81 { LLDB_OPT_SET_4, true , "attach-name" , 'n', required_argument, NULL, eArgTypeProcessName, 82 "Tells the debugger to attach to a process with the given name." }, 83 { LLDB_OPT_SET_4, true , "wait-for" , 'w', no_argument , NULL, eArgTypeNone, 84 "Tells the debugger to wait for a process with the given pid or name to launch before attaching." }, 85 { LLDB_OPT_SET_5, true , "attach-pid" , 'p', required_argument, NULL, eArgTypePid, 86 "Tells the debugger to attach to a process with the given pid." }, 87 { LLDB_3_TO_5, false, "script-language", 'l', required_argument, NULL, eArgTypeScriptLang, 88 "Tells the debugger to use the specified scripting language for user-defined scripts, rather than the default. " 89 "Valid scripting languages that can be specified include Python, Perl, Ruby and Tcl. Currently only the Python " 90 "extensions have been implemented." }, 91 { LLDB_3_TO_5, false, "debug" , 'd', no_argument , NULL, eArgTypeNone, 92 "Tells the debugger to print out extra information for debugging itself." }, 93 { LLDB_3_TO_5, false, "source" , 's', required_argument, NULL, eArgTypeFilename, 94 "Tells the debugger to read in and execute the file <file>, which should contain lldb commands." }, 95 { LLDB_3_TO_5, false, "editor" , 'e', no_argument , NULL, eArgTypeNone, 96 "Tells the debugger to open source files using the host's \"external editor\" mechanism." }, 97 { LLDB_3_TO_5, false, "no-lldbinit" , 'x', no_argument , NULL, eArgTypeNone, 98 "Do not automatically parse any '.lldbinit' files." }, 99 { 0, false, NULL , 0 , 0 , NULL, eArgTypeNone, NULL } 100 }; 101 102 static const uint32_t last_option_set_with_args = 2; 103 104 Driver::Driver () : 105 SBBroadcaster ("Driver"), 106 m_debugger (SBDebugger::Create(false)), 107 m_editline_pty (), 108 m_editline_slave_fh (NULL), 109 m_editline_reader (), 110 m_io_channel_ap (), 111 m_option_data (), 112 m_waiting_for_command (false) 113 { 114 // We want to be able to handle CTRL+D in the terminal to have it terminate 115 // certain input 116 m_debugger.SetCloseInputOnEOF (false); 117 g_debugger_name = (char *) m_debugger.GetInstanceName(); 118 if (g_debugger_name == NULL) 119 g_debugger_name = (char *) ""; 120 g_driver = this; 121 } 122 123 Driver::~Driver () 124 { 125 g_driver = NULL; 126 g_debugger_name = NULL; 127 } 128 129 void 130 Driver::CloseIOChannelFile () 131 { 132 // Write and End of File sequence to the file descriptor to ensure any 133 // read functions can exit. 134 char eof_str[] = "\x04"; 135 ::write (m_editline_pty.GetMasterFileDescriptor(), eof_str, strlen(eof_str)); 136 137 m_editline_pty.CloseMasterFileDescriptor(); 138 139 if (m_editline_slave_fh) 140 { 141 ::fclose (m_editline_slave_fh); 142 m_editline_slave_fh = NULL; 143 } 144 } 145 146 // This function takes INDENT, which tells how many spaces to output at the front 147 // of each line; TEXT, which is the text that is to be output. It outputs the 148 // text, on multiple lines if necessary, to RESULT, with INDENT spaces at the 149 // front of each line. It breaks lines on spaces, tabs or newlines, shortening 150 // the line if necessary to not break in the middle of a word. It assumes that 151 // each output line should contain a maximum of OUTPUT_MAX_COLUMNS characters. 152 153 void 154 OutputFormattedUsageText (FILE *out, int indent, const char *text, int output_max_columns) 155 { 156 int len = strlen (text); 157 std::string text_string (text); 158 159 // Force indentation to be reasonable. 160 if (indent >= output_max_columns) 161 indent = 0; 162 163 // Will it all fit on one line? 164 165 if (len + indent < output_max_columns) 166 // Output as a single line 167 fprintf (out, "%*s%s\n", indent, "", text); 168 else 169 { 170 // We need to break it up into multiple lines. 171 int text_width = output_max_columns - indent - 1; 172 int start = 0; 173 int end = start; 174 int final_end = len; 175 int sub_len; 176 177 while (end < final_end) 178 { 179 // Dont start the 'text' on a space, since we're already outputting the indentation. 180 while ((start < final_end) && (text[start] == ' ')) 181 start++; 182 183 end = start + text_width; 184 if (end > final_end) 185 end = final_end; 186 else 187 { 188 // If we're not at the end of the text, make sure we break the line on white space. 189 while (end > start 190 && text[end] != ' ' && text[end] != '\t' && text[end] != '\n') 191 end--; 192 } 193 sub_len = end - start; 194 std::string substring = text_string.substr (start, sub_len); 195 fprintf (out, "%*s%s\n", indent, "", substring.c_str()); 196 start = end + 1; 197 } 198 } 199 } 200 201 void 202 ShowUsage (FILE *out, OptionDefinition *option_table, Driver::OptionData data) 203 { 204 uint32_t screen_width = 80; 205 uint32_t indent_level = 0; 206 const char *name = "lldb"; 207 208 fprintf (out, "\nUsage:\n\n"); 209 210 indent_level += 2; 211 212 213 // First, show each usage level set of options, e.g. <cmd> [options-for-level-0] 214 // <cmd> [options-for-level-1] 215 // etc. 216 217 uint32_t num_options; 218 uint32_t num_option_sets = 0; 219 220 for (num_options = 0; option_table[num_options].long_option != NULL; ++num_options) 221 { 222 uint32_t this_usage_mask = option_table[num_options].usage_mask; 223 if (this_usage_mask == LLDB_OPT_SET_ALL) 224 { 225 if (num_option_sets == 0) 226 num_option_sets = 1; 227 } 228 else 229 { 230 for (uint32_t j = 0; j < LLDB_MAX_NUM_OPTION_SETS; j++) 231 { 232 if (this_usage_mask & 1 << j) 233 { 234 if (num_option_sets <= j) 235 num_option_sets = j + 1; 236 } 237 } 238 } 239 } 240 241 for (uint32_t opt_set = 0; opt_set < num_option_sets; opt_set++) 242 { 243 uint32_t opt_set_mask; 244 245 opt_set_mask = 1 << opt_set; 246 247 if (opt_set > 0) 248 fprintf (out, "\n"); 249 fprintf (out, "%*s%s", indent_level, "", name); 250 bool is_help_line = false; 251 252 for (uint32_t i = 0; i < num_options; ++i) 253 { 254 if (option_table[i].usage_mask & opt_set_mask) 255 { 256 CommandArgumentType arg_type = option_table[i].argument_type; 257 const char *arg_name = SBCommandInterpreter::GetArgumentTypeAsCString (arg_type); 258 // This is a bit of a hack, but there's no way to say certain options don't have arguments yet... 259 // so we do it by hand here. 260 if (option_table[i].short_option == 'h') 261 is_help_line = true; 262 263 if (option_table[i].required) 264 { 265 if (option_table[i].option_has_arg == required_argument) 266 fprintf (out, " -%c <%s>", option_table[i].short_option, arg_name); 267 else if (option_table[i].option_has_arg == optional_argument) 268 fprintf (out, " -%c [<%s>]", option_table[i].short_option, arg_name); 269 else 270 fprintf (out, " -%c", option_table[i].short_option); 271 } 272 else 273 { 274 if (option_table[i].option_has_arg == required_argument) 275 fprintf (out, " [-%c <%s>]", option_table[i].short_option, arg_name); 276 else if (option_table[i].option_has_arg == optional_argument) 277 fprintf (out, " [-%c [<%s>]]", option_table[i].short_option, arg_name); 278 else 279 fprintf (out, " [-%c]", option_table[i].short_option); 280 } 281 } 282 } 283 if (!is_help_line && (opt_set <= last_option_set_with_args)) 284 fprintf (out, " [[--] <PROGRAM-ARG-1> [<PROGRAM_ARG-2> ...]]"); 285 } 286 287 fprintf (out, "\n\n"); 288 289 // Now print out all the detailed information about the various options: long form, short form and help text: 290 // -- long_name <argument> 291 // - short <argument> 292 // help text 293 294 // This variable is used to keep track of which options' info we've printed out, because some options can be in 295 // more than one usage level, but we only want to print the long form of its information once. 296 297 Driver::OptionData::OptionSet options_seen; 298 Driver::OptionData::OptionSet::iterator pos; 299 300 indent_level += 5; 301 302 for (uint32_t i = 0; i < num_options; ++i) 303 { 304 // Only print this option if we haven't already seen it. 305 pos = options_seen.find (option_table[i].short_option); 306 if (pos == options_seen.end()) 307 { 308 CommandArgumentType arg_type = option_table[i].argument_type; 309 const char *arg_name = SBCommandInterpreter::GetArgumentTypeAsCString (arg_type); 310 311 options_seen.insert (option_table[i].short_option); 312 fprintf (out, "%*s-%c ", indent_level, "", option_table[i].short_option); 313 if (arg_type != eArgTypeNone) 314 fprintf (out, "<%s>", arg_name); 315 fprintf (out, "\n"); 316 fprintf (out, "%*s--%s ", indent_level, "", option_table[i].long_option); 317 if (arg_type != eArgTypeNone) 318 fprintf (out, "<%s>", arg_name); 319 fprintf (out, "\n"); 320 indent_level += 5; 321 OutputFormattedUsageText (out, indent_level, option_table[i].usage_text, screen_width); 322 indent_level -= 5; 323 fprintf (out, "\n"); 324 } 325 } 326 327 indent_level -= 5; 328 329 fprintf (out, "\n%*s(If you don't provide -f then the first argument will be the file to be debugged" 330 "\n%*s so '%s -- <filename> [<ARG1> [<ARG2>]]' also works." 331 "\n%*s Remember to end the options with \"--\" if any of your arguments have a \"-\" in them.)\n\n", 332 indent_level, "", 333 indent_level, "", 334 name, 335 indent_level, ""); 336 } 337 338 void 339 BuildGetOptTable (OptionDefinition *expanded_option_table, std::vector<struct option> &getopt_table, 340 uint32_t num_options) 341 { 342 if (num_options == 0) 343 return; 344 345 uint32_t i; 346 uint32_t j; 347 std::bitset<256> option_seen; 348 349 getopt_table.resize (num_options + 1); 350 351 for (i = 0, j = 0; i < num_options; ++i) 352 { 353 char short_opt = expanded_option_table[i].short_option; 354 355 if (option_seen.test(short_opt) == false) 356 { 357 getopt_table[j].name = expanded_option_table[i].long_option; 358 getopt_table[j].has_arg = expanded_option_table[i].option_has_arg; 359 getopt_table[j].flag = NULL; 360 getopt_table[j].val = expanded_option_table[i].short_option; 361 option_seen.set(short_opt); 362 ++j; 363 } 364 } 365 366 getopt_table[j].name = NULL; 367 getopt_table[j].has_arg = 0; 368 getopt_table[j].flag = NULL; 369 getopt_table[j].val = 0; 370 371 } 372 373 Driver::OptionData::OptionData () : 374 m_args(), 375 m_script_lang (lldb::eScriptLanguageDefault), 376 m_crash_log (), 377 m_source_command_files (), 378 m_debug_mode (false), 379 m_print_version (false), 380 m_print_help (false), 381 m_use_external_editor(false), 382 m_wait_for(false), 383 m_process_name(), 384 m_process_pid(LLDB_INVALID_PROCESS_ID), 385 m_seen_options() 386 { 387 } 388 389 Driver::OptionData::~OptionData () 390 { 391 } 392 393 void 394 Driver::OptionData::Clear () 395 { 396 m_args.clear (); 397 m_script_lang = lldb::eScriptLanguageDefault; 398 m_source_command_files.clear (); 399 m_debug_mode = false; 400 m_print_help = false; 401 m_print_version = false; 402 m_use_external_editor = false; 403 m_wait_for = false; 404 m_process_name.erase(); 405 m_process_pid = LLDB_INVALID_PROCESS_ID; 406 } 407 408 void 409 Driver::ResetOptionValues () 410 { 411 m_option_data.Clear (); 412 } 413 414 const char * 415 Driver::GetFilename() const 416 { 417 if (m_option_data.m_args.empty()) 418 return NULL; 419 return m_option_data.m_args.front().c_str(); 420 } 421 422 const char * 423 Driver::GetCrashLogFilename() const 424 { 425 if (m_option_data.m_crash_log.empty()) 426 return NULL; 427 return m_option_data.m_crash_log.c_str(); 428 } 429 430 lldb::ScriptLanguage 431 Driver::GetScriptLanguage() const 432 { 433 return m_option_data.m_script_lang; 434 } 435 436 size_t 437 Driver::GetNumSourceCommandFiles () const 438 { 439 return m_option_data.m_source_command_files.size(); 440 } 441 442 const char * 443 Driver::GetSourceCommandFileAtIndex (uint32_t idx) const 444 { 445 if (idx < m_option_data.m_source_command_files.size()) 446 return m_option_data.m_source_command_files[idx].c_str(); 447 return NULL; 448 } 449 450 bool 451 Driver::GetDebugMode() const 452 { 453 return m_option_data.m_debug_mode; 454 } 455 456 457 // Check the arguments that were passed to this program to make sure they are valid and to get their 458 // argument values (if any). Return a boolean value indicating whether or not to start up the full 459 // debugger (i.e. the Command Interpreter) or not. Return FALSE if the arguments were invalid OR 460 // if the user only wanted help or version information. 461 462 SBError 463 Driver::ParseArgs (int argc, const char *argv[], FILE *out_fh, bool &exit) 464 { 465 ResetOptionValues (); 466 467 SBCommandReturnObject result; 468 469 SBError error; 470 std::string option_string; 471 struct option *long_options = NULL; 472 std::vector<struct option> long_options_vector; 473 uint32_t num_options; 474 475 for (num_options = 0; g_options[num_options].long_option != NULL; ++num_options) 476 /* Do Nothing. */; 477 478 if (num_options == 0) 479 { 480 if (argc > 1) 481 error.SetErrorStringWithFormat ("invalid number of options"); 482 return error; 483 } 484 485 BuildGetOptTable (g_options, long_options_vector, num_options); 486 487 if (long_options_vector.empty()) 488 long_options = NULL; 489 else 490 long_options = &long_options_vector.front(); 491 492 if (long_options == NULL) 493 { 494 error.SetErrorStringWithFormat ("invalid long options"); 495 return error; 496 } 497 498 // Build the option_string argument for call to getopt_long. 499 500 for (int i = 0; long_options[i].name != NULL; ++i) 501 { 502 if (long_options[i].flag == NULL) 503 { 504 option_string.push_back ((char) long_options[i].val); 505 switch (long_options[i].has_arg) 506 { 507 default: 508 case no_argument: 509 break; 510 case required_argument: 511 option_string.push_back (':'); 512 break; 513 case optional_argument: 514 option_string.append ("::"); 515 break; 516 } 517 } 518 } 519 520 // This is kind of a pain, but since we make the debugger in the Driver's constructor, we can't 521 // know at that point whether we should read in init files yet. So we don't read them in in the 522 // Driver constructor, then set the flags back to "read them in" here, and then if we see the 523 // "-n" flag, we'll turn it off again. Finally we have to read them in by hand later in the 524 // main loop. 525 526 m_debugger.SkipLLDBInitFiles (false); 527 m_debugger.SkipAppInitFiles (false); 528 529 // Prepare for & make calls to getopt_long. 530 #if __GLIBC__ 531 optind = 0; 532 #else 533 optreset = 1; 534 optind = 1; 535 #endif 536 int val; 537 while (1) 538 { 539 int long_options_index = -1; 540 val = ::getopt_long (argc, const_cast<char **>(argv), option_string.c_str(), long_options, &long_options_index); 541 542 if (val == -1) 543 break; 544 else if (val == '?') 545 { 546 m_option_data.m_print_help = true; 547 error.SetErrorStringWithFormat ("unknown or ambiguous option"); 548 break; 549 } 550 else if (val == 0) 551 continue; 552 else 553 { 554 m_option_data.m_seen_options.insert ((char) val); 555 if (long_options_index == -1) 556 { 557 for (int i = 0; 558 long_options[i].name || long_options[i].has_arg || long_options[i].flag || long_options[i].val; 559 ++i) 560 { 561 if (long_options[i].val == val) 562 { 563 long_options_index = i; 564 break; 565 } 566 } 567 } 568 569 if (long_options_index >= 0) 570 { 571 const char short_option = (char) g_options[long_options_index].short_option; 572 573 switch (short_option) 574 { 575 case 'h': 576 m_option_data.m_print_help = true; 577 break; 578 579 case 'v': 580 m_option_data.m_print_version = true; 581 break; 582 583 case 'c': 584 m_option_data.m_crash_log = optarg; 585 break; 586 587 case 'e': 588 m_option_data.m_use_external_editor = true; 589 break; 590 591 case 'x': 592 m_debugger.SkipLLDBInitFiles (true); 593 m_debugger.SkipAppInitFiles (true); 594 break; 595 596 case 'f': 597 { 598 SBFileSpec file(optarg); 599 if (file.Exists()) 600 { 601 m_option_data.m_args.push_back (optarg); 602 } 603 else if (file.ResolveExecutableLocation()) 604 { 605 char path[PATH_MAX]; 606 file.GetPath (path, sizeof(path)); 607 m_option_data.m_args.push_back (path); 608 } 609 else 610 error.SetErrorStringWithFormat("file specified in --file (-f) option doesn't exist: '%s'", optarg); 611 } 612 break; 613 614 case 'a': 615 if (!m_debugger.SetDefaultArchitecture (optarg)) 616 error.SetErrorStringWithFormat("invalid architecture in the -a or --arch option: '%s'", optarg); 617 break; 618 619 case 'l': 620 m_option_data.m_script_lang = m_debugger.GetScriptingLanguage (optarg); 621 break; 622 623 case 'd': 624 m_option_data.m_debug_mode = true; 625 break; 626 627 case 'n': 628 m_option_data.m_process_name = optarg; 629 break; 630 631 case 'w': 632 m_option_data.m_wait_for = true; 633 break; 634 635 case 'p': 636 { 637 char *remainder; 638 m_option_data.m_process_pid = strtol (optarg, &remainder, 0); 639 if (remainder == optarg || *remainder != '\0') 640 error.SetErrorStringWithFormat ("Could not convert process PID: \"%s\" into a pid.", 641 optarg); 642 } 643 break; 644 case 's': 645 { 646 SBFileSpec file(optarg); 647 if (file.Exists()) 648 m_option_data.m_source_command_files.push_back (optarg); 649 else if (file.ResolveExecutableLocation()) 650 { 651 char final_path[PATH_MAX]; 652 file.GetPath (final_path, sizeof(final_path)); 653 std::string path_str (final_path); 654 m_option_data.m_source_command_files.push_back (path_str); 655 } 656 else 657 error.SetErrorStringWithFormat("file specified in --source (-s) option doesn't exist: '%s'", optarg); 658 } 659 break; 660 661 default: 662 m_option_data.m_print_help = true; 663 error.SetErrorStringWithFormat ("unrecognized option %c", short_option); 664 break; 665 } 666 } 667 else 668 { 669 error.SetErrorStringWithFormat ("invalid option with value %i", val); 670 } 671 if (error.Fail()) 672 { 673 return error; 674 } 675 } 676 } 677 678 if (error.Fail() || m_option_data.m_print_help) 679 { 680 ShowUsage (out_fh, g_options, m_option_data); 681 exit = true; 682 } 683 else if (m_option_data.m_print_version) 684 { 685 ::fprintf (out_fh, "%s\n", m_debugger.GetVersionString()); 686 exit = true; 687 } 688 else if (! m_option_data.m_crash_log.empty()) 689 { 690 // Handle crash log stuff here. 691 } 692 else if (m_option_data.m_process_name.empty() && m_option_data.m_process_pid == LLDB_INVALID_PROCESS_ID) 693 { 694 // Any arguments that are left over after option parsing are for 695 // the program. If a file was specified with -f then the filename 696 // is already in the m_option_data.m_args array, and any remaining args 697 // are arguments for the inferior program. If no file was specified with 698 // -f, then what is left is the program name followed by any arguments. 699 700 // Skip any options we consumed with getopt_long 701 argc -= optind; 702 argv += optind; 703 704 if (argc > 0) 705 { 706 for (int arg_idx=0; arg_idx<argc; ++arg_idx) 707 { 708 const char *arg = argv[arg_idx]; 709 if (arg) 710 m_option_data.m_args.push_back (arg); 711 } 712 } 713 714 } 715 else 716 { 717 // Skip any options we consumed with getopt_long 718 argc -= optind; 719 argv += optind; 720 721 if (argc > 0) 722 ::fprintf (out_fh, "Warning: program arguments are ignored when attaching.\n"); 723 } 724 725 return error; 726 } 727 728 size_t 729 Driver::GetProcessSTDOUT () 730 { 731 // The process has stuff waiting for stdout; get it and write it out to the appropriate place. 732 char stdio_buffer[1024]; 733 size_t len; 734 size_t total_bytes = 0; 735 while ((len = m_debugger.GetSelectedTarget().GetProcess().GetSTDOUT (stdio_buffer, sizeof (stdio_buffer))) > 0) 736 { 737 m_io_channel_ap->OutWrite (stdio_buffer, len, ASYNC); 738 total_bytes += len; 739 } 740 return total_bytes; 741 } 742 743 size_t 744 Driver::GetProcessSTDERR () 745 { 746 // The process has stuff waiting for stderr; get it and write it out to the appropriate place. 747 char stdio_buffer[1024]; 748 size_t len; 749 size_t total_bytes = 0; 750 while ((len = m_debugger.GetSelectedTarget().GetProcess().GetSTDERR (stdio_buffer, sizeof (stdio_buffer))) > 0) 751 { 752 m_io_channel_ap->ErrWrite (stdio_buffer, len, ASYNC); 753 total_bytes += len; 754 } 755 return total_bytes; 756 } 757 758 void 759 Driver::UpdateSelectedThread () 760 { 761 using namespace lldb; 762 SBProcess process(m_debugger.GetSelectedTarget().GetProcess()); 763 if (process.IsValid()) 764 { 765 SBThread curr_thread (process.GetSelectedThread()); 766 SBThread thread; 767 StopReason curr_thread_stop_reason = eStopReasonInvalid; 768 curr_thread_stop_reason = curr_thread.GetStopReason(); 769 770 if (!curr_thread.IsValid() || 771 curr_thread_stop_reason == eStopReasonInvalid || 772 curr_thread_stop_reason == eStopReasonNone) 773 { 774 // Prefer a thread that has just completed its plan over another thread as current thread. 775 SBThread plan_thread; 776 SBThread other_thread; 777 const size_t num_threads = process.GetNumThreads(); 778 size_t i; 779 for (i = 0; i < num_threads; ++i) 780 { 781 thread = process.GetThreadAtIndex(i); 782 StopReason thread_stop_reason = thread.GetStopReason(); 783 switch (thread_stop_reason) 784 { 785 default: 786 case eStopReasonInvalid: 787 case eStopReasonNone: 788 break; 789 790 case eStopReasonTrace: 791 case eStopReasonBreakpoint: 792 case eStopReasonWatchpoint: 793 case eStopReasonSignal: 794 case eStopReasonException: 795 if (!other_thread.IsValid()) 796 other_thread = thread; 797 break; 798 case eStopReasonPlanComplete: 799 if (!plan_thread.IsValid()) 800 plan_thread = thread; 801 break; 802 } 803 } 804 if (plan_thread.IsValid()) 805 process.SetSelectedThread (plan_thread); 806 else if (other_thread.IsValid()) 807 process.SetSelectedThread (other_thread); 808 else 809 { 810 if (curr_thread.IsValid()) 811 thread = curr_thread; 812 else 813 thread = process.GetThreadAtIndex(0); 814 815 if (thread.IsValid()) 816 process.SetSelectedThread (thread); 817 } 818 } 819 } 820 } 821 822 823 // This function handles events that were broadcast by the process. 824 void 825 Driver::HandleProcessEvent (const SBEvent &event) 826 { 827 using namespace lldb; 828 const uint32_t event_type = event.GetType(); 829 830 if (event_type & SBProcess::eBroadcastBitSTDOUT) 831 { 832 // The process has stdout available, get it and write it out to the 833 // appropriate place. 834 GetProcessSTDOUT (); 835 } 836 else if (event_type & SBProcess::eBroadcastBitSTDERR) 837 { 838 // The process has stderr available, get it and write it out to the 839 // appropriate place. 840 GetProcessSTDERR (); 841 } 842 else if (event_type & SBProcess::eBroadcastBitStateChanged) 843 { 844 // Drain all stout and stderr so we don't see any output come after 845 // we print our prompts 846 GetProcessSTDOUT (); 847 GetProcessSTDERR (); 848 // Something changed in the process; get the event and report the process's current status and location to 849 // the user. 850 StateType event_state = SBProcess::GetStateFromEvent (event); 851 if (event_state == eStateInvalid) 852 return; 853 854 SBProcess process (SBProcess::GetProcessFromEvent (event)); 855 assert (process.IsValid()); 856 857 switch (event_state) 858 { 859 case eStateInvalid: 860 case eStateUnloaded: 861 case eStateConnected: 862 case eStateAttaching: 863 case eStateLaunching: 864 case eStateStepping: 865 case eStateDetached: 866 { 867 char message[1024]; 868 int message_len = ::snprintf (message, sizeof(message), "Process %d %s\n", process.GetProcessID(), 869 m_debugger.StateAsCString (event_state)); 870 m_io_channel_ap->OutWrite(message, message_len, ASYNC); 871 } 872 break; 873 874 case eStateRunning: 875 // Don't be chatty when we run... 876 break; 877 878 case eStateExited: 879 { 880 SBCommandReturnObject result; 881 m_debugger.GetCommandInterpreter().HandleCommand("process status", result, false); 882 m_io_channel_ap->ErrWrite (result.GetError(), result.GetErrorSize(), ASYNC); 883 m_io_channel_ap->OutWrite (result.GetOutput(), result.GetOutputSize(), ASYNC); 884 } 885 break; 886 887 case eStateStopped: 888 case eStateCrashed: 889 case eStateSuspended: 890 // Make sure the program hasn't been auto-restarted: 891 if (SBProcess::GetRestartedFromEvent (event)) 892 { 893 // FIXME: Do we want to report this, or would that just be annoyingly chatty? 894 char message[1024]; 895 int message_len = ::snprintf (message, sizeof(message), "Process %d stopped and was programmatically restarted.\n", 896 process.GetProcessID()); 897 m_io_channel_ap->OutWrite(message, message_len, ASYNC); 898 } 899 else 900 { 901 SBCommandReturnObject result; 902 UpdateSelectedThread (); 903 m_debugger.GetCommandInterpreter().HandleCommand("process status", result, false); 904 m_io_channel_ap->ErrWrite (result.GetError(), result.GetErrorSize(), ASYNC); 905 m_io_channel_ap->OutWrite (result.GetOutput(), result.GetOutputSize(), ASYNC); 906 } 907 break; 908 } 909 } 910 } 911 912 // This function handles events broadcast by the IOChannel (HasInput, UserInterrupt, or ThreadShouldExit). 913 914 bool 915 Driver::HandleIOEvent (const SBEvent &event) 916 { 917 bool quit = false; 918 919 const uint32_t event_type = event.GetType(); 920 921 if (event_type & IOChannel::eBroadcastBitHasUserInput) 922 { 923 // We got some input (i.e. a command string) from the user; pass it off to the command interpreter for 924 // handling. 925 926 const char *command_string = SBEvent::GetCStringFromEvent(event); 927 if (command_string == NULL) 928 command_string = ""; 929 SBCommandReturnObject result; 930 931 // We don't want the result to bypass the OutWrite function in IOChannel, as this can result in odd 932 // output orderings and problems with the prompt. 933 m_debugger.GetCommandInterpreter().HandleCommand (command_string, result, true); 934 935 if (result.GetOutputSize() > 0) 936 m_io_channel_ap->OutWrite (result.GetOutput(), result.GetOutputSize(), NO_ASYNC); 937 938 if (result.GetErrorSize() > 0) 939 m_io_channel_ap->OutWrite (result.GetError(), result.GetErrorSize(), NO_ASYNC); 940 941 // We are done getting and running our command, we can now clear the 942 // m_waiting_for_command so we can get another one. 943 m_waiting_for_command = false; 944 945 // If our editline input reader is active, it means another input reader 946 // got pushed onto the input reader and caused us to become deactivated. 947 // When the input reader above us gets popped, we will get re-activated 948 // and our prompt will refresh in our callback 949 if (m_editline_reader.IsActive()) 950 { 951 ReadyForCommand (); 952 } 953 } 954 else if (event_type & IOChannel::eBroadcastBitUserInterrupt) 955 { 956 // This is here to handle control-c interrupts from the user. It has not yet really been implemented. 957 // TO BE DONE: PROPERLY HANDLE CONTROL-C FROM USER 958 //m_io_channel_ap->CancelInput(); 959 // Anything else? Send Interrupt to process? 960 } 961 else if ((event_type & IOChannel::eBroadcastBitThreadShouldExit) || 962 (event_type & IOChannel::eBroadcastBitThreadDidExit)) 963 { 964 // If the IOChannel thread is trying to go away, then it is definitely 965 // time to end the debugging session. 966 quit = true; 967 } 968 969 return quit; 970 } 971 972 void 973 Driver::MasterThreadBytesReceived (void *baton, const void *src, size_t src_len) 974 { 975 Driver *driver = (Driver*)baton; 976 driver->GetFromMaster ((const char *)src, src_len); 977 } 978 979 void 980 Driver::GetFromMaster (const char *src, size_t src_len) 981 { 982 // Echo the characters back to the Debugger's stdout, that way if you 983 // type characters while a command is running, you'll see what you've typed. 984 FILE *out_fh = m_debugger.GetOutputFileHandle(); 985 if (out_fh) 986 ::fwrite (src, 1, src_len, out_fh); 987 } 988 989 size_t 990 Driver::EditLineInputReaderCallback 991 ( 992 void *baton, 993 SBInputReader *reader, 994 InputReaderAction notification, 995 const char *bytes, 996 size_t bytes_len 997 ) 998 { 999 Driver *driver = (Driver *)baton; 1000 1001 switch (notification) 1002 { 1003 case eInputReaderActivate: 1004 break; 1005 1006 case eInputReaderReactivate: 1007 driver->ReadyForCommand(); 1008 break; 1009 1010 case eInputReaderDeactivate: 1011 break; 1012 1013 case eInputReaderAsynchronousOutputWritten: 1014 if (driver->m_io_channel_ap.get() != NULL) 1015 driver->m_io_channel_ap->RefreshPrompt(); 1016 break; 1017 1018 case eInputReaderInterrupt: 1019 if (driver->m_io_channel_ap.get() != NULL) 1020 { 1021 driver->m_io_channel_ap->OutWrite ("^C\n", 3, NO_ASYNC); 1022 driver->m_io_channel_ap->RefreshPrompt(); 1023 } 1024 break; 1025 1026 case eInputReaderEndOfFile: 1027 if (driver->m_io_channel_ap.get() != NULL) 1028 { 1029 driver->m_io_channel_ap->OutWrite ("^D\n", 3, NO_ASYNC); 1030 driver->m_io_channel_ap->RefreshPrompt (); 1031 } 1032 write (driver->m_editline_pty.GetMasterFileDescriptor(), "quit\n", 5); 1033 break; 1034 1035 case eInputReaderGotToken: 1036 write (driver->m_editline_pty.GetMasterFileDescriptor(), bytes, bytes_len); 1037 break; 1038 1039 case eInputReaderDone: 1040 break; 1041 } 1042 return bytes_len; 1043 } 1044 1045 void 1046 Driver::MainLoop () 1047 { 1048 char error_str[1024]; 1049 if (m_editline_pty.OpenFirstAvailableMaster(O_RDWR|O_NOCTTY, error_str, sizeof(error_str)) == false) 1050 { 1051 ::fprintf (stderr, "error: failed to open driver pseudo terminal : %s", error_str); 1052 exit(1); 1053 } 1054 else 1055 { 1056 const char *driver_slave_name = m_editline_pty.GetSlaveName (error_str, sizeof(error_str)); 1057 if (driver_slave_name == NULL) 1058 { 1059 ::fprintf (stderr, "error: failed to get slave name for driver pseudo terminal : %s", error_str); 1060 exit(2); 1061 } 1062 else 1063 { 1064 m_editline_slave_fh = ::fopen (driver_slave_name, "r+"); 1065 if (m_editline_slave_fh == NULL) 1066 { 1067 SBError error; 1068 error.SetErrorToErrno(); 1069 ::fprintf (stderr, "error: failed to get open slave for driver pseudo terminal : %s", 1070 error.GetCString()); 1071 exit(3); 1072 } 1073 1074 ::setbuf (m_editline_slave_fh, NULL); 1075 } 1076 } 1077 1078 lldb_utility::PseudoTerminal editline_output_pty; 1079 FILE *editline_output_slave_fh = NULL; 1080 1081 if (editline_output_pty.OpenFirstAvailableMaster (O_RDWR|O_NOCTTY, error_str, sizeof (error_str)) == false) 1082 { 1083 ::fprintf (stderr, "error: failed to open output pseudo terminal : %s", error_str); 1084 exit(1); 1085 } 1086 else 1087 { 1088 const char *output_slave_name = editline_output_pty.GetSlaveName (error_str, sizeof(error_str)); 1089 if (output_slave_name == NULL) 1090 { 1091 ::fprintf (stderr, "error: failed to get slave name for output pseudo terminal : %s", error_str); 1092 exit(2); 1093 } 1094 else 1095 { 1096 editline_output_slave_fh = ::fopen (output_slave_name, "r+"); 1097 if (editline_output_slave_fh == NULL) 1098 { 1099 SBError error; 1100 error.SetErrorToErrno(); 1101 ::fprintf (stderr, "error: failed to get open slave for output pseudo terminal : %s", 1102 error.GetCString()); 1103 exit(3); 1104 } 1105 ::setbuf (editline_output_slave_fh, NULL); 1106 } 1107 } 1108 1109 // struct termios stdin_termios; 1110 1111 if (::tcgetattr(STDIN_FILENO, &g_old_stdin_termios) == 0) 1112 atexit (reset_stdin_termios); 1113 1114 ::setbuf (stdin, NULL); 1115 ::setbuf (stdout, NULL); 1116 1117 m_debugger.SetErrorFileHandle (stderr, false); 1118 m_debugger.SetOutputFileHandle (stdout, false); 1119 m_debugger.SetInputFileHandle (stdin, true); 1120 1121 m_debugger.SetUseExternalEditor(m_option_data.m_use_external_editor); 1122 1123 // You have to drain anything that comes to the master side of the PTY. master_out_comm is 1124 // for that purpose. The reason you need to do this is a curious reason... editline will echo 1125 // characters to the PTY when it gets characters while el_gets is not running, and then when 1126 // you call el_gets (or el_getc) it will try to reset the terminal back to raw mode which blocks 1127 // if there are unconsumed characters in the out buffer. 1128 // However, you don't need to do anything with the characters, since editline will dump these 1129 // unconsumed characters after printing the prompt again in el_gets. 1130 1131 SBCommunication master_out_comm("driver.editline"); 1132 master_out_comm.SetCloseOnEOF (false); 1133 master_out_comm.AdoptFileDesriptor(m_editline_pty.GetMasterFileDescriptor(), false); 1134 master_out_comm.SetReadThreadBytesReceivedCallback(Driver::MasterThreadBytesReceived, this); 1135 1136 if (master_out_comm.ReadThreadStart () == false) 1137 { 1138 ::fprintf (stderr, "error: failed to start master out read thread"); 1139 exit(5); 1140 } 1141 1142 SBCommandInterpreter sb_interpreter = m_debugger.GetCommandInterpreter(); 1143 1144 m_io_channel_ap.reset (new IOChannel(m_editline_slave_fh, editline_output_slave_fh, stdout, stderr, this)); 1145 1146 SBCommunication out_comm_2("driver.editline_output"); 1147 out_comm_2.SetCloseOnEOF (false); 1148 out_comm_2.AdoptFileDesriptor (editline_output_pty.GetMasterFileDescriptor(), false); 1149 out_comm_2.SetReadThreadBytesReceivedCallback (IOChannel::LibeditOutputBytesReceived, m_io_channel_ap.get()); 1150 1151 if (out_comm_2.ReadThreadStart () == false) 1152 { 1153 ::fprintf (stderr, "error: failed to start libedit output read thread"); 1154 exit (5); 1155 } 1156 1157 1158 struct winsize window_size; 1159 if (isatty (STDIN_FILENO) 1160 && ::ioctl (STDIN_FILENO, TIOCGWINSZ, &window_size) == 0) 1161 { 1162 if (window_size.ws_col > 0) 1163 m_debugger.SetTerminalWidth (window_size.ws_col); 1164 } 1165 1166 // Since input can be redirected by the debugger, we must insert our editline 1167 // input reader in the queue so we know when our reader should be active 1168 // and so we can receive bytes only when we are supposed to. 1169 SBError err (m_editline_reader.Initialize (m_debugger, 1170 Driver::EditLineInputReaderCallback, // callback 1171 this, // baton 1172 eInputReaderGranularityByte, // token_size 1173 NULL, // end token - NULL means never done 1174 NULL, // prompt - taken care of elsewhere 1175 false)); // echo input - don't need Debugger 1176 // to do this, we handle it elsewhere 1177 1178 if (err.Fail()) 1179 { 1180 ::fprintf (stderr, "error: %s", err.GetCString()); 1181 exit (6); 1182 } 1183 1184 m_debugger.PushInputReader (m_editline_reader); 1185 1186 SBListener listener(m_debugger.GetListener()); 1187 if (listener.IsValid()) 1188 { 1189 1190 listener.StartListeningForEvents (*m_io_channel_ap, 1191 IOChannel::eBroadcastBitHasUserInput | 1192 IOChannel::eBroadcastBitUserInterrupt | 1193 IOChannel::eBroadcastBitThreadShouldExit | 1194 IOChannel::eBroadcastBitThreadDidStart | 1195 IOChannel::eBroadcastBitThreadDidExit); 1196 1197 if (m_io_channel_ap->Start ()) 1198 { 1199 bool iochannel_thread_exited = false; 1200 1201 listener.StartListeningForEvents (sb_interpreter.GetBroadcaster(), 1202 SBCommandInterpreter::eBroadcastBitQuitCommandReceived | 1203 SBCommandInterpreter::eBroadcastBitAsynchronousOutputData | 1204 SBCommandInterpreter::eBroadcastBitAsynchronousErrorData); 1205 1206 // Before we handle any options from the command line, we parse the 1207 // .lldbinit file in the user's home directory. 1208 SBCommandReturnObject result; 1209 sb_interpreter.SourceInitFileInHomeDirectory(result); 1210 if (GetDebugMode()) 1211 { 1212 result.PutError (m_debugger.GetErrorFileHandle()); 1213 result.PutOutput (m_debugger.GetOutputFileHandle()); 1214 } 1215 1216 // Now we handle options we got from the command line 1217 char command_string[PATH_MAX * 2]; 1218 const size_t num_source_command_files = GetNumSourceCommandFiles(); 1219 if (num_source_command_files > 0) 1220 { 1221 for (size_t i=0; i < num_source_command_files; ++i) 1222 { 1223 const char *command_file = GetSourceCommandFileAtIndex(i); 1224 ::snprintf (command_string, sizeof(command_string), "command source '%s'", command_file); 1225 m_debugger.GetCommandInterpreter().HandleCommand (command_string, result, false); 1226 if (GetDebugMode()) 1227 { 1228 result.PutError (m_debugger.GetErrorFileHandle()); 1229 result.PutOutput (m_debugger.GetOutputFileHandle()); 1230 } 1231 } 1232 } 1233 1234 const size_t num_args = m_option_data.m_args.size(); 1235 if (num_args > 0) 1236 { 1237 char arch_name[64]; 1238 if (m_debugger.GetDefaultArchitecture (arch_name, sizeof (arch_name))) 1239 ::snprintf (command_string, 1240 sizeof (command_string), 1241 "target create --arch=%s '%s'", 1242 arch_name, 1243 m_option_data.m_args[0].c_str()); 1244 else 1245 ::snprintf (command_string, 1246 sizeof(command_string), 1247 "target create '%s'", 1248 m_option_data.m_args[0].c_str()); 1249 1250 m_debugger.HandleCommand (command_string); 1251 1252 if (num_args > 1) 1253 { 1254 m_debugger.HandleCommand ("settings clear target.process.run-args"); 1255 char arg_cstr[1024]; 1256 for (size_t arg_idx = 1; arg_idx < num_args; ++arg_idx) 1257 { 1258 ::snprintf (arg_cstr, 1259 sizeof(arg_cstr), 1260 "settings append target.process.run-args \"%s\"", 1261 m_option_data.m_args[arg_idx].c_str()); 1262 m_debugger.HandleCommand (arg_cstr); 1263 } 1264 } 1265 } 1266 1267 // Now that all option parsing is done, we try and parse the .lldbinit 1268 // file in the current working directory 1269 sb_interpreter.SourceInitFileInCurrentWorkingDirectory (result); 1270 if (GetDebugMode()) 1271 { 1272 result.PutError(m_debugger.GetErrorFileHandle()); 1273 result.PutOutput(m_debugger.GetOutputFileHandle()); 1274 } 1275 1276 SBEvent event; 1277 1278 // Make sure the IO channel is started up before we try to tell it we 1279 // are ready for input 1280 listener.WaitForEventForBroadcasterWithType (UINT32_MAX, 1281 *m_io_channel_ap, 1282 IOChannel::eBroadcastBitThreadDidStart, 1283 event); 1284 // If we were asked to attach, then do that here: 1285 // I'm going to use the command string rather than directly 1286 // calling the API's because then I don't have to recode the 1287 // event handling here. 1288 if (!m_option_data.m_process_name.empty() 1289 || m_option_data.m_process_pid != LLDB_INVALID_PROCESS_ID) 1290 { 1291 std::string command_str("process attach "); 1292 if (m_option_data.m_process_pid != LLDB_INVALID_PROCESS_ID) 1293 { 1294 command_str.append("-p "); 1295 char pid_buffer[32]; 1296 ::snprintf (pid_buffer, sizeof(pid_buffer), "%d", m_option_data.m_process_pid); 1297 command_str.append(pid_buffer); 1298 } 1299 else 1300 { 1301 command_str.append("-n \""); 1302 command_str.append(m_option_data.m_process_name); 1303 command_str.push_back('\"'); 1304 if (m_option_data.m_wait_for) 1305 command_str.append(" -w"); 1306 } 1307 1308 if (m_debugger.GetOutputFileHandle()) 1309 ::fprintf (m_debugger.GetOutputFileHandle(), 1310 "Attaching to process with:\n %s\n", 1311 command_str.c_str()); 1312 1313 // Force the attach to be synchronous: 1314 bool orig_async = m_debugger.GetAsync(); 1315 m_debugger.SetAsync(true); 1316 m_debugger.HandleCommand(command_str.c_str()); 1317 m_debugger.SetAsync(orig_async); 1318 } 1319 1320 ReadyForCommand (); 1321 1322 bool done = false; 1323 while (!done) 1324 { 1325 listener.WaitForEvent (UINT32_MAX, event); 1326 if (event.IsValid()) 1327 { 1328 if (event.GetBroadcaster().IsValid()) 1329 { 1330 uint32_t event_type = event.GetType(); 1331 if (event.BroadcasterMatchesRef (*m_io_channel_ap)) 1332 { 1333 if ((event_type & IOChannel::eBroadcastBitThreadShouldExit) || 1334 (event_type & IOChannel::eBroadcastBitThreadDidExit)) 1335 { 1336 done = true; 1337 if (event_type & IOChannel::eBroadcastBitThreadDidExit) 1338 iochannel_thread_exited = true; 1339 } 1340 else 1341 done = HandleIOEvent (event); 1342 } 1343 else if (event.BroadcasterMatchesRef (m_debugger.GetSelectedTarget().GetProcess().GetBroadcaster())) 1344 { 1345 HandleProcessEvent (event); 1346 } 1347 else if (event.BroadcasterMatchesRef (sb_interpreter.GetBroadcaster())) 1348 { 1349 if (event_type & SBCommandInterpreter::eBroadcastBitQuitCommandReceived) 1350 done = true; 1351 else if (event_type & SBCommandInterpreter::eBroadcastBitAsynchronousErrorData) 1352 { 1353 const char *data = SBEvent::GetCStringFromEvent (event); 1354 m_io_channel_ap->ErrWrite (data, strlen(data), ASYNC); 1355 } 1356 else if (event_type & SBCommandInterpreter::eBroadcastBitAsynchronousOutputData) 1357 { 1358 const char *data = SBEvent::GetCStringFromEvent (event); 1359 m_io_channel_ap->OutWrite (data, strlen(data), ASYNC); 1360 } 1361 } 1362 } 1363 } 1364 } 1365 1366 reset_stdin_termios (); 1367 1368 CloseIOChannelFile (); 1369 1370 if (!iochannel_thread_exited) 1371 { 1372 event.Clear(); 1373 listener.GetNextEventForBroadcasterWithType (*m_io_channel_ap, 1374 IOChannel::eBroadcastBitThreadDidExit, 1375 event); 1376 if (!event.IsValid()) 1377 { 1378 // Send end EOF to the driver file descriptor 1379 m_io_channel_ap->Stop(); 1380 } 1381 } 1382 1383 SBDebugger::Destroy (m_debugger); 1384 } 1385 } 1386 } 1387 1388 1389 void 1390 Driver::ReadyForCommand () 1391 { 1392 if (m_waiting_for_command == false) 1393 { 1394 m_waiting_for_command = true; 1395 BroadcastEventByType (Driver::eBroadcastBitReadyForInput, true); 1396 } 1397 } 1398 1399 1400 void 1401 sigwinch_handler (int signo) 1402 { 1403 struct winsize window_size; 1404 if (isatty (STDIN_FILENO) 1405 && ::ioctl (STDIN_FILENO, TIOCGWINSZ, &window_size) == 0) 1406 { 1407 if ((window_size.ws_col > 0) && (strlen (g_debugger_name) > 0)) 1408 { 1409 char width_str_buffer[25]; 1410 ::sprintf (width_str_buffer, "%d", window_size.ws_col); 1411 SBDebugger::SetInternalVariable ("term-width", width_str_buffer, g_debugger_name); 1412 } 1413 } 1414 } 1415 1416 void 1417 sigint_handler (int signo) 1418 { 1419 static bool g_interrupt_sent = false; 1420 if (g_driver) 1421 { 1422 if (!g_interrupt_sent) 1423 { 1424 g_interrupt_sent = true; 1425 g_driver->GetDebugger().DispatchInputInterrupt(); 1426 g_interrupt_sent = false; 1427 return; 1428 } 1429 } 1430 1431 exit (signo); 1432 } 1433 1434 int 1435 main (int argc, char const *argv[], const char *envp[]) 1436 { 1437 SBDebugger::Initialize(); 1438 1439 SBHostOS::ThreadCreated ("<lldb.driver.main-thread>"); 1440 1441 signal (SIGPIPE, SIG_IGN); 1442 signal (SIGWINCH, sigwinch_handler); 1443 signal (SIGINT, sigint_handler); 1444 1445 // Create a scope for driver so that the driver object will destroy itself 1446 // before SBDebugger::Terminate() is called. 1447 { 1448 Driver driver; 1449 1450 bool exit = false; 1451 SBError error (driver.ParseArgs (argc, argv, stdout, exit)); 1452 if (error.Fail()) 1453 { 1454 const char *error_cstr = error.GetCString (); 1455 if (error_cstr) 1456 ::fprintf (stderr, "error: %s\n", error_cstr); 1457 } 1458 else if (!exit) 1459 { 1460 driver.MainLoop (); 1461 } 1462 } 1463 1464 SBDebugger::Terminate(); 1465 return 0; 1466 } 1467