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