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