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/Core/Debugger.h" 13 14 #include <map> 15 16 #include "clang/AST/DeclCXX.h" 17 #include "clang/AST/Type.h" 18 #include "llvm/ADT/StringRef.h" 19 20 #include "lldb/lldb-private.h" 21 #include "lldb/Core/Module.h" 22 #include "lldb/Core/PluginManager.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/StreamFile.h" 28 #include "lldb/Core/StreamString.h" 29 #include "lldb/Core/StructuredData.h" 30 #include "lldb/Core/Timer.h" 31 #include "lldb/Core/ValueObject.h" 32 #include "lldb/Core/ValueObjectVariable.h" 33 #include "lldb/DataFormatters/DataVisualization.h" 34 #include "lldb/DataFormatters/FormatManager.h" 35 #include "lldb/DataFormatters/TypeSummary.h" 36 #include "lldb/Host/ConnectionFileDescriptor.h" 37 #include "lldb/Host/HostInfo.h" 38 #include "lldb/Host/Terminal.h" 39 #include "lldb/Host/ThreadLauncher.h" 40 #include "lldb/Interpreter/CommandInterpreter.h" 41 #include "lldb/Interpreter/OptionValueSInt64.h" 42 #include "lldb/Interpreter/OptionValueString.h" 43 #include "lldb/Symbol/ClangASTContext.h" 44 #include "lldb/Symbol/CompileUnit.h" 45 #include "lldb/Symbol/Function.h" 46 #include "lldb/Symbol/Symbol.h" 47 #include "lldb/Symbol/VariableList.h" 48 #include "lldb/Target/CPPLanguageRuntime.h" 49 #include "lldb/Target/ObjCLanguageRuntime.h" 50 #include "lldb/Target/TargetList.h" 51 #include "lldb/Target/Process.h" 52 #include "lldb/Target/RegisterContext.h" 53 #include "lldb/Target/SectionLoadList.h" 54 #include "lldb/Target/StopInfo.h" 55 #include "lldb/Target/Target.h" 56 #include "lldb/Target/Thread.h" 57 #include "lldb/Utility/AnsiTerminal.h" 58 59 #include "llvm/Support/DynamicLibrary.h" 60 61 using namespace lldb; 62 using namespace lldb_private; 63 64 65 static uint32_t g_shared_debugger_refcount = 0; 66 static lldb::user_id_t g_unique_id = 1; 67 static size_t g_debugger_event_thread_stack_bytes = 8 * 1024 * 1024; 68 69 #pragma mark Static Functions 70 71 static Mutex & 72 GetDebuggerListMutex () 73 { 74 static Mutex g_mutex(Mutex::eMutexTypeRecursive); 75 return g_mutex; 76 } 77 78 typedef std::vector<DebuggerSP> DebuggerList; 79 80 static DebuggerList & 81 GetDebuggerList() 82 { 83 // hide the static debugger list inside a singleton accessor to avoid 84 // global init constructors 85 static DebuggerList g_list; 86 return g_list; 87 } 88 89 OptionEnumValueElement 90 g_show_disassembly_enum_values[] = 91 { 92 { Debugger::eStopDisassemblyTypeNever, "never", "Never show disassembly when displaying a stop context."}, 93 { Debugger::eStopDisassemblyTypeNoSource, "no-source", "Show disassembly when there is no source information, or the source file is missing when displaying a stop context."}, 94 { Debugger::eStopDisassemblyTypeAlways, "always", "Always show disassembly when displaying a stop context."}, 95 { 0, NULL, NULL } 96 }; 97 98 OptionEnumValueElement 99 g_language_enumerators[] = 100 { 101 { eScriptLanguageNone, "none", "Disable scripting languages."}, 102 { eScriptLanguagePython, "python", "Select python as the default scripting language."}, 103 { eScriptLanguageDefault, "default", "Select the lldb default as the default scripting language."}, 104 { 0, NULL, NULL } 105 }; 106 107 #define MODULE_WITH_FUNC "{ ${module.file.basename}{`${function.name-with-args}${function.pc-offset}}}" 108 #define FILE_AND_LINE "{ at ${line.file.basename}:${line.number}}" 109 110 #define DEFAULT_THREAD_FORMAT "thread #${thread.index}: tid = ${thread.id%tid}"\ 111 "{, ${frame.pc}}"\ 112 MODULE_WITH_FUNC\ 113 FILE_AND_LINE\ 114 "{, name = '${thread.name}'}"\ 115 "{, queue = '${thread.queue}'}"\ 116 "{, activity = '${thread.info.activity.name}'}" \ 117 "{, ${thread.info.trace_messages} messages}" \ 118 "{, stop reason = ${thread.stop-reason}}"\ 119 "{\\nReturn value: ${thread.return-value}}"\ 120 "{\\nCompleted expression: ${thread.completed-expression}}"\ 121 "\\n" 122 123 #define DEFAULT_FRAME_FORMAT "frame #${frame.index}: ${frame.pc}"\ 124 MODULE_WITH_FUNC\ 125 FILE_AND_LINE\ 126 "\\n" 127 128 #define DEFAULT_DISASSEMBLY_FORMAT "${current-pc-arrow}${addr-file-or-load}{ <${function.name-without-args}${function.concrete-only-addr-offset-no-padding}>}: " 129 130 static PropertyDefinition 131 g_properties[] = 132 { 133 { "auto-confirm", OptionValue::eTypeBoolean, true, false, NULL, NULL, "If true all confirmation prompts will receive their default reply." }, 134 { "disassembly-format", OptionValue::eTypeString , true, 0 , DEFAULT_DISASSEMBLY_FORMAT, NULL, "The default disassembly format string to use when disassembling instruction sequences." }, 135 { "frame-format", OptionValue::eTypeString , true, 0 , DEFAULT_FRAME_FORMAT, NULL, "The default frame format string to use when displaying stack frame information for threads." }, 136 { "notify-void", OptionValue::eTypeBoolean, true, false, NULL, NULL, "Notify the user explicitly if an expression returns void (default: false)." }, 137 { "prompt", OptionValue::eTypeString , true, OptionValueString::eOptionEncodeCharacterEscapeSequences, "(lldb) ", NULL, "The debugger command line prompt displayed for the user." }, 138 { "script-lang", OptionValue::eTypeEnum , true, eScriptLanguagePython, NULL, g_language_enumerators, "The script language to be used for evaluating user-written scripts." }, 139 { "stop-disassembly-count", OptionValue::eTypeSInt64 , true, 4 , NULL, NULL, "The number of disassembly lines to show when displaying a stopped context." }, 140 { "stop-disassembly-display", OptionValue::eTypeEnum , true, Debugger::eStopDisassemblyTypeNoSource, NULL, g_show_disassembly_enum_values, "Control when to display disassembly when displaying a stopped context." }, 141 { "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." }, 142 { "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." }, 143 { "term-width", OptionValue::eTypeSInt64 , true, 80 , NULL, NULL, "The maximum number of columns to use for displaying text." }, 144 { "thread-format", OptionValue::eTypeString , true, 0 , DEFAULT_THREAD_FORMAT, NULL, "The default thread format string to use when displaying thread information." }, 145 { "use-external-editor", OptionValue::eTypeBoolean, true, false, NULL, NULL, "Whether to use an external editor or not." }, 146 { "use-color", OptionValue::eTypeBoolean, true, true , NULL, NULL, "Whether to use Ansi color codes or not." }, 147 { "auto-one-line-summaries", OptionValue::eTypeBoolean, true, true, NULL, NULL, "If true, LLDB will automatically display small structs in one-liner format (default: true)." }, 148 { "escape-non-printables", OptionValue::eTypeBoolean, true, true, NULL, NULL, "If true, LLDB will automatically escape non-printable and escape characters when formatting strings." }, 149 150 { NULL, OptionValue::eTypeInvalid, true, 0 , NULL, NULL, NULL } 151 }; 152 153 enum 154 { 155 ePropertyAutoConfirm = 0, 156 ePropertyDisassemblyFormat, 157 ePropertyFrameFormat, 158 ePropertyNotiftVoid, 159 ePropertyPrompt, 160 ePropertyScriptLanguage, 161 ePropertyStopDisassemblyCount, 162 ePropertyStopDisassemblyDisplay, 163 ePropertyStopLineCountAfter, 164 ePropertyStopLineCountBefore, 165 ePropertyTerminalWidth, 166 ePropertyThreadFormat, 167 ePropertyUseExternalEditor, 168 ePropertyUseColor, 169 ePropertyAutoOneLineSummaries, 170 ePropertyEscapeNonPrintables 171 }; 172 173 Debugger::LoadPluginCallbackType Debugger::g_load_plugin_callback = NULL; 174 175 Error 176 Debugger::SetPropertyValue (const ExecutionContext *exe_ctx, 177 VarSetOperationType op, 178 const char *property_path, 179 const char *value) 180 { 181 bool is_load_script = strcmp(property_path,"target.load-script-from-symbol-file") == 0; 182 bool is_escape_non_printables = strcmp(property_path, "escape-non-printables") == 0; 183 TargetSP target_sp; 184 LoadScriptFromSymFile load_script_old_value; 185 if (is_load_script && exe_ctx->GetTargetSP()) 186 { 187 target_sp = exe_ctx->GetTargetSP(); 188 load_script_old_value = target_sp->TargetProperties::GetLoadScriptFromSymbolFile(); 189 } 190 Error error (Properties::SetPropertyValue (exe_ctx, op, property_path, value)); 191 if (error.Success()) 192 { 193 // FIXME it would be nice to have "on-change" callbacks for properties 194 if (strcmp(property_path, g_properties[ePropertyPrompt].name) == 0) 195 { 196 const char *new_prompt = GetPrompt(); 197 std::string str = lldb_utility::ansi::FormatAnsiTerminalCodes (new_prompt, GetUseColor()); 198 if (str.length()) 199 new_prompt = str.c_str(); 200 GetCommandInterpreter().UpdatePrompt(new_prompt); 201 EventSP prompt_change_event_sp (new Event(CommandInterpreter::eBroadcastBitResetPrompt, new EventDataBytes (new_prompt))); 202 GetCommandInterpreter().BroadcastEvent (prompt_change_event_sp); 203 } 204 else if (strcmp(property_path, g_properties[ePropertyUseColor].name) == 0) 205 { 206 // use-color changed. Ping the prompt so it can reset the ansi terminal codes. 207 SetPrompt (GetPrompt()); 208 } 209 else if (is_load_script && target_sp && load_script_old_value == eLoadScriptFromSymFileWarn) 210 { 211 if (target_sp->TargetProperties::GetLoadScriptFromSymbolFile() == eLoadScriptFromSymFileTrue) 212 { 213 std::list<Error> errors; 214 StreamString feedback_stream; 215 if (!target_sp->LoadScriptingResources(errors,&feedback_stream)) 216 { 217 StreamFileSP stream_sp (GetErrorFile()); 218 if (stream_sp) 219 { 220 for (auto error : errors) 221 { 222 stream_sp->Printf("%s\n",error.AsCString()); 223 } 224 if (feedback_stream.GetSize()) 225 stream_sp->Printf("%s",feedback_stream.GetData()); 226 } 227 } 228 } 229 } 230 else if (is_escape_non_printables) 231 { 232 DataVisualization::ForceUpdate(); 233 } 234 } 235 return error; 236 } 237 238 bool 239 Debugger::GetAutoConfirm () const 240 { 241 const uint32_t idx = ePropertyAutoConfirm; 242 return m_collection_sp->GetPropertyAtIndexAsBoolean (NULL, idx, g_properties[idx].default_uint_value != 0); 243 } 244 245 const char * 246 Debugger::GetDisassemblyFormat() const 247 { 248 const uint32_t idx = ePropertyDisassemblyFormat; 249 return m_collection_sp->GetPropertyAtIndexAsString (NULL, idx, g_properties[idx].default_cstr_value); 250 } 251 252 const char * 253 Debugger::GetFrameFormat() const 254 { 255 const uint32_t idx = ePropertyFrameFormat; 256 return m_collection_sp->GetPropertyAtIndexAsString (NULL, idx, g_properties[idx].default_cstr_value); 257 } 258 259 bool 260 Debugger::GetNotifyVoid () const 261 { 262 const uint32_t idx = ePropertyNotiftVoid; 263 return m_collection_sp->GetPropertyAtIndexAsBoolean (NULL, idx, g_properties[idx].default_uint_value != 0); 264 } 265 266 const char * 267 Debugger::GetPrompt() const 268 { 269 const uint32_t idx = ePropertyPrompt; 270 return m_collection_sp->GetPropertyAtIndexAsString (NULL, idx, g_properties[idx].default_cstr_value); 271 } 272 273 void 274 Debugger::SetPrompt(const char *p) 275 { 276 const uint32_t idx = ePropertyPrompt; 277 m_collection_sp->SetPropertyAtIndexAsString (NULL, idx, p); 278 const char *new_prompt = GetPrompt(); 279 std::string str = lldb_utility::ansi::FormatAnsiTerminalCodes (new_prompt, GetUseColor()); 280 if (str.length()) 281 new_prompt = str.c_str(); 282 GetCommandInterpreter().UpdatePrompt(new_prompt); 283 } 284 285 const char * 286 Debugger::GetThreadFormat() const 287 { 288 const uint32_t idx = ePropertyThreadFormat; 289 return m_collection_sp->GetPropertyAtIndexAsString (NULL, idx, g_properties[idx].default_cstr_value); 290 } 291 292 lldb::ScriptLanguage 293 Debugger::GetScriptLanguage() const 294 { 295 const uint32_t idx = ePropertyScriptLanguage; 296 return (lldb::ScriptLanguage)m_collection_sp->GetPropertyAtIndexAsEnumeration (NULL, idx, g_properties[idx].default_uint_value); 297 } 298 299 bool 300 Debugger::SetScriptLanguage (lldb::ScriptLanguage script_lang) 301 { 302 const uint32_t idx = ePropertyScriptLanguage; 303 return m_collection_sp->SetPropertyAtIndexAsEnumeration (NULL, idx, script_lang); 304 } 305 306 uint32_t 307 Debugger::GetTerminalWidth () const 308 { 309 const uint32_t idx = ePropertyTerminalWidth; 310 return m_collection_sp->GetPropertyAtIndexAsSInt64 (NULL, idx, g_properties[idx].default_uint_value); 311 } 312 313 bool 314 Debugger::SetTerminalWidth (uint32_t term_width) 315 { 316 const uint32_t idx = ePropertyTerminalWidth; 317 return m_collection_sp->SetPropertyAtIndexAsSInt64 (NULL, idx, term_width); 318 } 319 320 bool 321 Debugger::GetUseExternalEditor () const 322 { 323 const uint32_t idx = ePropertyUseExternalEditor; 324 return m_collection_sp->GetPropertyAtIndexAsBoolean (NULL, idx, g_properties[idx].default_uint_value != 0); 325 } 326 327 bool 328 Debugger::SetUseExternalEditor (bool b) 329 { 330 const uint32_t idx = ePropertyUseExternalEditor; 331 return m_collection_sp->SetPropertyAtIndexAsBoolean (NULL, idx, b); 332 } 333 334 bool 335 Debugger::GetUseColor () const 336 { 337 const uint32_t idx = ePropertyUseColor; 338 return m_collection_sp->GetPropertyAtIndexAsBoolean (NULL, idx, g_properties[idx].default_uint_value != 0); 339 } 340 341 bool 342 Debugger::SetUseColor (bool b) 343 { 344 const uint32_t idx = ePropertyUseColor; 345 bool ret = m_collection_sp->SetPropertyAtIndexAsBoolean (NULL, idx, b); 346 SetPrompt (GetPrompt()); 347 return ret; 348 } 349 350 uint32_t 351 Debugger::GetStopSourceLineCount (bool before) const 352 { 353 const uint32_t idx = before ? ePropertyStopLineCountBefore : ePropertyStopLineCountAfter; 354 return m_collection_sp->GetPropertyAtIndexAsSInt64 (NULL, idx, g_properties[idx].default_uint_value); 355 } 356 357 Debugger::StopDisassemblyType 358 Debugger::GetStopDisassemblyDisplay () const 359 { 360 const uint32_t idx = ePropertyStopDisassemblyDisplay; 361 return (Debugger::StopDisassemblyType)m_collection_sp->GetPropertyAtIndexAsEnumeration (NULL, idx, g_properties[idx].default_uint_value); 362 } 363 364 uint32_t 365 Debugger::GetDisassemblyLineCount () const 366 { 367 const uint32_t idx = ePropertyStopDisassemblyCount; 368 return m_collection_sp->GetPropertyAtIndexAsSInt64 (NULL, idx, g_properties[idx].default_uint_value); 369 } 370 371 bool 372 Debugger::GetAutoOneLineSummaries () const 373 { 374 const uint32_t idx = ePropertyAutoOneLineSummaries; 375 return m_collection_sp->GetPropertyAtIndexAsBoolean (NULL, idx, true); 376 } 377 378 bool 379 Debugger::GetEscapeNonPrintables () const 380 { 381 const uint32_t idx = ePropertyEscapeNonPrintables; 382 return m_collection_sp->GetPropertyAtIndexAsBoolean (NULL, idx, true); 383 } 384 385 #pragma mark Debugger 386 387 //const DebuggerPropertiesSP & 388 //Debugger::GetSettings() const 389 //{ 390 // return m_properties_sp; 391 //} 392 // 393 394 int 395 Debugger::TestDebuggerRefCount () 396 { 397 return g_shared_debugger_refcount; 398 } 399 400 void 401 Debugger::Initialize (LoadPluginCallbackType load_plugin_callback) 402 { 403 g_load_plugin_callback = load_plugin_callback; 404 if (g_shared_debugger_refcount++ == 0) 405 lldb_private::Initialize(); 406 } 407 408 void 409 Debugger::Terminate () 410 { 411 if (g_shared_debugger_refcount > 0) 412 { 413 g_shared_debugger_refcount--; 414 if (g_shared_debugger_refcount == 0) 415 { 416 lldb_private::WillTerminate(); 417 lldb_private::Terminate(); 418 419 // Clear our master list of debugger objects 420 Mutex::Locker locker (GetDebuggerListMutex ()); 421 GetDebuggerList().clear(); 422 } 423 } 424 } 425 426 void 427 Debugger::SettingsInitialize () 428 { 429 Target::SettingsInitialize (); 430 } 431 432 void 433 Debugger::SettingsTerminate () 434 { 435 Target::SettingsTerminate (); 436 } 437 438 bool 439 Debugger::LoadPlugin (const FileSpec& spec, Error& error) 440 { 441 if (g_load_plugin_callback) 442 { 443 llvm::sys::DynamicLibrary dynlib = g_load_plugin_callback (shared_from_this(), spec, error); 444 if (dynlib.isValid()) 445 { 446 m_loaded_plugins.push_back(dynlib); 447 return true; 448 } 449 } 450 else 451 { 452 // The g_load_plugin_callback is registered in SBDebugger::Initialize() 453 // and if the public API layer isn't available (code is linking against 454 // all of the internal LLDB static libraries), then we can't load plugins 455 error.SetErrorString("Public API layer is not available"); 456 } 457 return false; 458 } 459 460 static FileSpec::EnumerateDirectoryResult 461 LoadPluginCallback 462 ( 463 void *baton, 464 FileSpec::FileType file_type, 465 const FileSpec &file_spec 466 ) 467 { 468 Error error; 469 470 static ConstString g_dylibext("dylib"); 471 static ConstString g_solibext("so"); 472 473 if (!baton) 474 return FileSpec::eEnumerateDirectoryResultQuit; 475 476 Debugger *debugger = (Debugger*)baton; 477 478 // If we have a regular file, a symbolic link or unknown file type, try 479 // and process the file. We must handle unknown as sometimes the directory 480 // enumeration might be enumerating a file system that doesn't have correct 481 // file type information. 482 if (file_type == FileSpec::eFileTypeRegular || 483 file_type == FileSpec::eFileTypeSymbolicLink || 484 file_type == FileSpec::eFileTypeUnknown ) 485 { 486 FileSpec plugin_file_spec (file_spec); 487 plugin_file_spec.ResolvePath (); 488 489 if (plugin_file_spec.GetFileNameExtension() != g_dylibext && 490 plugin_file_spec.GetFileNameExtension() != g_solibext) 491 { 492 return FileSpec::eEnumerateDirectoryResultNext; 493 } 494 495 Error plugin_load_error; 496 debugger->LoadPlugin (plugin_file_spec, plugin_load_error); 497 498 return FileSpec::eEnumerateDirectoryResultNext; 499 } 500 501 else if (file_type == FileSpec::eFileTypeUnknown || 502 file_type == FileSpec::eFileTypeDirectory || 503 file_type == FileSpec::eFileTypeSymbolicLink ) 504 { 505 // Try and recurse into anything that a directory or symbolic link. 506 // We must also do this for unknown as sometimes the directory enumeration 507 // might be enumerating a file system that doesn't have correct file type 508 // information. 509 return FileSpec::eEnumerateDirectoryResultEnter; 510 } 511 512 return FileSpec::eEnumerateDirectoryResultNext; 513 } 514 515 void 516 Debugger::InstanceInitialize () 517 { 518 FileSpec dir_spec; 519 const bool find_directories = true; 520 const bool find_files = true; 521 const bool find_other = true; 522 char dir_path[PATH_MAX]; 523 if (HostInfo::GetLLDBPath(ePathTypeLLDBSystemPlugins, dir_spec)) 524 { 525 if (dir_spec.Exists() && dir_spec.GetPath(dir_path, sizeof(dir_path))) 526 { 527 FileSpec::EnumerateDirectory (dir_path, 528 find_directories, 529 find_files, 530 find_other, 531 LoadPluginCallback, 532 this); 533 } 534 } 535 536 if (HostInfo::GetLLDBPath(ePathTypeLLDBUserPlugins, dir_spec)) 537 { 538 if (dir_spec.Exists() && dir_spec.GetPath(dir_path, sizeof(dir_path))) 539 { 540 FileSpec::EnumerateDirectory (dir_path, 541 find_directories, 542 find_files, 543 find_other, 544 LoadPluginCallback, 545 this); 546 } 547 } 548 549 PluginManager::DebuggerInitialize (*this); 550 } 551 552 DebuggerSP 553 Debugger::CreateInstance (lldb::LogOutputCallback log_callback, void *baton) 554 { 555 DebuggerSP debugger_sp (new Debugger(log_callback, baton)); 556 if (g_shared_debugger_refcount > 0) 557 { 558 Mutex::Locker locker (GetDebuggerListMutex ()); 559 GetDebuggerList().push_back(debugger_sp); 560 } 561 debugger_sp->InstanceInitialize (); 562 return debugger_sp; 563 } 564 565 void 566 Debugger::Destroy (DebuggerSP &debugger_sp) 567 { 568 if (debugger_sp.get() == NULL) 569 return; 570 571 debugger_sp->Clear(); 572 573 if (g_shared_debugger_refcount > 0) 574 { 575 Mutex::Locker locker (GetDebuggerListMutex ()); 576 DebuggerList &debugger_list = GetDebuggerList (); 577 DebuggerList::iterator pos, end = debugger_list.end(); 578 for (pos = debugger_list.begin (); pos != end; ++pos) 579 { 580 if ((*pos).get() == debugger_sp.get()) 581 { 582 debugger_list.erase (pos); 583 return; 584 } 585 } 586 } 587 } 588 589 DebuggerSP 590 Debugger::FindDebuggerWithInstanceName (const ConstString &instance_name) 591 { 592 DebuggerSP debugger_sp; 593 if (g_shared_debugger_refcount > 0) 594 { 595 Mutex::Locker locker (GetDebuggerListMutex ()); 596 DebuggerList &debugger_list = GetDebuggerList(); 597 DebuggerList::iterator pos, end = debugger_list.end(); 598 599 for (pos = debugger_list.begin(); pos != end; ++pos) 600 { 601 if ((*pos).get()->m_instance_name == instance_name) 602 { 603 debugger_sp = *pos; 604 break; 605 } 606 } 607 } 608 return debugger_sp; 609 } 610 611 TargetSP 612 Debugger::FindTargetWithProcessID (lldb::pid_t pid) 613 { 614 TargetSP target_sp; 615 if (g_shared_debugger_refcount > 0) 616 { 617 Mutex::Locker locker (GetDebuggerListMutex ()); 618 DebuggerList &debugger_list = GetDebuggerList(); 619 DebuggerList::iterator pos, end = debugger_list.end(); 620 for (pos = debugger_list.begin(); pos != end; ++pos) 621 { 622 target_sp = (*pos)->GetTargetList().FindTargetWithProcessID (pid); 623 if (target_sp) 624 break; 625 } 626 } 627 return target_sp; 628 } 629 630 TargetSP 631 Debugger::FindTargetWithProcess (Process *process) 632 { 633 TargetSP target_sp; 634 if (g_shared_debugger_refcount > 0) 635 { 636 Mutex::Locker locker (GetDebuggerListMutex ()); 637 DebuggerList &debugger_list = GetDebuggerList(); 638 DebuggerList::iterator pos, end = debugger_list.end(); 639 for (pos = debugger_list.begin(); pos != end; ++pos) 640 { 641 target_sp = (*pos)->GetTargetList().FindTargetWithProcess (process); 642 if (target_sp) 643 break; 644 } 645 } 646 return target_sp; 647 } 648 649 Debugger::Debugger(lldb::LogOutputCallback log_callback, void *baton) : 650 UserID(g_unique_id++), 651 Properties(OptionValuePropertiesSP(new OptionValueProperties())), 652 m_input_file_sp(new StreamFile(stdin, false)), 653 m_output_file_sp(new StreamFile(stdout, false)), 654 m_error_file_sp(new StreamFile(stderr, false)), 655 m_terminal_state(), 656 m_target_list(*this), 657 m_platform_list(), 658 m_listener("lldb.Debugger"), 659 m_source_manager_ap(), 660 m_source_file_cache(), 661 m_command_interpreter_ap(new CommandInterpreter(*this, eScriptLanguageDefault, false)), 662 m_input_reader_stack(), 663 m_instance_name(), 664 m_loaded_plugins(), 665 m_event_handler_thread (), 666 m_io_handler_thread (), 667 m_sync_broadcaster (NULL, "lldb.debugger.sync") 668 { 669 char instance_cstr[256]; 670 snprintf(instance_cstr, sizeof(instance_cstr), "debugger_%d", (int)GetID()); 671 m_instance_name.SetCString(instance_cstr); 672 if (log_callback) 673 m_log_callback_stream_sp.reset (new StreamCallback (log_callback, baton)); 674 m_command_interpreter_ap->Initialize (); 675 // Always add our default platform to the platform list 676 PlatformSP default_platform_sp (Platform::GetHostPlatform()); 677 assert (default_platform_sp.get()); 678 m_platform_list.Append (default_platform_sp, true); 679 680 m_collection_sp->Initialize (g_properties); 681 m_collection_sp->AppendProperty (ConstString("target"), 682 ConstString("Settings specify to debugging targets."), 683 true, 684 Target::GetGlobalProperties()->GetValueProperties()); 685 if (m_command_interpreter_ap.get()) 686 { 687 m_collection_sp->AppendProperty (ConstString("interpreter"), 688 ConstString("Settings specify to the debugger's command interpreter."), 689 true, 690 m_command_interpreter_ap->GetValueProperties()); 691 } 692 OptionValueSInt64 *term_width = m_collection_sp->GetPropertyAtIndexAsOptionValueSInt64 (NULL, ePropertyTerminalWidth); 693 term_width->SetMinimumValue(10); 694 term_width->SetMaximumValue(1024); 695 696 // Turn off use-color if this is a dumb terminal. 697 const char *term = getenv ("TERM"); 698 if (term && !strcmp (term, "dumb")) 699 SetUseColor (false); 700 } 701 702 Debugger::~Debugger () 703 { 704 Clear(); 705 } 706 707 void 708 Debugger::Clear() 709 { 710 ClearIOHandlers(); 711 StopIOHandlerThread(); 712 StopEventHandlerThread(); 713 m_listener.Clear(); 714 int num_targets = m_target_list.GetNumTargets(); 715 for (int i = 0; i < num_targets; i++) 716 { 717 TargetSP target_sp (m_target_list.GetTargetAtIndex (i)); 718 if (target_sp) 719 { 720 ProcessSP process_sp (target_sp->GetProcessSP()); 721 if (process_sp) 722 process_sp->Finalize(); 723 target_sp->Destroy(); 724 } 725 } 726 BroadcasterManager::Clear (); 727 728 // Close the input file _before_ we close the input read communications class 729 // as it does NOT own the input file, our m_input_file does. 730 m_terminal_state.Clear(); 731 if (m_input_file_sp) 732 m_input_file_sp->GetFile().Close (); 733 734 m_command_interpreter_ap->Clear(); 735 } 736 737 bool 738 Debugger::GetCloseInputOnEOF () const 739 { 740 // return m_input_comm.GetCloseOnEOF(); 741 return false; 742 } 743 744 void 745 Debugger::SetCloseInputOnEOF (bool b) 746 { 747 // m_input_comm.SetCloseOnEOF(b); 748 } 749 750 bool 751 Debugger::GetAsyncExecution () 752 { 753 return !m_command_interpreter_ap->GetSynchronous(); 754 } 755 756 void 757 Debugger::SetAsyncExecution (bool async_execution) 758 { 759 m_command_interpreter_ap->SetSynchronous (!async_execution); 760 } 761 762 763 void 764 Debugger::SetInputFileHandle (FILE *fh, bool tranfer_ownership) 765 { 766 if (m_input_file_sp) 767 m_input_file_sp->GetFile().SetStream (fh, tranfer_ownership); 768 else 769 m_input_file_sp.reset (new StreamFile (fh, tranfer_ownership)); 770 771 File &in_file = m_input_file_sp->GetFile(); 772 if (in_file.IsValid() == false) 773 in_file.SetStream (stdin, true); 774 775 // Save away the terminal state if that is relevant, so that we can restore it in RestoreInputState. 776 SaveInputTerminalState (); 777 } 778 779 void 780 Debugger::SetOutputFileHandle (FILE *fh, bool tranfer_ownership) 781 { 782 if (m_output_file_sp) 783 m_output_file_sp->GetFile().SetStream (fh, tranfer_ownership); 784 else 785 m_output_file_sp.reset (new StreamFile (fh, tranfer_ownership)); 786 787 File &out_file = m_output_file_sp->GetFile(); 788 if (out_file.IsValid() == false) 789 out_file.SetStream (stdout, false); 790 791 // do not create the ScriptInterpreter just for setting the output file handle 792 // as the constructor will know how to do the right thing on its own 793 const bool can_create = false; 794 ScriptInterpreter* script_interpreter = GetCommandInterpreter().GetScriptInterpreter(can_create); 795 if (script_interpreter) 796 script_interpreter->ResetOutputFileHandle (fh); 797 } 798 799 void 800 Debugger::SetErrorFileHandle (FILE *fh, bool tranfer_ownership) 801 { 802 if (m_error_file_sp) 803 m_error_file_sp->GetFile().SetStream (fh, tranfer_ownership); 804 else 805 m_error_file_sp.reset (new StreamFile (fh, tranfer_ownership)); 806 807 File &err_file = m_error_file_sp->GetFile(); 808 if (err_file.IsValid() == false) 809 err_file.SetStream (stderr, false); 810 } 811 812 void 813 Debugger::SaveInputTerminalState () 814 { 815 if (m_input_file_sp) 816 { 817 File &in_file = m_input_file_sp->GetFile(); 818 if (in_file.GetDescriptor() != File::kInvalidDescriptor) 819 m_terminal_state.Save(in_file.GetDescriptor(), true); 820 } 821 } 822 823 void 824 Debugger::RestoreInputTerminalState () 825 { 826 m_terminal_state.Restore(); 827 } 828 829 ExecutionContext 830 Debugger::GetSelectedExecutionContext () 831 { 832 ExecutionContext exe_ctx; 833 TargetSP target_sp(GetSelectedTarget()); 834 exe_ctx.SetTargetSP (target_sp); 835 836 if (target_sp) 837 { 838 ProcessSP process_sp (target_sp->GetProcessSP()); 839 exe_ctx.SetProcessSP (process_sp); 840 if (process_sp && process_sp->IsRunning() == false) 841 { 842 ThreadSP thread_sp (process_sp->GetThreadList().GetSelectedThread()); 843 if (thread_sp) 844 { 845 exe_ctx.SetThreadSP (thread_sp); 846 exe_ctx.SetFrameSP (thread_sp->GetSelectedFrame()); 847 if (exe_ctx.GetFramePtr() == NULL) 848 exe_ctx.SetFrameSP (thread_sp->GetStackFrameAtIndex (0)); 849 } 850 } 851 } 852 return exe_ctx; 853 } 854 855 void 856 Debugger::DispatchInputInterrupt () 857 { 858 Mutex::Locker locker (m_input_reader_stack.GetMutex()); 859 IOHandlerSP reader_sp (m_input_reader_stack.Top()); 860 if (reader_sp) 861 reader_sp->Interrupt(); 862 } 863 864 void 865 Debugger::DispatchInputEndOfFile () 866 { 867 Mutex::Locker locker (m_input_reader_stack.GetMutex()); 868 IOHandlerSP reader_sp (m_input_reader_stack.Top()); 869 if (reader_sp) 870 reader_sp->GotEOF(); 871 } 872 873 void 874 Debugger::ClearIOHandlers () 875 { 876 // The bottom input reader should be the main debugger input reader. We do not want to close that one here. 877 Mutex::Locker locker (m_input_reader_stack.GetMutex()); 878 while (m_input_reader_stack.GetSize() > 1) 879 { 880 IOHandlerSP reader_sp (m_input_reader_stack.Top()); 881 if (reader_sp) 882 { 883 m_input_reader_stack.Pop(); 884 reader_sp->SetIsDone(true); 885 reader_sp->Cancel(); 886 } 887 } 888 } 889 890 void 891 Debugger::ExecuteIOHanders() 892 { 893 894 while (1) 895 { 896 IOHandlerSP reader_sp(m_input_reader_stack.Top()); 897 if (!reader_sp) 898 break; 899 900 reader_sp->Activate(); 901 reader_sp->Run(); 902 reader_sp->Deactivate(); 903 904 // Remove all input readers that are done from the top of the stack 905 while (1) 906 { 907 IOHandlerSP top_reader_sp = m_input_reader_stack.Top(); 908 if (top_reader_sp && top_reader_sp->GetIsDone()) 909 m_input_reader_stack.Pop(); 910 else 911 break; 912 } 913 } 914 ClearIOHandlers(); 915 } 916 917 bool 918 Debugger::IsTopIOHandler (const lldb::IOHandlerSP& reader_sp) 919 { 920 return m_input_reader_stack.IsTop (reader_sp); 921 } 922 923 924 ConstString 925 Debugger::GetTopIOHandlerControlSequence(char ch) 926 { 927 return m_input_reader_stack.GetTopIOHandlerControlSequence (ch); 928 } 929 930 void 931 Debugger::RunIOHandler (const IOHandlerSP& reader_sp) 932 { 933 PushIOHandler (reader_sp); 934 935 IOHandlerSP top_reader_sp = reader_sp; 936 while (top_reader_sp) 937 { 938 top_reader_sp->Activate(); 939 top_reader_sp->Run(); 940 top_reader_sp->Deactivate(); 941 942 if (top_reader_sp.get() == reader_sp.get()) 943 { 944 if (PopIOHandler (reader_sp)) 945 break; 946 } 947 948 while (1) 949 { 950 top_reader_sp = m_input_reader_stack.Top(); 951 if (top_reader_sp && top_reader_sp->GetIsDone()) 952 m_input_reader_stack.Pop(); 953 else 954 break; 955 } 956 } 957 } 958 959 void 960 Debugger::AdoptTopIOHandlerFilesIfInvalid (StreamFileSP &in, StreamFileSP &out, StreamFileSP &err) 961 { 962 // Before an IOHandler runs, it must have in/out/err streams. 963 // This function is called when one ore more of the streams 964 // are NULL. We use the top input reader's in/out/err streams, 965 // or fall back to the debugger file handles, or we fall back 966 // onto stdin/stdout/stderr as a last resort. 967 968 Mutex::Locker locker (m_input_reader_stack.GetMutex()); 969 IOHandlerSP top_reader_sp (m_input_reader_stack.Top()); 970 // If no STDIN has been set, then set it appropriately 971 if (!in) 972 { 973 if (top_reader_sp) 974 in = top_reader_sp->GetInputStreamFile(); 975 else 976 in = GetInputFile(); 977 978 // If there is nothing, use stdin 979 if (!in) 980 in = StreamFileSP(new StreamFile(stdin, false)); 981 } 982 // If no STDOUT has been set, then set it appropriately 983 if (!out) 984 { 985 if (top_reader_sp) 986 out = top_reader_sp->GetOutputStreamFile(); 987 else 988 out = GetOutputFile(); 989 990 // If there is nothing, use stdout 991 if (!out) 992 out = StreamFileSP(new StreamFile(stdout, false)); 993 } 994 // If no STDERR has been set, then set it appropriately 995 if (!err) 996 { 997 if (top_reader_sp) 998 err = top_reader_sp->GetErrorStreamFile(); 999 else 1000 err = GetErrorFile(); 1001 1002 // If there is nothing, use stderr 1003 if (!err) 1004 err = StreamFileSP(new StreamFile(stdout, false)); 1005 1006 } 1007 } 1008 1009 void 1010 Debugger::PushIOHandler (const IOHandlerSP& reader_sp) 1011 { 1012 if (!reader_sp) 1013 return; 1014 1015 // Got the current top input reader... 1016 IOHandlerSP top_reader_sp (m_input_reader_stack.Top()); 1017 1018 // Don't push the same IO handler twice... 1019 if (reader_sp.get() != top_reader_sp.get()) 1020 { 1021 // Push our new input reader 1022 m_input_reader_stack.Push (reader_sp); 1023 1024 // Interrupt the top input reader to it will exit its Run() function 1025 // and let this new input reader take over 1026 if (top_reader_sp) 1027 top_reader_sp->Deactivate(); 1028 } 1029 } 1030 1031 bool 1032 Debugger::PopIOHandler (const IOHandlerSP& pop_reader_sp) 1033 { 1034 bool result = false; 1035 1036 Mutex::Locker locker (m_input_reader_stack.GetMutex()); 1037 1038 // The reader on the stop of the stack is done, so let the next 1039 // read on the stack refresh its prompt and if there is one... 1040 if (!m_input_reader_stack.IsEmpty()) 1041 { 1042 IOHandlerSP reader_sp(m_input_reader_stack.Top()); 1043 1044 if (!pop_reader_sp || pop_reader_sp.get() == reader_sp.get()) 1045 { 1046 reader_sp->Deactivate(); 1047 reader_sp->Cancel(); 1048 m_input_reader_stack.Pop (); 1049 1050 reader_sp = m_input_reader_stack.Top(); 1051 if (reader_sp) 1052 reader_sp->Activate(); 1053 1054 result = true; 1055 } 1056 } 1057 return result; 1058 } 1059 1060 bool 1061 Debugger::HideTopIOHandler() 1062 { 1063 Mutex::Locker locker; 1064 1065 if (locker.TryLock(m_input_reader_stack.GetMutex())) 1066 { 1067 IOHandlerSP reader_sp(m_input_reader_stack.Top()); 1068 if (reader_sp) 1069 reader_sp->Hide(); 1070 return true; 1071 } 1072 return false; 1073 } 1074 1075 void 1076 Debugger::RefreshTopIOHandler() 1077 { 1078 IOHandlerSP reader_sp(m_input_reader_stack.Top()); 1079 if (reader_sp) 1080 reader_sp->Refresh(); 1081 } 1082 1083 1084 StreamSP 1085 Debugger::GetAsyncOutputStream () 1086 { 1087 return StreamSP (new StreamAsynchronousIO (GetCommandInterpreter(), 1088 CommandInterpreter::eBroadcastBitAsynchronousOutputData)); 1089 } 1090 1091 StreamSP 1092 Debugger::GetAsyncErrorStream () 1093 { 1094 return StreamSP (new StreamAsynchronousIO (GetCommandInterpreter(), 1095 CommandInterpreter::eBroadcastBitAsynchronousErrorData)); 1096 } 1097 1098 size_t 1099 Debugger::GetNumDebuggers() 1100 { 1101 if (g_shared_debugger_refcount > 0) 1102 { 1103 Mutex::Locker locker (GetDebuggerListMutex ()); 1104 return GetDebuggerList().size(); 1105 } 1106 return 0; 1107 } 1108 1109 lldb::DebuggerSP 1110 Debugger::GetDebuggerAtIndex (size_t index) 1111 { 1112 DebuggerSP debugger_sp; 1113 1114 if (g_shared_debugger_refcount > 0) 1115 { 1116 Mutex::Locker locker (GetDebuggerListMutex ()); 1117 DebuggerList &debugger_list = GetDebuggerList(); 1118 1119 if (index < debugger_list.size()) 1120 debugger_sp = debugger_list[index]; 1121 } 1122 1123 return debugger_sp; 1124 } 1125 1126 DebuggerSP 1127 Debugger::FindDebuggerWithID (lldb::user_id_t id) 1128 { 1129 DebuggerSP debugger_sp; 1130 1131 if (g_shared_debugger_refcount > 0) 1132 { 1133 Mutex::Locker locker (GetDebuggerListMutex ()); 1134 DebuggerList &debugger_list = GetDebuggerList(); 1135 DebuggerList::iterator pos, end = debugger_list.end(); 1136 for (pos = debugger_list.begin(); pos != end; ++pos) 1137 { 1138 if ((*pos).get()->GetID() == id) 1139 { 1140 debugger_sp = *pos; 1141 break; 1142 } 1143 } 1144 } 1145 return debugger_sp; 1146 } 1147 1148 #if 0 1149 static void 1150 TestPromptFormats (StackFrame *frame) 1151 { 1152 if (frame == NULL) 1153 return; 1154 1155 StreamString s; 1156 const char *prompt_format = 1157 "{addr = '${addr}'\n}" 1158 "{addr-file-or-load = '${addr-file-or-load}'\n}" 1159 "{current-pc-arrow = '${current-pc-arrow}'\n}" 1160 "{process.id = '${process.id}'\n}" 1161 "{process.name = '${process.name}'\n}" 1162 "{process.file.basename = '${process.file.basename}'\n}" 1163 "{process.file.fullpath = '${process.file.fullpath}'\n}" 1164 "{thread.id = '${thread.id}'\n}" 1165 "{thread.index = '${thread.index}'\n}" 1166 "{thread.name = '${thread.name}'\n}" 1167 "{thread.queue = '${thread.queue}'\n}" 1168 "{thread.stop-reason = '${thread.stop-reason}'\n}" 1169 "{target.arch = '${target.arch}'\n}" 1170 "{module.file.basename = '${module.file.basename}'\n}" 1171 "{module.file.fullpath = '${module.file.fullpath}'\n}" 1172 "{file.basename = '${file.basename}'\n}" 1173 "{file.fullpath = '${file.fullpath}'\n}" 1174 "{frame.index = '${frame.index}'\n}" 1175 "{frame.pc = '${frame.pc}'\n}" 1176 "{frame.sp = '${frame.sp}'\n}" 1177 "{frame.fp = '${frame.fp}'\n}" 1178 "{frame.flags = '${frame.flags}'\n}" 1179 "{frame.reg.rdi = '${frame.reg.rdi}'\n}" 1180 "{frame.reg.rip = '${frame.reg.rip}'\n}" 1181 "{frame.reg.rsp = '${frame.reg.rsp}'\n}" 1182 "{frame.reg.rbp = '${frame.reg.rbp}'\n}" 1183 "{frame.reg.rflags = '${frame.reg.rflags}'\n}" 1184 "{frame.reg.xmm0 = '${frame.reg.xmm0}'\n}" 1185 "{frame.reg.carp = '${frame.reg.carp}'\n}" 1186 "{function.id = '${function.id}'\n}" 1187 "{function.changed = '${function.changed}'\n}" 1188 "{function.initial-function = '${function.initial-function}'\n}" 1189 "{function.name = '${function.name}'\n}" 1190 "{function.name-without-args = '${function.name-without-args}'\n}" 1191 "{function.name-with-args = '${function.name-with-args}'\n}" 1192 "{function.addr-offset = '${function.addr-offset}'\n}" 1193 "{function.concrete-only-addr-offset-no-padding = '${function.concrete-only-addr-offset-no-padding}'\n}" 1194 "{function.line-offset = '${function.line-offset}'\n}" 1195 "{function.pc-offset = '${function.pc-offset}'\n}" 1196 "{line.file.basename = '${line.file.basename}'\n}" 1197 "{line.file.fullpath = '${line.file.fullpath}'\n}" 1198 "{line.number = '${line.number}'\n}" 1199 "{line.start-addr = '${line.start-addr}'\n}" 1200 "{line.end-addr = '${line.end-addr}'\n}" 1201 ; 1202 1203 SymbolContext sc (frame->GetSymbolContext(eSymbolContextEverything)); 1204 ExecutionContext exe_ctx; 1205 frame->CalculateExecutionContext(exe_ctx); 1206 if (Debugger::FormatPrompt (prompt_format, &sc, &exe_ctx, &sc.line_entry.range.GetBaseAddress(), s)) 1207 { 1208 printf("%s\n", s.GetData()); 1209 } 1210 else 1211 { 1212 printf ("what we got: %s\n", s.GetData()); 1213 } 1214 } 1215 #endif 1216 1217 static bool 1218 ScanFormatDescriptor (const char* var_name_begin, 1219 const char* var_name_end, 1220 const char** var_name_final, 1221 const char** percent_position, 1222 Format* custom_format, 1223 ValueObject::ValueObjectRepresentationStyle* val_obj_display) 1224 { 1225 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES)); 1226 *percent_position = ::strchr(var_name_begin,'%'); 1227 if (!*percent_position || *percent_position > var_name_end) 1228 { 1229 if (log) 1230 log->Printf("[ScanFormatDescriptor] no format descriptor in string, skipping"); 1231 *var_name_final = var_name_end; 1232 } 1233 else 1234 { 1235 *var_name_final = *percent_position; 1236 std::string format_name(*var_name_final+1, var_name_end-*var_name_final-1); 1237 if (log) 1238 log->Printf("[ScanFormatDescriptor] parsing %s as a format descriptor", format_name.c_str()); 1239 if ( !FormatManager::GetFormatFromCString(format_name.c_str(), 1240 true, 1241 *custom_format) ) 1242 { 1243 if (log) 1244 log->Printf("[ScanFormatDescriptor] %s is an unknown format", format_name.c_str()); 1245 1246 switch (format_name.front()) 1247 { 1248 case '@': // if this is an @ sign, print ObjC description 1249 *val_obj_display = ValueObject::eValueObjectRepresentationStyleLanguageSpecific; 1250 break; 1251 case 'V': // if this is a V, print the value using the default format 1252 *val_obj_display = ValueObject::eValueObjectRepresentationStyleValue; 1253 break; 1254 case 'L': // if this is an L, print the location of the value 1255 *val_obj_display = ValueObject::eValueObjectRepresentationStyleLocation; 1256 break; 1257 case 'S': // if this is an S, print the summary after all 1258 *val_obj_display = ValueObject::eValueObjectRepresentationStyleSummary; 1259 break; 1260 case '#': // if this is a '#', print the number of children 1261 *val_obj_display = ValueObject::eValueObjectRepresentationStyleChildrenCount; 1262 break; 1263 case 'T': // if this is a 'T', print the type 1264 *val_obj_display = ValueObject::eValueObjectRepresentationStyleType; 1265 break; 1266 case 'N': // if this is a 'N', print the name 1267 *val_obj_display = ValueObject::eValueObjectRepresentationStyleName; 1268 break; 1269 case '>': // if this is a '>', print the name 1270 *val_obj_display = ValueObject::eValueObjectRepresentationStyleExpressionPath; 1271 break; 1272 default: 1273 if (log) 1274 log->Printf("ScanFormatDescriptor] %s is an error, leaving the previous value alone", format_name.c_str()); 1275 break; 1276 } 1277 } 1278 // a good custom format tells us to print the value using it 1279 else 1280 { 1281 if (log) 1282 log->Printf("[ScanFormatDescriptor] will display value for this VO"); 1283 *val_obj_display = ValueObject::eValueObjectRepresentationStyleValue; 1284 } 1285 } 1286 if (log) 1287 log->Printf("[ScanFormatDescriptor] final format description outcome: custom_format = %d, val_obj_display = %d", 1288 *custom_format, 1289 *val_obj_display); 1290 return true; 1291 } 1292 1293 static bool 1294 ScanBracketedRange (const char* var_name_begin, 1295 const char* var_name_end, 1296 const char* var_name_final, 1297 const char** open_bracket_position, 1298 const char** separator_position, 1299 const char** close_bracket_position, 1300 const char** var_name_final_if_array_range, 1301 int64_t* index_lower, 1302 int64_t* index_higher) 1303 { 1304 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES)); 1305 *open_bracket_position = ::strchr(var_name_begin,'['); 1306 if (*open_bracket_position && *open_bracket_position < var_name_final) 1307 { 1308 *separator_position = ::strchr(*open_bracket_position,'-'); // might be NULL if this is a simple var[N] bitfield 1309 *close_bracket_position = ::strchr(*open_bracket_position,']'); 1310 // as usual, we assume that [] will come before % 1311 //printf("trying to expand a []\n"); 1312 *var_name_final_if_array_range = *open_bracket_position; 1313 if (*close_bracket_position - *open_bracket_position == 1) 1314 { 1315 if (log) 1316 log->Printf("[ScanBracketedRange] '[]' detected.. going from 0 to end of data"); 1317 *index_lower = 0; 1318 } 1319 else if (*separator_position == NULL || *separator_position > var_name_end) 1320 { 1321 char *end = NULL; 1322 *index_lower = ::strtoul (*open_bracket_position+1, &end, 0); 1323 *index_higher = *index_lower; 1324 if (log) 1325 log->Printf("[ScanBracketedRange] [%" PRId64 "] detected, high index is same", *index_lower); 1326 } 1327 else if (*close_bracket_position && *close_bracket_position < var_name_end) 1328 { 1329 char *end = NULL; 1330 *index_lower = ::strtoul (*open_bracket_position+1, &end, 0); 1331 *index_higher = ::strtoul (*separator_position+1, &end, 0); 1332 if (log) 1333 log->Printf("[ScanBracketedRange] [%" PRId64 "-%" PRId64 "] detected", *index_lower, *index_higher); 1334 } 1335 else 1336 { 1337 if (log) 1338 log->Printf("[ScanBracketedRange] expression is erroneous, cannot extract indices out of it"); 1339 return false; 1340 } 1341 if (*index_lower > *index_higher && *index_higher > 0) 1342 { 1343 if (log) 1344 log->Printf("[ScanBracketedRange] swapping indices"); 1345 int64_t temp = *index_lower; 1346 *index_lower = *index_higher; 1347 *index_higher = temp; 1348 } 1349 } 1350 else if (log) 1351 log->Printf("[ScanBracketedRange] no bracketed range, skipping entirely"); 1352 return true; 1353 } 1354 1355 template <typename T> 1356 static bool RunScriptFormatKeyword(Stream &s, ScriptInterpreter *script_interpreter, T t, const std::string& script_name) 1357 { 1358 if (script_interpreter) 1359 { 1360 Error script_error; 1361 std::string script_output; 1362 1363 if (script_interpreter->RunScriptFormatKeyword(script_name.c_str(), t, script_output, script_error) && script_error.Success()) 1364 { 1365 s.Printf("%s", script_output.c_str()); 1366 return true; 1367 } 1368 else 1369 { 1370 s.Printf("<error: %s>",script_error.AsCString()); 1371 } 1372 } 1373 return false; 1374 } 1375 1376 static ValueObjectSP 1377 ExpandIndexedExpression (ValueObject* valobj, 1378 size_t index, 1379 StackFrame* frame, 1380 bool deref_pointer) 1381 { 1382 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES)); 1383 const char* ptr_deref_format = "[%d]"; 1384 std::string ptr_deref_buffer(10,0); 1385 ::sprintf(&ptr_deref_buffer[0], ptr_deref_format, index); 1386 if (log) 1387 log->Printf("[ExpandIndexedExpression] name to deref: %s",ptr_deref_buffer.c_str()); 1388 const char* first_unparsed; 1389 ValueObject::GetValueForExpressionPathOptions options; 1390 ValueObject::ExpressionPathEndResultType final_value_type; 1391 ValueObject::ExpressionPathScanEndReason reason_to_stop; 1392 ValueObject::ExpressionPathAftermath what_next = (deref_pointer ? ValueObject::eExpressionPathAftermathDereference : ValueObject::eExpressionPathAftermathNothing); 1393 ValueObjectSP item = valobj->GetValueForExpressionPath (ptr_deref_buffer.c_str(), 1394 &first_unparsed, 1395 &reason_to_stop, 1396 &final_value_type, 1397 options, 1398 &what_next); 1399 if (!item) 1400 { 1401 if (log) 1402 log->Printf("[ExpandIndexedExpression] ERROR: unparsed portion = %s, why stopping = %d," 1403 " final_value_type %d", 1404 first_unparsed, reason_to_stop, final_value_type); 1405 } 1406 else 1407 { 1408 if (log) 1409 log->Printf("[ExpandIndexedExpression] ALL RIGHT: unparsed portion = %s, why stopping = %d," 1410 " final_value_type %d", 1411 first_unparsed, reason_to_stop, final_value_type); 1412 } 1413 return item; 1414 } 1415 1416 static inline bool 1417 IsToken(const char *var_name_begin, const char *var) 1418 { 1419 return (::strncmp (var_name_begin, var, strlen(var)) == 0); 1420 } 1421 1422 static bool 1423 IsTokenWithFormat(const char *var_name_begin, const char *var, std::string &format, const char *default_format, 1424 const ExecutionContext *exe_ctx_ptr, const SymbolContext *sc_ptr) 1425 { 1426 int var_len = strlen(var); 1427 if (::strncmp (var_name_begin, var, var_len) == 0) 1428 { 1429 var_name_begin += var_len; 1430 if (*var_name_begin == '}') 1431 { 1432 format = default_format; 1433 return true; 1434 } 1435 else if (*var_name_begin == '%') 1436 { 1437 // Allow format specifiers: x|X|u with optional width specifiers. 1438 // ${thread.id%x} ; hex 1439 // ${thread.id%X} ; uppercase hex 1440 // ${thread.id%u} ; unsigned decimal 1441 // ${thread.id%8.8X} ; width.precision + specifier 1442 // ${thread.id%tid} ; unsigned on FreeBSD/Linux, otherwise default_format (0x%4.4x for thread.id) 1443 int dot_count = 0; 1444 const char *specifier = NULL; 1445 int width_precision_length = 0; 1446 const char *width_precision = ++var_name_begin; 1447 while (isdigit(*var_name_begin) || *var_name_begin == '.') 1448 { 1449 dot_count += (*var_name_begin == '.'); 1450 if (dot_count > 1) 1451 break; 1452 var_name_begin++; 1453 width_precision_length++; 1454 } 1455 1456 if (IsToken (var_name_begin, "tid}")) 1457 { 1458 Target *target = Target::GetTargetFromContexts (exe_ctx_ptr, sc_ptr); 1459 if (target) 1460 { 1461 ArchSpec arch (target->GetArchitecture ()); 1462 llvm::Triple::OSType ostype = arch.IsValid() ? arch.GetTriple().getOS() : llvm::Triple::UnknownOS; 1463 if ((ostype == llvm::Triple::FreeBSD) || (ostype == llvm::Triple::Linux)) 1464 specifier = PRIu64; 1465 } 1466 if (!specifier) 1467 { 1468 format = default_format; 1469 return true; 1470 } 1471 } 1472 else if (IsToken (var_name_begin, "x}")) 1473 specifier = PRIx64; 1474 else if (IsToken (var_name_begin, "X}")) 1475 specifier = PRIX64; 1476 else if (IsToken (var_name_begin, "u}")) 1477 specifier = PRIu64; 1478 1479 if (specifier) 1480 { 1481 format = "%"; 1482 if (width_precision_length) 1483 format += std::string(width_precision, width_precision_length); 1484 format += specifier; 1485 return true; 1486 } 1487 } 1488 } 1489 return false; 1490 } 1491 1492 // Find information for the "thread.info.*" specifiers in a format string 1493 static bool 1494 FormatThreadExtendedInfoRecurse 1495 ( 1496 const char *var_name_begin, 1497 StructuredData::ObjectSP thread_info_dictionary, 1498 const SymbolContext *sc, 1499 const ExecutionContext *exe_ctx, 1500 Stream &s 1501 ) 1502 { 1503 bool var_success = false; 1504 std::string token_format; 1505 1506 llvm::StringRef var_name(var_name_begin); 1507 size_t percent_idx = var_name.find('%'); 1508 size_t close_curly_idx = var_name.find('}'); 1509 llvm::StringRef path = var_name; 1510 llvm::StringRef formatter = var_name; 1511 1512 // 'path' will be the dot separated list of objects to transverse up until we hit 1513 // a close curly brace, a percent sign, or an end of string. 1514 if (percent_idx != llvm::StringRef::npos || close_curly_idx != llvm::StringRef::npos) 1515 { 1516 if (percent_idx != llvm::StringRef::npos && close_curly_idx != llvm::StringRef::npos) 1517 { 1518 if (percent_idx < close_curly_idx) 1519 { 1520 path = var_name.slice(0, percent_idx); 1521 formatter = var_name.substr (percent_idx); 1522 } 1523 else 1524 { 1525 path = var_name.slice(0, close_curly_idx); 1526 formatter = var_name.substr (close_curly_idx); 1527 } 1528 } 1529 else if (percent_idx != llvm::StringRef::npos) 1530 { 1531 path = var_name.slice(0, percent_idx); 1532 formatter = var_name.substr (percent_idx); 1533 } 1534 else if (close_curly_idx != llvm::StringRef::npos) 1535 { 1536 path = var_name.slice(0, close_curly_idx); 1537 formatter = var_name.substr (close_curly_idx); 1538 } 1539 } 1540 1541 StructuredData::ObjectSP value = thread_info_dictionary->GetObjectForDotSeparatedPath (path); 1542 1543 if (value.get()) 1544 { 1545 if (value->GetType() == StructuredData::Type::eTypeInteger) 1546 { 1547 if (IsTokenWithFormat (formatter.str().c_str(), "", token_format, "0x%4.4" PRIx64, exe_ctx, sc)) 1548 { 1549 s.Printf(token_format.c_str(), value->GetAsInteger()->GetValue()); 1550 var_success = true; 1551 } 1552 } 1553 else if (value->GetType() == StructuredData::Type::eTypeFloat) 1554 { 1555 s.Printf ("%f", value->GetAsFloat()->GetValue()); 1556 var_success = true; 1557 } 1558 else if (value->GetType() == StructuredData::Type::eTypeString) 1559 { 1560 s.Printf("%s", value->GetAsString()->GetValue().c_str()); 1561 var_success = true; 1562 } 1563 else if (value->GetType() == StructuredData::Type::eTypeArray) 1564 { 1565 if (value->GetAsArray()->GetSize() > 0) 1566 { 1567 s.Printf ("%zu", value->GetAsArray()->GetSize()); 1568 var_success = true; 1569 } 1570 } 1571 else if (value->GetType() == StructuredData::Type::eTypeDictionary) 1572 { 1573 s.Printf ("%zu", value->GetAsDictionary()->GetKeys()->GetAsArray()->GetSize()); 1574 var_success = true; 1575 } 1576 } 1577 1578 return var_success; 1579 } 1580 1581 1582 static bool 1583 FormatPromptRecurse 1584 ( 1585 const char *format, 1586 const SymbolContext *sc, 1587 const ExecutionContext *exe_ctx, 1588 const Address *addr, 1589 Stream &s, 1590 const char **end, 1591 ValueObject* valobj, 1592 bool function_changed, 1593 bool initial_function 1594 ) 1595 { 1596 ValueObject* realvalobj = NULL; // makes it super-easy to parse pointers 1597 bool success = true; 1598 const char *p; 1599 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES)); 1600 1601 for (p = format; *p != '\0'; ++p) 1602 { 1603 if (realvalobj) 1604 { 1605 valobj = realvalobj; 1606 realvalobj = NULL; 1607 } 1608 size_t non_special_chars = ::strcspn (p, "${}\\"); 1609 if (non_special_chars > 0) 1610 { 1611 if (success) 1612 s.Write (p, non_special_chars); 1613 p += non_special_chars; 1614 } 1615 1616 if (*p == '\0') 1617 { 1618 break; 1619 } 1620 else if (*p == '{') 1621 { 1622 // Start a new scope that must have everything it needs if it is to 1623 // to make it into the final output stream "s". If you want to make 1624 // a format that only prints out the function or symbol name if there 1625 // is one in the symbol context you can use: 1626 // "{function =${function.name}}" 1627 // The first '{' starts a new scope that end with the matching '}' at 1628 // the end of the string. The contents "function =${function.name}" 1629 // will then be evaluated and only be output if there is a function 1630 // or symbol with a valid name. 1631 StreamString sub_strm; 1632 1633 ++p; // Skip the '{' 1634 1635 if (FormatPromptRecurse (p, sc, exe_ctx, addr, sub_strm, &p, valobj, function_changed, initial_function)) 1636 { 1637 // The stream had all it needed 1638 s.Write(sub_strm.GetData(), sub_strm.GetSize()); 1639 } 1640 if (*p != '}') 1641 { 1642 success = false; 1643 break; 1644 } 1645 } 1646 else if (*p == '}') 1647 { 1648 // End of a enclosing scope 1649 break; 1650 } 1651 else if (*p == '$') 1652 { 1653 // We have a prompt variable to print 1654 ++p; 1655 if (*p == '{') 1656 { 1657 ++p; 1658 const char *var_name_begin = p; 1659 const char *var_name_end = ::strchr (p, '}'); 1660 1661 if (var_name_end && var_name_begin < var_name_end) 1662 { 1663 // if we have already failed to parse, skip this variable 1664 if (success) 1665 { 1666 const char *cstr = NULL; 1667 std::string token_format; 1668 Address format_addr; 1669 1670 // normally "addr" means print a raw address but 1671 // "file-addr-or-load-addr" means print a module + file addr if there's no load addr 1672 bool print_file_addr_or_load_addr = false; 1673 bool addr_offset_concrete_func_only = false; 1674 bool addr_offset_print_with_no_padding = false; 1675 bool calculate_format_addr_function_offset = false; 1676 // Set reg_kind and reg_num to invalid values 1677 RegisterKind reg_kind = kNumRegisterKinds; 1678 uint32_t reg_num = LLDB_INVALID_REGNUM; 1679 FileSpec format_file_spec; 1680 const RegisterInfo *reg_info = NULL; 1681 RegisterContext *reg_ctx = NULL; 1682 bool do_deref_pointer = false; 1683 ValueObject::ExpressionPathScanEndReason reason_to_stop = ValueObject::eExpressionPathScanEndReasonEndOfString; 1684 ValueObject::ExpressionPathEndResultType final_value_type = ValueObject::eExpressionPathEndResultTypePlain; 1685 1686 // Each variable must set success to true below... 1687 bool var_success = false; 1688 switch (var_name_begin[0]) 1689 { 1690 case '*': 1691 case 'v': 1692 case 's': 1693 { 1694 if (!valobj) 1695 break; 1696 1697 if (log) 1698 log->Printf("[Debugger::FormatPrompt] initial string: %s",var_name_begin); 1699 1700 // check for *var and *svar 1701 if (*var_name_begin == '*') 1702 { 1703 do_deref_pointer = true; 1704 var_name_begin++; 1705 if (log) 1706 log->Printf("[Debugger::FormatPrompt] found a deref, new string is: %s",var_name_begin); 1707 } 1708 1709 if (*var_name_begin == 's') 1710 { 1711 if (!valobj->IsSynthetic()) 1712 valobj = valobj->GetSyntheticValue().get(); 1713 if (!valobj) 1714 break; 1715 var_name_begin++; 1716 if (log) 1717 log->Printf("[Debugger::FormatPrompt] found a synthetic, new string is: %s",var_name_begin); 1718 } 1719 1720 // should be a 'v' by now 1721 if (*var_name_begin != 'v') 1722 break; 1723 1724 if (log) 1725 log->Printf("[Debugger::FormatPrompt] string I am working with: %s",var_name_begin); 1726 1727 ValueObject::ExpressionPathAftermath what_next = (do_deref_pointer ? 1728 ValueObject::eExpressionPathAftermathDereference : ValueObject::eExpressionPathAftermathNothing); 1729 ValueObject::GetValueForExpressionPathOptions options; 1730 options.DontCheckDotVsArrowSyntax().DoAllowBitfieldSyntax().DoAllowFragileIVar().DoAllowSyntheticChildren(); 1731 ValueObject::ValueObjectRepresentationStyle val_obj_display = ValueObject::eValueObjectRepresentationStyleSummary; 1732 ValueObject* target = NULL; 1733 Format custom_format = eFormatInvalid; 1734 const char* var_name_final = NULL; 1735 const char* var_name_final_if_array_range = NULL; 1736 const char* close_bracket_position = NULL; 1737 int64_t index_lower = -1; 1738 int64_t index_higher = -1; 1739 bool is_array_range = false; 1740 const char* first_unparsed; 1741 bool was_plain_var = false; 1742 bool was_var_format = false; 1743 bool was_var_indexed = false; 1744 1745 if (!valobj) break; 1746 // simplest case ${var}, just print valobj's value 1747 if (IsToken (var_name_begin, "var}")) 1748 { 1749 was_plain_var = true; 1750 target = valobj; 1751 val_obj_display = ValueObject::eValueObjectRepresentationStyleValue; 1752 } 1753 else if (IsToken (var_name_begin, "var.script:")) 1754 { 1755 var_name_begin += ::strlen("var.script:"); 1756 std::string script_name(var_name_begin,var_name_end); 1757 ScriptInterpreter* script_interpreter = valobj->GetTargetSP()->GetDebugger().GetCommandInterpreter().GetScriptInterpreter(); 1758 if (RunScriptFormatKeyword (s, script_interpreter, valobj, script_name)) 1759 var_success = true; 1760 break; 1761 } 1762 else if (IsToken (var_name_begin,"var%")) 1763 { 1764 was_var_format = true; 1765 // this is a variable with some custom format applied to it 1766 const char* percent_position; 1767 target = valobj; 1768 val_obj_display = ValueObject::eValueObjectRepresentationStyleValue; 1769 ScanFormatDescriptor (var_name_begin, 1770 var_name_end, 1771 &var_name_final, 1772 &percent_position, 1773 &custom_format, 1774 &val_obj_display); 1775 } 1776 // this is ${var.something} or multiple .something nested 1777 else if (IsToken (var_name_begin, "var")) 1778 { 1779 if (IsToken (var_name_begin, "var[")) 1780 was_var_indexed = true; 1781 const char* percent_position; 1782 ScanFormatDescriptor (var_name_begin, 1783 var_name_end, 1784 &var_name_final, 1785 &percent_position, 1786 &custom_format, 1787 &val_obj_display); 1788 1789 const char* open_bracket_position; 1790 const char* separator_position; 1791 ScanBracketedRange (var_name_begin, 1792 var_name_end, 1793 var_name_final, 1794 &open_bracket_position, 1795 &separator_position, 1796 &close_bracket_position, 1797 &var_name_final_if_array_range, 1798 &index_lower, 1799 &index_higher); 1800 1801 Error error; 1802 1803 std::string expr_path(var_name_final-var_name_begin-1,0); 1804 memcpy(&expr_path[0], var_name_begin+3,var_name_final-var_name_begin-3); 1805 1806 if (log) 1807 log->Printf("[Debugger::FormatPrompt] symbol to expand: %s",expr_path.c_str()); 1808 1809 target = valobj->GetValueForExpressionPath(expr_path.c_str(), 1810 &first_unparsed, 1811 &reason_to_stop, 1812 &final_value_type, 1813 options, 1814 &what_next).get(); 1815 1816 if (!target) 1817 { 1818 if (log) 1819 log->Printf("[Debugger::FormatPrompt] ERROR: unparsed portion = %s, why stopping = %d," 1820 " final_value_type %d", 1821 first_unparsed, reason_to_stop, final_value_type); 1822 break; 1823 } 1824 else 1825 { 1826 if (log) 1827 log->Printf("[Debugger::FormatPrompt] ALL RIGHT: unparsed portion = %s, why stopping = %d," 1828 " final_value_type %d", 1829 first_unparsed, reason_to_stop, final_value_type); 1830 target = target->GetQualifiedRepresentationIfAvailable(target->GetDynamicValueType(), true).get(); 1831 } 1832 } 1833 else 1834 break; 1835 1836 is_array_range = (final_value_type == ValueObject::eExpressionPathEndResultTypeBoundedRange || 1837 final_value_type == ValueObject::eExpressionPathEndResultTypeUnboundedRange); 1838 1839 do_deref_pointer = (what_next == ValueObject::eExpressionPathAftermathDereference); 1840 1841 if (do_deref_pointer && !is_array_range) 1842 { 1843 // I have not deref-ed yet, let's do it 1844 // this happens when we are not going through GetValueForVariableExpressionPath 1845 // to get to the target ValueObject 1846 Error error; 1847 target = target->Dereference(error).get(); 1848 if (error.Fail()) 1849 { 1850 if (log) 1851 log->Printf("[Debugger::FormatPrompt] ERROR: %s\n", error.AsCString("unknown")); \ 1852 break; 1853 } 1854 do_deref_pointer = false; 1855 } 1856 1857 if (!target) 1858 { 1859 if (log) 1860 log->Printf("[Debugger::FormatPrompt] could not calculate target for prompt expression"); 1861 break; 1862 } 1863 1864 // we do not want to use the summary for a bitfield of type T:n 1865 // if we were originally dealing with just a T - that would get 1866 // us into an endless recursion 1867 if (target->IsBitfield() && was_var_indexed) 1868 { 1869 // TODO: check for a (T:n)-specific summary - we should still obey that 1870 StreamString bitfield_name; 1871 bitfield_name.Printf("%s:%d", target->GetTypeName().AsCString(), target->GetBitfieldBitSize()); 1872 lldb::TypeNameSpecifierImplSP type_sp(new TypeNameSpecifierImpl(bitfield_name.GetData(),false)); 1873 if (!DataVisualization::GetSummaryForType(type_sp)) 1874 val_obj_display = ValueObject::eValueObjectRepresentationStyleValue; 1875 } 1876 1877 // TODO use flags for these 1878 const uint32_t type_info_flags = target->GetClangType().GetTypeInfo(NULL); 1879 bool is_array = (type_info_flags & eTypeIsArray) != 0; 1880 bool is_pointer = (type_info_flags & eTypeIsPointer) != 0; 1881 bool is_aggregate = target->GetClangType().IsAggregateType(); 1882 1883 if ((is_array || is_pointer) && (!is_array_range) && val_obj_display == ValueObject::eValueObjectRepresentationStyleValue) // this should be wrong, but there are some exceptions 1884 { 1885 StreamString str_temp; 1886 if (log) 1887 log->Printf("[Debugger::FormatPrompt] I am into array || pointer && !range"); 1888 1889 if (target->HasSpecialPrintableRepresentation(val_obj_display, custom_format)) 1890 { 1891 // try to use the special cases 1892 var_success = target->DumpPrintableRepresentation(str_temp, 1893 val_obj_display, 1894 custom_format); 1895 if (log) 1896 log->Printf("[Debugger::FormatPrompt] special cases did%s match", var_success ? "" : "n't"); 1897 1898 // should not happen 1899 if (var_success) 1900 s << str_temp.GetData(); 1901 var_success = true; 1902 break; 1903 } 1904 else 1905 { 1906 if (was_plain_var) // if ${var} 1907 { 1908 s << target->GetTypeName() << " @ " << target->GetLocationAsCString(); 1909 } 1910 else if (is_pointer) // if pointer, value is the address stored 1911 { 1912 target->DumpPrintableRepresentation (s, 1913 val_obj_display, 1914 custom_format, 1915 ValueObject::ePrintableRepresentationSpecialCasesDisable); 1916 } 1917 var_success = true; 1918 break; 1919 } 1920 } 1921 1922 // if directly trying to print ${var}, and this is an aggregate, display a nice 1923 // type @ location message 1924 if (is_aggregate && was_plain_var) 1925 { 1926 s << target->GetTypeName() << " @ " << target->GetLocationAsCString(); 1927 var_success = true; 1928 break; 1929 } 1930 1931 // if directly trying to print ${var%V}, and this is an aggregate, do not let the user do it 1932 if (is_aggregate && ((was_var_format && val_obj_display == ValueObject::eValueObjectRepresentationStyleValue))) 1933 { 1934 s << "<invalid use of aggregate type>"; 1935 var_success = true; 1936 break; 1937 } 1938 1939 if (!is_array_range) 1940 { 1941 if (log) 1942 log->Printf("[Debugger::FormatPrompt] dumping ordinary printable output"); 1943 var_success = target->DumpPrintableRepresentation(s,val_obj_display, custom_format); 1944 } 1945 else 1946 { 1947 if (log) 1948 log->Printf("[Debugger::FormatPrompt] checking if I can handle as array"); 1949 if (!is_array && !is_pointer) 1950 break; 1951 if (log) 1952 log->Printf("[Debugger::FormatPrompt] handle as array"); 1953 const char* special_directions = NULL; 1954 StreamString special_directions_writer; 1955 if (close_bracket_position && (var_name_end-close_bracket_position > 1)) 1956 { 1957 ConstString additional_data; 1958 additional_data.SetCStringWithLength(close_bracket_position+1, var_name_end-close_bracket_position-1); 1959 special_directions_writer.Printf("${%svar%s}", 1960 do_deref_pointer ? "*" : "", 1961 additional_data.GetCString()); 1962 special_directions = special_directions_writer.GetData(); 1963 } 1964 1965 // let us display items index_lower thru index_higher of this array 1966 s.PutChar('['); 1967 var_success = true; 1968 1969 if (index_higher < 0) 1970 index_higher = valobj->GetNumChildren() - 1; 1971 1972 uint32_t max_num_children = target->GetTargetSP()->GetMaximumNumberOfChildrenToDisplay(); 1973 1974 for (;index_lower<=index_higher;index_lower++) 1975 { 1976 ValueObject* item = ExpandIndexedExpression (target, 1977 index_lower, 1978 exe_ctx->GetFramePtr(), 1979 false).get(); 1980 1981 if (!item) 1982 { 1983 if (log) 1984 log->Printf("[Debugger::FormatPrompt] ERROR in getting child item at index %" PRId64, index_lower); 1985 } 1986 else 1987 { 1988 if (log) 1989 log->Printf("[Debugger::FormatPrompt] special_directions for child item: %s",special_directions); 1990 } 1991 1992 if (!special_directions) 1993 var_success &= item->DumpPrintableRepresentation(s,val_obj_display, custom_format); 1994 else 1995 var_success &= FormatPromptRecurse(special_directions, sc, exe_ctx, addr, s, NULL, item, function_changed, initial_function); 1996 1997 if (--max_num_children == 0) 1998 { 1999 s.PutCString(", ..."); 2000 break; 2001 } 2002 2003 if (index_lower < index_higher) 2004 s.PutChar(','); 2005 } 2006 s.PutChar(']'); 2007 } 2008 } 2009 break; 2010 case 'a': 2011 if (IsToken (var_name_begin, "addr-file-or-load}")) 2012 { 2013 print_file_addr_or_load_addr = true; 2014 } 2015 if (IsToken (var_name_begin, "addr}") 2016 || IsToken (var_name_begin, "addr-file-or-load}")) 2017 { 2018 if (addr && addr->IsValid()) 2019 { 2020 var_success = true; 2021 format_addr = *addr; 2022 } 2023 } 2024 break; 2025 2026 case 'p': 2027 if (IsToken (var_name_begin, "process.")) 2028 { 2029 if (exe_ctx) 2030 { 2031 Process *process = exe_ctx->GetProcessPtr(); 2032 if (process) 2033 { 2034 var_name_begin += ::strlen ("process."); 2035 if (IsTokenWithFormat (var_name_begin, "id", token_format, "%" PRIu64, exe_ctx, sc)) 2036 { 2037 s.Printf(token_format.c_str(), process->GetID()); 2038 var_success = true; 2039 } 2040 else if ((IsToken (var_name_begin, "name}")) || 2041 (IsToken (var_name_begin, "file.basename}")) || 2042 (IsToken (var_name_begin, "file.fullpath}"))) 2043 { 2044 Module *exe_module = process->GetTarget().GetExecutableModulePointer(); 2045 if (exe_module) 2046 { 2047 if (var_name_begin[0] == 'n' || var_name_begin[5] == 'f') 2048 { 2049 format_file_spec.GetFilename() = exe_module->GetFileSpec().GetFilename(); 2050 var_success = (bool)format_file_spec; 2051 } 2052 else 2053 { 2054 format_file_spec = exe_module->GetFileSpec(); 2055 var_success = (bool)format_file_spec; 2056 } 2057 } 2058 } 2059 else if (IsToken (var_name_begin, "script:")) 2060 { 2061 var_name_begin += ::strlen("script:"); 2062 std::string script_name(var_name_begin,var_name_end); 2063 ScriptInterpreter* script_interpreter = process->GetTarget().GetDebugger().GetCommandInterpreter().GetScriptInterpreter(); 2064 if (RunScriptFormatKeyword (s, script_interpreter, process, script_name)) 2065 var_success = true; 2066 } 2067 } 2068 } 2069 } 2070 break; 2071 2072 case 't': 2073 if (IsToken (var_name_begin, "thread.")) 2074 { 2075 if (exe_ctx) 2076 { 2077 Thread *thread = exe_ctx->GetThreadPtr(); 2078 if (thread) 2079 { 2080 var_name_begin += ::strlen ("thread."); 2081 if (IsTokenWithFormat (var_name_begin, "id", token_format, "0x%4.4" PRIx64, exe_ctx, sc)) 2082 { 2083 s.Printf(token_format.c_str(), thread->GetID()); 2084 var_success = true; 2085 } 2086 else if (IsTokenWithFormat (var_name_begin, "protocol_id", token_format, "0x%4.4" PRIx64, exe_ctx, sc)) 2087 { 2088 s.Printf(token_format.c_str(), thread->GetProtocolID()); 2089 var_success = true; 2090 } 2091 else if (IsTokenWithFormat (var_name_begin, "index", token_format, "%" PRIu64, exe_ctx, sc)) 2092 { 2093 s.Printf(token_format.c_str(), (uint64_t)thread->GetIndexID()); 2094 var_success = true; 2095 } 2096 else if (IsToken (var_name_begin, "name}")) 2097 { 2098 cstr = thread->GetName(); 2099 var_success = cstr && cstr[0]; 2100 if (var_success) 2101 s.PutCString(cstr); 2102 } 2103 else if (IsToken (var_name_begin, "queue}")) 2104 { 2105 cstr = thread->GetQueueName(); 2106 var_success = cstr && cstr[0]; 2107 if (var_success) 2108 s.PutCString(cstr); 2109 } 2110 else if (IsToken (var_name_begin, "stop-reason}")) 2111 { 2112 StopInfoSP stop_info_sp = thread->GetStopInfo (); 2113 if (stop_info_sp && stop_info_sp->IsValid()) 2114 { 2115 cstr = stop_info_sp->GetDescription(); 2116 if (cstr && cstr[0]) 2117 { 2118 s.PutCString(cstr); 2119 var_success = true; 2120 } 2121 } 2122 } 2123 else if (IsToken (var_name_begin, "return-value}")) 2124 { 2125 StopInfoSP stop_info_sp = thread->GetStopInfo (); 2126 if (stop_info_sp && stop_info_sp->IsValid()) 2127 { 2128 ValueObjectSP return_valobj_sp = StopInfo::GetReturnValueObject (stop_info_sp); 2129 if (return_valobj_sp) 2130 { 2131 return_valobj_sp->Dump(s); 2132 var_success = true; 2133 } 2134 } 2135 } 2136 else if (IsToken (var_name_begin, "completed-expression}")) 2137 { 2138 StopInfoSP stop_info_sp = thread->GetStopInfo (); 2139 if (stop_info_sp && stop_info_sp->IsValid()) 2140 { 2141 ClangExpressionVariableSP expression_var_sp = StopInfo::GetExpressionVariable (stop_info_sp); 2142 if (expression_var_sp && expression_var_sp->GetValueObject()) 2143 { 2144 expression_var_sp->GetValueObject()->Dump(s); 2145 var_success = true; 2146 } 2147 } 2148 } 2149 else if (IsToken (var_name_begin, "script:")) 2150 { 2151 var_name_begin += ::strlen("script:"); 2152 std::string script_name(var_name_begin,var_name_end); 2153 ScriptInterpreter* script_interpreter = thread->GetProcess()->GetTarget().GetDebugger().GetCommandInterpreter().GetScriptInterpreter(); 2154 if (RunScriptFormatKeyword (s, script_interpreter, thread, script_name)) 2155 var_success = true; 2156 } 2157 else if (IsToken (var_name_begin, "info.")) 2158 { 2159 var_name_begin += ::strlen("info."); 2160 StructuredData::ObjectSP object_sp = thread->GetExtendedInfo(); 2161 if (object_sp && object_sp->GetType() == StructuredData::Type::eTypeDictionary) 2162 { 2163 var_success = FormatThreadExtendedInfoRecurse (var_name_begin, object_sp, sc, exe_ctx, s); 2164 } 2165 } 2166 } 2167 } 2168 } 2169 else if (IsToken (var_name_begin, "target.")) 2170 { 2171 // TODO: hookup properties 2172 // if (!target_properties_sp) 2173 // { 2174 // Target *target = Target::GetTargetFromContexts (exe_ctx, sc); 2175 // if (target) 2176 // target_properties_sp = target->GetProperties(); 2177 // } 2178 // 2179 // if (target_properties_sp) 2180 // { 2181 // var_name_begin += ::strlen ("target."); 2182 // const char *end_property = strchr(var_name_begin, '}'); 2183 // if (end_property) 2184 // { 2185 // ConstString property_name(var_name_begin, end_property - var_name_begin); 2186 // std::string property_value (target_properties_sp->GetPropertyValue(property_name)); 2187 // if (!property_value.empty()) 2188 // { 2189 // s.PutCString (property_value.c_str()); 2190 // var_success = true; 2191 // } 2192 // } 2193 // } 2194 Target *target = Target::GetTargetFromContexts (exe_ctx, sc); 2195 if (target) 2196 { 2197 var_name_begin += ::strlen ("target."); 2198 if (IsToken (var_name_begin, "arch}")) 2199 { 2200 ArchSpec arch (target->GetArchitecture ()); 2201 if (arch.IsValid()) 2202 { 2203 s.PutCString (arch.GetArchitectureName()); 2204 var_success = true; 2205 } 2206 } 2207 else if (IsToken (var_name_begin, "script:")) 2208 { 2209 var_name_begin += ::strlen("script:"); 2210 std::string script_name(var_name_begin,var_name_end); 2211 ScriptInterpreter* script_interpreter = target->GetDebugger().GetCommandInterpreter().GetScriptInterpreter(); 2212 if (RunScriptFormatKeyword (s, script_interpreter, target, script_name)) 2213 var_success = true; 2214 } 2215 } 2216 } 2217 break; 2218 2219 case 'm': 2220 if (IsToken (var_name_begin, "module.")) 2221 { 2222 if (sc && sc->module_sp.get()) 2223 { 2224 Module *module = sc->module_sp.get(); 2225 var_name_begin += ::strlen ("module."); 2226 2227 if (IsToken (var_name_begin, "file.")) 2228 { 2229 if (module->GetFileSpec()) 2230 { 2231 var_name_begin += ::strlen ("file."); 2232 2233 if (IsToken (var_name_begin, "basename}")) 2234 { 2235 format_file_spec.GetFilename() = module->GetFileSpec().GetFilename(); 2236 var_success = (bool)format_file_spec; 2237 } 2238 else if (IsToken (var_name_begin, "fullpath}")) 2239 { 2240 format_file_spec = module->GetFileSpec(); 2241 var_success = (bool)format_file_spec; 2242 } 2243 } 2244 } 2245 } 2246 } 2247 break; 2248 2249 2250 case 'f': 2251 if (IsToken (var_name_begin, "file.")) 2252 { 2253 if (sc && sc->comp_unit != NULL) 2254 { 2255 var_name_begin += ::strlen ("file."); 2256 2257 if (IsToken (var_name_begin, "basename}")) 2258 { 2259 format_file_spec.GetFilename() = sc->comp_unit->GetFilename(); 2260 var_success = (bool)format_file_spec; 2261 } 2262 else if (IsToken (var_name_begin, "fullpath}")) 2263 { 2264 format_file_spec = *sc->comp_unit; 2265 var_success = (bool)format_file_spec; 2266 } 2267 } 2268 } 2269 else if (IsToken (var_name_begin, "frame.")) 2270 { 2271 if (exe_ctx) 2272 { 2273 StackFrame *frame = exe_ctx->GetFramePtr(); 2274 if (frame) 2275 { 2276 var_name_begin += ::strlen ("frame."); 2277 if (IsToken (var_name_begin, "index}")) 2278 { 2279 s.Printf("%u", frame->GetFrameIndex()); 2280 var_success = true; 2281 } 2282 else if (IsToken (var_name_begin, "pc}")) 2283 { 2284 reg_kind = eRegisterKindGeneric; 2285 reg_num = LLDB_REGNUM_GENERIC_PC; 2286 var_success = true; 2287 } 2288 else if (IsToken (var_name_begin, "sp}")) 2289 { 2290 reg_kind = eRegisterKindGeneric; 2291 reg_num = LLDB_REGNUM_GENERIC_SP; 2292 var_success = true; 2293 } 2294 else if (IsToken (var_name_begin, "fp}")) 2295 { 2296 reg_kind = eRegisterKindGeneric; 2297 reg_num = LLDB_REGNUM_GENERIC_FP; 2298 var_success = true; 2299 } 2300 else if (IsToken (var_name_begin, "flags}")) 2301 { 2302 reg_kind = eRegisterKindGeneric; 2303 reg_num = LLDB_REGNUM_GENERIC_FLAGS; 2304 var_success = true; 2305 } 2306 else if (IsToken (var_name_begin, "reg.")) 2307 { 2308 reg_ctx = frame->GetRegisterContext().get(); 2309 if (reg_ctx) 2310 { 2311 var_name_begin += ::strlen ("reg."); 2312 if (var_name_begin < var_name_end) 2313 { 2314 std::string reg_name (var_name_begin, var_name_end); 2315 reg_info = reg_ctx->GetRegisterInfoByName (reg_name.c_str()); 2316 if (reg_info) 2317 var_success = true; 2318 } 2319 } 2320 } 2321 else if (IsToken (var_name_begin, "script:")) 2322 { 2323 var_name_begin += ::strlen("script:"); 2324 std::string script_name(var_name_begin,var_name_end); 2325 ScriptInterpreter* script_interpreter = frame->GetThread()->GetProcess()->GetTarget().GetDebugger().GetCommandInterpreter().GetScriptInterpreter(); 2326 if (RunScriptFormatKeyword (s, script_interpreter, frame, script_name)) 2327 var_success = true; 2328 } 2329 } 2330 } 2331 } 2332 else if (IsToken (var_name_begin, "function.")) 2333 { 2334 if (sc && (sc->function != NULL || sc->symbol != NULL)) 2335 { 2336 var_name_begin += ::strlen ("function."); 2337 if (IsToken (var_name_begin, "id}")) 2338 { 2339 if (sc->function) 2340 s.Printf("function{0x%8.8" PRIx64 "}", sc->function->GetID()); 2341 else 2342 s.Printf("symbol[%u]", sc->symbol->GetID()); 2343 2344 var_success = true; 2345 } 2346 if (IsToken (var_name_begin, "changed}") && function_changed) 2347 { 2348 var_success = true; 2349 } 2350 if (IsToken (var_name_begin, "initial-function}") && initial_function) 2351 { 2352 var_success = true; 2353 } 2354 else if (IsToken (var_name_begin, "name}")) 2355 { 2356 if (sc->function) 2357 cstr = sc->function->GetName().AsCString (NULL); 2358 else if (sc->symbol) 2359 cstr = sc->symbol->GetName().AsCString (NULL); 2360 if (cstr) 2361 { 2362 s.PutCString(cstr); 2363 2364 if (sc->block) 2365 { 2366 Block *inline_block = sc->block->GetContainingInlinedBlock (); 2367 if (inline_block) 2368 { 2369 const InlineFunctionInfo *inline_info = sc->block->GetInlinedFunctionInfo(); 2370 if (inline_info) 2371 { 2372 s.PutCString(" [inlined] "); 2373 inline_info->GetName().Dump(&s); 2374 } 2375 } 2376 } 2377 var_success = true; 2378 } 2379 } 2380 else if (IsToken (var_name_begin, "name-without-args}")) 2381 { 2382 ConstString name; 2383 if (sc->function) 2384 name = sc->function->GetMangled().GetName (Mangled::ePreferDemangledWithoutArguments); 2385 else if (sc->symbol) 2386 name = sc->symbol->GetMangled().GetName (Mangled::ePreferDemangledWithoutArguments); 2387 if (name) 2388 { 2389 s.PutCString(name.GetCString()); 2390 var_success = true; 2391 } 2392 } 2393 else if (IsToken (var_name_begin, "name-with-args}")) 2394 { 2395 // Print the function name with arguments in it 2396 2397 if (sc->function) 2398 { 2399 var_success = true; 2400 ExecutionContextScope *exe_scope = exe_ctx ? exe_ctx->GetBestExecutionContextScope() : NULL; 2401 cstr = sc->function->GetName().AsCString (NULL); 2402 if (cstr) 2403 { 2404 const InlineFunctionInfo *inline_info = NULL; 2405 VariableListSP variable_list_sp; 2406 bool get_function_vars = true; 2407 if (sc->block) 2408 { 2409 Block *inline_block = sc->block->GetContainingInlinedBlock (); 2410 2411 if (inline_block) 2412 { 2413 get_function_vars = false; 2414 inline_info = sc->block->GetInlinedFunctionInfo(); 2415 if (inline_info) 2416 variable_list_sp = inline_block->GetBlockVariableList (true); 2417 } 2418 } 2419 2420 if (get_function_vars) 2421 { 2422 variable_list_sp = sc->function->GetBlock(true).GetBlockVariableList (true); 2423 } 2424 2425 if (inline_info) 2426 { 2427 s.PutCString (cstr); 2428 s.PutCString (" [inlined] "); 2429 cstr = inline_info->GetName().GetCString(); 2430 } 2431 2432 VariableList args; 2433 if (variable_list_sp) 2434 variable_list_sp->AppendVariablesWithScope(eValueTypeVariableArgument, args); 2435 if (args.GetSize() > 0) 2436 { 2437 const char *open_paren = strchr (cstr, '('); 2438 const char *close_paren = nullptr; 2439 const char *generic = strchr(cstr, '<'); 2440 // if before the arguments list begins there is a template sign 2441 // then scan to the end of the generic args before you try to find 2442 // the arguments list 2443 if (generic && open_paren && generic < open_paren) 2444 { 2445 int generic_depth = 1; 2446 ++generic; 2447 for (; 2448 *generic && generic_depth > 0; 2449 generic++) 2450 { 2451 if (*generic == '<') 2452 generic_depth++; 2453 if (*generic == '>') 2454 generic_depth--; 2455 } 2456 if (*generic) 2457 open_paren = strchr(generic, '('); 2458 else 2459 open_paren = nullptr; 2460 } 2461 if (open_paren) 2462 { 2463 if (IsToken (open_paren, "(anonymous namespace)")) 2464 { 2465 open_paren = strchr (open_paren + strlen("(anonymous namespace)"), '('); 2466 if (open_paren) 2467 close_paren = strchr (open_paren, ')'); 2468 } 2469 else 2470 close_paren = strchr (open_paren, ')'); 2471 } 2472 2473 if (open_paren) 2474 s.Write(cstr, open_paren - cstr + 1); 2475 else 2476 { 2477 s.PutCString (cstr); 2478 s.PutChar ('('); 2479 } 2480 const size_t num_args = args.GetSize(); 2481 for (size_t arg_idx = 0; arg_idx < num_args; ++arg_idx) 2482 { 2483 std::string buffer; 2484 2485 VariableSP var_sp (args.GetVariableAtIndex (arg_idx)); 2486 ValueObjectSP var_value_sp (ValueObjectVariable::Create (exe_scope, var_sp)); 2487 const char *var_representation = nullptr; 2488 const char *var_name = var_value_sp->GetName().GetCString(); 2489 if (var_value_sp->GetClangType().IsAggregateType() && 2490 DataVisualization::ShouldPrintAsOneLiner(*var_value_sp.get())) 2491 { 2492 static StringSummaryFormat format(TypeSummaryImpl::Flags() 2493 .SetHideItemNames(false) 2494 .SetShowMembersOneLiner(true), 2495 ""); 2496 format.FormatObject(var_value_sp.get(), buffer, TypeSummaryOptions()); 2497 var_representation = buffer.c_str(); 2498 } 2499 else 2500 var_representation = var_value_sp->GetValueAsCString(); 2501 if (arg_idx > 0) 2502 s.PutCString (", "); 2503 if (var_value_sp->GetError().Success()) 2504 { 2505 if (var_representation) 2506 s.Printf ("%s=%s", var_name, var_representation); 2507 else 2508 s.Printf ("%s=%s at %s", var_name, var_value_sp->GetTypeName().GetCString(), var_value_sp->GetLocationAsCString()); 2509 } 2510 else 2511 s.Printf ("%s=<unavailable>", var_name); 2512 } 2513 2514 if (close_paren) 2515 s.PutCString (close_paren); 2516 else 2517 s.PutChar(')'); 2518 2519 } 2520 else 2521 { 2522 s.PutCString(cstr); 2523 } 2524 } 2525 } 2526 else if (sc->symbol) 2527 { 2528 cstr = sc->symbol->GetName().AsCString (NULL); 2529 if (cstr) 2530 { 2531 s.PutCString(cstr); 2532 var_success = true; 2533 } 2534 } 2535 } 2536 else if (IsToken (var_name_begin, "addr-offset}") 2537 || IsToken (var_name_begin, "concrete-only-addr-offset-no-padding}")) 2538 { 2539 if (IsToken (var_name_begin, "concrete-only-addr-offset-no-padding}")) 2540 { 2541 addr_offset_print_with_no_padding = true; 2542 addr_offset_concrete_func_only = true; 2543 } 2544 var_success = addr != NULL; 2545 if (var_success) 2546 { 2547 format_addr = *addr; 2548 calculate_format_addr_function_offset = true; 2549 } 2550 } 2551 else if (IsToken (var_name_begin, "line-offset}")) 2552 { 2553 var_success = sc->line_entry.range.GetBaseAddress().IsValid(); 2554 if (var_success) 2555 { 2556 format_addr = sc->line_entry.range.GetBaseAddress(); 2557 calculate_format_addr_function_offset = true; 2558 } 2559 } 2560 else if (IsToken (var_name_begin, "pc-offset}")) 2561 { 2562 StackFrame *frame = exe_ctx->GetFramePtr(); 2563 var_success = frame != NULL; 2564 if (var_success) 2565 { 2566 format_addr = frame->GetFrameCodeAddress(); 2567 calculate_format_addr_function_offset = true; 2568 } 2569 } 2570 } 2571 } 2572 break; 2573 2574 case 'l': 2575 if (IsToken (var_name_begin, "line.")) 2576 { 2577 if (sc && sc->line_entry.IsValid()) 2578 { 2579 var_name_begin += ::strlen ("line."); 2580 if (IsToken (var_name_begin, "file.")) 2581 { 2582 var_name_begin += ::strlen ("file."); 2583 2584 if (IsToken (var_name_begin, "basename}")) 2585 { 2586 format_file_spec.GetFilename() = sc->line_entry.file.GetFilename(); 2587 var_success = (bool)format_file_spec; 2588 } 2589 else if (IsToken (var_name_begin, "fullpath}")) 2590 { 2591 format_file_spec = sc->line_entry.file; 2592 var_success = (bool)format_file_spec; 2593 } 2594 } 2595 else if (IsTokenWithFormat (var_name_begin, "number", token_format, "%" PRIu64, exe_ctx, sc)) 2596 { 2597 var_success = true; 2598 s.Printf(token_format.c_str(), (uint64_t)sc->line_entry.line); 2599 } 2600 else if ((IsToken (var_name_begin, "start-addr}")) || 2601 (IsToken (var_name_begin, "end-addr}"))) 2602 { 2603 var_success = sc && sc->line_entry.range.GetBaseAddress().IsValid(); 2604 if (var_success) 2605 { 2606 format_addr = sc->line_entry.range.GetBaseAddress(); 2607 if (var_name_begin[0] == 'e') 2608 format_addr.Slide (sc->line_entry.range.GetByteSize()); 2609 } 2610 } 2611 } 2612 } 2613 break; 2614 case 'c': 2615 if (IsToken (var_name_begin, "current-pc-arrow")) 2616 { 2617 if (addr && exe_ctx && exe_ctx->GetFramePtr()) 2618 { 2619 RegisterContextSP reg_ctx = exe_ctx->GetFramePtr()->GetRegisterContextSP(); 2620 if (reg_ctx.get()) 2621 { 2622 addr_t pc_loadaddr = reg_ctx->GetPC(); 2623 if (pc_loadaddr != LLDB_INVALID_ADDRESS) 2624 { 2625 Address pc; 2626 pc.SetLoadAddress (pc_loadaddr, exe_ctx->GetTargetPtr()); 2627 if (pc == *addr) 2628 { 2629 s.Printf ("-> "); 2630 var_success = true; 2631 } 2632 } 2633 } 2634 if (var_success == false) 2635 { 2636 s.Printf(" "); 2637 var_success = true; 2638 } 2639 } 2640 var_success = true; 2641 } 2642 break; 2643 } 2644 2645 if (var_success) 2646 { 2647 // If format addr is valid, then we need to print an address 2648 if (reg_num != LLDB_INVALID_REGNUM) 2649 { 2650 StackFrame *frame = exe_ctx->GetFramePtr(); 2651 // We have a register value to display... 2652 if (reg_num == LLDB_REGNUM_GENERIC_PC && reg_kind == eRegisterKindGeneric) 2653 { 2654 format_addr = frame->GetFrameCodeAddress(); 2655 } 2656 else 2657 { 2658 if (reg_ctx == NULL) 2659 reg_ctx = frame->GetRegisterContext().get(); 2660 2661 if (reg_ctx) 2662 { 2663 if (reg_kind != kNumRegisterKinds) 2664 reg_num = reg_ctx->ConvertRegisterKindToRegisterNumber(reg_kind, reg_num); 2665 reg_info = reg_ctx->GetRegisterInfoAtIndex (reg_num); 2666 var_success = reg_info != NULL; 2667 } 2668 } 2669 } 2670 2671 if (reg_info != NULL) 2672 { 2673 RegisterValue reg_value; 2674 var_success = reg_ctx->ReadRegister (reg_info, reg_value); 2675 if (var_success) 2676 { 2677 reg_value.Dump(&s, reg_info, false, false, eFormatDefault); 2678 } 2679 } 2680 2681 if (format_file_spec) 2682 { 2683 s << format_file_spec; 2684 } 2685 2686 // If format addr is valid, then we need to print an address 2687 if (format_addr.IsValid()) 2688 { 2689 var_success = false; 2690 2691 if (calculate_format_addr_function_offset) 2692 { 2693 Address func_addr; 2694 2695 if (sc) 2696 { 2697 if (sc->function) 2698 { 2699 func_addr = sc->function->GetAddressRange().GetBaseAddress(); 2700 if (sc->block && addr_offset_concrete_func_only == false) 2701 { 2702 // Check to make sure we aren't in an inline 2703 // function. If we are, use the inline block 2704 // range that contains "format_addr" since 2705 // blocks can be discontiguous. 2706 Block *inline_block = sc->block->GetContainingInlinedBlock (); 2707 AddressRange inline_range; 2708 if (inline_block && inline_block->GetRangeContainingAddress (format_addr, inline_range)) 2709 func_addr = inline_range.GetBaseAddress(); 2710 } 2711 } 2712 else if (sc->symbol && sc->symbol->ValueIsAddress()) 2713 func_addr = sc->symbol->GetAddress(); 2714 } 2715 2716 if (func_addr.IsValid()) 2717 { 2718 const char *addr_offset_padding = " "; 2719 if (addr_offset_print_with_no_padding) 2720 { 2721 addr_offset_padding = ""; 2722 } 2723 if (func_addr.GetSection() == format_addr.GetSection()) 2724 { 2725 addr_t func_file_addr = func_addr.GetFileAddress(); 2726 addr_t addr_file_addr = format_addr.GetFileAddress(); 2727 if (addr_file_addr > func_file_addr) 2728 s.Printf("%s+%s%" PRIu64, addr_offset_padding, addr_offset_padding, addr_file_addr - func_file_addr); 2729 else if (addr_file_addr < func_file_addr) 2730 s.Printf("%s-%s%" PRIu64, addr_offset_padding, addr_offset_padding, func_file_addr - addr_file_addr); 2731 var_success = true; 2732 } 2733 else 2734 { 2735 Target *target = Target::GetTargetFromContexts (exe_ctx, sc); 2736 if (target) 2737 { 2738 addr_t func_load_addr = func_addr.GetLoadAddress (target); 2739 addr_t addr_load_addr = format_addr.GetLoadAddress (target); 2740 if (addr_load_addr > func_load_addr) 2741 s.Printf("%s+%s%" PRIu64, addr_offset_padding, addr_offset_padding, addr_load_addr - func_load_addr); 2742 else if (addr_load_addr < func_load_addr) 2743 s.Printf("%s-%s%" PRIu64, addr_offset_padding, addr_offset_padding, func_load_addr - addr_load_addr); 2744 var_success = true; 2745 } 2746 } 2747 } 2748 } 2749 else 2750 { 2751 Target *target = Target::GetTargetFromContexts (exe_ctx, sc); 2752 addr_t vaddr = LLDB_INVALID_ADDRESS; 2753 if (exe_ctx && !target->GetSectionLoadList().IsEmpty()) 2754 vaddr = format_addr.GetLoadAddress (target); 2755 if (vaddr == LLDB_INVALID_ADDRESS) 2756 vaddr = format_addr.GetFileAddress (); 2757 2758 if (vaddr != LLDB_INVALID_ADDRESS) 2759 { 2760 int addr_width = 0; 2761 if (exe_ctx && target) 2762 { 2763 addr_width = target->GetArchitecture().GetAddressByteSize() * 2; 2764 } 2765 if (addr_width == 0) 2766 addr_width = 16; 2767 if (print_file_addr_or_load_addr) 2768 { 2769 format_addr.Dump (&s, exe_ctx ? exe_ctx->GetBestExecutionContextScope() : NULL, Address::DumpStyleLoadAddress, Address::DumpStyleModuleWithFileAddress, 0); 2770 } 2771 else 2772 { 2773 s.Printf("0x%*.*" PRIx64, addr_width, addr_width, vaddr); 2774 } 2775 var_success = true; 2776 } 2777 } 2778 } 2779 } 2780 2781 if (var_success == false) 2782 success = false; 2783 } 2784 p = var_name_end; 2785 } 2786 else 2787 break; 2788 } 2789 else 2790 { 2791 // We got a dollar sign with no '{' after it, it must just be a dollar sign 2792 s.PutChar(*p); 2793 } 2794 } 2795 else if (*p == '\\') 2796 { 2797 ++p; // skip the slash 2798 switch (*p) 2799 { 2800 case 'a': s.PutChar ('\a'); break; 2801 case 'b': s.PutChar ('\b'); break; 2802 case 'f': s.PutChar ('\f'); break; 2803 case 'n': s.PutChar ('\n'); break; 2804 case 'r': s.PutChar ('\r'); break; 2805 case 't': s.PutChar ('\t'); break; 2806 case 'v': s.PutChar ('\v'); break; 2807 case '\'': s.PutChar ('\''); break; 2808 case '\\': s.PutChar ('\\'); break; 2809 case '0': 2810 // 1 to 3 octal chars 2811 { 2812 // Make a string that can hold onto the initial zero char, 2813 // up to 3 octal digits, and a terminating NULL. 2814 char oct_str[5] = { 0, 0, 0, 0, 0 }; 2815 2816 int i; 2817 for (i=0; (p[i] >= '0' && p[i] <= '7') && i<4; ++i) 2818 oct_str[i] = p[i]; 2819 2820 // We don't want to consume the last octal character since 2821 // the main for loop will do this for us, so we advance p by 2822 // one less than i (even if i is zero) 2823 p += i - 1; 2824 unsigned long octal_value = ::strtoul (oct_str, NULL, 8); 2825 if (octal_value <= UINT8_MAX) 2826 { 2827 s.PutChar((char)octal_value); 2828 } 2829 } 2830 break; 2831 2832 case 'x': 2833 // hex number in the format 2834 if (isxdigit(p[1])) 2835 { 2836 ++p; // Skip the 'x' 2837 2838 // Make a string that can hold onto two hex chars plus a 2839 // NULL terminator 2840 char hex_str[3] = { 0,0,0 }; 2841 hex_str[0] = *p; 2842 if (isxdigit(p[1])) 2843 { 2844 ++p; // Skip the first of the two hex chars 2845 hex_str[1] = *p; 2846 } 2847 2848 unsigned long hex_value = strtoul (hex_str, NULL, 16); 2849 if (hex_value <= UINT8_MAX) 2850 s.PutChar ((char)hex_value); 2851 } 2852 else 2853 { 2854 s.PutChar('x'); 2855 } 2856 break; 2857 2858 default: 2859 // Just desensitize any other character by just printing what 2860 // came after the '\' 2861 s << *p; 2862 break; 2863 2864 } 2865 2866 } 2867 } 2868 if (end) 2869 *end = p; 2870 return success; 2871 } 2872 2873 bool 2874 Debugger::FormatPrompt 2875 ( 2876 const char *format, 2877 const SymbolContext *sc, 2878 const ExecutionContext *exe_ctx, 2879 const Address *addr, 2880 Stream &s, 2881 ValueObject* valobj 2882 ) 2883 { 2884 bool use_color = exe_ctx ? exe_ctx->GetTargetRef().GetDebugger().GetUseColor() : true; 2885 std::string format_str = lldb_utility::ansi::FormatAnsiTerminalCodes (format, use_color); 2886 if (format_str.length()) 2887 format = format_str.c_str(); 2888 return FormatPromptRecurse (format, sc, exe_ctx, addr, s, NULL, valobj, false, false); 2889 } 2890 2891 bool 2892 Debugger::FormatDisassemblerAddress (const char *format, 2893 const SymbolContext *sc, 2894 const SymbolContext *prev_sc, 2895 const ExecutionContext *exe_ctx, 2896 const Address *addr, 2897 Stream &s) 2898 { 2899 if (format == NULL && exe_ctx != NULL && exe_ctx->HasTargetScope()) 2900 { 2901 format = exe_ctx->GetTargetRef().GetDebugger().GetDisassemblyFormat(); 2902 } 2903 bool function_changed = false; 2904 bool initial_function = false; 2905 if (prev_sc && (prev_sc->function || prev_sc->symbol)) 2906 { 2907 if (sc && (sc->function || sc->symbol)) 2908 { 2909 if (prev_sc->symbol && sc->symbol) 2910 { 2911 if (!sc->symbol->Compare (prev_sc->symbol->GetName(), prev_sc->symbol->GetType())) 2912 { 2913 function_changed = true; 2914 } 2915 } 2916 else if (prev_sc->function && sc->function) 2917 { 2918 if (prev_sc->function->GetMangled() != sc->function->GetMangled()) 2919 { 2920 function_changed = true; 2921 } 2922 } 2923 } 2924 } 2925 // The first context on a list of instructions will have a prev_sc that 2926 // has no Function or Symbol -- if SymbolContext had an IsValid() method, it 2927 // would return false. But we do get a prev_sc pointer. 2928 if ((sc && (sc->function || sc->symbol)) 2929 && prev_sc && (prev_sc->function == NULL && prev_sc->symbol == NULL)) 2930 { 2931 initial_function = true; 2932 } 2933 return FormatPromptRecurse (format, sc, exe_ctx, addr, s, NULL, NULL, function_changed, initial_function); 2934 } 2935 2936 2937 void 2938 Debugger::SetLoggingCallback (lldb::LogOutputCallback log_callback, void *baton) 2939 { 2940 // For simplicity's sake, I am not going to deal with how to close down any 2941 // open logging streams, I just redirect everything from here on out to the 2942 // callback. 2943 m_log_callback_stream_sp.reset (new StreamCallback (log_callback, baton)); 2944 } 2945 2946 bool 2947 Debugger::EnableLog (const char *channel, const char **categories, const char *log_file, uint32_t log_options, Stream &error_stream) 2948 { 2949 Log::Callbacks log_callbacks; 2950 2951 StreamSP log_stream_sp; 2952 if (m_log_callback_stream_sp) 2953 { 2954 log_stream_sp = m_log_callback_stream_sp; 2955 // For now when using the callback mode you always get thread & timestamp. 2956 log_options |= LLDB_LOG_OPTION_PREPEND_TIMESTAMP | LLDB_LOG_OPTION_PREPEND_THREAD_NAME; 2957 } 2958 else if (log_file == NULL || *log_file == '\0') 2959 { 2960 log_stream_sp = GetOutputFile(); 2961 } 2962 else 2963 { 2964 LogStreamMap::iterator pos = m_log_streams.find(log_file); 2965 if (pos != m_log_streams.end()) 2966 log_stream_sp = pos->second.lock(); 2967 if (!log_stream_sp) 2968 { 2969 log_stream_sp.reset (new StreamFile (log_file)); 2970 m_log_streams[log_file] = log_stream_sp; 2971 } 2972 } 2973 assert (log_stream_sp.get()); 2974 2975 if (log_options == 0) 2976 log_options = LLDB_LOG_OPTION_PREPEND_THREAD_NAME | LLDB_LOG_OPTION_THREADSAFE; 2977 2978 if (Log::GetLogChannelCallbacks (ConstString(channel), log_callbacks)) 2979 { 2980 log_callbacks.enable (log_stream_sp, log_options, categories, &error_stream); 2981 return true; 2982 } 2983 else 2984 { 2985 LogChannelSP log_channel_sp (LogChannel::FindPlugin (channel)); 2986 if (log_channel_sp) 2987 { 2988 if (log_channel_sp->Enable (log_stream_sp, log_options, &error_stream, categories)) 2989 { 2990 return true; 2991 } 2992 else 2993 { 2994 error_stream.Printf ("Invalid log channel '%s'.\n", channel); 2995 return false; 2996 } 2997 } 2998 else 2999 { 3000 error_stream.Printf ("Invalid log channel '%s'.\n", channel); 3001 return false; 3002 } 3003 } 3004 return false; 3005 } 3006 3007 SourceManager & 3008 Debugger::GetSourceManager () 3009 { 3010 if (m_source_manager_ap.get() == NULL) 3011 m_source_manager_ap.reset (new SourceManager (shared_from_this())); 3012 return *m_source_manager_ap; 3013 } 3014 3015 3016 3017 // This function handles events that were broadcast by the process. 3018 void 3019 Debugger::HandleBreakpointEvent (const EventSP &event_sp) 3020 { 3021 using namespace lldb; 3022 const uint32_t event_type = Breakpoint::BreakpointEventData::GetBreakpointEventTypeFromEvent (event_sp); 3023 3024 // if (event_type & eBreakpointEventTypeAdded 3025 // || event_type & eBreakpointEventTypeRemoved 3026 // || event_type & eBreakpointEventTypeEnabled 3027 // || event_type & eBreakpointEventTypeDisabled 3028 // || event_type & eBreakpointEventTypeCommandChanged 3029 // || event_type & eBreakpointEventTypeConditionChanged 3030 // || event_type & eBreakpointEventTypeIgnoreChanged 3031 // || event_type & eBreakpointEventTypeLocationsResolved) 3032 // { 3033 // // Don't do anything about these events, since the breakpoint commands already echo these actions. 3034 // } 3035 // 3036 if (event_type & eBreakpointEventTypeLocationsAdded) 3037 { 3038 uint32_t num_new_locations = Breakpoint::BreakpointEventData::GetNumBreakpointLocationsFromEvent(event_sp); 3039 if (num_new_locations > 0) 3040 { 3041 BreakpointSP breakpoint = Breakpoint::BreakpointEventData::GetBreakpointFromEvent(event_sp); 3042 StreamFileSP output_sp (GetOutputFile()); 3043 if (output_sp) 3044 { 3045 output_sp->Printf("%d location%s added to breakpoint %d\n", 3046 num_new_locations, 3047 num_new_locations == 1 ? "" : "s", 3048 breakpoint->GetID()); 3049 RefreshTopIOHandler(); 3050 } 3051 } 3052 } 3053 // else if (event_type & eBreakpointEventTypeLocationsRemoved) 3054 // { 3055 // // These locations just get disabled, not sure it is worth spamming folks about this on the command line. 3056 // } 3057 // else if (event_type & eBreakpointEventTypeLocationsResolved) 3058 // { 3059 // // This might be an interesting thing to note, but I'm going to leave it quiet for now, it just looked noisy. 3060 // } 3061 } 3062 3063 size_t 3064 Debugger::GetProcessSTDOUT (Process *process, Stream *stream) 3065 { 3066 size_t total_bytes = 0; 3067 if (stream == NULL) 3068 stream = GetOutputFile().get(); 3069 3070 if (stream) 3071 { 3072 // The process has stuff waiting for stdout; get it and write it out to the appropriate place. 3073 if (process == NULL) 3074 { 3075 TargetSP target_sp = GetTargetList().GetSelectedTarget(); 3076 if (target_sp) 3077 process = target_sp->GetProcessSP().get(); 3078 } 3079 if (process) 3080 { 3081 Error error; 3082 size_t len; 3083 char stdio_buffer[1024]; 3084 while ((len = process->GetSTDOUT (stdio_buffer, sizeof (stdio_buffer), error)) > 0) 3085 { 3086 stream->Write(stdio_buffer, len); 3087 total_bytes += len; 3088 } 3089 } 3090 stream->Flush(); 3091 } 3092 return total_bytes; 3093 } 3094 3095 size_t 3096 Debugger::GetProcessSTDERR (Process *process, Stream *stream) 3097 { 3098 size_t total_bytes = 0; 3099 if (stream == NULL) 3100 stream = GetOutputFile().get(); 3101 3102 if (stream) 3103 { 3104 // The process has stuff waiting for stderr; get it and write it out to the appropriate place. 3105 if (process == NULL) 3106 { 3107 TargetSP target_sp = GetTargetList().GetSelectedTarget(); 3108 if (target_sp) 3109 process = target_sp->GetProcessSP().get(); 3110 } 3111 if (process) 3112 { 3113 Error error; 3114 size_t len; 3115 char stdio_buffer[1024]; 3116 while ((len = process->GetSTDERR (stdio_buffer, sizeof (stdio_buffer), error)) > 0) 3117 { 3118 stream->Write(stdio_buffer, len); 3119 total_bytes += len; 3120 } 3121 } 3122 stream->Flush(); 3123 } 3124 return total_bytes; 3125 } 3126 3127 3128 // This function handles events that were broadcast by the process. 3129 void 3130 Debugger::HandleProcessEvent (const EventSP &event_sp) 3131 { 3132 using namespace lldb; 3133 const uint32_t event_type = event_sp->GetType(); 3134 ProcessSP process_sp = Process::ProcessEventData::GetProcessFromEvent(event_sp.get()); 3135 3136 StreamString output_stream; 3137 StreamString error_stream; 3138 const bool gui_enabled = IsForwardingEvents(); 3139 3140 if (!gui_enabled) 3141 { 3142 bool pop_process_io_handler = false; 3143 assert (process_sp); 3144 3145 if (event_type & Process::eBroadcastBitSTDOUT || event_type & Process::eBroadcastBitStateChanged) 3146 { 3147 GetProcessSTDOUT (process_sp.get(), &output_stream); 3148 } 3149 3150 if (event_type & Process::eBroadcastBitSTDERR || event_type & Process::eBroadcastBitStateChanged) 3151 { 3152 GetProcessSTDERR (process_sp.get(), &error_stream); 3153 } 3154 3155 if (event_type & Process::eBroadcastBitStateChanged) 3156 { 3157 Process::HandleProcessStateChangedEvent (event_sp, &output_stream, pop_process_io_handler); 3158 } 3159 3160 if (output_stream.GetSize() || error_stream.GetSize()) 3161 { 3162 StreamFileSP error_stream_sp (GetOutputFile()); 3163 bool top_io_handler_hid = false; 3164 3165 if (process_sp->ProcessIOHandlerIsActive() == false) 3166 top_io_handler_hid = HideTopIOHandler(); 3167 3168 if (output_stream.GetSize()) 3169 { 3170 StreamFileSP output_stream_sp (GetOutputFile()); 3171 if (output_stream_sp) 3172 output_stream_sp->Write (output_stream.GetData(), output_stream.GetSize()); 3173 } 3174 3175 if (error_stream.GetSize()) 3176 { 3177 StreamFileSP error_stream_sp (GetErrorFile()); 3178 if (error_stream_sp) 3179 error_stream_sp->Write (error_stream.GetData(), error_stream.GetSize()); 3180 } 3181 3182 if (top_io_handler_hid) 3183 RefreshTopIOHandler(); 3184 } 3185 3186 if (pop_process_io_handler) 3187 process_sp->PopProcessIOHandler(); 3188 } 3189 } 3190 3191 void 3192 Debugger::HandleThreadEvent (const EventSP &event_sp) 3193 { 3194 // At present the only thread event we handle is the Frame Changed event, 3195 // and all we do for that is just reprint the thread status for that thread. 3196 using namespace lldb; 3197 const uint32_t event_type = event_sp->GetType(); 3198 if (event_type == Thread::eBroadcastBitStackChanged || 3199 event_type == Thread::eBroadcastBitThreadSelected ) 3200 { 3201 ThreadSP thread_sp (Thread::ThreadEventData::GetThreadFromEvent (event_sp.get())); 3202 if (thread_sp) 3203 { 3204 HideTopIOHandler(); 3205 StreamFileSP stream_sp (GetOutputFile()); 3206 thread_sp->GetStatus(*stream_sp, 0, 1, 1); 3207 RefreshTopIOHandler(); 3208 } 3209 } 3210 } 3211 3212 bool 3213 Debugger::IsForwardingEvents () 3214 { 3215 return (bool)m_forward_listener_sp; 3216 } 3217 3218 void 3219 Debugger::EnableForwardEvents (const ListenerSP &listener_sp) 3220 { 3221 m_forward_listener_sp = listener_sp; 3222 } 3223 3224 void 3225 Debugger::CancelForwardEvents (const ListenerSP &listener_sp) 3226 { 3227 m_forward_listener_sp.reset(); 3228 } 3229 3230 3231 void 3232 Debugger::DefaultEventHandler() 3233 { 3234 Listener& listener(GetListener()); 3235 ConstString broadcaster_class_target(Target::GetStaticBroadcasterClass()); 3236 ConstString broadcaster_class_process(Process::GetStaticBroadcasterClass()); 3237 ConstString broadcaster_class_thread(Thread::GetStaticBroadcasterClass()); 3238 BroadcastEventSpec target_event_spec (broadcaster_class_target, 3239 Target::eBroadcastBitBreakpointChanged); 3240 3241 BroadcastEventSpec process_event_spec (broadcaster_class_process, 3242 Process::eBroadcastBitStateChanged | 3243 Process::eBroadcastBitSTDOUT | 3244 Process::eBroadcastBitSTDERR); 3245 3246 BroadcastEventSpec thread_event_spec (broadcaster_class_thread, 3247 Thread::eBroadcastBitStackChanged | 3248 Thread::eBroadcastBitThreadSelected ); 3249 3250 listener.StartListeningForEventSpec (*this, target_event_spec); 3251 listener.StartListeningForEventSpec (*this, process_event_spec); 3252 listener.StartListeningForEventSpec (*this, thread_event_spec); 3253 listener.StartListeningForEvents (m_command_interpreter_ap.get(), 3254 CommandInterpreter::eBroadcastBitQuitCommandReceived | 3255 CommandInterpreter::eBroadcastBitAsynchronousOutputData | 3256 CommandInterpreter::eBroadcastBitAsynchronousErrorData ); 3257 3258 // Let the thread that spawned us know that we have started up and 3259 // that we are now listening to all required events so no events get missed 3260 m_sync_broadcaster.BroadcastEvent(eBroadcastBitEventThreadIsListening); 3261 3262 bool done = false; 3263 while (!done) 3264 { 3265 EventSP event_sp; 3266 if (listener.WaitForEvent(NULL, event_sp)) 3267 { 3268 if (event_sp) 3269 { 3270 Broadcaster *broadcaster = event_sp->GetBroadcaster(); 3271 if (broadcaster) 3272 { 3273 uint32_t event_type = event_sp->GetType(); 3274 ConstString broadcaster_class (broadcaster->GetBroadcasterClass()); 3275 if (broadcaster_class == broadcaster_class_process) 3276 { 3277 HandleProcessEvent (event_sp); 3278 } 3279 else if (broadcaster_class == broadcaster_class_target) 3280 { 3281 if (Breakpoint::BreakpointEventData::GetEventDataFromEvent(event_sp.get())) 3282 { 3283 HandleBreakpointEvent (event_sp); 3284 } 3285 } 3286 else if (broadcaster_class == broadcaster_class_thread) 3287 { 3288 HandleThreadEvent (event_sp); 3289 } 3290 else if (broadcaster == m_command_interpreter_ap.get()) 3291 { 3292 if (event_type & CommandInterpreter::eBroadcastBitQuitCommandReceived) 3293 { 3294 done = true; 3295 } 3296 else if (event_type & CommandInterpreter::eBroadcastBitAsynchronousErrorData) 3297 { 3298 const char *data = reinterpret_cast<const char *>(EventDataBytes::GetBytesFromEvent (event_sp.get())); 3299 if (data && data[0]) 3300 { 3301 StreamFileSP error_sp (GetErrorFile()); 3302 if (error_sp) 3303 { 3304 HideTopIOHandler(); 3305 error_sp->PutCString(data); 3306 error_sp->Flush(); 3307 RefreshTopIOHandler(); 3308 } 3309 } 3310 } 3311 else if (event_type & CommandInterpreter::eBroadcastBitAsynchronousOutputData) 3312 { 3313 const char *data = reinterpret_cast<const char *>(EventDataBytes::GetBytesFromEvent (event_sp.get())); 3314 if (data && data[0]) 3315 { 3316 StreamFileSP output_sp (GetOutputFile()); 3317 if (output_sp) 3318 { 3319 HideTopIOHandler(); 3320 output_sp->PutCString(data); 3321 output_sp->Flush(); 3322 RefreshTopIOHandler(); 3323 } 3324 } 3325 } 3326 } 3327 } 3328 3329 if (m_forward_listener_sp) 3330 m_forward_listener_sp->AddEvent(event_sp); 3331 } 3332 } 3333 } 3334 } 3335 3336 lldb::thread_result_t 3337 Debugger::EventHandlerThread (lldb::thread_arg_t arg) 3338 { 3339 ((Debugger *)arg)->DefaultEventHandler(); 3340 return NULL; 3341 } 3342 3343 bool 3344 Debugger::StartEventHandlerThread() 3345 { 3346 if (!m_event_handler_thread.IsJoinable()) 3347 { 3348 // We must synchronize with the DefaultEventHandler() thread to ensure 3349 // it is up and running and listening to events before we return from 3350 // this function. We do this by listening to events for the 3351 // eBroadcastBitEventThreadIsListening from the m_sync_broadcaster 3352 Listener listener("lldb.debugger.event-handler"); 3353 listener.StartListeningForEvents(&m_sync_broadcaster, eBroadcastBitEventThreadIsListening); 3354 3355 // Use larger 8MB stack for this thread 3356 m_event_handler_thread = ThreadLauncher::LaunchThread("lldb.debugger.event-handler", EventHandlerThread, 3357 this, 3358 NULL, 3359 g_debugger_event_thread_stack_bytes); 3360 3361 // Make sure DefaultEventHandler() is running and listening to events before we return 3362 // from this function. We are only listening for events of type 3363 // eBroadcastBitEventThreadIsListening so we don't need to check the event, we just need 3364 // to wait an infinite amount of time for it (NULL timeout as the first parameter) 3365 lldb::EventSP event_sp; 3366 listener.WaitForEvent(NULL, event_sp); 3367 } 3368 return m_event_handler_thread.IsJoinable(); 3369 } 3370 3371 void 3372 Debugger::StopEventHandlerThread() 3373 { 3374 if (m_event_handler_thread.IsJoinable()) 3375 { 3376 GetCommandInterpreter().BroadcastEvent(CommandInterpreter::eBroadcastBitQuitCommandReceived); 3377 m_event_handler_thread.Join(nullptr); 3378 } 3379 } 3380 3381 3382 lldb::thread_result_t 3383 Debugger::IOHandlerThread (lldb::thread_arg_t arg) 3384 { 3385 Debugger *debugger = (Debugger *)arg; 3386 debugger->ExecuteIOHanders(); 3387 debugger->StopEventHandlerThread(); 3388 return NULL; 3389 } 3390 3391 bool 3392 Debugger::StartIOHandlerThread() 3393 { 3394 if (!m_io_handler_thread.IsJoinable()) 3395 m_io_handler_thread = ThreadLauncher::LaunchThread ("lldb.debugger.io-handler", 3396 IOHandlerThread, 3397 this, 3398 NULL, 3399 8*1024*1024); // Use larger 8MB stack for this thread 3400 return m_io_handler_thread.IsJoinable(); 3401 } 3402 3403 void 3404 Debugger::StopIOHandlerThread() 3405 { 3406 if (m_io_handler_thread.IsJoinable()) 3407 { 3408 if (m_input_file_sp) 3409 m_input_file_sp->GetFile().Close(); 3410 m_io_handler_thread.Join(nullptr); 3411 } 3412 } 3413 3414 Target * 3415 Debugger::GetDummyTarget() 3416 { 3417 return m_target_list.GetDummyTarget (*this).get(); 3418 } 3419 3420 Target * 3421 Debugger::GetSelectedOrDummyTarget(bool prefer_dummy) 3422 { 3423 Target *target = nullptr; 3424 if (!prefer_dummy) 3425 { 3426 target = m_target_list.GetSelectedTarget().get(); 3427 if (target) 3428 return target; 3429 } 3430 3431 return GetDummyTarget(); 3432 } 3433 3434