1 //===-- CommandObjectBreakpointCommand.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 // C Includes 11 // C++ Includes 12 13 14 #include "CommandObjectBreakpointCommand.h" 15 #include "CommandObjectBreakpoint.h" 16 17 #include "lldb/Interpreter/CommandInterpreter.h" 18 #include "lldb/Interpreter/CommandReturnObject.h" 19 #include "lldb/Target/Target.h" 20 #include "lldb/Target/Thread.h" 21 #include "lldb/Breakpoint/BreakpointIDList.h" 22 #include "lldb/Breakpoint/Breakpoint.h" 23 #include "lldb/Breakpoint/BreakpointLocation.h" 24 #include "lldb/Breakpoint/StoppointCallbackContext.h" 25 #include "lldb/Core/State.h" 26 27 using namespace lldb; 28 using namespace lldb_private; 29 30 //------------------------------------------------------------------------- 31 // CommandObjectBreakpointCommandAdd::CommandOptions 32 //------------------------------------------------------------------------- 33 34 CommandObjectBreakpointCommandAdd::CommandOptions::CommandOptions () : 35 Options () 36 { 37 } 38 39 CommandObjectBreakpointCommandAdd::CommandOptions::~CommandOptions () 40 { 41 } 42 43 lldb::OptionDefinition 44 CommandObjectBreakpointCommandAdd::CommandOptions::g_option_table[] = 45 { 46 { LLDB_OPT_SET_1, true, "script", 's', no_argument, NULL, 0, NULL, 47 "Write the breakpoint command script in the default scripting language."}, 48 49 { LLDB_OPT_SET_2, true, "python", 'p', no_argument, NULL, 0, NULL, 50 "Write the breakpoint command script in the Python scripting language."}, 51 52 { LLDB_OPT_SET_3, true, "commands", 'c', no_argument, NULL, 0, NULL, 53 "Write the breakpoint command script using standard debugger commands."}, 54 55 { 0, false, NULL, 0, 0, NULL, 0, NULL, NULL } 56 }; 57 58 const lldb::OptionDefinition* 59 CommandObjectBreakpointCommandAdd::CommandOptions::GetDefinitions () 60 { 61 return g_option_table; 62 } 63 64 65 Error 66 CommandObjectBreakpointCommandAdd::CommandOptions::SetOptionValue 67 ( 68 int option_idx, 69 const char *option_arg 70 ) 71 { 72 Error error; 73 char short_option = (char) m_getopt_table[option_idx].val; 74 75 switch (short_option) 76 { 77 case 's': 78 m_use_commands = false; 79 m_use_script_language = true; 80 m_script_language = eScriptLanguageDefault; 81 break; 82 case 'p': 83 m_use_commands = false; 84 m_use_script_language = true; 85 m_script_language = eScriptLanguagePython; 86 break; 87 case 'c': 88 m_use_commands = true; 89 m_use_script_language = false; 90 m_script_language = eScriptLanguageNone; 91 break; 92 default: 93 break; 94 } 95 return error; 96 } 97 98 void 99 CommandObjectBreakpointCommandAdd::CommandOptions::ResetOptionValues () 100 { 101 Options::ResetOptionValues(); 102 103 m_use_commands = false; 104 m_use_script_language = false; 105 m_script_language = eScriptLanguageNone; 106 } 107 108 //------------------------------------------------------------------------- 109 // CommandObjectBreakpointCommandAdd 110 //------------------------------------------------------------------------- 111 112 113 CommandObjectBreakpointCommandAdd::CommandObjectBreakpointCommandAdd () : 114 CommandObject ("add", 115 "Add a set of commands to a breakpoint, to be executed whenever the breakpoint is hit.", 116 "breakpoint command add <cmd-options> <breakpoint-id>") 117 { 118 SetHelpLong ( 119 "\nGeneral information about entering breakpoint commands \n\ 120 ------------------------------------------------------ \n\ 121 \n\ 122 This command will cause you to be prompted to enter the command or set \n\ 123 of commands you wish to be executed when the specified breakpoint is \n\ 124 hit. You will be told to enter your command(s), and will see a '> ' \n\ 125 prompt. Because you can enter one or many commands to be executed when \n\ 126 a breakpoint is hit, you will continue to be prompted after each \n\ 127 new-line that you enter, until you enter the word 'DONE', which will \n\ 128 cause the commands you have entered to be stored with the breakpoint \n\ 129 and executed when the breakpoint is hit. \n\ 130 \n\ 131 Syntax checking is not necessarily done when breakpoint commands are \n\ 132 entered. An improperly written breakpoint command will attempt to get \n\ 133 executed when the breakpoint gets hit, and usually silently fail. If \n\ 134 your breakpoint command does not appear to be getting executed, go \n\ 135 back and check your syntax. \n\ 136 \n\ 137 \n\ 138 Special information about PYTHON breakpoint commands \n\ 139 ---------------------------------------------------- \n\ 140 \n\ 141 You may enter either one line of Python or multiple lines of Python \n\ 142 (including defining whole functions, if desired). If you enter a \n\ 143 single line of Python, that will be passed to the Python interpreter \n\ 144 'as is' when the breakpoint gets hit. If you enter function \n\ 145 definitions, they will be passed to the Python interpreter as soon as \n\ 146 you finish entering the breakpoint command, and they can be called \n\ 147 later (don't forget to add calls to them, if you want them called when \n\ 148 the breakpoint is hit). If you enter multiple lines of Python that \n\ 149 are not function definitions, they will be collected into a new, \n\ 150 automatically generated Python function, and a call to the newly \n\ 151 generated function will be attached to the breakpoint. Important \n\ 152 Note: Because loose Python code gets collected into functions, if you \n\ 153 want to access global variables in the 'loose' code, you need to \n\ 154 specify that they are global, using the 'global' keyword. Be sure to \n\ 155 use correct Python syntax, including indentation, when entering Python \n\ 156 breakpoint commands. \n\ 157 \n\ 158 Example Python one-line breakpoint command: \n\ 159 \n\ 160 (lldb) breakpoint command add -p 1 \n\ 161 Enter your Python command(s). Type 'DONE' to end. \n\ 162 > print \"Hit this breakpoint!\" \n\ 163 > DONE \n\ 164 \n\ 165 As a convenience, this also works for a short Python one-liner: \n\ 166 (lldb) breakpoint command add -p 1 \"import time; print time.asctime()\" \n\ 167 (lldb) run \n\ 168 Launching '.../a.out' (x86_64) \n\ 169 (lldb) Fri Sep 10 12:17:45 2010 \n\ 170 Process 21778 Stopped \n\ 171 * thread #1: tid = 0x2e03, 0x0000000100000de8 a.out`c + 7 at main.c:39, stop reason = breakpoint 1.1, queue = com.apple.main-thread \n\ 172 36 \n\ 173 37 int c(int val)\n\ 174 38 {\n\ 175 39 -> return val + 3;\n\ 176 40 }\n\ 177 41 \n\ 178 42 int main (int argc, char const *argv[])\n\ 179 (lldb) \n\ 180 \n\ 181 Example multiple line Python breakpoint command, using function definition: \n\ 182 \n\ 183 (lldb) breakpoint command add -p 1 \n\ 184 Enter your Python command(s). Type 'DONE' to end. \n\ 185 > def breakpoint_output (bp_no): \n\ 186 > out_string = \"Hit breakpoint number \" + repr (bp_no) \n\ 187 > print out_string \n\ 188 > return True \n\ 189 > breakpoint_output (1) \n\ 190 > DONE \n\ 191 \n\ 192 \n\ 193 Example multiple line Python breakpoint command, using 'loose' Python: \n\ 194 \n\ 195 (lldb) breakpoint command add -p 1 \n\ 196 Enter your Python command(s). Type 'DONE' to end. \n\ 197 > global bp_count \n\ 198 > bp_count = bp_count + 1 \n\ 199 > print \"Hit this breakpoint \" + repr(bp_count) + \" times!\" \n\ 200 > DONE \n\ 201 \n\ 202 In this case, since there is a reference to a global variable, \n\ 203 'bp_count', you will also need to make sure 'bp_count' exists and is \n\ 204 initialized: \n\ 205 \n\ 206 (lldb) script \n\ 207 >>> bp_count = 0 \n\ 208 >>> quit() \n\ 209 \n\ 210 (lldb) \n\ 211 \n\ 212 Special information about debugger command breakpoint commands \n\ 213 -------------------------------------------------------------- \n\ 214 \n\ 215 You may enter any debugger command, exactly as you would at the \n\ 216 debugger prompt. You may enter as many debugger commands as you like, \n\ 217 but do NOT enter more than one command per line. \n" ); 218 } 219 220 CommandObjectBreakpointCommandAdd::~CommandObjectBreakpointCommandAdd () 221 { 222 } 223 224 bool 225 CommandObjectBreakpointCommandAdd::Execute 226 ( 227 CommandInterpreter &interpreter, 228 Args& command, 229 CommandReturnObject &result 230 ) 231 { 232 Target *target = interpreter.GetDebugger().GetSelectedTarget().get(); 233 234 if (target == NULL) 235 { 236 result.AppendError ("There is not a current executable; there are no breakpoints to which to add commands"); 237 result.SetStatus (eReturnStatusFailed); 238 return false; 239 } 240 241 const BreakpointList &breakpoints = target->GetBreakpointList(); 242 size_t num_breakpoints = breakpoints.GetSize(); 243 244 if (num_breakpoints == 0) 245 { 246 result.AppendError ("No breakpoints exist to have commands added"); 247 result.SetStatus (eReturnStatusFailed); 248 return false; 249 } 250 251 if (command.GetArgumentCount() == 0) 252 { 253 result.AppendError ("No breakpoint specified to which to add the commands"); 254 result.SetStatus (eReturnStatusFailed); 255 return false; 256 } 257 258 BreakpointIDList valid_bp_ids; 259 CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (command, target, result, &valid_bp_ids); 260 261 if (result.Succeeded()) 262 { 263 const size_t count = valid_bp_ids.GetSize(); 264 for (size_t i = 0; i < count; ++i) 265 { 266 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i); 267 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) 268 { 269 Breakpoint *bp = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get(); 270 if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) 271 { 272 BreakpointLocationSP bp_loc_sp(bp->FindLocationByID (cur_bp_id.GetLocationID())); 273 if (bp_loc_sp) 274 { 275 if (m_options.m_use_script_language) 276 { 277 // Special handling for one-liner. 278 if (command.GetArgumentCount() == 2) 279 interpreter.GetScriptInterpreter()->SetBreakpointCommandCallback (interpreter, 280 bp_loc_sp->GetLocationOptions(), 281 command.GetArgumentAtIndex(1)); 282 else 283 interpreter.GetScriptInterpreter()->CollectDataForBreakpointCommandCallback (interpreter, 284 bp_loc_sp->GetLocationOptions(), 285 result); 286 } 287 else 288 { 289 CollectDataForBreakpointCommandCallback (interpreter, 290 bp_loc_sp->GetLocationOptions(), 291 result); 292 } 293 } 294 } 295 else 296 { 297 if (m_options.m_use_script_language) 298 { 299 // Special handling for one-liner. 300 if (command.GetArgumentCount() == 2) 301 interpreter.GetScriptInterpreter()->SetBreakpointCommandCallback (interpreter, 302 bp->GetOptions(), 303 command.GetArgumentAtIndex(1)); 304 else 305 interpreter.GetScriptInterpreter()->CollectDataForBreakpointCommandCallback (interpreter, 306 bp->GetOptions(), 307 result); 308 } 309 else 310 { 311 CollectDataForBreakpointCommandCallback (interpreter, 312 bp->GetOptions(), 313 result); 314 } 315 } 316 } 317 } 318 } 319 320 return result.Succeeded(); 321 } 322 323 Options * 324 CommandObjectBreakpointCommandAdd::GetOptions () 325 { 326 return &m_options; 327 } 328 329 const char *g_reader_instructions = "Enter your debugger command(s). Type 'DONE' to end."; 330 331 void 332 CommandObjectBreakpointCommandAdd::CollectDataForBreakpointCommandCallback 333 ( 334 CommandInterpreter &interpreter, 335 BreakpointOptions *bp_options, 336 CommandReturnObject &result 337 ) 338 { 339 InputReaderSP reader_sp (new InputReader(interpreter.GetDebugger())); 340 std::auto_ptr<BreakpointOptions::CommandData> data_ap(new BreakpointOptions::CommandData()); 341 if (reader_sp && data_ap.get()) 342 { 343 BatonSP baton_sp (new BreakpointOptions::CommandBaton (data_ap.release())); 344 bp_options->SetCallback (CommandObjectBreakpointCommand::BreakpointOptionsCallbackFunction, baton_sp); 345 346 Error err (reader_sp->Initialize (CommandObjectBreakpointCommandAdd::GenerateBreakpointCommandCallback, 347 bp_options, // baton 348 eInputReaderGranularityLine, // token size, to pass to callback function 349 "DONE", // end token 350 "> ", // prompt 351 true)); // echo input 352 if (err.Success()) 353 { 354 interpreter.GetDebugger().PushInputReader (reader_sp); 355 result.SetStatus (eReturnStatusSuccessFinishNoResult); 356 } 357 else 358 { 359 result.AppendError (err.AsCString()); 360 result.SetStatus (eReturnStatusFailed); 361 } 362 } 363 else 364 { 365 result.AppendError("out of memory"); 366 result.SetStatus (eReturnStatusFailed); 367 } 368 369 } 370 371 size_t 372 CommandObjectBreakpointCommandAdd::GenerateBreakpointCommandCallback 373 ( 374 void *baton, 375 InputReader &reader, 376 lldb::InputReaderAction notification, 377 const char *bytes, 378 size_t bytes_len 379 ) 380 { 381 FILE *out_fh = reader.GetDebugger().GetOutputFileHandle(); 382 383 switch (notification) 384 { 385 case eInputReaderActivate: 386 if (out_fh) 387 { 388 ::fprintf (out_fh, "%s\n", g_reader_instructions); 389 if (reader.GetPrompt()) 390 ::fprintf (out_fh, "%s", reader.GetPrompt()); 391 } 392 break; 393 394 case eInputReaderDeactivate: 395 break; 396 397 case eInputReaderReactivate: 398 if (out_fh && reader.GetPrompt()) 399 ::fprintf (out_fh, "%s", reader.GetPrompt()); 400 break; 401 402 case eInputReaderGotToken: 403 if (bytes && bytes_len && baton) 404 { 405 BreakpointOptions *bp_options = (BreakpointOptions *) baton; 406 if (bp_options) 407 { 408 Baton *bp_options_baton = bp_options->GetBaton(); 409 if (bp_options_baton) 410 ((BreakpointOptions::CommandData *)bp_options_baton->m_data)->user_source.AppendString (bytes, bytes_len); 411 } 412 } 413 if (out_fh && !reader.IsDone() && reader.GetPrompt()) 414 ::fprintf (out_fh, "%s", reader.GetPrompt()); 415 break; 416 417 case eInputReaderDone: 418 break; 419 } 420 421 return bytes_len; 422 } 423 424 425 //------------------------------------------------------------------------- 426 // CommandObjectBreakpointCommandRemove 427 //------------------------------------------------------------------------- 428 429 CommandObjectBreakpointCommandRemove::CommandObjectBreakpointCommandRemove () : 430 CommandObject ("remove", 431 "Remove the set of commands from a breakpoint.", 432 "breakpoint command remove <breakpoint-id>") 433 { 434 } 435 436 CommandObjectBreakpointCommandRemove::~CommandObjectBreakpointCommandRemove () 437 { 438 } 439 440 bool 441 CommandObjectBreakpointCommandRemove::Execute 442 ( 443 CommandInterpreter &interpreter, 444 Args& command, 445 CommandReturnObject &result 446 ) 447 { 448 Target *target = interpreter.GetDebugger().GetSelectedTarget().get(); 449 450 if (target == NULL) 451 { 452 result.AppendError ("There is not a current executable; there are no breakpoints from which to remove commands"); 453 result.SetStatus (eReturnStatusFailed); 454 return false; 455 } 456 457 const BreakpointList &breakpoints = target->GetBreakpointList(); 458 size_t num_breakpoints = breakpoints.GetSize(); 459 460 if (num_breakpoints == 0) 461 { 462 result.AppendError ("No breakpoints exist to have commands removed"); 463 result.SetStatus (eReturnStatusFailed); 464 return false; 465 } 466 467 if (command.GetArgumentCount() == 0) 468 { 469 result.AppendError ("No breakpoint specified from which to remove the commands"); 470 result.SetStatus (eReturnStatusFailed); 471 return false; 472 } 473 474 BreakpointIDList valid_bp_ids; 475 CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (command, target, result, &valid_bp_ids); 476 477 if (result.Succeeded()) 478 { 479 const size_t count = valid_bp_ids.GetSize(); 480 for (size_t i = 0; i < count; ++i) 481 { 482 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i); 483 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) 484 { 485 Breakpoint *bp = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get(); 486 if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) 487 { 488 BreakpointLocationSP bp_loc_sp (bp->FindLocationByID (cur_bp_id.GetLocationID())); 489 if (bp_loc_sp) 490 bp_loc_sp->ClearCallback(); 491 else 492 { 493 result.AppendErrorWithFormat("Invalid breakpoint ID: %u.%u.\n", 494 cur_bp_id.GetBreakpointID(), 495 cur_bp_id.GetLocationID()); 496 result.SetStatus (eReturnStatusFailed); 497 return false; 498 } 499 } 500 else 501 { 502 bp->ClearCallback(); 503 } 504 } 505 } 506 } 507 return result.Succeeded(); 508 } 509 510 511 //------------------------------------------------------------------------- 512 // CommandObjectBreakpointCommandList 513 //------------------------------------------------------------------------- 514 515 CommandObjectBreakpointCommandList::CommandObjectBreakpointCommandList () : 516 CommandObject ("List", 517 "List the script or set of commands to be executed when the breakpoint is hit.", 518 "breakpoint command list <breakpoint-id>") 519 { 520 } 521 522 CommandObjectBreakpointCommandList::~CommandObjectBreakpointCommandList () 523 { 524 } 525 526 bool 527 CommandObjectBreakpointCommandList::Execute 528 ( 529 CommandInterpreter &interpreter, 530 Args& command, 531 CommandReturnObject &result 532 ) 533 { 534 Target *target = interpreter.GetDebugger().GetSelectedTarget().get(); 535 536 if (target == NULL) 537 { 538 result.AppendError ("There is not a current executable; there are no breakpoints for which to list commands"); 539 result.SetStatus (eReturnStatusFailed); 540 return false; 541 } 542 543 const BreakpointList &breakpoints = target->GetBreakpointList(); 544 size_t num_breakpoints = breakpoints.GetSize(); 545 546 if (num_breakpoints == 0) 547 { 548 result.AppendError ("No breakpoints exist for which to list commands"); 549 result.SetStatus (eReturnStatusFailed); 550 return false; 551 } 552 553 if (command.GetArgumentCount() == 0) 554 { 555 result.AppendError ("No breakpoint specified for which to list the commands"); 556 result.SetStatus (eReturnStatusFailed); 557 return false; 558 } 559 560 BreakpointIDList valid_bp_ids; 561 CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (command, target, result, &valid_bp_ids); 562 563 if (result.Succeeded()) 564 { 565 const size_t count = valid_bp_ids.GetSize(); 566 for (size_t i = 0; i < count; ++i) 567 { 568 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i); 569 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) 570 { 571 Breakpoint *bp = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get(); 572 573 if (bp) 574 { 575 const BreakpointOptions *bp_options = NULL; 576 if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) 577 { 578 BreakpointLocationSP bp_loc_sp(bp->FindLocationByID (cur_bp_id.GetLocationID())); 579 if (bp_loc_sp) 580 bp_options = bp_loc_sp->GetOptionsNoCreate(); 581 else 582 { 583 result.AppendErrorWithFormat("Invalid breakpoint ID: %u.%u.\n", 584 cur_bp_id.GetBreakpointID(), 585 cur_bp_id.GetLocationID()); 586 result.SetStatus (eReturnStatusFailed); 587 return false; 588 } 589 } 590 else 591 { 592 bp_options = bp->GetOptions(); 593 } 594 595 if (bp_options) 596 { 597 StreamString id_str; 598 BreakpointID::GetCanonicalReference (&id_str, cur_bp_id.GetBreakpointID(), cur_bp_id.GetLocationID()); 599 const Baton *baton = bp_options->GetBaton(); 600 if (baton) 601 { 602 result.GetOutputStream().Printf ("Breakpoint %s:\n", id_str.GetData()); 603 result.GetOutputStream().IndentMore (); 604 baton->GetDescription(&result.GetOutputStream(), eDescriptionLevelFull); 605 result.GetOutputStream().IndentLess (); 606 } 607 else 608 { 609 result.AppendMessageWithFormat ("Breakpoint %s does not have an associated command.\n", id_str.GetData()); 610 } 611 } 612 result.SetStatus (eReturnStatusSuccessFinishResult); 613 } 614 else 615 { 616 result.AppendErrorWithFormat("Invalid breakpoint ID: %u.\n", cur_bp_id.GetBreakpointID()); 617 result.SetStatus (eReturnStatusFailed); 618 } 619 620 } 621 } 622 } 623 624 return result.Succeeded(); 625 } 626 627 //------------------------------------------------------------------------- 628 // CommandObjectBreakpointCommand 629 //------------------------------------------------------------------------- 630 631 CommandObjectBreakpointCommand::CommandObjectBreakpointCommand (CommandInterpreter &interpreter) : 632 CommandObjectMultiword ("command", 633 "A set of commands for adding, removing and examining bits of code to be executed when the breakpoint is hit (breakpoint 'commmands').", 634 "command <sub-command> [<sub-command-options>] <breakpoint-id>") 635 { 636 bool status; 637 CommandObjectSP add_command_object (new CommandObjectBreakpointCommandAdd ()); 638 CommandObjectSP remove_command_object (new CommandObjectBreakpointCommandRemove ()); 639 CommandObjectSP list_command_object (new CommandObjectBreakpointCommandList ()); 640 641 add_command_object->SetCommandName ("breakpoint command add"); 642 remove_command_object->SetCommandName ("breakpoint command remove"); 643 list_command_object->SetCommandName ("breakpoint command list"); 644 645 status = LoadSubCommand (interpreter, "add", add_command_object); 646 status = LoadSubCommand (interpreter, "remove", remove_command_object); 647 status = LoadSubCommand (interpreter, "list", list_command_object); 648 } 649 650 651 CommandObjectBreakpointCommand::~CommandObjectBreakpointCommand () 652 { 653 } 654 655 bool 656 CommandObjectBreakpointCommand::BreakpointOptionsCallbackFunction 657 ( 658 void *baton, 659 StoppointCallbackContext *context, 660 lldb::user_id_t break_id, 661 lldb::user_id_t break_loc_id 662 ) 663 { 664 bool ret_value = true; 665 if (baton == NULL) 666 return true; 667 668 669 BreakpointOptions::CommandData *data = (BreakpointOptions::CommandData *) baton; 670 StringList &commands = data->user_source; 671 672 if (commands.GetSize() > 0) 673 { 674 uint32_t num_commands = commands.GetSize(); 675 CommandReturnObject result; 676 if (context->exe_ctx.target) 677 { 678 679 Debugger &debugger = context->exe_ctx.target->GetDebugger(); 680 CommandInterpreter &interpreter = debugger.GetCommandInterpreter(); 681 682 FILE *out_fh = debugger.GetOutputFileHandle(); 683 FILE *err_fh = debugger.GetErrorFileHandle(); 684 685 uint32_t i; 686 for (i = 0; i < num_commands; ++i) 687 { 688 689 // First time through we use the context from the stoppoint, after that we use whatever 690 // has been set by the previous command. 691 692 if (!interpreter.HandleCommand (commands.GetStringAtIndex(i), false, result, &context->exe_ctx)) 693 break; 694 695 // FIXME: This isn't really the right way to do this. We should be able to peek at the public 696 // to see if there is any new events, but that is racey, since the internal process thread has to run and 697 // deliver the event to the public queue before a run will show up. So for now we check 698 // the internal thread state. 699 700 lldb::StateType internal_state = context->exe_ctx.process->GetPrivateState(); 701 if (internal_state != eStateStopped) 702 { 703 if (i < num_commands - 1) 704 { 705 if (out_fh) 706 ::fprintf (out_fh, "Short-circuiting command execution because target state changed to %s." 707 " last command: \"%s\"\n", StateAsCString(internal_state), 708 commands.GetStringAtIndex(i)); 709 } 710 break; 711 } 712 713 if (out_fh) 714 ::fprintf (out_fh, "%s", result.GetErrorStream().GetData()); 715 if (err_fh) 716 ::fprintf (err_fh, "%s", result.GetOutputStream().GetData()); 717 result.Clear(); 718 result.SetStatus (eReturnStatusSuccessFinishNoResult); 719 } 720 721 if (err_fh && !result.Succeeded() && i < num_commands) 722 ::fprintf (err_fh, "Attempt to execute '%s' failed.\n", commands.GetStringAtIndex(i)); 723 724 if (out_fh) 725 ::fprintf (out_fh, "%s", result.GetErrorStream().GetData()); 726 727 if (err_fh) 728 ::fprintf (err_fh, "%s", result.GetOutputStream().GetData()); 729 } 730 } 731 return ret_value; 732 } 733 734