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