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