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