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 const char * 931 Debugger::GetIOHandlerCommandPrefix() 932 { 933 return m_input_reader_stack.GetTopIOHandlerCommandPrefix(); 934 } 935 936 const char * 937 Debugger::GetIOHandlerHelpPrologue() 938 { 939 return m_input_reader_stack.GetTopIOHandlerHelpPrologue(); 940 } 941 942 void 943 Debugger::RunIOHandler (const IOHandlerSP& reader_sp) 944 { 945 PushIOHandler (reader_sp); 946 947 IOHandlerSP top_reader_sp = reader_sp; 948 while (top_reader_sp) 949 { 950 top_reader_sp->Activate(); 951 top_reader_sp->Run(); 952 top_reader_sp->Deactivate(); 953 954 if (top_reader_sp.get() == reader_sp.get()) 955 { 956 if (PopIOHandler (reader_sp)) 957 break; 958 } 959 960 while (1) 961 { 962 top_reader_sp = m_input_reader_stack.Top(); 963 if (top_reader_sp && top_reader_sp->GetIsDone()) 964 m_input_reader_stack.Pop(); 965 else 966 break; 967 } 968 } 969 } 970 971 void 972 Debugger::AdoptTopIOHandlerFilesIfInvalid (StreamFileSP &in, StreamFileSP &out, StreamFileSP &err) 973 { 974 // Before an IOHandler runs, it must have in/out/err streams. 975 // This function is called when one ore more of the streams 976 // are NULL. We use the top input reader's in/out/err streams, 977 // or fall back to the debugger file handles, or we fall back 978 // onto stdin/stdout/stderr as a last resort. 979 980 Mutex::Locker locker (m_input_reader_stack.GetMutex()); 981 IOHandlerSP top_reader_sp (m_input_reader_stack.Top()); 982 // If no STDIN has been set, then set it appropriately 983 if (!in) 984 { 985 if (top_reader_sp) 986 in = top_reader_sp->GetInputStreamFile(); 987 else 988 in = GetInputFile(); 989 990 // If there is nothing, use stdin 991 if (!in) 992 in = StreamFileSP(new StreamFile(stdin, false)); 993 } 994 // If no STDOUT has been set, then set it appropriately 995 if (!out) 996 { 997 if (top_reader_sp) 998 out = top_reader_sp->GetOutputStreamFile(); 999 else 1000 out = GetOutputFile(); 1001 1002 // If there is nothing, use stdout 1003 if (!out) 1004 out = StreamFileSP(new StreamFile(stdout, false)); 1005 } 1006 // If no STDERR has been set, then set it appropriately 1007 if (!err) 1008 { 1009 if (top_reader_sp) 1010 err = top_reader_sp->GetErrorStreamFile(); 1011 else 1012 err = GetErrorFile(); 1013 1014 // If there is nothing, use stderr 1015 if (!err) 1016 err = StreamFileSP(new StreamFile(stdout, false)); 1017 1018 } 1019 } 1020 1021 void 1022 Debugger::PushIOHandler (const IOHandlerSP& reader_sp) 1023 { 1024 if (!reader_sp) 1025 return; 1026 1027 // Got the current top input reader... 1028 IOHandlerSP top_reader_sp (m_input_reader_stack.Top()); 1029 1030 // Don't push the same IO handler twice... 1031 if (reader_sp.get() != top_reader_sp.get()) 1032 { 1033 // Push our new input reader 1034 m_input_reader_stack.Push (reader_sp); 1035 1036 // Interrupt the top input reader to it will exit its Run() function 1037 // and let this new input reader take over 1038 if (top_reader_sp) 1039 top_reader_sp->Deactivate(); 1040 } 1041 } 1042 1043 bool 1044 Debugger::PopIOHandler (const IOHandlerSP& pop_reader_sp) 1045 { 1046 bool result = false; 1047 1048 Mutex::Locker locker (m_input_reader_stack.GetMutex()); 1049 1050 // The reader on the stop of the stack is done, so let the next 1051 // read on the stack refresh its prompt and if there is one... 1052 if (!m_input_reader_stack.IsEmpty()) 1053 { 1054 IOHandlerSP reader_sp(m_input_reader_stack.Top()); 1055 1056 if (!pop_reader_sp || pop_reader_sp.get() == reader_sp.get()) 1057 { 1058 reader_sp->Deactivate(); 1059 reader_sp->Cancel(); 1060 m_input_reader_stack.Pop (); 1061 1062 reader_sp = m_input_reader_stack.Top(); 1063 if (reader_sp) 1064 reader_sp->Activate(); 1065 1066 result = true; 1067 } 1068 } 1069 return result; 1070 } 1071 1072 bool 1073 Debugger::HideTopIOHandler() 1074 { 1075 Mutex::Locker locker; 1076 1077 if (locker.TryLock(m_input_reader_stack.GetMutex())) 1078 { 1079 IOHandlerSP reader_sp(m_input_reader_stack.Top()); 1080 if (reader_sp) 1081 reader_sp->Hide(); 1082 return true; 1083 } 1084 return false; 1085 } 1086 1087 void 1088 Debugger::RefreshTopIOHandler() 1089 { 1090 IOHandlerSP reader_sp(m_input_reader_stack.Top()); 1091 if (reader_sp) 1092 reader_sp->Refresh(); 1093 } 1094 1095 1096 StreamSP 1097 Debugger::GetAsyncOutputStream () 1098 { 1099 return StreamSP (new StreamAsynchronousIO (GetCommandInterpreter(), 1100 CommandInterpreter::eBroadcastBitAsynchronousOutputData)); 1101 } 1102 1103 StreamSP 1104 Debugger::GetAsyncErrorStream () 1105 { 1106 return StreamSP (new StreamAsynchronousIO (GetCommandInterpreter(), 1107 CommandInterpreter::eBroadcastBitAsynchronousErrorData)); 1108 } 1109 1110 size_t 1111 Debugger::GetNumDebuggers() 1112 { 1113 if (g_shared_debugger_refcount > 0) 1114 { 1115 Mutex::Locker locker (GetDebuggerListMutex ()); 1116 return GetDebuggerList().size(); 1117 } 1118 return 0; 1119 } 1120 1121 lldb::DebuggerSP 1122 Debugger::GetDebuggerAtIndex (size_t index) 1123 { 1124 DebuggerSP debugger_sp; 1125 1126 if (g_shared_debugger_refcount > 0) 1127 { 1128 Mutex::Locker locker (GetDebuggerListMutex ()); 1129 DebuggerList &debugger_list = GetDebuggerList(); 1130 1131 if (index < debugger_list.size()) 1132 debugger_sp = debugger_list[index]; 1133 } 1134 1135 return debugger_sp; 1136 } 1137 1138 DebuggerSP 1139 Debugger::FindDebuggerWithID (lldb::user_id_t id) 1140 { 1141 DebuggerSP debugger_sp; 1142 1143 if (g_shared_debugger_refcount > 0) 1144 { 1145 Mutex::Locker locker (GetDebuggerListMutex ()); 1146 DebuggerList &debugger_list = GetDebuggerList(); 1147 DebuggerList::iterator pos, end = debugger_list.end(); 1148 for (pos = debugger_list.begin(); pos != end; ++pos) 1149 { 1150 if ((*pos).get()->GetID() == id) 1151 { 1152 debugger_sp = *pos; 1153 break; 1154 } 1155 } 1156 } 1157 return debugger_sp; 1158 } 1159 1160 #if 0 1161 static void 1162 TestPromptFormats (StackFrame *frame) 1163 { 1164 if (frame == NULL) 1165 return; 1166 1167 StreamString s; 1168 const char *prompt_format = 1169 "{addr = '${addr}'\n}" 1170 "{addr-file-or-load = '${addr-file-or-load}'\n}" 1171 "{current-pc-arrow = '${current-pc-arrow}'\n}" 1172 "{process.id = '${process.id}'\n}" 1173 "{process.name = '${process.name}'\n}" 1174 "{process.file.basename = '${process.file.basename}'\n}" 1175 "{process.file.fullpath = '${process.file.fullpath}'\n}" 1176 "{thread.id = '${thread.id}'\n}" 1177 "{thread.index = '${thread.index}'\n}" 1178 "{thread.name = '${thread.name}'\n}" 1179 "{thread.queue = '${thread.queue}'\n}" 1180 "{thread.stop-reason = '${thread.stop-reason}'\n}" 1181 "{target.arch = '${target.arch}'\n}" 1182 "{module.file.basename = '${module.file.basename}'\n}" 1183 "{module.file.fullpath = '${module.file.fullpath}'\n}" 1184 "{file.basename = '${file.basename}'\n}" 1185 "{file.fullpath = '${file.fullpath}'\n}" 1186 "{frame.index = '${frame.index}'\n}" 1187 "{frame.pc = '${frame.pc}'\n}" 1188 "{frame.sp = '${frame.sp}'\n}" 1189 "{frame.fp = '${frame.fp}'\n}" 1190 "{frame.flags = '${frame.flags}'\n}" 1191 "{frame.reg.rdi = '${frame.reg.rdi}'\n}" 1192 "{frame.reg.rip = '${frame.reg.rip}'\n}" 1193 "{frame.reg.rsp = '${frame.reg.rsp}'\n}" 1194 "{frame.reg.rbp = '${frame.reg.rbp}'\n}" 1195 "{frame.reg.rflags = '${frame.reg.rflags}'\n}" 1196 "{frame.reg.xmm0 = '${frame.reg.xmm0}'\n}" 1197 "{frame.reg.carp = '${frame.reg.carp}'\n}" 1198 "{function.id = '${function.id}'\n}" 1199 "{function.changed = '${function.changed}'\n}" 1200 "{function.initial-function = '${function.initial-function}'\n}" 1201 "{function.name = '${function.name}'\n}" 1202 "{function.name-without-args = '${function.name-without-args}'\n}" 1203 "{function.name-with-args = '${function.name-with-args}'\n}" 1204 "{function.addr-offset = '${function.addr-offset}'\n}" 1205 "{function.concrete-only-addr-offset-no-padding = '${function.concrete-only-addr-offset-no-padding}'\n}" 1206 "{function.line-offset = '${function.line-offset}'\n}" 1207 "{function.pc-offset = '${function.pc-offset}'\n}" 1208 "{line.file.basename = '${line.file.basename}'\n}" 1209 "{line.file.fullpath = '${line.file.fullpath}'\n}" 1210 "{line.number = '${line.number}'\n}" 1211 "{line.start-addr = '${line.start-addr}'\n}" 1212 "{line.end-addr = '${line.end-addr}'\n}" 1213 ; 1214 1215 SymbolContext sc (frame->GetSymbolContext(eSymbolContextEverything)); 1216 ExecutionContext exe_ctx; 1217 frame->CalculateExecutionContext(exe_ctx); 1218 if (Debugger::FormatPrompt (prompt_format, &sc, &exe_ctx, &sc.line_entry.range.GetBaseAddress(), s)) 1219 { 1220 printf("%s\n", s.GetData()); 1221 } 1222 else 1223 { 1224 printf ("what we got: %s\n", s.GetData()); 1225 } 1226 } 1227 #endif 1228 1229 static bool 1230 ScanFormatDescriptor (const char* var_name_begin, 1231 const char* var_name_end, 1232 const char** var_name_final, 1233 const char** percent_position, 1234 Format* custom_format, 1235 ValueObject::ValueObjectRepresentationStyle* val_obj_display) 1236 { 1237 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES)); 1238 *percent_position = ::strchr(var_name_begin,'%'); 1239 if (!*percent_position || *percent_position > var_name_end) 1240 { 1241 if (log) 1242 log->Printf("[ScanFormatDescriptor] no format descriptor in string, skipping"); 1243 *var_name_final = var_name_end; 1244 } 1245 else 1246 { 1247 *var_name_final = *percent_position; 1248 std::string format_name(*var_name_final+1, var_name_end-*var_name_final-1); 1249 if (log) 1250 log->Printf("[ScanFormatDescriptor] parsing %s as a format descriptor", format_name.c_str()); 1251 if ( !FormatManager::GetFormatFromCString(format_name.c_str(), 1252 true, 1253 *custom_format) ) 1254 { 1255 if (log) 1256 log->Printf("[ScanFormatDescriptor] %s is an unknown format", format_name.c_str()); 1257 1258 switch (format_name.front()) 1259 { 1260 case '@': // if this is an @ sign, print ObjC description 1261 *val_obj_display = ValueObject::eValueObjectRepresentationStyleLanguageSpecific; 1262 break; 1263 case 'V': // if this is a V, print the value using the default format 1264 *val_obj_display = ValueObject::eValueObjectRepresentationStyleValue; 1265 break; 1266 case 'L': // if this is an L, print the location of the value 1267 *val_obj_display = ValueObject::eValueObjectRepresentationStyleLocation; 1268 break; 1269 case 'S': // if this is an S, print the summary after all 1270 *val_obj_display = ValueObject::eValueObjectRepresentationStyleSummary; 1271 break; 1272 case '#': // if this is a '#', print the number of children 1273 *val_obj_display = ValueObject::eValueObjectRepresentationStyleChildrenCount; 1274 break; 1275 case 'T': // if this is a 'T', print the type 1276 *val_obj_display = ValueObject::eValueObjectRepresentationStyleType; 1277 break; 1278 case 'N': // if this is a 'N', print the name 1279 *val_obj_display = ValueObject::eValueObjectRepresentationStyleName; 1280 break; 1281 case '>': // if this is a '>', print the name 1282 *val_obj_display = ValueObject::eValueObjectRepresentationStyleExpressionPath; 1283 break; 1284 default: 1285 if (log) 1286 log->Printf("ScanFormatDescriptor] %s is an error, leaving the previous value alone", format_name.c_str()); 1287 break; 1288 } 1289 } 1290 // a good custom format tells us to print the value using it 1291 else 1292 { 1293 if (log) 1294 log->Printf("[ScanFormatDescriptor] will display value for this VO"); 1295 *val_obj_display = ValueObject::eValueObjectRepresentationStyleValue; 1296 } 1297 } 1298 if (log) 1299 log->Printf("[ScanFormatDescriptor] final format description outcome: custom_format = %d, val_obj_display = %d", 1300 *custom_format, 1301 *val_obj_display); 1302 return true; 1303 } 1304 1305 static bool 1306 ScanBracketedRange (const char* var_name_begin, 1307 const char* var_name_end, 1308 const char* var_name_final, 1309 const char** open_bracket_position, 1310 const char** separator_position, 1311 const char** close_bracket_position, 1312 const char** var_name_final_if_array_range, 1313 int64_t* index_lower, 1314 int64_t* index_higher) 1315 { 1316 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES)); 1317 *open_bracket_position = ::strchr(var_name_begin,'['); 1318 if (*open_bracket_position && *open_bracket_position < var_name_final) 1319 { 1320 *separator_position = ::strchr(*open_bracket_position,'-'); // might be NULL if this is a simple var[N] bitfield 1321 *close_bracket_position = ::strchr(*open_bracket_position,']'); 1322 // as usual, we assume that [] will come before % 1323 //printf("trying to expand a []\n"); 1324 *var_name_final_if_array_range = *open_bracket_position; 1325 if (*close_bracket_position - *open_bracket_position == 1) 1326 { 1327 if (log) 1328 log->Printf("[ScanBracketedRange] '[]' detected.. going from 0 to end of data"); 1329 *index_lower = 0; 1330 } 1331 else if (*separator_position == NULL || *separator_position > var_name_end) 1332 { 1333 char *end = NULL; 1334 *index_lower = ::strtoul (*open_bracket_position+1, &end, 0); 1335 *index_higher = *index_lower; 1336 if (log) 1337 log->Printf("[ScanBracketedRange] [%" PRId64 "] detected, high index is same", *index_lower); 1338 } 1339 else if (*close_bracket_position && *close_bracket_position < var_name_end) 1340 { 1341 char *end = NULL; 1342 *index_lower = ::strtoul (*open_bracket_position+1, &end, 0); 1343 *index_higher = ::strtoul (*separator_position+1, &end, 0); 1344 if (log) 1345 log->Printf("[ScanBracketedRange] [%" PRId64 "-%" PRId64 "] detected", *index_lower, *index_higher); 1346 } 1347 else 1348 { 1349 if (log) 1350 log->Printf("[ScanBracketedRange] expression is erroneous, cannot extract indices out of it"); 1351 return false; 1352 } 1353 if (*index_lower > *index_higher && *index_higher > 0) 1354 { 1355 if (log) 1356 log->Printf("[ScanBracketedRange] swapping indices"); 1357 int64_t temp = *index_lower; 1358 *index_lower = *index_higher; 1359 *index_higher = temp; 1360 } 1361 } 1362 else if (log) 1363 log->Printf("[ScanBracketedRange] no bracketed range, skipping entirely"); 1364 return true; 1365 } 1366 1367 template <typename T> 1368 static bool RunScriptFormatKeyword(Stream &s, ScriptInterpreter *script_interpreter, T t, const std::string& script_name) 1369 { 1370 if (script_interpreter) 1371 { 1372 Error script_error; 1373 std::string script_output; 1374 1375 if (script_interpreter->RunScriptFormatKeyword(script_name.c_str(), t, script_output, script_error) && script_error.Success()) 1376 { 1377 s.Printf("%s", script_output.c_str()); 1378 return true; 1379 } 1380 else 1381 { 1382 s.Printf("<error: %s>",script_error.AsCString()); 1383 } 1384 } 1385 return false; 1386 } 1387 1388 static ValueObjectSP 1389 ExpandIndexedExpression (ValueObject* valobj, 1390 size_t index, 1391 StackFrame* frame, 1392 bool deref_pointer) 1393 { 1394 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES)); 1395 const char* ptr_deref_format = "[%d]"; 1396 std::string ptr_deref_buffer(10,0); 1397 ::sprintf(&ptr_deref_buffer[0], ptr_deref_format, index); 1398 if (log) 1399 log->Printf("[ExpandIndexedExpression] name to deref: %s",ptr_deref_buffer.c_str()); 1400 const char* first_unparsed; 1401 ValueObject::GetValueForExpressionPathOptions options; 1402 ValueObject::ExpressionPathEndResultType final_value_type; 1403 ValueObject::ExpressionPathScanEndReason reason_to_stop; 1404 ValueObject::ExpressionPathAftermath what_next = (deref_pointer ? ValueObject::eExpressionPathAftermathDereference : ValueObject::eExpressionPathAftermathNothing); 1405 ValueObjectSP item = valobj->GetValueForExpressionPath (ptr_deref_buffer.c_str(), 1406 &first_unparsed, 1407 &reason_to_stop, 1408 &final_value_type, 1409 options, 1410 &what_next); 1411 if (!item) 1412 { 1413 if (log) 1414 log->Printf("[ExpandIndexedExpression] ERROR: unparsed portion = %s, why stopping = %d," 1415 " final_value_type %d", 1416 first_unparsed, reason_to_stop, final_value_type); 1417 } 1418 else 1419 { 1420 if (log) 1421 log->Printf("[ExpandIndexedExpression] ALL RIGHT: unparsed portion = %s, why stopping = %d," 1422 " final_value_type %d", 1423 first_unparsed, reason_to_stop, final_value_type); 1424 } 1425 return item; 1426 } 1427 1428 static inline bool 1429 IsToken(const char *var_name_begin, const char *var) 1430 { 1431 return (::strncmp (var_name_begin, var, strlen(var)) == 0); 1432 } 1433 1434 static bool 1435 IsTokenWithFormat(const char *var_name_begin, const char *var, std::string &format, const char *default_format, 1436 const ExecutionContext *exe_ctx_ptr, const SymbolContext *sc_ptr) 1437 { 1438 int var_len = strlen(var); 1439 if (::strncmp (var_name_begin, var, var_len) == 0) 1440 { 1441 var_name_begin += var_len; 1442 if (*var_name_begin == '}') 1443 { 1444 format = default_format; 1445 return true; 1446 } 1447 else if (*var_name_begin == '%') 1448 { 1449 // Allow format specifiers: x|X|u with optional width specifiers. 1450 // ${thread.id%x} ; hex 1451 // ${thread.id%X} ; uppercase hex 1452 // ${thread.id%u} ; unsigned decimal 1453 // ${thread.id%8.8X} ; width.precision + specifier 1454 // ${thread.id%tid} ; unsigned on FreeBSD/Linux, otherwise default_format (0x%4.4x for thread.id) 1455 int dot_count = 0; 1456 const char *specifier = NULL; 1457 int width_precision_length = 0; 1458 const char *width_precision = ++var_name_begin; 1459 while (isdigit(*var_name_begin) || *var_name_begin == '.') 1460 { 1461 dot_count += (*var_name_begin == '.'); 1462 if (dot_count > 1) 1463 break; 1464 var_name_begin++; 1465 width_precision_length++; 1466 } 1467 1468 if (IsToken (var_name_begin, "tid}")) 1469 { 1470 Target *target = Target::GetTargetFromContexts (exe_ctx_ptr, sc_ptr); 1471 if (target) 1472 { 1473 ArchSpec arch (target->GetArchitecture ()); 1474 llvm::Triple::OSType ostype = arch.IsValid() ? arch.GetTriple().getOS() : llvm::Triple::UnknownOS; 1475 if ((ostype == llvm::Triple::FreeBSD) || (ostype == llvm::Triple::Linux)) 1476 specifier = PRIu64; 1477 } 1478 if (!specifier) 1479 { 1480 format = default_format; 1481 return true; 1482 } 1483 } 1484 else if (IsToken (var_name_begin, "x}")) 1485 specifier = PRIx64; 1486 else if (IsToken (var_name_begin, "X}")) 1487 specifier = PRIX64; 1488 else if (IsToken (var_name_begin, "u}")) 1489 specifier = PRIu64; 1490 1491 if (specifier) 1492 { 1493 format = "%"; 1494 if (width_precision_length) 1495 format += std::string(width_precision, width_precision_length); 1496 format += specifier; 1497 return true; 1498 } 1499 } 1500 } 1501 return false; 1502 } 1503 1504 // Find information for the "thread.info.*" specifiers in a format string 1505 static bool 1506 FormatThreadExtendedInfoRecurse 1507 ( 1508 const char *var_name_begin, 1509 StructuredData::ObjectSP thread_info_dictionary, 1510 const SymbolContext *sc, 1511 const ExecutionContext *exe_ctx, 1512 Stream &s 1513 ) 1514 { 1515 bool var_success = false; 1516 std::string token_format; 1517 1518 llvm::StringRef var_name(var_name_begin); 1519 size_t percent_idx = var_name.find('%'); 1520 size_t close_curly_idx = var_name.find('}'); 1521 llvm::StringRef path = var_name; 1522 llvm::StringRef formatter = var_name; 1523 1524 // 'path' will be the dot separated list of objects to transverse up until we hit 1525 // a close curly brace, a percent sign, or an end of string. 1526 if (percent_idx != llvm::StringRef::npos || close_curly_idx != llvm::StringRef::npos) 1527 { 1528 if (percent_idx != llvm::StringRef::npos && close_curly_idx != llvm::StringRef::npos) 1529 { 1530 if (percent_idx < close_curly_idx) 1531 { 1532 path = var_name.slice(0, percent_idx); 1533 formatter = var_name.substr (percent_idx); 1534 } 1535 else 1536 { 1537 path = var_name.slice(0, close_curly_idx); 1538 formatter = var_name.substr (close_curly_idx); 1539 } 1540 } 1541 else if (percent_idx != llvm::StringRef::npos) 1542 { 1543 path = var_name.slice(0, percent_idx); 1544 formatter = var_name.substr (percent_idx); 1545 } 1546 else if (close_curly_idx != llvm::StringRef::npos) 1547 { 1548 path = var_name.slice(0, close_curly_idx); 1549 formatter = var_name.substr (close_curly_idx); 1550 } 1551 } 1552 1553 StructuredData::ObjectSP value = thread_info_dictionary->GetObjectForDotSeparatedPath (path); 1554 1555 if (value.get()) 1556 { 1557 if (value->GetType() == StructuredData::Type::eTypeInteger) 1558 { 1559 if (IsTokenWithFormat (formatter.str().c_str(), "", token_format, "0x%4.4" PRIx64, exe_ctx, sc)) 1560 { 1561 s.Printf(token_format.c_str(), value->GetAsInteger()->GetValue()); 1562 var_success = true; 1563 } 1564 } 1565 else if (value->GetType() == StructuredData::Type::eTypeFloat) 1566 { 1567 s.Printf ("%f", value->GetAsFloat()->GetValue()); 1568 var_success = true; 1569 } 1570 else if (value->GetType() == StructuredData::Type::eTypeString) 1571 { 1572 s.Printf("%s", value->GetAsString()->GetValue().c_str()); 1573 var_success = true; 1574 } 1575 else if (value->GetType() == StructuredData::Type::eTypeArray) 1576 { 1577 if (value->GetAsArray()->GetSize() > 0) 1578 { 1579 s.Printf ("%zu", value->GetAsArray()->GetSize()); 1580 var_success = true; 1581 } 1582 } 1583 else if (value->GetType() == StructuredData::Type::eTypeDictionary) 1584 { 1585 s.Printf ("%zu", value->GetAsDictionary()->GetKeys()->GetAsArray()->GetSize()); 1586 var_success = true; 1587 } 1588 } 1589 1590 return var_success; 1591 } 1592 1593 1594 static bool 1595 FormatPromptRecurse 1596 ( 1597 const char *format, 1598 const SymbolContext *sc, 1599 const ExecutionContext *exe_ctx, 1600 const Address *addr, 1601 Stream &s, 1602 const char **end, 1603 ValueObject* valobj, 1604 bool function_changed, 1605 bool initial_function 1606 ) 1607 { 1608 ValueObject* realvalobj = NULL; // makes it super-easy to parse pointers 1609 bool success = true; 1610 const char *p; 1611 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES)); 1612 1613 for (p = format; *p != '\0'; ++p) 1614 { 1615 if (realvalobj) 1616 { 1617 valobj = realvalobj; 1618 realvalobj = NULL; 1619 } 1620 size_t non_special_chars = ::strcspn (p, "${}\\"); 1621 if (non_special_chars > 0) 1622 { 1623 if (success) 1624 s.Write (p, non_special_chars); 1625 p += non_special_chars; 1626 } 1627 1628 if (*p == '\0') 1629 { 1630 break; 1631 } 1632 else if (*p == '{') 1633 { 1634 // Start a new scope that must have everything it needs if it is to 1635 // to make it into the final output stream "s". If you want to make 1636 // a format that only prints out the function or symbol name if there 1637 // is one in the symbol context you can use: 1638 // "{function =${function.name}}" 1639 // The first '{' starts a new scope that end with the matching '}' at 1640 // the end of the string. The contents "function =${function.name}" 1641 // will then be evaluated and only be output if there is a function 1642 // or symbol with a valid name. 1643 StreamString sub_strm; 1644 1645 ++p; // Skip the '{' 1646 1647 if (FormatPromptRecurse (p, sc, exe_ctx, addr, sub_strm, &p, valobj, function_changed, initial_function)) 1648 { 1649 // The stream had all it needed 1650 s.Write(sub_strm.GetData(), sub_strm.GetSize()); 1651 } 1652 if (*p != '}') 1653 { 1654 success = false; 1655 break; 1656 } 1657 } 1658 else if (*p == '}') 1659 { 1660 // End of a enclosing scope 1661 break; 1662 } 1663 else if (*p == '$') 1664 { 1665 // We have a prompt variable to print 1666 ++p; 1667 if (*p == '{') 1668 { 1669 ++p; 1670 const char *var_name_begin = p; 1671 const char *var_name_end = ::strchr (p, '}'); 1672 1673 if (var_name_end && var_name_begin < var_name_end) 1674 { 1675 // if we have already failed to parse, skip this variable 1676 if (success) 1677 { 1678 const char *cstr = NULL; 1679 std::string token_format; 1680 Address format_addr; 1681 1682 // normally "addr" means print a raw address but 1683 // "file-addr-or-load-addr" means print a module + file addr if there's no load addr 1684 bool print_file_addr_or_load_addr = false; 1685 bool addr_offset_concrete_func_only = false; 1686 bool addr_offset_print_with_no_padding = false; 1687 bool calculate_format_addr_function_offset = false; 1688 // Set reg_kind and reg_num to invalid values 1689 RegisterKind reg_kind = kNumRegisterKinds; 1690 uint32_t reg_num = LLDB_INVALID_REGNUM; 1691 FileSpec format_file_spec; 1692 const RegisterInfo *reg_info = NULL; 1693 RegisterContext *reg_ctx = NULL; 1694 bool do_deref_pointer = false; 1695 ValueObject::ExpressionPathScanEndReason reason_to_stop = ValueObject::eExpressionPathScanEndReasonEndOfString; 1696 ValueObject::ExpressionPathEndResultType final_value_type = ValueObject::eExpressionPathEndResultTypePlain; 1697 1698 // Each variable must set success to true below... 1699 bool var_success = false; 1700 switch (var_name_begin[0]) 1701 { 1702 case '*': 1703 case 'v': 1704 case 's': 1705 { 1706 if (!valobj) 1707 break; 1708 1709 if (log) 1710 log->Printf("[Debugger::FormatPrompt] initial string: %s",var_name_begin); 1711 1712 // check for *var and *svar 1713 if (*var_name_begin == '*') 1714 { 1715 do_deref_pointer = true; 1716 var_name_begin++; 1717 if (log) 1718 log->Printf("[Debugger::FormatPrompt] found a deref, new string is: %s",var_name_begin); 1719 } 1720 1721 if (*var_name_begin == 's') 1722 { 1723 if (!valobj->IsSynthetic()) 1724 valobj = valobj->GetSyntheticValue().get(); 1725 if (!valobj) 1726 break; 1727 var_name_begin++; 1728 if (log) 1729 log->Printf("[Debugger::FormatPrompt] found a synthetic, new string is: %s",var_name_begin); 1730 } 1731 1732 // should be a 'v' by now 1733 if (*var_name_begin != 'v') 1734 break; 1735 1736 if (log) 1737 log->Printf("[Debugger::FormatPrompt] string I am working with: %s",var_name_begin); 1738 1739 ValueObject::ExpressionPathAftermath what_next = (do_deref_pointer ? 1740 ValueObject::eExpressionPathAftermathDereference : ValueObject::eExpressionPathAftermathNothing); 1741 ValueObject::GetValueForExpressionPathOptions options; 1742 options.DontCheckDotVsArrowSyntax().DoAllowBitfieldSyntax().DoAllowFragileIVar().DoAllowSyntheticChildren(); 1743 ValueObject::ValueObjectRepresentationStyle val_obj_display = ValueObject::eValueObjectRepresentationStyleSummary; 1744 ValueObject* target = NULL; 1745 Format custom_format = eFormatInvalid; 1746 const char* var_name_final = NULL; 1747 const char* var_name_final_if_array_range = NULL; 1748 const char* close_bracket_position = NULL; 1749 int64_t index_lower = -1; 1750 int64_t index_higher = -1; 1751 bool is_array_range = false; 1752 const char* first_unparsed; 1753 bool was_plain_var = false; 1754 bool was_var_format = false; 1755 bool was_var_indexed = false; 1756 1757 if (!valobj) break; 1758 // simplest case ${var}, just print valobj's value 1759 if (IsToken (var_name_begin, "var}")) 1760 { 1761 was_plain_var = true; 1762 target = valobj; 1763 val_obj_display = ValueObject::eValueObjectRepresentationStyleValue; 1764 } 1765 else if (IsToken (var_name_begin, "var.script:")) 1766 { 1767 var_name_begin += ::strlen("var.script:"); 1768 std::string script_name(var_name_begin,var_name_end); 1769 ScriptInterpreter* script_interpreter = valobj->GetTargetSP()->GetDebugger().GetCommandInterpreter().GetScriptInterpreter(); 1770 if (RunScriptFormatKeyword (s, script_interpreter, valobj, script_name)) 1771 var_success = true; 1772 break; 1773 } 1774 else if (IsToken (var_name_begin,"var%")) 1775 { 1776 was_var_format = true; 1777 // this is a variable with some custom format applied to it 1778 const char* percent_position; 1779 target = valobj; 1780 val_obj_display = ValueObject::eValueObjectRepresentationStyleValue; 1781 ScanFormatDescriptor (var_name_begin, 1782 var_name_end, 1783 &var_name_final, 1784 &percent_position, 1785 &custom_format, 1786 &val_obj_display); 1787 } 1788 // this is ${var.something} or multiple .something nested 1789 else if (IsToken (var_name_begin, "var")) 1790 { 1791 if (IsToken (var_name_begin, "var[")) 1792 was_var_indexed = true; 1793 const char* percent_position; 1794 ScanFormatDescriptor (var_name_begin, 1795 var_name_end, 1796 &var_name_final, 1797 &percent_position, 1798 &custom_format, 1799 &val_obj_display); 1800 1801 const char* open_bracket_position; 1802 const char* separator_position; 1803 ScanBracketedRange (var_name_begin, 1804 var_name_end, 1805 var_name_final, 1806 &open_bracket_position, 1807 &separator_position, 1808 &close_bracket_position, 1809 &var_name_final_if_array_range, 1810 &index_lower, 1811 &index_higher); 1812 1813 Error error; 1814 1815 std::string expr_path(var_name_final-var_name_begin-1,0); 1816 memcpy(&expr_path[0], var_name_begin+3,var_name_final-var_name_begin-3); 1817 1818 if (log) 1819 log->Printf("[Debugger::FormatPrompt] symbol to expand: %s",expr_path.c_str()); 1820 1821 target = valobj->GetValueForExpressionPath(expr_path.c_str(), 1822 &first_unparsed, 1823 &reason_to_stop, 1824 &final_value_type, 1825 options, 1826 &what_next).get(); 1827 1828 if (!target) 1829 { 1830 if (log) 1831 log->Printf("[Debugger::FormatPrompt] ERROR: unparsed portion = %s, why stopping = %d," 1832 " final_value_type %d", 1833 first_unparsed, reason_to_stop, final_value_type); 1834 break; 1835 } 1836 else 1837 { 1838 if (log) 1839 log->Printf("[Debugger::FormatPrompt] ALL RIGHT: unparsed portion = %s, why stopping = %d," 1840 " final_value_type %d", 1841 first_unparsed, reason_to_stop, final_value_type); 1842 target = target->GetQualifiedRepresentationIfAvailable(target->GetDynamicValueType(), true).get(); 1843 } 1844 } 1845 else 1846 break; 1847 1848 is_array_range = (final_value_type == ValueObject::eExpressionPathEndResultTypeBoundedRange || 1849 final_value_type == ValueObject::eExpressionPathEndResultTypeUnboundedRange); 1850 1851 do_deref_pointer = (what_next == ValueObject::eExpressionPathAftermathDereference); 1852 1853 if (do_deref_pointer && !is_array_range) 1854 { 1855 // I have not deref-ed yet, let's do it 1856 // this happens when we are not going through GetValueForVariableExpressionPath 1857 // to get to the target ValueObject 1858 Error error; 1859 target = target->Dereference(error).get(); 1860 if (error.Fail()) 1861 { 1862 if (log) 1863 log->Printf("[Debugger::FormatPrompt] ERROR: %s\n", error.AsCString("unknown")); \ 1864 break; 1865 } 1866 do_deref_pointer = false; 1867 } 1868 1869 if (!target) 1870 { 1871 if (log) 1872 log->Printf("[Debugger::FormatPrompt] could not calculate target for prompt expression"); 1873 break; 1874 } 1875 1876 // we do not want to use the summary for a bitfield of type T:n 1877 // if we were originally dealing with just a T - that would get 1878 // us into an endless recursion 1879 if (target->IsBitfield() && was_var_indexed) 1880 { 1881 // TODO: check for a (T:n)-specific summary - we should still obey that 1882 StreamString bitfield_name; 1883 bitfield_name.Printf("%s:%d", target->GetTypeName().AsCString(), target->GetBitfieldBitSize()); 1884 lldb::TypeNameSpecifierImplSP type_sp(new TypeNameSpecifierImpl(bitfield_name.GetData(),false)); 1885 if (!DataVisualization::GetSummaryForType(type_sp)) 1886 val_obj_display = ValueObject::eValueObjectRepresentationStyleValue; 1887 } 1888 1889 // TODO use flags for these 1890 const uint32_t type_info_flags = target->GetClangType().GetTypeInfo(NULL); 1891 bool is_array = (type_info_flags & eTypeIsArray) != 0; 1892 bool is_pointer = (type_info_flags & eTypeIsPointer) != 0; 1893 bool is_aggregate = target->GetClangType().IsAggregateType(); 1894 1895 if ((is_array || is_pointer) && (!is_array_range) && val_obj_display == ValueObject::eValueObjectRepresentationStyleValue) // this should be wrong, but there are some exceptions 1896 { 1897 StreamString str_temp; 1898 if (log) 1899 log->Printf("[Debugger::FormatPrompt] I am into array || pointer && !range"); 1900 1901 if (target->HasSpecialPrintableRepresentation(val_obj_display, custom_format)) 1902 { 1903 // try to use the special cases 1904 var_success = target->DumpPrintableRepresentation(str_temp, 1905 val_obj_display, 1906 custom_format); 1907 if (log) 1908 log->Printf("[Debugger::FormatPrompt] special cases did%s match", var_success ? "" : "n't"); 1909 1910 // should not happen 1911 if (var_success) 1912 s << str_temp.GetData(); 1913 var_success = true; 1914 break; 1915 } 1916 else 1917 { 1918 if (was_plain_var) // if ${var} 1919 { 1920 s << target->GetTypeName() << " @ " << target->GetLocationAsCString(); 1921 } 1922 else if (is_pointer) // if pointer, value is the address stored 1923 { 1924 target->DumpPrintableRepresentation (s, 1925 val_obj_display, 1926 custom_format, 1927 ValueObject::ePrintableRepresentationSpecialCasesDisable); 1928 } 1929 var_success = true; 1930 break; 1931 } 1932 } 1933 1934 // if directly trying to print ${var}, and this is an aggregate, display a nice 1935 // type @ location message 1936 if (is_aggregate && was_plain_var) 1937 { 1938 s << target->GetTypeName() << " @ " << target->GetLocationAsCString(); 1939 var_success = true; 1940 break; 1941 } 1942 1943 // if directly trying to print ${var%V}, and this is an aggregate, do not let the user do it 1944 if (is_aggregate && ((was_var_format && val_obj_display == ValueObject::eValueObjectRepresentationStyleValue))) 1945 { 1946 s << "<invalid use of aggregate type>"; 1947 var_success = true; 1948 break; 1949 } 1950 1951 if (!is_array_range) 1952 { 1953 if (log) 1954 log->Printf("[Debugger::FormatPrompt] dumping ordinary printable output"); 1955 var_success = target->DumpPrintableRepresentation(s,val_obj_display, custom_format); 1956 } 1957 else 1958 { 1959 if (log) 1960 log->Printf("[Debugger::FormatPrompt] checking if I can handle as array"); 1961 if (!is_array && !is_pointer) 1962 break; 1963 if (log) 1964 log->Printf("[Debugger::FormatPrompt] handle as array"); 1965 const char* special_directions = NULL; 1966 StreamString special_directions_writer; 1967 if (close_bracket_position && (var_name_end-close_bracket_position > 1)) 1968 { 1969 ConstString additional_data; 1970 additional_data.SetCStringWithLength(close_bracket_position+1, var_name_end-close_bracket_position-1); 1971 special_directions_writer.Printf("${%svar%s}", 1972 do_deref_pointer ? "*" : "", 1973 additional_data.GetCString()); 1974 special_directions = special_directions_writer.GetData(); 1975 } 1976 1977 // let us display items index_lower thru index_higher of this array 1978 s.PutChar('['); 1979 var_success = true; 1980 1981 if (index_higher < 0) 1982 index_higher = valobj->GetNumChildren() - 1; 1983 1984 uint32_t max_num_children = target->GetTargetSP()->GetMaximumNumberOfChildrenToDisplay(); 1985 1986 for (;index_lower<=index_higher;index_lower++) 1987 { 1988 ValueObject* item = ExpandIndexedExpression (target, 1989 index_lower, 1990 exe_ctx->GetFramePtr(), 1991 false).get(); 1992 1993 if (!item) 1994 { 1995 if (log) 1996 log->Printf("[Debugger::FormatPrompt] ERROR in getting child item at index %" PRId64, index_lower); 1997 } 1998 else 1999 { 2000 if (log) 2001 log->Printf("[Debugger::FormatPrompt] special_directions for child item: %s",special_directions); 2002 } 2003 2004 if (!special_directions) 2005 var_success &= item->DumpPrintableRepresentation(s,val_obj_display, custom_format); 2006 else 2007 var_success &= FormatPromptRecurse(special_directions, sc, exe_ctx, addr, s, NULL, item, function_changed, initial_function); 2008 2009 if (--max_num_children == 0) 2010 { 2011 s.PutCString(", ..."); 2012 break; 2013 } 2014 2015 if (index_lower < index_higher) 2016 s.PutChar(','); 2017 } 2018 s.PutChar(']'); 2019 } 2020 } 2021 break; 2022 case 'a': 2023 if (IsToken (var_name_begin, "addr-file-or-load}")) 2024 { 2025 print_file_addr_or_load_addr = true; 2026 } 2027 if (IsToken (var_name_begin, "addr}") 2028 || IsToken (var_name_begin, "addr-file-or-load}")) 2029 { 2030 if (addr && addr->IsValid()) 2031 { 2032 var_success = true; 2033 format_addr = *addr; 2034 } 2035 } 2036 break; 2037 2038 case 'p': 2039 if (IsToken (var_name_begin, "process.")) 2040 { 2041 if (exe_ctx) 2042 { 2043 Process *process = exe_ctx->GetProcessPtr(); 2044 if (process) 2045 { 2046 var_name_begin += ::strlen ("process."); 2047 if (IsTokenWithFormat (var_name_begin, "id", token_format, "%" PRIu64, exe_ctx, sc)) 2048 { 2049 s.Printf(token_format.c_str(), process->GetID()); 2050 var_success = true; 2051 } 2052 else if ((IsToken (var_name_begin, "name}")) || 2053 (IsToken (var_name_begin, "file.basename}")) || 2054 (IsToken (var_name_begin, "file.fullpath}"))) 2055 { 2056 Module *exe_module = process->GetTarget().GetExecutableModulePointer(); 2057 if (exe_module) 2058 { 2059 if (var_name_begin[0] == 'n' || var_name_begin[5] == 'f') 2060 { 2061 format_file_spec.GetFilename() = exe_module->GetFileSpec().GetFilename(); 2062 var_success = (bool)format_file_spec; 2063 } 2064 else 2065 { 2066 format_file_spec = exe_module->GetFileSpec(); 2067 var_success = (bool)format_file_spec; 2068 } 2069 } 2070 } 2071 else if (IsToken (var_name_begin, "script:")) 2072 { 2073 var_name_begin += ::strlen("script:"); 2074 std::string script_name(var_name_begin,var_name_end); 2075 ScriptInterpreter* script_interpreter = process->GetTarget().GetDebugger().GetCommandInterpreter().GetScriptInterpreter(); 2076 if (RunScriptFormatKeyword (s, script_interpreter, process, script_name)) 2077 var_success = true; 2078 } 2079 } 2080 } 2081 } 2082 break; 2083 2084 case 't': 2085 if (IsToken (var_name_begin, "thread.")) 2086 { 2087 if (exe_ctx) 2088 { 2089 Thread *thread = exe_ctx->GetThreadPtr(); 2090 if (thread) 2091 { 2092 var_name_begin += ::strlen ("thread."); 2093 if (IsTokenWithFormat (var_name_begin, "id", token_format, "0x%4.4" PRIx64, exe_ctx, sc)) 2094 { 2095 s.Printf(token_format.c_str(), thread->GetID()); 2096 var_success = true; 2097 } 2098 else if (IsTokenWithFormat (var_name_begin, "protocol_id", token_format, "0x%4.4" PRIx64, exe_ctx, sc)) 2099 { 2100 s.Printf(token_format.c_str(), thread->GetProtocolID()); 2101 var_success = true; 2102 } 2103 else if (IsTokenWithFormat (var_name_begin, "index", token_format, "%" PRIu64, exe_ctx, sc)) 2104 { 2105 s.Printf(token_format.c_str(), (uint64_t)thread->GetIndexID()); 2106 var_success = true; 2107 } 2108 else if (IsToken (var_name_begin, "name}")) 2109 { 2110 cstr = thread->GetName(); 2111 var_success = cstr && cstr[0]; 2112 if (var_success) 2113 s.PutCString(cstr); 2114 } 2115 else if (IsToken (var_name_begin, "queue}")) 2116 { 2117 cstr = thread->GetQueueName(); 2118 var_success = cstr && cstr[0]; 2119 if (var_success) 2120 s.PutCString(cstr); 2121 } 2122 else if (IsToken (var_name_begin, "stop-reason}")) 2123 { 2124 StopInfoSP stop_info_sp = thread->GetStopInfo (); 2125 if (stop_info_sp && stop_info_sp->IsValid()) 2126 { 2127 cstr = stop_info_sp->GetDescription(); 2128 if (cstr && cstr[0]) 2129 { 2130 s.PutCString(cstr); 2131 var_success = true; 2132 } 2133 } 2134 } 2135 else if (IsToken (var_name_begin, "return-value}")) 2136 { 2137 StopInfoSP stop_info_sp = thread->GetStopInfo (); 2138 if (stop_info_sp && stop_info_sp->IsValid()) 2139 { 2140 ValueObjectSP return_valobj_sp = StopInfo::GetReturnValueObject (stop_info_sp); 2141 if (return_valobj_sp) 2142 { 2143 return_valobj_sp->Dump(s); 2144 var_success = true; 2145 } 2146 } 2147 } 2148 else if (IsToken (var_name_begin, "completed-expression}")) 2149 { 2150 StopInfoSP stop_info_sp = thread->GetStopInfo (); 2151 if (stop_info_sp && stop_info_sp->IsValid()) 2152 { 2153 ClangExpressionVariableSP expression_var_sp = StopInfo::GetExpressionVariable (stop_info_sp); 2154 if (expression_var_sp && expression_var_sp->GetValueObject()) 2155 { 2156 expression_var_sp->GetValueObject()->Dump(s); 2157 var_success = true; 2158 } 2159 } 2160 } 2161 else if (IsToken (var_name_begin, "script:")) 2162 { 2163 var_name_begin += ::strlen("script:"); 2164 std::string script_name(var_name_begin,var_name_end); 2165 ScriptInterpreter* script_interpreter = thread->GetProcess()->GetTarget().GetDebugger().GetCommandInterpreter().GetScriptInterpreter(); 2166 if (RunScriptFormatKeyword (s, script_interpreter, thread, script_name)) 2167 var_success = true; 2168 } 2169 else if (IsToken (var_name_begin, "info.")) 2170 { 2171 var_name_begin += ::strlen("info."); 2172 StructuredData::ObjectSP object_sp = thread->GetExtendedInfo(); 2173 if (object_sp && object_sp->GetType() == StructuredData::Type::eTypeDictionary) 2174 { 2175 var_success = FormatThreadExtendedInfoRecurse (var_name_begin, object_sp, sc, exe_ctx, s); 2176 } 2177 } 2178 } 2179 } 2180 } 2181 else if (IsToken (var_name_begin, "target.")) 2182 { 2183 // TODO: hookup properties 2184 // if (!target_properties_sp) 2185 // { 2186 // Target *target = Target::GetTargetFromContexts (exe_ctx, sc); 2187 // if (target) 2188 // target_properties_sp = target->GetProperties(); 2189 // } 2190 // 2191 // if (target_properties_sp) 2192 // { 2193 // var_name_begin += ::strlen ("target."); 2194 // const char *end_property = strchr(var_name_begin, '}'); 2195 // if (end_property) 2196 // { 2197 // ConstString property_name(var_name_begin, end_property - var_name_begin); 2198 // std::string property_value (target_properties_sp->GetPropertyValue(property_name)); 2199 // if (!property_value.empty()) 2200 // { 2201 // s.PutCString (property_value.c_str()); 2202 // var_success = true; 2203 // } 2204 // } 2205 // } 2206 Target *target = Target::GetTargetFromContexts (exe_ctx, sc); 2207 if (target) 2208 { 2209 var_name_begin += ::strlen ("target."); 2210 if (IsToken (var_name_begin, "arch}")) 2211 { 2212 ArchSpec arch (target->GetArchitecture ()); 2213 if (arch.IsValid()) 2214 { 2215 s.PutCString (arch.GetArchitectureName()); 2216 var_success = true; 2217 } 2218 } 2219 else if (IsToken (var_name_begin, "script:")) 2220 { 2221 var_name_begin += ::strlen("script:"); 2222 std::string script_name(var_name_begin,var_name_end); 2223 ScriptInterpreter* script_interpreter = target->GetDebugger().GetCommandInterpreter().GetScriptInterpreter(); 2224 if (RunScriptFormatKeyword (s, script_interpreter, target, script_name)) 2225 var_success = true; 2226 } 2227 } 2228 } 2229 break; 2230 2231 case 'm': 2232 if (IsToken (var_name_begin, "module.")) 2233 { 2234 if (sc && sc->module_sp.get()) 2235 { 2236 Module *module = sc->module_sp.get(); 2237 var_name_begin += ::strlen ("module."); 2238 2239 if (IsToken (var_name_begin, "file.")) 2240 { 2241 if (module->GetFileSpec()) 2242 { 2243 var_name_begin += ::strlen ("file."); 2244 2245 if (IsToken (var_name_begin, "basename}")) 2246 { 2247 format_file_spec.GetFilename() = module->GetFileSpec().GetFilename(); 2248 var_success = (bool)format_file_spec; 2249 } 2250 else if (IsToken (var_name_begin, "fullpath}")) 2251 { 2252 format_file_spec = module->GetFileSpec(); 2253 var_success = (bool)format_file_spec; 2254 } 2255 } 2256 } 2257 } 2258 } 2259 break; 2260 2261 2262 case 'f': 2263 if (IsToken (var_name_begin, "file.")) 2264 { 2265 if (sc && sc->comp_unit != NULL) 2266 { 2267 var_name_begin += ::strlen ("file."); 2268 2269 if (IsToken (var_name_begin, "basename}")) 2270 { 2271 format_file_spec.GetFilename() = sc->comp_unit->GetFilename(); 2272 var_success = (bool)format_file_spec; 2273 } 2274 else if (IsToken (var_name_begin, "fullpath}")) 2275 { 2276 format_file_spec = *sc->comp_unit; 2277 var_success = (bool)format_file_spec; 2278 } 2279 } 2280 } 2281 else if (IsToken (var_name_begin, "frame.")) 2282 { 2283 if (exe_ctx) 2284 { 2285 StackFrame *frame = exe_ctx->GetFramePtr(); 2286 if (frame) 2287 { 2288 var_name_begin += ::strlen ("frame."); 2289 if (IsToken (var_name_begin, "index}")) 2290 { 2291 s.Printf("%u", frame->GetFrameIndex()); 2292 var_success = true; 2293 } 2294 else if (IsToken (var_name_begin, "pc}")) 2295 { 2296 reg_kind = eRegisterKindGeneric; 2297 reg_num = LLDB_REGNUM_GENERIC_PC; 2298 var_success = true; 2299 } 2300 else if (IsToken (var_name_begin, "sp}")) 2301 { 2302 reg_kind = eRegisterKindGeneric; 2303 reg_num = LLDB_REGNUM_GENERIC_SP; 2304 var_success = true; 2305 } 2306 else if (IsToken (var_name_begin, "fp}")) 2307 { 2308 reg_kind = eRegisterKindGeneric; 2309 reg_num = LLDB_REGNUM_GENERIC_FP; 2310 var_success = true; 2311 } 2312 else if (IsToken (var_name_begin, "flags}")) 2313 { 2314 reg_kind = eRegisterKindGeneric; 2315 reg_num = LLDB_REGNUM_GENERIC_FLAGS; 2316 var_success = true; 2317 } 2318 else if (IsToken (var_name_begin, "reg.")) 2319 { 2320 reg_ctx = frame->GetRegisterContext().get(); 2321 if (reg_ctx) 2322 { 2323 var_name_begin += ::strlen ("reg."); 2324 if (var_name_begin < var_name_end) 2325 { 2326 std::string reg_name (var_name_begin, var_name_end); 2327 reg_info = reg_ctx->GetRegisterInfoByName (reg_name.c_str()); 2328 if (reg_info) 2329 var_success = true; 2330 } 2331 } 2332 } 2333 else if (IsToken (var_name_begin, "script:")) 2334 { 2335 var_name_begin += ::strlen("script:"); 2336 std::string script_name(var_name_begin,var_name_end); 2337 ScriptInterpreter* script_interpreter = frame->GetThread()->GetProcess()->GetTarget().GetDebugger().GetCommandInterpreter().GetScriptInterpreter(); 2338 if (RunScriptFormatKeyword (s, script_interpreter, frame, script_name)) 2339 var_success = true; 2340 } 2341 } 2342 } 2343 } 2344 else if (IsToken (var_name_begin, "function.")) 2345 { 2346 if (sc && (sc->function != NULL || sc->symbol != NULL)) 2347 { 2348 var_name_begin += ::strlen ("function."); 2349 if (IsToken (var_name_begin, "id}")) 2350 { 2351 if (sc->function) 2352 s.Printf("function{0x%8.8" PRIx64 "}", sc->function->GetID()); 2353 else 2354 s.Printf("symbol[%u]", sc->symbol->GetID()); 2355 2356 var_success = true; 2357 } 2358 if (IsToken (var_name_begin, "changed}") && function_changed) 2359 { 2360 var_success = true; 2361 } 2362 if (IsToken (var_name_begin, "initial-function}") && initial_function) 2363 { 2364 var_success = true; 2365 } 2366 else if (IsToken (var_name_begin, "name}")) 2367 { 2368 if (sc->function) 2369 cstr = sc->function->GetName().AsCString (NULL); 2370 else if (sc->symbol) 2371 cstr = sc->symbol->GetName().AsCString (NULL); 2372 if (cstr) 2373 { 2374 s.PutCString(cstr); 2375 2376 if (sc->block) 2377 { 2378 Block *inline_block = sc->block->GetContainingInlinedBlock (); 2379 if (inline_block) 2380 { 2381 const InlineFunctionInfo *inline_info = sc->block->GetInlinedFunctionInfo(); 2382 if (inline_info) 2383 { 2384 s.PutCString(" [inlined] "); 2385 inline_info->GetName().Dump(&s); 2386 } 2387 } 2388 } 2389 var_success = true; 2390 } 2391 } 2392 else if (IsToken (var_name_begin, "name-without-args}")) 2393 { 2394 ConstString name; 2395 if (sc->function) 2396 name = sc->function->GetMangled().GetName (Mangled::ePreferDemangledWithoutArguments); 2397 else if (sc->symbol) 2398 name = sc->symbol->GetMangled().GetName (Mangled::ePreferDemangledWithoutArguments); 2399 if (name) 2400 { 2401 s.PutCString(name.GetCString()); 2402 var_success = true; 2403 } 2404 } 2405 else if (IsToken (var_name_begin, "name-with-args}")) 2406 { 2407 // Print the function name with arguments in it 2408 2409 if (sc->function) 2410 { 2411 var_success = true; 2412 ExecutionContextScope *exe_scope = exe_ctx ? exe_ctx->GetBestExecutionContextScope() : NULL; 2413 cstr = sc->function->GetName().AsCString (NULL); 2414 if (cstr) 2415 { 2416 const InlineFunctionInfo *inline_info = NULL; 2417 VariableListSP variable_list_sp; 2418 bool get_function_vars = true; 2419 if (sc->block) 2420 { 2421 Block *inline_block = sc->block->GetContainingInlinedBlock (); 2422 2423 if (inline_block) 2424 { 2425 get_function_vars = false; 2426 inline_info = sc->block->GetInlinedFunctionInfo(); 2427 if (inline_info) 2428 variable_list_sp = inline_block->GetBlockVariableList (true); 2429 } 2430 } 2431 2432 if (get_function_vars) 2433 { 2434 variable_list_sp = sc->function->GetBlock(true).GetBlockVariableList (true); 2435 } 2436 2437 if (inline_info) 2438 { 2439 s.PutCString (cstr); 2440 s.PutCString (" [inlined] "); 2441 cstr = inline_info->GetName().GetCString(); 2442 } 2443 2444 VariableList args; 2445 if (variable_list_sp) 2446 variable_list_sp->AppendVariablesWithScope(eValueTypeVariableArgument, args); 2447 if (args.GetSize() > 0) 2448 { 2449 const char *open_paren = strchr (cstr, '('); 2450 const char *close_paren = nullptr; 2451 const char *generic = strchr(cstr, '<'); 2452 // if before the arguments list begins there is a template sign 2453 // then scan to the end of the generic args before you try to find 2454 // the arguments list 2455 if (generic && open_paren && generic < open_paren) 2456 { 2457 int generic_depth = 1; 2458 ++generic; 2459 for (; 2460 *generic && generic_depth > 0; 2461 generic++) 2462 { 2463 if (*generic == '<') 2464 generic_depth++; 2465 if (*generic == '>') 2466 generic_depth--; 2467 } 2468 if (*generic) 2469 open_paren = strchr(generic, '('); 2470 else 2471 open_paren = nullptr; 2472 } 2473 if (open_paren) 2474 { 2475 if (IsToken (open_paren, "(anonymous namespace)")) 2476 { 2477 open_paren = strchr (open_paren + strlen("(anonymous namespace)"), '('); 2478 if (open_paren) 2479 close_paren = strchr (open_paren, ')'); 2480 } 2481 else 2482 close_paren = strchr (open_paren, ')'); 2483 } 2484 2485 if (open_paren) 2486 s.Write(cstr, open_paren - cstr + 1); 2487 else 2488 { 2489 s.PutCString (cstr); 2490 s.PutChar ('('); 2491 } 2492 const size_t num_args = args.GetSize(); 2493 for (size_t arg_idx = 0; arg_idx < num_args; ++arg_idx) 2494 { 2495 std::string buffer; 2496 2497 VariableSP var_sp (args.GetVariableAtIndex (arg_idx)); 2498 ValueObjectSP var_value_sp (ValueObjectVariable::Create (exe_scope, var_sp)); 2499 const char *var_representation = nullptr; 2500 const char *var_name = var_value_sp->GetName().GetCString(); 2501 if (var_value_sp->GetClangType().IsAggregateType() && 2502 DataVisualization::ShouldPrintAsOneLiner(*var_value_sp.get())) 2503 { 2504 static StringSummaryFormat format(TypeSummaryImpl::Flags() 2505 .SetHideItemNames(false) 2506 .SetShowMembersOneLiner(true), 2507 ""); 2508 format.FormatObject(var_value_sp.get(), buffer, TypeSummaryOptions()); 2509 var_representation = buffer.c_str(); 2510 } 2511 else 2512 var_representation = var_value_sp->GetValueAsCString(); 2513 if (arg_idx > 0) 2514 s.PutCString (", "); 2515 if (var_value_sp->GetError().Success()) 2516 { 2517 if (var_representation) 2518 s.Printf ("%s=%s", var_name, var_representation); 2519 else 2520 s.Printf ("%s=%s at %s", var_name, var_value_sp->GetTypeName().GetCString(), var_value_sp->GetLocationAsCString()); 2521 } 2522 else 2523 s.Printf ("%s=<unavailable>", var_name); 2524 } 2525 2526 if (close_paren) 2527 s.PutCString (close_paren); 2528 else 2529 s.PutChar(')'); 2530 2531 } 2532 else 2533 { 2534 s.PutCString(cstr); 2535 } 2536 } 2537 } 2538 else if (sc->symbol) 2539 { 2540 cstr = sc->symbol->GetName().AsCString (NULL); 2541 if (cstr) 2542 { 2543 s.PutCString(cstr); 2544 var_success = true; 2545 } 2546 } 2547 } 2548 else if (IsToken (var_name_begin, "addr-offset}") 2549 || IsToken (var_name_begin, "concrete-only-addr-offset-no-padding}")) 2550 { 2551 if (IsToken (var_name_begin, "concrete-only-addr-offset-no-padding}")) 2552 { 2553 addr_offset_print_with_no_padding = true; 2554 addr_offset_concrete_func_only = true; 2555 } 2556 var_success = addr != NULL; 2557 if (var_success) 2558 { 2559 format_addr = *addr; 2560 calculate_format_addr_function_offset = true; 2561 } 2562 } 2563 else if (IsToken (var_name_begin, "line-offset}")) 2564 { 2565 var_success = sc->line_entry.range.GetBaseAddress().IsValid(); 2566 if (var_success) 2567 { 2568 format_addr = sc->line_entry.range.GetBaseAddress(); 2569 calculate_format_addr_function_offset = true; 2570 } 2571 } 2572 else if (IsToken (var_name_begin, "pc-offset}")) 2573 { 2574 StackFrame *frame = exe_ctx->GetFramePtr(); 2575 var_success = frame != NULL; 2576 if (var_success) 2577 { 2578 format_addr = frame->GetFrameCodeAddress(); 2579 calculate_format_addr_function_offset = true; 2580 } 2581 } 2582 } 2583 } 2584 break; 2585 2586 case 'l': 2587 if (IsToken (var_name_begin, "line.")) 2588 { 2589 if (sc && sc->line_entry.IsValid()) 2590 { 2591 var_name_begin += ::strlen ("line."); 2592 if (IsToken (var_name_begin, "file.")) 2593 { 2594 var_name_begin += ::strlen ("file."); 2595 2596 if (IsToken (var_name_begin, "basename}")) 2597 { 2598 format_file_spec.GetFilename() = sc->line_entry.file.GetFilename(); 2599 var_success = (bool)format_file_spec; 2600 } 2601 else if (IsToken (var_name_begin, "fullpath}")) 2602 { 2603 format_file_spec = sc->line_entry.file; 2604 var_success = (bool)format_file_spec; 2605 } 2606 } 2607 else if (IsTokenWithFormat (var_name_begin, "number", token_format, "%" PRIu64, exe_ctx, sc)) 2608 { 2609 var_success = true; 2610 s.Printf(token_format.c_str(), (uint64_t)sc->line_entry.line); 2611 } 2612 else if ((IsToken (var_name_begin, "start-addr}")) || 2613 (IsToken (var_name_begin, "end-addr}"))) 2614 { 2615 var_success = sc && sc->line_entry.range.GetBaseAddress().IsValid(); 2616 if (var_success) 2617 { 2618 format_addr = sc->line_entry.range.GetBaseAddress(); 2619 if (var_name_begin[0] == 'e') 2620 format_addr.Slide (sc->line_entry.range.GetByteSize()); 2621 } 2622 } 2623 } 2624 } 2625 break; 2626 case 'c': 2627 if (IsToken (var_name_begin, "current-pc-arrow")) 2628 { 2629 if (addr && exe_ctx && exe_ctx->GetFramePtr()) 2630 { 2631 RegisterContextSP reg_ctx = exe_ctx->GetFramePtr()->GetRegisterContextSP(); 2632 if (reg_ctx.get()) 2633 { 2634 addr_t pc_loadaddr = reg_ctx->GetPC(); 2635 if (pc_loadaddr != LLDB_INVALID_ADDRESS) 2636 { 2637 Address pc; 2638 pc.SetLoadAddress (pc_loadaddr, exe_ctx->GetTargetPtr()); 2639 if (pc == *addr) 2640 { 2641 s.Printf ("-> "); 2642 var_success = true; 2643 } 2644 } 2645 } 2646 if (var_success == false) 2647 { 2648 s.Printf(" "); 2649 var_success = true; 2650 } 2651 } 2652 var_success = true; 2653 } 2654 break; 2655 } 2656 2657 if (var_success) 2658 { 2659 // If format addr is valid, then we need to print an address 2660 if (reg_num != LLDB_INVALID_REGNUM) 2661 { 2662 StackFrame *frame = exe_ctx->GetFramePtr(); 2663 // We have a register value to display... 2664 if (reg_num == LLDB_REGNUM_GENERIC_PC && reg_kind == eRegisterKindGeneric) 2665 { 2666 format_addr = frame->GetFrameCodeAddress(); 2667 } 2668 else 2669 { 2670 if (reg_ctx == NULL) 2671 reg_ctx = frame->GetRegisterContext().get(); 2672 2673 if (reg_ctx) 2674 { 2675 if (reg_kind != kNumRegisterKinds) 2676 reg_num = reg_ctx->ConvertRegisterKindToRegisterNumber(reg_kind, reg_num); 2677 reg_info = reg_ctx->GetRegisterInfoAtIndex (reg_num); 2678 var_success = reg_info != NULL; 2679 } 2680 } 2681 } 2682 2683 if (reg_info != NULL) 2684 { 2685 RegisterValue reg_value; 2686 var_success = reg_ctx->ReadRegister (reg_info, reg_value); 2687 if (var_success) 2688 { 2689 reg_value.Dump(&s, reg_info, false, false, eFormatDefault); 2690 } 2691 } 2692 2693 if (format_file_spec) 2694 { 2695 s << format_file_spec; 2696 } 2697 2698 // If format addr is valid, then we need to print an address 2699 if (format_addr.IsValid()) 2700 { 2701 var_success = false; 2702 2703 if (calculate_format_addr_function_offset) 2704 { 2705 Address func_addr; 2706 2707 if (sc) 2708 { 2709 if (sc->function) 2710 { 2711 func_addr = sc->function->GetAddressRange().GetBaseAddress(); 2712 if (sc->block && addr_offset_concrete_func_only == false) 2713 { 2714 // Check to make sure we aren't in an inline 2715 // function. If we are, use the inline block 2716 // range that contains "format_addr" since 2717 // blocks can be discontiguous. 2718 Block *inline_block = sc->block->GetContainingInlinedBlock (); 2719 AddressRange inline_range; 2720 if (inline_block && inline_block->GetRangeContainingAddress (format_addr, inline_range)) 2721 func_addr = inline_range.GetBaseAddress(); 2722 } 2723 } 2724 else if (sc->symbol && sc->symbol->ValueIsAddress()) 2725 func_addr = sc->symbol->GetAddress(); 2726 } 2727 2728 if (func_addr.IsValid()) 2729 { 2730 const char *addr_offset_padding = " "; 2731 if (addr_offset_print_with_no_padding) 2732 { 2733 addr_offset_padding = ""; 2734 } 2735 if (func_addr.GetSection() == format_addr.GetSection()) 2736 { 2737 addr_t func_file_addr = func_addr.GetFileAddress(); 2738 addr_t addr_file_addr = format_addr.GetFileAddress(); 2739 if (addr_file_addr > func_file_addr) 2740 s.Printf("%s+%s%" PRIu64, addr_offset_padding, addr_offset_padding, addr_file_addr - func_file_addr); 2741 else if (addr_file_addr < func_file_addr) 2742 s.Printf("%s-%s%" PRIu64, addr_offset_padding, addr_offset_padding, func_file_addr - addr_file_addr); 2743 var_success = true; 2744 } 2745 else 2746 { 2747 Target *target = Target::GetTargetFromContexts (exe_ctx, sc); 2748 if (target) 2749 { 2750 addr_t func_load_addr = func_addr.GetLoadAddress (target); 2751 addr_t addr_load_addr = format_addr.GetLoadAddress (target); 2752 if (addr_load_addr > func_load_addr) 2753 s.Printf("%s+%s%" PRIu64, addr_offset_padding, addr_offset_padding, addr_load_addr - func_load_addr); 2754 else if (addr_load_addr < func_load_addr) 2755 s.Printf("%s-%s%" PRIu64, addr_offset_padding, addr_offset_padding, func_load_addr - addr_load_addr); 2756 var_success = true; 2757 } 2758 } 2759 } 2760 } 2761 else 2762 { 2763 Target *target = Target::GetTargetFromContexts (exe_ctx, sc); 2764 addr_t vaddr = LLDB_INVALID_ADDRESS; 2765 if (exe_ctx && !target->GetSectionLoadList().IsEmpty()) 2766 vaddr = format_addr.GetLoadAddress (target); 2767 if (vaddr == LLDB_INVALID_ADDRESS) 2768 vaddr = format_addr.GetFileAddress (); 2769 2770 if (vaddr != LLDB_INVALID_ADDRESS) 2771 { 2772 int addr_width = 0; 2773 if (exe_ctx && target) 2774 { 2775 addr_width = target->GetArchitecture().GetAddressByteSize() * 2; 2776 } 2777 if (addr_width == 0) 2778 addr_width = 16; 2779 if (print_file_addr_or_load_addr) 2780 { 2781 format_addr.Dump (&s, exe_ctx ? exe_ctx->GetBestExecutionContextScope() : NULL, Address::DumpStyleLoadAddress, Address::DumpStyleModuleWithFileAddress, 0); 2782 } 2783 else 2784 { 2785 s.Printf("0x%*.*" PRIx64, addr_width, addr_width, vaddr); 2786 } 2787 var_success = true; 2788 } 2789 } 2790 } 2791 } 2792 2793 if (var_success == false) 2794 success = false; 2795 } 2796 p = var_name_end; 2797 } 2798 else 2799 break; 2800 } 2801 else 2802 { 2803 // We got a dollar sign with no '{' after it, it must just be a dollar sign 2804 s.PutChar(*p); 2805 } 2806 } 2807 else if (*p == '\\') 2808 { 2809 ++p; // skip the slash 2810 switch (*p) 2811 { 2812 case 'a': s.PutChar ('\a'); break; 2813 case 'b': s.PutChar ('\b'); break; 2814 case 'f': s.PutChar ('\f'); break; 2815 case 'n': s.PutChar ('\n'); break; 2816 case 'r': s.PutChar ('\r'); break; 2817 case 't': s.PutChar ('\t'); break; 2818 case 'v': s.PutChar ('\v'); break; 2819 case '\'': s.PutChar ('\''); break; 2820 case '\\': s.PutChar ('\\'); break; 2821 case '0': 2822 // 1 to 3 octal chars 2823 { 2824 // Make a string that can hold onto the initial zero char, 2825 // up to 3 octal digits, and a terminating NULL. 2826 char oct_str[5] = { 0, 0, 0, 0, 0 }; 2827 2828 int i; 2829 for (i=0; (p[i] >= '0' && p[i] <= '7') && i<4; ++i) 2830 oct_str[i] = p[i]; 2831 2832 // We don't want to consume the last octal character since 2833 // the main for loop will do this for us, so we advance p by 2834 // one less than i (even if i is zero) 2835 p += i - 1; 2836 unsigned long octal_value = ::strtoul (oct_str, NULL, 8); 2837 if (octal_value <= UINT8_MAX) 2838 { 2839 s.PutChar((char)octal_value); 2840 } 2841 } 2842 break; 2843 2844 case 'x': 2845 // hex number in the format 2846 if (isxdigit(p[1])) 2847 { 2848 ++p; // Skip the 'x' 2849 2850 // Make a string that can hold onto two hex chars plus a 2851 // NULL terminator 2852 char hex_str[3] = { 0,0,0 }; 2853 hex_str[0] = *p; 2854 if (isxdigit(p[1])) 2855 { 2856 ++p; // Skip the first of the two hex chars 2857 hex_str[1] = *p; 2858 } 2859 2860 unsigned long hex_value = strtoul (hex_str, NULL, 16); 2861 if (hex_value <= UINT8_MAX) 2862 s.PutChar ((char)hex_value); 2863 } 2864 else 2865 { 2866 s.PutChar('x'); 2867 } 2868 break; 2869 2870 default: 2871 // Just desensitize any other character by just printing what 2872 // came after the '\' 2873 s << *p; 2874 break; 2875 2876 } 2877 2878 } 2879 } 2880 if (end) 2881 *end = p; 2882 return success; 2883 } 2884 2885 bool 2886 Debugger::FormatPrompt 2887 ( 2888 const char *format, 2889 const SymbolContext *sc, 2890 const ExecutionContext *exe_ctx, 2891 const Address *addr, 2892 Stream &s, 2893 ValueObject* valobj 2894 ) 2895 { 2896 bool use_color = exe_ctx ? exe_ctx->GetTargetRef().GetDebugger().GetUseColor() : true; 2897 std::string format_str = lldb_utility::ansi::FormatAnsiTerminalCodes (format, use_color); 2898 if (format_str.length()) 2899 format = format_str.c_str(); 2900 return FormatPromptRecurse (format, sc, exe_ctx, addr, s, NULL, valobj, false, false); 2901 } 2902 2903 bool 2904 Debugger::FormatDisassemblerAddress (const char *format, 2905 const SymbolContext *sc, 2906 const SymbolContext *prev_sc, 2907 const ExecutionContext *exe_ctx, 2908 const Address *addr, 2909 Stream &s) 2910 { 2911 if (format == NULL && exe_ctx != NULL && exe_ctx->HasTargetScope()) 2912 { 2913 format = exe_ctx->GetTargetRef().GetDebugger().GetDisassemblyFormat(); 2914 } 2915 bool function_changed = false; 2916 bool initial_function = false; 2917 if (prev_sc && (prev_sc->function || prev_sc->symbol)) 2918 { 2919 if (sc && (sc->function || sc->symbol)) 2920 { 2921 if (prev_sc->symbol && sc->symbol) 2922 { 2923 if (!sc->symbol->Compare (prev_sc->symbol->GetName(), prev_sc->symbol->GetType())) 2924 { 2925 function_changed = true; 2926 } 2927 } 2928 else if (prev_sc->function && sc->function) 2929 { 2930 if (prev_sc->function->GetMangled() != sc->function->GetMangled()) 2931 { 2932 function_changed = true; 2933 } 2934 } 2935 } 2936 } 2937 // The first context on a list of instructions will have a prev_sc that 2938 // has no Function or Symbol -- if SymbolContext had an IsValid() method, it 2939 // would return false. But we do get a prev_sc pointer. 2940 if ((sc && (sc->function || sc->symbol)) 2941 && prev_sc && (prev_sc->function == NULL && prev_sc->symbol == NULL)) 2942 { 2943 initial_function = true; 2944 } 2945 return FormatPromptRecurse (format, sc, exe_ctx, addr, s, NULL, NULL, function_changed, initial_function); 2946 } 2947 2948 2949 void 2950 Debugger::SetLoggingCallback (lldb::LogOutputCallback log_callback, void *baton) 2951 { 2952 // For simplicity's sake, I am not going to deal with how to close down any 2953 // open logging streams, I just redirect everything from here on out to the 2954 // callback. 2955 m_log_callback_stream_sp.reset (new StreamCallback (log_callback, baton)); 2956 } 2957 2958 bool 2959 Debugger::EnableLog (const char *channel, const char **categories, const char *log_file, uint32_t log_options, Stream &error_stream) 2960 { 2961 Log::Callbacks log_callbacks; 2962 2963 StreamSP log_stream_sp; 2964 if (m_log_callback_stream_sp) 2965 { 2966 log_stream_sp = m_log_callback_stream_sp; 2967 // For now when using the callback mode you always get thread & timestamp. 2968 log_options |= LLDB_LOG_OPTION_PREPEND_TIMESTAMP | LLDB_LOG_OPTION_PREPEND_THREAD_NAME; 2969 } 2970 else if (log_file == NULL || *log_file == '\0') 2971 { 2972 log_stream_sp = GetOutputFile(); 2973 } 2974 else 2975 { 2976 LogStreamMap::iterator pos = m_log_streams.find(log_file); 2977 if (pos != m_log_streams.end()) 2978 log_stream_sp = pos->second.lock(); 2979 if (!log_stream_sp) 2980 { 2981 log_stream_sp.reset (new StreamFile (log_file)); 2982 m_log_streams[log_file] = log_stream_sp; 2983 } 2984 } 2985 assert (log_stream_sp.get()); 2986 2987 if (log_options == 0) 2988 log_options = LLDB_LOG_OPTION_PREPEND_THREAD_NAME | LLDB_LOG_OPTION_THREADSAFE; 2989 2990 if (Log::GetLogChannelCallbacks (ConstString(channel), log_callbacks)) 2991 { 2992 log_callbacks.enable (log_stream_sp, log_options, categories, &error_stream); 2993 return true; 2994 } 2995 else 2996 { 2997 LogChannelSP log_channel_sp (LogChannel::FindPlugin (channel)); 2998 if (log_channel_sp) 2999 { 3000 if (log_channel_sp->Enable (log_stream_sp, log_options, &error_stream, categories)) 3001 { 3002 return true; 3003 } 3004 else 3005 { 3006 error_stream.Printf ("Invalid log channel '%s'.\n", channel); 3007 return false; 3008 } 3009 } 3010 else 3011 { 3012 error_stream.Printf ("Invalid log channel '%s'.\n", channel); 3013 return false; 3014 } 3015 } 3016 return false; 3017 } 3018 3019 SourceManager & 3020 Debugger::GetSourceManager () 3021 { 3022 if (m_source_manager_ap.get() == NULL) 3023 m_source_manager_ap.reset (new SourceManager (shared_from_this())); 3024 return *m_source_manager_ap; 3025 } 3026 3027 3028 3029 // This function handles events that were broadcast by the process. 3030 void 3031 Debugger::HandleBreakpointEvent (const EventSP &event_sp) 3032 { 3033 using namespace lldb; 3034 const uint32_t event_type = Breakpoint::BreakpointEventData::GetBreakpointEventTypeFromEvent (event_sp); 3035 3036 // if (event_type & eBreakpointEventTypeAdded 3037 // || event_type & eBreakpointEventTypeRemoved 3038 // || event_type & eBreakpointEventTypeEnabled 3039 // || event_type & eBreakpointEventTypeDisabled 3040 // || event_type & eBreakpointEventTypeCommandChanged 3041 // || event_type & eBreakpointEventTypeConditionChanged 3042 // || event_type & eBreakpointEventTypeIgnoreChanged 3043 // || event_type & eBreakpointEventTypeLocationsResolved) 3044 // { 3045 // // Don't do anything about these events, since the breakpoint commands already echo these actions. 3046 // } 3047 // 3048 if (event_type & eBreakpointEventTypeLocationsAdded) 3049 { 3050 uint32_t num_new_locations = Breakpoint::BreakpointEventData::GetNumBreakpointLocationsFromEvent(event_sp); 3051 if (num_new_locations > 0) 3052 { 3053 BreakpointSP breakpoint = Breakpoint::BreakpointEventData::GetBreakpointFromEvent(event_sp); 3054 StreamFileSP output_sp (GetOutputFile()); 3055 if (output_sp) 3056 { 3057 output_sp->Printf("%d location%s added to breakpoint %d\n", 3058 num_new_locations, 3059 num_new_locations == 1 ? "" : "s", 3060 breakpoint->GetID()); 3061 RefreshTopIOHandler(); 3062 } 3063 } 3064 } 3065 // else if (event_type & eBreakpointEventTypeLocationsRemoved) 3066 // { 3067 // // These locations just get disabled, not sure it is worth spamming folks about this on the command line. 3068 // } 3069 // else if (event_type & eBreakpointEventTypeLocationsResolved) 3070 // { 3071 // // This might be an interesting thing to note, but I'm going to leave it quiet for now, it just looked noisy. 3072 // } 3073 } 3074 3075 size_t 3076 Debugger::GetProcessSTDOUT (Process *process, Stream *stream) 3077 { 3078 size_t total_bytes = 0; 3079 if (stream == NULL) 3080 stream = GetOutputFile().get(); 3081 3082 if (stream) 3083 { 3084 // The process has stuff waiting for stdout; get it and write it out to the appropriate place. 3085 if (process == NULL) 3086 { 3087 TargetSP target_sp = GetTargetList().GetSelectedTarget(); 3088 if (target_sp) 3089 process = target_sp->GetProcessSP().get(); 3090 } 3091 if (process) 3092 { 3093 Error error; 3094 size_t len; 3095 char stdio_buffer[1024]; 3096 while ((len = process->GetSTDOUT (stdio_buffer, sizeof (stdio_buffer), error)) > 0) 3097 { 3098 stream->Write(stdio_buffer, len); 3099 total_bytes += len; 3100 } 3101 } 3102 stream->Flush(); 3103 } 3104 return total_bytes; 3105 } 3106 3107 size_t 3108 Debugger::GetProcessSTDERR (Process *process, Stream *stream) 3109 { 3110 size_t total_bytes = 0; 3111 if (stream == NULL) 3112 stream = GetOutputFile().get(); 3113 3114 if (stream) 3115 { 3116 // The process has stuff waiting for stderr; get it and write it out to the appropriate place. 3117 if (process == NULL) 3118 { 3119 TargetSP target_sp = GetTargetList().GetSelectedTarget(); 3120 if (target_sp) 3121 process = target_sp->GetProcessSP().get(); 3122 } 3123 if (process) 3124 { 3125 Error error; 3126 size_t len; 3127 char stdio_buffer[1024]; 3128 while ((len = process->GetSTDERR (stdio_buffer, sizeof (stdio_buffer), error)) > 0) 3129 { 3130 stream->Write(stdio_buffer, len); 3131 total_bytes += len; 3132 } 3133 } 3134 stream->Flush(); 3135 } 3136 return total_bytes; 3137 } 3138 3139 3140 // This function handles events that were broadcast by the process. 3141 void 3142 Debugger::HandleProcessEvent (const EventSP &event_sp) 3143 { 3144 using namespace lldb; 3145 const uint32_t event_type = event_sp->GetType(); 3146 ProcessSP process_sp = Process::ProcessEventData::GetProcessFromEvent(event_sp.get()); 3147 3148 StreamString output_stream; 3149 StreamString error_stream; 3150 const bool gui_enabled = IsForwardingEvents(); 3151 3152 if (!gui_enabled) 3153 { 3154 bool pop_process_io_handler = false; 3155 assert (process_sp); 3156 3157 if (event_type & Process::eBroadcastBitSTDOUT || event_type & Process::eBroadcastBitStateChanged) 3158 { 3159 GetProcessSTDOUT (process_sp.get(), &output_stream); 3160 } 3161 3162 if (event_type & Process::eBroadcastBitSTDERR || event_type & Process::eBroadcastBitStateChanged) 3163 { 3164 GetProcessSTDERR (process_sp.get(), &error_stream); 3165 } 3166 3167 if (event_type & Process::eBroadcastBitStateChanged) 3168 { 3169 Process::HandleProcessStateChangedEvent (event_sp, &output_stream, pop_process_io_handler); 3170 } 3171 3172 if (output_stream.GetSize() || error_stream.GetSize()) 3173 { 3174 StreamFileSP error_stream_sp (GetOutputFile()); 3175 bool top_io_handler_hid = false; 3176 3177 if (process_sp->ProcessIOHandlerIsActive() == false) 3178 top_io_handler_hid = HideTopIOHandler(); 3179 3180 if (output_stream.GetSize()) 3181 { 3182 StreamFileSP output_stream_sp (GetOutputFile()); 3183 if (output_stream_sp) 3184 output_stream_sp->Write (output_stream.GetData(), output_stream.GetSize()); 3185 } 3186 3187 if (error_stream.GetSize()) 3188 { 3189 StreamFileSP error_stream_sp (GetErrorFile()); 3190 if (error_stream_sp) 3191 error_stream_sp->Write (error_stream.GetData(), error_stream.GetSize()); 3192 } 3193 3194 if (top_io_handler_hid) 3195 RefreshTopIOHandler(); 3196 } 3197 3198 if (pop_process_io_handler) 3199 process_sp->PopProcessIOHandler(); 3200 } 3201 } 3202 3203 void 3204 Debugger::HandleThreadEvent (const EventSP &event_sp) 3205 { 3206 // At present the only thread event we handle is the Frame Changed event, 3207 // and all we do for that is just reprint the thread status for that thread. 3208 using namespace lldb; 3209 const uint32_t event_type = event_sp->GetType(); 3210 if (event_type == Thread::eBroadcastBitStackChanged || 3211 event_type == Thread::eBroadcastBitThreadSelected ) 3212 { 3213 ThreadSP thread_sp (Thread::ThreadEventData::GetThreadFromEvent (event_sp.get())); 3214 if (thread_sp) 3215 { 3216 HideTopIOHandler(); 3217 StreamFileSP stream_sp (GetOutputFile()); 3218 thread_sp->GetStatus(*stream_sp, 0, 1, 1); 3219 RefreshTopIOHandler(); 3220 } 3221 } 3222 } 3223 3224 bool 3225 Debugger::IsForwardingEvents () 3226 { 3227 return (bool)m_forward_listener_sp; 3228 } 3229 3230 void 3231 Debugger::EnableForwardEvents (const ListenerSP &listener_sp) 3232 { 3233 m_forward_listener_sp = listener_sp; 3234 } 3235 3236 void 3237 Debugger::CancelForwardEvents (const ListenerSP &listener_sp) 3238 { 3239 m_forward_listener_sp.reset(); 3240 } 3241 3242 3243 void 3244 Debugger::DefaultEventHandler() 3245 { 3246 Listener& listener(GetListener()); 3247 ConstString broadcaster_class_target(Target::GetStaticBroadcasterClass()); 3248 ConstString broadcaster_class_process(Process::GetStaticBroadcasterClass()); 3249 ConstString broadcaster_class_thread(Thread::GetStaticBroadcasterClass()); 3250 BroadcastEventSpec target_event_spec (broadcaster_class_target, 3251 Target::eBroadcastBitBreakpointChanged); 3252 3253 BroadcastEventSpec process_event_spec (broadcaster_class_process, 3254 Process::eBroadcastBitStateChanged | 3255 Process::eBroadcastBitSTDOUT | 3256 Process::eBroadcastBitSTDERR); 3257 3258 BroadcastEventSpec thread_event_spec (broadcaster_class_thread, 3259 Thread::eBroadcastBitStackChanged | 3260 Thread::eBroadcastBitThreadSelected ); 3261 3262 listener.StartListeningForEventSpec (*this, target_event_spec); 3263 listener.StartListeningForEventSpec (*this, process_event_spec); 3264 listener.StartListeningForEventSpec (*this, thread_event_spec); 3265 listener.StartListeningForEvents (m_command_interpreter_ap.get(), 3266 CommandInterpreter::eBroadcastBitQuitCommandReceived | 3267 CommandInterpreter::eBroadcastBitAsynchronousOutputData | 3268 CommandInterpreter::eBroadcastBitAsynchronousErrorData ); 3269 3270 // Let the thread that spawned us know that we have started up and 3271 // that we are now listening to all required events so no events get missed 3272 m_sync_broadcaster.BroadcastEvent(eBroadcastBitEventThreadIsListening); 3273 3274 bool done = false; 3275 while (!done) 3276 { 3277 EventSP event_sp; 3278 if (listener.WaitForEvent(NULL, event_sp)) 3279 { 3280 if (event_sp) 3281 { 3282 Broadcaster *broadcaster = event_sp->GetBroadcaster(); 3283 if (broadcaster) 3284 { 3285 uint32_t event_type = event_sp->GetType(); 3286 ConstString broadcaster_class (broadcaster->GetBroadcasterClass()); 3287 if (broadcaster_class == broadcaster_class_process) 3288 { 3289 HandleProcessEvent (event_sp); 3290 } 3291 else if (broadcaster_class == broadcaster_class_target) 3292 { 3293 if (Breakpoint::BreakpointEventData::GetEventDataFromEvent(event_sp.get())) 3294 { 3295 HandleBreakpointEvent (event_sp); 3296 } 3297 } 3298 else if (broadcaster_class == broadcaster_class_thread) 3299 { 3300 HandleThreadEvent (event_sp); 3301 } 3302 else if (broadcaster == m_command_interpreter_ap.get()) 3303 { 3304 if (event_type & CommandInterpreter::eBroadcastBitQuitCommandReceived) 3305 { 3306 done = true; 3307 } 3308 else if (event_type & CommandInterpreter::eBroadcastBitAsynchronousErrorData) 3309 { 3310 const char *data = reinterpret_cast<const char *>(EventDataBytes::GetBytesFromEvent (event_sp.get())); 3311 if (data && data[0]) 3312 { 3313 StreamFileSP error_sp (GetErrorFile()); 3314 if (error_sp) 3315 { 3316 HideTopIOHandler(); 3317 error_sp->PutCString(data); 3318 error_sp->Flush(); 3319 RefreshTopIOHandler(); 3320 } 3321 } 3322 } 3323 else if (event_type & CommandInterpreter::eBroadcastBitAsynchronousOutputData) 3324 { 3325 const char *data = reinterpret_cast<const char *>(EventDataBytes::GetBytesFromEvent (event_sp.get())); 3326 if (data && data[0]) 3327 { 3328 StreamFileSP output_sp (GetOutputFile()); 3329 if (output_sp) 3330 { 3331 HideTopIOHandler(); 3332 output_sp->PutCString(data); 3333 output_sp->Flush(); 3334 RefreshTopIOHandler(); 3335 } 3336 } 3337 } 3338 } 3339 } 3340 3341 if (m_forward_listener_sp) 3342 m_forward_listener_sp->AddEvent(event_sp); 3343 } 3344 } 3345 } 3346 } 3347 3348 lldb::thread_result_t 3349 Debugger::EventHandlerThread (lldb::thread_arg_t arg) 3350 { 3351 ((Debugger *)arg)->DefaultEventHandler(); 3352 return NULL; 3353 } 3354 3355 bool 3356 Debugger::StartEventHandlerThread() 3357 { 3358 if (!m_event_handler_thread.IsJoinable()) 3359 { 3360 // We must synchronize with the DefaultEventHandler() thread to ensure 3361 // it is up and running and listening to events before we return from 3362 // this function. We do this by listening to events for the 3363 // eBroadcastBitEventThreadIsListening from the m_sync_broadcaster 3364 Listener listener("lldb.debugger.event-handler"); 3365 listener.StartListeningForEvents(&m_sync_broadcaster, eBroadcastBitEventThreadIsListening); 3366 3367 // Use larger 8MB stack for this thread 3368 m_event_handler_thread = ThreadLauncher::LaunchThread("lldb.debugger.event-handler", EventHandlerThread, 3369 this, 3370 NULL, 3371 g_debugger_event_thread_stack_bytes); 3372 3373 // Make sure DefaultEventHandler() is running and listening to events before we return 3374 // from this function. We are only listening for events of type 3375 // eBroadcastBitEventThreadIsListening so we don't need to check the event, we just need 3376 // to wait an infinite amount of time for it (NULL timeout as the first parameter) 3377 lldb::EventSP event_sp; 3378 listener.WaitForEvent(NULL, event_sp); 3379 } 3380 return m_event_handler_thread.IsJoinable(); 3381 } 3382 3383 void 3384 Debugger::StopEventHandlerThread() 3385 { 3386 if (m_event_handler_thread.IsJoinable()) 3387 { 3388 GetCommandInterpreter().BroadcastEvent(CommandInterpreter::eBroadcastBitQuitCommandReceived); 3389 m_event_handler_thread.Join(nullptr); 3390 } 3391 } 3392 3393 3394 lldb::thread_result_t 3395 Debugger::IOHandlerThread (lldb::thread_arg_t arg) 3396 { 3397 Debugger *debugger = (Debugger *)arg; 3398 debugger->ExecuteIOHanders(); 3399 debugger->StopEventHandlerThread(); 3400 return NULL; 3401 } 3402 3403 bool 3404 Debugger::StartIOHandlerThread() 3405 { 3406 if (!m_io_handler_thread.IsJoinable()) 3407 m_io_handler_thread = ThreadLauncher::LaunchThread ("lldb.debugger.io-handler", 3408 IOHandlerThread, 3409 this, 3410 NULL, 3411 8*1024*1024); // Use larger 8MB stack for this thread 3412 return m_io_handler_thread.IsJoinable(); 3413 } 3414 3415 void 3416 Debugger::StopIOHandlerThread() 3417 { 3418 if (m_io_handler_thread.IsJoinable()) 3419 { 3420 if (m_input_file_sp) 3421 m_input_file_sp->GetFile().Close(); 3422 m_io_handler_thread.Join(nullptr); 3423 } 3424 } 3425 3426 Target * 3427 Debugger::GetDummyTarget() 3428 { 3429 return m_target_list.GetDummyTarget (*this).get(); 3430 } 3431 3432 Target * 3433 Debugger::GetSelectedOrDummyTarget(bool prefer_dummy) 3434 { 3435 Target *target = nullptr; 3436 if (!prefer_dummy) 3437 { 3438 target = m_target_list.GetSelectedTarget().get(); 3439 if (target) 3440 return target; 3441 } 3442 3443 return GetDummyTarget(); 3444 } 3445 3446