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