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