Driver.cpp revision 263363
1251881Speter//===-- Driver.cpp ----------------------------------------------*- C++ -*-===// 2251881Speter// 3251881Speter// The LLVM Compiler Infrastructure 4251881Speter// 5251881Speter// This file is distributed under the University of Illinois Open Source 6251881Speter// License. See LICENSE.TXT for details. 7251881Speter// 8251881Speter//===----------------------------------------------------------------------===// 9251881Speter 10251881Speter#include "Driver.h" 11251881Speter 12251881Speter#include <stdio.h> 13251881Speter#include <string.h> 14251881Speter#include <stdlib.h> 15251881Speter#include <limits.h> 16251881Speter#include <fcntl.h> 17251881Speter 18251881Speter#include <string> 19251881Speter 20251881Speter#include <thread> 21251881Speter#include "IOChannel.h" 22251881Speter#include "lldb/API/SBBreakpoint.h" 23251881Speter#include "lldb/API/SBCommandInterpreter.h" 24251881Speter#include "lldb/API/SBCommandReturnObject.h" 25299742Sdim#include "lldb/API/SBCommunication.h" 26299742Sdim#include "lldb/API/SBDebugger.h" 27251881Speter#include "lldb/API/SBEvent.h" 28251881Speter#include "lldb/API/SBHostOS.h" 29251881Speter#include "lldb/API/SBListener.h" 30251881Speter#include "lldb/API/SBStream.h" 31251881Speter#include "lldb/API/SBTarget.h" 32251881Speter#include "lldb/API/SBThread.h" 33251881Speter#include "lldb/API/SBProcess.h" 34251881Speter 35251881Speterusing namespace lldb; 36251881Speter 37251881Speterstatic void reset_stdin_termios (); 38251881Speterstatic bool g_old_stdin_termios_is_valid = false; 39251881Speterstatic struct termios g_old_stdin_termios; 40251881Speter 41251881Speterstatic char *g_debugger_name = (char *) ""; 42251881Speterstatic Driver *g_driver = NULL; 43251881Speter 44251881Speter// In the Driver::MainLoop, we change the terminal settings. This function is 45251881Speter// added as an atexit handler to make sure we clean them up. 46251881Speterstatic void 47251881Speterreset_stdin_termios () 48299742Sdim{ 49299742Sdim if (g_old_stdin_termios_is_valid) 50251881Speter { 51251881Speter g_old_stdin_termios_is_valid = false; 52251881Speter ::tcsetattr (STDIN_FILENO, TCSANOW, &g_old_stdin_termios); 53299742Sdim } 54299742Sdim} 55251881Speter 56251881Spetertypedef struct 57251881Speter{ 58251881Speter uint32_t usage_mask; // Used to mark options that can be used together. If (1 << n & usage_mask) != 0 59251881Speter // then this option belongs to option set n. 60251881Speter bool required; // This option is required (in the current usage level) 61251881Speter const char * long_option; // Full name for this option. 62251881Speter int short_option; // Single character for this option. 63251881Speter int option_has_arg; // no_argument, required_argument or optional_argument 64251881Speter uint32_t completion_type; // Cookie the option class can use to do define the argument completion. 65251881Speter lldb::CommandArgumentType argument_type; // Type of argument this option takes 66251881Speter const char * usage_text; // Full text explaining what this options does and what (if any) argument to 67251881Speter // pass it. 68251881Speter} OptionDefinition; 69251881Speter 70251881Speter#define LLDB_3_TO_5 LLDB_OPT_SET_3|LLDB_OPT_SET_4|LLDB_OPT_SET_5 71251881Speter#define LLDB_4_TO_5 LLDB_OPT_SET_4|LLDB_OPT_SET_5 72251881Speter 73251881Speterstatic OptionDefinition g_options[] = 74251881Speter{ 75251881Speter { LLDB_OPT_SET_1, true , "help" , 'h', no_argument , 0, eArgTypeNone, 76251881Speter "Prints out the usage information for the LLDB debugger." }, 77251881Speter { LLDB_OPT_SET_2, true , "version" , 'v', no_argument , 0, eArgTypeNone, 78251881Speter "Prints out the current version number of the LLDB debugger." }, 79251881Speter { LLDB_OPT_SET_3, true , "arch" , 'a', required_argument, 0, eArgTypeArchitecture, 80251881Speter "Tells the debugger to use the specified architecture when starting and running the program. <architecture> must " 81251881Speter "be one of the architectures for which the program was compiled." }, 82251881Speter { LLDB_OPT_SET_3, true , "file" , 'f', required_argument, 0, eArgTypeFilename, 83251881Speter "Tells the debugger to use the file <filename> as the program to be debugged." }, 84251881Speter { LLDB_OPT_SET_3, false, "core" , 'c', required_argument, 0, eArgTypeFilename, 85251881Speter "Tells the debugger to use the fullpath to <path> as the core file." }, 86251881Speter { LLDB_OPT_SET_4, true , "attach-name" , 'n', required_argument, 0, eArgTypeProcessName, 87251881Speter "Tells the debugger to attach to a process with the given name." }, 88251881Speter { LLDB_OPT_SET_4, true , "wait-for" , 'w', no_argument , 0, eArgTypeNone, 89251881Speter "Tells the debugger to wait for a process with the given pid or name to launch before attaching." }, 90251881Speter { LLDB_OPT_SET_5, true , "attach-pid" , 'p', required_argument, 0, eArgTypePid, 91251881Speter "Tells the debugger to attach to a process with the given pid." }, 92251881Speter { LLDB_3_TO_5, false, "script-language", 'l', required_argument, 0, eArgTypeScriptLang, 93251881Speter "Tells the debugger to use the specified scripting language for user-defined scripts, rather than the default. " 94251881Speter "Valid scripting languages that can be specified include Python, Perl, Ruby and Tcl. Currently only the Python " 95251881Speter "extensions have been implemented." }, 96251881Speter { LLDB_3_TO_5, false, "debug" , 'd', no_argument , 0, eArgTypeNone, 97251881Speter "Tells the debugger to print out extra information for debugging itself." }, 98251881Speter { LLDB_3_TO_5, false, "source-quietly" , 'b', no_argument , 0, eArgTypeNone, 99251881Speter "Tells the debugger to print out extra information for debugging itself." }, 100251881Speter { LLDB_3_TO_5, false, "source" , 's', required_argument, 0, eArgTypeFilename, 101251881Speter "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." }, 102251881Speter { LLDB_3_TO_5, false, "one-line" , 'o', required_argument, 0, eArgTypeNone, 103251881Speter "Tells the debugger to execute this one-line lldb command after any file provided on the command line has been loaded." }, 104251881Speter { LLDB_3_TO_5, false, "source-before-file" , 'S', required_argument, 0, eArgTypeFilename, 105251881Speter "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." }, 106251881Speter { LLDB_3_TO_5, false, "one-line-before-file" , 'O', required_argument, 0, eArgTypeNone, 107251881Speter "Tells the debugger to execute this one-line lldb command before any file provided on the command line has been loaded." }, 108251881Speter { LLDB_3_TO_5, false, "editor" , 'e', no_argument , 0, eArgTypeNone, 109251881Speter "Tells the debugger to open source files using the host's \"external editor\" mechanism." }, 110251881Speter { LLDB_3_TO_5, false, "no-lldbinit" , 'x', no_argument , 0, eArgTypeNone, 111251881Speter "Do not automatically parse any '.lldbinit' files." }, 112251881Speter { LLDB_3_TO_5, false, "no-use-colors" , 'X', no_argument , 0, eArgTypeNone, 113251881Speter "Do not use colors." }, 114251881Speter { LLDB_OPT_SET_6, true , "python-path" , 'P', no_argument , 0, eArgTypeNone, 115251881Speter "Prints out the path to the lldb.py file for this version of lldb." }, 116251881Speter { 0, false, NULL , 0 , 0 , 0, eArgTypeNone, NULL } 117251881Speter}; 118251881Speter 119251881Speterstatic const uint32_t last_option_set_with_args = 2; 120251881Speter 121251881SpeterDriver::Driver () : 122251881Speter SBBroadcaster ("Driver"), 123251881Speter m_debugger (SBDebugger::Create(false)), 124251881Speter m_editline_pty (), 125251881Speter m_editline_slave_fh (NULL), 126251881Speter m_editline_reader (), 127251881Speter m_io_channel_ap (), 128251881Speter m_option_data (), 129251881Speter m_executing_user_command (false), 130251881Speter m_waiting_for_command (false), 131251881Speter m_done(false) 132251881Speter{ 133251881Speter // We want to be able to handle CTRL+D in the terminal to have it terminate 134251881Speter // certain input 135251881Speter m_debugger.SetCloseInputOnEOF (false); 136251881Speter g_debugger_name = (char *) m_debugger.GetInstanceName(); 137251881Speter if (g_debugger_name == NULL) 138251881Speter g_debugger_name = (char *) ""; 139251881Speter g_driver = this; 140251881Speter} 141251881Speter 142251881SpeterDriver::~Driver () 143251881Speter{ 144251881Speter g_driver = NULL; 145251881Speter g_debugger_name = NULL; 146251881Speter} 147251881Speter 148251881Spetervoid 149251881SpeterDriver::CloseIOChannelFile () 150299742Sdim{ 151299742Sdim // Write an End of File sequence to the file descriptor to ensure any 152251881Speter // read functions can exit. 153251881Speter char eof_str[] = "\x04"; 154251881Speter int mfd = m_editline_pty.GetMasterFileDescriptor(); 155251881Speter if (mfd != -1) 156251881Speter ::write (m_editline_pty.GetMasterFileDescriptor(), eof_str, strlen(eof_str)); 157251881Speter 158251881Speter m_editline_pty.CloseMasterFileDescriptor(); 159251881Speter 160251881Speter if (m_editline_slave_fh) 161251881Speter { 162251881Speter ::fclose (m_editline_slave_fh); 163251881Speter m_editline_slave_fh = NULL; 164251881Speter } 165251881Speter} 166251881Speter 167251881Speter// This function takes INDENT, which tells how many spaces to output at the front 168251881Speter// of each line; TEXT, which is the text that is to be output. It outputs the 169251881Speter// text, on multiple lines if necessary, to RESULT, with INDENT spaces at the 170251881Speter// front of each line. It breaks lines on spaces, tabs or newlines, shortening 171251881Speter// the line if necessary to not break in the middle of a word. It assumes that 172251881Speter// each output line should contain a maximum of OUTPUT_MAX_COLUMNS characters. 173251881Speter 174251881Spetervoid 175251881SpeterOutputFormattedUsageText (FILE *out, int indent, const char *text, int output_max_columns) 176251881Speter{ 177251881Speter int len = strlen (text); 178251881Speter std::string text_string (text); 179251881Speter 180251881Speter // Force indentation to be reasonable. 181251881Speter if (indent >= output_max_columns) 182251881Speter indent = 0; 183251881Speter 184251881Speter // Will it all fit on one line? 185251881Speter 186251881Speter if (len + indent < output_max_columns) 187251881Speter // Output as a single line 188251881Speter fprintf (out, "%*s%s\n", indent, "", text); 189251881Speter else 190251881Speter { 191251881Speter // We need to break it up into multiple lines. 192251881Speter int text_width = output_max_columns - indent - 1; 193251881Speter int start = 0; 194251881Speter int end = start; 195251881Speter int final_end = len; 196251881Speter int sub_len; 197251881Speter 198251881Speter while (end < final_end) 199251881Speter { 200251881Speter // Dont start the 'text' on a space, since we're already outputting the indentation. 201251881Speter while ((start < final_end) && (text[start] == ' ')) 202251881Speter start++; 203251881Speter 204251881Speter end = start + text_width; 205251881Speter if (end > final_end) 206251881Speter end = final_end; 207251881Speter else 208251881Speter { 209251881Speter // If we're not at the end of the text, make sure we break the line on white space. 210251881Speter while (end > start 211251881Speter && text[end] != ' ' && text[end] != '\t' && text[end] != '\n') 212251881Speter end--; 213299742Sdim } 214251881Speter sub_len = end - start; 215299742Sdim std::string substring = text_string.substr (start, sub_len); 216299742Sdim fprintf (out, "%*s%s\n", indent, "", substring.c_str()); 217299742Sdim start = end + 1; 218251881Speter } 219251881Speter } 220299742Sdim} 221251881Speter 222251881Spetervoid 223251881SpeterShowUsage (FILE *out, OptionDefinition *option_table, Driver::OptionData data) 224251881Speter{ 225251881Speter uint32_t screen_width = 80; 226251881Speter uint32_t indent_level = 0; 227251881Speter const char *name = "lldb"; 228251881Speter 229251881Speter fprintf (out, "\nUsage:\n\n"); 230251881Speter 231251881Speter indent_level += 2; 232251881Speter 233251881Speter 234251881Speter // First, show each usage level set of options, e.g. <cmd> [options-for-level-0] 235251881Speter // <cmd> [options-for-level-1] 236251881Speter // etc. 237251881Speter 238251881Speter uint32_t num_options; 239251881Speter uint32_t num_option_sets = 0; 240251881Speter 241251881Speter for (num_options = 0; option_table[num_options].long_option != NULL; ++num_options) 242251881Speter { 243251881Speter uint32_t this_usage_mask = option_table[num_options].usage_mask; 244251881Speter if (this_usage_mask == LLDB_OPT_SET_ALL) 245251881Speter { 246251881Speter if (num_option_sets == 0) 247251881Speter num_option_sets = 1; 248251881Speter } 249251881Speter else 250251881Speter { 251251881Speter for (uint32_t j = 0; j < LLDB_MAX_NUM_OPTION_SETS; j++) 252251881Speter { 253251881Speter if (this_usage_mask & 1 << j) 254251881Speter { 255251881Speter if (num_option_sets <= j) 256251881Speter num_option_sets = j + 1; 257251881Speter } 258251881Speter } 259251881Speter } 260251881Speter } 261251881Speter 262251881Speter for (uint32_t opt_set = 0; opt_set < num_option_sets; opt_set++) 263251881Speter { 264251881Speter uint32_t opt_set_mask; 265251881Speter 266251881Speter opt_set_mask = 1 << opt_set; 267251881Speter 268251881Speter if (opt_set > 0) 269251881Speter fprintf (out, "\n"); 270251881Speter fprintf (out, "%*s%s", indent_level, "", name); 271251881Speter bool is_help_line = false; 272251881Speter 273251881Speter for (uint32_t i = 0; i < num_options; ++i) 274251881Speter { 275251881Speter if (option_table[i].usage_mask & opt_set_mask) 276251881Speter { 277251881Speter CommandArgumentType arg_type = option_table[i].argument_type; 278251881Speter const char *arg_name = SBCommandInterpreter::GetArgumentTypeAsCString (arg_type); 279251881Speter // This is a bit of a hack, but there's no way to say certain options don't have arguments yet... 280251881Speter // so we do it by hand here. 281251881Speter if (option_table[i].short_option == 'h') 282251881Speter is_help_line = true; 283251881Speter 284251881Speter if (option_table[i].required) 285251881Speter { 286251881Speter if (option_table[i].option_has_arg == required_argument) 287251881Speter fprintf (out, " -%c <%s>", option_table[i].short_option, arg_name); 288251881Speter else if (option_table[i].option_has_arg == optional_argument) 289251881Speter fprintf (out, " -%c [<%s>]", option_table[i].short_option, arg_name); 290251881Speter else 291251881Speter fprintf (out, " -%c", option_table[i].short_option); 292251881Speter } 293251881Speter else 294251881Speter { 295251881Speter if (option_table[i].option_has_arg == required_argument) 296251881Speter fprintf (out, " [-%c <%s>]", option_table[i].short_option, arg_name); 297251881Speter else if (option_table[i].option_has_arg == optional_argument) 298251881Speter fprintf (out, " [-%c [<%s>]]", option_table[i].short_option, arg_name); 299251881Speter else 300251881Speter fprintf (out, " [-%c]", option_table[i].short_option); 301251881Speter } 302251881Speter } 303251881Speter } 304299742Sdim if (!is_help_line && (opt_set <= last_option_set_with_args)) 305299742Sdim fprintf (out, " [[--] <PROGRAM-ARG-1> [<PROGRAM_ARG-2> ...]]"); 306299742Sdim } 307299742Sdim 308299742Sdim fprintf (out, "\n\n"); 309299742Sdim 310251881Speter // Now print out all the detailed information about the various options: long form, short form and help text: 311251881Speter // -- long_name <argument> 312251881Speter // - short <argument> 313251881Speter // help text 314251881Speter 315251881Speter // This variable is used to keep track of which options' info we've printed out, because some options can be in 316251881Speter // more than one usage level, but we only want to print the long form of its information once. 317251881Speter 318251881Speter Driver::OptionData::OptionSet options_seen; 319251881Speter Driver::OptionData::OptionSet::iterator pos; 320251881Speter 321251881Speter indent_level += 5; 322251881Speter 323251881Speter for (uint32_t i = 0; i < num_options; ++i) 324251881Speter { 325251881Speter // Only print this option if we haven't already seen it. 326251881Speter pos = options_seen.find (option_table[i].short_option); 327251881Speter if (pos == options_seen.end()) 328251881Speter { 329251881Speter CommandArgumentType arg_type = option_table[i].argument_type; 330251881Speter const char *arg_name = SBCommandInterpreter::GetArgumentTypeAsCString (arg_type); 331251881Speter 332251881Speter options_seen.insert (option_table[i].short_option); 333251881Speter fprintf (out, "%*s-%c ", indent_level, "", option_table[i].short_option); 334251881Speter if (arg_type != eArgTypeNone) 335251881Speter fprintf (out, "<%s>", arg_name); 336251881Speter fprintf (out, "\n"); 337251881Speter fprintf (out, "%*s--%s ", indent_level, "", option_table[i].long_option); 338251881Speter if (arg_type != eArgTypeNone) 339251881Speter fprintf (out, "<%s>", arg_name); 340251881Speter fprintf (out, "\n"); 341251881Speter indent_level += 5; 342251881Speter OutputFormattedUsageText (out, indent_level, option_table[i].usage_text, screen_width); 343251881Speter indent_level -= 5; 344251881Speter fprintf (out, "\n"); 345251881Speter } 346251881Speter } 347251881Speter 348251881Speter indent_level -= 5; 349251881Speter 350251881Speter fprintf (out, "\n%*sMultiple \"-s\" and \"-o\" options can be provided. They will be processed from left to right in order, " 351251881Speter "\n%*swith the source files and commands interleaved. The same is true of the \"-S\" and \"-O\" options." 352251881Speter "\n%*sThe before file and after file sets can intermixed freely, the command parser will sort them out." 353251881Speter "\n%*sThe order of the file specifiers (\"-c\", \"-f\", etc.) is not significant in this regard.\n\n", 354251881Speter indent_level, "", 355251881Speter indent_level, "", 356251881Speter indent_level, "", 357251881Speter indent_level, ""); 358251881Speter 359251881Speter fprintf (out, "\n%*s(If you don't provide -f then the first argument will be the file to be debugged" 360251881Speter "\n%*s so '%s -- <filename> [<ARG1> [<ARG2>]]' also works." 361251881Speter "\n%*s Remember to end the options with \"--\" if any of your arguments have a \"-\" in them.)\n\n", 362251881Speter indent_level, "", 363251881Speter indent_level, "", 364251881Speter name, 365251881Speter indent_level, ""); 366251881Speter} 367251881Speter 368251881Spetervoid 369251881SpeterBuildGetOptTable (OptionDefinition *expanded_option_table, std::vector<struct option> &getopt_table, 370251881Speter uint32_t num_options) 371251881Speter{ 372251881Speter if (num_options == 0) 373251881Speter return; 374251881Speter 375251881Speter uint32_t i; 376251881Speter uint32_t j; 377251881Speter std::bitset<256> option_seen; 378251881Speter 379251881Speter getopt_table.resize (num_options + 1); 380251881Speter 381251881Speter for (i = 0, j = 0; i < num_options; ++i) 382251881Speter { 383251881Speter char short_opt = expanded_option_table[i].short_option; 384251881Speter 385251881Speter if (option_seen.test(short_opt) == false) 386251881Speter { 387251881Speter getopt_table[j].name = expanded_option_table[i].long_option; 388251881Speter getopt_table[j].has_arg = expanded_option_table[i].option_has_arg; 389251881Speter getopt_table[j].flag = NULL; 390251881Speter getopt_table[j].val = expanded_option_table[i].short_option; 391251881Speter option_seen.set(short_opt); 392251881Speter ++j; 393251881Speter } 394251881Speter } 395251881Speter 396251881Speter getopt_table[j].name = NULL; 397251881Speter getopt_table[j].has_arg = 0; 398251881Speter getopt_table[j].flag = NULL; 399251881Speter getopt_table[j].val = 0; 400251881Speter 401251881Speter} 402251881Speter 403251881SpeterDriver::OptionData::OptionData () : 404251881Speter m_args(), 405251881Speter m_script_lang (lldb::eScriptLanguageDefault), 406251881Speter m_core_file (), 407251881Speter m_crash_log (), 408251881Speter m_initial_commands (), 409251881Speter m_after_file_commands (), 410299742Sdim m_debug_mode (false), 411251881Speter m_source_quietly(false), 412251881Speter m_print_version (false), 413251881Speter m_print_python_path (false), 414251881Speter m_print_help (false), 415299742Sdim m_wait_for(false), 416299742Sdim m_process_name(), 417251881Speter m_process_pid(LLDB_INVALID_PROCESS_ID), 418251881Speter m_use_external_editor(false), 419251881Speter m_seen_options() 420251881Speter{ 421251881Speter} 422251881Speter 423251881SpeterDriver::OptionData::~OptionData () 424251881Speter{ 425251881Speter} 426299742Sdim 427251881Spetervoid 428251881SpeterDriver::OptionData::Clear () 429251881Speter{ 430251881Speter m_args.clear (); 431251881Speter m_script_lang = lldb::eScriptLanguageDefault; 432251881Speter m_initial_commands.clear (); 433251881Speter m_after_file_commands.clear (); 434251881Speter m_debug_mode = false; 435251881Speter m_source_quietly = false; 436251881Speter m_print_help = false; 437251881Speter m_print_version = false; 438251881Speter m_print_python_path = false; 439251881Speter m_use_external_editor = false; 440251881Speter m_wait_for = false; 441251881Speter m_process_name.erase(); 442251881Speter m_process_pid = LLDB_INVALID_PROCESS_ID; 443251881Speter} 444251881Speter 445251881Spetervoid 446299742SdimDriver::OptionData::AddInitialCommand (const char *command, bool before_file, bool is_file, SBError &error) 447299742Sdim{ 448299742Sdim std::vector<std::pair<bool, std::string> > *command_set; 449251881Speter if (before_file) 450251881Speter command_set = &(m_initial_commands); 451251881Speter else 452251881Speter command_set = &(m_after_file_commands); 453299742Sdim 454299742Sdim if (is_file) 455251881Speter { 456251881Speter SBFileSpec file(command); 457251881Speter if (file.Exists()) 458251881Speter command_set->push_back (std::pair<bool, std::string> (true, optarg)); 459299742Sdim else if (file.ResolveExecutableLocation()) 460299742Sdim { 461299742Sdim char final_path[PATH_MAX]; 462251881Speter file.GetPath (final_path, sizeof(final_path)); 463251881Speter std::string path_str (final_path); 464251881Speter command_set->push_back (std::pair<bool, std::string> (true, path_str)); 465251881Speter } 466251881Speter else 467251881Speter error.SetErrorStringWithFormat("file specified in --source (-s) option doesn't exist: '%s'", optarg); 468251881Speter } 469251881Speter else 470251881Speter command_set->push_back (std::pair<bool, std::string> (false, optarg)); 471251881Speter} 472251881Speter 473251881Spetervoid 474251881SpeterDriver::ResetOptionValues () 475251881Speter{ 476299742Sdim m_option_data.Clear (); 477299742Sdim} 478251881Speter 479251881Speterconst char * 480251881SpeterDriver::GetFilename() const 481251881Speter{ 482299742Sdim if (m_option_data.m_args.empty()) 483299742Sdim return NULL; 484251881Speter return m_option_data.m_args.front().c_str(); 485251881Speter} 486251881Speter 487251881Speterconst char * 488251881SpeterDriver::GetCrashLogFilename() const 489251881Speter{ 490251881Speter if (m_option_data.m_crash_log.empty()) 491251881Speter return NULL; 492251881Speter return m_option_data.m_crash_log.c_str(); 493251881Speter} 494251881Speter 495251881Speterlldb::ScriptLanguage 496251881SpeterDriver::GetScriptLanguage() const 497251881Speter{ 498299742Sdim return m_option_data.m_script_lang; 499299742Sdim} 500251881Speter 501251881Spetervoid 502251881SpeterDriver::ExecuteInitialCommands (bool before_file) 503251881Speter{ 504251881Speter size_t num_commands; 505251881Speter std::vector<std::pair<bool, std::string> > *command_set; 506251881Speter if (before_file) 507251881Speter command_set = &(m_option_data.m_initial_commands); 508251881Speter else 509251881Speter command_set = &(m_option_data.m_after_file_commands); 510251881Speter 511251881Speter num_commands = command_set->size(); 512251881Speter SBCommandReturnObject result; 513251881Speter bool old_async = GetDebugger().GetAsync(); 514251881Speter GetDebugger().SetAsync(false); 515251881Speter for (size_t idx = 0; idx < num_commands; idx++) 516251881Speter { 517251881Speter bool is_file = (*command_set)[idx].first; 518251881Speter const char *command = (*command_set)[idx].second.c_str(); 519251881Speter char command_string[PATH_MAX * 2]; 520251881Speter const bool dump_stream_only_if_no_immediate = true; 521251881Speter const char *executed_command = command; 522251881Speter if (is_file) 523251881Speter { 524251881Speter ::snprintf (command_string, sizeof(command_string), "command source '%s'", command); 525251881Speter executed_command = command_string; 526251881Speter } 527251881Speter 528251881Speter m_debugger.GetCommandInterpreter().HandleCommand (executed_command, result, false); 529251881Speter if (!m_option_data.m_source_quietly || result.Succeeded() == false) 530251881Speter { 531251881Speter const size_t output_size = result.GetOutputSize(); 532251881Speter if (output_size > 0) 533251881Speter m_io_channel_ap->OutWrite (result.GetOutput(dump_stream_only_if_no_immediate), output_size, NO_ASYNC); 534251881Speter const size_t error_size = result.GetErrorSize(); 535251881Speter if (error_size > 0) 536251881Speter m_io_channel_ap->OutWrite (result.GetError(dump_stream_only_if_no_immediate), error_size, NO_ASYNC); 537251881Speter } 538251881Speter 539251881Speter if (result.Succeeded() == false) 540251881Speter { 541251881Speter char error_buffer[1024]; 542251881Speter size_t error_size; 543251881Speter const char *type = before_file ? "before file" : "after_file"; 544251881Speter if (is_file) 545251881Speter error_size = ::snprintf(error_buffer, sizeof(error_buffer), "Aborting %s command execution, command file: '%s' failed.\n", type, command); 546251881Speter else 547251881Speter error_size = ::snprintf(error_buffer, sizeof(error_buffer), "Aborting %s command execution, command: '%s' failed.\n", type, command); 548251881Speter 549251881Speter m_io_channel_ap->OutWrite(error_buffer, error_size, NO_ASYNC); 550251881Speter break; 551251881Speter } 552251881Speter result.Clear(); 553251881Speter } 554251881Speter GetDebugger().SetAsync(old_async); 555251881Speter} 556251881Speter 557251881Speterbool 558251881SpeterDriver::GetDebugMode() const 559251881Speter{ 560251881Speter return m_option_data.m_debug_mode; 561251881Speter} 562251881Speter 563251881Speter 564251881Speter// Check the arguments that were passed to this program to make sure they are valid and to get their 565251881Speter// argument values (if any). Return a boolean value indicating whether or not to start up the full 566251881Speter// debugger (i.e. the Command Interpreter) or not. Return FALSE if the arguments were invalid OR 567251881Speter// if the user only wanted help or version information. 568251881Speter 569251881SpeterSBError 570251881SpeterDriver::ParseArgs (int argc, const char *argv[], FILE *out_fh, bool &exiting) 571251881Speter{ 572251881Speter ResetOptionValues (); 573251881Speter 574251881Speter SBCommandReturnObject result; 575251881Speter 576251881Speter SBError error; 577251881Speter std::string option_string; 578251881Speter struct option *long_options = NULL; 579251881Speter std::vector<struct option> long_options_vector; 580269847Speter uint32_t num_options; 581251881Speter 582251881Speter for (num_options = 0; g_options[num_options].long_option != NULL; ++num_options) 583299742Sdim /* Do Nothing. */; 584251881Speter 585251881Speter if (num_options == 0) 586251881Speter { 587251881Speter if (argc > 1) 588251881Speter error.SetErrorStringWithFormat ("invalid number of options"); 589251881Speter return error; 590251881Speter } 591299742Sdim 592251881Speter BuildGetOptTable (g_options, long_options_vector, num_options); 593251881Speter 594251881Speter if (long_options_vector.empty()) 595251881Speter long_options = NULL; 596251881Speter else 597251881Speter long_options = &long_options_vector.front(); 598251881Speter 599299742Sdim if (long_options == NULL) 600251881Speter { 601299742Sdim error.SetErrorStringWithFormat ("invalid long options"); 602253734Speter return error; 603251881Speter } 604299742Sdim 605251881Speter // Build the option_string argument for call to getopt_long_only. 606 607 for (int i = 0; long_options[i].name != NULL; ++i) 608 { 609 if (long_options[i].flag == NULL) 610 { 611 option_string.push_back ((char) long_options[i].val); 612 switch (long_options[i].has_arg) 613 { 614 default: 615 case no_argument: 616 break; 617 case required_argument: 618 option_string.push_back (':'); 619 break; 620 case optional_argument: 621 option_string.append ("::"); 622 break; 623 } 624 } 625 } 626 627 // This is kind of a pain, but since we make the debugger in the Driver's constructor, we can't 628 // know at that point whether we should read in init files yet. So we don't read them in in the 629 // Driver constructor, then set the flags back to "read them in" here, and then if we see the 630 // "-n" flag, we'll turn it off again. Finally we have to read them in by hand later in the 631 // main loop. 632 633 m_debugger.SkipLLDBInitFiles (false); 634 m_debugger.SkipAppInitFiles (false); 635 636 // Prepare for & make calls to getopt_long_only. 637#if __GLIBC__ 638 optind = 0; 639#else 640 optreset = 1; 641 optind = 1; 642#endif 643 int val; 644 while (1) 645 { 646 int long_options_index = -1; 647 val = ::getopt_long_only (argc, const_cast<char **>(argv), option_string.c_str(), long_options, &long_options_index); 648 649 if (val == -1) 650 break; 651 else if (val == '?') 652 { 653 m_option_data.m_print_help = true; 654 error.SetErrorStringWithFormat ("unknown or ambiguous option"); 655 break; 656 } 657 else if (val == 0) 658 continue; 659 else 660 { 661 m_option_data.m_seen_options.insert ((char) val); 662 if (long_options_index == -1) 663 { 664 for (int i = 0; 665 long_options[i].name || long_options[i].has_arg || long_options[i].flag || long_options[i].val; 666 ++i) 667 { 668 if (long_options[i].val == val) 669 { 670 long_options_index = i; 671 break; 672 } 673 } 674 } 675 676 if (long_options_index >= 0) 677 { 678 const int short_option = g_options[long_options_index].short_option; 679 680 switch (short_option) 681 { 682 case 'h': 683 m_option_data.m_print_help = true; 684 break; 685 686 case 'v': 687 m_option_data.m_print_version = true; 688 break; 689 690 case 'P': 691 m_option_data.m_print_python_path = true; 692 break; 693 694 case 'c': 695 { 696 SBFileSpec file(optarg); 697 if (file.Exists()) 698 { 699 m_option_data.m_core_file = optarg; 700 } 701 else 702 error.SetErrorStringWithFormat("file specified in --core (-c) option doesn't exist: '%s'", optarg); 703 } 704 break; 705 706 case 'e': 707 m_option_data.m_use_external_editor = true; 708 break; 709 710 case 'x': 711 m_debugger.SkipLLDBInitFiles (true); 712 m_debugger.SkipAppInitFiles (true); 713 break; 714 715 case 'X': 716 m_debugger.SetUseColor (false); 717 break; 718 719 case 'f': 720 { 721 SBFileSpec file(optarg); 722 if (file.Exists()) 723 { 724 m_option_data.m_args.push_back (optarg); 725 } 726 else if (file.ResolveExecutableLocation()) 727 { 728 char path[PATH_MAX]; 729 file.GetPath (path, sizeof(path)); 730 m_option_data.m_args.push_back (path); 731 } 732 else 733 error.SetErrorStringWithFormat("file specified in --file (-f) option doesn't exist: '%s'", optarg); 734 } 735 break; 736 737 case 'a': 738 if (!m_debugger.SetDefaultArchitecture (optarg)) 739 error.SetErrorStringWithFormat("invalid architecture in the -a or --arch option: '%s'", optarg); 740 break; 741 742 case 'l': 743 m_option_data.m_script_lang = m_debugger.GetScriptingLanguage (optarg); 744 break; 745 746 case 'd': 747 m_option_data.m_debug_mode = true; 748 break; 749 750 case 'q': 751 m_option_data.m_source_quietly = true; 752 break; 753 754 case 'n': 755 m_option_data.m_process_name = optarg; 756 break; 757 758 case 'w': 759 m_option_data.m_wait_for = true; 760 break; 761 762 case 'p': 763 { 764 char *remainder; 765 m_option_data.m_process_pid = strtol (optarg, &remainder, 0); 766 if (remainder == optarg || *remainder != '\0') 767 error.SetErrorStringWithFormat ("Could not convert process PID: \"%s\" into a pid.", 768 optarg); 769 } 770 break; 771 case 's': 772 m_option_data.AddInitialCommand(optarg, false, true, error); 773 break; 774 case 'o': 775 m_option_data.AddInitialCommand(optarg, false, false, error); 776 break; 777 case 'S': 778 m_option_data.AddInitialCommand(optarg, true, true, error); 779 break; 780 case 'O': 781 m_option_data.AddInitialCommand(optarg, true, false, error); 782 break; 783 default: 784 m_option_data.m_print_help = true; 785 error.SetErrorStringWithFormat ("unrecognized option %c", short_option); 786 break; 787 } 788 } 789 else 790 { 791 error.SetErrorStringWithFormat ("invalid option with value %i", val); 792 } 793 if (error.Fail()) 794 { 795 return error; 796 } 797 } 798 } 799 800 if (error.Fail() || m_option_data.m_print_help) 801 { 802 ShowUsage (out_fh, g_options, m_option_data); 803 exiting = true; 804 } 805 else if (m_option_data.m_print_version) 806 { 807 ::fprintf (out_fh, "%s\n", m_debugger.GetVersionString()); 808 exiting = true; 809 } 810 else if (m_option_data.m_print_python_path) 811 { 812 SBFileSpec python_file_spec = SBHostOS::GetLLDBPythonPath(); 813 if (python_file_spec.IsValid()) 814 { 815 char python_path[PATH_MAX]; 816 size_t num_chars = python_file_spec.GetPath(python_path, PATH_MAX); 817 if (num_chars < PATH_MAX) 818 { 819 ::fprintf (out_fh, "%s\n", python_path); 820 } 821 else 822 ::fprintf (out_fh, "<PATH TOO LONG>\n"); 823 } 824 else 825 ::fprintf (out_fh, "<COULD NOT FIND PATH>\n"); 826 exiting = true; 827 } 828 else if (m_option_data.m_process_name.empty() && m_option_data.m_process_pid == LLDB_INVALID_PROCESS_ID) 829 { 830 // Any arguments that are left over after option parsing are for 831 // the program. If a file was specified with -f then the filename 832 // is already in the m_option_data.m_args array, and any remaining args 833 // are arguments for the inferior program. If no file was specified with 834 // -f, then what is left is the program name followed by any arguments. 835 836 // Skip any options we consumed with getopt_long_only 837 argc -= optind; 838 argv += optind; 839 840 if (argc > 0) 841 { 842 for (int arg_idx=0; arg_idx<argc; ++arg_idx) 843 { 844 const char *arg = argv[arg_idx]; 845 if (arg) 846 m_option_data.m_args.push_back (arg); 847 } 848 } 849 850 } 851 else 852 { 853 // Skip any options we consumed with getopt_long_only 854 argc -= optind; 855 //argv += optind; // Commented out to keep static analyzer happy 856 857 if (argc > 0) 858 ::fprintf (out_fh, "Warning: program arguments are ignored when attaching.\n"); 859 } 860 861 return error; 862} 863 864size_t 865Driver::GetProcessSTDOUT () 866{ 867 // The process has stuff waiting for stdout; get it and write it out to the appropriate place. 868 char stdio_buffer[1024]; 869 size_t len; 870 size_t total_bytes = 0; 871 while ((len = m_debugger.GetSelectedTarget().GetProcess().GetSTDOUT (stdio_buffer, sizeof (stdio_buffer))) > 0) 872 { 873 m_io_channel_ap->OutWrite (stdio_buffer, len, NO_ASYNC); 874 total_bytes += len; 875 } 876 return total_bytes; 877} 878 879size_t 880Driver::GetProcessSTDERR () 881{ 882 // The process has stuff waiting for stderr; get it and write it out to the appropriate place. 883 char stdio_buffer[1024]; 884 size_t len; 885 size_t total_bytes = 0; 886 while ((len = m_debugger.GetSelectedTarget().GetProcess().GetSTDERR (stdio_buffer, sizeof (stdio_buffer))) > 0) 887 { 888 m_io_channel_ap->ErrWrite (stdio_buffer, len, NO_ASYNC); 889 total_bytes += len; 890 } 891 return total_bytes; 892} 893 894void 895Driver::UpdateSelectedThread () 896{ 897 using namespace lldb; 898 SBProcess process(m_debugger.GetSelectedTarget().GetProcess()); 899 if (process.IsValid()) 900 { 901 SBThread curr_thread (process.GetSelectedThread()); 902 SBThread thread; 903 StopReason curr_thread_stop_reason = eStopReasonInvalid; 904 curr_thread_stop_reason = curr_thread.GetStopReason(); 905 906 if (!curr_thread.IsValid() || 907 curr_thread_stop_reason == eStopReasonInvalid || 908 curr_thread_stop_reason == eStopReasonNone) 909 { 910 // Prefer a thread that has just completed its plan over another thread as current thread. 911 SBThread plan_thread; 912 SBThread other_thread; 913 const size_t num_threads = process.GetNumThreads(); 914 size_t i; 915 for (i = 0; i < num_threads; ++i) 916 { 917 thread = process.GetThreadAtIndex(i); 918 StopReason thread_stop_reason = thread.GetStopReason(); 919 switch (thread_stop_reason) 920 { 921 case eStopReasonInvalid: 922 case eStopReasonNone: 923 break; 924 925 case eStopReasonTrace: 926 case eStopReasonBreakpoint: 927 case eStopReasonWatchpoint: 928 case eStopReasonSignal: 929 case eStopReasonException: 930 case eStopReasonExec: 931 case eStopReasonThreadExiting: 932 if (!other_thread.IsValid()) 933 other_thread = thread; 934 break; 935 case eStopReasonPlanComplete: 936 if (!plan_thread.IsValid()) 937 plan_thread = thread; 938 break; 939 } 940 } 941 if (plan_thread.IsValid()) 942 process.SetSelectedThread (plan_thread); 943 else if (other_thread.IsValid()) 944 process.SetSelectedThread (other_thread); 945 else 946 { 947 if (curr_thread.IsValid()) 948 thread = curr_thread; 949 else 950 thread = process.GetThreadAtIndex(0); 951 952 if (thread.IsValid()) 953 process.SetSelectedThread (thread); 954 } 955 } 956 } 957} 958 959// This function handles events that were broadcast by the process. 960void 961Driver::HandleBreakpointEvent (const SBEvent &event) 962{ 963 using namespace lldb; 964 const uint32_t event_type = SBBreakpoint::GetBreakpointEventTypeFromEvent (event); 965 966 if (event_type & eBreakpointEventTypeAdded 967 || event_type & eBreakpointEventTypeRemoved 968 || event_type & eBreakpointEventTypeEnabled 969 || event_type & eBreakpointEventTypeDisabled 970 || event_type & eBreakpointEventTypeCommandChanged 971 || event_type & eBreakpointEventTypeConditionChanged 972 || event_type & eBreakpointEventTypeIgnoreChanged 973 || event_type & eBreakpointEventTypeLocationsResolved) 974 { 975 // Don't do anything about these events, since the breakpoint commands already echo these actions. 976 } 977 else if (event_type & eBreakpointEventTypeLocationsAdded) 978 { 979 char message[256]; 980 uint32_t num_new_locations = SBBreakpoint::GetNumBreakpointLocationsFromEvent(event); 981 if (num_new_locations > 0) 982 { 983 SBBreakpoint breakpoint = SBBreakpoint::GetBreakpointFromEvent(event); 984 int message_len = ::snprintf (message, sizeof(message), "%d location%s added to breakpoint %d\n", 985 num_new_locations, 986 num_new_locations == 1 ? "" : "s", 987 breakpoint.GetID()); 988 m_io_channel_ap->OutWrite(message, message_len, ASYNC); 989 } 990 } 991 else if (event_type & eBreakpointEventTypeLocationsRemoved) 992 { 993 // These locations just get disabled, not sure it is worth spamming folks about this on the command line. 994 } 995 else if (event_type & eBreakpointEventTypeLocationsResolved) 996 { 997 // This might be an interesting thing to note, but I'm going to leave it quiet for now, it just looked noisy. 998 } 999} 1000 1001// This function handles events that were broadcast by the process. 1002void 1003Driver::HandleProcessEvent (const SBEvent &event) 1004{ 1005 using namespace lldb; 1006 const uint32_t event_type = event.GetType(); 1007 1008 if (event_type & SBProcess::eBroadcastBitSTDOUT) 1009 { 1010 // The process has stdout available, get it and write it out to the 1011 // appropriate place. 1012 GetProcessSTDOUT (); 1013 } 1014 else if (event_type & SBProcess::eBroadcastBitSTDERR) 1015 { 1016 // The process has stderr available, get it and write it out to the 1017 // appropriate place. 1018 GetProcessSTDERR (); 1019 } 1020 else if (event_type & SBProcess::eBroadcastBitStateChanged) 1021 { 1022 // Drain all stout and stderr so we don't see any output come after 1023 // we print our prompts 1024 GetProcessSTDOUT (); 1025 GetProcessSTDERR (); 1026 // Something changed in the process; get the event and report the process's current status and location to 1027 // the user. 1028 StateType event_state = SBProcess::GetStateFromEvent (event); 1029 if (event_state == eStateInvalid) 1030 return; 1031 1032 SBProcess process (SBProcess::GetProcessFromEvent (event)); 1033 assert (process.IsValid()); 1034 1035 switch (event_state) 1036 { 1037 case eStateInvalid: 1038 case eStateUnloaded: 1039 case eStateConnected: 1040 case eStateAttaching: 1041 case eStateLaunching: 1042 case eStateStepping: 1043 case eStateDetached: 1044 { 1045 char message[1024]; 1046 int message_len = ::snprintf (message, sizeof(message), "Process %" PRIu64 " %s\n", process.GetProcessID(), 1047 m_debugger.StateAsCString (event_state)); 1048 m_io_channel_ap->OutWrite(message, message_len, ASYNC); 1049 } 1050 break; 1051 1052 case eStateRunning: 1053 // Don't be chatty when we run... 1054 break; 1055 1056 case eStateExited: 1057 { 1058 SBCommandReturnObject result; 1059 m_debugger.GetCommandInterpreter().HandleCommand("process status", result, false); 1060 m_io_channel_ap->ErrWrite (result.GetError(), result.GetErrorSize(), ASYNC); 1061 m_io_channel_ap->OutWrite (result.GetOutput(), result.GetOutputSize(), ASYNC); 1062 } 1063 break; 1064 1065 case eStateStopped: 1066 case eStateCrashed: 1067 case eStateSuspended: 1068 // Make sure the program hasn't been auto-restarted: 1069 if (SBProcess::GetRestartedFromEvent (event)) 1070 { 1071 size_t num_reasons = SBProcess::GetNumRestartedReasonsFromEvent(event); 1072 if (num_reasons > 0) 1073 { 1074 // FIXME: Do we want to report this, or would that just be annoyingly chatty? 1075 if (num_reasons == 1) 1076 { 1077 char message[1024]; 1078 const char *reason = SBProcess::GetRestartedReasonAtIndexFromEvent (event, 0); 1079 int message_len = ::snprintf (message, sizeof(message), "Process %" PRIu64 " stopped and restarted: %s\n", 1080 process.GetProcessID(), reason ? reason : "<UNKNOWN REASON>"); 1081 m_io_channel_ap->OutWrite(message, message_len, ASYNC); 1082 } 1083 else 1084 { 1085 char message[1024]; 1086 int message_len = ::snprintf (message, sizeof(message), "Process %" PRIu64 " stopped and restarted, reasons:\n", 1087 process.GetProcessID()); 1088 m_io_channel_ap->OutWrite(message, message_len, ASYNC); 1089 for (size_t i = 0; i < num_reasons; i++) 1090 { 1091 const char *reason = SBProcess::GetRestartedReasonAtIndexFromEvent (event, i); 1092 int message_len = ::snprintf(message, sizeof(message), "\t%s\n", reason ? reason : "<UNKNOWN REASON>"); 1093 m_io_channel_ap->OutWrite(message, message_len, ASYNC); 1094 } 1095 } 1096 } 1097 } 1098 else 1099 { 1100 if (GetDebugger().GetSelectedTarget() == process.GetTarget()) 1101 { 1102 SBCommandReturnObject result; 1103 UpdateSelectedThread (); 1104 m_debugger.GetCommandInterpreter().HandleCommand("process status", result, false); 1105 m_io_channel_ap->ErrWrite (result.GetError(), result.GetErrorSize(), ASYNC); 1106 m_io_channel_ap->OutWrite (result.GetOutput(), result.GetOutputSize(), ASYNC); 1107 } 1108 else 1109 { 1110 SBStream out_stream; 1111 uint32_t target_idx = GetDebugger().GetIndexOfTarget(process.GetTarget()); 1112 if (target_idx != UINT32_MAX) 1113 out_stream.Printf ("Target %d: (", target_idx); 1114 else 1115 out_stream.Printf ("Target <unknown index>: ("); 1116 process.GetTarget().GetDescription (out_stream, eDescriptionLevelBrief); 1117 out_stream.Printf (") stopped.\n"); 1118 m_io_channel_ap->OutWrite (out_stream.GetData(), out_stream.GetSize(), ASYNC); 1119 } 1120 } 1121 break; 1122 } 1123 } 1124} 1125 1126void 1127Driver::HandleThreadEvent (const SBEvent &event) 1128{ 1129 // At present the only thread event we handle is the Frame Changed event, and all we do for that is just 1130 // reprint the thread status for that thread. 1131 using namespace lldb; 1132 const uint32_t event_type = event.GetType(); 1133 if (event_type == SBThread::eBroadcastBitStackChanged 1134 || event_type == SBThread::eBroadcastBitThreadSelected) 1135 { 1136 SBThread thread = SBThread::GetThreadFromEvent (event); 1137 if (thread.IsValid()) 1138 { 1139 SBStream out_stream; 1140 thread.GetStatus(out_stream); 1141 m_io_channel_ap->OutWrite (out_stream.GetData (), out_stream.GetSize (), ASYNC); 1142 } 1143 } 1144} 1145 1146// This function handles events broadcast by the IOChannel (HasInput, UserInterrupt, or ThreadShouldExit). 1147 1148bool 1149Driver::HandleIOEvent (const SBEvent &event) 1150{ 1151 bool quit = false; 1152 1153 const uint32_t event_type = event.GetType(); 1154 1155 if (event_type & IOChannel::eBroadcastBitHasUserInput) 1156 { 1157 // We got some input (i.e. a command string) from the user; pass it off to the command interpreter for 1158 // handling. 1159 1160 const char *command_string = SBEvent::GetCStringFromEvent(event); 1161 if (command_string == NULL) 1162 command_string = ""; 1163 SBCommandReturnObject result; 1164 1165 // We don't want the result to bypass the OutWrite function in IOChannel, as this can result in odd 1166 // output orderings and problems with the prompt. 1167 1168 // Note that we are in the process of executing a command 1169 m_executing_user_command = true; 1170 1171 m_debugger.GetCommandInterpreter().HandleCommand (command_string, result, true); 1172 1173 // Note that we are back from executing a user command 1174 m_executing_user_command = false; 1175 1176 // Display any STDOUT/STDERR _prior_ to emitting the command result text 1177 GetProcessSTDOUT (); 1178 GetProcessSTDERR (); 1179 1180 const bool only_if_no_immediate = true; 1181 1182 // Now emit the command output text from the command we just executed 1183 const size_t output_size = result.GetOutputSize(); 1184 if (output_size > 0) 1185 m_io_channel_ap->OutWrite (result.GetOutput(only_if_no_immediate), output_size, NO_ASYNC); 1186 1187 // Now emit the command error text from the command we just executed 1188 const size_t error_size = result.GetErrorSize(); 1189 if (error_size > 0) 1190 m_io_channel_ap->OutWrite (result.GetError(only_if_no_immediate), error_size, NO_ASYNC); 1191 1192 // We are done getting and running our command, we can now clear the 1193 // m_waiting_for_command so we can get another one. 1194 m_waiting_for_command = false; 1195 1196 // If our editline input reader is active, it means another input reader 1197 // got pushed onto the input reader and caused us to become deactivated. 1198 // When the input reader above us gets popped, we will get re-activated 1199 // and our prompt will refresh in our callback 1200 if (m_editline_reader.IsActive()) 1201 { 1202 ReadyForCommand (); 1203 } 1204 } 1205 else if (event_type & IOChannel::eBroadcastBitUserInterrupt) 1206 { 1207 // This is here to handle control-c interrupts from the user. It has not yet really been implemented. 1208 // TO BE DONE: PROPERLY HANDLE CONTROL-C FROM USER 1209 //m_io_channel_ap->CancelInput(); 1210 // Anything else? Send Interrupt to process? 1211 } 1212 else if ((event_type & IOChannel::eBroadcastBitThreadShouldExit) || 1213 (event_type & IOChannel::eBroadcastBitThreadDidExit)) 1214 { 1215 // If the IOChannel thread is trying to go away, then it is definitely 1216 // time to end the debugging session. 1217 quit = true; 1218 } 1219 1220 return quit; 1221} 1222 1223void 1224Driver::MasterThreadBytesReceived (void *baton, const void *src, size_t src_len) 1225{ 1226 Driver *driver = (Driver*)baton; 1227 driver->GetFromMaster ((const char *)src, src_len); 1228} 1229 1230void 1231Driver::GetFromMaster (const char *src, size_t src_len) 1232{ 1233 // Echo the characters back to the Debugger's stdout, that way if you 1234 // type characters while a command is running, you'll see what you've typed. 1235 FILE *out_fh = m_debugger.GetOutputFileHandle(); 1236 if (out_fh) 1237 ::fwrite (src, 1, src_len, out_fh); 1238} 1239 1240size_t 1241Driver::EditLineInputReaderCallback 1242( 1243 void *baton, 1244 SBInputReader *reader, 1245 InputReaderAction notification, 1246 const char *bytes, 1247 size_t bytes_len 1248) 1249{ 1250 Driver *driver = (Driver *)baton; 1251 1252 switch (notification) 1253 { 1254 case eInputReaderActivate: 1255 break; 1256 1257 case eInputReaderReactivate: 1258 if (driver->m_executing_user_command == false) 1259 driver->ReadyForCommand(); 1260 break; 1261 1262 case eInputReaderDeactivate: 1263 break; 1264 1265 case eInputReaderAsynchronousOutputWritten: 1266 if (driver->m_io_channel_ap.get() != NULL) 1267 driver->m_io_channel_ap->RefreshPrompt(); 1268 break; 1269 1270 case eInputReaderInterrupt: 1271 if (driver->m_io_channel_ap.get() != NULL) 1272 { 1273 SBProcess process(driver->GetDebugger().GetSelectedTarget().GetProcess()); 1274 if (!driver->m_io_channel_ap->EditLineHasCharacters() 1275 && process.IsValid() 1276 && (process.GetState() == lldb::eStateRunning || process.GetState() == lldb::eStateAttaching)) 1277 { 1278 process.SendAsyncInterrupt (); 1279 } 1280 else 1281 { 1282 driver->m_io_channel_ap->OutWrite ("^C\n", 3, NO_ASYNC); 1283 // I wish I could erase the entire input line, but there's no public API for that. 1284 driver->m_io_channel_ap->EraseCharsBeforeCursor(); 1285 driver->m_io_channel_ap->RefreshPrompt(); 1286 } 1287 } 1288 break; 1289 1290 case eInputReaderEndOfFile: 1291 if (driver->m_io_channel_ap.get() != NULL) 1292 { 1293 driver->m_io_channel_ap->OutWrite ("^D\n", 3, NO_ASYNC); 1294 driver->m_io_channel_ap->RefreshPrompt (); 1295 } 1296 write (driver->m_editline_pty.GetMasterFileDescriptor(), "quit\n", 5); 1297 break; 1298 1299 case eInputReaderGotToken: 1300 write (driver->m_editline_pty.GetMasterFileDescriptor(), bytes, bytes_len); 1301 break; 1302 1303 case eInputReaderDone: 1304 break; 1305 } 1306 return bytes_len; 1307} 1308 1309void 1310Driver::MainLoop () 1311{ 1312#if defined(_MSC_VER) 1313 m_editline_slave_fh = stdin; 1314 FILE *editline_output_slave_fh = stdout; 1315 lldb_utility::PseudoTerminal editline_output_pty; 1316#else 1317 1318 char error_str[1024]; 1319 if (m_editline_pty.OpenFirstAvailableMaster(O_RDWR|O_NOCTTY, error_str, sizeof(error_str)) == false) 1320 { 1321 ::fprintf (stderr, "error: failed to open driver pseudo terminal : %s", error_str); 1322 exit(1); 1323 } 1324 else 1325 { 1326 const char *driver_slave_name = m_editline_pty.GetSlaveName (error_str, sizeof(error_str)); 1327 if (driver_slave_name == NULL) 1328 { 1329 ::fprintf (stderr, "error: failed to get slave name for driver pseudo terminal : %s", error_str); 1330 exit(2); 1331 } 1332 else 1333 { 1334 m_editline_slave_fh = ::fopen (driver_slave_name, "r+"); 1335 if (m_editline_slave_fh == NULL) 1336 { 1337 SBError error; 1338 error.SetErrorToErrno(); 1339 ::fprintf (stderr, "error: failed to get open slave for driver pseudo terminal : %s", 1340 error.GetCString()); 1341 exit(3); 1342 } 1343 1344 ::setbuf (m_editline_slave_fh, NULL); 1345 } 1346 } 1347 1348 lldb_utility::PseudoTerminal editline_output_pty; 1349 FILE *editline_output_slave_fh = NULL; 1350 1351 if (editline_output_pty.OpenFirstAvailableMaster (O_RDWR|O_NOCTTY, error_str, sizeof (error_str)) == false) 1352 { 1353 ::fprintf (stderr, "error: failed to open output pseudo terminal : %s", error_str); 1354 exit(1); 1355 } 1356 else 1357 { 1358 const char *output_slave_name = editline_output_pty.GetSlaveName (error_str, sizeof(error_str)); 1359 if (output_slave_name == NULL) 1360 { 1361 ::fprintf (stderr, "error: failed to get slave name for output pseudo terminal : %s", error_str); 1362 exit(2); 1363 } 1364 else 1365 { 1366 editline_output_slave_fh = ::fopen (output_slave_name, "r+"); 1367 if (editline_output_slave_fh == NULL) 1368 { 1369 SBError error; 1370 error.SetErrorToErrno(); 1371 ::fprintf (stderr, "error: failed to get open slave for output pseudo terminal : %s", 1372 error.GetCString()); 1373 exit(3); 1374 } 1375 ::setbuf (editline_output_slave_fh, NULL); 1376 } 1377 } 1378#endif 1379 1380 // struct termios stdin_termios; 1381 1382 if (::tcgetattr(STDIN_FILENO, &g_old_stdin_termios) == 0) 1383 { 1384 g_old_stdin_termios_is_valid = true; 1385 atexit (reset_stdin_termios); 1386 } 1387 1388 ::setbuf (stdin, NULL); 1389 ::setbuf (stdout, NULL); 1390 1391 m_debugger.SetErrorFileHandle (stderr, false); 1392 m_debugger.SetOutputFileHandle (stdout, false); 1393 m_debugger.SetInputFileHandle (stdin, true); 1394 1395 m_debugger.SetUseExternalEditor(m_option_data.m_use_external_editor); 1396 1397 // You have to drain anything that comes to the master side of the PTY. master_out_comm is 1398 // for that purpose. The reason you need to do this is a curious reason... editline will echo 1399 // characters to the PTY when it gets characters while el_gets is not running, and then when 1400 // you call el_gets (or el_getc) it will try to reset the terminal back to raw mode which blocks 1401 // if there are unconsumed characters in the out buffer. 1402 // However, you don't need to do anything with the characters, since editline will dump these 1403 // unconsumed characters after printing the prompt again in el_gets. 1404 1405 SBCommunication master_out_comm("driver.editline"); 1406 master_out_comm.SetCloseOnEOF (false); 1407 master_out_comm.AdoptFileDesriptor(m_editline_pty.GetMasterFileDescriptor(), false); 1408 master_out_comm.SetReadThreadBytesReceivedCallback(Driver::MasterThreadBytesReceived, this); 1409 1410 if (master_out_comm.ReadThreadStart () == false) 1411 { 1412 ::fprintf (stderr, "error: failed to start master out read thread"); 1413 exit(5); 1414 } 1415 1416 SBCommandInterpreter sb_interpreter = m_debugger.GetCommandInterpreter(); 1417 1418 m_io_channel_ap.reset (new IOChannel(m_editline_slave_fh, editline_output_slave_fh, stdout, stderr, this)); 1419 1420#if !defined (_MSC_VER) 1421 SBCommunication out_comm_2("driver.editline_output"); 1422 out_comm_2.SetCloseOnEOF (false); 1423 out_comm_2.AdoptFileDesriptor (editline_output_pty.GetMasterFileDescriptor(), false); 1424 out_comm_2.SetReadThreadBytesReceivedCallback (IOChannel::LibeditOutputBytesReceived, m_io_channel_ap.get()); 1425 1426 if (out_comm_2.ReadThreadStart () == false) 1427 { 1428 ::fprintf (stderr, "error: failed to start libedit output read thread"); 1429 exit (5); 1430 } 1431#endif 1432 1433 1434 struct winsize window_size; 1435 if (isatty (STDIN_FILENO) 1436 && ::ioctl (STDIN_FILENO, TIOCGWINSZ, &window_size) == 0) 1437 { 1438 if (window_size.ws_col > 0) 1439 m_debugger.SetTerminalWidth (window_size.ws_col); 1440 } 1441 1442 // Since input can be redirected by the debugger, we must insert our editline 1443 // input reader in the queue so we know when our reader should be active 1444 // and so we can receive bytes only when we are supposed to. 1445 SBError err (m_editline_reader.Initialize (m_debugger, 1446 Driver::EditLineInputReaderCallback, // callback 1447 this, // baton 1448 eInputReaderGranularityByte, // token_size 1449 NULL, // end token - NULL means never done 1450 NULL, // prompt - taken care of elsewhere 1451 false)); // echo input - don't need Debugger 1452 // to do this, we handle it elsewhere 1453 1454 if (err.Fail()) 1455 { 1456 ::fprintf (stderr, "error: %s", err.GetCString()); 1457 exit (6); 1458 } 1459 1460 m_debugger.PushInputReader (m_editline_reader); 1461 1462 SBListener listener(m_debugger.GetListener()); 1463 if (listener.IsValid()) 1464 { 1465 1466 listener.StartListeningForEventClass(m_debugger, 1467 SBTarget::GetBroadcasterClassName(), 1468 SBTarget::eBroadcastBitBreakpointChanged); 1469 listener.StartListeningForEventClass(m_debugger, 1470 SBThread::GetBroadcasterClassName(), 1471 SBThread::eBroadcastBitStackChanged | 1472 SBThread::eBroadcastBitThreadSelected); 1473 listener.StartListeningForEvents (*m_io_channel_ap, 1474 IOChannel::eBroadcastBitHasUserInput | 1475 IOChannel::eBroadcastBitUserInterrupt | 1476 IOChannel::eBroadcastBitThreadShouldExit | 1477 IOChannel::eBroadcastBitThreadDidStart | 1478 IOChannel::eBroadcastBitThreadDidExit); 1479 1480 if (m_io_channel_ap->Start ()) 1481 { 1482 bool iochannel_thread_exited = false; 1483 1484 listener.StartListeningForEvents (sb_interpreter.GetBroadcaster(), 1485 SBCommandInterpreter::eBroadcastBitQuitCommandReceived | 1486 SBCommandInterpreter::eBroadcastBitAsynchronousOutputData | 1487 SBCommandInterpreter::eBroadcastBitAsynchronousErrorData); 1488 1489 // Before we handle any options from the command line, we parse the 1490 // .lldbinit file in the user's home directory. 1491 SBCommandReturnObject result; 1492 sb_interpreter.SourceInitFileInHomeDirectory(result); 1493 if (GetDebugMode()) 1494 { 1495 result.PutError (m_debugger.GetErrorFileHandle()); 1496 result.PutOutput (m_debugger.GetOutputFileHandle()); 1497 } 1498 1499 // Now we handle options we got from the command line 1500 // First source in the commands specified to be run before the file arguments are processed. 1501 ExecuteInitialCommands(true); 1502 1503 // Was there a core file specified? 1504 std::string core_file_spec(""); 1505 if (!m_option_data.m_core_file.empty()) 1506 core_file_spec.append("--core ").append(m_option_data.m_core_file); 1507 1508 char command_string[PATH_MAX * 2]; 1509 const size_t num_args = m_option_data.m_args.size(); 1510 if (num_args > 0) 1511 { 1512 char arch_name[64]; 1513 if (m_debugger.GetDefaultArchitecture (arch_name, sizeof (arch_name))) 1514 ::snprintf (command_string, 1515 sizeof (command_string), 1516 "target create --arch=%s %s \"%s\"", 1517 arch_name, 1518 core_file_spec.c_str(), 1519 m_option_data.m_args[0].c_str()); 1520 else 1521 ::snprintf (command_string, 1522 sizeof(command_string), 1523 "target create %s \"%s\"", 1524 core_file_spec.c_str(), 1525 m_option_data.m_args[0].c_str()); 1526 1527 m_debugger.HandleCommand (command_string); 1528 1529 if (num_args > 1) 1530 { 1531 m_debugger.HandleCommand ("settings clear target.run-args"); 1532 char arg_cstr[1024]; 1533 for (size_t arg_idx = 1; arg_idx < num_args; ++arg_idx) 1534 { 1535 ::snprintf (arg_cstr, 1536 sizeof(arg_cstr), 1537 "settings append target.run-args \"%s\"", 1538 m_option_data.m_args[arg_idx].c_str()); 1539 m_debugger.HandleCommand (arg_cstr); 1540 } 1541 } 1542 } 1543 else if (!core_file_spec.empty()) 1544 { 1545 ::snprintf (command_string, 1546 sizeof(command_string), 1547 "target create %s", 1548 core_file_spec.c_str()); 1549 m_debugger.HandleCommand (command_string);; 1550 } 1551 1552 // Now that all option parsing is done, we try and parse the .lldbinit 1553 // file in the current working directory 1554 sb_interpreter.SourceInitFileInCurrentWorkingDirectory (result); 1555 if (GetDebugMode()) 1556 { 1557 result.PutError(m_debugger.GetErrorFileHandle()); 1558 result.PutOutput(m_debugger.GetOutputFileHandle()); 1559 } 1560 1561 // Now execute the commands specified for after the file arguments are processed. 1562 ExecuteInitialCommands(false); 1563 1564 SBEvent event; 1565 1566 // Make sure the IO channel is started up before we try to tell it we 1567 // are ready for input 1568 listener.WaitForEventForBroadcasterWithType (UINT32_MAX, 1569 *m_io_channel_ap, 1570 IOChannel::eBroadcastBitThreadDidStart, 1571 event); 1572 // If we were asked to attach, then do that here: 1573 // I'm going to use the command string rather than directly 1574 // calling the API's because then I don't have to recode the 1575 // event handling here. 1576 if (!m_option_data.m_process_name.empty() 1577 || m_option_data.m_process_pid != LLDB_INVALID_PROCESS_ID) 1578 { 1579 std::string command_str("process attach "); 1580 if (m_option_data.m_process_pid != LLDB_INVALID_PROCESS_ID) 1581 { 1582 command_str.append("-p "); 1583 char pid_buffer[32]; 1584 ::snprintf (pid_buffer, sizeof(pid_buffer), "%" PRIu64, m_option_data.m_process_pid); 1585 command_str.append(pid_buffer); 1586 } 1587 else 1588 { 1589 command_str.append("-n \""); 1590 command_str.append(m_option_data.m_process_name); 1591 command_str.push_back('\"'); 1592 if (m_option_data.m_wait_for) 1593 command_str.append(" -w"); 1594 } 1595 1596 if (m_debugger.GetOutputFileHandle()) 1597 ::fprintf (m_debugger.GetOutputFileHandle(), 1598 "Attaching to process with:\n %s\n", 1599 command_str.c_str()); 1600 1601 // Force the attach to be synchronous: 1602 bool orig_async = m_debugger.GetAsync(); 1603 m_debugger.SetAsync(true); 1604 m_debugger.HandleCommand(command_str.c_str()); 1605 m_debugger.SetAsync(orig_async); 1606 } 1607 1608 ReadyForCommand (); 1609 1610 while (!GetIsDone()) 1611 { 1612 listener.WaitForEvent (UINT32_MAX, event); 1613 if (event.IsValid()) 1614 { 1615 if (event.GetBroadcaster().IsValid()) 1616 { 1617 uint32_t event_type = event.GetType(); 1618 if (event.BroadcasterMatchesRef (*m_io_channel_ap)) 1619 { 1620 if ((event_type & IOChannel::eBroadcastBitThreadShouldExit) || 1621 (event_type & IOChannel::eBroadcastBitThreadDidExit)) 1622 { 1623 SetIsDone(); 1624 if (event_type & IOChannel::eBroadcastBitThreadDidExit) 1625 iochannel_thread_exited = true; 1626 } 1627 else 1628 { 1629 if (HandleIOEvent (event)) 1630 SetIsDone(); 1631 } 1632 } 1633 else if (SBProcess::EventIsProcessEvent (event)) 1634 { 1635 HandleProcessEvent (event); 1636 } 1637 else if (SBBreakpoint::EventIsBreakpointEvent (event)) 1638 { 1639 HandleBreakpointEvent (event); 1640 } 1641 else if (SBThread::EventIsThreadEvent (event)) 1642 { 1643 HandleThreadEvent (event); 1644 } 1645 else if (event.BroadcasterMatchesRef (sb_interpreter.GetBroadcaster())) 1646 { 1647 // TODO: deprecate the eBroadcastBitQuitCommandReceived event 1648 // now that we have SBCommandInterpreter::SetCommandOverrideCallback() 1649 // that can take over a command 1650 if (event_type & SBCommandInterpreter::eBroadcastBitQuitCommandReceived) 1651 { 1652 SetIsDone(); 1653 } 1654 else if (event_type & SBCommandInterpreter::eBroadcastBitAsynchronousErrorData) 1655 { 1656 const char *data = SBEvent::GetCStringFromEvent (event); 1657 m_io_channel_ap->ErrWrite (data, strlen(data), ASYNC); 1658 } 1659 else if (event_type & SBCommandInterpreter::eBroadcastBitAsynchronousOutputData) 1660 { 1661 const char *data = SBEvent::GetCStringFromEvent (event); 1662 m_io_channel_ap->OutWrite (data, strlen(data), ASYNC); 1663 } 1664 } 1665 } 1666 } 1667 } 1668 1669 master_out_comm.SetReadThreadBytesReceivedCallback(NULL, NULL); 1670 master_out_comm.Disconnect(); 1671 master_out_comm.ReadThreadStop(); 1672 1673#if !defined(_MSC_VER) 1674 out_comm_2.SetReadThreadBytesReceivedCallback(NULL, NULL); 1675 out_comm_2.Disconnect(); 1676 out_comm_2.ReadThreadStop(); 1677#endif 1678 1679 editline_output_pty.CloseMasterFileDescriptor(); 1680 reset_stdin_termios(); 1681 fclose (stdin); 1682 1683 CloseIOChannelFile (); 1684 1685 if (!iochannel_thread_exited) 1686 { 1687 event.Clear(); 1688 listener.GetNextEventForBroadcasterWithType (*m_io_channel_ap, 1689 IOChannel::eBroadcastBitThreadDidExit, 1690 event); 1691 if (!event.IsValid()) 1692 { 1693 // Send end EOF to the driver file descriptor 1694 m_io_channel_ap->Stop(); 1695 } 1696 } 1697 1698 SBDebugger::Destroy (m_debugger); 1699 } 1700 } 1701} 1702 1703 1704void 1705Driver::ReadyForCommand () 1706{ 1707 if (m_waiting_for_command == false) 1708 { 1709 m_waiting_for_command = true; 1710 BroadcastEventByType (Driver::eBroadcastBitReadyForInput, true); 1711 } 1712} 1713 1714void 1715Driver::ResizeWindow (unsigned short col) 1716{ 1717 GetDebugger().SetTerminalWidth (col); 1718 if (m_io_channel_ap.get() != NULL) 1719 { 1720 m_io_channel_ap->ElResize(); 1721 } 1722} 1723 1724void 1725sigwinch_handler (int signo) 1726{ 1727 struct winsize window_size; 1728 if (isatty (STDIN_FILENO) 1729 && ::ioctl (STDIN_FILENO, TIOCGWINSZ, &window_size) == 0) 1730 { 1731 if ((window_size.ws_col > 0) && g_driver != NULL) 1732 { 1733 g_driver->ResizeWindow (window_size.ws_col); 1734 } 1735 } 1736} 1737 1738void 1739sigint_handler (int signo) 1740{ 1741 static bool g_interrupt_sent = false; 1742 if (g_driver) 1743 { 1744 if (!g_interrupt_sent) 1745 { 1746 g_interrupt_sent = true; 1747 g_driver->GetDebugger().DispatchInputInterrupt(); 1748 g_interrupt_sent = false; 1749 return; 1750 } 1751 } 1752 1753 exit (signo); 1754} 1755 1756void 1757sigtstp_handler (int signo) 1758{ 1759 g_driver->GetDebugger().SaveInputTerminalState(); 1760 signal (signo, SIG_DFL); 1761 kill (getpid(), signo); 1762 signal (signo, sigtstp_handler); 1763} 1764 1765void 1766sigcont_handler (int signo) 1767{ 1768 g_driver->GetDebugger().RestoreInputTerminalState(); 1769 signal (signo, SIG_DFL); 1770 kill (getpid(), signo); 1771 signal (signo, sigcont_handler); 1772} 1773 1774int 1775main (int argc, char const *argv[], const char *envp[]) 1776{ 1777 SBDebugger::Initialize(); 1778 1779 SBHostOS::ThreadCreated ("<lldb.driver.main-thread>"); 1780 1781 signal (SIGPIPE, SIG_IGN); 1782 signal (SIGWINCH, sigwinch_handler); 1783 signal (SIGINT, sigint_handler); 1784 signal (SIGTSTP, sigtstp_handler); 1785 signal (SIGCONT, sigcont_handler); 1786 1787 // Create a scope for driver so that the driver object will destroy itself 1788 // before SBDebugger::Terminate() is called. 1789 { 1790 Driver driver; 1791 1792 bool exiting = false; 1793 SBError error (driver.ParseArgs (argc, argv, stdout, exiting)); 1794 if (error.Fail()) 1795 { 1796 const char *error_cstr = error.GetCString (); 1797 if (error_cstr) 1798 ::fprintf (stderr, "error: %s\n", error_cstr); 1799 } 1800 else if (!exiting) 1801 { 1802 driver.MainLoop (); 1803 } 1804 } 1805 1806 SBDebugger::Terminate(); 1807 return 0; 1808} 1809