1 //===-- Debugger.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 "lldb/Core/Debugger.h" 11 12 #include <map> 13 14 #include "clang/AST/DeclCXX.h" 15 #include "clang/AST/Type.h" 16 17 #include "lldb/lldb-private.h" 18 #include "lldb/Core/ConnectionFileDescriptor.h" 19 #include "lldb/Core/DataVisualization.h" 20 #include "lldb/Core/FormatManager.h" 21 #include "lldb/Core/InputReader.h" 22 #include "lldb/Core/RegisterValue.h" 23 #include "lldb/Core/State.h" 24 #include "lldb/Core/StreamAsynchronousIO.h" 25 #include "lldb/Core/StreamCallback.h" 26 #include "lldb/Core/StreamString.h" 27 #include "lldb/Core/Timer.h" 28 #include "lldb/Core/ValueObject.h" 29 #include "lldb/Core/ValueObjectVariable.h" 30 #include "lldb/Host/Terminal.h" 31 #include "lldb/Interpreter/CommandInterpreter.h" 32 #include "lldb/Symbol/VariableList.h" 33 #include "lldb/Target/TargetList.h" 34 #include "lldb/Target/Process.h" 35 #include "lldb/Target/RegisterContext.h" 36 #include "lldb/Target/StopInfo.h" 37 #include "lldb/Target/Thread.h" 38 #include "lldb/Utility/AnsiTerminal.h" 39 40 using namespace lldb; 41 using namespace lldb_private; 42 43 44 static uint32_t g_shared_debugger_refcount = 0; 45 static lldb::user_id_t g_unique_id = 1; 46 47 #pragma mark Static Functions 48 49 static Mutex & 50 GetDebuggerListMutex () 51 { 52 static Mutex g_mutex(Mutex::eMutexTypeRecursive); 53 return g_mutex; 54 } 55 56 typedef std::vector<DebuggerSP> DebuggerList; 57 58 static DebuggerList & 59 GetDebuggerList() 60 { 61 // hide the static debugger list inside a singleton accessor to avoid 62 // global init contructors 63 static DebuggerList g_list; 64 return g_list; 65 } 66 67 68 static const ConstString & 69 PromptVarName () 70 { 71 static ConstString g_const_string ("prompt"); 72 return g_const_string; 73 } 74 75 static const ConstString & 76 GetFrameFormatName () 77 { 78 static ConstString g_const_string ("frame-format"); 79 return g_const_string; 80 } 81 82 static const ConstString & 83 GetThreadFormatName () 84 { 85 static ConstString g_const_string ("thread-format"); 86 return g_const_string; 87 } 88 89 static const ConstString & 90 ScriptLangVarName () 91 { 92 static ConstString g_const_string ("script-lang"); 93 return g_const_string; 94 } 95 96 static const ConstString & 97 TermWidthVarName () 98 { 99 static ConstString g_const_string ("term-width"); 100 return g_const_string; 101 } 102 103 static const ConstString & 104 UseExternalEditorVarName () 105 { 106 static ConstString g_const_string ("use-external-editor"); 107 return g_const_string; 108 } 109 110 static const ConstString & 111 AutoConfirmName () 112 { 113 static ConstString g_const_string ("auto-confirm"); 114 return g_const_string; 115 } 116 117 static const ConstString & 118 StopSourceContextBeforeName () 119 { 120 static ConstString g_const_string ("stop-line-count-before"); 121 return g_const_string; 122 } 123 124 static const ConstString & 125 StopSourceContextAfterName () 126 { 127 static ConstString g_const_string ("stop-line-count-after"); 128 return g_const_string; 129 } 130 131 static const ConstString & 132 StopDisassemblyCountName () 133 { 134 static ConstString g_const_string ("stop-disassembly-count"); 135 return g_const_string; 136 } 137 138 static const ConstString & 139 StopDisassemblyDisplayName () 140 { 141 static ConstString g_const_string ("stop-disassembly-display"); 142 return g_const_string; 143 } 144 145 OptionEnumValueElement 146 DebuggerInstanceSettings::g_show_disassembly_enum_values[] = 147 { 148 { eStopDisassemblyTypeNever, "never", "Never show disassembly when displaying a stop context."}, 149 { eStopDisassemblyTypeNoSource, "no-source", "Show disassembly when there is no source information, or the source file is missing when displaying a stop context."}, 150 { eStopDisassemblyTypeAlways, "always", "Always show disassembly when displaying a stop context."}, 151 { 0, NULL, NULL } 152 }; 153 154 155 156 #pragma mark Debugger 157 158 UserSettingsControllerSP & 159 Debugger::GetSettingsController () 160 { 161 static UserSettingsControllerSP g_settings_controller_sp; 162 if (!g_settings_controller_sp) 163 { 164 g_settings_controller_sp.reset (new Debugger::SettingsController); 165 166 // The first shared pointer to Debugger::SettingsController in 167 // g_settings_controller_sp must be fully created above so that 168 // the DebuggerInstanceSettings can use a weak_ptr to refer back 169 // to the master setttings controller 170 InstanceSettingsSP default_instance_settings_sp (new DebuggerInstanceSettings (g_settings_controller_sp, 171 false, 172 InstanceSettings::GetDefaultName().AsCString())); 173 g_settings_controller_sp->SetDefaultInstanceSettings (default_instance_settings_sp); 174 } 175 return g_settings_controller_sp; 176 } 177 178 int 179 Debugger::TestDebuggerRefCount () 180 { 181 return g_shared_debugger_refcount; 182 } 183 184 void 185 Debugger::Initialize () 186 { 187 if (g_shared_debugger_refcount++ == 0) 188 lldb_private::Initialize(); 189 } 190 191 void 192 Debugger::Terminate () 193 { 194 if (g_shared_debugger_refcount > 0) 195 { 196 g_shared_debugger_refcount--; 197 if (g_shared_debugger_refcount == 0) 198 { 199 lldb_private::WillTerminate(); 200 lldb_private::Terminate(); 201 202 // Clear our master list of debugger objects 203 Mutex::Locker locker (GetDebuggerListMutex ()); 204 GetDebuggerList().clear(); 205 } 206 } 207 } 208 209 void 210 Debugger::SettingsInitialize () 211 { 212 static bool g_initialized = false; 213 214 if (!g_initialized) 215 { 216 g_initialized = true; 217 UserSettingsController::InitializeSettingsController (GetSettingsController(), 218 SettingsController::global_settings_table, 219 SettingsController::instance_settings_table); 220 // Now call SettingsInitialize for each settings 'child' of Debugger 221 Target::SettingsInitialize (); 222 } 223 } 224 225 void 226 Debugger::SettingsTerminate () 227 { 228 229 // Must call SettingsTerminate() for each settings 'child' of Debugger, before terminating the Debugger's 230 // Settings. 231 232 Target::SettingsTerminate (); 233 234 // Now terminate the Debugger Settings. 235 236 UserSettingsControllerSP &usc = GetSettingsController(); 237 UserSettingsController::FinalizeSettingsController (usc); 238 usc.reset(); 239 } 240 241 DebuggerSP 242 Debugger::CreateInstance (lldb::LogOutputCallback log_callback, void *baton) 243 { 244 DebuggerSP debugger_sp (new Debugger(log_callback, baton)); 245 if (g_shared_debugger_refcount > 0) 246 { 247 Mutex::Locker locker (GetDebuggerListMutex ()); 248 GetDebuggerList().push_back(debugger_sp); 249 } 250 return debugger_sp; 251 } 252 253 void 254 Debugger::Destroy (DebuggerSP &debugger_sp) 255 { 256 if (debugger_sp.get() == NULL) 257 return; 258 259 debugger_sp->Clear(); 260 261 if (g_shared_debugger_refcount > 0) 262 { 263 Mutex::Locker locker (GetDebuggerListMutex ()); 264 DebuggerList &debugger_list = GetDebuggerList (); 265 DebuggerList::iterator pos, end = debugger_list.end(); 266 for (pos = debugger_list.begin (); pos != end; ++pos) 267 { 268 if ((*pos).get() == debugger_sp.get()) 269 { 270 debugger_list.erase (pos); 271 return; 272 } 273 } 274 } 275 } 276 277 DebuggerSP 278 Debugger::FindDebuggerWithInstanceName (const ConstString &instance_name) 279 { 280 DebuggerSP debugger_sp; 281 282 if (g_shared_debugger_refcount > 0) 283 { 284 Mutex::Locker locker (GetDebuggerListMutex ()); 285 DebuggerList &debugger_list = GetDebuggerList(); 286 DebuggerList::iterator pos, end = debugger_list.end(); 287 288 for (pos = debugger_list.begin(); pos != end; ++pos) 289 { 290 if ((*pos).get()->m_instance_name == instance_name) 291 { 292 debugger_sp = *pos; 293 break; 294 } 295 } 296 } 297 return debugger_sp; 298 } 299 300 TargetSP 301 Debugger::FindTargetWithProcessID (lldb::pid_t pid) 302 { 303 TargetSP target_sp; 304 if (g_shared_debugger_refcount > 0) 305 { 306 Mutex::Locker locker (GetDebuggerListMutex ()); 307 DebuggerList &debugger_list = GetDebuggerList(); 308 DebuggerList::iterator pos, end = debugger_list.end(); 309 for (pos = debugger_list.begin(); pos != end; ++pos) 310 { 311 target_sp = (*pos)->GetTargetList().FindTargetWithProcessID (pid); 312 if (target_sp) 313 break; 314 } 315 } 316 return target_sp; 317 } 318 319 TargetSP 320 Debugger::FindTargetWithProcess (Process *process) 321 { 322 TargetSP target_sp; 323 if (g_shared_debugger_refcount > 0) 324 { 325 Mutex::Locker locker (GetDebuggerListMutex ()); 326 DebuggerList &debugger_list = GetDebuggerList(); 327 DebuggerList::iterator pos, end = debugger_list.end(); 328 for (pos = debugger_list.begin(); pos != end; ++pos) 329 { 330 target_sp = (*pos)->GetTargetList().FindTargetWithProcess (process); 331 if (target_sp) 332 break; 333 } 334 } 335 return target_sp; 336 } 337 338 339 Debugger::Debugger (lldb::LogOutputCallback log_callback, void *baton) : 340 UserID (g_unique_id++), 341 DebuggerInstanceSettings (GetSettingsController()), 342 m_input_comm("debugger.input"), 343 m_input_file (), 344 m_output_file (), 345 m_error_file (), 346 m_target_list (*this), 347 m_platform_list (), 348 m_listener ("lldb.Debugger"), 349 m_source_manager(*this), 350 m_source_file_cache(), 351 m_command_interpreter_ap (new CommandInterpreter (*this, eScriptLanguageDefault, false)), 352 m_input_reader_stack (), 353 m_input_reader_data () 354 { 355 if (log_callback) 356 m_log_callback_stream_sp.reset (new StreamCallback (log_callback, baton)); 357 m_command_interpreter_ap->Initialize (); 358 // Always add our default platform to the platform list 359 PlatformSP default_platform_sp (Platform::GetDefaultPlatform()); 360 assert (default_platform_sp.get()); 361 m_platform_list.Append (default_platform_sp, true); 362 } 363 364 Debugger::~Debugger () 365 { 366 Clear(); 367 } 368 369 void 370 Debugger::Clear() 371 { 372 CleanUpInputReaders(); 373 m_listener.Clear(); 374 int num_targets = m_target_list.GetNumTargets(); 375 for (int i = 0; i < num_targets; i++) 376 { 377 TargetSP target_sp (m_target_list.GetTargetAtIndex (i)); 378 if (target_sp) 379 { 380 ProcessSP process_sp (target_sp->GetProcessSP()); 381 if (process_sp) 382 { 383 if (process_sp->GetShouldDetach()) 384 process_sp->Detach(); 385 } 386 target_sp->Destroy(); 387 } 388 } 389 BroadcasterManager::Clear (); 390 391 // Close the input file _before_ we close the input read communications class 392 // as it does NOT own the input file, our m_input_file does. 393 GetInputFile().Close (); 394 // Now that we have closed m_input_file, we can now tell our input communication 395 // class to close down. Its read thread should quickly exit after we close 396 // the input file handle above. 397 m_input_comm.Clear (); 398 } 399 400 bool 401 Debugger::GetCloseInputOnEOF () const 402 { 403 return m_input_comm.GetCloseOnEOF(); 404 } 405 406 void 407 Debugger::SetCloseInputOnEOF (bool b) 408 { 409 m_input_comm.SetCloseOnEOF(b); 410 } 411 412 bool 413 Debugger::GetAsyncExecution () 414 { 415 return !m_command_interpreter_ap->GetSynchronous(); 416 } 417 418 void 419 Debugger::SetAsyncExecution (bool async_execution) 420 { 421 m_command_interpreter_ap->SetSynchronous (!async_execution); 422 } 423 424 425 void 426 Debugger::SetInputFileHandle (FILE *fh, bool tranfer_ownership) 427 { 428 File &in_file = GetInputFile(); 429 in_file.SetStream (fh, tranfer_ownership); 430 if (in_file.IsValid() == false) 431 in_file.SetStream (stdin, true); 432 433 // Disconnect from any old connection if we had one 434 m_input_comm.Disconnect (); 435 // Pass false as the second argument to ConnectionFileDescriptor below because 436 // our "in_file" above will already take ownership if requested and we don't 437 // want to objects trying to own and close a file descriptor. 438 m_input_comm.SetConnection (new ConnectionFileDescriptor (in_file.GetDescriptor(), false)); 439 m_input_comm.SetReadThreadBytesReceivedCallback (Debugger::DispatchInputCallback, this); 440 441 Error error; 442 if (m_input_comm.StartReadThread (&error) == false) 443 { 444 File &err_file = GetErrorFile(); 445 446 err_file.Printf ("error: failed to main input read thread: %s", error.AsCString() ? error.AsCString() : "unkown error"); 447 exit(1); 448 } 449 } 450 451 void 452 Debugger::SetOutputFileHandle (FILE *fh, bool tranfer_ownership) 453 { 454 File &out_file = GetOutputFile(); 455 out_file.SetStream (fh, tranfer_ownership); 456 if (out_file.IsValid() == false) 457 out_file.SetStream (stdout, false); 458 459 GetCommandInterpreter().GetScriptInterpreter()->ResetOutputFileHandle (fh); 460 } 461 462 void 463 Debugger::SetErrorFileHandle (FILE *fh, bool tranfer_ownership) 464 { 465 File &err_file = GetErrorFile(); 466 err_file.SetStream (fh, tranfer_ownership); 467 if (err_file.IsValid() == false) 468 err_file.SetStream (stderr, false); 469 } 470 471 ExecutionContext 472 Debugger::GetSelectedExecutionContext () 473 { 474 ExecutionContext exe_ctx; 475 TargetSP target_sp(GetSelectedTarget()); 476 exe_ctx.SetTargetSP (target_sp); 477 478 if (target_sp) 479 { 480 ProcessSP process_sp (target_sp->GetProcessSP()); 481 exe_ctx.SetProcessSP (process_sp); 482 if (process_sp && process_sp->IsRunning() == false) 483 { 484 ThreadSP thread_sp (process_sp->GetThreadList().GetSelectedThread()); 485 if (thread_sp) 486 { 487 exe_ctx.SetThreadSP (thread_sp); 488 exe_ctx.SetFrameSP (thread_sp->GetSelectedFrame()); 489 if (exe_ctx.GetFramePtr() == NULL) 490 exe_ctx.SetFrameSP (thread_sp->GetStackFrameAtIndex (0)); 491 } 492 } 493 } 494 return exe_ctx; 495 496 } 497 498 InputReaderSP 499 Debugger::GetCurrentInputReader () 500 { 501 InputReaderSP reader_sp; 502 503 if (!m_input_reader_stack.IsEmpty()) 504 { 505 // Clear any finished readers from the stack 506 while (CheckIfTopInputReaderIsDone()) ; 507 508 if (!m_input_reader_stack.IsEmpty()) 509 reader_sp = m_input_reader_stack.Top(); 510 } 511 512 return reader_sp; 513 } 514 515 void 516 Debugger::DispatchInputCallback (void *baton, const void *bytes, size_t bytes_len) 517 { 518 if (bytes_len > 0) 519 ((Debugger *)baton)->DispatchInput ((char *)bytes, bytes_len); 520 else 521 ((Debugger *)baton)->DispatchInputEndOfFile (); 522 } 523 524 525 void 526 Debugger::DispatchInput (const char *bytes, size_t bytes_len) 527 { 528 if (bytes == NULL || bytes_len == 0) 529 return; 530 531 WriteToDefaultReader (bytes, bytes_len); 532 } 533 534 void 535 Debugger::DispatchInputInterrupt () 536 { 537 m_input_reader_data.clear(); 538 539 InputReaderSP reader_sp (GetCurrentInputReader ()); 540 if (reader_sp) 541 { 542 reader_sp->Notify (eInputReaderInterrupt); 543 544 // If notifying the reader of the interrupt finished the reader, we should pop it off the stack. 545 while (CheckIfTopInputReaderIsDone ()) ; 546 } 547 } 548 549 void 550 Debugger::DispatchInputEndOfFile () 551 { 552 m_input_reader_data.clear(); 553 554 InputReaderSP reader_sp (GetCurrentInputReader ()); 555 if (reader_sp) 556 { 557 reader_sp->Notify (eInputReaderEndOfFile); 558 559 // If notifying the reader of the end-of-file finished the reader, we should pop it off the stack. 560 while (CheckIfTopInputReaderIsDone ()) ; 561 } 562 } 563 564 void 565 Debugger::CleanUpInputReaders () 566 { 567 m_input_reader_data.clear(); 568 569 // The bottom input reader should be the main debugger input reader. We do not want to close that one here. 570 while (m_input_reader_stack.GetSize() > 1) 571 { 572 InputReaderSP reader_sp (GetCurrentInputReader ()); 573 if (reader_sp) 574 { 575 reader_sp->Notify (eInputReaderEndOfFile); 576 reader_sp->SetIsDone (true); 577 } 578 } 579 } 580 581 void 582 Debugger::NotifyTopInputReader (InputReaderAction notification) 583 { 584 InputReaderSP reader_sp (GetCurrentInputReader()); 585 if (reader_sp) 586 { 587 reader_sp->Notify (notification); 588 589 // Flush out any input readers that are done. 590 while (CheckIfTopInputReaderIsDone ()) 591 /* Do nothing. */; 592 } 593 } 594 595 bool 596 Debugger::InputReaderIsTopReader (const InputReaderSP& reader_sp) 597 { 598 InputReaderSP top_reader_sp (GetCurrentInputReader()); 599 600 return (reader_sp.get() == top_reader_sp.get()); 601 } 602 603 604 void 605 Debugger::WriteToDefaultReader (const char *bytes, size_t bytes_len) 606 { 607 if (bytes && bytes_len) 608 m_input_reader_data.append (bytes, bytes_len); 609 610 if (m_input_reader_data.empty()) 611 return; 612 613 while (!m_input_reader_stack.IsEmpty() && !m_input_reader_data.empty()) 614 { 615 // Get the input reader from the top of the stack 616 InputReaderSP reader_sp (GetCurrentInputReader ()); 617 if (!reader_sp) 618 break; 619 620 size_t bytes_handled = reader_sp->HandleRawBytes (m_input_reader_data.c_str(), 621 m_input_reader_data.size()); 622 if (bytes_handled) 623 { 624 m_input_reader_data.erase (0, bytes_handled); 625 } 626 else 627 { 628 // No bytes were handled, we might not have reached our 629 // granularity, just return and wait for more data 630 break; 631 } 632 } 633 634 // Flush out any input readers that are done. 635 while (CheckIfTopInputReaderIsDone ()) 636 /* Do nothing. */; 637 638 } 639 640 void 641 Debugger::PushInputReader (const InputReaderSP& reader_sp) 642 { 643 if (!reader_sp) 644 return; 645 646 // Deactivate the old top reader 647 InputReaderSP top_reader_sp (GetCurrentInputReader ()); 648 649 if (top_reader_sp) 650 top_reader_sp->Notify (eInputReaderDeactivate); 651 652 m_input_reader_stack.Push (reader_sp); 653 reader_sp->Notify (eInputReaderActivate); 654 ActivateInputReader (reader_sp); 655 } 656 657 bool 658 Debugger::PopInputReader (const InputReaderSP& pop_reader_sp) 659 { 660 bool result = false; 661 662 // The reader on the stop of the stack is done, so let the next 663 // read on the stack referesh its prompt and if there is one... 664 if (!m_input_reader_stack.IsEmpty()) 665 { 666 // Cannot call GetCurrentInputReader here, as that would cause an infinite loop. 667 InputReaderSP reader_sp(m_input_reader_stack.Top()); 668 669 if (!pop_reader_sp || pop_reader_sp.get() == reader_sp.get()) 670 { 671 m_input_reader_stack.Pop (); 672 reader_sp->Notify (eInputReaderDeactivate); 673 reader_sp->Notify (eInputReaderDone); 674 result = true; 675 676 if (!m_input_reader_stack.IsEmpty()) 677 { 678 reader_sp = m_input_reader_stack.Top(); 679 if (reader_sp) 680 { 681 ActivateInputReader (reader_sp); 682 reader_sp->Notify (eInputReaderReactivate); 683 } 684 } 685 } 686 } 687 return result; 688 } 689 690 bool 691 Debugger::CheckIfTopInputReaderIsDone () 692 { 693 bool result = false; 694 if (!m_input_reader_stack.IsEmpty()) 695 { 696 // Cannot call GetCurrentInputReader here, as that would cause an infinite loop. 697 InputReaderSP reader_sp(m_input_reader_stack.Top()); 698 699 if (reader_sp && reader_sp->IsDone()) 700 { 701 result = true; 702 PopInputReader (reader_sp); 703 } 704 } 705 return result; 706 } 707 708 void 709 Debugger::ActivateInputReader (const InputReaderSP &reader_sp) 710 { 711 int input_fd = m_input_file.GetFile().GetDescriptor(); 712 713 if (input_fd >= 0) 714 { 715 Terminal tty(input_fd); 716 717 tty.SetEcho(reader_sp->GetEcho()); 718 719 switch (reader_sp->GetGranularity()) 720 { 721 case eInputReaderGranularityByte: 722 case eInputReaderGranularityWord: 723 tty.SetCanonical (false); 724 break; 725 726 case eInputReaderGranularityLine: 727 case eInputReaderGranularityAll: 728 tty.SetCanonical (true); 729 break; 730 731 default: 732 break; 733 } 734 } 735 } 736 737 StreamSP 738 Debugger::GetAsyncOutputStream () 739 { 740 return StreamSP (new StreamAsynchronousIO (GetCommandInterpreter(), 741 CommandInterpreter::eBroadcastBitAsynchronousOutputData)); 742 } 743 744 StreamSP 745 Debugger::GetAsyncErrorStream () 746 { 747 return StreamSP (new StreamAsynchronousIO (GetCommandInterpreter(), 748 CommandInterpreter::eBroadcastBitAsynchronousErrorData)); 749 } 750 751 uint32_t 752 Debugger::GetNumDebuggers() 753 { 754 if (g_shared_debugger_refcount > 0) 755 { 756 Mutex::Locker locker (GetDebuggerListMutex ()); 757 return GetDebuggerList().size(); 758 } 759 return 0; 760 } 761 762 lldb::DebuggerSP 763 Debugger::GetDebuggerAtIndex (uint32_t index) 764 { 765 DebuggerSP debugger_sp; 766 767 if (g_shared_debugger_refcount > 0) 768 { 769 Mutex::Locker locker (GetDebuggerListMutex ()); 770 DebuggerList &debugger_list = GetDebuggerList(); 771 772 if (index < debugger_list.size()) 773 debugger_sp = debugger_list[index]; 774 } 775 776 return debugger_sp; 777 } 778 779 DebuggerSP 780 Debugger::FindDebuggerWithID (lldb::user_id_t id) 781 { 782 DebuggerSP debugger_sp; 783 784 if (g_shared_debugger_refcount > 0) 785 { 786 Mutex::Locker locker (GetDebuggerListMutex ()); 787 DebuggerList &debugger_list = GetDebuggerList(); 788 DebuggerList::iterator pos, end = debugger_list.end(); 789 for (pos = debugger_list.begin(); pos != end; ++pos) 790 { 791 if ((*pos).get()->GetID() == id) 792 { 793 debugger_sp = *pos; 794 break; 795 } 796 } 797 } 798 return debugger_sp; 799 } 800 801 static void 802 TestPromptFormats (StackFrame *frame) 803 { 804 if (frame == NULL) 805 return; 806 807 StreamString s; 808 const char *prompt_format = 809 "{addr = '${addr}'\n}" 810 "{process.id = '${process.id}'\n}" 811 "{process.name = '${process.name}'\n}" 812 "{process.file.basename = '${process.file.basename}'\n}" 813 "{process.file.fullpath = '${process.file.fullpath}'\n}" 814 "{thread.id = '${thread.id}'\n}" 815 "{thread.index = '${thread.index}'\n}" 816 "{thread.name = '${thread.name}'\n}" 817 "{thread.queue = '${thread.queue}'\n}" 818 "{thread.stop-reason = '${thread.stop-reason}'\n}" 819 "{target.arch = '${target.arch}'\n}" 820 "{module.file.basename = '${module.file.basename}'\n}" 821 "{module.file.fullpath = '${module.file.fullpath}'\n}" 822 "{file.basename = '${file.basename}'\n}" 823 "{file.fullpath = '${file.fullpath}'\n}" 824 "{frame.index = '${frame.index}'\n}" 825 "{frame.pc = '${frame.pc}'\n}" 826 "{frame.sp = '${frame.sp}'\n}" 827 "{frame.fp = '${frame.fp}'\n}" 828 "{frame.flags = '${frame.flags}'\n}" 829 "{frame.reg.rdi = '${frame.reg.rdi}'\n}" 830 "{frame.reg.rip = '${frame.reg.rip}'\n}" 831 "{frame.reg.rsp = '${frame.reg.rsp}'\n}" 832 "{frame.reg.rbp = '${frame.reg.rbp}'\n}" 833 "{frame.reg.rflags = '${frame.reg.rflags}'\n}" 834 "{frame.reg.xmm0 = '${frame.reg.xmm0}'\n}" 835 "{frame.reg.carp = '${frame.reg.carp}'\n}" 836 "{function.id = '${function.id}'\n}" 837 "{function.name = '${function.name}'\n}" 838 "{function.name-with-args = '${function.name-with-args}'\n}" 839 "{function.addr-offset = '${function.addr-offset}'\n}" 840 "{function.line-offset = '${function.line-offset}'\n}" 841 "{function.pc-offset = '${function.pc-offset}'\n}" 842 "{line.file.basename = '${line.file.basename}'\n}" 843 "{line.file.fullpath = '${line.file.fullpath}'\n}" 844 "{line.number = '${line.number}'\n}" 845 "{line.start-addr = '${line.start-addr}'\n}" 846 "{line.end-addr = '${line.end-addr}'\n}" 847 ; 848 849 SymbolContext sc (frame->GetSymbolContext(eSymbolContextEverything)); 850 ExecutionContext exe_ctx; 851 frame->CalculateExecutionContext(exe_ctx); 852 const char *end = NULL; 853 if (Debugger::FormatPrompt (prompt_format, &sc, &exe_ctx, &sc.line_entry.range.GetBaseAddress(), s, &end)) 854 { 855 printf("%s\n", s.GetData()); 856 } 857 else 858 { 859 printf ("error: at '%s'\n", end); 860 printf ("what we got: %s\n", s.GetData()); 861 } 862 } 863 864 static bool 865 ScanFormatDescriptor (const char* var_name_begin, 866 const char* var_name_end, 867 const char** var_name_final, 868 const char** percent_position, 869 Format* custom_format, 870 ValueObject::ValueObjectRepresentationStyle* val_obj_display) 871 { 872 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES)); 873 *percent_position = ::strchr(var_name_begin,'%'); 874 if (!*percent_position || *percent_position > var_name_end) 875 { 876 if (log) 877 log->Printf("no format descriptor in string, skipping"); 878 *var_name_final = var_name_end; 879 } 880 else 881 { 882 *var_name_final = *percent_position; 883 char* format_name = new char[var_name_end-*var_name_final]; format_name[var_name_end-*var_name_final-1] = '\0'; 884 memcpy(format_name, *var_name_final+1, var_name_end-*var_name_final-1); 885 if (log) 886 log->Printf("parsing %s as a format descriptor", format_name); 887 if ( !FormatManager::GetFormatFromCString(format_name, 888 true, 889 *custom_format) ) 890 { 891 if (log) 892 log->Printf("%s is an unknown format", format_name); 893 // if this is an @ sign, print ObjC description 894 if (*format_name == '@') 895 *val_obj_display = ValueObject::eValueObjectRepresentationStyleLanguageSpecific; 896 // if this is a V, print the value using the default format 897 else if (*format_name == 'V') 898 *val_obj_display = ValueObject::eValueObjectRepresentationStyleValue; 899 // if this is an L, print the location of the value 900 else if (*format_name == 'L') 901 *val_obj_display = ValueObject::eValueObjectRepresentationStyleLocation; 902 // if this is an S, print the summary after all 903 else if (*format_name == 'S') 904 *val_obj_display = ValueObject::eValueObjectRepresentationStyleSummary; 905 else if (*format_name == '#') 906 *val_obj_display = ValueObject::eValueObjectRepresentationStyleChildrenCount; 907 else if (*format_name == 'T') 908 *val_obj_display = ValueObject::eValueObjectRepresentationStyleType; 909 else if (log) 910 log->Printf("%s is an error, leaving the previous value alone", format_name); 911 } 912 // a good custom format tells us to print the value using it 913 else 914 { 915 if (log) 916 log->Printf("will display value for this VO"); 917 *val_obj_display = ValueObject::eValueObjectRepresentationStyleValue; 918 } 919 delete format_name; 920 } 921 if (log) 922 log->Printf("final format description outcome: custom_format = %d, val_obj_display = %d", 923 *custom_format, 924 *val_obj_display); 925 return true; 926 } 927 928 static bool 929 ScanBracketedRange (const char* var_name_begin, 930 const char* var_name_end, 931 const char* var_name_final, 932 const char** open_bracket_position, 933 const char** separator_position, 934 const char** close_bracket_position, 935 const char** var_name_final_if_array_range, 936 int64_t* index_lower, 937 int64_t* index_higher) 938 { 939 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES)); 940 *open_bracket_position = ::strchr(var_name_begin,'['); 941 if (*open_bracket_position && *open_bracket_position < var_name_final) 942 { 943 *separator_position = ::strchr(*open_bracket_position,'-'); // might be NULL if this is a simple var[N] bitfield 944 *close_bracket_position = ::strchr(*open_bracket_position,']'); 945 // as usual, we assume that [] will come before % 946 //printf("trying to expand a []\n"); 947 *var_name_final_if_array_range = *open_bracket_position; 948 if (*close_bracket_position - *open_bracket_position == 1) 949 { 950 if (log) 951 log->Printf("[] detected.. going from 0 to end of data"); 952 *index_lower = 0; 953 } 954 else if (*separator_position == NULL || *separator_position > var_name_end) 955 { 956 char *end = NULL; 957 *index_lower = ::strtoul (*open_bracket_position+1, &end, 0); 958 *index_higher = *index_lower; 959 if (log) 960 log->Printf("[%lld] detected, high index is same", *index_lower); 961 } 962 else if (*close_bracket_position && *close_bracket_position < var_name_end) 963 { 964 char *end = NULL; 965 *index_lower = ::strtoul (*open_bracket_position+1, &end, 0); 966 *index_higher = ::strtoul (*separator_position+1, &end, 0); 967 if (log) 968 log->Printf("[%lld-%lld] detected", *index_lower, *index_higher); 969 } 970 else 971 { 972 if (log) 973 log->Printf("expression is erroneous, cannot extract indices out of it"); 974 return false; 975 } 976 if (*index_lower > *index_higher && *index_higher > 0) 977 { 978 if (log) 979 log->Printf("swapping indices"); 980 int temp = *index_lower; 981 *index_lower = *index_higher; 982 *index_higher = temp; 983 } 984 } 985 else if (log) 986 log->Printf("no bracketed range, skipping entirely"); 987 return true; 988 } 989 990 991 static ValueObjectSP 992 ExpandExpressionPath (ValueObject* valobj, 993 StackFrame* frame, 994 bool* do_deref_pointer, 995 const char* var_name_begin, 996 const char* var_name_final, 997 Error& error) 998 { 999 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES)); 1000 StreamString sstring; 1001 VariableSP var_sp; 1002 1003 if (*do_deref_pointer) 1004 { 1005 if (log) 1006 log->Printf("been told to deref_pointer by caller"); 1007 sstring.PutChar('*'); 1008 } 1009 else if (valobj->IsDereferenceOfParent() && ClangASTContext::IsPointerType(valobj->GetParent()->GetClangType()) && !valobj->IsArrayItemForPointer()) 1010 { 1011 if (log) 1012 log->Printf("decided to deref_pointer myself"); 1013 sstring.PutChar('*'); 1014 *do_deref_pointer = true; 1015 } 1016 1017 valobj->GetExpressionPath(sstring, true, ValueObject::eGetExpressionPathFormatHonorPointers); 1018 if (log) 1019 log->Printf("expression path to expand in phase 0: %s",sstring.GetData()); 1020 sstring.PutRawBytes(var_name_begin+3, var_name_final-var_name_begin-3); 1021 if (log) 1022 log->Printf("expression path to expand in phase 1: %s",sstring.GetData()); 1023 std::string name = std::string(sstring.GetData()); 1024 ValueObjectSP target = frame->GetValueForVariableExpressionPath (name.c_str(), 1025 eNoDynamicValues, 1026 0, 1027 var_sp, 1028 error); 1029 return target; 1030 } 1031 1032 static ValueObjectSP 1033 ExpandIndexedExpression (ValueObject* valobj, 1034 uint32_t index, 1035 StackFrame* frame, 1036 bool deref_pointer) 1037 { 1038 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES)); 1039 const char* ptr_deref_format = "[%d]"; 1040 std::auto_ptr<char> ptr_deref_buffer(new char[10]); 1041 ::sprintf(ptr_deref_buffer.get(), ptr_deref_format, index); 1042 if (log) 1043 log->Printf("name to deref: %s",ptr_deref_buffer.get()); 1044 const char* first_unparsed; 1045 ValueObject::GetValueForExpressionPathOptions options; 1046 ValueObject::ExpressionPathEndResultType final_value_type; 1047 ValueObject::ExpressionPathScanEndReason reason_to_stop; 1048 ValueObject::ExpressionPathAftermath what_next = (deref_pointer ? ValueObject::eExpressionPathAftermathDereference : ValueObject::eExpressionPathAftermathNothing); 1049 ValueObjectSP item = valobj->GetValueForExpressionPath (ptr_deref_buffer.get(), 1050 &first_unparsed, 1051 &reason_to_stop, 1052 &final_value_type, 1053 options, 1054 &what_next); 1055 if (!item) 1056 { 1057 if (log) 1058 log->Printf("ERROR: unparsed portion = %s, why stopping = %d," 1059 " final_value_type %d", 1060 first_unparsed, reason_to_stop, final_value_type); 1061 } 1062 else 1063 { 1064 if (log) 1065 log->Printf("ALL RIGHT: unparsed portion = %s, why stopping = %d," 1066 " final_value_type %d", 1067 first_unparsed, reason_to_stop, final_value_type); 1068 } 1069 return item; 1070 } 1071 1072 bool 1073 Debugger::FormatPrompt 1074 ( 1075 const char *format, 1076 const SymbolContext *sc, 1077 const ExecutionContext *exe_ctx, 1078 const Address *addr, 1079 Stream &s, 1080 const char **end, 1081 ValueObject* valobj 1082 ) 1083 { 1084 ValueObject* realvalobj = NULL; // makes it super-easy to parse pointers 1085 bool success = true; 1086 const char *p; 1087 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES)); 1088 for (p = format; *p != '\0'; ++p) 1089 { 1090 if (realvalobj) 1091 { 1092 valobj = realvalobj; 1093 realvalobj = NULL; 1094 } 1095 size_t non_special_chars = ::strcspn (p, "${}\\"); 1096 if (non_special_chars > 0) 1097 { 1098 if (success) 1099 s.Write (p, non_special_chars); 1100 p += non_special_chars; 1101 } 1102 1103 if (*p == '\0') 1104 { 1105 break; 1106 } 1107 else if (*p == '{') 1108 { 1109 // Start a new scope that must have everything it needs if it is to 1110 // to make it into the final output stream "s". If you want to make 1111 // a format that only prints out the function or symbol name if there 1112 // is one in the symbol context you can use: 1113 // "{function =${function.name}}" 1114 // The first '{' starts a new scope that end with the matching '}' at 1115 // the end of the string. The contents "function =${function.name}" 1116 // will then be evaluated and only be output if there is a function 1117 // or symbol with a valid name. 1118 StreamString sub_strm; 1119 1120 ++p; // Skip the '{' 1121 1122 if (FormatPrompt (p, sc, exe_ctx, addr, sub_strm, &p, valobj)) 1123 { 1124 // The stream had all it needed 1125 s.Write(sub_strm.GetData(), sub_strm.GetSize()); 1126 } 1127 if (*p != '}') 1128 { 1129 success = false; 1130 break; 1131 } 1132 } 1133 else if (*p == '}') 1134 { 1135 // End of a enclosing scope 1136 break; 1137 } 1138 else if (*p == '$') 1139 { 1140 // We have a prompt variable to print 1141 ++p; 1142 if (*p == '{') 1143 { 1144 ++p; 1145 const char *var_name_begin = p; 1146 const char *var_name_end = ::strchr (p, '}'); 1147 1148 if (var_name_end && var_name_begin < var_name_end) 1149 { 1150 // if we have already failed to parse, skip this variable 1151 if (success) 1152 { 1153 const char *cstr = NULL; 1154 Address format_addr; 1155 bool calculate_format_addr_function_offset = false; 1156 // Set reg_kind and reg_num to invalid values 1157 RegisterKind reg_kind = kNumRegisterKinds; 1158 uint32_t reg_num = LLDB_INVALID_REGNUM; 1159 FileSpec format_file_spec; 1160 const RegisterInfo *reg_info = NULL; 1161 RegisterContext *reg_ctx = NULL; 1162 bool do_deref_pointer = false; 1163 ValueObject::ExpressionPathScanEndReason reason_to_stop = ValueObject::eExpressionPathScanEndReasonEndOfString; 1164 ValueObject::ExpressionPathEndResultType final_value_type = ValueObject::eExpressionPathEndResultTypePlain; 1165 1166 // Each variable must set success to true below... 1167 bool var_success = false; 1168 switch (var_name_begin[0]) 1169 { 1170 case '*': 1171 case 'v': 1172 case 's': 1173 { 1174 if (!valobj) 1175 break; 1176 1177 if (log) 1178 log->Printf("initial string: %s",var_name_begin); 1179 1180 // check for *var and *svar 1181 if (*var_name_begin == '*') 1182 { 1183 do_deref_pointer = true; 1184 var_name_begin++; 1185 } 1186 1187 if (log) 1188 log->Printf("initial string: %s",var_name_begin); 1189 1190 if (*var_name_begin == 's') 1191 { 1192 if (!valobj->IsSynthetic()) 1193 valobj = valobj->GetSyntheticValue().get(); 1194 if (!valobj) 1195 break; 1196 var_name_begin++; 1197 } 1198 1199 if (log) 1200 log->Printf("initial string: %s",var_name_begin); 1201 1202 // should be a 'v' by now 1203 if (*var_name_begin != 'v') 1204 break; 1205 1206 if (log) 1207 log->Printf("initial string: %s",var_name_begin); 1208 1209 ValueObject::ExpressionPathAftermath what_next = (do_deref_pointer ? 1210 ValueObject::eExpressionPathAftermathDereference : ValueObject::eExpressionPathAftermathNothing); 1211 ValueObject::GetValueForExpressionPathOptions options; 1212 options.DontCheckDotVsArrowSyntax().DoAllowBitfieldSyntax().DoAllowFragileIVar().DoAllowSyntheticChildren(); 1213 ValueObject::ValueObjectRepresentationStyle val_obj_display = ValueObject::eValueObjectRepresentationStyleSummary; 1214 ValueObject* target = NULL; 1215 Format custom_format = eFormatInvalid; 1216 const char* var_name_final = NULL; 1217 const char* var_name_final_if_array_range = NULL; 1218 const char* close_bracket_position = NULL; 1219 int64_t index_lower = -1; 1220 int64_t index_higher = -1; 1221 bool is_array_range = false; 1222 const char* first_unparsed; 1223 bool was_plain_var = false; 1224 bool was_var_format = false; 1225 bool was_var_indexed = false; 1226 1227 if (!valobj) break; 1228 // simplest case ${var}, just print valobj's value 1229 if (::strncmp (var_name_begin, "var}", strlen("var}")) == 0) 1230 { 1231 was_plain_var = true; 1232 target = valobj; 1233 val_obj_display = ValueObject::eValueObjectRepresentationStyleValue; 1234 } 1235 else if (::strncmp(var_name_begin,"var%",strlen("var%")) == 0) 1236 { 1237 was_var_format = true; 1238 // this is a variable with some custom format applied to it 1239 const char* percent_position; 1240 target = valobj; 1241 val_obj_display = ValueObject::eValueObjectRepresentationStyleValue; 1242 ScanFormatDescriptor (var_name_begin, 1243 var_name_end, 1244 &var_name_final, 1245 &percent_position, 1246 &custom_format, 1247 &val_obj_display); 1248 } 1249 // this is ${var.something} or multiple .something nested 1250 else if (::strncmp (var_name_begin, "var", strlen("var")) == 0) 1251 { 1252 if (::strncmp(var_name_begin, "var[", strlen("var[")) == 0) 1253 was_var_indexed = true; 1254 const char* percent_position; 1255 ScanFormatDescriptor (var_name_begin, 1256 var_name_end, 1257 &var_name_final, 1258 &percent_position, 1259 &custom_format, 1260 &val_obj_display); 1261 1262 const char* open_bracket_position; 1263 const char* separator_position; 1264 ScanBracketedRange (var_name_begin, 1265 var_name_end, 1266 var_name_final, 1267 &open_bracket_position, 1268 &separator_position, 1269 &close_bracket_position, 1270 &var_name_final_if_array_range, 1271 &index_lower, 1272 &index_higher); 1273 1274 Error error; 1275 1276 std::auto_ptr<char> expr_path(new char[var_name_final-var_name_begin-1]); 1277 ::memset(expr_path.get(), 0, var_name_final-var_name_begin-1); 1278 memcpy(expr_path.get(), var_name_begin+3,var_name_final-var_name_begin-3); 1279 1280 if (log) 1281 log->Printf("symbol to expand: %s",expr_path.get()); 1282 1283 target = valobj->GetValueForExpressionPath(expr_path.get(), 1284 &first_unparsed, 1285 &reason_to_stop, 1286 &final_value_type, 1287 options, 1288 &what_next).get(); 1289 1290 if (!target) 1291 { 1292 if (log) 1293 log->Printf("ERROR: unparsed portion = %s, why stopping = %d," 1294 " final_value_type %d", 1295 first_unparsed, reason_to_stop, final_value_type); 1296 break; 1297 } 1298 else 1299 { 1300 if (log) 1301 log->Printf("ALL RIGHT: unparsed portion = %s, why stopping = %d," 1302 " final_value_type %d", 1303 first_unparsed, reason_to_stop, final_value_type); 1304 } 1305 } 1306 else 1307 break; 1308 1309 is_array_range = (final_value_type == ValueObject::eExpressionPathEndResultTypeBoundedRange || 1310 final_value_type == ValueObject::eExpressionPathEndResultTypeUnboundedRange); 1311 1312 do_deref_pointer = (what_next == ValueObject::eExpressionPathAftermathDereference); 1313 1314 if (do_deref_pointer && !is_array_range) 1315 { 1316 // I have not deref-ed yet, let's do it 1317 // this happens when we are not going through GetValueForVariableExpressionPath 1318 // to get to the target ValueObject 1319 Error error; 1320 target = target->Dereference(error).get(); 1321 if (error.Fail()) 1322 { 1323 if (log) 1324 log->Printf("ERROR: %s\n", error.AsCString("unknown")); \ 1325 break; 1326 } 1327 do_deref_pointer = false; 1328 } 1329 1330 // <rdar://problem/11338654> 1331 // we do not want to use the summary for a bitfield of type T:n 1332 // if we were originally dealing with just a T - that would get 1333 // us into an endless recursion 1334 if (target->IsBitfield() && was_var_indexed) 1335 { 1336 // TODO: check for a (T:n)-specific summary - we should still obey that 1337 StreamString bitfield_name; 1338 bitfield_name.Printf("%s:%d", target->GetTypeName().AsCString(), target->GetBitfieldBitSize()); 1339 lldb::TypeNameSpecifierImplSP type_sp(new TypeNameSpecifierImpl(bitfield_name.GetData(),false)); 1340 if (!DataVisualization::GetSummaryForType(type_sp)) 1341 val_obj_display = ValueObject::eValueObjectRepresentationStyleValue; 1342 } 1343 1344 // TODO use flags for these 1345 bool is_array = ClangASTContext::IsArrayType(target->GetClangType()); 1346 bool is_pointer = ClangASTContext::IsPointerType(target->GetClangType()); 1347 bool is_aggregate = ClangASTContext::IsAggregateType(target->GetClangType()); 1348 1349 if ((is_array || is_pointer) && (!is_array_range) && val_obj_display == ValueObject::eValueObjectRepresentationStyleValue) // this should be wrong, but there are some exceptions 1350 { 1351 StreamString str_temp; 1352 if (log) 1353 log->Printf("I am into array || pointer && !range"); 1354 1355 if (target->HasSpecialPrintableRepresentation(val_obj_display, 1356 custom_format)) 1357 { 1358 // try to use the special cases 1359 var_success = target->DumpPrintableRepresentation(str_temp, 1360 val_obj_display, 1361 custom_format); 1362 if (log) 1363 log->Printf("special cases did%s match", var_success ? "" : "n't"); 1364 1365 // should not happen 1366 if (!var_success) 1367 s << "<invalid usage of pointer value as object>"; 1368 else 1369 s << str_temp.GetData(); 1370 var_success = true; 1371 break; 1372 } 1373 else 1374 { 1375 if (was_plain_var) // if ${var} 1376 { 1377 s << target->GetTypeName() << " @ " << target->GetLocationAsCString(); 1378 } 1379 else if (is_pointer) // if pointer, value is the address stored 1380 { 1381 var_success = target->DumpPrintableRepresentation(s, 1382 val_obj_display, 1383 custom_format, 1384 ValueObject::ePrintableRepresentationSpecialCasesDisable); 1385 } 1386 else 1387 { 1388 s << "<invalid usage of pointer value as object>"; 1389 } 1390 var_success = true; 1391 break; 1392 } 1393 } 1394 1395 // if directly trying to print ${var}, and this is an aggregate, display a nice 1396 // type @ location message 1397 if (is_aggregate && was_plain_var) 1398 { 1399 s << target->GetTypeName() << " @ " << target->GetLocationAsCString(); 1400 var_success = true; 1401 break; 1402 } 1403 1404 // if directly trying to print ${var%V}, and this is an aggregate, do not let the user do it 1405 if (is_aggregate && ((was_var_format && val_obj_display == ValueObject::eValueObjectRepresentationStyleValue))) 1406 { 1407 s << "<invalid use of aggregate type>"; 1408 var_success = true; 1409 break; 1410 } 1411 1412 if (!is_array_range) 1413 { 1414 if (log) 1415 log->Printf("dumping ordinary printable output"); 1416 var_success = target->DumpPrintableRepresentation(s,val_obj_display, custom_format); 1417 } 1418 else 1419 { 1420 if (log) 1421 log->Printf("checking if I can handle as array"); 1422 if (!is_array && !is_pointer) 1423 break; 1424 if (log) 1425 log->Printf("handle as array"); 1426 const char* special_directions = NULL; 1427 StreamString special_directions_writer; 1428 if (close_bracket_position && (var_name_end-close_bracket_position > 1)) 1429 { 1430 ConstString additional_data; 1431 additional_data.SetCStringWithLength(close_bracket_position+1, var_name_end-close_bracket_position-1); 1432 special_directions_writer.Printf("${%svar%s}", 1433 do_deref_pointer ? "*" : "", 1434 additional_data.GetCString()); 1435 special_directions = special_directions_writer.GetData(); 1436 } 1437 1438 // let us display items index_lower thru index_higher of this array 1439 s.PutChar('['); 1440 var_success = true; 1441 1442 if (index_higher < 0) 1443 index_higher = valobj->GetNumChildren() - 1; 1444 1445 uint32_t max_num_children = target->GetTargetSP()->GetMaximumNumberOfChildrenToDisplay(); 1446 1447 for (;index_lower<=index_higher;index_lower++) 1448 { 1449 ValueObject* item = ExpandIndexedExpression (target, 1450 index_lower, 1451 exe_ctx->GetFramePtr(), 1452 false).get(); 1453 1454 if (!item) 1455 { 1456 if (log) 1457 log->Printf("ERROR in getting child item at index %lld", index_lower); 1458 } 1459 else 1460 { 1461 if (log) 1462 log->Printf("special_directions for child item: %s",special_directions); 1463 } 1464 1465 if (!special_directions) 1466 var_success &= item->DumpPrintableRepresentation(s,val_obj_display, custom_format); 1467 else 1468 var_success &= FormatPrompt(special_directions, sc, exe_ctx, addr, s, NULL, item); 1469 1470 if (--max_num_children == 0) 1471 { 1472 s.PutCString(", ..."); 1473 break; 1474 } 1475 1476 if (index_lower < index_higher) 1477 s.PutChar(','); 1478 } 1479 s.PutChar(']'); 1480 } 1481 } 1482 break; 1483 case 'a': 1484 if (::strncmp (var_name_begin, "addr}", strlen("addr}")) == 0) 1485 { 1486 if (addr && addr->IsValid()) 1487 { 1488 var_success = true; 1489 format_addr = *addr; 1490 } 1491 } 1492 else if (::strncmp (var_name_begin, "ansi.", strlen("ansi.")) == 0) 1493 { 1494 var_success = true; 1495 var_name_begin += strlen("ansi."); // Skip the "ansi." 1496 if (::strncmp (var_name_begin, "fg.", strlen("fg.")) == 0) 1497 { 1498 var_name_begin += strlen("fg."); // Skip the "fg." 1499 if (::strncmp (var_name_begin, "black}", strlen("black}")) == 0) 1500 { 1501 s.Printf ("%s%s%s", 1502 lldb_utility::ansi::k_escape_start, 1503 lldb_utility::ansi::k_fg_black, 1504 lldb_utility::ansi::k_escape_end); 1505 } 1506 else if (::strncmp (var_name_begin, "red}", strlen("red}")) == 0) 1507 { 1508 s.Printf ("%s%s%s", 1509 lldb_utility::ansi::k_escape_start, 1510 lldb_utility::ansi::k_fg_red, 1511 lldb_utility::ansi::k_escape_end); 1512 } 1513 else if (::strncmp (var_name_begin, "green}", strlen("green}")) == 0) 1514 { 1515 s.Printf ("%s%s%s", 1516 lldb_utility::ansi::k_escape_start, 1517 lldb_utility::ansi::k_fg_green, 1518 lldb_utility::ansi::k_escape_end); 1519 } 1520 else if (::strncmp (var_name_begin, "yellow}", strlen("yellow}")) == 0) 1521 { 1522 s.Printf ("%s%s%s", 1523 lldb_utility::ansi::k_escape_start, 1524 lldb_utility::ansi::k_fg_yellow, 1525 lldb_utility::ansi::k_escape_end); 1526 } 1527 else if (::strncmp (var_name_begin, "blue}", strlen("blue}")) == 0) 1528 { 1529 s.Printf ("%s%s%s", 1530 lldb_utility::ansi::k_escape_start, 1531 lldb_utility::ansi::k_fg_blue, 1532 lldb_utility::ansi::k_escape_end); 1533 } 1534 else if (::strncmp (var_name_begin, "purple}", strlen("purple}")) == 0) 1535 { 1536 s.Printf ("%s%s%s", 1537 lldb_utility::ansi::k_escape_start, 1538 lldb_utility::ansi::k_fg_purple, 1539 lldb_utility::ansi::k_escape_end); 1540 } 1541 else if (::strncmp (var_name_begin, "cyan}", strlen("cyan}")) == 0) 1542 { 1543 s.Printf ("%s%s%s", 1544 lldb_utility::ansi::k_escape_start, 1545 lldb_utility::ansi::k_fg_cyan, 1546 lldb_utility::ansi::k_escape_end); 1547 } 1548 else if (::strncmp (var_name_begin, "white}", strlen("white}")) == 0) 1549 { 1550 s.Printf ("%s%s%s", 1551 lldb_utility::ansi::k_escape_start, 1552 lldb_utility::ansi::k_fg_white, 1553 lldb_utility::ansi::k_escape_end); 1554 } 1555 else 1556 { 1557 var_success = false; 1558 } 1559 } 1560 else if (::strncmp (var_name_begin, "bg.", strlen("bg.")) == 0) 1561 { 1562 var_name_begin += strlen("bg."); // Skip the "bg." 1563 if (::strncmp (var_name_begin, "black}", strlen("black}")) == 0) 1564 { 1565 s.Printf ("%s%s%s", 1566 lldb_utility::ansi::k_escape_start, 1567 lldb_utility::ansi::k_bg_black, 1568 lldb_utility::ansi::k_escape_end); 1569 } 1570 else if (::strncmp (var_name_begin, "red}", strlen("red}")) == 0) 1571 { 1572 s.Printf ("%s%s%s", 1573 lldb_utility::ansi::k_escape_start, 1574 lldb_utility::ansi::k_bg_red, 1575 lldb_utility::ansi::k_escape_end); 1576 } 1577 else if (::strncmp (var_name_begin, "green}", strlen("green}")) == 0) 1578 { 1579 s.Printf ("%s%s%s", 1580 lldb_utility::ansi::k_escape_start, 1581 lldb_utility::ansi::k_bg_green, 1582 lldb_utility::ansi::k_escape_end); 1583 } 1584 else if (::strncmp (var_name_begin, "yellow}", strlen("yellow}")) == 0) 1585 { 1586 s.Printf ("%s%s%s", 1587 lldb_utility::ansi::k_escape_start, 1588 lldb_utility::ansi::k_bg_yellow, 1589 lldb_utility::ansi::k_escape_end); 1590 } 1591 else if (::strncmp (var_name_begin, "blue}", strlen("blue}")) == 0) 1592 { 1593 s.Printf ("%s%s%s", 1594 lldb_utility::ansi::k_escape_start, 1595 lldb_utility::ansi::k_bg_blue, 1596 lldb_utility::ansi::k_escape_end); 1597 } 1598 else if (::strncmp (var_name_begin, "purple}", strlen("purple}")) == 0) 1599 { 1600 s.Printf ("%s%s%s", 1601 lldb_utility::ansi::k_escape_start, 1602 lldb_utility::ansi::k_bg_purple, 1603 lldb_utility::ansi::k_escape_end); 1604 } 1605 else if (::strncmp (var_name_begin, "cyan}", strlen("cyan}")) == 0) 1606 { 1607 s.Printf ("%s%s%s", 1608 lldb_utility::ansi::k_escape_start, 1609 lldb_utility::ansi::k_bg_cyan, 1610 lldb_utility::ansi::k_escape_end); 1611 } 1612 else if (::strncmp (var_name_begin, "white}", strlen("white}")) == 0) 1613 { 1614 s.Printf ("%s%s%s", 1615 lldb_utility::ansi::k_escape_start, 1616 lldb_utility::ansi::k_bg_white, 1617 lldb_utility::ansi::k_escape_end); 1618 } 1619 else 1620 { 1621 var_success = false; 1622 } 1623 } 1624 else if (::strncmp (var_name_begin, "normal}", strlen ("normal}")) == 0) 1625 { 1626 s.Printf ("%s%s%s", 1627 lldb_utility::ansi::k_escape_start, 1628 lldb_utility::ansi::k_ctrl_normal, 1629 lldb_utility::ansi::k_escape_end); 1630 } 1631 else if (::strncmp (var_name_begin, "bold}", strlen("bold}")) == 0) 1632 { 1633 s.Printf ("%s%s%s", 1634 lldb_utility::ansi::k_escape_start, 1635 lldb_utility::ansi::k_ctrl_bold, 1636 lldb_utility::ansi::k_escape_end); 1637 } 1638 else if (::strncmp (var_name_begin, "faint}", strlen("faint}")) == 0) 1639 { 1640 s.Printf ("%s%s%s", 1641 lldb_utility::ansi::k_escape_start, 1642 lldb_utility::ansi::k_ctrl_faint, 1643 lldb_utility::ansi::k_escape_end); 1644 } 1645 else if (::strncmp (var_name_begin, "italic}", strlen("italic}")) == 0) 1646 { 1647 s.Printf ("%s%s%s", 1648 lldb_utility::ansi::k_escape_start, 1649 lldb_utility::ansi::k_ctrl_italic, 1650 lldb_utility::ansi::k_escape_end); 1651 } 1652 else if (::strncmp (var_name_begin, "underline}", strlen("underline}")) == 0) 1653 { 1654 s.Printf ("%s%s%s", 1655 lldb_utility::ansi::k_escape_start, 1656 lldb_utility::ansi::k_ctrl_underline, 1657 lldb_utility::ansi::k_escape_end); 1658 } 1659 else if (::strncmp (var_name_begin, "slow-blink}", strlen("slow-blink}")) == 0) 1660 { 1661 s.Printf ("%s%s%s", 1662 lldb_utility::ansi::k_escape_start, 1663 lldb_utility::ansi::k_ctrl_slow_blink, 1664 lldb_utility::ansi::k_escape_end); 1665 } 1666 else if (::strncmp (var_name_begin, "fast-blink}", strlen("fast-blink}")) == 0) 1667 { 1668 s.Printf ("%s%s%s", 1669 lldb_utility::ansi::k_escape_start, 1670 lldb_utility::ansi::k_ctrl_fast_blink, 1671 lldb_utility::ansi::k_escape_end); 1672 } 1673 else if (::strncmp (var_name_begin, "negative}", strlen("negative}")) == 0) 1674 { 1675 s.Printf ("%s%s%s", 1676 lldb_utility::ansi::k_escape_start, 1677 lldb_utility::ansi::k_ctrl_negative, 1678 lldb_utility::ansi::k_escape_end); 1679 } 1680 else if (::strncmp (var_name_begin, "conceal}", strlen("conceal}")) == 0) 1681 { 1682 s.Printf ("%s%s%s", 1683 lldb_utility::ansi::k_escape_start, 1684 lldb_utility::ansi::k_ctrl_conceal, 1685 lldb_utility::ansi::k_escape_end); 1686 1687 } 1688 else if (::strncmp (var_name_begin, "crossed-out}", strlen("crossed-out}")) == 0) 1689 { 1690 s.Printf ("%s%s%s", 1691 lldb_utility::ansi::k_escape_start, 1692 lldb_utility::ansi::k_ctrl_crossed_out, 1693 lldb_utility::ansi::k_escape_end); 1694 } 1695 else 1696 { 1697 var_success = false; 1698 } 1699 } 1700 break; 1701 1702 case 'p': 1703 if (::strncmp (var_name_begin, "process.", strlen("process.")) == 0) 1704 { 1705 if (exe_ctx) 1706 { 1707 Process *process = exe_ctx->GetProcessPtr(); 1708 if (process) 1709 { 1710 var_name_begin += ::strlen ("process."); 1711 if (::strncmp (var_name_begin, "id}", strlen("id}")) == 0) 1712 { 1713 s.Printf("%llu", process->GetID()); 1714 var_success = true; 1715 } 1716 else if ((::strncmp (var_name_begin, "name}", strlen("name}")) == 0) || 1717 (::strncmp (var_name_begin, "file.basename}", strlen("file.basename}")) == 0) || 1718 (::strncmp (var_name_begin, "file.fullpath}", strlen("file.fullpath}")) == 0)) 1719 { 1720 Module *exe_module = process->GetTarget().GetExecutableModulePointer(); 1721 if (exe_module) 1722 { 1723 if (var_name_begin[0] == 'n' || var_name_begin[5] == 'f') 1724 { 1725 format_file_spec.GetFilename() = exe_module->GetFileSpec().GetFilename(); 1726 var_success = format_file_spec; 1727 } 1728 else 1729 { 1730 format_file_spec = exe_module->GetFileSpec(); 1731 var_success = format_file_spec; 1732 } 1733 } 1734 } 1735 } 1736 } 1737 } 1738 break; 1739 1740 case 't': 1741 if (::strncmp (var_name_begin, "thread.", strlen("thread.")) == 0) 1742 { 1743 if (exe_ctx) 1744 { 1745 Thread *thread = exe_ctx->GetThreadPtr(); 1746 if (thread) 1747 { 1748 var_name_begin += ::strlen ("thread."); 1749 if (::strncmp (var_name_begin, "id}", strlen("id}")) == 0) 1750 { 1751 s.Printf("0x%4.4llx", thread->GetID()); 1752 var_success = true; 1753 } 1754 else if (::strncmp (var_name_begin, "index}", strlen("index}")) == 0) 1755 { 1756 s.Printf("%u", thread->GetIndexID()); 1757 var_success = true; 1758 } 1759 else if (::strncmp (var_name_begin, "name}", strlen("name}")) == 0) 1760 { 1761 cstr = thread->GetName(); 1762 var_success = cstr && cstr[0]; 1763 if (var_success) 1764 s.PutCString(cstr); 1765 } 1766 else if (::strncmp (var_name_begin, "queue}", strlen("queue}")) == 0) 1767 { 1768 cstr = thread->GetQueueName(); 1769 var_success = cstr && cstr[0]; 1770 if (var_success) 1771 s.PutCString(cstr); 1772 } 1773 else if (::strncmp (var_name_begin, "stop-reason}", strlen("stop-reason}")) == 0) 1774 { 1775 StopInfoSP stop_info_sp = thread->GetStopInfo (); 1776 if (stop_info_sp) 1777 { 1778 cstr = stop_info_sp->GetDescription(); 1779 if (cstr && cstr[0]) 1780 { 1781 s.PutCString(cstr); 1782 var_success = true; 1783 } 1784 } 1785 } 1786 else if (::strncmp (var_name_begin, "return-value}", strlen("return-value}")) == 0) 1787 { 1788 StopInfoSP stop_info_sp = thread->GetStopInfo (); 1789 if (stop_info_sp) 1790 { 1791 ValueObjectSP return_valobj_sp = StopInfo::GetReturnValueObject (stop_info_sp); 1792 if (return_valobj_sp) 1793 { 1794 ValueObject::DumpValueObjectOptions dump_options; 1795 ValueObject::DumpValueObject (s, return_valobj_sp.get(), dump_options); 1796 var_success = true; 1797 } 1798 } 1799 } 1800 } 1801 } 1802 } 1803 else if (::strncmp (var_name_begin, "target.", strlen("target.")) == 0) 1804 { 1805 Target *target = Target::GetTargetFromContexts (exe_ctx, sc); 1806 if (target) 1807 { 1808 var_name_begin += ::strlen ("target."); 1809 if (::strncmp (var_name_begin, "arch}", strlen("arch}")) == 0) 1810 { 1811 ArchSpec arch (target->GetArchitecture ()); 1812 if (arch.IsValid()) 1813 { 1814 s.PutCString (arch.GetArchitectureName()); 1815 var_success = true; 1816 } 1817 } 1818 } 1819 } 1820 break; 1821 1822 1823 case 'm': 1824 if (::strncmp (var_name_begin, "module.", strlen("module.")) == 0) 1825 { 1826 if (sc && sc->module_sp.get()) 1827 { 1828 Module *module = sc->module_sp.get(); 1829 var_name_begin += ::strlen ("module."); 1830 1831 if (::strncmp (var_name_begin, "file.", strlen("file.")) == 0) 1832 { 1833 if (module->GetFileSpec()) 1834 { 1835 var_name_begin += ::strlen ("file."); 1836 1837 if (::strncmp (var_name_begin, "basename}", strlen("basename}")) == 0) 1838 { 1839 format_file_spec.GetFilename() = module->GetFileSpec().GetFilename(); 1840 var_success = format_file_spec; 1841 } 1842 else if (::strncmp (var_name_begin, "fullpath}", strlen("fullpath}")) == 0) 1843 { 1844 format_file_spec = module->GetFileSpec(); 1845 var_success = format_file_spec; 1846 } 1847 } 1848 } 1849 } 1850 } 1851 break; 1852 1853 1854 case 'f': 1855 if (::strncmp (var_name_begin, "file.", strlen("file.")) == 0) 1856 { 1857 if (sc && sc->comp_unit != NULL) 1858 { 1859 var_name_begin += ::strlen ("file."); 1860 1861 if (::strncmp (var_name_begin, "basename}", strlen("basename}")) == 0) 1862 { 1863 format_file_spec.GetFilename() = sc->comp_unit->GetFilename(); 1864 var_success = format_file_spec; 1865 } 1866 else if (::strncmp (var_name_begin, "fullpath}", strlen("fullpath}")) == 0) 1867 { 1868 format_file_spec = *sc->comp_unit; 1869 var_success = format_file_spec; 1870 } 1871 } 1872 } 1873 else if (::strncmp (var_name_begin, "frame.", strlen("frame.")) == 0) 1874 { 1875 if (exe_ctx) 1876 { 1877 StackFrame *frame = exe_ctx->GetFramePtr(); 1878 if (frame) 1879 { 1880 var_name_begin += ::strlen ("frame."); 1881 if (::strncmp (var_name_begin, "index}", strlen("index}")) == 0) 1882 { 1883 s.Printf("%u", frame->GetFrameIndex()); 1884 var_success = true; 1885 } 1886 else if (::strncmp (var_name_begin, "pc}", strlen("pc}")) == 0) 1887 { 1888 reg_kind = eRegisterKindGeneric; 1889 reg_num = LLDB_REGNUM_GENERIC_PC; 1890 var_success = true; 1891 } 1892 else if (::strncmp (var_name_begin, "sp}", strlen("sp}")) == 0) 1893 { 1894 reg_kind = eRegisterKindGeneric; 1895 reg_num = LLDB_REGNUM_GENERIC_SP; 1896 var_success = true; 1897 } 1898 else if (::strncmp (var_name_begin, "fp}", strlen("fp}")) == 0) 1899 { 1900 reg_kind = eRegisterKindGeneric; 1901 reg_num = LLDB_REGNUM_GENERIC_FP; 1902 var_success = true; 1903 } 1904 else if (::strncmp (var_name_begin, "flags}", strlen("flags}")) == 0) 1905 { 1906 reg_kind = eRegisterKindGeneric; 1907 reg_num = LLDB_REGNUM_GENERIC_FLAGS; 1908 var_success = true; 1909 } 1910 else if (::strncmp (var_name_begin, "reg.", strlen ("reg.")) == 0) 1911 { 1912 reg_ctx = frame->GetRegisterContext().get(); 1913 if (reg_ctx) 1914 { 1915 var_name_begin += ::strlen ("reg."); 1916 if (var_name_begin < var_name_end) 1917 { 1918 std::string reg_name (var_name_begin, var_name_end); 1919 reg_info = reg_ctx->GetRegisterInfoByName (reg_name.c_str()); 1920 if (reg_info) 1921 var_success = true; 1922 } 1923 } 1924 } 1925 } 1926 } 1927 } 1928 else if (::strncmp (var_name_begin, "function.", strlen("function.")) == 0) 1929 { 1930 if (sc && (sc->function != NULL || sc->symbol != NULL)) 1931 { 1932 var_name_begin += ::strlen ("function."); 1933 if (::strncmp (var_name_begin, "id}", strlen("id}")) == 0) 1934 { 1935 if (sc->function) 1936 s.Printf("function{0x%8.8llx}", sc->function->GetID()); 1937 else 1938 s.Printf("symbol[%u]", sc->symbol->GetID()); 1939 1940 var_success = true; 1941 } 1942 else if (::strncmp (var_name_begin, "name}", strlen("name}")) == 0) 1943 { 1944 if (sc->function) 1945 cstr = sc->function->GetName().AsCString (NULL); 1946 else if (sc->symbol) 1947 cstr = sc->symbol->GetName().AsCString (NULL); 1948 if (cstr) 1949 { 1950 s.PutCString(cstr); 1951 1952 if (sc->block) 1953 { 1954 Block *inline_block = sc->block->GetContainingInlinedBlock (); 1955 if (inline_block) 1956 { 1957 const InlineFunctionInfo *inline_info = sc->block->GetInlinedFunctionInfo(); 1958 if (inline_info) 1959 { 1960 s.PutCString(" [inlined] "); 1961 inline_info->GetName().Dump(&s); 1962 } 1963 } 1964 } 1965 var_success = true; 1966 } 1967 } 1968 else if (::strncmp (var_name_begin, "name-with-args}", strlen("name-with-args}")) == 0) 1969 { 1970 // Print the function name with arguments in it 1971 1972 if (sc->function) 1973 { 1974 var_success = true; 1975 ExecutionContextScope *exe_scope = exe_ctx ? exe_ctx->GetBestExecutionContextScope() : NULL; 1976 cstr = sc->function->GetName().AsCString (NULL); 1977 if (cstr) 1978 { 1979 const InlineFunctionInfo *inline_info = NULL; 1980 VariableListSP variable_list_sp; 1981 bool get_function_vars = true; 1982 if (sc->block) 1983 { 1984 Block *inline_block = sc->block->GetContainingInlinedBlock (); 1985 1986 if (inline_block) 1987 { 1988 get_function_vars = false; 1989 inline_info = sc->block->GetInlinedFunctionInfo(); 1990 if (inline_info) 1991 variable_list_sp = inline_block->GetBlockVariableList (true); 1992 } 1993 } 1994 1995 if (get_function_vars) 1996 { 1997 variable_list_sp = sc->function->GetBlock(true).GetBlockVariableList (true); 1998 } 1999 2000 if (inline_info) 2001 { 2002 s.PutCString (cstr); 2003 s.PutCString (" [inlined] "); 2004 cstr = inline_info->GetName().GetCString(); 2005 } 2006 2007 VariableList args; 2008 if (variable_list_sp) 2009 { 2010 const size_t num_variables = variable_list_sp->GetSize(); 2011 for (size_t var_idx = 0; var_idx < num_variables; ++var_idx) 2012 { 2013 VariableSP var_sp (variable_list_sp->GetVariableAtIndex(var_idx)); 2014 if (var_sp->GetScope() == eValueTypeVariableArgument) 2015 args.AddVariable (var_sp); 2016 } 2017 2018 } 2019 if (args.GetSize() > 0) 2020 { 2021 const char *open_paren = strchr (cstr, '('); 2022 const char *close_paren = NULL; 2023 if (open_paren) 2024 close_paren = strchr (open_paren, ')'); 2025 2026 if (open_paren) 2027 s.Write(cstr, open_paren - cstr + 1); 2028 else 2029 { 2030 s.PutCString (cstr); 2031 s.PutChar ('('); 2032 } 2033 const size_t num_args = args.GetSize(); 2034 for (size_t arg_idx = 0; arg_idx < num_args; ++arg_idx) 2035 { 2036 VariableSP var_sp (args.GetVariableAtIndex (arg_idx)); 2037 ValueObjectSP var_value_sp (ValueObjectVariable::Create (exe_scope, var_sp)); 2038 const char *var_name = var_value_sp->GetName().GetCString(); 2039 const char *var_value = var_value_sp->GetValueAsCString(); 2040 if (var_value_sp->GetError().Success()) 2041 { 2042 if (arg_idx > 0) 2043 s.PutCString (", "); 2044 s.Printf ("%s=%s", var_name, var_value); 2045 } 2046 } 2047 2048 if (close_paren) 2049 s.PutCString (close_paren); 2050 else 2051 s.PutChar(')'); 2052 2053 } 2054 else 2055 { 2056 s.PutCString(cstr); 2057 } 2058 } 2059 } 2060 else if (sc->symbol) 2061 { 2062 cstr = sc->symbol->GetName().AsCString (NULL); 2063 if (cstr) 2064 { 2065 s.PutCString(cstr); 2066 var_success = true; 2067 } 2068 } 2069 } 2070 else if (::strncmp (var_name_begin, "addr-offset}", strlen("addr-offset}")) == 0) 2071 { 2072 var_success = addr != NULL; 2073 if (var_success) 2074 { 2075 format_addr = *addr; 2076 calculate_format_addr_function_offset = true; 2077 } 2078 } 2079 else if (::strncmp (var_name_begin, "line-offset}", strlen("line-offset}")) == 0) 2080 { 2081 var_success = sc->line_entry.range.GetBaseAddress().IsValid(); 2082 if (var_success) 2083 { 2084 format_addr = sc->line_entry.range.GetBaseAddress(); 2085 calculate_format_addr_function_offset = true; 2086 } 2087 } 2088 else if (::strncmp (var_name_begin, "pc-offset}", strlen("pc-offset}")) == 0) 2089 { 2090 StackFrame *frame = exe_ctx->GetFramePtr(); 2091 var_success = frame != NULL; 2092 if (var_success) 2093 { 2094 format_addr = frame->GetFrameCodeAddress(); 2095 calculate_format_addr_function_offset = true; 2096 } 2097 } 2098 } 2099 } 2100 break; 2101 2102 case 'l': 2103 if (::strncmp (var_name_begin, "line.", strlen("line.")) == 0) 2104 { 2105 if (sc && sc->line_entry.IsValid()) 2106 { 2107 var_name_begin += ::strlen ("line."); 2108 if (::strncmp (var_name_begin, "file.", strlen("file.")) == 0) 2109 { 2110 var_name_begin += ::strlen ("file."); 2111 2112 if (::strncmp (var_name_begin, "basename}", strlen("basename}")) == 0) 2113 { 2114 format_file_spec.GetFilename() = sc->line_entry.file.GetFilename(); 2115 var_success = format_file_spec; 2116 } 2117 else if (::strncmp (var_name_begin, "fullpath}", strlen("fullpath}")) == 0) 2118 { 2119 format_file_spec = sc->line_entry.file; 2120 var_success = format_file_spec; 2121 } 2122 } 2123 else if (::strncmp (var_name_begin, "number}", strlen("number}")) == 0) 2124 { 2125 var_success = true; 2126 s.Printf("%u", sc->line_entry.line); 2127 } 2128 else if ((::strncmp (var_name_begin, "start-addr}", strlen("start-addr}")) == 0) || 2129 (::strncmp (var_name_begin, "end-addr}", strlen("end-addr}")) == 0)) 2130 { 2131 var_success = sc && sc->line_entry.range.GetBaseAddress().IsValid(); 2132 if (var_success) 2133 { 2134 format_addr = sc->line_entry.range.GetBaseAddress(); 2135 if (var_name_begin[0] == 'e') 2136 format_addr.Slide (sc->line_entry.range.GetByteSize()); 2137 } 2138 } 2139 } 2140 } 2141 break; 2142 } 2143 2144 if (var_success) 2145 { 2146 // If format addr is valid, then we need to print an address 2147 if (reg_num != LLDB_INVALID_REGNUM) 2148 { 2149 StackFrame *frame = exe_ctx->GetFramePtr(); 2150 // We have a register value to display... 2151 if (reg_num == LLDB_REGNUM_GENERIC_PC && reg_kind == eRegisterKindGeneric) 2152 { 2153 format_addr = frame->GetFrameCodeAddress(); 2154 } 2155 else 2156 { 2157 if (reg_ctx == NULL) 2158 reg_ctx = frame->GetRegisterContext().get(); 2159 2160 if (reg_ctx) 2161 { 2162 if (reg_kind != kNumRegisterKinds) 2163 reg_num = reg_ctx->ConvertRegisterKindToRegisterNumber(reg_kind, reg_num); 2164 reg_info = reg_ctx->GetRegisterInfoAtIndex (reg_num); 2165 var_success = reg_info != NULL; 2166 } 2167 } 2168 } 2169 2170 if (reg_info != NULL) 2171 { 2172 RegisterValue reg_value; 2173 var_success = reg_ctx->ReadRegister (reg_info, reg_value); 2174 if (var_success) 2175 { 2176 reg_value.Dump(&s, reg_info, false, false, eFormatDefault); 2177 } 2178 } 2179 2180 if (format_file_spec) 2181 { 2182 s << format_file_spec; 2183 } 2184 2185 // If format addr is valid, then we need to print an address 2186 if (format_addr.IsValid()) 2187 { 2188 var_success = false; 2189 2190 if (calculate_format_addr_function_offset) 2191 { 2192 Address func_addr; 2193 2194 if (sc) 2195 { 2196 if (sc->function) 2197 { 2198 func_addr = sc->function->GetAddressRange().GetBaseAddress(); 2199 if (sc->block) 2200 { 2201 // Check to make sure we aren't in an inline 2202 // function. If we are, use the inline block 2203 // range that contains "format_addr" since 2204 // blocks can be discontiguous. 2205 Block *inline_block = sc->block->GetContainingInlinedBlock (); 2206 AddressRange inline_range; 2207 if (inline_block && inline_block->GetRangeContainingAddress (format_addr, inline_range)) 2208 func_addr = inline_range.GetBaseAddress(); 2209 } 2210 } 2211 else if (sc->symbol && sc->symbol->ValueIsAddress()) 2212 func_addr = sc->symbol->GetAddress(); 2213 } 2214 2215 if (func_addr.IsValid()) 2216 { 2217 if (func_addr.GetSection() == format_addr.GetSection()) 2218 { 2219 addr_t func_file_addr = func_addr.GetFileAddress(); 2220 addr_t addr_file_addr = format_addr.GetFileAddress(); 2221 if (addr_file_addr > func_file_addr) 2222 s.Printf(" + %llu", addr_file_addr - func_file_addr); 2223 else if (addr_file_addr < func_file_addr) 2224 s.Printf(" - %llu", func_file_addr - addr_file_addr); 2225 var_success = true; 2226 } 2227 else 2228 { 2229 Target *target = Target::GetTargetFromContexts (exe_ctx, sc); 2230 if (target) 2231 { 2232 addr_t func_load_addr = func_addr.GetLoadAddress (target); 2233 addr_t addr_load_addr = format_addr.GetLoadAddress (target); 2234 if (addr_load_addr > func_load_addr) 2235 s.Printf(" + %llu", addr_load_addr - func_load_addr); 2236 else if (addr_load_addr < func_load_addr) 2237 s.Printf(" - %llu", func_load_addr - addr_load_addr); 2238 var_success = true; 2239 } 2240 } 2241 } 2242 } 2243 else 2244 { 2245 Target *target = Target::GetTargetFromContexts (exe_ctx, sc); 2246 addr_t vaddr = LLDB_INVALID_ADDRESS; 2247 if (exe_ctx && !target->GetSectionLoadList().IsEmpty()) 2248 vaddr = format_addr.GetLoadAddress (target); 2249 if (vaddr == LLDB_INVALID_ADDRESS) 2250 vaddr = format_addr.GetFileAddress (); 2251 2252 if (vaddr != LLDB_INVALID_ADDRESS) 2253 { 2254 int addr_width = target->GetArchitecture().GetAddressByteSize() * 2; 2255 if (addr_width == 0) 2256 addr_width = 16; 2257 s.Printf("0x%*.*llx", addr_width, addr_width, vaddr); 2258 var_success = true; 2259 } 2260 } 2261 } 2262 } 2263 2264 if (var_success == false) 2265 success = false; 2266 } 2267 p = var_name_end; 2268 } 2269 else 2270 break; 2271 } 2272 else 2273 { 2274 // We got a dollar sign with no '{' after it, it must just be a dollar sign 2275 s.PutChar(*p); 2276 } 2277 } 2278 else if (*p == '\\') 2279 { 2280 ++p; // skip the slash 2281 switch (*p) 2282 { 2283 case 'a': s.PutChar ('\a'); break; 2284 case 'b': s.PutChar ('\b'); break; 2285 case 'f': s.PutChar ('\f'); break; 2286 case 'n': s.PutChar ('\n'); break; 2287 case 'r': s.PutChar ('\r'); break; 2288 case 't': s.PutChar ('\t'); break; 2289 case 'v': s.PutChar ('\v'); break; 2290 case '\'': s.PutChar ('\''); break; 2291 case '\\': s.PutChar ('\\'); break; 2292 case '0': 2293 // 1 to 3 octal chars 2294 { 2295 // Make a string that can hold onto the initial zero char, 2296 // up to 3 octal digits, and a terminating NULL. 2297 char oct_str[5] = { 0, 0, 0, 0, 0 }; 2298 2299 int i; 2300 for (i=0; (p[i] >= '0' && p[i] <= '7') && i<4; ++i) 2301 oct_str[i] = p[i]; 2302 2303 // We don't want to consume the last octal character since 2304 // the main for loop will do this for us, so we advance p by 2305 // one less than i (even if i is zero) 2306 p += i - 1; 2307 unsigned long octal_value = ::strtoul (oct_str, NULL, 8); 2308 if (octal_value <= UINT8_MAX) 2309 { 2310 char octal_char = octal_value; 2311 s.Write (&octal_char, 1); 2312 } 2313 } 2314 break; 2315 2316 case 'x': 2317 // hex number in the format 2318 if (isxdigit(p[1])) 2319 { 2320 ++p; // Skip the 'x' 2321 2322 // Make a string that can hold onto two hex chars plus a 2323 // NULL terminator 2324 char hex_str[3] = { 0,0,0 }; 2325 hex_str[0] = *p; 2326 if (isxdigit(p[1])) 2327 { 2328 ++p; // Skip the first of the two hex chars 2329 hex_str[1] = *p; 2330 } 2331 2332 unsigned long hex_value = strtoul (hex_str, NULL, 16); 2333 if (hex_value <= UINT8_MAX) 2334 s.PutChar (hex_value); 2335 } 2336 else 2337 { 2338 s.PutChar('x'); 2339 } 2340 break; 2341 2342 default: 2343 // Just desensitize any other character by just printing what 2344 // came after the '\' 2345 s << *p; 2346 break; 2347 2348 } 2349 2350 } 2351 } 2352 if (end) 2353 *end = p; 2354 return success; 2355 } 2356 2357 void 2358 Debugger::SetLoggingCallback (lldb::LogOutputCallback log_callback, void *baton) 2359 { 2360 // For simplicity's sake, I am not going to deal with how to close down any 2361 // open logging streams, I just redirect everything from here on out to the 2362 // callback. 2363 m_log_callback_stream_sp.reset (new StreamCallback (log_callback, baton)); 2364 } 2365 2366 bool 2367 Debugger::EnableLog (const char *channel, const char **categories, const char *log_file, uint32_t log_options, Stream &error_stream) 2368 { 2369 Log::Callbacks log_callbacks; 2370 2371 StreamSP log_stream_sp; 2372 if (m_log_callback_stream_sp != NULL) 2373 { 2374 log_stream_sp = m_log_callback_stream_sp; 2375 // For now when using the callback mode you always get thread & timestamp. 2376 log_options |= LLDB_LOG_OPTION_PREPEND_TIMESTAMP | LLDB_LOG_OPTION_PREPEND_THREAD_NAME; 2377 } 2378 else if (log_file == NULL || *log_file == '\0') 2379 { 2380 log_stream_sp.reset(new StreamFile(GetOutputFile().GetDescriptor(), false)); 2381 } 2382 else 2383 { 2384 LogStreamMap::iterator pos = m_log_streams.find(log_file); 2385 if (pos == m_log_streams.end()) 2386 { 2387 log_stream_sp.reset (new StreamFile (log_file)); 2388 m_log_streams[log_file] = log_stream_sp; 2389 } 2390 else 2391 log_stream_sp = pos->second; 2392 } 2393 assert (log_stream_sp.get()); 2394 2395 if (log_options == 0) 2396 log_options = LLDB_LOG_OPTION_PREPEND_THREAD_NAME | LLDB_LOG_OPTION_THREADSAFE; 2397 2398 if (Log::GetLogChannelCallbacks (channel, log_callbacks)) 2399 { 2400 log_callbacks.enable (log_stream_sp, log_options, categories, &error_stream); 2401 return true; 2402 } 2403 else 2404 { 2405 LogChannelSP log_channel_sp (LogChannel::FindPlugin (channel)); 2406 if (log_channel_sp) 2407 { 2408 if (log_channel_sp->Enable (log_stream_sp, log_options, &error_stream, categories)) 2409 { 2410 return true; 2411 } 2412 else 2413 { 2414 error_stream.Printf ("Invalid log channel '%s'.\n", channel); 2415 return false; 2416 } 2417 } 2418 else 2419 { 2420 error_stream.Printf ("Invalid log channel '%s'.\n", channel); 2421 return false; 2422 } 2423 } 2424 return false; 2425 } 2426 2427 #pragma mark Debugger::SettingsController 2428 2429 //-------------------------------------------------- 2430 // class Debugger::SettingsController 2431 //-------------------------------------------------- 2432 2433 Debugger::SettingsController::SettingsController () : 2434 UserSettingsController ("", UserSettingsControllerSP()) 2435 { 2436 } 2437 2438 Debugger::SettingsController::~SettingsController () 2439 { 2440 } 2441 2442 2443 InstanceSettingsSP 2444 Debugger::SettingsController::CreateInstanceSettings (const char *instance_name) 2445 { 2446 InstanceSettingsSP new_settings_sp (new DebuggerInstanceSettings (GetSettingsController(), 2447 false, 2448 instance_name)); 2449 return new_settings_sp; 2450 } 2451 2452 #pragma mark DebuggerInstanceSettings 2453 //-------------------------------------------------- 2454 // class DebuggerInstanceSettings 2455 //-------------------------------------------------- 2456 2457 DebuggerInstanceSettings::DebuggerInstanceSettings 2458 ( 2459 const UserSettingsControllerSP &m_owner_sp, 2460 bool live_instance, 2461 const char *name 2462 ) : 2463 InstanceSettings (m_owner_sp, name ? name : InstanceSettings::InvalidName().AsCString(), live_instance), 2464 m_term_width (80), 2465 m_stop_source_before_count (3), 2466 m_stop_source_after_count (3), 2467 m_stop_disassembly_count (4), 2468 m_stop_disassembly_display (eStopDisassemblyTypeNoSource), 2469 m_prompt (), 2470 m_frame_format (), 2471 m_thread_format (), 2472 m_script_lang (), 2473 m_use_external_editor (false), 2474 m_auto_confirm_on (false) 2475 { 2476 // CopyInstanceSettings is a pure virtual function in InstanceSettings; it therefore cannot be called 2477 // until the vtables for DebuggerInstanceSettings are properly set up, i.e. AFTER all the initializers. 2478 // For this reason it has to be called here, rather than in the initializer or in the parent constructor. 2479 // The same is true of CreateInstanceName(). 2480 2481 if (GetInstanceName() == InstanceSettings::InvalidName()) 2482 { 2483 ChangeInstanceName (std::string (CreateInstanceName().AsCString())); 2484 m_owner_sp->RegisterInstanceSettings (this); 2485 } 2486 2487 if (live_instance) 2488 { 2489 const InstanceSettingsSP &pending_settings = m_owner_sp->FindPendingSettings (m_instance_name); 2490 CopyInstanceSettings (pending_settings, false); 2491 } 2492 } 2493 2494 DebuggerInstanceSettings::DebuggerInstanceSettings (const DebuggerInstanceSettings &rhs) : 2495 InstanceSettings (Debugger::GetSettingsController(), CreateInstanceName ().AsCString()), 2496 m_prompt (rhs.m_prompt), 2497 m_frame_format (rhs.m_frame_format), 2498 m_thread_format (rhs.m_thread_format), 2499 m_script_lang (rhs.m_script_lang), 2500 m_use_external_editor (rhs.m_use_external_editor), 2501 m_auto_confirm_on(rhs.m_auto_confirm_on) 2502 { 2503 UserSettingsControllerSP owner_sp (m_owner_wp.lock()); 2504 if (owner_sp) 2505 { 2506 CopyInstanceSettings (owner_sp->FindPendingSettings (m_instance_name), false); 2507 owner_sp->RemovePendingSettings (m_instance_name); 2508 } 2509 } 2510 2511 DebuggerInstanceSettings::~DebuggerInstanceSettings () 2512 { 2513 } 2514 2515 DebuggerInstanceSettings& 2516 DebuggerInstanceSettings::operator= (const DebuggerInstanceSettings &rhs) 2517 { 2518 if (this != &rhs) 2519 { 2520 m_term_width = rhs.m_term_width; 2521 m_prompt = rhs.m_prompt; 2522 m_frame_format = rhs.m_frame_format; 2523 m_thread_format = rhs.m_thread_format; 2524 m_script_lang = rhs.m_script_lang; 2525 m_use_external_editor = rhs.m_use_external_editor; 2526 m_auto_confirm_on = rhs.m_auto_confirm_on; 2527 } 2528 2529 return *this; 2530 } 2531 2532 bool 2533 DebuggerInstanceSettings::ValidTermWidthValue (const char *value, Error err) 2534 { 2535 bool valid = false; 2536 2537 // Verify we have a value string. 2538 if (value == NULL || value[0] == '\0') 2539 { 2540 err.SetErrorString ("missing value, can't set terminal width without a value"); 2541 } 2542 else 2543 { 2544 char *end = NULL; 2545 const uint32_t width = ::strtoul (value, &end, 0); 2546 2547 if (end && end[0] == '\0') 2548 { 2549 return ValidTermWidthValue (width, err); 2550 } 2551 else 2552 err.SetErrorStringWithFormat ("'%s' is not a valid unsigned integer string", value); 2553 } 2554 2555 return valid; 2556 } 2557 2558 bool 2559 DebuggerInstanceSettings::ValidTermWidthValue (uint32_t value, Error err) 2560 { 2561 if (value >= 10 && value <= 1024) 2562 return true; 2563 else 2564 { 2565 err.SetErrorString ("invalid term-width value; value must be between 10 and 1024"); 2566 return false; 2567 } 2568 } 2569 2570 void 2571 DebuggerInstanceSettings::UpdateInstanceSettingsVariable (const ConstString &var_name, 2572 const char *index_value, 2573 const char *value, 2574 const ConstString &instance_name, 2575 const SettingEntry &entry, 2576 VarSetOperationType op, 2577 Error &err, 2578 bool pending) 2579 { 2580 2581 if (var_name == TermWidthVarName()) 2582 { 2583 if (ValidTermWidthValue (value, err)) 2584 { 2585 m_term_width = ::strtoul (value, NULL, 0); 2586 } 2587 } 2588 else if (var_name == PromptVarName()) 2589 { 2590 UserSettingsController::UpdateStringVariable (op, m_prompt, value, err); 2591 if (!pending) 2592 { 2593 // 'instance_name' is actually (probably) in the form '[<instance_name>]'; if so, we need to 2594 // strip off the brackets before passing it to BroadcastPromptChange. 2595 2596 std::string tmp_instance_name (instance_name.AsCString()); 2597 if ((tmp_instance_name[0] == '[') 2598 && (tmp_instance_name[instance_name.GetLength() - 1] == ']')) 2599 tmp_instance_name = tmp_instance_name.substr (1, instance_name.GetLength() - 2); 2600 ConstString new_name (tmp_instance_name.c_str()); 2601 2602 BroadcastPromptChange (new_name, m_prompt.c_str()); 2603 } 2604 } 2605 else if (var_name == GetFrameFormatName()) 2606 { 2607 UserSettingsController::UpdateStringVariable (op, m_frame_format, value, err); 2608 } 2609 else if (var_name == GetThreadFormatName()) 2610 { 2611 UserSettingsController::UpdateStringVariable (op, m_thread_format, value, err); 2612 } 2613 else if (var_name == ScriptLangVarName()) 2614 { 2615 bool success; 2616 m_script_lang = Args::StringToScriptLanguage (value, eScriptLanguageDefault, 2617 &success); 2618 } 2619 else if (var_name == UseExternalEditorVarName ()) 2620 { 2621 UserSettingsController::UpdateBooleanVariable (op, m_use_external_editor, value, false, err); 2622 } 2623 else if (var_name == AutoConfirmName ()) 2624 { 2625 UserSettingsController::UpdateBooleanVariable (op, m_auto_confirm_on, value, false, err); 2626 } 2627 else if (var_name == StopSourceContextBeforeName ()) 2628 { 2629 uint32_t new_value = Args::StringToUInt32(value, UINT32_MAX, 10, NULL); 2630 if (new_value != UINT32_MAX) 2631 m_stop_source_before_count = new_value; 2632 else 2633 err.SetErrorStringWithFormat("invalid unsigned string value '%s' for the '%s' setting", value, StopSourceContextAfterName ().GetCString()); 2634 } 2635 else if (var_name == StopSourceContextAfterName ()) 2636 { 2637 uint32_t new_value = Args::StringToUInt32(value, UINT32_MAX, 10, NULL); 2638 if (new_value != UINT32_MAX) 2639 m_stop_source_after_count = new_value; 2640 else 2641 err.SetErrorStringWithFormat("invalid unsigned string value '%s' for the '%s' setting", value, StopSourceContextBeforeName ().GetCString()); 2642 } 2643 else if (var_name == StopDisassemblyCountName ()) 2644 { 2645 uint32_t new_value = Args::StringToUInt32(value, UINT32_MAX, 10, NULL); 2646 if (new_value != UINT32_MAX) 2647 m_stop_disassembly_count = new_value; 2648 else 2649 err.SetErrorStringWithFormat("invalid unsigned string value '%s' for the '%s' setting", value, StopDisassemblyCountName ().GetCString()); 2650 } 2651 else if (var_name == StopDisassemblyDisplayName ()) 2652 { 2653 int new_value; 2654 UserSettingsController::UpdateEnumVariable (g_show_disassembly_enum_values, &new_value, value, err); 2655 if (err.Success()) 2656 m_stop_disassembly_display = (StopDisassemblyType)new_value; 2657 } 2658 } 2659 2660 bool 2661 DebuggerInstanceSettings::GetInstanceSettingsValue (const SettingEntry &entry, 2662 const ConstString &var_name, 2663 StringList &value, 2664 Error *err) 2665 { 2666 if (var_name == PromptVarName()) 2667 { 2668 value.AppendString (m_prompt.c_str(), m_prompt.size()); 2669 2670 } 2671 else if (var_name == ScriptLangVarName()) 2672 { 2673 value.AppendString (ScriptInterpreter::LanguageToString (m_script_lang).c_str()); 2674 } 2675 else if (var_name == TermWidthVarName()) 2676 { 2677 StreamString width_str; 2678 width_str.Printf ("%u", m_term_width); 2679 value.AppendString (width_str.GetData()); 2680 } 2681 else if (var_name == GetFrameFormatName ()) 2682 { 2683 value.AppendString(m_frame_format.c_str(), m_frame_format.size()); 2684 } 2685 else if (var_name == GetThreadFormatName ()) 2686 { 2687 value.AppendString(m_thread_format.c_str(), m_thread_format.size()); 2688 } 2689 else if (var_name == UseExternalEditorVarName()) 2690 { 2691 if (m_use_external_editor) 2692 value.AppendString ("true"); 2693 else 2694 value.AppendString ("false"); 2695 } 2696 else if (var_name == AutoConfirmName()) 2697 { 2698 if (m_auto_confirm_on) 2699 value.AppendString ("true"); 2700 else 2701 value.AppendString ("false"); 2702 } 2703 else if (var_name == StopSourceContextAfterName ()) 2704 { 2705 StreamString strm; 2706 strm.Printf ("%u", m_stop_source_before_count); 2707 value.AppendString (strm.GetData()); 2708 } 2709 else if (var_name == StopSourceContextBeforeName ()) 2710 { 2711 StreamString strm; 2712 strm.Printf ("%u", m_stop_source_after_count); 2713 value.AppendString (strm.GetData()); 2714 } 2715 else if (var_name == StopDisassemblyCountName ()) 2716 { 2717 StreamString strm; 2718 strm.Printf ("%u", m_stop_disassembly_count); 2719 value.AppendString (strm.GetData()); 2720 } 2721 else if (var_name == StopDisassemblyDisplayName ()) 2722 { 2723 if (m_stop_disassembly_display >= eStopDisassemblyTypeNever && m_stop_disassembly_display <= eStopDisassemblyTypeAlways) 2724 value.AppendString (g_show_disassembly_enum_values[m_stop_disassembly_display].string_value); 2725 else 2726 value.AppendString ("<invalid>"); 2727 } 2728 else 2729 { 2730 if (err) 2731 err->SetErrorStringWithFormat ("unrecognized variable name '%s'", var_name.AsCString()); 2732 return false; 2733 } 2734 return true; 2735 } 2736 2737 void 2738 DebuggerInstanceSettings::CopyInstanceSettings (const InstanceSettingsSP &new_settings, 2739 bool pending) 2740 { 2741 if (new_settings.get() == NULL) 2742 return; 2743 2744 DebuggerInstanceSettings *new_debugger_settings = (DebuggerInstanceSettings *) new_settings.get(); 2745 2746 m_prompt = new_debugger_settings->m_prompt; 2747 if (!pending) 2748 { 2749 // 'instance_name' is actually (probably) in the form '[<instance_name>]'; if so, we need to 2750 // strip off the brackets before passing it to BroadcastPromptChange. 2751 2752 std::string tmp_instance_name (m_instance_name.AsCString()); 2753 if ((tmp_instance_name[0] == '[') 2754 && (tmp_instance_name[m_instance_name.GetLength() - 1] == ']')) 2755 tmp_instance_name = tmp_instance_name.substr (1, m_instance_name.GetLength() - 2); 2756 ConstString new_name (tmp_instance_name.c_str()); 2757 2758 BroadcastPromptChange (new_name, m_prompt.c_str()); 2759 } 2760 m_frame_format = new_debugger_settings->m_frame_format; 2761 m_thread_format = new_debugger_settings->m_thread_format; 2762 m_term_width = new_debugger_settings->m_term_width; 2763 m_script_lang = new_debugger_settings->m_script_lang; 2764 m_use_external_editor = new_debugger_settings->m_use_external_editor; 2765 m_auto_confirm_on = new_debugger_settings->m_auto_confirm_on; 2766 } 2767 2768 2769 bool 2770 DebuggerInstanceSettings::BroadcastPromptChange (const ConstString &instance_name, const char *new_prompt) 2771 { 2772 std::string tmp_prompt; 2773 2774 if (new_prompt != NULL) 2775 { 2776 tmp_prompt = new_prompt ; 2777 int len = tmp_prompt.size(); 2778 if (len > 1 2779 && (tmp_prompt[0] == '\'' || tmp_prompt[0] == '"') 2780 && (tmp_prompt[len-1] == tmp_prompt[0])) 2781 { 2782 tmp_prompt = tmp_prompt.substr(1,len-2); 2783 } 2784 len = tmp_prompt.size(); 2785 if (tmp_prompt[len-1] != ' ') 2786 tmp_prompt.append(" "); 2787 } 2788 EventSP new_event_sp; 2789 new_event_sp.reset (new Event(CommandInterpreter::eBroadcastBitResetPrompt, 2790 new EventDataBytes (tmp_prompt.c_str()))); 2791 2792 if (instance_name.GetLength() != 0) 2793 { 2794 // Set prompt for a particular instance. 2795 Debugger *dbg = Debugger::FindDebuggerWithInstanceName (instance_name).get(); 2796 if (dbg != NULL) 2797 { 2798 dbg->GetCommandInterpreter().BroadcastEvent (new_event_sp); 2799 } 2800 } 2801 2802 return true; 2803 } 2804 2805 const ConstString 2806 DebuggerInstanceSettings::CreateInstanceName () 2807 { 2808 static int instance_count = 1; 2809 StreamString sstr; 2810 2811 sstr.Printf ("debugger_%d", instance_count); 2812 ++instance_count; 2813 2814 const ConstString ret_val (sstr.GetData()); 2815 2816 return ret_val; 2817 } 2818 2819 2820 //-------------------------------------------------- 2821 // SettingsController Variable Tables 2822 //-------------------------------------------------- 2823 2824 2825 SettingEntry 2826 Debugger::SettingsController::global_settings_table[] = 2827 { 2828 //{ "var-name", var-type, "default", enum-table, init'd, hidden, "help-text"}, 2829 // The Debugger level global table should always be empty; all Debugger settable variables should be instance 2830 // variables. 2831 { NULL, eSetVarTypeNone, NULL, NULL, 0, 0, NULL } 2832 }; 2833 2834 #define MODULE_WITH_FUNC "{ ${module.file.basename}{`${function.name}${function.pc-offset}}}" 2835 #define FILE_AND_LINE "{ at ${line.file.basename}:${line.number}}" 2836 2837 #define DEFAULT_THREAD_FORMAT "thread #${thread.index}: tid = ${thread.id}"\ 2838 "{, ${frame.pc}}"\ 2839 MODULE_WITH_FUNC\ 2840 FILE_AND_LINE\ 2841 "{, stop reason = ${thread.stop-reason}}"\ 2842 "{\\nReturn value: ${thread.return-value}}"\ 2843 "\\n" 2844 2845 //#define DEFAULT_THREAD_FORMAT "thread #${thread.index}: tid = ${thread.id}"\ 2846 // "{, ${frame.pc}}"\ 2847 // MODULE_WITH_FUNC\ 2848 // FILE_AND_LINE\ 2849 // "{, stop reason = ${thread.stop-reason}}"\ 2850 // "{, name = ${thread.name}}"\ 2851 // "{, queue = ${thread.queue}}"\ 2852 // "\\n" 2853 2854 #define DEFAULT_FRAME_FORMAT "frame #${frame.index}: ${frame.pc}"\ 2855 MODULE_WITH_FUNC\ 2856 FILE_AND_LINE\ 2857 "\\n" 2858 2859 SettingEntry 2860 Debugger::SettingsController::instance_settings_table[] = 2861 { 2862 // NAME Setting variable type Default Enum Init'd Hidden Help 2863 // ======================= ======================= ====================== ==== ====== ====== ====================== 2864 { "frame-format", eSetVarTypeString, DEFAULT_FRAME_FORMAT, NULL, false, false, "The default frame format string to use when displaying thread information." }, 2865 { "prompt", eSetVarTypeString, "(lldb) ", NULL, false, false, "The debugger command line prompt displayed for the user." }, 2866 { "script-lang", eSetVarTypeString, "python", NULL, false, false, "The script language to be used for evaluating user-written scripts." }, 2867 { "term-width", eSetVarTypeInt, "80" , NULL, false, false, "The maximum number of columns to use for displaying text." }, 2868 { "thread-format", eSetVarTypeString, DEFAULT_THREAD_FORMAT, NULL, false, false, "The default thread format string to use when displaying thread information." }, 2869 { "use-external-editor", eSetVarTypeBoolean, "false", NULL, false, false, "Whether to use an external editor or not." }, 2870 { "auto-confirm", eSetVarTypeBoolean, "false", NULL, false, false, "If true all confirmation prompts will receive their default reply." }, 2871 { "stop-line-count-before",eSetVarTypeInt, "3", NULL, false, false, "The number of sources lines to display that come before the current source line when displaying a stopped context." }, 2872 { "stop-line-count-after", eSetVarTypeInt, "3", NULL, false, false, "The number of sources lines to display that come after the current source line when displaying a stopped context." }, 2873 { "stop-disassembly-count", eSetVarTypeInt, "0", NULL, false, false, "The number of disassembly lines to show when displaying a stopped context." }, 2874 { "stop-disassembly-display", eSetVarTypeEnum, "no-source", g_show_disassembly_enum_values, false, false, "Control when to display disassembly when displaying a stopped context." }, 2875 { NULL, eSetVarTypeNone, NULL, NULL, false, false, NULL } 2876 }; 2877