Driver.cpp revision 269024
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 <stdio.h> 13#include <string.h> 14#include <stdlib.h> 15#include <limits.h> 16#include <fcntl.h> 17 18#include <string> 19 20#include <thread> 21#include "lldb/API/SBBreakpoint.h" 22#include "lldb/API/SBCommandInterpreter.h" 23#include "lldb/API/SBCommandReturnObject.h" 24#include "lldb/API/SBCommunication.h" 25#include "lldb/API/SBDebugger.h" 26#include "lldb/API/SBEvent.h" 27#include "lldb/API/SBHostOS.h" 28#include "lldb/API/SBListener.h" 29#include "lldb/API/SBStream.h" 30#include "lldb/API/SBTarget.h" 31#include "lldb/API/SBThread.h" 32#include "lldb/API/SBProcess.h" 33 34using namespace lldb; 35 36static void reset_stdin_termios (); 37static bool g_old_stdin_termios_is_valid = false; 38static struct termios g_old_stdin_termios; 39 40static char *g_debugger_name = (char *) ""; 41static Driver *g_driver = NULL; 42 43// In the Driver::MainLoop, we change the terminal settings. This function is 44// added as an atexit handler to make sure we clean them up. 45static void 46reset_stdin_termios () 47{ 48 if (g_old_stdin_termios_is_valid) 49 { 50 g_old_stdin_termios_is_valid = false; 51 ::tcsetattr (STDIN_FILENO, TCSANOW, &g_old_stdin_termios); 52 } 53} 54 55typedef struct 56{ 57 uint32_t usage_mask; // Used to mark options that can be used together. If (1 << n & usage_mask) != 0 58 // then this option belongs to option set n. 59 bool required; // This option is required (in the current usage level) 60 const char * long_option; // Full name for this option. 61 int short_option; // Single character for this option. 62 int option_has_arg; // no_argument, required_argument or optional_argument 63 uint32_t completion_type; // Cookie the option class can use to do define the argument completion. 64 lldb::CommandArgumentType argument_type; // Type of argument this option takes 65 const char * usage_text; // Full text explaining what this options does and what (if any) argument to 66 // pass it. 67} OptionDefinition; 68 69#define LLDB_3_TO_5 LLDB_OPT_SET_3|LLDB_OPT_SET_4|LLDB_OPT_SET_5 70#define LLDB_4_TO_5 LLDB_OPT_SET_4|LLDB_OPT_SET_5 71 72static OptionDefinition g_options[] = 73{ 74 { LLDB_OPT_SET_1, true , "help" , 'h', no_argument , 0, eArgTypeNone, 75 "Prints out the usage information for the LLDB debugger." }, 76 { LLDB_OPT_SET_2, true , "version" , 'v', no_argument , 0, eArgTypeNone, 77 "Prints out the current version number of the LLDB debugger." }, 78 { LLDB_OPT_SET_3, true , "arch" , 'a', required_argument, 0, eArgTypeArchitecture, 79 "Tells the debugger to use the specified architecture when starting and running the program. <architecture> must " 80 "be one of the architectures for which the program was compiled." }, 81 { LLDB_OPT_SET_3, true , "file" , 'f', required_argument, 0, eArgTypeFilename, 82 "Tells the debugger to use the file <filename> as the program to be debugged." }, 83 { LLDB_OPT_SET_3, false, "core" , 'c', required_argument, 0, eArgTypeFilename, 84 "Tells the debugger to use the fullpath to <path> as the core file." }, 85 { LLDB_OPT_SET_5, true , "attach-pid" , 'p', required_argument, 0, eArgTypePid, 86 "Tells the debugger to attach to a process with the given pid." }, 87 { LLDB_OPT_SET_4, true , "attach-name" , 'n', required_argument, 0, eArgTypeProcessName, 88 "Tells the debugger to attach to a process with the given name." }, 89 { LLDB_OPT_SET_4, true , "wait-for" , 'w', no_argument , 0, eArgTypeNone, 90 "Tells the debugger to wait for a process with the given pid or name to launch before attaching." }, 91 { LLDB_3_TO_5, false, "source" , 's', required_argument, 0, eArgTypeFilename, 92 "Tells the debugger to read in and execute the lldb commands in the given file, after any file provided on the command line has been loaded." }, 93 { LLDB_3_TO_5, false, "one-line" , 'o', required_argument, 0, eArgTypeNone, 94 "Tells the debugger to execute this one-line lldb command after any file provided on the command line has been loaded." }, 95 { LLDB_3_TO_5, false, "source-before-file" , 'S', required_argument, 0, eArgTypeFilename, 96 "Tells the debugger to read in and execute the lldb commands in the given file, before any file provided on the command line has been loaded." }, 97 { LLDB_3_TO_5, false, "one-line-before-file" , 'O', required_argument, 0, eArgTypeNone, 98 "Tells the debugger to execute this one-line lldb command before any file provided on the command line has been loaded." }, 99 { LLDB_3_TO_5, false, "source-quietly" , 'Q', no_argument , 0, eArgTypeNone, 100 "Tells the debugger suppress output from commands provided in the -s, -S, -O and -o commands." }, 101 { LLDB_3_TO_5, false, "editor" , 'e', no_argument , 0, eArgTypeNone, 102 "Tells the debugger to open source files using the host's \"external editor\" mechanism." }, 103 { LLDB_3_TO_5, false, "no-lldbinit" , 'x', no_argument , 0, eArgTypeNone, 104 "Do not automatically parse any '.lldbinit' files." }, 105 { LLDB_3_TO_5, false, "no-use-colors" , 'X', no_argument , 0, eArgTypeNone, 106 "Do not use colors." }, 107 { LLDB_OPT_SET_6, true , "python-path" , 'P', no_argument , 0, eArgTypeNone, 108 "Prints out the path to the lldb.py file for this version of lldb." }, 109 { LLDB_3_TO_5, false, "script-language", 'l', required_argument, 0, eArgTypeScriptLang, 110 "Tells the debugger to use the specified scripting language for user-defined scripts, rather than the default. " 111 "Valid scripting languages that can be specified include Python, Perl, Ruby and Tcl. Currently only the Python " 112 "extensions have been implemented." }, 113 { LLDB_3_TO_5, false, "debug" , 'd', no_argument , 0, eArgTypeNone, 114 "Tells the debugger to print out extra information for debugging itself." }, 115 { 0, false, NULL , 0 , 0 , 0, eArgTypeNone, NULL } 116}; 117 118static const uint32_t last_option_set_with_args = 2; 119 120Driver::Driver () : 121 SBBroadcaster ("Driver"), 122 m_debugger (SBDebugger::Create(false)), 123 m_option_data () 124{ 125 // We want to be able to handle CTRL+D in the terminal to have it terminate 126 // certain input 127 m_debugger.SetCloseInputOnEOF (false); 128 g_debugger_name = (char *) m_debugger.GetInstanceName(); 129 if (g_debugger_name == NULL) 130 g_debugger_name = (char *) ""; 131 g_driver = this; 132} 133 134Driver::~Driver () 135{ 136 g_driver = NULL; 137 g_debugger_name = NULL; 138} 139 140 141// This function takes INDENT, which tells how many spaces to output at the front 142// of each line; TEXT, which is the text that is to be output. It outputs the 143// text, on multiple lines if necessary, to RESULT, with INDENT spaces at the 144// front of each line. It breaks lines on spaces, tabs or newlines, shortening 145// the line if necessary to not break in the middle of a word. It assumes that 146// each output line should contain a maximum of OUTPUT_MAX_COLUMNS characters. 147 148void 149OutputFormattedUsageText (FILE *out, int indent, const char *text, int output_max_columns) 150{ 151 int len = strlen (text); 152 std::string text_string (text); 153 154 // Force indentation to be reasonable. 155 if (indent >= output_max_columns) 156 indent = 0; 157 158 // Will it all fit on one line? 159 160 if (len + indent < output_max_columns) 161 // Output as a single line 162 fprintf (out, "%*s%s\n", indent, "", text); 163 else 164 { 165 // We need to break it up into multiple lines. 166 int text_width = output_max_columns - indent - 1; 167 int start = 0; 168 int end = start; 169 int final_end = len; 170 int sub_len; 171 172 while (end < final_end) 173 { 174 // Dont start the 'text' on a space, since we're already outputting the indentation. 175 while ((start < final_end) && (text[start] == ' ')) 176 start++; 177 178 end = start + text_width; 179 if (end > final_end) 180 end = final_end; 181 else 182 { 183 // If we're not at the end of the text, make sure we break the line on white space. 184 while (end > start 185 && text[end] != ' ' && text[end] != '\t' && text[end] != '\n') 186 end--; 187 } 188 sub_len = end - start; 189 std::string substring = text_string.substr (start, sub_len); 190 fprintf (out, "%*s%s\n", indent, "", substring.c_str()); 191 start = end + 1; 192 } 193 } 194} 195 196void 197ShowUsage (FILE *out, OptionDefinition *option_table, Driver::OptionData data) 198{ 199 uint32_t screen_width = 80; 200 uint32_t indent_level = 0; 201 const char *name = "lldb"; 202 203 fprintf (out, "\nUsage:\n\n"); 204 205 indent_level += 2; 206 207 208 // First, show each usage level set of options, e.g. <cmd> [options-for-level-0] 209 // <cmd> [options-for-level-1] 210 // etc. 211 212 uint32_t num_options; 213 uint32_t num_option_sets = 0; 214 215 for (num_options = 0; option_table[num_options].long_option != NULL; ++num_options) 216 { 217 uint32_t this_usage_mask = option_table[num_options].usage_mask; 218 if (this_usage_mask == LLDB_OPT_SET_ALL) 219 { 220 if (num_option_sets == 0) 221 num_option_sets = 1; 222 } 223 else 224 { 225 for (uint32_t j = 0; j < LLDB_MAX_NUM_OPTION_SETS; j++) 226 { 227 if (this_usage_mask & 1 << j) 228 { 229 if (num_option_sets <= j) 230 num_option_sets = j + 1; 231 } 232 } 233 } 234 } 235 236 for (uint32_t opt_set = 0; opt_set < num_option_sets; opt_set++) 237 { 238 uint32_t opt_set_mask; 239 240 opt_set_mask = 1 << opt_set; 241 242 if (opt_set > 0) 243 fprintf (out, "\n"); 244 fprintf (out, "%*s%s", indent_level, "", name); 245 bool is_help_line = false; 246 247 for (uint32_t i = 0; i < num_options; ++i) 248 { 249 if (option_table[i].usage_mask & opt_set_mask) 250 { 251 CommandArgumentType arg_type = option_table[i].argument_type; 252 const char *arg_name = SBCommandInterpreter::GetArgumentTypeAsCString (arg_type); 253 // This is a bit of a hack, but there's no way to say certain options don't have arguments yet... 254 // so we do it by hand here. 255 if (option_table[i].short_option == 'h') 256 is_help_line = true; 257 258 if (option_table[i].required) 259 { 260 if (option_table[i].option_has_arg == required_argument) 261 fprintf (out, " -%c <%s>", option_table[i].short_option, arg_name); 262 else if (option_table[i].option_has_arg == optional_argument) 263 fprintf (out, " -%c [<%s>]", option_table[i].short_option, arg_name); 264 else 265 fprintf (out, " -%c", option_table[i].short_option); 266 } 267 else 268 { 269 if (option_table[i].option_has_arg == required_argument) 270 fprintf (out, " [-%c <%s>]", option_table[i].short_option, arg_name); 271 else if (option_table[i].option_has_arg == optional_argument) 272 fprintf (out, " [-%c [<%s>]]", option_table[i].short_option, arg_name); 273 else 274 fprintf (out, " [-%c]", option_table[i].short_option); 275 } 276 } 277 } 278 if (!is_help_line && (opt_set <= last_option_set_with_args)) 279 fprintf (out, " [[--] <PROGRAM-ARG-1> [<PROGRAM_ARG-2> ...]]"); 280 } 281 282 fprintf (out, "\n\n"); 283 284 // Now print out all the detailed information about the various options: long form, short form and help text: 285 // -- long_name <argument> 286 // - short <argument> 287 // help text 288 289 // This variable is used to keep track of which options' info we've printed out, because some options can be in 290 // more than one usage level, but we only want to print the long form of its information once. 291 292 Driver::OptionData::OptionSet options_seen; 293 Driver::OptionData::OptionSet::iterator pos; 294 295 indent_level += 5; 296 297 for (uint32_t i = 0; i < num_options; ++i) 298 { 299 // Only print this option if we haven't already seen it. 300 pos = options_seen.find (option_table[i].short_option); 301 if (pos == options_seen.end()) 302 { 303 CommandArgumentType arg_type = option_table[i].argument_type; 304 const char *arg_name = SBCommandInterpreter::GetArgumentTypeAsCString (arg_type); 305 306 options_seen.insert (option_table[i].short_option); 307 fprintf (out, "%*s-%c ", indent_level, "", option_table[i].short_option); 308 if (arg_type != eArgTypeNone) 309 fprintf (out, "<%s>", arg_name); 310 fprintf (out, "\n"); 311 fprintf (out, "%*s--%s ", indent_level, "", option_table[i].long_option); 312 if (arg_type != eArgTypeNone) 313 fprintf (out, "<%s>", arg_name); 314 fprintf (out, "\n"); 315 indent_level += 5; 316 OutputFormattedUsageText (out, indent_level, option_table[i].usage_text, screen_width); 317 indent_level -= 5; 318 fprintf (out, "\n"); 319 } 320 } 321 322 indent_level -= 5; 323 324 fprintf (out, "\n%*sNotes:\n", 325 indent_level, ""); 326 indent_level += 5; 327 328 fprintf (out, "\n%*sMultiple \"-s\" and \"-o\" options can be provided. They will be processed from left to right in order, " 329 "\n%*swith the source files and commands interleaved. The same is true of the \"-S\" and \"-O\" options." 330 "\n%*sThe before file and after file sets can intermixed freely, the command parser will sort them out." 331 "\n%*sThe order of the file specifiers (\"-c\", \"-f\", etc.) is not significant in this regard.\n\n", 332 indent_level, "", 333 indent_level, "", 334 indent_level, "", 335 indent_level, ""); 336 337 fprintf (out, "\n%*sIf you don't provide -f then the first argument will be the file to be debugged" 338 "\n%*swhich means that '%s -- <filename> [<ARG1> [<ARG2>]]' also works." 339 "\n%*sBut remember to end the options with \"--\" if any of your arguments have a \"-\" in them.\n\n", 340 indent_level, "", 341 indent_level, "", 342 name, 343 indent_level, ""); 344} 345 346void 347BuildGetOptTable (OptionDefinition *expanded_option_table, std::vector<struct option> &getopt_table, 348 uint32_t num_options) 349{ 350 if (num_options == 0) 351 return; 352 353 uint32_t i; 354 uint32_t j; 355 std::bitset<256> option_seen; 356 357 getopt_table.resize (num_options + 1); 358 359 for (i = 0, j = 0; i < num_options; ++i) 360 { 361 char short_opt = expanded_option_table[i].short_option; 362 363 if (option_seen.test(short_opt) == false) 364 { 365 getopt_table[j].name = expanded_option_table[i].long_option; 366 getopt_table[j].has_arg = expanded_option_table[i].option_has_arg; 367 getopt_table[j].flag = NULL; 368 getopt_table[j].val = expanded_option_table[i].short_option; 369 option_seen.set(short_opt); 370 ++j; 371 } 372 } 373 374 getopt_table[j].name = NULL; 375 getopt_table[j].has_arg = 0; 376 getopt_table[j].flag = NULL; 377 getopt_table[j].val = 0; 378 379} 380 381Driver::OptionData::OptionData () : 382 m_args(), 383 m_script_lang (lldb::eScriptLanguageDefault), 384 m_core_file (), 385 m_crash_log (), 386 m_initial_commands (), 387 m_after_file_commands (), 388 m_debug_mode (false), 389 m_source_quietly(false), 390 m_print_version (false), 391 m_print_python_path (false), 392 m_print_help (false), 393 m_wait_for(false), 394 m_process_name(), 395 m_process_pid(LLDB_INVALID_PROCESS_ID), 396 m_use_external_editor(false), 397 m_seen_options() 398{ 399} 400 401Driver::OptionData::~OptionData () 402{ 403} 404 405void 406Driver::OptionData::Clear () 407{ 408 m_args.clear (); 409 m_script_lang = lldb::eScriptLanguageDefault; 410 m_initial_commands.clear (); 411 m_after_file_commands.clear (); 412 m_debug_mode = false; 413 m_source_quietly = false; 414 m_print_help = false; 415 m_print_version = false; 416 m_print_python_path = false; 417 m_use_external_editor = false; 418 m_wait_for = false; 419 m_process_name.erase(); 420 m_process_pid = LLDB_INVALID_PROCESS_ID; 421} 422 423void 424Driver::OptionData::AddInitialCommand (const char *command, bool before_file, bool is_file, SBError &error) 425{ 426 std::vector<std::pair<bool, std::string> > *command_set; 427 if (before_file) 428 command_set = &(m_initial_commands); 429 else 430 command_set = &(m_after_file_commands); 431 432 if (is_file) 433 { 434 SBFileSpec file(command); 435 if (file.Exists()) 436 command_set->push_back (std::pair<bool, std::string> (true, optarg)); 437 else if (file.ResolveExecutableLocation()) 438 { 439 char final_path[PATH_MAX]; 440 file.GetPath (final_path, sizeof(final_path)); 441 std::string path_str (final_path); 442 command_set->push_back (std::pair<bool, std::string> (true, path_str)); 443 } 444 else 445 error.SetErrorStringWithFormat("file specified in --source (-s) option doesn't exist: '%s'", optarg); 446 } 447 else 448 command_set->push_back (std::pair<bool, std::string> (false, optarg)); 449} 450 451void 452Driver::ResetOptionValues () 453{ 454 m_option_data.Clear (); 455} 456 457const char * 458Driver::GetFilename() const 459{ 460 if (m_option_data.m_args.empty()) 461 return NULL; 462 return m_option_data.m_args.front().c_str(); 463} 464 465const char * 466Driver::GetCrashLogFilename() const 467{ 468 if (m_option_data.m_crash_log.empty()) 469 return NULL; 470 return m_option_data.m_crash_log.c_str(); 471} 472 473lldb::ScriptLanguage 474Driver::GetScriptLanguage() const 475{ 476 return m_option_data.m_script_lang; 477} 478 479void 480Driver::ExecuteInitialCommands (bool before_file) 481{ 482 size_t num_commands; 483 std::vector<std::pair<bool, std::string> > *command_set; 484 if (before_file) 485 command_set = &(m_option_data.m_initial_commands); 486 else 487 command_set = &(m_option_data.m_after_file_commands); 488 489 num_commands = command_set->size(); 490 SBCommandReturnObject result; 491 bool old_async = GetDebugger().GetAsync(); 492 GetDebugger().SetAsync(false); 493 for (size_t idx = 0; idx < num_commands; idx++) 494 { 495 bool is_file = (*command_set)[idx].first; 496 const char *command = (*command_set)[idx].second.c_str(); 497 char command_string[PATH_MAX * 2]; 498 const bool dump_stream_only_if_no_immediate = true; 499 const char *executed_command = command; 500 if (is_file) 501 { 502 ::snprintf (command_string, sizeof(command_string), "command source -s %i '%s'", m_option_data.m_source_quietly, command); 503 executed_command = command_string; 504 } 505 506 m_debugger.GetCommandInterpreter().HandleCommand (executed_command, result, false); 507 if (!m_option_data.m_source_quietly || result.Succeeded() == false) 508 { 509 const size_t output_size = result.GetOutputSize(); 510 if (output_size > 0) 511 { 512 const char *cstr = result.GetOutput(dump_stream_only_if_no_immediate); 513 if (cstr) 514 printf ("%s", cstr); 515 } 516 const size_t error_size = result.GetErrorSize(); 517 if (error_size > 0) 518 { 519 const char *cstr = result.GetError(dump_stream_only_if_no_immediate); 520 if (cstr) 521 printf ("%s", cstr); 522 } 523 } 524 525 if (result.Succeeded() == false) 526 { 527 const char *type = before_file ? "before file" : "after_file"; 528 if (is_file) 529 ::fprintf(stderr, "Aborting %s command execution, command file: '%s' failed.\n", type, command); 530 else 531 ::fprintf(stderr, "Aborting %s command execution, command: '%s' failed.\n", type, command); 532 break; 533 } 534 result.Clear(); 535 } 536 GetDebugger().SetAsync(old_async); 537} 538 539bool 540Driver::GetDebugMode() const 541{ 542 return m_option_data.m_debug_mode; 543} 544 545 546// Check the arguments that were passed to this program to make sure they are valid and to get their 547// argument values (if any). Return a boolean value indicating whether or not to start up the full 548// debugger (i.e. the Command Interpreter) or not. Return FALSE if the arguments were invalid OR 549// if the user only wanted help or version information. 550 551SBError 552Driver::ParseArgs (int argc, const char *argv[], FILE *out_fh, bool &exiting) 553{ 554 ResetOptionValues (); 555 556 SBCommandReturnObject result; 557 558 SBError error; 559 std::string option_string; 560 struct option *long_options = NULL; 561 std::vector<struct option> long_options_vector; 562 uint32_t num_options; 563 564 for (num_options = 0; g_options[num_options].long_option != NULL; ++num_options) 565 /* Do Nothing. */; 566 567 if (num_options == 0) 568 { 569 if (argc > 1) 570 error.SetErrorStringWithFormat ("invalid number of options"); 571 return error; 572 } 573 574 BuildGetOptTable (g_options, long_options_vector, num_options); 575 576 if (long_options_vector.empty()) 577 long_options = NULL; 578 else 579 long_options = &long_options_vector.front(); 580 581 if (long_options == NULL) 582 { 583 error.SetErrorStringWithFormat ("invalid long options"); 584 return error; 585 } 586 587 // Build the option_string argument for call to getopt_long_only. 588 589 for (int i = 0; long_options[i].name != NULL; ++i) 590 { 591 if (long_options[i].flag == NULL) 592 { 593 option_string.push_back ((char) long_options[i].val); 594 switch (long_options[i].has_arg) 595 { 596 default: 597 case no_argument: 598 break; 599 case required_argument: 600 option_string.push_back (':'); 601 break; 602 case optional_argument: 603 option_string.append ("::"); 604 break; 605 } 606 } 607 } 608 609 // This is kind of a pain, but since we make the debugger in the Driver's constructor, we can't 610 // know at that point whether we should read in init files yet. So we don't read them in in the 611 // Driver constructor, then set the flags back to "read them in" here, and then if we see the 612 // "-n" flag, we'll turn it off again. Finally we have to read them in by hand later in the 613 // main loop. 614 615 m_debugger.SkipLLDBInitFiles (false); 616 m_debugger.SkipAppInitFiles (false); 617 618 // Prepare for & make calls to getopt_long_only. 619#if __GLIBC__ 620 optind = 0; 621#else 622 optreset = 1; 623 optind = 1; 624#endif 625 int val; 626 while (1) 627 { 628 int long_options_index = -1; 629 val = ::getopt_long_only (argc, const_cast<char **>(argv), option_string.c_str(), long_options, &long_options_index); 630 631 if (val == -1) 632 break; 633 else if (val == '?') 634 { 635 m_option_data.m_print_help = true; 636 error.SetErrorStringWithFormat ("unknown or ambiguous option"); 637 break; 638 } 639 else if (val == 0) 640 continue; 641 else 642 { 643 m_option_data.m_seen_options.insert ((char) val); 644 if (long_options_index == -1) 645 { 646 for (int i = 0; 647 long_options[i].name || long_options[i].has_arg || long_options[i].flag || long_options[i].val; 648 ++i) 649 { 650 if (long_options[i].val == val) 651 { 652 long_options_index = i; 653 break; 654 } 655 } 656 } 657 658 if (long_options_index >= 0) 659 { 660 const int short_option = g_options[long_options_index].short_option; 661 662 switch (short_option) 663 { 664 case 'h': 665 m_option_data.m_print_help = true; 666 break; 667 668 case 'v': 669 m_option_data.m_print_version = true; 670 break; 671 672 case 'P': 673 m_option_data.m_print_python_path = true; 674 break; 675 676 case 'c': 677 { 678 SBFileSpec file(optarg); 679 if (file.Exists()) 680 { 681 m_option_data.m_core_file = optarg; 682 } 683 else 684 error.SetErrorStringWithFormat("file specified in --core (-c) option doesn't exist: '%s'", optarg); 685 } 686 break; 687 688 case 'e': 689 m_option_data.m_use_external_editor = true; 690 break; 691 692 case 'x': 693 m_debugger.SkipLLDBInitFiles (true); 694 m_debugger.SkipAppInitFiles (true); 695 break; 696 697 case 'X': 698 m_debugger.SetUseColor (false); 699 break; 700 701 case 'f': 702 { 703 SBFileSpec file(optarg); 704 if (file.Exists()) 705 { 706 m_option_data.m_args.push_back (optarg); 707 } 708 else if (file.ResolveExecutableLocation()) 709 { 710 char path[PATH_MAX]; 711 file.GetPath (path, sizeof(path)); 712 m_option_data.m_args.push_back (path); 713 } 714 else 715 error.SetErrorStringWithFormat("file specified in --file (-f) option doesn't exist: '%s'", optarg); 716 } 717 break; 718 719 case 'a': 720 if (!m_debugger.SetDefaultArchitecture (optarg)) 721 error.SetErrorStringWithFormat("invalid architecture in the -a or --arch option: '%s'", optarg); 722 break; 723 724 case 'l': 725 m_option_data.m_script_lang = m_debugger.GetScriptingLanguage (optarg); 726 break; 727 728 case 'd': 729 m_option_data.m_debug_mode = true; 730 break; 731 732 case 'Q': 733 m_option_data.m_source_quietly = true; 734 break; 735 736 case 'n': 737 m_option_data.m_process_name = optarg; 738 break; 739 740 case 'w': 741 m_option_data.m_wait_for = true; 742 break; 743 744 case 'p': 745 { 746 char *remainder; 747 m_option_data.m_process_pid = strtol (optarg, &remainder, 0); 748 if (remainder == optarg || *remainder != '\0') 749 error.SetErrorStringWithFormat ("Could not convert process PID: \"%s\" into a pid.", 750 optarg); 751 } 752 break; 753 case 's': 754 m_option_data.AddInitialCommand(optarg, false, true, error); 755 break; 756 case 'o': 757 m_option_data.AddInitialCommand(optarg, false, false, error); 758 break; 759 case 'S': 760 m_option_data.AddInitialCommand(optarg, true, true, error); 761 break; 762 case 'O': 763 m_option_data.AddInitialCommand(optarg, true, false, error); 764 break; 765 default: 766 m_option_data.m_print_help = true; 767 error.SetErrorStringWithFormat ("unrecognized option %c", short_option); 768 break; 769 } 770 } 771 else 772 { 773 error.SetErrorStringWithFormat ("invalid option with value %i", val); 774 } 775 if (error.Fail()) 776 { 777 return error; 778 } 779 } 780 } 781 782 if (error.Fail() || m_option_data.m_print_help) 783 { 784 ShowUsage (out_fh, g_options, m_option_data); 785 exiting = true; 786 } 787 else if (m_option_data.m_print_version) 788 { 789 ::fprintf (out_fh, "%s\n", m_debugger.GetVersionString()); 790 exiting = true; 791 } 792 else if (m_option_data.m_print_python_path) 793 { 794 SBFileSpec python_file_spec = SBHostOS::GetLLDBPythonPath(); 795 if (python_file_spec.IsValid()) 796 { 797 char python_path[PATH_MAX]; 798 size_t num_chars = python_file_spec.GetPath(python_path, PATH_MAX); 799 if (num_chars < PATH_MAX) 800 { 801 ::fprintf (out_fh, "%s\n", python_path); 802 } 803 else 804 ::fprintf (out_fh, "<PATH TOO LONG>\n"); 805 } 806 else 807 ::fprintf (out_fh, "<COULD NOT FIND PATH>\n"); 808 exiting = true; 809 } 810 else if (m_option_data.m_process_name.empty() && m_option_data.m_process_pid == LLDB_INVALID_PROCESS_ID) 811 { 812 // Any arguments that are left over after option parsing are for 813 // the program. If a file was specified with -f then the filename 814 // is already in the m_option_data.m_args array, and any remaining args 815 // are arguments for the inferior program. If no file was specified with 816 // -f, then what is left is the program name followed by any arguments. 817 818 // Skip any options we consumed with getopt_long_only 819 argc -= optind; 820 argv += optind; 821 822 if (argc > 0) 823 { 824 for (int arg_idx=0; arg_idx<argc; ++arg_idx) 825 { 826 const char *arg = argv[arg_idx]; 827 if (arg) 828 m_option_data.m_args.push_back (arg); 829 } 830 } 831 832 } 833 else 834 { 835 // Skip any options we consumed with getopt_long_only 836 argc -= optind; 837 //argv += optind; // Commented out to keep static analyzer happy 838 839 if (argc > 0) 840 ::fprintf (out_fh, "Warning: program arguments are ignored when attaching.\n"); 841 } 842 843 return error; 844} 845 846void 847Driver::MainLoop () 848{ 849 if (::tcgetattr(STDIN_FILENO, &g_old_stdin_termios) == 0) 850 { 851 g_old_stdin_termios_is_valid = true; 852 atexit (reset_stdin_termios); 853 } 854 855 ::setbuf (stdin, NULL); 856 ::setbuf (stdout, NULL); 857 858 m_debugger.SetErrorFileHandle (stderr, false); 859 m_debugger.SetOutputFileHandle (stdout, false); 860 m_debugger.SetInputFileHandle (stdin, true); 861 862 m_debugger.SetUseExternalEditor(m_option_data.m_use_external_editor); 863 864 struct winsize window_size; 865 if (isatty (STDIN_FILENO) 866 && ::ioctl (STDIN_FILENO, TIOCGWINSZ, &window_size) == 0) 867 { 868 if (window_size.ws_col > 0) 869 m_debugger.SetTerminalWidth (window_size.ws_col); 870 } 871 872 SBCommandInterpreter sb_interpreter = m_debugger.GetCommandInterpreter(); 873 874 // Before we handle any options from the command line, we parse the 875 // .lldbinit file in the user's home directory. 876 SBCommandReturnObject result; 877 sb_interpreter.SourceInitFileInHomeDirectory(result); 878 if (GetDebugMode()) 879 { 880 result.PutError (m_debugger.GetErrorFileHandle()); 881 result.PutOutput (m_debugger.GetOutputFileHandle()); 882 } 883 884 // Now we handle options we got from the command line 885 // First source in the commands specified to be run before the file arguments are processed. 886 ExecuteInitialCommands(true); 887 888 // Was there a core file specified? 889 std::string core_file_spec(""); 890 if (!m_option_data.m_core_file.empty()) 891 core_file_spec.append("--core ").append(m_option_data.m_core_file); 892 893 char command_string[PATH_MAX * 2]; 894 const size_t num_args = m_option_data.m_args.size(); 895 if (num_args > 0) 896 { 897 char arch_name[64]; 898 if (m_debugger.GetDefaultArchitecture (arch_name, sizeof (arch_name))) 899 ::snprintf (command_string, 900 sizeof (command_string), 901 "target create --arch=%s %s \"%s\"", 902 arch_name, 903 core_file_spec.c_str(), 904 m_option_data.m_args[0].c_str()); 905 else 906 ::snprintf (command_string, 907 sizeof(command_string), 908 "target create %s \"%s\"", 909 core_file_spec.c_str(), 910 m_option_data.m_args[0].c_str()); 911 912 m_debugger.HandleCommand (command_string); 913 914 if (num_args > 1) 915 { 916 m_debugger.HandleCommand ("settings clear target.run-args"); 917 char arg_cstr[1024]; 918 for (size_t arg_idx = 1; arg_idx < num_args; ++arg_idx) 919 { 920 ::snprintf (arg_cstr, 921 sizeof(arg_cstr), 922 "settings append target.run-args \"%s\"", 923 m_option_data.m_args[arg_idx].c_str()); 924 m_debugger.HandleCommand (arg_cstr); 925 } 926 } 927 } 928 else if (!core_file_spec.empty()) 929 { 930 ::snprintf (command_string, 931 sizeof(command_string), 932 "target create %s", 933 core_file_spec.c_str()); 934 m_debugger.HandleCommand (command_string);; 935 } 936 else if (!m_option_data.m_process_name.empty()) 937 { 938 ::snprintf (command_string, 939 sizeof(command_string), 940 "process attach --name '%s'%s", 941 m_option_data.m_process_name.c_str(), 942 m_option_data.m_wait_for ? " --waitfor" : ""); 943 m_debugger.HandleCommand (command_string); 944 } 945 else if (LLDB_INVALID_PROCESS_ID != m_option_data.m_process_pid) 946 { 947 ::snprintf (command_string, 948 sizeof(command_string), 949 "process attach --pid %" PRIu64, 950 m_option_data.m_process_pid); 951 m_debugger.HandleCommand (command_string); 952 } 953 954 ExecuteInitialCommands(false); 955 956 // Now that all option parsing is done, we try and parse the .lldbinit 957 // file in the current working directory 958 sb_interpreter.SourceInitFileInCurrentWorkingDirectory (result); 959 if (GetDebugMode()) 960 { 961 result.PutError(m_debugger.GetErrorFileHandle()); 962 result.PutOutput(m_debugger.GetOutputFileHandle()); 963 } 964 965 bool handle_events = true; 966 bool spawn_thread = false; 967 m_debugger.RunCommandInterpreter(handle_events, spawn_thread); 968 969 reset_stdin_termios(); 970 fclose (stdin); 971 972 SBDebugger::Destroy (m_debugger); 973} 974 975 976void 977Driver::ResizeWindow (unsigned short col) 978{ 979 GetDebugger().SetTerminalWidth (col); 980} 981 982void 983sigwinch_handler (int signo) 984{ 985 struct winsize window_size; 986 if (isatty (STDIN_FILENO) 987 && ::ioctl (STDIN_FILENO, TIOCGWINSZ, &window_size) == 0) 988 { 989 if ((window_size.ws_col > 0) && g_driver != NULL) 990 { 991 g_driver->ResizeWindow (window_size.ws_col); 992 } 993 } 994} 995 996void 997sigint_handler (int signo) 998{ 999 static bool g_interrupt_sent = false; 1000 if (g_driver) 1001 { 1002 if (!g_interrupt_sent) 1003 { 1004 g_interrupt_sent = true; 1005 g_driver->GetDebugger().DispatchInputInterrupt(); 1006 g_interrupt_sent = false; 1007 return; 1008 } 1009 } 1010 1011 exit (signo); 1012} 1013 1014void 1015sigtstp_handler (int signo) 1016{ 1017 g_driver->GetDebugger().SaveInputTerminalState(); 1018 signal (signo, SIG_DFL); 1019 kill (getpid(), signo); 1020 signal (signo, sigtstp_handler); 1021} 1022 1023void 1024sigcont_handler (int signo) 1025{ 1026 g_driver->GetDebugger().RestoreInputTerminalState(); 1027 signal (signo, SIG_DFL); 1028 kill (getpid(), signo); 1029 signal (signo, sigcont_handler); 1030} 1031 1032int 1033main (int argc, char const *argv[], const char *envp[]) 1034{ 1035 SBDebugger::Initialize(); 1036 1037 SBHostOS::ThreadCreated ("<lldb.driver.main-thread>"); 1038 1039 signal (SIGPIPE, SIG_IGN); 1040 signal (SIGWINCH, sigwinch_handler); 1041 signal (SIGINT, sigint_handler); 1042 signal (SIGTSTP, sigtstp_handler); 1043 signal (SIGCONT, sigcont_handler); 1044 1045 // Create a scope for driver so that the driver object will destroy itself 1046 // before SBDebugger::Terminate() is called. 1047 { 1048 Driver driver; 1049 1050 bool exiting = false; 1051 SBError error (driver.ParseArgs (argc, argv, stdout, exiting)); 1052 if (error.Fail()) 1053 { 1054 const char *error_cstr = error.GetCString (); 1055 if (error_cstr) 1056 ::fprintf (stderr, "error: %s\n", error_cstr); 1057 } 1058 else if (!exiting) 1059 { 1060 driver.MainLoop (); 1061 } 1062 } 1063 1064 SBDebugger::Terminate(); 1065 return 0; 1066} 1067