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