130fdc8d8SChris Lattner //===-- Debugger.cpp --------------------------------------------*- C++ -*-===// 230fdc8d8SChris Lattner // 330fdc8d8SChris Lattner // The LLVM Compiler Infrastructure 430fdc8d8SChris Lattner // 530fdc8d8SChris Lattner // This file is distributed under the University of Illinois Open Source 630fdc8d8SChris Lattner // License. See LICENSE.TXT for details. 730fdc8d8SChris Lattner // 830fdc8d8SChris Lattner //===----------------------------------------------------------------------===// 930fdc8d8SChris Lattner 1093a64300SDaniel Malea #include "lldb/lldb-python.h" 1193a64300SDaniel Malea 124a33d318SGreg Clayton #include "lldb/Core/Debugger.h" 134a33d318SGreg Clayton 144a33d318SGreg Clayton #include <map> 154a33d318SGreg Clayton 164becb37eSEnrico Granata #include "clang/AST/DeclCXX.h" 174becb37eSEnrico Granata #include "clang/AST/Type.h" 18705b1809SJason Molenda #include "llvm/ADT/StringRef.h" 194becb37eSEnrico Granata 2030fdc8d8SChris Lattner #include "lldb/lldb-private.h" 211f746071SGreg Clayton #include "lldb/Core/Module.h" 22e8cd0c98SGreg Clayton #include "lldb/Core/PluginManager.h" 237349bd90SGreg Clayton #include "lldb/Core/RegisterValue.h" 2430fdc8d8SChris Lattner #include "lldb/Core/State.h" 255b52f0c7SJim Ingham #include "lldb/Core/StreamAsynchronousIO.h" 26228063cdSJim Ingham #include "lldb/Core/StreamCallback.h" 2744d93782SGreg Clayton #include "lldb/Core/StreamFile.h" 281b654882SGreg Clayton #include "lldb/Core/StreamString.h" 29705b1809SJason Molenda #include "lldb/Core/StructuredData.h" 3030fdc8d8SChris Lattner #include "lldb/Core/Timer.h" 314becb37eSEnrico Granata #include "lldb/Core/ValueObject.h" 326d3dbf51SGreg Clayton #include "lldb/Core/ValueObjectVariable.h" 335548cb50SEnrico Granata #include "lldb/DataFormatters/DataVisualization.h" 345548cb50SEnrico Granata #include "lldb/DataFormatters/FormatManager.h" 35894f7359SEnrico Granata #include "lldb/DataFormatters/TypeSummary.h" 3693a66fc1SZachary Turner #include "lldb/Host/ConnectionFileDescriptor.h" 3742ff0ad8SZachary Turner #include "lldb/Host/HostInfo.h" 38a3406614SGreg Clayton #include "lldb/Host/Terminal.h" 3939de3110SZachary Turner #include "lldb/Host/ThreadLauncher.h" 406611103cSGreg Clayton #include "lldb/Interpreter/CommandInterpreter.h" 4167cc0636SGreg Clayton #include "lldb/Interpreter/OptionValueSInt64.h" 4267cc0636SGreg Clayton #include "lldb/Interpreter/OptionValueString.h" 431f746071SGreg Clayton #include "lldb/Symbol/ClangASTContext.h" 441f746071SGreg Clayton #include "lldb/Symbol/CompileUnit.h" 451f746071SGreg Clayton #include "lldb/Symbol/Function.h" 461f746071SGreg Clayton #include "lldb/Symbol/Symbol.h" 476d3dbf51SGreg Clayton #include "lldb/Symbol/VariableList.h" 48aff1b357SJason Molenda #include "lldb/Target/CPPLanguageRuntime.h" 49aff1b357SJason Molenda #include "lldb/Target/ObjCLanguageRuntime.h" 5030fdc8d8SChris Lattner #include "lldb/Target/TargetList.h" 5130fdc8d8SChris Lattner #include "lldb/Target/Process.h" 521b654882SGreg Clayton #include "lldb/Target/RegisterContext.h" 535fb8f797SGreg Clayton #include "lldb/Target/SectionLoadList.h" 541b654882SGreg Clayton #include "lldb/Target/StopInfo.h" 5584a53dfbSEnrico Granata #include "lldb/Target/Target.h" 5630fdc8d8SChris Lattner #include "lldb/Target/Thread.h" 575a31471eSGreg Clayton #include "lldb/Utility/AnsiTerminal.h" 5830fdc8d8SChris Lattner 5958a559c0SZachary Turner #include "llvm/Support/DynamicLibrary.h" 6058a559c0SZachary Turner 6130fdc8d8SChris Lattner using namespace lldb; 6230fdc8d8SChris Lattner using namespace lldb_private; 6330fdc8d8SChris Lattner 6430fdc8d8SChris Lattner 651b654882SGreg Clayton static uint32_t g_shared_debugger_refcount = 0; 66ebc1bb27SCaroline Tice static lldb::user_id_t g_unique_id = 1; 67ebc1bb27SCaroline Tice 681b654882SGreg Clayton #pragma mark Static Functions 691b654882SGreg Clayton 701b654882SGreg Clayton static Mutex & 711b654882SGreg Clayton GetDebuggerListMutex () 721b654882SGreg Clayton { 731b654882SGreg Clayton static Mutex g_mutex(Mutex::eMutexTypeRecursive); 741b654882SGreg Clayton return g_mutex; 751b654882SGreg Clayton } 761b654882SGreg Clayton 771b654882SGreg Clayton typedef std::vector<DebuggerSP> DebuggerList; 781b654882SGreg Clayton 791b654882SGreg Clayton static DebuggerList & 801b654882SGreg Clayton GetDebuggerList() 811b654882SGreg Clayton { 821b654882SGreg Clayton // hide the static debugger list inside a singleton accessor to avoid 836a7f3338SBruce Mitchener // global init constructors 841b654882SGreg Clayton static DebuggerList g_list; 851b654882SGreg Clayton return g_list; 861b654882SGreg Clayton } 87e372b98dSGreg Clayton 88e372b98dSGreg Clayton OptionEnumValueElement 8967cc0636SGreg Clayton g_show_disassembly_enum_values[] = 90e372b98dSGreg Clayton { 9167cc0636SGreg Clayton { Debugger::eStopDisassemblyTypeNever, "never", "Never show disassembly when displaying a stop context."}, 9267cc0636SGreg Clayton { Debugger::eStopDisassemblyTypeNoSource, "no-source", "Show disassembly when there is no source information, or the source file is missing when displaying a stop context."}, 9367cc0636SGreg Clayton { Debugger::eStopDisassemblyTypeAlways, "always", "Always show disassembly when displaying a stop context."}, 94e372b98dSGreg Clayton { 0, NULL, NULL } 95e372b98dSGreg Clayton }; 96e372b98dSGreg Clayton 9767cc0636SGreg Clayton OptionEnumValueElement 9867cc0636SGreg Clayton g_language_enumerators[] = 9967cc0636SGreg Clayton { 10067cc0636SGreg Clayton { eScriptLanguageNone, "none", "Disable scripting languages."}, 10167cc0636SGreg Clayton { eScriptLanguagePython, "python", "Select python as the default scripting language."}, 10267cc0636SGreg Clayton { eScriptLanguageDefault, "default", "Select the lldb default as the default scripting language."}, 103a12993c9SGreg Clayton { 0, NULL, NULL } 10467cc0636SGreg Clayton }; 105e372b98dSGreg Clayton 10667cc0636SGreg Clayton #define MODULE_WITH_FUNC "{ ${module.file.basename}{`${function.name-with-args}${function.pc-offset}}}" 10767cc0636SGreg Clayton #define FILE_AND_LINE "{ at ${line.file.basename}:${line.number}}" 10867cc0636SGreg Clayton 1090769b2b1SMichael Sartain #define DEFAULT_THREAD_FORMAT "thread #${thread.index}: tid = ${thread.id%tid}"\ 11067cc0636SGreg Clayton "{, ${frame.pc}}"\ 11167cc0636SGreg Clayton MODULE_WITH_FUNC\ 11267cc0636SGreg Clayton FILE_AND_LINE\ 1130769b2b1SMichael Sartain "{, name = '${thread.name}'}"\ 1140769b2b1SMichael Sartain "{, queue = '${thread.queue}'}"\ 115705b1809SJason Molenda "{, activity = '${thread.info.activity.name}'}" \ 116705b1809SJason Molenda "{, ${thread.info.trace_messages} messages}" \ 11767cc0636SGreg Clayton "{, stop reason = ${thread.stop-reason}}"\ 11867cc0636SGreg Clayton "{\\nReturn value: ${thread.return-value}}"\ 11930fadafeSJim Ingham "{\\nCompleted expression: ${thread.completed-expression}}"\ 12067cc0636SGreg Clayton "\\n" 12167cc0636SGreg Clayton 12267cc0636SGreg Clayton #define DEFAULT_FRAME_FORMAT "frame #${frame.index}: ${frame.pc}"\ 12367cc0636SGreg Clayton MODULE_WITH_FUNC\ 12467cc0636SGreg Clayton FILE_AND_LINE\ 12567cc0636SGreg Clayton "\\n" 12667cc0636SGreg Clayton 127aff1b357SJason Molenda #define DEFAULT_DISASSEMBLY_FORMAT "${addr-file-or-load} <${function.name-without-args}${function.concrete-only-addr-offset-no-padding}>: " 12867cc0636SGreg Clayton 12967cc0636SGreg Clayton 130754a9369SGreg Clayton static PropertyDefinition 131754a9369SGreg Clayton g_properties[] = 13267cc0636SGreg Clayton { 13367cc0636SGreg Clayton { "auto-confirm", OptionValue::eTypeBoolean, true, false, NULL, NULL, "If true all confirmation prompts will receive their default reply." }, 134aff1b357SJason Molenda { "disassembly-format", OptionValue::eTypeString , true, 0 , DEFAULT_DISASSEMBLY_FORMAT, NULL, "The default disassembly format string to use when disassembling instruction sequences." }, 13567cc0636SGreg Clayton { "frame-format", OptionValue::eTypeString , true, 0 , DEFAULT_FRAME_FORMAT, NULL, "The default frame format string to use when displaying stack frame information for threads." }, 13667cc0636SGreg Clayton { "notify-void", OptionValue::eTypeBoolean, true, false, NULL, NULL, "Notify the user explicitly if an expression returns void (default: false)." }, 1374c05410fSGreg Clayton { "prompt", OptionValue::eTypeString , true, OptionValueString::eOptionEncodeCharacterEscapeSequences, "(lldb) ", NULL, "The debugger command line prompt displayed for the user." }, 13867cc0636SGreg Clayton { "script-lang", OptionValue::eTypeEnum , true, eScriptLanguagePython, NULL, g_language_enumerators, "The script language to be used for evaluating user-written scripts." }, 13967cc0636SGreg Clayton { "stop-disassembly-count", OptionValue::eTypeSInt64 , true, 4 , NULL, NULL, "The number of disassembly lines to show when displaying a stopped context." }, 14067cc0636SGreg Clayton { "stop-disassembly-display", OptionValue::eTypeEnum , true, Debugger::eStopDisassemblyTypeNoSource, NULL, g_show_disassembly_enum_values, "Control when to display disassembly when displaying a stopped context." }, 14167cc0636SGreg Clayton { "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." }, 14267cc0636SGreg Clayton { "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." }, 14367cc0636SGreg Clayton { "term-width", OptionValue::eTypeSInt64 , true, 80 , NULL, NULL, "The maximum number of columns to use for displaying text." }, 14467cc0636SGreg Clayton { "thread-format", OptionValue::eTypeString , true, 0 , DEFAULT_THREAD_FORMAT, NULL, "The default thread format string to use when displaying thread information." }, 14567cc0636SGreg Clayton { "use-external-editor", OptionValue::eTypeBoolean, true, false, NULL, NULL, "Whether to use an external editor or not." }, 146c3ce7f27SMichael Sartain { "use-color", OptionValue::eTypeBoolean, true, true , NULL, NULL, "Whether to use Ansi color codes or not." }, 14790a8db30SEnrico Granata { "auto-one-line-summaries", OptionValue::eTypeBoolean, true, true, NULL, NULL, "If true, LLDB will automatically display small structs in one-liner format (default: true)." }, 148e8cd0c98SGreg Clayton 14967cc0636SGreg Clayton { NULL, OptionValue::eTypeInvalid, true, 0 , NULL, NULL, NULL } 15067cc0636SGreg Clayton }; 15167cc0636SGreg Clayton 15267cc0636SGreg Clayton enum 15367cc0636SGreg Clayton { 15467cc0636SGreg Clayton ePropertyAutoConfirm = 0, 155aff1b357SJason Molenda ePropertyDisassemblyFormat, 15667cc0636SGreg Clayton ePropertyFrameFormat, 15767cc0636SGreg Clayton ePropertyNotiftVoid, 15867cc0636SGreg Clayton ePropertyPrompt, 15967cc0636SGreg Clayton ePropertyScriptLanguage, 16067cc0636SGreg Clayton ePropertyStopDisassemblyCount, 16167cc0636SGreg Clayton ePropertyStopDisassemblyDisplay, 16267cc0636SGreg Clayton ePropertyStopLineCountAfter, 16367cc0636SGreg Clayton ePropertyStopLineCountBefore, 16467cc0636SGreg Clayton ePropertyTerminalWidth, 16567cc0636SGreg Clayton ePropertyThreadFormat, 166c3ce7f27SMichael Sartain ePropertyUseExternalEditor, 167c3ce7f27SMichael Sartain ePropertyUseColor, 16890a8db30SEnrico Granata ePropertyAutoOneLineSummaries 16967cc0636SGreg Clayton }; 17067cc0636SGreg Clayton 1715fb8f797SGreg Clayton Debugger::LoadPluginCallbackType Debugger::g_load_plugin_callback = NULL; 1724c05410fSGreg Clayton 1734c05410fSGreg Clayton Error 1744c05410fSGreg Clayton Debugger::SetPropertyValue (const ExecutionContext *exe_ctx, 1754c05410fSGreg Clayton VarSetOperationType op, 1764c05410fSGreg Clayton const char *property_path, 1774c05410fSGreg Clayton const char *value) 1784c05410fSGreg Clayton { 17984a53dfbSEnrico Granata bool is_load_script = strcmp(property_path,"target.load-script-from-symbol-file") == 0; 18084a53dfbSEnrico Granata TargetSP target_sp; 181397ddd5fSEnrico Granata LoadScriptFromSymFile load_script_old_value; 18284a53dfbSEnrico Granata if (is_load_script && exe_ctx->GetTargetSP()) 18384a53dfbSEnrico Granata { 18484a53dfbSEnrico Granata target_sp = exe_ctx->GetTargetSP(); 18584a53dfbSEnrico Granata load_script_old_value = target_sp->TargetProperties::GetLoadScriptFromSymbolFile(); 18684a53dfbSEnrico Granata } 1874c05410fSGreg Clayton Error error (Properties::SetPropertyValue (exe_ctx, op, property_path, value)); 1884c05410fSGreg Clayton if (error.Success()) 1894c05410fSGreg Clayton { 19084a53dfbSEnrico Granata // FIXME it would be nice to have "on-change" callbacks for properties 1914c05410fSGreg Clayton if (strcmp(property_path, g_properties[ePropertyPrompt].name) == 0) 1924c05410fSGreg Clayton { 1934c05410fSGreg Clayton const char *new_prompt = GetPrompt(); 194c3ce7f27SMichael Sartain std::string str = lldb_utility::ansi::FormatAnsiTerminalCodes (new_prompt, GetUseColor()); 195c3ce7f27SMichael Sartain if (str.length()) 196c3ce7f27SMichael Sartain new_prompt = str.c_str(); 19744d93782SGreg Clayton GetCommandInterpreter().UpdatePrompt(new_prompt); 1984c05410fSGreg Clayton EventSP prompt_change_event_sp (new Event(CommandInterpreter::eBroadcastBitResetPrompt, new EventDataBytes (new_prompt))); 1994c05410fSGreg Clayton GetCommandInterpreter().BroadcastEvent (prompt_change_event_sp); 2004c05410fSGreg Clayton } 201c3ce7f27SMichael Sartain else if (strcmp(property_path, g_properties[ePropertyUseColor].name) == 0) 202c3ce7f27SMichael Sartain { 203c3ce7f27SMichael Sartain // use-color changed. Ping the prompt so it can reset the ansi terminal codes. 204c3ce7f27SMichael Sartain SetPrompt (GetPrompt()); 205c3ce7f27SMichael Sartain } 206397ddd5fSEnrico Granata else if (is_load_script && target_sp && load_script_old_value == eLoadScriptFromSymFileWarn) 20784a53dfbSEnrico Granata { 208397ddd5fSEnrico Granata if (target_sp->TargetProperties::GetLoadScriptFromSymbolFile() == eLoadScriptFromSymFileTrue) 20984a53dfbSEnrico Granata { 21084a53dfbSEnrico Granata std::list<Error> errors; 2119730339bSEnrico Granata StreamString feedback_stream; 2129730339bSEnrico Granata if (!target_sp->LoadScriptingResources(errors,&feedback_stream)) 21384a53dfbSEnrico Granata { 21444d93782SGreg Clayton StreamFileSP stream_sp (GetErrorFile()); 21544d93782SGreg Clayton if (stream_sp) 21644d93782SGreg Clayton { 21784a53dfbSEnrico Granata for (auto error : errors) 21884a53dfbSEnrico Granata { 21944d93782SGreg Clayton stream_sp->Printf("%s\n",error.AsCString()); 22084a53dfbSEnrico Granata } 2219730339bSEnrico Granata if (feedback_stream.GetSize()) 22244d93782SGreg Clayton stream_sp->Printf("%s",feedback_stream.GetData()); 22344d93782SGreg Clayton } 22484a53dfbSEnrico Granata } 22584a53dfbSEnrico Granata } 22684a53dfbSEnrico Granata } 2274c05410fSGreg Clayton } 2284c05410fSGreg Clayton return error; 2294c05410fSGreg Clayton } 2304c05410fSGreg Clayton 23167cc0636SGreg Clayton bool 23267cc0636SGreg Clayton Debugger::GetAutoConfirm () const 23367cc0636SGreg Clayton { 23467cc0636SGreg Clayton const uint32_t idx = ePropertyAutoConfirm; 235754a9369SGreg Clayton return m_collection_sp->GetPropertyAtIndexAsBoolean (NULL, idx, g_properties[idx].default_uint_value != 0); 23667cc0636SGreg Clayton } 23767cc0636SGreg Clayton 23867cc0636SGreg Clayton const char * 239aff1b357SJason Molenda Debugger::GetDisassemblyFormat() const 240aff1b357SJason Molenda { 241aff1b357SJason Molenda const uint32_t idx = ePropertyDisassemblyFormat; 242aff1b357SJason Molenda return m_collection_sp->GetPropertyAtIndexAsString (NULL, idx, g_properties[idx].default_cstr_value); 243aff1b357SJason Molenda } 244aff1b357SJason Molenda 245aff1b357SJason Molenda const char * 24667cc0636SGreg Clayton Debugger::GetFrameFormat() const 24767cc0636SGreg Clayton { 24867cc0636SGreg Clayton const uint32_t idx = ePropertyFrameFormat; 249754a9369SGreg Clayton return m_collection_sp->GetPropertyAtIndexAsString (NULL, idx, g_properties[idx].default_cstr_value); 25067cc0636SGreg Clayton } 25167cc0636SGreg Clayton 25267cc0636SGreg Clayton bool 25367cc0636SGreg Clayton Debugger::GetNotifyVoid () const 25467cc0636SGreg Clayton { 25567cc0636SGreg Clayton const uint32_t idx = ePropertyNotiftVoid; 256754a9369SGreg Clayton return m_collection_sp->GetPropertyAtIndexAsBoolean (NULL, idx, g_properties[idx].default_uint_value != 0); 25767cc0636SGreg Clayton } 25867cc0636SGreg Clayton 25967cc0636SGreg Clayton const char * 26067cc0636SGreg Clayton Debugger::GetPrompt() const 26167cc0636SGreg Clayton { 26267cc0636SGreg Clayton const uint32_t idx = ePropertyPrompt; 263754a9369SGreg Clayton return m_collection_sp->GetPropertyAtIndexAsString (NULL, idx, g_properties[idx].default_cstr_value); 26467cc0636SGreg Clayton } 26567cc0636SGreg Clayton 26667cc0636SGreg Clayton void 26767cc0636SGreg Clayton Debugger::SetPrompt(const char *p) 26867cc0636SGreg Clayton { 26967cc0636SGreg Clayton const uint32_t idx = ePropertyPrompt; 27067cc0636SGreg Clayton m_collection_sp->SetPropertyAtIndexAsString (NULL, idx, p); 27167cc0636SGreg Clayton const char *new_prompt = GetPrompt(); 272c3ce7f27SMichael Sartain std::string str = lldb_utility::ansi::FormatAnsiTerminalCodes (new_prompt, GetUseColor()); 273c3ce7f27SMichael Sartain if (str.length()) 274c3ce7f27SMichael Sartain new_prompt = str.c_str(); 27544d93782SGreg Clayton GetCommandInterpreter().UpdatePrompt(new_prompt); 27667cc0636SGreg Clayton } 27767cc0636SGreg Clayton 27867cc0636SGreg Clayton const char * 27967cc0636SGreg Clayton Debugger::GetThreadFormat() const 28067cc0636SGreg Clayton { 28167cc0636SGreg Clayton const uint32_t idx = ePropertyThreadFormat; 282754a9369SGreg Clayton return m_collection_sp->GetPropertyAtIndexAsString (NULL, idx, g_properties[idx].default_cstr_value); 28367cc0636SGreg Clayton } 28467cc0636SGreg Clayton 28567cc0636SGreg Clayton lldb::ScriptLanguage 28667cc0636SGreg Clayton Debugger::GetScriptLanguage() const 28767cc0636SGreg Clayton { 28867cc0636SGreg Clayton const uint32_t idx = ePropertyScriptLanguage; 289754a9369SGreg Clayton return (lldb::ScriptLanguage)m_collection_sp->GetPropertyAtIndexAsEnumeration (NULL, idx, g_properties[idx].default_uint_value); 29067cc0636SGreg Clayton } 29167cc0636SGreg Clayton 29267cc0636SGreg Clayton bool 29367cc0636SGreg Clayton Debugger::SetScriptLanguage (lldb::ScriptLanguage script_lang) 29467cc0636SGreg Clayton { 29567cc0636SGreg Clayton const uint32_t idx = ePropertyScriptLanguage; 29667cc0636SGreg Clayton return m_collection_sp->SetPropertyAtIndexAsEnumeration (NULL, idx, script_lang); 29767cc0636SGreg Clayton } 29867cc0636SGreg Clayton 29967cc0636SGreg Clayton uint32_t 30067cc0636SGreg Clayton Debugger::GetTerminalWidth () const 30167cc0636SGreg Clayton { 30267cc0636SGreg Clayton const uint32_t idx = ePropertyTerminalWidth; 303754a9369SGreg Clayton return m_collection_sp->GetPropertyAtIndexAsSInt64 (NULL, idx, g_properties[idx].default_uint_value); 30467cc0636SGreg Clayton } 30567cc0636SGreg Clayton 30667cc0636SGreg Clayton bool 30767cc0636SGreg Clayton Debugger::SetTerminalWidth (uint32_t term_width) 30867cc0636SGreg Clayton { 30967cc0636SGreg Clayton const uint32_t idx = ePropertyTerminalWidth; 31067cc0636SGreg Clayton return m_collection_sp->SetPropertyAtIndexAsSInt64 (NULL, idx, term_width); 31167cc0636SGreg Clayton } 31267cc0636SGreg Clayton 31367cc0636SGreg Clayton bool 31467cc0636SGreg Clayton Debugger::GetUseExternalEditor () const 31567cc0636SGreg Clayton { 31667cc0636SGreg Clayton const uint32_t idx = ePropertyUseExternalEditor; 317754a9369SGreg Clayton return m_collection_sp->GetPropertyAtIndexAsBoolean (NULL, idx, g_properties[idx].default_uint_value != 0); 31867cc0636SGreg Clayton } 31967cc0636SGreg Clayton 32067cc0636SGreg Clayton bool 32167cc0636SGreg Clayton Debugger::SetUseExternalEditor (bool b) 32267cc0636SGreg Clayton { 32367cc0636SGreg Clayton const uint32_t idx = ePropertyUseExternalEditor; 32467cc0636SGreg Clayton return m_collection_sp->SetPropertyAtIndexAsBoolean (NULL, idx, b); 32567cc0636SGreg Clayton } 32667cc0636SGreg Clayton 327c3ce7f27SMichael Sartain bool 328c3ce7f27SMichael Sartain Debugger::GetUseColor () const 329c3ce7f27SMichael Sartain { 330c3ce7f27SMichael Sartain const uint32_t idx = ePropertyUseColor; 331c3ce7f27SMichael Sartain return m_collection_sp->GetPropertyAtIndexAsBoolean (NULL, idx, g_properties[idx].default_uint_value != 0); 332c3ce7f27SMichael Sartain } 333c3ce7f27SMichael Sartain 334c3ce7f27SMichael Sartain bool 335c3ce7f27SMichael Sartain Debugger::SetUseColor (bool b) 336c3ce7f27SMichael Sartain { 337c3ce7f27SMichael Sartain const uint32_t idx = ePropertyUseColor; 338c3ce7f27SMichael Sartain bool ret = m_collection_sp->SetPropertyAtIndexAsBoolean (NULL, idx, b); 339c3ce7f27SMichael Sartain SetPrompt (GetPrompt()); 340c3ce7f27SMichael Sartain return ret; 341c3ce7f27SMichael Sartain } 342c3ce7f27SMichael Sartain 34367cc0636SGreg Clayton uint32_t 34467cc0636SGreg Clayton Debugger::GetStopSourceLineCount (bool before) const 34567cc0636SGreg Clayton { 34667cc0636SGreg Clayton const uint32_t idx = before ? ePropertyStopLineCountBefore : ePropertyStopLineCountAfter; 347754a9369SGreg Clayton return m_collection_sp->GetPropertyAtIndexAsSInt64 (NULL, idx, g_properties[idx].default_uint_value); 34867cc0636SGreg Clayton } 34967cc0636SGreg Clayton 35067cc0636SGreg Clayton Debugger::StopDisassemblyType 35167cc0636SGreg Clayton Debugger::GetStopDisassemblyDisplay () const 35267cc0636SGreg Clayton { 35367cc0636SGreg Clayton const uint32_t idx = ePropertyStopDisassemblyDisplay; 354754a9369SGreg Clayton return (Debugger::StopDisassemblyType)m_collection_sp->GetPropertyAtIndexAsEnumeration (NULL, idx, g_properties[idx].default_uint_value); 35567cc0636SGreg Clayton } 35667cc0636SGreg Clayton 35767cc0636SGreg Clayton uint32_t 35867cc0636SGreg Clayton Debugger::GetDisassemblyLineCount () const 35967cc0636SGreg Clayton { 36067cc0636SGreg Clayton const uint32_t idx = ePropertyStopDisassemblyCount; 361754a9369SGreg Clayton return m_collection_sp->GetPropertyAtIndexAsSInt64 (NULL, idx, g_properties[idx].default_uint_value); 36267cc0636SGreg Clayton } 363e372b98dSGreg Clayton 364553fad5cSEnrico Granata bool 36590a8db30SEnrico Granata Debugger::GetAutoOneLineSummaries () const 366553fad5cSEnrico Granata { 36790a8db30SEnrico Granata const uint32_t idx = ePropertyAutoOneLineSummaries; 368553fad5cSEnrico Granata return m_collection_sp->GetPropertyAtIndexAsBoolean (NULL, idx, true); 369553fad5cSEnrico Granata 370553fad5cSEnrico Granata } 371553fad5cSEnrico Granata 3721b654882SGreg Clayton #pragma mark Debugger 3731b654882SGreg Clayton 37467cc0636SGreg Clayton //const DebuggerPropertiesSP & 37567cc0636SGreg Clayton //Debugger::GetSettings() const 37667cc0636SGreg Clayton //{ 37767cc0636SGreg Clayton // return m_properties_sp; 37867cc0636SGreg Clayton //} 37967cc0636SGreg Clayton // 38099d0faf2SGreg Clayton 3812f88aadfSCaroline Tice int 3822f88aadfSCaroline Tice Debugger::TestDebuggerRefCount () 3832f88aadfSCaroline Tice { 3842f88aadfSCaroline Tice return g_shared_debugger_refcount; 3852f88aadfSCaroline Tice } 3862f88aadfSCaroline Tice 38730fdc8d8SChris Lattner void 3885fb8f797SGreg Clayton Debugger::Initialize (LoadPluginCallbackType load_plugin_callback) 38930fdc8d8SChris Lattner { 3905fb8f797SGreg Clayton g_load_plugin_callback = load_plugin_callback; 391c15f55e2SGreg Clayton if (g_shared_debugger_refcount++ == 0) 392dbe54508SGreg Clayton lldb_private::Initialize(); 39399d0faf2SGreg Clayton } 39430fdc8d8SChris Lattner 39530fdc8d8SChris Lattner void 39630fdc8d8SChris Lattner Debugger::Terminate () 39730fdc8d8SChris Lattner { 3986611103cSGreg Clayton if (g_shared_debugger_refcount > 0) 3996611103cSGreg Clayton { 40030fdc8d8SChris Lattner g_shared_debugger_refcount--; 40130fdc8d8SChris Lattner if (g_shared_debugger_refcount == 0) 40230fdc8d8SChris Lattner { 403dbe54508SGreg Clayton lldb_private::WillTerminate(); 404dbe54508SGreg Clayton lldb_private::Terminate(); 4056760a517SCaroline Tice 40699d0faf2SGreg Clayton // Clear our master list of debugger objects 40799d0faf2SGreg Clayton Mutex::Locker locker (GetDebuggerListMutex ()); 40899d0faf2SGreg Clayton GetDebuggerList().clear(); 40930fdc8d8SChris Lattner } 4106760a517SCaroline Tice } 4116760a517SCaroline Tice } 41230fdc8d8SChris Lattner 41320bd37f7SCaroline Tice void 41420bd37f7SCaroline Tice Debugger::SettingsInitialize () 41520bd37f7SCaroline Tice { 4166920b52bSGreg Clayton Target::SettingsInitialize (); 41720bd37f7SCaroline Tice } 41820bd37f7SCaroline Tice 41920bd37f7SCaroline Tice void 42020bd37f7SCaroline Tice Debugger::SettingsTerminate () 42120bd37f7SCaroline Tice { 4226920b52bSGreg Clayton Target::SettingsTerminate (); 42320bd37f7SCaroline Tice } 42420bd37f7SCaroline Tice 42521dfcd9dSEnrico Granata bool 426e743c782SEnrico Granata Debugger::LoadPlugin (const FileSpec& spec, Error& error) 42721dfcd9dSEnrico Granata { 4285fb8f797SGreg Clayton if (g_load_plugin_callback) 429e743c782SEnrico Granata { 43058a559c0SZachary Turner llvm::sys::DynamicLibrary dynlib = g_load_plugin_callback (shared_from_this(), spec, error); 43158a559c0SZachary Turner if (dynlib.isValid()) 43221dfcd9dSEnrico Granata { 43358a559c0SZachary Turner m_loaded_plugins.push_back(dynlib); 43421dfcd9dSEnrico Granata return true; 43521dfcd9dSEnrico Granata } 4365fb8f797SGreg Clayton } 4375fb8f797SGreg Clayton else 4385fb8f797SGreg Clayton { 4395fb8f797SGreg Clayton // The g_load_plugin_callback is registered in SBDebugger::Initialize() 4405fb8f797SGreg Clayton // and if the public API layer isn't available (code is linking against 4415fb8f797SGreg Clayton // all of the internal LLDB static libraries), then we can't load plugins 4425fb8f797SGreg Clayton error.SetErrorString("Public API layer is not available"); 4435fb8f797SGreg Clayton } 44421dfcd9dSEnrico Granata return false; 44521dfcd9dSEnrico Granata } 44621dfcd9dSEnrico Granata 44721dfcd9dSEnrico Granata static FileSpec::EnumerateDirectoryResult 44821dfcd9dSEnrico Granata LoadPluginCallback 44921dfcd9dSEnrico Granata ( 45021dfcd9dSEnrico Granata void *baton, 45121dfcd9dSEnrico Granata FileSpec::FileType file_type, 45221dfcd9dSEnrico Granata const FileSpec &file_spec 45321dfcd9dSEnrico Granata ) 45421dfcd9dSEnrico Granata { 45521dfcd9dSEnrico Granata Error error; 45621dfcd9dSEnrico Granata 45721dfcd9dSEnrico Granata static ConstString g_dylibext("dylib"); 4583cf443ddSMichael Sartain static ConstString g_solibext("so"); 45921dfcd9dSEnrico Granata 46021dfcd9dSEnrico Granata if (!baton) 46121dfcd9dSEnrico Granata return FileSpec::eEnumerateDirectoryResultQuit; 46221dfcd9dSEnrico Granata 46321dfcd9dSEnrico Granata Debugger *debugger = (Debugger*)baton; 46421dfcd9dSEnrico Granata 46521dfcd9dSEnrico Granata // If we have a regular file, a symbolic link or unknown file type, try 46621dfcd9dSEnrico Granata // and process the file. We must handle unknown as sometimes the directory 46721dfcd9dSEnrico Granata // enumeration might be enumerating a file system that doesn't have correct 46821dfcd9dSEnrico Granata // file type information. 46921dfcd9dSEnrico Granata if (file_type == FileSpec::eFileTypeRegular || 47021dfcd9dSEnrico Granata file_type == FileSpec::eFileTypeSymbolicLink || 47121dfcd9dSEnrico Granata file_type == FileSpec::eFileTypeUnknown ) 47221dfcd9dSEnrico Granata { 47321dfcd9dSEnrico Granata FileSpec plugin_file_spec (file_spec); 47421dfcd9dSEnrico Granata plugin_file_spec.ResolvePath (); 47521dfcd9dSEnrico Granata 4763cf443ddSMichael Sartain if (plugin_file_spec.GetFileNameExtension() != g_dylibext && 4773cf443ddSMichael Sartain plugin_file_spec.GetFileNameExtension() != g_solibext) 4783cf443ddSMichael Sartain { 47921dfcd9dSEnrico Granata return FileSpec::eEnumerateDirectoryResultNext; 4803cf443ddSMichael Sartain } 48121dfcd9dSEnrico Granata 482e743c782SEnrico Granata Error plugin_load_error; 483e743c782SEnrico Granata debugger->LoadPlugin (plugin_file_spec, plugin_load_error); 48421dfcd9dSEnrico Granata 48521dfcd9dSEnrico Granata return FileSpec::eEnumerateDirectoryResultNext; 48621dfcd9dSEnrico Granata } 48721dfcd9dSEnrico Granata 48821dfcd9dSEnrico Granata else if (file_type == FileSpec::eFileTypeUnknown || 48921dfcd9dSEnrico Granata file_type == FileSpec::eFileTypeDirectory || 49021dfcd9dSEnrico Granata file_type == FileSpec::eFileTypeSymbolicLink ) 49121dfcd9dSEnrico Granata { 49221dfcd9dSEnrico Granata // Try and recurse into anything that a directory or symbolic link. 49321dfcd9dSEnrico Granata // We must also do this for unknown as sometimes the directory enumeration 4946a7f3338SBruce Mitchener // might be enumerating a file system that doesn't have correct file type 49521dfcd9dSEnrico Granata // information. 49621dfcd9dSEnrico Granata return FileSpec::eEnumerateDirectoryResultEnter; 49721dfcd9dSEnrico Granata } 49821dfcd9dSEnrico Granata 49921dfcd9dSEnrico Granata return FileSpec::eEnumerateDirectoryResultNext; 50021dfcd9dSEnrico Granata } 50121dfcd9dSEnrico Granata 50221dfcd9dSEnrico Granata void 50321dfcd9dSEnrico Granata Debugger::InstanceInitialize () 50421dfcd9dSEnrico Granata { 50521dfcd9dSEnrico Granata FileSpec dir_spec; 50621dfcd9dSEnrico Granata const bool find_directories = true; 50721dfcd9dSEnrico Granata const bool find_files = true; 50821dfcd9dSEnrico Granata const bool find_other = true; 50921dfcd9dSEnrico Granata char dir_path[PATH_MAX]; 51042ff0ad8SZachary Turner if (HostInfo::GetLLDBPath(ePathTypeLLDBSystemPlugins, dir_spec)) 51121dfcd9dSEnrico Granata { 51221dfcd9dSEnrico Granata if (dir_spec.Exists() && dir_spec.GetPath(dir_path, sizeof(dir_path))) 51321dfcd9dSEnrico Granata { 51421dfcd9dSEnrico Granata FileSpec::EnumerateDirectory (dir_path, 51521dfcd9dSEnrico Granata find_directories, 51621dfcd9dSEnrico Granata find_files, 51721dfcd9dSEnrico Granata find_other, 51821dfcd9dSEnrico Granata LoadPluginCallback, 51921dfcd9dSEnrico Granata this); 52021dfcd9dSEnrico Granata } 52121dfcd9dSEnrico Granata } 52221dfcd9dSEnrico Granata 52342ff0ad8SZachary Turner if (HostInfo::GetLLDBPath(ePathTypeLLDBUserPlugins, dir_spec)) 52421dfcd9dSEnrico Granata { 52521dfcd9dSEnrico Granata if (dir_spec.Exists() && dir_spec.GetPath(dir_path, sizeof(dir_path))) 52621dfcd9dSEnrico Granata { 52721dfcd9dSEnrico Granata FileSpec::EnumerateDirectory (dir_path, 52821dfcd9dSEnrico Granata find_directories, 52921dfcd9dSEnrico Granata find_files, 53021dfcd9dSEnrico Granata find_other, 53121dfcd9dSEnrico Granata LoadPluginCallback, 53221dfcd9dSEnrico Granata this); 53321dfcd9dSEnrico Granata } 53421dfcd9dSEnrico Granata } 535e8cd0c98SGreg Clayton 536e8cd0c98SGreg Clayton PluginManager::DebuggerInitialize (*this); 53721dfcd9dSEnrico Granata } 53821dfcd9dSEnrico Granata 5396611103cSGreg Clayton DebuggerSP 540228063cdSJim Ingham Debugger::CreateInstance (lldb::LogOutputCallback log_callback, void *baton) 5416611103cSGreg Clayton { 542228063cdSJim Ingham DebuggerSP debugger_sp (new Debugger(log_callback, baton)); 543c15f55e2SGreg Clayton if (g_shared_debugger_refcount > 0) 5446611103cSGreg Clayton { 5456611103cSGreg Clayton Mutex::Locker locker (GetDebuggerListMutex ()); 5466611103cSGreg Clayton GetDebuggerList().push_back(debugger_sp); 5476611103cSGreg Clayton } 54821dfcd9dSEnrico Granata debugger_sp->InstanceInitialize (); 5496611103cSGreg Clayton return debugger_sp; 5506611103cSGreg Clayton } 5516611103cSGreg Clayton 552e02657b1SCaroline Tice void 5534d122c40SGreg Clayton Debugger::Destroy (DebuggerSP &debugger_sp) 554e02657b1SCaroline Tice { 555e02657b1SCaroline Tice if (debugger_sp.get() == NULL) 556e02657b1SCaroline Tice return; 557e02657b1SCaroline Tice 5588314c525SJim Ingham debugger_sp->Clear(); 5598314c525SJim Ingham 560c15f55e2SGreg Clayton if (g_shared_debugger_refcount > 0) 561c15f55e2SGreg Clayton { 562e02657b1SCaroline Tice Mutex::Locker locker (GetDebuggerListMutex ()); 563e02657b1SCaroline Tice DebuggerList &debugger_list = GetDebuggerList (); 564e02657b1SCaroline Tice DebuggerList::iterator pos, end = debugger_list.end(); 565e02657b1SCaroline Tice for (pos = debugger_list.begin (); pos != end; ++pos) 566e02657b1SCaroline Tice { 567e02657b1SCaroline Tice if ((*pos).get() == debugger_sp.get()) 568e02657b1SCaroline Tice { 569e02657b1SCaroline Tice debugger_list.erase (pos); 570e02657b1SCaroline Tice return; 571e02657b1SCaroline Tice } 572e02657b1SCaroline Tice } 573e02657b1SCaroline Tice } 574c15f55e2SGreg Clayton } 575e02657b1SCaroline Tice 5764d122c40SGreg Clayton DebuggerSP 5773df9a8dfSCaroline Tice Debugger::FindDebuggerWithInstanceName (const ConstString &instance_name) 5783df9a8dfSCaroline Tice { 5794d122c40SGreg Clayton DebuggerSP debugger_sp; 5806920b52bSGreg Clayton if (g_shared_debugger_refcount > 0) 5816920b52bSGreg Clayton { 5826920b52bSGreg Clayton Mutex::Locker locker (GetDebuggerListMutex ()); 5836920b52bSGreg Clayton DebuggerList &debugger_list = GetDebuggerList(); 5846920b52bSGreg Clayton DebuggerList::iterator pos, end = debugger_list.end(); 5856920b52bSGreg Clayton 5866920b52bSGreg Clayton for (pos = debugger_list.begin(); pos != end; ++pos) 5876920b52bSGreg Clayton { 5886920b52bSGreg Clayton if ((*pos).get()->m_instance_name == instance_name) 5896920b52bSGreg Clayton { 5906920b52bSGreg Clayton debugger_sp = *pos; 5916920b52bSGreg Clayton break; 5926920b52bSGreg Clayton } 5936920b52bSGreg Clayton } 5946920b52bSGreg Clayton } 5953df9a8dfSCaroline Tice return debugger_sp; 5963df9a8dfSCaroline Tice } 5976611103cSGreg Clayton 5986611103cSGreg Clayton TargetSP 5996611103cSGreg Clayton Debugger::FindTargetWithProcessID (lldb::pid_t pid) 6006611103cSGreg Clayton { 6014d122c40SGreg Clayton TargetSP target_sp; 602c15f55e2SGreg Clayton if (g_shared_debugger_refcount > 0) 603c15f55e2SGreg Clayton { 6046611103cSGreg Clayton Mutex::Locker locker (GetDebuggerListMutex ()); 6056611103cSGreg Clayton DebuggerList &debugger_list = GetDebuggerList(); 6066611103cSGreg Clayton DebuggerList::iterator pos, end = debugger_list.end(); 6076611103cSGreg Clayton for (pos = debugger_list.begin(); pos != end; ++pos) 6086611103cSGreg Clayton { 6096611103cSGreg Clayton target_sp = (*pos)->GetTargetList().FindTargetWithProcessID (pid); 6106611103cSGreg Clayton if (target_sp) 6116611103cSGreg Clayton break; 6126611103cSGreg Clayton } 613c15f55e2SGreg Clayton } 6146611103cSGreg Clayton return target_sp; 6156611103cSGreg Clayton } 6166611103cSGreg Clayton 617e4e45924SGreg Clayton TargetSP 618e4e45924SGreg Clayton Debugger::FindTargetWithProcess (Process *process) 619e4e45924SGreg Clayton { 620e4e45924SGreg Clayton TargetSP target_sp; 621c15f55e2SGreg Clayton if (g_shared_debugger_refcount > 0) 622c15f55e2SGreg Clayton { 623e4e45924SGreg Clayton Mutex::Locker locker (GetDebuggerListMutex ()); 624e4e45924SGreg Clayton DebuggerList &debugger_list = GetDebuggerList(); 625e4e45924SGreg Clayton DebuggerList::iterator pos, end = debugger_list.end(); 626e4e45924SGreg Clayton for (pos = debugger_list.begin(); pos != end; ++pos) 627e4e45924SGreg Clayton { 628e4e45924SGreg Clayton target_sp = (*pos)->GetTargetList().FindTargetWithProcess (process); 629e4e45924SGreg Clayton if (target_sp) 630e4e45924SGreg Clayton break; 631e4e45924SGreg Clayton } 632c15f55e2SGreg Clayton } 633e4e45924SGreg Clayton return target_sp; 634e4e45924SGreg Clayton } 635e4e45924SGreg Clayton 636e6481c7eSJason Molenda Debugger::Debugger(lldb::LogOutputCallback log_callback, void *baton) : 637e6481c7eSJason Molenda UserID(g_unique_id++), 638e6481c7eSJason Molenda Properties(OptionValuePropertiesSP(new OptionValueProperties())), 639e6481c7eSJason Molenda m_input_file_sp(new StreamFile(stdin, false)), 640e6481c7eSJason Molenda m_output_file_sp(new StreamFile(stdout, false)), 641e6481c7eSJason Molenda m_error_file_sp(new StreamFile(stderr, false)), 642e6481c7eSJason Molenda m_terminal_state(), 643e6481c7eSJason Molenda m_target_list(*this), 644e6481c7eSJason Molenda m_platform_list(), 645e6481c7eSJason Molenda m_listener("lldb.Debugger"), 646e6481c7eSJason Molenda m_source_manager_ap(), 647e6481c7eSJason Molenda m_source_file_cache(), 648e6481c7eSJason Molenda m_command_interpreter_ap(new CommandInterpreter(*this, eScriptLanguageDefault, false)), 649e6481c7eSJason Molenda m_input_reader_stack(), 650e6481c7eSJason Molenda m_instance_name(), 651e6481c7eSJason Molenda m_loaded_plugins() 65230fdc8d8SChris Lattner { 65367cc0636SGreg Clayton char instance_cstr[256]; 65467cc0636SGreg Clayton snprintf(instance_cstr, sizeof(instance_cstr), "debugger_%d", (int)GetID()); 65567cc0636SGreg Clayton m_instance_name.SetCString(instance_cstr); 656228063cdSJim Ingham if (log_callback) 657228063cdSJim Ingham m_log_callback_stream_sp.reset (new StreamCallback (log_callback, baton)); 6586611103cSGreg Clayton m_command_interpreter_ap->Initialize (); 659ded470d3SGreg Clayton // Always add our default platform to the platform list 660615eb7e6SGreg Clayton PlatformSP default_platform_sp (Platform::GetHostPlatform()); 661ded470d3SGreg Clayton assert (default_platform_sp.get()); 662ded470d3SGreg Clayton m_platform_list.Append (default_platform_sp, true); 66367cc0636SGreg Clayton 664754a9369SGreg Clayton m_collection_sp->Initialize (g_properties); 66567cc0636SGreg Clayton m_collection_sp->AppendProperty (ConstString("target"), 66667cc0636SGreg Clayton ConstString("Settings specify to debugging targets."), 66767cc0636SGreg Clayton true, 66867cc0636SGreg Clayton Target::GetGlobalProperties()->GetValueProperties()); 669754a9369SGreg Clayton if (m_command_interpreter_ap.get()) 670754a9369SGreg Clayton { 671754a9369SGreg Clayton m_collection_sp->AppendProperty (ConstString("interpreter"), 672754a9369SGreg Clayton ConstString("Settings specify to the debugger's command interpreter."), 673754a9369SGreg Clayton true, 674754a9369SGreg Clayton m_command_interpreter_ap->GetValueProperties()); 675754a9369SGreg Clayton } 67667cc0636SGreg Clayton OptionValueSInt64 *term_width = m_collection_sp->GetPropertyAtIndexAsOptionValueSInt64 (NULL, ePropertyTerminalWidth); 67767cc0636SGreg Clayton term_width->SetMinimumValue(10); 67867cc0636SGreg Clayton term_width->SetMaximumValue(1024); 679c3ce7f27SMichael Sartain 680c3ce7f27SMichael Sartain // Turn off use-color if this is a dumb terminal. 681c3ce7f27SMichael Sartain const char *term = getenv ("TERM"); 682c3ce7f27SMichael Sartain if (term && !strcmp (term, "dumb")) 683c3ce7f27SMichael Sartain SetUseColor (false); 68430fdc8d8SChris Lattner } 68530fdc8d8SChris Lattner 68630fdc8d8SChris Lattner Debugger::~Debugger () 68730fdc8d8SChris Lattner { 6888314c525SJim Ingham Clear(); 6898314c525SJim Ingham } 6908314c525SJim Ingham 6918314c525SJim Ingham void 6928314c525SJim Ingham Debugger::Clear() 6938314c525SJim Ingham { 69444d93782SGreg Clayton ClearIOHandlers(); 69544d93782SGreg Clayton StopIOHandlerThread(); 69644d93782SGreg Clayton StopEventHandlerThread(); 6971ed54f50SGreg Clayton m_listener.Clear(); 6986611103cSGreg Clayton int num_targets = m_target_list.GetNumTargets(); 6996611103cSGreg Clayton for (int i = 0; i < num_targets; i++) 7006611103cSGreg Clayton { 701ccbc08e6SGreg Clayton TargetSP target_sp (m_target_list.GetTargetAtIndex (i)); 702ccbc08e6SGreg Clayton if (target_sp) 703ccbc08e6SGreg Clayton { 704ccbc08e6SGreg Clayton ProcessSP process_sp (target_sp->GetProcessSP()); 7056611103cSGreg Clayton if (process_sp) 7061fd07059SJim Ingham process_sp->Finalize(); 707ccbc08e6SGreg Clayton target_sp->Destroy(); 7086611103cSGreg Clayton } 70930fdc8d8SChris Lattner } 7104bddaeb5SJim Ingham BroadcasterManager::Clear (); 71130fdc8d8SChris Lattner 7120d69a3a4SGreg Clayton // Close the input file _before_ we close the input read communications class 7130d69a3a4SGreg Clayton // as it does NOT own the input file, our m_input_file does. 714c5917d9aSJim Ingham m_terminal_state.Clear(); 71544d93782SGreg Clayton if (m_input_file_sp) 71644d93782SGreg Clayton m_input_file_sp->GetFile().Close (); 7170c4129f2SGreg Clayton 7180c4129f2SGreg Clayton m_command_interpreter_ap->Clear(); 7198314c525SJim Ingham } 72030fdc8d8SChris Lattner 72130fdc8d8SChris Lattner bool 722fc3f027dSGreg Clayton Debugger::GetCloseInputOnEOF () const 723fc3f027dSGreg Clayton { 72444d93782SGreg Clayton // return m_input_comm.GetCloseOnEOF(); 72544d93782SGreg Clayton return false; 726fc3f027dSGreg Clayton } 727fc3f027dSGreg Clayton 728fc3f027dSGreg Clayton void 729fc3f027dSGreg Clayton Debugger::SetCloseInputOnEOF (bool b) 730fc3f027dSGreg Clayton { 73144d93782SGreg Clayton // m_input_comm.SetCloseOnEOF(b); 732fc3f027dSGreg Clayton } 733fc3f027dSGreg Clayton 734fc3f027dSGreg Clayton bool 73530fdc8d8SChris Lattner Debugger::GetAsyncExecution () 73630fdc8d8SChris Lattner { 7376611103cSGreg Clayton return !m_command_interpreter_ap->GetSynchronous(); 73830fdc8d8SChris Lattner } 73930fdc8d8SChris Lattner 74030fdc8d8SChris Lattner void 74130fdc8d8SChris Lattner Debugger::SetAsyncExecution (bool async_execution) 74230fdc8d8SChris Lattner { 7436611103cSGreg Clayton m_command_interpreter_ap->SetSynchronous (!async_execution); 74430fdc8d8SChris Lattner } 74530fdc8d8SChris Lattner 74630fdc8d8SChris Lattner 74730fdc8d8SChris Lattner void 74830fdc8d8SChris Lattner Debugger::SetInputFileHandle (FILE *fh, bool tranfer_ownership) 74930fdc8d8SChris Lattner { 75044d93782SGreg Clayton if (m_input_file_sp) 75144d93782SGreg Clayton m_input_file_sp->GetFile().SetStream (fh, tranfer_ownership); 75244d93782SGreg Clayton else 75344d93782SGreg Clayton m_input_file_sp.reset (new StreamFile (fh, tranfer_ownership)); 75444d93782SGreg Clayton 75544d93782SGreg Clayton File &in_file = m_input_file_sp->GetFile(); 75651b1e2d2SGreg Clayton if (in_file.IsValid() == false) 75751b1e2d2SGreg Clayton in_file.SetStream (stdin, true); 75830fdc8d8SChris Lattner 759c5917d9aSJim Ingham // Save away the terminal state if that is relevant, so that we can restore it in RestoreInputState. 760c5917d9aSJim Ingham SaveInputTerminalState (); 76130fdc8d8SChris Lattner } 76230fdc8d8SChris Lattner 76330fdc8d8SChris Lattner void 76430fdc8d8SChris Lattner Debugger::SetOutputFileHandle (FILE *fh, bool tranfer_ownership) 76530fdc8d8SChris Lattner { 76644d93782SGreg Clayton if (m_output_file_sp) 76744d93782SGreg Clayton m_output_file_sp->GetFile().SetStream (fh, tranfer_ownership); 76844d93782SGreg Clayton else 76944d93782SGreg Clayton m_output_file_sp.reset (new StreamFile (fh, tranfer_ownership)); 77044d93782SGreg Clayton 77144d93782SGreg Clayton File &out_file = m_output_file_sp->GetFile(); 77251b1e2d2SGreg Clayton if (out_file.IsValid() == false) 77351b1e2d2SGreg Clayton out_file.SetStream (stdout, false); 7742f88aadfSCaroline Tice 775b588726eSEnrico Granata // do not create the ScriptInterpreter just for setting the output file handle 776b588726eSEnrico Granata // as the constructor will know how to do the right thing on its own 777b588726eSEnrico Granata const bool can_create = false; 778b588726eSEnrico Granata ScriptInterpreter* script_interpreter = GetCommandInterpreter().GetScriptInterpreter(can_create); 779b588726eSEnrico Granata if (script_interpreter) 780b588726eSEnrico Granata script_interpreter->ResetOutputFileHandle (fh); 78130fdc8d8SChris Lattner } 78230fdc8d8SChris Lattner 78330fdc8d8SChris Lattner void 78430fdc8d8SChris Lattner Debugger::SetErrorFileHandle (FILE *fh, bool tranfer_ownership) 78530fdc8d8SChris Lattner { 78644d93782SGreg Clayton if (m_error_file_sp) 78744d93782SGreg Clayton m_error_file_sp->GetFile().SetStream (fh, tranfer_ownership); 78844d93782SGreg Clayton else 78944d93782SGreg Clayton m_error_file_sp.reset (new StreamFile (fh, tranfer_ownership)); 79044d93782SGreg Clayton 79144d93782SGreg Clayton File &err_file = m_error_file_sp->GetFile(); 79251b1e2d2SGreg Clayton if (err_file.IsValid() == false) 79351b1e2d2SGreg Clayton err_file.SetStream (stderr, false); 79430fdc8d8SChris Lattner } 79530fdc8d8SChris Lattner 796c5917d9aSJim Ingham void 797c5917d9aSJim Ingham Debugger::SaveInputTerminalState () 798c5917d9aSJim Ingham { 79944d93782SGreg Clayton if (m_input_file_sp) 80044d93782SGreg Clayton { 80144d93782SGreg Clayton File &in_file = m_input_file_sp->GetFile(); 802c5917d9aSJim Ingham if (in_file.GetDescriptor() != File::kInvalidDescriptor) 803c5917d9aSJim Ingham m_terminal_state.Save(in_file.GetDescriptor(), true); 804c5917d9aSJim Ingham } 80544d93782SGreg Clayton } 806c5917d9aSJim Ingham 807c5917d9aSJim Ingham void 808c5917d9aSJim Ingham Debugger::RestoreInputTerminalState () 809c5917d9aSJim Ingham { 810c5917d9aSJim Ingham m_terminal_state.Restore(); 811c5917d9aSJim Ingham } 812c5917d9aSJim Ingham 81330fdc8d8SChris Lattner ExecutionContext 8142976d00aSJim Ingham Debugger::GetSelectedExecutionContext () 81530fdc8d8SChris Lattner { 81630fdc8d8SChris Lattner ExecutionContext exe_ctx; 817c14ee32dSGreg Clayton TargetSP target_sp(GetSelectedTarget()); 818c14ee32dSGreg Clayton exe_ctx.SetTargetSP (target_sp); 81930fdc8d8SChris Lattner 82030fdc8d8SChris Lattner if (target_sp) 82130fdc8d8SChris Lattner { 822c14ee32dSGreg Clayton ProcessSP process_sp (target_sp->GetProcessSP()); 823c14ee32dSGreg Clayton exe_ctx.SetProcessSP (process_sp); 824c14ee32dSGreg Clayton if (process_sp && process_sp->IsRunning() == false) 82530fdc8d8SChris Lattner { 826c14ee32dSGreg Clayton ThreadSP thread_sp (process_sp->GetThreadList().GetSelectedThread()); 827c14ee32dSGreg Clayton if (thread_sp) 82830fdc8d8SChris Lattner { 829c14ee32dSGreg Clayton exe_ctx.SetThreadSP (thread_sp); 830c14ee32dSGreg Clayton exe_ctx.SetFrameSP (thread_sp->GetSelectedFrame()); 831c14ee32dSGreg Clayton if (exe_ctx.GetFramePtr() == NULL) 832c14ee32dSGreg Clayton exe_ctx.SetFrameSP (thread_sp->GetStackFrameAtIndex (0)); 83330fdc8d8SChris Lattner } 83430fdc8d8SChris Lattner } 83530fdc8d8SChris Lattner } 83630fdc8d8SChris Lattner return exe_ctx; 83730fdc8d8SChris Lattner } 83830fdc8d8SChris Lattner 83930fdc8d8SChris Lattner void 840efed6131SCaroline Tice Debugger::DispatchInputInterrupt () 841efed6131SCaroline Tice { 84244d93782SGreg Clayton Mutex::Locker locker (m_input_reader_stack.GetMutex()); 84344d93782SGreg Clayton IOHandlerSP reader_sp (m_input_reader_stack.Top()); 844efed6131SCaroline Tice if (reader_sp) 84544d93782SGreg Clayton reader_sp->Interrupt(); 846efed6131SCaroline Tice } 847efed6131SCaroline Tice 848efed6131SCaroline Tice void 849efed6131SCaroline Tice Debugger::DispatchInputEndOfFile () 850efed6131SCaroline Tice { 85144d93782SGreg Clayton Mutex::Locker locker (m_input_reader_stack.GetMutex()); 85244d93782SGreg Clayton IOHandlerSP reader_sp (m_input_reader_stack.Top()); 853efed6131SCaroline Tice if (reader_sp) 85444d93782SGreg Clayton reader_sp->GotEOF(); 855efed6131SCaroline Tice } 856efed6131SCaroline Tice 857efed6131SCaroline Tice void 85844d93782SGreg Clayton Debugger::ClearIOHandlers () 8593d6086f6SCaroline Tice { 860b44880caSCaroline Tice // The bottom input reader should be the main debugger input reader. We do not want to close that one here. 86144d93782SGreg Clayton Mutex::Locker locker (m_input_reader_stack.GetMutex()); 862d5a0a01bSCaroline Tice while (m_input_reader_stack.GetSize() > 1) 8633d6086f6SCaroline Tice { 86444d93782SGreg Clayton IOHandlerSP reader_sp (m_input_reader_stack.Top()); 8653d6086f6SCaroline Tice if (reader_sp) 8663d6086f6SCaroline Tice { 86744d93782SGreg Clayton m_input_reader_stack.Pop(); 8683d6086f6SCaroline Tice reader_sp->SetIsDone(true); 869e68f5d6bSGreg Clayton reader_sp->Cancel(); 8703d6086f6SCaroline Tice } 8713d6086f6SCaroline Tice } 8723d6086f6SCaroline Tice } 8733d6086f6SCaroline Tice 8743d6086f6SCaroline Tice void 87544d93782SGreg Clayton Debugger::ExecuteIOHanders() 876969ed3d1SCaroline Tice { 87744d93782SGreg Clayton 87844d93782SGreg Clayton while (1) 879969ed3d1SCaroline Tice { 88044d93782SGreg Clayton IOHandlerSP reader_sp(m_input_reader_stack.Top()); 88130fdc8d8SChris Lattner if (!reader_sp) 88230fdc8d8SChris Lattner break; 88330fdc8d8SChris Lattner 88444d93782SGreg Clayton reader_sp->Activate(); 88544d93782SGreg Clayton reader_sp->Run(); 88644d93782SGreg Clayton reader_sp->Deactivate(); 88744d93782SGreg Clayton 88844d93782SGreg Clayton // Remove all input readers that are done from the top of the stack 88944d93782SGreg Clayton while (1) 89030fdc8d8SChris Lattner { 89144d93782SGreg Clayton IOHandlerSP top_reader_sp = m_input_reader_stack.Top(); 89244d93782SGreg Clayton if (top_reader_sp && top_reader_sp->GetIsDone()) 89344d93782SGreg Clayton m_input_reader_stack.Pop(); 89430fdc8d8SChris Lattner else 89530fdc8d8SChris Lattner break; 89630fdc8d8SChris Lattner } 89730fdc8d8SChris Lattner } 89844d93782SGreg Clayton ClearIOHandlers(); 89944d93782SGreg Clayton } 90030fdc8d8SChris Lattner 90144d93782SGreg Clayton bool 90244d93782SGreg Clayton Debugger::IsTopIOHandler (const lldb::IOHandlerSP& reader_sp) 90344d93782SGreg Clayton { 90444d93782SGreg Clayton return m_input_reader_stack.IsTop (reader_sp); 90544d93782SGreg Clayton } 90630fdc8d8SChris Lattner 90744d93782SGreg Clayton 90844d93782SGreg Clayton ConstString 90944d93782SGreg Clayton Debugger::GetTopIOHandlerControlSequence(char ch) 91044d93782SGreg Clayton { 91144d93782SGreg Clayton return m_input_reader_stack.GetTopIOHandlerControlSequence (ch); 91230fdc8d8SChris Lattner } 91330fdc8d8SChris Lattner 91430fdc8d8SChris Lattner void 91544d93782SGreg Clayton Debugger::RunIOHandler (const IOHandlerSP& reader_sp) 91644d93782SGreg Clayton { 91744d93782SGreg Clayton Mutex::Locker locker (m_input_reader_stack.GetMutex()); 91844d93782SGreg Clayton PushIOHandler (reader_sp); 919577508dfSGreg Clayton 920577508dfSGreg Clayton IOHandlerSP top_reader_sp = reader_sp; 921577508dfSGreg Clayton while (top_reader_sp) 922577508dfSGreg Clayton { 923577508dfSGreg Clayton top_reader_sp->Activate(); 924577508dfSGreg Clayton top_reader_sp->Run(); 925577508dfSGreg Clayton top_reader_sp->Deactivate(); 926577508dfSGreg Clayton 927577508dfSGreg Clayton if (top_reader_sp.get() == reader_sp.get()) 928577508dfSGreg Clayton { 929577508dfSGreg Clayton if (PopIOHandler (reader_sp)) 930577508dfSGreg Clayton break; 931577508dfSGreg Clayton } 932577508dfSGreg Clayton 933577508dfSGreg Clayton while (1) 934577508dfSGreg Clayton { 935577508dfSGreg Clayton top_reader_sp = m_input_reader_stack.Top(); 936577508dfSGreg Clayton if (top_reader_sp && top_reader_sp->GetIsDone()) 937577508dfSGreg Clayton m_input_reader_stack.Pop(); 938577508dfSGreg Clayton else 939577508dfSGreg Clayton break; 940577508dfSGreg Clayton } 941577508dfSGreg Clayton } 94244d93782SGreg Clayton } 94344d93782SGreg Clayton 94444d93782SGreg Clayton void 94544d93782SGreg Clayton Debugger::AdoptTopIOHandlerFilesIfInvalid (StreamFileSP &in, StreamFileSP &out, StreamFileSP &err) 94644d93782SGreg Clayton { 94744d93782SGreg Clayton // Before an IOHandler runs, it must have in/out/err streams. 94844d93782SGreg Clayton // This function is called when one ore more of the streams 94944d93782SGreg Clayton // are NULL. We use the top input reader's in/out/err streams, 95044d93782SGreg Clayton // or fall back to the debugger file handles, or we fall back 95144d93782SGreg Clayton // onto stdin/stdout/stderr as a last resort. 95244d93782SGreg Clayton 95344d93782SGreg Clayton Mutex::Locker locker (m_input_reader_stack.GetMutex()); 95444d93782SGreg Clayton IOHandlerSP top_reader_sp (m_input_reader_stack.Top()); 95544d93782SGreg Clayton // If no STDIN has been set, then set it appropriately 95644d93782SGreg Clayton if (!in) 95744d93782SGreg Clayton { 95844d93782SGreg Clayton if (top_reader_sp) 95944d93782SGreg Clayton in = top_reader_sp->GetInputStreamFile(); 96044d93782SGreg Clayton else 96144d93782SGreg Clayton in = GetInputFile(); 96244d93782SGreg Clayton 96344d93782SGreg Clayton // If there is nothing, use stdin 96444d93782SGreg Clayton if (!in) 96544d93782SGreg Clayton in = StreamFileSP(new StreamFile(stdin, false)); 96644d93782SGreg Clayton } 96744d93782SGreg Clayton // If no STDOUT has been set, then set it appropriately 96844d93782SGreg Clayton if (!out) 96944d93782SGreg Clayton { 97044d93782SGreg Clayton if (top_reader_sp) 97144d93782SGreg Clayton out = top_reader_sp->GetOutputStreamFile(); 97244d93782SGreg Clayton else 97344d93782SGreg Clayton out = GetOutputFile(); 97444d93782SGreg Clayton 97544d93782SGreg Clayton // If there is nothing, use stdout 97644d93782SGreg Clayton if (!out) 97744d93782SGreg Clayton out = StreamFileSP(new StreamFile(stdout, false)); 97844d93782SGreg Clayton } 97944d93782SGreg Clayton // If no STDERR has been set, then set it appropriately 98044d93782SGreg Clayton if (!err) 98144d93782SGreg Clayton { 98244d93782SGreg Clayton if (top_reader_sp) 98344d93782SGreg Clayton err = top_reader_sp->GetErrorStreamFile(); 98444d93782SGreg Clayton else 98544d93782SGreg Clayton err = GetErrorFile(); 98644d93782SGreg Clayton 98744d93782SGreg Clayton // If there is nothing, use stderr 98844d93782SGreg Clayton if (!err) 98944d93782SGreg Clayton err = StreamFileSP(new StreamFile(stdout, false)); 99044d93782SGreg Clayton 99144d93782SGreg Clayton } 99244d93782SGreg Clayton } 99344d93782SGreg Clayton 99444d93782SGreg Clayton void 99544d93782SGreg Clayton Debugger::PushIOHandler (const IOHandlerSP& reader_sp) 99630fdc8d8SChris Lattner { 99730fdc8d8SChris Lattner if (!reader_sp) 99830fdc8d8SChris Lattner return; 999b44880caSCaroline Tice 100044d93782SGreg Clayton // Got the current top input reader... 100144d93782SGreg Clayton IOHandlerSP top_reader_sp (m_input_reader_stack.Top()); 1002b44880caSCaroline Tice 1003b4874f1aSGreg Clayton // Don't push the same IO handler twice... 1004b4874f1aSGreg Clayton if (reader_sp.get() != top_reader_sp.get()) 1005b4874f1aSGreg Clayton { 100644d93782SGreg Clayton // Push our new input reader 1007d5a0a01bSCaroline Tice m_input_reader_stack.Push (reader_sp); 100844d93782SGreg Clayton 100944d93782SGreg Clayton // Interrupt the top input reader to it will exit its Run() function 101044d93782SGreg Clayton // and let this new input reader take over 101144d93782SGreg Clayton if (top_reader_sp) 101244d93782SGreg Clayton top_reader_sp->Deactivate(); 101330fdc8d8SChris Lattner } 1014b4874f1aSGreg Clayton } 101530fdc8d8SChris Lattner 101630fdc8d8SChris Lattner bool 101744d93782SGreg Clayton Debugger::PopIOHandler (const IOHandlerSP& pop_reader_sp) 101830fdc8d8SChris Lattner { 101930fdc8d8SChris Lattner bool result = false; 102030fdc8d8SChris Lattner 102144d93782SGreg Clayton Mutex::Locker locker (m_input_reader_stack.GetMutex()); 102244d93782SGreg Clayton 102330fdc8d8SChris Lattner // The reader on the stop of the stack is done, so let the next 10246a7f3338SBruce Mitchener // read on the stack refresh its prompt and if there is one... 1025d5a0a01bSCaroline Tice if (!m_input_reader_stack.IsEmpty()) 102630fdc8d8SChris Lattner { 102744d93782SGreg Clayton IOHandlerSP reader_sp(m_input_reader_stack.Top()); 102830fdc8d8SChris Lattner 102930fdc8d8SChris Lattner if (!pop_reader_sp || pop_reader_sp.get() == reader_sp.get()) 103030fdc8d8SChris Lattner { 103144d93782SGreg Clayton reader_sp->Deactivate(); 1032b4874f1aSGreg Clayton reader_sp->Cancel(); 1033d5a0a01bSCaroline Tice m_input_reader_stack.Pop (); 103430fdc8d8SChris Lattner 1035d5a0a01bSCaroline Tice reader_sp = m_input_reader_stack.Top(); 103630fdc8d8SChris Lattner if (reader_sp) 103744d93782SGreg Clayton reader_sp->Activate(); 103844d93782SGreg Clayton 103944d93782SGreg Clayton result = true; 104030fdc8d8SChris Lattner } 104130fdc8d8SChris Lattner } 104230fdc8d8SChris Lattner return result; 104330fdc8d8SChris Lattner } 104430fdc8d8SChris Lattner 104530fdc8d8SChris Lattner bool 104644d93782SGreg Clayton Debugger::HideTopIOHandler() 104730fdc8d8SChris Lattner { 104844d93782SGreg Clayton Mutex::Locker locker; 104930fdc8d8SChris Lattner 105044d93782SGreg Clayton if (locker.TryLock(m_input_reader_stack.GetMutex())) 105130fdc8d8SChris Lattner { 105244d93782SGreg Clayton IOHandlerSP reader_sp(m_input_reader_stack.Top()); 105344d93782SGreg Clayton if (reader_sp) 105444d93782SGreg Clayton reader_sp->Hide(); 105544d93782SGreg Clayton return true; 105630fdc8d8SChris Lattner } 105744d93782SGreg Clayton return false; 105830fdc8d8SChris Lattner } 105930fdc8d8SChris Lattner 106030fdc8d8SChris Lattner void 106144d93782SGreg Clayton Debugger::RefreshTopIOHandler() 106230fdc8d8SChris Lattner { 106344d93782SGreg Clayton IOHandlerSP reader_sp(m_input_reader_stack.Top()); 106444d93782SGreg Clayton if (reader_sp) 106544d93782SGreg Clayton reader_sp->Refresh(); 106630fdc8d8SChris Lattner } 106744d93782SGreg Clayton 10686611103cSGreg Clayton 10695b52f0c7SJim Ingham StreamSP 10705b52f0c7SJim Ingham Debugger::GetAsyncOutputStream () 10715b52f0c7SJim Ingham { 10725b52f0c7SJim Ingham return StreamSP (new StreamAsynchronousIO (GetCommandInterpreter(), 10735b52f0c7SJim Ingham CommandInterpreter::eBroadcastBitAsynchronousOutputData)); 10745b52f0c7SJim Ingham } 10755b52f0c7SJim Ingham 10765b52f0c7SJim Ingham StreamSP 10775b52f0c7SJim Ingham Debugger::GetAsyncErrorStream () 10785b52f0c7SJim Ingham { 10795b52f0c7SJim Ingham return StreamSP (new StreamAsynchronousIO (GetCommandInterpreter(), 10805b52f0c7SJim Ingham CommandInterpreter::eBroadcastBitAsynchronousErrorData)); 10815b52f0c7SJim Ingham } 10825b52f0c7SJim Ingham 1083c7bece56SGreg Clayton size_t 1084061858ceSEnrico Granata Debugger::GetNumDebuggers() 1085061858ceSEnrico Granata { 1086c15f55e2SGreg Clayton if (g_shared_debugger_refcount > 0) 1087c15f55e2SGreg Clayton { 1088061858ceSEnrico Granata Mutex::Locker locker (GetDebuggerListMutex ()); 1089061858ceSEnrico Granata return GetDebuggerList().size(); 1090061858ceSEnrico Granata } 1091c15f55e2SGreg Clayton return 0; 1092c15f55e2SGreg Clayton } 1093061858ceSEnrico Granata 1094061858ceSEnrico Granata lldb::DebuggerSP 1095c7bece56SGreg Clayton Debugger::GetDebuggerAtIndex (size_t index) 1096061858ceSEnrico Granata { 1097061858ceSEnrico Granata DebuggerSP debugger_sp; 1098061858ceSEnrico Granata 1099c15f55e2SGreg Clayton if (g_shared_debugger_refcount > 0) 1100c15f55e2SGreg Clayton { 1101061858ceSEnrico Granata Mutex::Locker locker (GetDebuggerListMutex ()); 1102061858ceSEnrico Granata DebuggerList &debugger_list = GetDebuggerList(); 1103061858ceSEnrico Granata 1104061858ceSEnrico Granata if (index < debugger_list.size()) 1105061858ceSEnrico Granata debugger_sp = debugger_list[index]; 1106c15f55e2SGreg Clayton } 1107061858ceSEnrico Granata 1108061858ceSEnrico Granata return debugger_sp; 1109061858ceSEnrico Granata } 1110061858ceSEnrico Granata 1111ebc1bb27SCaroline Tice DebuggerSP 1112ebc1bb27SCaroline Tice Debugger::FindDebuggerWithID (lldb::user_id_t id) 1113ebc1bb27SCaroline Tice { 11144d122c40SGreg Clayton DebuggerSP debugger_sp; 1115ebc1bb27SCaroline Tice 1116c15f55e2SGreg Clayton if (g_shared_debugger_refcount > 0) 1117c15f55e2SGreg Clayton { 1118ebc1bb27SCaroline Tice Mutex::Locker locker (GetDebuggerListMutex ()); 1119ebc1bb27SCaroline Tice DebuggerList &debugger_list = GetDebuggerList(); 1120ebc1bb27SCaroline Tice DebuggerList::iterator pos, end = debugger_list.end(); 1121ebc1bb27SCaroline Tice for (pos = debugger_list.begin(); pos != end; ++pos) 1122ebc1bb27SCaroline Tice { 1123ebc1bb27SCaroline Tice if ((*pos).get()->GetID() == id) 1124ebc1bb27SCaroline Tice { 1125ebc1bb27SCaroline Tice debugger_sp = *pos; 1126ebc1bb27SCaroline Tice break; 1127ebc1bb27SCaroline Tice } 1128ebc1bb27SCaroline Tice } 1129c15f55e2SGreg Clayton } 1130ebc1bb27SCaroline Tice return debugger_sp; 1131ebc1bb27SCaroline Tice } 11323df9a8dfSCaroline Tice 11332643b905SSaleem Abdulrasool #if 0 11341b654882SGreg Clayton static void 1135b57e4a1bSJason Molenda TestPromptFormats (StackFrame *frame) 11361b654882SGreg Clayton { 11371b654882SGreg Clayton if (frame == NULL) 11381b654882SGreg Clayton return; 11391b654882SGreg Clayton 11401b654882SGreg Clayton StreamString s; 11411b654882SGreg Clayton const char *prompt_format = 11421b654882SGreg Clayton "{addr = '${addr}'\n}" 1143aff1b357SJason Molenda "{addr-file-or-load = '${addr-file-or-load}'\n}" 1144aff1b357SJason Molenda "{current-pc-arrow = '${current-pc-arrow}'\n}" 11451b654882SGreg Clayton "{process.id = '${process.id}'\n}" 11461b654882SGreg Clayton "{process.name = '${process.name}'\n}" 11471b654882SGreg Clayton "{process.file.basename = '${process.file.basename}'\n}" 11481b654882SGreg Clayton "{process.file.fullpath = '${process.file.fullpath}'\n}" 11491b654882SGreg Clayton "{thread.id = '${thread.id}'\n}" 11501b654882SGreg Clayton "{thread.index = '${thread.index}'\n}" 11511b654882SGreg Clayton "{thread.name = '${thread.name}'\n}" 11521b654882SGreg Clayton "{thread.queue = '${thread.queue}'\n}" 11531b654882SGreg Clayton "{thread.stop-reason = '${thread.stop-reason}'\n}" 11541b654882SGreg Clayton "{target.arch = '${target.arch}'\n}" 11551b654882SGreg Clayton "{module.file.basename = '${module.file.basename}'\n}" 11561b654882SGreg Clayton "{module.file.fullpath = '${module.file.fullpath}'\n}" 11571b654882SGreg Clayton "{file.basename = '${file.basename}'\n}" 11581b654882SGreg Clayton "{file.fullpath = '${file.fullpath}'\n}" 11591b654882SGreg Clayton "{frame.index = '${frame.index}'\n}" 11601b654882SGreg Clayton "{frame.pc = '${frame.pc}'\n}" 11611b654882SGreg Clayton "{frame.sp = '${frame.sp}'\n}" 11621b654882SGreg Clayton "{frame.fp = '${frame.fp}'\n}" 11631b654882SGreg Clayton "{frame.flags = '${frame.flags}'\n}" 11641b654882SGreg Clayton "{frame.reg.rdi = '${frame.reg.rdi}'\n}" 11651b654882SGreg Clayton "{frame.reg.rip = '${frame.reg.rip}'\n}" 11661b654882SGreg Clayton "{frame.reg.rsp = '${frame.reg.rsp}'\n}" 11671b654882SGreg Clayton "{frame.reg.rbp = '${frame.reg.rbp}'\n}" 11681b654882SGreg Clayton "{frame.reg.rflags = '${frame.reg.rflags}'\n}" 11691b654882SGreg Clayton "{frame.reg.xmm0 = '${frame.reg.xmm0}'\n}" 11701b654882SGreg Clayton "{frame.reg.carp = '${frame.reg.carp}'\n}" 11711b654882SGreg Clayton "{function.id = '${function.id}'\n}" 1172aff1b357SJason Molenda "{function.changed = '${function.changed}'\n}" 1173aff1b357SJason Molenda "{function.initial-function = '${function.initial-function}'\n}" 11741b654882SGreg Clayton "{function.name = '${function.name}'\n}" 1175aff1b357SJason Molenda "{function.name-without-args = '${function.name-without-args}'\n}" 1176ccbc08e6SGreg Clayton "{function.name-with-args = '${function.name-with-args}'\n}" 11771b654882SGreg Clayton "{function.addr-offset = '${function.addr-offset}'\n}" 1178aff1b357SJason Molenda "{function.concrete-only-addr-offset-no-padding = '${function.concrete-only-addr-offset-no-padding}'\n}" 11791b654882SGreg Clayton "{function.line-offset = '${function.line-offset}'\n}" 11801b654882SGreg Clayton "{function.pc-offset = '${function.pc-offset}'\n}" 11811b654882SGreg Clayton "{line.file.basename = '${line.file.basename}'\n}" 11821b654882SGreg Clayton "{line.file.fullpath = '${line.file.fullpath}'\n}" 11831b654882SGreg Clayton "{line.number = '${line.number}'\n}" 11841b654882SGreg Clayton "{line.start-addr = '${line.start-addr}'\n}" 11851b654882SGreg Clayton "{line.end-addr = '${line.end-addr}'\n}" 11861b654882SGreg Clayton ; 11871b654882SGreg Clayton 11881b654882SGreg Clayton SymbolContext sc (frame->GetSymbolContext(eSymbolContextEverything)); 11891b654882SGreg Clayton ExecutionContext exe_ctx; 11900603aa9dSGreg Clayton frame->CalculateExecutionContext(exe_ctx); 1191c3ce7f27SMichael Sartain if (Debugger::FormatPrompt (prompt_format, &sc, &exe_ctx, &sc.line_entry.range.GetBaseAddress(), s)) 11921b654882SGreg Clayton { 11931b654882SGreg Clayton printf("%s\n", s.GetData()); 11941b654882SGreg Clayton } 11951b654882SGreg Clayton else 11961b654882SGreg Clayton { 11971b654882SGreg Clayton printf ("what we got: %s\n", s.GetData()); 11981b654882SGreg Clayton } 11991b654882SGreg Clayton } 12002643b905SSaleem Abdulrasool #endif 12011b654882SGreg Clayton 12029fc1944eSEnrico Granata static bool 12039fc1944eSEnrico Granata ScanFormatDescriptor (const char* var_name_begin, 12049fc1944eSEnrico Granata const char* var_name_end, 12059fc1944eSEnrico Granata const char** var_name_final, 12069fc1944eSEnrico Granata const char** percent_position, 12074d122c40SGreg Clayton Format* custom_format, 12089fc1944eSEnrico Granata ValueObject::ValueObjectRepresentationStyle* val_obj_display) 12099fc1944eSEnrico Granata { 12105160ce5cSGreg Clayton Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES)); 12119fc1944eSEnrico Granata *percent_position = ::strchr(var_name_begin,'%'); 12129fc1944eSEnrico Granata if (!*percent_position || *percent_position > var_name_end) 1213e992a089SEnrico Granata { 1214e992a089SEnrico Granata if (log) 1215d228483dSEnrico Granata log->Printf("[ScanFormatDescriptor] no format descriptor in string, skipping"); 12169fc1944eSEnrico Granata *var_name_final = var_name_end; 1217e992a089SEnrico Granata } 12189fc1944eSEnrico Granata else 12199fc1944eSEnrico Granata { 12209fc1944eSEnrico Granata *var_name_final = *percent_position; 122136aa5ae6SEnrico Granata std::string format_name(*var_name_final+1, var_name_end-*var_name_final-1); 1222e992a089SEnrico Granata if (log) 122368ae4117SEnrico Granata log->Printf("[ScanFormatDescriptor] parsing %s as a format descriptor", format_name.c_str()); 122436aa5ae6SEnrico Granata if ( !FormatManager::GetFormatFromCString(format_name.c_str(), 12259fc1944eSEnrico Granata true, 12269fc1944eSEnrico Granata *custom_format) ) 12279fc1944eSEnrico Granata { 1228e992a089SEnrico Granata if (log) 122968ae4117SEnrico Granata log->Printf("[ScanFormatDescriptor] %s is an unknown format", format_name.c_str()); 123036aa5ae6SEnrico Granata 123136aa5ae6SEnrico Granata switch (format_name.front()) 123236aa5ae6SEnrico Granata { 123336aa5ae6SEnrico Granata case '@': // if this is an @ sign, print ObjC description 123486cc9829SEnrico Granata *val_obj_display = ValueObject::eValueObjectRepresentationStyleLanguageSpecific; 123536aa5ae6SEnrico Granata break; 123636aa5ae6SEnrico Granata case 'V': // if this is a V, print the value using the default format 123786cc9829SEnrico Granata *val_obj_display = ValueObject::eValueObjectRepresentationStyleValue; 123836aa5ae6SEnrico Granata break; 123936aa5ae6SEnrico Granata case 'L': // if this is an L, print the location of the value 124086cc9829SEnrico Granata *val_obj_display = ValueObject::eValueObjectRepresentationStyleLocation; 124136aa5ae6SEnrico Granata break; 124236aa5ae6SEnrico Granata case 'S': // if this is an S, print the summary after all 124386cc9829SEnrico Granata *val_obj_display = ValueObject::eValueObjectRepresentationStyleSummary; 124436aa5ae6SEnrico Granata break; 124536aa5ae6SEnrico Granata case '#': // if this is a '#', print the number of children 124686cc9829SEnrico Granata *val_obj_display = ValueObject::eValueObjectRepresentationStyleChildrenCount; 124736aa5ae6SEnrico Granata break; 124836aa5ae6SEnrico Granata case 'T': // if this is a 'T', print the type 124986cc9829SEnrico Granata *val_obj_display = ValueObject::eValueObjectRepresentationStyleType; 125036aa5ae6SEnrico Granata break; 12512c75f11eSEnrico Granata case 'N': // if this is a 'N', print the name 12522c75f11eSEnrico Granata *val_obj_display = ValueObject::eValueObjectRepresentationStyleName; 12532c75f11eSEnrico Granata break; 12542c75f11eSEnrico Granata case '>': // if this is a '>', print the name 12552c75f11eSEnrico Granata *val_obj_display = ValueObject::eValueObjectRepresentationStyleExpressionPath; 12562c75f11eSEnrico Granata break; 125736aa5ae6SEnrico Granata default: 12585c42d8a8SJim Ingham if (log) 125936aa5ae6SEnrico Granata log->Printf("ScanFormatDescriptor] %s is an error, leaving the previous value alone", format_name.c_str()); 126036aa5ae6SEnrico Granata break; 126136aa5ae6SEnrico Granata } 12629fc1944eSEnrico Granata } 12639fc1944eSEnrico Granata // a good custom format tells us to print the value using it 12649fc1944eSEnrico Granata else 1265e992a089SEnrico Granata { 1266e992a089SEnrico Granata if (log) 126768ae4117SEnrico Granata log->Printf("[ScanFormatDescriptor] will display value for this VO"); 126886cc9829SEnrico Granata *val_obj_display = ValueObject::eValueObjectRepresentationStyleValue; 1269e992a089SEnrico Granata } 12709fc1944eSEnrico Granata } 1271e992a089SEnrico Granata if (log) 127268ae4117SEnrico Granata log->Printf("[ScanFormatDescriptor] final format description outcome: custom_format = %d, val_obj_display = %d", 1273e992a089SEnrico Granata *custom_format, 1274e992a089SEnrico Granata *val_obj_display); 12759fc1944eSEnrico Granata return true; 12769fc1944eSEnrico Granata } 12779fc1944eSEnrico Granata 12789fc1944eSEnrico Granata static bool 12799fc1944eSEnrico Granata ScanBracketedRange (const char* var_name_begin, 12809fc1944eSEnrico Granata const char* var_name_end, 12819fc1944eSEnrico Granata const char* var_name_final, 12829fc1944eSEnrico Granata const char** open_bracket_position, 12839fc1944eSEnrico Granata const char** separator_position, 12849fc1944eSEnrico Granata const char** close_bracket_position, 12859fc1944eSEnrico Granata const char** var_name_final_if_array_range, 12869fc1944eSEnrico Granata int64_t* index_lower, 12879fc1944eSEnrico Granata int64_t* index_higher) 12889fc1944eSEnrico Granata { 12895160ce5cSGreg Clayton Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES)); 12909fc1944eSEnrico Granata *open_bracket_position = ::strchr(var_name_begin,'['); 12919fc1944eSEnrico Granata if (*open_bracket_position && *open_bracket_position < var_name_final) 12929fc1944eSEnrico Granata { 12939fc1944eSEnrico Granata *separator_position = ::strchr(*open_bracket_position,'-'); // might be NULL if this is a simple var[N] bitfield 12949fc1944eSEnrico Granata *close_bracket_position = ::strchr(*open_bracket_position,']'); 12959fc1944eSEnrico Granata // as usual, we assume that [] will come before % 12969fc1944eSEnrico Granata //printf("trying to expand a []\n"); 12979fc1944eSEnrico Granata *var_name_final_if_array_range = *open_bracket_position; 12989fc1944eSEnrico Granata if (*close_bracket_position - *open_bracket_position == 1) 12999fc1944eSEnrico Granata { 1300e992a089SEnrico Granata if (log) 1301d228483dSEnrico Granata log->Printf("[ScanBracketedRange] '[]' detected.. going from 0 to end of data"); 13029fc1944eSEnrico Granata *index_lower = 0; 13039fc1944eSEnrico Granata } 13049fc1944eSEnrico Granata else if (*separator_position == NULL || *separator_position > var_name_end) 13059fc1944eSEnrico Granata { 13069fc1944eSEnrico Granata char *end = NULL; 13079fc1944eSEnrico Granata *index_lower = ::strtoul (*open_bracket_position+1, &end, 0); 13089fc1944eSEnrico Granata *index_higher = *index_lower; 1309e992a089SEnrico Granata if (log) 1310d01b2953SDaniel Malea log->Printf("[ScanBracketedRange] [%" PRId64 "] detected, high index is same", *index_lower); 13119fc1944eSEnrico Granata } 13129fc1944eSEnrico Granata else if (*close_bracket_position && *close_bracket_position < var_name_end) 13139fc1944eSEnrico Granata { 13149fc1944eSEnrico Granata char *end = NULL; 13159fc1944eSEnrico Granata *index_lower = ::strtoul (*open_bracket_position+1, &end, 0); 13169fc1944eSEnrico Granata *index_higher = ::strtoul (*separator_position+1, &end, 0); 1317e992a089SEnrico Granata if (log) 1318d01b2953SDaniel Malea log->Printf("[ScanBracketedRange] [%" PRId64 "-%" PRId64 "] detected", *index_lower, *index_higher); 13199fc1944eSEnrico Granata } 13209fc1944eSEnrico Granata else 1321e992a089SEnrico Granata { 1322e992a089SEnrico Granata if (log) 1323d228483dSEnrico Granata log->Printf("[ScanBracketedRange] expression is erroneous, cannot extract indices out of it"); 13249fc1944eSEnrico Granata return false; 1325e992a089SEnrico Granata } 13269fc1944eSEnrico Granata if (*index_lower > *index_higher && *index_higher > 0) 13279fc1944eSEnrico Granata { 1328e992a089SEnrico Granata if (log) 1329d228483dSEnrico Granata log->Printf("[ScanBracketedRange] swapping indices"); 1330c7bece56SGreg Clayton int64_t temp = *index_lower; 13319fc1944eSEnrico Granata *index_lower = *index_higher; 13329fc1944eSEnrico Granata *index_higher = temp; 13339fc1944eSEnrico Granata } 13349fc1944eSEnrico Granata } 1335e992a089SEnrico Granata else if (log) 1336d228483dSEnrico Granata log->Printf("[ScanBracketedRange] no bracketed range, skipping entirely"); 13379fc1944eSEnrico Granata return true; 13389fc1944eSEnrico Granata } 13399fc1944eSEnrico Granata 13400769b2b1SMichael Sartain template <typename T> 13410769b2b1SMichael Sartain static bool RunScriptFormatKeyword(Stream &s, ScriptInterpreter *script_interpreter, T t, const std::string& script_name) 13420769b2b1SMichael Sartain { 13430769b2b1SMichael Sartain if (script_interpreter) 13440769b2b1SMichael Sartain { 13450769b2b1SMichael Sartain Error script_error; 13460769b2b1SMichael Sartain std::string script_output; 13470769b2b1SMichael Sartain 13480769b2b1SMichael Sartain if (script_interpreter->RunScriptFormatKeyword(script_name.c_str(), t, script_output, script_error) && script_error.Success()) 13490769b2b1SMichael Sartain { 13500769b2b1SMichael Sartain s.Printf("%s", script_output.c_str()); 13510769b2b1SMichael Sartain return true; 13520769b2b1SMichael Sartain } 13530769b2b1SMichael Sartain else 13540769b2b1SMichael Sartain { 13550769b2b1SMichael Sartain s.Printf("<error: %s>",script_error.AsCString()); 13560769b2b1SMichael Sartain } 13570769b2b1SMichael Sartain } 13580769b2b1SMichael Sartain return false; 13590769b2b1SMichael Sartain } 13600769b2b1SMichael Sartain 13619fc1944eSEnrico Granata static ValueObjectSP 1362c482a192SEnrico Granata ExpandIndexedExpression (ValueObject* valobj, 1363c7bece56SGreg Clayton size_t index, 1364b57e4a1bSJason Molenda StackFrame* frame, 1365fc7a7f3bSEnrico Granata bool deref_pointer) 13669fc1944eSEnrico Granata { 13675160ce5cSGreg Clayton Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES)); 1368fc7a7f3bSEnrico Granata const char* ptr_deref_format = "[%d]"; 1369599171adSEnrico Granata std::string ptr_deref_buffer(10,0); 1370599171adSEnrico Granata ::sprintf(&ptr_deref_buffer[0], ptr_deref_format, index); 1371e992a089SEnrico Granata if (log) 1372599171adSEnrico Granata log->Printf("[ExpandIndexedExpression] name to deref: %s",ptr_deref_buffer.c_str()); 1373fc7a7f3bSEnrico Granata const char* first_unparsed; 1374fc7a7f3bSEnrico Granata ValueObject::GetValueForExpressionPathOptions options; 1375fc7a7f3bSEnrico Granata ValueObject::ExpressionPathEndResultType final_value_type; 1376fc7a7f3bSEnrico Granata ValueObject::ExpressionPathScanEndReason reason_to_stop; 137786cc9829SEnrico Granata ValueObject::ExpressionPathAftermath what_next = (deref_pointer ? ValueObject::eExpressionPathAftermathDereference : ValueObject::eExpressionPathAftermathNothing); 1378599171adSEnrico Granata ValueObjectSP item = valobj->GetValueForExpressionPath (ptr_deref_buffer.c_str(), 1379fc7a7f3bSEnrico Granata &first_unparsed, 1380fc7a7f3bSEnrico Granata &reason_to_stop, 1381fc7a7f3bSEnrico Granata &final_value_type, 1382fc7a7f3bSEnrico Granata options, 1383fc7a7f3bSEnrico Granata &what_next); 1384fc7a7f3bSEnrico Granata if (!item) 1385fc7a7f3bSEnrico Granata { 1386e992a089SEnrico Granata if (log) 1387d228483dSEnrico Granata log->Printf("[ExpandIndexedExpression] ERROR: unparsed portion = %s, why stopping = %d," 1388e992a089SEnrico Granata " final_value_type %d", 1389fc7a7f3bSEnrico Granata first_unparsed, reason_to_stop, final_value_type); 1390fc7a7f3bSEnrico Granata } 13919fc1944eSEnrico Granata else 13929fc1944eSEnrico Granata { 1393e992a089SEnrico Granata if (log) 1394d228483dSEnrico Granata log->Printf("[ExpandIndexedExpression] ALL RIGHT: unparsed portion = %s, why stopping = %d," 1395e992a089SEnrico Granata " final_value_type %d", 1396fc7a7f3bSEnrico Granata first_unparsed, reason_to_stop, final_value_type); 13979fc1944eSEnrico Granata } 13989fc1944eSEnrico Granata return item; 13999fc1944eSEnrico Granata } 14009fc1944eSEnrico Granata 14010769b2b1SMichael Sartain static inline bool 14020769b2b1SMichael Sartain IsToken(const char *var_name_begin, const char *var) 14030769b2b1SMichael Sartain { 14040769b2b1SMichael Sartain return (::strncmp (var_name_begin, var, strlen(var)) == 0); 14050769b2b1SMichael Sartain } 14060769b2b1SMichael Sartain 14070769b2b1SMichael Sartain static bool 14080769b2b1SMichael Sartain IsTokenWithFormat(const char *var_name_begin, const char *var, std::string &format, const char *default_format, 14090769b2b1SMichael Sartain const ExecutionContext *exe_ctx_ptr, const SymbolContext *sc_ptr) 14100769b2b1SMichael Sartain { 14110769b2b1SMichael Sartain int var_len = strlen(var); 14120769b2b1SMichael Sartain if (::strncmp (var_name_begin, var, var_len) == 0) 14130769b2b1SMichael Sartain { 14140769b2b1SMichael Sartain var_name_begin += var_len; 14150769b2b1SMichael Sartain if (*var_name_begin == '}') 14160769b2b1SMichael Sartain { 14170769b2b1SMichael Sartain format = default_format; 14180769b2b1SMichael Sartain return true; 14190769b2b1SMichael Sartain } 14200769b2b1SMichael Sartain else if (*var_name_begin == '%') 14210769b2b1SMichael Sartain { 14220769b2b1SMichael Sartain // Allow format specifiers: x|X|u with optional width specifiers. 14230769b2b1SMichael Sartain // ${thread.id%x} ; hex 14240769b2b1SMichael Sartain // ${thread.id%X} ; uppercase hex 14250769b2b1SMichael Sartain // ${thread.id%u} ; unsigned decimal 14260769b2b1SMichael Sartain // ${thread.id%8.8X} ; width.precision + specifier 14270769b2b1SMichael Sartain // ${thread.id%tid} ; unsigned on FreeBSD/Linux, otherwise default_format (0x%4.4x for thread.id) 14280769b2b1SMichael Sartain int dot_count = 0; 14290769b2b1SMichael Sartain const char *specifier = NULL; 14300769b2b1SMichael Sartain int width_precision_length = 0; 14310769b2b1SMichael Sartain const char *width_precision = ++var_name_begin; 14320769b2b1SMichael Sartain while (isdigit(*var_name_begin) || *var_name_begin == '.') 14330769b2b1SMichael Sartain { 14340769b2b1SMichael Sartain dot_count += (*var_name_begin == '.'); 14350769b2b1SMichael Sartain if (dot_count > 1) 14360769b2b1SMichael Sartain break; 14370769b2b1SMichael Sartain var_name_begin++; 14380769b2b1SMichael Sartain width_precision_length++; 14390769b2b1SMichael Sartain } 14400769b2b1SMichael Sartain 14410769b2b1SMichael Sartain if (IsToken (var_name_begin, "tid}")) 14420769b2b1SMichael Sartain { 14430769b2b1SMichael Sartain Target *target = Target::GetTargetFromContexts (exe_ctx_ptr, sc_ptr); 14440769b2b1SMichael Sartain if (target) 14450769b2b1SMichael Sartain { 14460769b2b1SMichael Sartain ArchSpec arch (target->GetArchitecture ()); 14470769b2b1SMichael Sartain llvm::Triple::OSType ostype = arch.IsValid() ? arch.GetTriple().getOS() : llvm::Triple::UnknownOS; 14480769b2b1SMichael Sartain if ((ostype == llvm::Triple::FreeBSD) || (ostype == llvm::Triple::Linux)) 14490769b2b1SMichael Sartain specifier = PRIu64; 14500769b2b1SMichael Sartain } 14510769b2b1SMichael Sartain if (!specifier) 14520769b2b1SMichael Sartain { 14530769b2b1SMichael Sartain format = default_format; 14540769b2b1SMichael Sartain return true; 14550769b2b1SMichael Sartain } 14560769b2b1SMichael Sartain } 14570769b2b1SMichael Sartain else if (IsToken (var_name_begin, "x}")) 14580769b2b1SMichael Sartain specifier = PRIx64; 14590769b2b1SMichael Sartain else if (IsToken (var_name_begin, "X}")) 14600769b2b1SMichael Sartain specifier = PRIX64; 14610769b2b1SMichael Sartain else if (IsToken (var_name_begin, "u}")) 14620769b2b1SMichael Sartain specifier = PRIu64; 14630769b2b1SMichael Sartain 14640769b2b1SMichael Sartain if (specifier) 14650769b2b1SMichael Sartain { 14660769b2b1SMichael Sartain format = "%"; 14670769b2b1SMichael Sartain if (width_precision_length) 14680769b2b1SMichael Sartain format += std::string(width_precision, width_precision_length); 14690769b2b1SMichael Sartain format += specifier; 14700769b2b1SMichael Sartain return true; 14710769b2b1SMichael Sartain } 14720769b2b1SMichael Sartain } 14730769b2b1SMichael Sartain } 14740769b2b1SMichael Sartain return false; 14750769b2b1SMichael Sartain } 14760769b2b1SMichael Sartain 1477705b1809SJason Molenda // Find information for the "thread.info.*" specifiers in a format string 1478705b1809SJason Molenda static bool 1479705b1809SJason Molenda FormatThreadExtendedInfoRecurse 1480705b1809SJason Molenda ( 1481705b1809SJason Molenda const char *var_name_begin, 1482705b1809SJason Molenda StructuredData::ObjectSP thread_info_dictionary, 1483705b1809SJason Molenda const SymbolContext *sc, 1484705b1809SJason Molenda const ExecutionContext *exe_ctx, 1485705b1809SJason Molenda Stream &s 1486705b1809SJason Molenda ) 1487705b1809SJason Molenda { 1488705b1809SJason Molenda bool var_success = false; 1489705b1809SJason Molenda std::string token_format; 1490705b1809SJason Molenda 1491705b1809SJason Molenda llvm::StringRef var_name(var_name_begin); 1492705b1809SJason Molenda size_t percent_idx = var_name.find('%'); 1493705b1809SJason Molenda size_t close_curly_idx = var_name.find('}'); 1494705b1809SJason Molenda llvm::StringRef path = var_name; 1495705b1809SJason Molenda llvm::StringRef formatter = var_name; 1496705b1809SJason Molenda 1497705b1809SJason Molenda // 'path' will be the dot separated list of objects to transverse up until we hit 1498705b1809SJason Molenda // a close curly brace, a percent sign, or an end of string. 1499705b1809SJason Molenda if (percent_idx != llvm::StringRef::npos || close_curly_idx != llvm::StringRef::npos) 1500705b1809SJason Molenda { 1501705b1809SJason Molenda if (percent_idx != llvm::StringRef::npos && close_curly_idx != llvm::StringRef::npos) 1502705b1809SJason Molenda { 1503705b1809SJason Molenda if (percent_idx < close_curly_idx) 1504705b1809SJason Molenda { 1505705b1809SJason Molenda path = var_name.slice(0, percent_idx); 1506705b1809SJason Molenda formatter = var_name.substr (percent_idx); 1507705b1809SJason Molenda } 1508705b1809SJason Molenda else 1509705b1809SJason Molenda { 1510705b1809SJason Molenda path = var_name.slice(0, close_curly_idx); 1511705b1809SJason Molenda formatter = var_name.substr (close_curly_idx); 1512705b1809SJason Molenda } 1513705b1809SJason Molenda } 1514705b1809SJason Molenda else if (percent_idx != llvm::StringRef::npos) 1515705b1809SJason Molenda { 1516705b1809SJason Molenda path = var_name.slice(0, percent_idx); 1517705b1809SJason Molenda formatter = var_name.substr (percent_idx); 1518705b1809SJason Molenda } 1519705b1809SJason Molenda else if (close_curly_idx != llvm::StringRef::npos) 1520705b1809SJason Molenda { 1521705b1809SJason Molenda path = var_name.slice(0, close_curly_idx); 1522705b1809SJason Molenda formatter = var_name.substr (close_curly_idx); 1523705b1809SJason Molenda } 1524705b1809SJason Molenda } 1525705b1809SJason Molenda 1526705b1809SJason Molenda StructuredData::ObjectSP value = thread_info_dictionary->GetObjectForDotSeparatedPath (path); 1527705b1809SJason Molenda 1528705b1809SJason Molenda if (value.get()) 1529705b1809SJason Molenda { 1530705b1809SJason Molenda if (value->GetType() == StructuredData::Type::eTypeInteger) 1531705b1809SJason Molenda { 1532705b1809SJason Molenda if (IsTokenWithFormat (formatter.str().c_str(), "", token_format, "0x%4.4" PRIx64, exe_ctx, sc)) 1533705b1809SJason Molenda { 1534705b1809SJason Molenda s.Printf(token_format.c_str(), value->GetAsInteger()->GetValue()); 1535705b1809SJason Molenda var_success = true; 1536705b1809SJason Molenda } 1537705b1809SJason Molenda } 1538705b1809SJason Molenda else if (value->GetType() == StructuredData::Type::eTypeFloat) 1539705b1809SJason Molenda { 1540705b1809SJason Molenda s.Printf ("%f", value->GetAsFloat()->GetValue()); 1541705b1809SJason Molenda var_success = true; 1542705b1809SJason Molenda } 1543705b1809SJason Molenda else if (value->GetType() == StructuredData::Type::eTypeString) 1544705b1809SJason Molenda { 1545705b1809SJason Molenda s.Printf("%s", value->GetAsString()->GetValue().c_str()); 1546705b1809SJason Molenda var_success = true; 1547705b1809SJason Molenda } 1548705b1809SJason Molenda else if (value->GetType() == StructuredData::Type::eTypeArray) 1549705b1809SJason Molenda { 1550705b1809SJason Molenda if (value->GetAsArray()->GetSize() > 0) 1551705b1809SJason Molenda { 1552705b1809SJason Molenda s.Printf ("%zu", value->GetAsArray()->GetSize()); 1553705b1809SJason Molenda var_success = true; 1554705b1809SJason Molenda } 1555705b1809SJason Molenda } 1556705b1809SJason Molenda else if (value->GetType() == StructuredData::Type::eTypeDictionary) 1557705b1809SJason Molenda { 1558705b1809SJason Molenda s.Printf ("%zu", value->GetAsDictionary()->GetKeys()->GetAsArray()->GetSize()); 1559705b1809SJason Molenda var_success = true; 1560705b1809SJason Molenda } 1561705b1809SJason Molenda } 1562705b1809SJason Molenda 1563705b1809SJason Molenda return var_success; 1564705b1809SJason Molenda } 1565705b1809SJason Molenda 1566705b1809SJason Molenda 1567c3ce7f27SMichael Sartain static bool 1568c3ce7f27SMichael Sartain FormatPromptRecurse 15691b654882SGreg Clayton ( 15701b654882SGreg Clayton const char *format, 15711b654882SGreg Clayton const SymbolContext *sc, 15721b654882SGreg Clayton const ExecutionContext *exe_ctx, 15731b654882SGreg Clayton const Address *addr, 15741b654882SGreg Clayton Stream &s, 15754becb37eSEnrico Granata const char **end, 1576aff1b357SJason Molenda ValueObject* valobj, 1577aff1b357SJason Molenda bool function_changed, 1578aff1b357SJason Molenda bool initial_function 15791b654882SGreg Clayton ) 15801b654882SGreg Clayton { 1581c482a192SEnrico Granata ValueObject* realvalobj = NULL; // makes it super-easy to parse pointers 15821b654882SGreg Clayton bool success = true; 15831b654882SGreg Clayton const char *p; 15845160ce5cSGreg Clayton Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES)); 1585c3ce7f27SMichael Sartain 15861b654882SGreg Clayton for (p = format; *p != '\0'; ++p) 15871b654882SGreg Clayton { 1588c482a192SEnrico Granata if (realvalobj) 15894becb37eSEnrico Granata { 1590c482a192SEnrico Granata valobj = realvalobj; 1591c482a192SEnrico Granata realvalobj = NULL; 15924becb37eSEnrico Granata } 15931b654882SGreg Clayton size_t non_special_chars = ::strcspn (p, "${}\\"); 15941b654882SGreg Clayton if (non_special_chars > 0) 15951b654882SGreg Clayton { 15961b654882SGreg Clayton if (success) 15971b654882SGreg Clayton s.Write (p, non_special_chars); 15981b654882SGreg Clayton p += non_special_chars; 15991b654882SGreg Clayton } 16001b654882SGreg Clayton 16011b654882SGreg Clayton if (*p == '\0') 16021b654882SGreg Clayton { 16031b654882SGreg Clayton break; 16041b654882SGreg Clayton } 16051b654882SGreg Clayton else if (*p == '{') 16061b654882SGreg Clayton { 16071b654882SGreg Clayton // Start a new scope that must have everything it needs if it is to 16081b654882SGreg Clayton // to make it into the final output stream "s". If you want to make 16091b654882SGreg Clayton // a format that only prints out the function or symbol name if there 16101b654882SGreg Clayton // is one in the symbol context you can use: 16111b654882SGreg Clayton // "{function =${function.name}}" 16121b654882SGreg Clayton // The first '{' starts a new scope that end with the matching '}' at 16131b654882SGreg Clayton // the end of the string. The contents "function =${function.name}" 16141b654882SGreg Clayton // will then be evaluated and only be output if there is a function 16151b654882SGreg Clayton // or symbol with a valid name. 16161b654882SGreg Clayton StreamString sub_strm; 16171b654882SGreg Clayton 16181b654882SGreg Clayton ++p; // Skip the '{' 16191b654882SGreg Clayton 1620aff1b357SJason Molenda if (FormatPromptRecurse (p, sc, exe_ctx, addr, sub_strm, &p, valobj, function_changed, initial_function)) 16211b654882SGreg Clayton { 16221b654882SGreg Clayton // The stream had all it needed 16231b654882SGreg Clayton s.Write(sub_strm.GetData(), sub_strm.GetSize()); 16241b654882SGreg Clayton } 16251b654882SGreg Clayton if (*p != '}') 16261b654882SGreg Clayton { 16271b654882SGreg Clayton success = false; 16281b654882SGreg Clayton break; 16291b654882SGreg Clayton } 16301b654882SGreg Clayton } 16311b654882SGreg Clayton else if (*p == '}') 16321b654882SGreg Clayton { 16331b654882SGreg Clayton // End of a enclosing scope 16341b654882SGreg Clayton break; 16351b654882SGreg Clayton } 16361b654882SGreg Clayton else if (*p == '$') 16371b654882SGreg Clayton { 16381b654882SGreg Clayton // We have a prompt variable to print 16391b654882SGreg Clayton ++p; 16401b654882SGreg Clayton if (*p == '{') 16411b654882SGreg Clayton { 16421b654882SGreg Clayton ++p; 16431b654882SGreg Clayton const char *var_name_begin = p; 16441b654882SGreg Clayton const char *var_name_end = ::strchr (p, '}'); 16451b654882SGreg Clayton 16461b654882SGreg Clayton if (var_name_end && var_name_begin < var_name_end) 16471b654882SGreg Clayton { 16481b654882SGreg Clayton // if we have already failed to parse, skip this variable 16491b654882SGreg Clayton if (success) 16501b654882SGreg Clayton { 16511b654882SGreg Clayton const char *cstr = NULL; 16520769b2b1SMichael Sartain std::string token_format; 16531b654882SGreg Clayton Address format_addr; 1654aff1b357SJason Molenda 1655aff1b357SJason Molenda // normally "addr" means print a raw address but 1656aff1b357SJason Molenda // "file-addr-or-load-addr" means print a module + file addr if there's no load addr 1657aff1b357SJason Molenda bool print_file_addr_or_load_addr = false; 1658aff1b357SJason Molenda bool addr_offset_concrete_func_only = false; 1659aff1b357SJason Molenda bool addr_offset_print_with_no_padding = false; 16601b654882SGreg Clayton bool calculate_format_addr_function_offset = false; 16611b654882SGreg Clayton // Set reg_kind and reg_num to invalid values 16621b654882SGreg Clayton RegisterKind reg_kind = kNumRegisterKinds; 16631b654882SGreg Clayton uint32_t reg_num = LLDB_INVALID_REGNUM; 16641b654882SGreg Clayton FileSpec format_file_spec; 1665e0d378b3SGreg Clayton const RegisterInfo *reg_info = NULL; 16661b654882SGreg Clayton RegisterContext *reg_ctx = NULL; 16679fc1944eSEnrico Granata bool do_deref_pointer = false; 166886cc9829SEnrico Granata ValueObject::ExpressionPathScanEndReason reason_to_stop = ValueObject::eExpressionPathScanEndReasonEndOfString; 166986cc9829SEnrico Granata ValueObject::ExpressionPathEndResultType final_value_type = ValueObject::eExpressionPathEndResultTypePlain; 16701b654882SGreg Clayton 16711b654882SGreg Clayton // Each variable must set success to true below... 16721b654882SGreg Clayton bool var_success = false; 16731b654882SGreg Clayton switch (var_name_begin[0]) 16741b654882SGreg Clayton { 16754becb37eSEnrico Granata case '*': 16766f3533fbSEnrico Granata case 'v': 16776f3533fbSEnrico Granata case 's': 16784becb37eSEnrico Granata { 1679c482a192SEnrico Granata if (!valobj) 168034132754SGreg Clayton break; 16816f3533fbSEnrico Granata 1682c3e320a7SEnrico Granata if (log) 1683d228483dSEnrico Granata log->Printf("[Debugger::FormatPrompt] initial string: %s",var_name_begin); 1684c3e320a7SEnrico Granata 16856f3533fbSEnrico Granata // check for *var and *svar 16866f3533fbSEnrico Granata if (*var_name_begin == '*') 16876f3533fbSEnrico Granata { 16889fc1944eSEnrico Granata do_deref_pointer = true; 16899fc1944eSEnrico Granata var_name_begin++; 1690c3e320a7SEnrico Granata if (log) 169168ae4117SEnrico Granata log->Printf("[Debugger::FormatPrompt] found a deref, new string is: %s",var_name_begin); 169268ae4117SEnrico Granata } 1693c3e320a7SEnrico Granata 16946f3533fbSEnrico Granata if (*var_name_begin == 's') 16954becb37eSEnrico Granata { 1696c5bc412cSEnrico Granata if (!valobj->IsSynthetic()) 169786cc9829SEnrico Granata valobj = valobj->GetSyntheticValue().get(); 169886cc9829SEnrico Granata if (!valobj) 169986cc9829SEnrico Granata break; 17006f3533fbSEnrico Granata var_name_begin++; 1701c3e320a7SEnrico Granata if (log) 170268ae4117SEnrico Granata log->Printf("[Debugger::FormatPrompt] found a synthetic, new string is: %s",var_name_begin); 170368ae4117SEnrico Granata } 1704c3e320a7SEnrico Granata 17056f3533fbSEnrico Granata // should be a 'v' by now 17066f3533fbSEnrico Granata if (*var_name_begin != 'v') 17076f3533fbSEnrico Granata break; 17086f3533fbSEnrico Granata 1709c3e320a7SEnrico Granata if (log) 171068ae4117SEnrico Granata log->Printf("[Debugger::FormatPrompt] string I am working with: %s",var_name_begin); 1711c3e320a7SEnrico Granata 1712fc7a7f3bSEnrico Granata ValueObject::ExpressionPathAftermath what_next = (do_deref_pointer ? 171386cc9829SEnrico Granata ValueObject::eExpressionPathAftermathDereference : ValueObject::eExpressionPathAftermathNothing); 1714fc7a7f3bSEnrico Granata ValueObject::GetValueForExpressionPathOptions options; 17158c9d3560SEnrico Granata options.DontCheckDotVsArrowSyntax().DoAllowBitfieldSyntax().DoAllowFragileIVar().DoAllowSyntheticChildren(); 171686cc9829SEnrico Granata ValueObject::ValueObjectRepresentationStyle val_obj_display = ValueObject::eValueObjectRepresentationStyleSummary; 171734132754SGreg Clayton ValueObject* target = NULL; 17184d122c40SGreg Clayton Format custom_format = eFormatInvalid; 171934132754SGreg Clayton const char* var_name_final = NULL; 17209fc1944eSEnrico Granata const char* var_name_final_if_array_range = NULL; 172134132754SGreg Clayton const char* close_bracket_position = NULL; 172234132754SGreg Clayton int64_t index_lower = -1; 172334132754SGreg Clayton int64_t index_higher = -1; 17249fc1944eSEnrico Granata bool is_array_range = false; 1725fc7a7f3bSEnrico Granata const char* first_unparsed; 172685933ed4SEnrico Granata bool was_plain_var = false; 172785933ed4SEnrico Granata bool was_var_format = false; 1728a777dc2aSEnrico Granata bool was_var_indexed = false; 1729fc7a7f3bSEnrico Granata 1730c482a192SEnrico Granata if (!valobj) break; 1731c482a192SEnrico Granata // simplest case ${var}, just print valobj's value 17320769b2b1SMichael Sartain if (IsToken (var_name_begin, "var}")) 17330a3958e0SEnrico Granata { 173485933ed4SEnrico Granata was_plain_var = true; 1735c482a192SEnrico Granata target = valobj; 173686cc9829SEnrico Granata val_obj_display = ValueObject::eValueObjectRepresentationStyleValue; 17370a3958e0SEnrico Granata } 17380769b2b1SMichael Sartain else if (IsToken (var_name_begin,"var%")) 17399fc1944eSEnrico Granata { 174085933ed4SEnrico Granata was_var_format = true; 17419fc1944eSEnrico Granata // this is a variable with some custom format applied to it 17429fc1944eSEnrico Granata const char* percent_position; 1743c482a192SEnrico Granata target = valobj; 174486cc9829SEnrico Granata val_obj_display = ValueObject::eValueObjectRepresentationStyleValue; 17459fc1944eSEnrico Granata ScanFormatDescriptor (var_name_begin, 17469fc1944eSEnrico Granata var_name_end, 17479fc1944eSEnrico Granata &var_name_final, 17489fc1944eSEnrico Granata &percent_position, 17499fc1944eSEnrico Granata &custom_format, 17509fc1944eSEnrico Granata &val_obj_display); 17510a3958e0SEnrico Granata } 17529fc1944eSEnrico Granata // this is ${var.something} or multiple .something nested 17530769b2b1SMichael Sartain else if (IsToken (var_name_begin, "var")) 17549fc1944eSEnrico Granata { 17550769b2b1SMichael Sartain if (IsToken (var_name_begin, "var[")) 1756a777dc2aSEnrico Granata was_var_indexed = true; 17579fc1944eSEnrico Granata const char* percent_position; 17589fc1944eSEnrico Granata ScanFormatDescriptor (var_name_begin, 17599fc1944eSEnrico Granata var_name_end, 17609fc1944eSEnrico Granata &var_name_final, 17619fc1944eSEnrico Granata &percent_position, 17629fc1944eSEnrico Granata &custom_format, 17639fc1944eSEnrico Granata &val_obj_display); 17649fc1944eSEnrico Granata 17659fc1944eSEnrico Granata const char* open_bracket_position; 17669fc1944eSEnrico Granata const char* separator_position; 17679fc1944eSEnrico Granata ScanBracketedRange (var_name_begin, 17689fc1944eSEnrico Granata var_name_end, 17699fc1944eSEnrico Granata var_name_final, 17709fc1944eSEnrico Granata &open_bracket_position, 17719fc1944eSEnrico Granata &separator_position, 17729fc1944eSEnrico Granata &close_bracket_position, 17739fc1944eSEnrico Granata &var_name_final_if_array_range, 17749fc1944eSEnrico Granata &index_lower, 17759fc1944eSEnrico Granata &index_higher); 17769fc1944eSEnrico Granata 17779fc1944eSEnrico Granata Error error; 17789fc1944eSEnrico Granata 1779599171adSEnrico Granata std::string expr_path(var_name_final-var_name_begin-1,0); 1780599171adSEnrico Granata memcpy(&expr_path[0], var_name_begin+3,var_name_final-var_name_begin-3); 1781fc7a7f3bSEnrico Granata 1782e992a089SEnrico Granata if (log) 1783599171adSEnrico Granata log->Printf("[Debugger::FormatPrompt] symbol to expand: %s",expr_path.c_str()); 1784fc7a7f3bSEnrico Granata 1785599171adSEnrico Granata target = valobj->GetValueForExpressionPath(expr_path.c_str(), 1786fc7a7f3bSEnrico Granata &first_unparsed, 1787fc7a7f3bSEnrico Granata &reason_to_stop, 1788fc7a7f3bSEnrico Granata &final_value_type, 1789fc7a7f3bSEnrico Granata options, 1790fc7a7f3bSEnrico Granata &what_next).get(); 1791fc7a7f3bSEnrico Granata 1792fc7a7f3bSEnrico Granata if (!target) 17939fc1944eSEnrico Granata { 1794e992a089SEnrico Granata if (log) 1795d228483dSEnrico Granata log->Printf("[Debugger::FormatPrompt] ERROR: unparsed portion = %s, why stopping = %d," 1796e992a089SEnrico Granata " final_value_type %d", 1797fc7a7f3bSEnrico Granata first_unparsed, reason_to_stop, final_value_type); 1798fc7a7f3bSEnrico Granata break; 17990a3958e0SEnrico Granata } 1800a7187d00SEnrico Granata else 1801fc7a7f3bSEnrico Granata { 1802e992a089SEnrico Granata if (log) 1803d228483dSEnrico Granata log->Printf("[Debugger::FormatPrompt] ALL RIGHT: unparsed portion = %s, why stopping = %d," 1804e992a089SEnrico Granata " final_value_type %d", 1805fc7a7f3bSEnrico Granata first_unparsed, reason_to_stop, final_value_type); 1806a7187d00SEnrico Granata } 18070a3958e0SEnrico Granata } 18080a3958e0SEnrico Granata else 18090a3958e0SEnrico Granata break; 18109fc1944eSEnrico Granata 181186cc9829SEnrico Granata is_array_range = (final_value_type == ValueObject::eExpressionPathEndResultTypeBoundedRange || 181286cc9829SEnrico Granata final_value_type == ValueObject::eExpressionPathEndResultTypeUnboundedRange); 1813fc7a7f3bSEnrico Granata 181486cc9829SEnrico Granata do_deref_pointer = (what_next == ValueObject::eExpressionPathAftermathDereference); 1815fc7a7f3bSEnrico Granata 1816a7187d00SEnrico Granata if (do_deref_pointer && !is_array_range) 18170a3958e0SEnrico Granata { 18189fc1944eSEnrico Granata // I have not deref-ed yet, let's do it 18199fc1944eSEnrico Granata // this happens when we are not going through GetValueForVariableExpressionPath 18209fc1944eSEnrico Granata // to get to the target ValueObject 18219fc1944eSEnrico Granata Error error; 18229fc1944eSEnrico Granata target = target->Dereference(error).get(); 1823dc940730SEnrico Granata if (error.Fail()) 1824dc940730SEnrico Granata { 1825dc940730SEnrico Granata if (log) 1826d228483dSEnrico Granata log->Printf("[Debugger::FormatPrompt] ERROR: %s\n", error.AsCString("unknown")); \ 1827dc940730SEnrico Granata break; 1828dc940730SEnrico Granata } 18299fc1944eSEnrico Granata do_deref_pointer = false; 18300a3958e0SEnrico Granata } 18310a3958e0SEnrico Granata 1832f164d940SJim Ingham if (!target) 1833f164d940SJim Ingham { 1834f164d940SJim Ingham if (log) 1835f164d940SJim Ingham log->Printf("[Debugger::FormatPrompt] could not calculate target for prompt expression"); 1836f164d940SJim Ingham break; 1837f164d940SJim Ingham } 1838f164d940SJim Ingham 1839a777dc2aSEnrico Granata // we do not want to use the summary for a bitfield of type T:n 1840a777dc2aSEnrico Granata // if we were originally dealing with just a T - that would get 1841a777dc2aSEnrico Granata // us into an endless recursion 1842a777dc2aSEnrico Granata if (target->IsBitfield() && was_var_indexed) 1843a777dc2aSEnrico Granata { 1844a777dc2aSEnrico Granata // TODO: check for a (T:n)-specific summary - we should still obey that 1845a777dc2aSEnrico Granata StreamString bitfield_name; 1846a777dc2aSEnrico Granata bitfield_name.Printf("%s:%d", target->GetTypeName().AsCString(), target->GetBitfieldBitSize()); 1847a777dc2aSEnrico Granata lldb::TypeNameSpecifierImplSP type_sp(new TypeNameSpecifierImpl(bitfield_name.GetData(),false)); 1848a777dc2aSEnrico Granata if (!DataVisualization::GetSummaryForType(type_sp)) 1849a777dc2aSEnrico Granata val_obj_display = ValueObject::eValueObjectRepresentationStyleValue; 1850a777dc2aSEnrico Granata } 1851a777dc2aSEnrico Granata 185285933ed4SEnrico Granata // TODO use flags for these 185357ee3067SGreg Clayton const uint32_t type_info_flags = target->GetClangType().GetTypeInfo(NULL); 185457ee3067SGreg Clayton bool is_array = (type_info_flags & ClangASTType::eTypeIsArray) != 0; 185557ee3067SGreg Clayton bool is_pointer = (type_info_flags & ClangASTType::eTypeIsPointer) != 0; 185657ee3067SGreg Clayton bool is_aggregate = target->GetClangType().IsAggregateType(); 1857f4efecd9SEnrico Granata 185886cc9829SEnrico Granata if ((is_array || is_pointer) && (!is_array_range) && val_obj_display == ValueObject::eValueObjectRepresentationStyleValue) // this should be wrong, but there are some exceptions 1859f4efecd9SEnrico Granata { 186085933ed4SEnrico Granata StreamString str_temp; 1861e992a089SEnrico Granata if (log) 1862d228483dSEnrico Granata log->Printf("[Debugger::FormatPrompt] I am into array || pointer && !range"); 1863d64d0bc0SEnrico Granata 18645088c486SGreg Clayton if (target->HasSpecialPrintableRepresentation(val_obj_display, custom_format)) 1865d64d0bc0SEnrico Granata { 1866f4efecd9SEnrico Granata // try to use the special cases 186785933ed4SEnrico Granata var_success = target->DumpPrintableRepresentation(str_temp, 186885933ed4SEnrico Granata val_obj_display, 186985933ed4SEnrico Granata custom_format); 1870e992a089SEnrico Granata if (log) 1871d228483dSEnrico Granata log->Printf("[Debugger::FormatPrompt] special cases did%s match", var_success ? "" : "n't"); 1872d64d0bc0SEnrico Granata 1873d64d0bc0SEnrico Granata // should not happen 18745088c486SGreg Clayton if (var_success) 187585933ed4SEnrico Granata s << str_temp.GetData(); 1876d64d0bc0SEnrico Granata var_success = true; 1877d64d0bc0SEnrico Granata break; 1878d64d0bc0SEnrico Granata } 1879d64d0bc0SEnrico Granata else 1880d64d0bc0SEnrico Granata { 188188da35f8SEnrico Granata if (was_plain_var) // if ${var} 1882d64d0bc0SEnrico Granata { 1883d64d0bc0SEnrico Granata s << target->GetTypeName() << " @ " << target->GetLocationAsCString(); 1884d64d0bc0SEnrico Granata } 188588da35f8SEnrico Granata else if (is_pointer) // if pointer, value is the address stored 188688da35f8SEnrico Granata { 188723f59509SGreg Clayton target->DumpPrintableRepresentation (s, 188888da35f8SEnrico Granata val_obj_display, 188986cc9829SEnrico Granata custom_format, 189086cc9829SEnrico Granata ValueObject::ePrintableRepresentationSpecialCasesDisable); 189188da35f8SEnrico Granata } 1892d64d0bc0SEnrico Granata var_success = true; 1893d64d0bc0SEnrico Granata break; 1894d64d0bc0SEnrico Granata } 1895d64d0bc0SEnrico Granata } 1896d64d0bc0SEnrico Granata 1897d64d0bc0SEnrico Granata // if directly trying to print ${var}, and this is an aggregate, display a nice 1898d64d0bc0SEnrico Granata // type @ location message 1899d64d0bc0SEnrico Granata if (is_aggregate && was_plain_var) 1900d64d0bc0SEnrico Granata { 1901d64d0bc0SEnrico Granata s << target->GetTypeName() << " @ " << target->GetLocationAsCString(); 1902d64d0bc0SEnrico Granata var_success = true; 190385933ed4SEnrico Granata break; 190485933ed4SEnrico Granata } 190585933ed4SEnrico Granata 1906d64d0bc0SEnrico Granata // if directly trying to print ${var%V}, and this is an aggregate, do not let the user do it 190786cc9829SEnrico Granata if (is_aggregate && ((was_var_format && val_obj_display == ValueObject::eValueObjectRepresentationStyleValue))) 190885933ed4SEnrico Granata { 190985933ed4SEnrico Granata s << "<invalid use of aggregate type>"; 191085933ed4SEnrico Granata var_success = true; 1911f4efecd9SEnrico Granata break; 1912f4efecd9SEnrico Granata } 1913f4efecd9SEnrico Granata 19149fc1944eSEnrico Granata if (!is_array_range) 1915e992a089SEnrico Granata { 1916e992a089SEnrico Granata if (log) 1917d228483dSEnrico Granata log->Printf("[Debugger::FormatPrompt] dumping ordinary printable output"); 19189fc1944eSEnrico Granata var_success = target->DumpPrintableRepresentation(s,val_obj_display, custom_format); 1919e992a089SEnrico Granata } 19209fc1944eSEnrico Granata else 19219fc1944eSEnrico Granata { 1922e992a089SEnrico Granata if (log) 1923d228483dSEnrico Granata log->Printf("[Debugger::FormatPrompt] checking if I can handle as array"); 19249fc1944eSEnrico Granata if (!is_array && !is_pointer) 19259fc1944eSEnrico Granata break; 1926e992a089SEnrico Granata if (log) 1927d228483dSEnrico Granata log->Printf("[Debugger::FormatPrompt] handle as array"); 1928fc7a7f3bSEnrico Granata const char* special_directions = NULL; 1929fc7a7f3bSEnrico Granata StreamString special_directions_writer; 19300a3958e0SEnrico Granata if (close_bracket_position && (var_name_end-close_bracket_position > 1)) 19310a3958e0SEnrico Granata { 1932fc7a7f3bSEnrico Granata ConstString additional_data; 1933fc7a7f3bSEnrico Granata additional_data.SetCStringWithLength(close_bracket_position+1, var_name_end-close_bracket_position-1); 1934fc7a7f3bSEnrico Granata special_directions_writer.Printf("${%svar%s}", 1935fc7a7f3bSEnrico Granata do_deref_pointer ? "*" : "", 1936fc7a7f3bSEnrico Granata additional_data.GetCString()); 1937fc7a7f3bSEnrico Granata special_directions = special_directions_writer.GetData(); 19380a3958e0SEnrico Granata } 19390a3958e0SEnrico Granata 19400a3958e0SEnrico Granata // let us display items index_lower thru index_higher of this array 19410a3958e0SEnrico Granata s.PutChar('['); 19420a3958e0SEnrico Granata var_success = true; 19430a3958e0SEnrico Granata 19449fc1944eSEnrico Granata if (index_higher < 0) 1945c482a192SEnrico Granata index_higher = valobj->GetNumChildren() - 1; 19460a3958e0SEnrico Granata 1947cc4d0146SGreg Clayton uint32_t max_num_children = target->GetTargetSP()->GetMaximumNumberOfChildrenToDisplay(); 194822c55d18SEnrico Granata 19490a3958e0SEnrico Granata for (;index_lower<=index_higher;index_lower++) 19500a3958e0SEnrico Granata { 1951fc7a7f3bSEnrico Granata ValueObject* item = ExpandIndexedExpression (target, 19529fc1944eSEnrico Granata index_lower, 1953c14ee32dSGreg Clayton exe_ctx->GetFramePtr(), 1954fc7a7f3bSEnrico Granata false).get(); 19550a3958e0SEnrico Granata 1956fc7a7f3bSEnrico Granata if (!item) 1957fc7a7f3bSEnrico Granata { 1958e992a089SEnrico Granata if (log) 1959d01b2953SDaniel Malea log->Printf("[Debugger::FormatPrompt] ERROR in getting child item at index %" PRId64, index_lower); 1960fc7a7f3bSEnrico Granata } 1961fc7a7f3bSEnrico Granata else 1962fc7a7f3bSEnrico Granata { 1963e992a089SEnrico Granata if (log) 1964d228483dSEnrico Granata log->Printf("[Debugger::FormatPrompt] special_directions for child item: %s",special_directions); 1965fc7a7f3bSEnrico Granata } 1966fc7a7f3bSEnrico Granata 19670a3958e0SEnrico Granata if (!special_directions) 19689fc1944eSEnrico Granata var_success &= item->DumpPrintableRepresentation(s,val_obj_display, custom_format); 19690a3958e0SEnrico Granata else 1970aff1b357SJason Molenda var_success &= FormatPromptRecurse(special_directions, sc, exe_ctx, addr, s, NULL, item, function_changed, initial_function); 19710a3958e0SEnrico Granata 197222c55d18SEnrico Granata if (--max_num_children == 0) 197322c55d18SEnrico Granata { 197422c55d18SEnrico Granata s.PutCString(", ..."); 197522c55d18SEnrico Granata break; 197622c55d18SEnrico Granata } 197722c55d18SEnrico Granata 19780a3958e0SEnrico Granata if (index_lower < index_higher) 19790a3958e0SEnrico Granata s.PutChar(','); 19800a3958e0SEnrico Granata } 19810a3958e0SEnrico Granata s.PutChar(']'); 19824becb37eSEnrico Granata } 19834becb37eSEnrico Granata } 198434132754SGreg Clayton break; 19851b654882SGreg Clayton case 'a': 1986aff1b357SJason Molenda if (IsToken (var_name_begin, "addr-file-or-load}")) 1987aff1b357SJason Molenda { 1988aff1b357SJason Molenda print_file_addr_or_load_addr = true; 1989aff1b357SJason Molenda } 1990aff1b357SJason Molenda if (IsToken (var_name_begin, "addr}") 1991aff1b357SJason Molenda || IsToken (var_name_begin, "addr-file-or-load}")) 19921b654882SGreg Clayton { 19931b654882SGreg Clayton if (addr && addr->IsValid()) 19941b654882SGreg Clayton { 19951b654882SGreg Clayton var_success = true; 19961b654882SGreg Clayton format_addr = *addr; 19971b654882SGreg Clayton } 19981b654882SGreg Clayton } 19991b654882SGreg Clayton break; 20001b654882SGreg Clayton 20011b654882SGreg Clayton case 'p': 20020769b2b1SMichael Sartain if (IsToken (var_name_begin, "process.")) 20031b654882SGreg Clayton { 2004c14ee32dSGreg Clayton if (exe_ctx) 2005c14ee32dSGreg Clayton { 2006c14ee32dSGreg Clayton Process *process = exe_ctx->GetProcessPtr(); 2007c14ee32dSGreg Clayton if (process) 20081b654882SGreg Clayton { 20091b654882SGreg Clayton var_name_begin += ::strlen ("process."); 20100769b2b1SMichael Sartain if (IsTokenWithFormat (var_name_begin, "id", token_format, "%" PRIu64, exe_ctx, sc)) 20111b654882SGreg Clayton { 20120769b2b1SMichael Sartain s.Printf(token_format.c_str(), process->GetID()); 20131b654882SGreg Clayton var_success = true; 20141b654882SGreg Clayton } 20150769b2b1SMichael Sartain else if ((IsToken (var_name_begin, "name}")) || 20160769b2b1SMichael Sartain (IsToken (var_name_begin, "file.basename}")) || 20170769b2b1SMichael Sartain (IsToken (var_name_begin, "file.fullpath}"))) 20181b654882SGreg Clayton { 2019c14ee32dSGreg Clayton Module *exe_module = process->GetTarget().GetExecutableModulePointer(); 2020aa149cbdSGreg Clayton if (exe_module) 20211b654882SGreg Clayton { 20221b654882SGreg Clayton if (var_name_begin[0] == 'n' || var_name_begin[5] == 'f') 20231b654882SGreg Clayton { 2024aa149cbdSGreg Clayton format_file_spec.GetFilename() = exe_module->GetFileSpec().GetFilename(); 20259076c0ffSSean Callanan var_success = (bool)format_file_spec; 20261b654882SGreg Clayton } 20271b654882SGreg Clayton else 20281b654882SGreg Clayton { 2029aa149cbdSGreg Clayton format_file_spec = exe_module->GetFileSpec(); 20309076c0ffSSean Callanan var_success = (bool)format_file_spec; 20311b654882SGreg Clayton } 20321b654882SGreg Clayton } 20331b654882SGreg Clayton } 20340769b2b1SMichael Sartain else if (IsToken (var_name_begin, "script:")) 2035aad8e480SEnrico Granata { 2036aad8e480SEnrico Granata var_name_begin += ::strlen("script:"); 2037aad8e480SEnrico Granata std::string script_name(var_name_begin,var_name_end); 2038aad8e480SEnrico Granata ScriptInterpreter* script_interpreter = process->GetTarget().GetDebugger().GetCommandInterpreter().GetScriptInterpreter(); 20390769b2b1SMichael Sartain if (RunScriptFormatKeyword (s, script_interpreter, process, script_name)) 2040aad8e480SEnrico Granata var_success = true; 2041aad8e480SEnrico Granata } 20421b654882SGreg Clayton } 20431b654882SGreg Clayton } 2044c14ee32dSGreg Clayton } 20451b654882SGreg Clayton break; 20461b654882SGreg Clayton 20471b654882SGreg Clayton case 't': 20480769b2b1SMichael Sartain if (IsToken (var_name_begin, "thread.")) 20491b654882SGreg Clayton { 2050c14ee32dSGreg Clayton if (exe_ctx) 2051c14ee32dSGreg Clayton { 2052c14ee32dSGreg Clayton Thread *thread = exe_ctx->GetThreadPtr(); 2053c14ee32dSGreg Clayton if (thread) 20541b654882SGreg Clayton { 20551b654882SGreg Clayton var_name_begin += ::strlen ("thread."); 20560769b2b1SMichael Sartain if (IsTokenWithFormat (var_name_begin, "id", token_format, "0x%4.4" PRIx64, exe_ctx, sc)) 20571b654882SGreg Clayton { 20580769b2b1SMichael Sartain s.Printf(token_format.c_str(), thread->GetID()); 20591b654882SGreg Clayton var_success = true; 20601b654882SGreg Clayton } 20610769b2b1SMichael Sartain else if (IsTokenWithFormat (var_name_begin, "protocol_id", token_format, "0x%4.4" PRIx64, exe_ctx, sc)) 2062160c9d81SGreg Clayton { 20630769b2b1SMichael Sartain s.Printf(token_format.c_str(), thread->GetProtocolID()); 2064160c9d81SGreg Clayton var_success = true; 2065160c9d81SGreg Clayton } 20660769b2b1SMichael Sartain else if (IsTokenWithFormat (var_name_begin, "index", token_format, "%" PRIu64, exe_ctx, sc)) 20671b654882SGreg Clayton { 20680769b2b1SMichael Sartain s.Printf(token_format.c_str(), (uint64_t)thread->GetIndexID()); 20691b654882SGreg Clayton var_success = true; 20701b654882SGreg Clayton } 20710769b2b1SMichael Sartain else if (IsToken (var_name_begin, "name}")) 20721b654882SGreg Clayton { 2073c14ee32dSGreg Clayton cstr = thread->GetName(); 20741b654882SGreg Clayton var_success = cstr && cstr[0]; 20751b654882SGreg Clayton if (var_success) 20761b654882SGreg Clayton s.PutCString(cstr); 20771b654882SGreg Clayton } 20780769b2b1SMichael Sartain else if (IsToken (var_name_begin, "queue}")) 20791b654882SGreg Clayton { 2080c14ee32dSGreg Clayton cstr = thread->GetQueueName(); 20811b654882SGreg Clayton var_success = cstr && cstr[0]; 20821b654882SGreg Clayton if (var_success) 20831b654882SGreg Clayton s.PutCString(cstr); 20841b654882SGreg Clayton } 20850769b2b1SMichael Sartain else if (IsToken (var_name_begin, "stop-reason}")) 20861b654882SGreg Clayton { 2087c14ee32dSGreg Clayton StopInfoSP stop_info_sp = thread->GetStopInfo (); 20885d88a068SJim Ingham if (stop_info_sp && stop_info_sp->IsValid()) 20891b654882SGreg Clayton { 2090b15bfc75SJim Ingham cstr = stop_info_sp->GetDescription(); 20911b654882SGreg Clayton if (cstr && cstr[0]) 20921b654882SGreg Clayton { 20931b654882SGreg Clayton s.PutCString(cstr); 20941b654882SGreg Clayton var_success = true; 20951b654882SGreg Clayton } 20961b654882SGreg Clayton } 20971b654882SGreg Clayton } 20980769b2b1SMichael Sartain else if (IsToken (var_name_begin, "return-value}")) 209973ca05a2SJim Ingham { 210073ca05a2SJim Ingham StopInfoSP stop_info_sp = thread->GetStopInfo (); 21015d88a068SJim Ingham if (stop_info_sp && stop_info_sp->IsValid()) 210273ca05a2SJim Ingham { 210373ca05a2SJim Ingham ValueObjectSP return_valobj_sp = StopInfo::GetReturnValueObject (stop_info_sp); 210473ca05a2SJim Ingham if (return_valobj_sp) 210573ca05a2SJim Ingham { 21064d93b8cdSEnrico Granata return_valobj_sp->Dump(s); 210773ca05a2SJim Ingham var_success = true; 210873ca05a2SJim Ingham } 210973ca05a2SJim Ingham } 211073ca05a2SJim Ingham } 211130fadafeSJim Ingham else if (IsToken (var_name_begin, "completed-expression}")) 211230fadafeSJim Ingham { 211330fadafeSJim Ingham StopInfoSP stop_info_sp = thread->GetStopInfo (); 211430fadafeSJim Ingham if (stop_info_sp && stop_info_sp->IsValid()) 211530fadafeSJim Ingham { 211630fadafeSJim Ingham ClangExpressionVariableSP expression_var_sp = StopInfo::GetExpressionVariable (stop_info_sp); 211730fadafeSJim Ingham if (expression_var_sp && expression_var_sp->GetValueObject()) 211830fadafeSJim Ingham { 211930fadafeSJim Ingham expression_var_sp->GetValueObject()->Dump(s); 212030fadafeSJim Ingham var_success = true; 212130fadafeSJim Ingham } 212230fadafeSJim Ingham } 212330fadafeSJim Ingham } 21240769b2b1SMichael Sartain else if (IsToken (var_name_begin, "script:")) 2125aad8e480SEnrico Granata { 2126aad8e480SEnrico Granata var_name_begin += ::strlen("script:"); 2127aad8e480SEnrico Granata std::string script_name(var_name_begin,var_name_end); 2128aad8e480SEnrico Granata ScriptInterpreter* script_interpreter = thread->GetProcess()->GetTarget().GetDebugger().GetCommandInterpreter().GetScriptInterpreter(); 21290769b2b1SMichael Sartain if (RunScriptFormatKeyword (s, script_interpreter, thread, script_name)) 2130aad8e480SEnrico Granata var_success = true; 2131aad8e480SEnrico Granata } 2132705b1809SJason Molenda else if (IsToken (var_name_begin, "info.")) 2133705b1809SJason Molenda { 2134705b1809SJason Molenda var_name_begin += ::strlen("info."); 2135705b1809SJason Molenda StructuredData::ObjectSP object_sp = thread->GetExtendedInfo(); 2136705b1809SJason Molenda if (object_sp && object_sp->GetType() == StructuredData::Type::eTypeDictionary) 2137705b1809SJason Molenda { 2138705b1809SJason Molenda var_success = FormatThreadExtendedInfoRecurse (var_name_begin, object_sp, sc, exe_ctx, s); 2139705b1809SJason Molenda } 2140705b1809SJason Molenda } 2141aad8e480SEnrico Granata } 2142aad8e480SEnrico Granata } 214373ca05a2SJim Ingham } 21440769b2b1SMichael Sartain else if (IsToken (var_name_begin, "target.")) 21451b654882SGreg Clayton { 214667cc0636SGreg Clayton // TODO: hookup properties 214767cc0636SGreg Clayton // if (!target_properties_sp) 214867cc0636SGreg Clayton // { 214967cc0636SGreg Clayton // Target *target = Target::GetTargetFromContexts (exe_ctx, sc); 215067cc0636SGreg Clayton // if (target) 215167cc0636SGreg Clayton // target_properties_sp = target->GetProperties(); 215267cc0636SGreg Clayton // } 215367cc0636SGreg Clayton // 215467cc0636SGreg Clayton // if (target_properties_sp) 215567cc0636SGreg Clayton // { 215667cc0636SGreg Clayton // var_name_begin += ::strlen ("target."); 215767cc0636SGreg Clayton // const char *end_property = strchr(var_name_begin, '}'); 215867cc0636SGreg Clayton // if (end_property) 215967cc0636SGreg Clayton // { 216067cc0636SGreg Clayton // ConstString property_name(var_name_begin, end_property - var_name_begin); 216167cc0636SGreg Clayton // std::string property_value (target_properties_sp->GetPropertyValue(property_name)); 216267cc0636SGreg Clayton // if (!property_value.empty()) 216367cc0636SGreg Clayton // { 216467cc0636SGreg Clayton // s.PutCString (property_value.c_str()); 216567cc0636SGreg Clayton // var_success = true; 216667cc0636SGreg Clayton // } 216767cc0636SGreg Clayton // } 216867cc0636SGreg Clayton // } 21690603aa9dSGreg Clayton Target *target = Target::GetTargetFromContexts (exe_ctx, sc); 21700603aa9dSGreg Clayton if (target) 21711b654882SGreg Clayton { 21721b654882SGreg Clayton var_name_begin += ::strlen ("target."); 21730769b2b1SMichael Sartain if (IsToken (var_name_begin, "arch}")) 21741b654882SGreg Clayton { 21751b654882SGreg Clayton ArchSpec arch (target->GetArchitecture ()); 21761b654882SGreg Clayton if (arch.IsValid()) 21771b654882SGreg Clayton { 217864195a2cSGreg Clayton s.PutCString (arch.GetArchitectureName()); 21791b654882SGreg Clayton var_success = true; 21801b654882SGreg Clayton } 21811b654882SGreg Clayton } 21820769b2b1SMichael Sartain else if (IsToken (var_name_begin, "script:")) 2183aad8e480SEnrico Granata { 2184aad8e480SEnrico Granata var_name_begin += ::strlen("script:"); 2185aad8e480SEnrico Granata std::string script_name(var_name_begin,var_name_end); 2186aad8e480SEnrico Granata ScriptInterpreter* script_interpreter = target->GetDebugger().GetCommandInterpreter().GetScriptInterpreter(); 21870769b2b1SMichael Sartain if (RunScriptFormatKeyword (s, script_interpreter, target, script_name)) 2188aad8e480SEnrico Granata var_success = true; 2189aad8e480SEnrico Granata } 21901b654882SGreg Clayton } 21911b654882SGreg Clayton } 21921b654882SGreg Clayton break; 21931b654882SGreg Clayton 21941b654882SGreg Clayton case 'm': 21950769b2b1SMichael Sartain if (IsToken (var_name_begin, "module.")) 21961b654882SGreg Clayton { 21970603aa9dSGreg Clayton if (sc && sc->module_sp.get()) 21981b654882SGreg Clayton { 21990603aa9dSGreg Clayton Module *module = sc->module_sp.get(); 22001b654882SGreg Clayton var_name_begin += ::strlen ("module."); 22011b654882SGreg Clayton 22020769b2b1SMichael Sartain if (IsToken (var_name_begin, "file.")) 22031b654882SGreg Clayton { 22041b654882SGreg Clayton if (module->GetFileSpec()) 22051b654882SGreg Clayton { 22061b654882SGreg Clayton var_name_begin += ::strlen ("file."); 22071b654882SGreg Clayton 22080769b2b1SMichael Sartain if (IsToken (var_name_begin, "basename}")) 22091b654882SGreg Clayton { 22101b654882SGreg Clayton format_file_spec.GetFilename() = module->GetFileSpec().GetFilename(); 22119076c0ffSSean Callanan var_success = (bool)format_file_spec; 22121b654882SGreg Clayton } 22130769b2b1SMichael Sartain else if (IsToken (var_name_begin, "fullpath}")) 22141b654882SGreg Clayton { 22151b654882SGreg Clayton format_file_spec = module->GetFileSpec(); 22169076c0ffSSean Callanan var_success = (bool)format_file_spec; 22171b654882SGreg Clayton } 22181b654882SGreg Clayton } 22191b654882SGreg Clayton } 22201b654882SGreg Clayton } 22211b654882SGreg Clayton } 22221b654882SGreg Clayton break; 22231b654882SGreg Clayton 22241b654882SGreg Clayton 22251b654882SGreg Clayton case 'f': 22260769b2b1SMichael Sartain if (IsToken (var_name_begin, "file.")) 22271b654882SGreg Clayton { 22281b654882SGreg Clayton if (sc && sc->comp_unit != NULL) 22291b654882SGreg Clayton { 22301b654882SGreg Clayton var_name_begin += ::strlen ("file."); 22311b654882SGreg Clayton 22320769b2b1SMichael Sartain if (IsToken (var_name_begin, "basename}")) 22331b654882SGreg Clayton { 22341b654882SGreg Clayton format_file_spec.GetFilename() = sc->comp_unit->GetFilename(); 22359076c0ffSSean Callanan var_success = (bool)format_file_spec; 22361b654882SGreg Clayton } 22370769b2b1SMichael Sartain else if (IsToken (var_name_begin, "fullpath}")) 22381b654882SGreg Clayton { 22391b654882SGreg Clayton format_file_spec = *sc->comp_unit; 22409076c0ffSSean Callanan var_success = (bool)format_file_spec; 22411b654882SGreg Clayton } 22421b654882SGreg Clayton } 22431b654882SGreg Clayton } 22440769b2b1SMichael Sartain else if (IsToken (var_name_begin, "frame.")) 22451b654882SGreg Clayton { 2246c14ee32dSGreg Clayton if (exe_ctx) 2247c14ee32dSGreg Clayton { 2248b57e4a1bSJason Molenda StackFrame *frame = exe_ctx->GetFramePtr(); 2249c14ee32dSGreg Clayton if (frame) 22501b654882SGreg Clayton { 22511b654882SGreg Clayton var_name_begin += ::strlen ("frame."); 22520769b2b1SMichael Sartain if (IsToken (var_name_begin, "index}")) 22531b654882SGreg Clayton { 2254c14ee32dSGreg Clayton s.Printf("%u", frame->GetFrameIndex()); 22551b654882SGreg Clayton var_success = true; 22561b654882SGreg Clayton } 22570769b2b1SMichael Sartain else if (IsToken (var_name_begin, "pc}")) 22581b654882SGreg Clayton { 22591b654882SGreg Clayton reg_kind = eRegisterKindGeneric; 22601b654882SGreg Clayton reg_num = LLDB_REGNUM_GENERIC_PC; 22611b654882SGreg Clayton var_success = true; 22621b654882SGreg Clayton } 22630769b2b1SMichael Sartain else if (IsToken (var_name_begin, "sp}")) 22641b654882SGreg Clayton { 22651b654882SGreg Clayton reg_kind = eRegisterKindGeneric; 22661b654882SGreg Clayton reg_num = LLDB_REGNUM_GENERIC_SP; 22671b654882SGreg Clayton var_success = true; 22681b654882SGreg Clayton } 22690769b2b1SMichael Sartain else if (IsToken (var_name_begin, "fp}")) 22701b654882SGreg Clayton { 22711b654882SGreg Clayton reg_kind = eRegisterKindGeneric; 22721b654882SGreg Clayton reg_num = LLDB_REGNUM_GENERIC_FP; 22731b654882SGreg Clayton var_success = true; 22741b654882SGreg Clayton } 22750769b2b1SMichael Sartain else if (IsToken (var_name_begin, "flags}")) 22761b654882SGreg Clayton { 22771b654882SGreg Clayton reg_kind = eRegisterKindGeneric; 22781b654882SGreg Clayton reg_num = LLDB_REGNUM_GENERIC_FLAGS; 22791b654882SGreg Clayton var_success = true; 22801b654882SGreg Clayton } 22810769b2b1SMichael Sartain else if (IsToken (var_name_begin, "reg.")) 22821b654882SGreg Clayton { 2283c14ee32dSGreg Clayton reg_ctx = frame->GetRegisterContext().get(); 22841b654882SGreg Clayton if (reg_ctx) 22851b654882SGreg Clayton { 22861b654882SGreg Clayton var_name_begin += ::strlen ("reg."); 22871b654882SGreg Clayton if (var_name_begin < var_name_end) 22881b654882SGreg Clayton { 22891b654882SGreg Clayton std::string reg_name (var_name_begin, var_name_end); 22901b654882SGreg Clayton reg_info = reg_ctx->GetRegisterInfoByName (reg_name.c_str()); 22911b654882SGreg Clayton if (reg_info) 22921b654882SGreg Clayton var_success = true; 22931b654882SGreg Clayton } 22941b654882SGreg Clayton } 22951b654882SGreg Clayton } 22960769b2b1SMichael Sartain else if (IsToken (var_name_begin, "script:")) 2297aad8e480SEnrico Granata { 2298aad8e480SEnrico Granata var_name_begin += ::strlen("script:"); 2299aad8e480SEnrico Granata std::string script_name(var_name_begin,var_name_end); 2300aad8e480SEnrico Granata ScriptInterpreter* script_interpreter = frame->GetThread()->GetProcess()->GetTarget().GetDebugger().GetCommandInterpreter().GetScriptInterpreter(); 23010769b2b1SMichael Sartain if (RunScriptFormatKeyword (s, script_interpreter, frame, script_name)) 2302aad8e480SEnrico Granata var_success = true; 2303aad8e480SEnrico Granata } 2304aad8e480SEnrico Granata } 2305aad8e480SEnrico Granata } 23061b654882SGreg Clayton } 23070769b2b1SMichael Sartain else if (IsToken (var_name_begin, "function.")) 23081b654882SGreg Clayton { 23091b654882SGreg Clayton if (sc && (sc->function != NULL || sc->symbol != NULL)) 23101b654882SGreg Clayton { 23111b654882SGreg Clayton var_name_begin += ::strlen ("function."); 23120769b2b1SMichael Sartain if (IsToken (var_name_begin, "id}")) 23131b654882SGreg Clayton { 23141b654882SGreg Clayton if (sc->function) 2315d01b2953SDaniel Malea s.Printf("function{0x%8.8" PRIx64 "}", sc->function->GetID()); 23161b654882SGreg Clayton else 23171b654882SGreg Clayton s.Printf("symbol[%u]", sc->symbol->GetID()); 23181b654882SGreg Clayton 23191b654882SGreg Clayton var_success = true; 23201b654882SGreg Clayton } 2321aff1b357SJason Molenda if (IsToken (var_name_begin, "changed}") && function_changed) 2322aff1b357SJason Molenda { 2323aff1b357SJason Molenda var_success = true; 2324aff1b357SJason Molenda } 2325aff1b357SJason Molenda if (IsToken (var_name_begin, "initial-function}") && initial_function) 2326aff1b357SJason Molenda { 2327aff1b357SJason Molenda var_success = true; 2328aff1b357SJason Molenda } 23290769b2b1SMichael Sartain else if (IsToken (var_name_begin, "name}")) 23301b654882SGreg Clayton { 23311b654882SGreg Clayton if (sc->function) 23321b654882SGreg Clayton cstr = sc->function->GetName().AsCString (NULL); 23331b654882SGreg Clayton else if (sc->symbol) 23341b654882SGreg Clayton cstr = sc->symbol->GetName().AsCString (NULL); 23351b654882SGreg Clayton if (cstr) 23361b654882SGreg Clayton { 23371b654882SGreg Clayton s.PutCString(cstr); 23380d9c9934SGreg Clayton 23390d9c9934SGreg Clayton if (sc->block) 23400d9c9934SGreg Clayton { 23410d9c9934SGreg Clayton Block *inline_block = sc->block->GetContainingInlinedBlock (); 23420d9c9934SGreg Clayton if (inline_block) 23430d9c9934SGreg Clayton { 23440d9c9934SGreg Clayton const InlineFunctionInfo *inline_info = sc->block->GetInlinedFunctionInfo(); 23450d9c9934SGreg Clayton if (inline_info) 23460d9c9934SGreg Clayton { 23470d9c9934SGreg Clayton s.PutCString(" [inlined] "); 23480d9c9934SGreg Clayton inline_info->GetName().Dump(&s); 23490d9c9934SGreg Clayton } 23500d9c9934SGreg Clayton } 23510d9c9934SGreg Clayton } 23521b654882SGreg Clayton var_success = true; 23531b654882SGreg Clayton } 23541b654882SGreg Clayton } 2355aff1b357SJason Molenda else if (IsToken (var_name_begin, "name-without-args}")) 2356aff1b357SJason Molenda { 2357aff1b357SJason Molenda ConstString name; 2358aff1b357SJason Molenda if (sc->function) 2359aff1b357SJason Molenda name = sc->function->GetMangled().GetName (Mangled::ePreferDemangledWithoutArguments); 2360aff1b357SJason Molenda else if (sc->symbol) 2361aff1b357SJason Molenda name = sc->symbol->GetMangled().GetName (Mangled::ePreferDemangledWithoutArguments); 2362aff1b357SJason Molenda if (name) 2363aff1b357SJason Molenda { 2364aff1b357SJason Molenda s.PutCString(name.GetCString()); 2365aff1b357SJason Molenda var_success = true; 2366aff1b357SJason Molenda } 2367aff1b357SJason Molenda } 23680769b2b1SMichael Sartain else if (IsToken (var_name_begin, "name-with-args}")) 23696d3dbf51SGreg Clayton { 23706d3dbf51SGreg Clayton // Print the function name with arguments in it 23716d3dbf51SGreg Clayton 23726d3dbf51SGreg Clayton if (sc->function) 23736d3dbf51SGreg Clayton { 23746d3dbf51SGreg Clayton var_success = true; 23756d3dbf51SGreg Clayton ExecutionContextScope *exe_scope = exe_ctx ? exe_ctx->GetBestExecutionContextScope() : NULL; 23766d3dbf51SGreg Clayton cstr = sc->function->GetName().AsCString (NULL); 23776d3dbf51SGreg Clayton if (cstr) 23786d3dbf51SGreg Clayton { 23796d3dbf51SGreg Clayton const InlineFunctionInfo *inline_info = NULL; 23806d3dbf51SGreg Clayton VariableListSP variable_list_sp; 23816d3dbf51SGreg Clayton bool get_function_vars = true; 23826d3dbf51SGreg Clayton if (sc->block) 23836d3dbf51SGreg Clayton { 23846d3dbf51SGreg Clayton Block *inline_block = sc->block->GetContainingInlinedBlock (); 23856d3dbf51SGreg Clayton 23866d3dbf51SGreg Clayton if (inline_block) 23876d3dbf51SGreg Clayton { 23886d3dbf51SGreg Clayton get_function_vars = false; 23896d3dbf51SGreg Clayton inline_info = sc->block->GetInlinedFunctionInfo(); 23906d3dbf51SGreg Clayton if (inline_info) 23916d3dbf51SGreg Clayton variable_list_sp = inline_block->GetBlockVariableList (true); 23926d3dbf51SGreg Clayton } 23936d3dbf51SGreg Clayton } 23946d3dbf51SGreg Clayton 23956d3dbf51SGreg Clayton if (get_function_vars) 23966d3dbf51SGreg Clayton { 23976d3dbf51SGreg Clayton variable_list_sp = sc->function->GetBlock(true).GetBlockVariableList (true); 23986d3dbf51SGreg Clayton } 23996d3dbf51SGreg Clayton 24006d3dbf51SGreg Clayton if (inline_info) 24016d3dbf51SGreg Clayton { 24026d3dbf51SGreg Clayton s.PutCString (cstr); 24036d3dbf51SGreg Clayton s.PutCString (" [inlined] "); 24046d3dbf51SGreg Clayton cstr = inline_info->GetName().GetCString(); 24056d3dbf51SGreg Clayton } 24066d3dbf51SGreg Clayton 24076d3dbf51SGreg Clayton VariableList args; 24086d3dbf51SGreg Clayton if (variable_list_sp) 2409cc7f9bf5SEnrico Granata variable_list_sp->AppendVariablesWithScope(eValueTypeVariableArgument, args); 24106d3dbf51SGreg Clayton if (args.GetSize() > 0) 24116d3dbf51SGreg Clayton { 24126d3dbf51SGreg Clayton const char *open_paren = strchr (cstr, '('); 2413e4a4f5d5SEnrico Granata const char *close_paren = nullptr; 2414e4a4f5d5SEnrico Granata const char *generic = strchr(cstr, '<'); 2415e4a4f5d5SEnrico Granata // if before the arguments list begins there is a template sign 2416e4a4f5d5SEnrico Granata // then scan to the end of the generic args before you try to find 2417e4a4f5d5SEnrico Granata // the arguments list 2418e4a4f5d5SEnrico Granata if (generic && open_paren && generic < open_paren) 2419e4a4f5d5SEnrico Granata { 2420e4a4f5d5SEnrico Granata int generic_depth = 1; 2421e4a4f5d5SEnrico Granata ++generic; 2422e4a4f5d5SEnrico Granata for (; 2423e4a4f5d5SEnrico Granata *generic && generic_depth > 0; 2424e4a4f5d5SEnrico Granata generic++) 2425e4a4f5d5SEnrico Granata { 2426e4a4f5d5SEnrico Granata if (*generic == '<') 2427e4a4f5d5SEnrico Granata generic_depth++; 2428e4a4f5d5SEnrico Granata if (*generic == '>') 2429e4a4f5d5SEnrico Granata generic_depth--; 2430e4a4f5d5SEnrico Granata } 2431e4a4f5d5SEnrico Granata if (*generic) 2432e4a4f5d5SEnrico Granata open_paren = strchr(generic, '('); 2433e4a4f5d5SEnrico Granata else 2434e4a4f5d5SEnrico Granata open_paren = nullptr; 2435e4a4f5d5SEnrico Granata } 24366d3dbf51SGreg Clayton if (open_paren) 2437855958caSGreg Clayton { 24380769b2b1SMichael Sartain if (IsToken (open_paren, "(anonymous namespace)")) 2439855958caSGreg Clayton { 2440855958caSGreg Clayton open_paren = strchr (open_paren + strlen("(anonymous namespace)"), '('); 2441855958caSGreg Clayton if (open_paren) 24426d3dbf51SGreg Clayton close_paren = strchr (open_paren, ')'); 2443855958caSGreg Clayton } 2444855958caSGreg Clayton else 2445855958caSGreg Clayton close_paren = strchr (open_paren, ')'); 2446855958caSGreg Clayton } 24476d3dbf51SGreg Clayton 24486d3dbf51SGreg Clayton if (open_paren) 24496d3dbf51SGreg Clayton s.Write(cstr, open_paren - cstr + 1); 24506d3dbf51SGreg Clayton else 24516d3dbf51SGreg Clayton { 24526d3dbf51SGreg Clayton s.PutCString (cstr); 24536d3dbf51SGreg Clayton s.PutChar ('('); 24546d3dbf51SGreg Clayton } 24555b6889b1SGreg Clayton const size_t num_args = args.GetSize(); 24566d3dbf51SGreg Clayton for (size_t arg_idx = 0; arg_idx < num_args; ++arg_idx) 24576d3dbf51SGreg Clayton { 2458894f7359SEnrico Granata std::string buffer; 2459894f7359SEnrico Granata 24606d3dbf51SGreg Clayton VariableSP var_sp (args.GetVariableAtIndex (arg_idx)); 24616d3dbf51SGreg Clayton ValueObjectSP var_value_sp (ValueObjectVariable::Create (exe_scope, var_sp)); 2462894f7359SEnrico Granata const char *var_representation = nullptr; 24636d3dbf51SGreg Clayton const char *var_name = var_value_sp->GetName().GetCString(); 2464894f7359SEnrico Granata if (var_value_sp->GetClangType().IsAggregateType() && 2465894f7359SEnrico Granata DataVisualization::ShouldPrintAsOneLiner(*var_value_sp.get())) 2466894f7359SEnrico Granata { 2467894f7359SEnrico Granata static StringSummaryFormat format(TypeSummaryImpl::Flags() 2468894f7359SEnrico Granata .SetHideItemNames(false) 2469894f7359SEnrico Granata .SetShowMembersOneLiner(true), 2470894f7359SEnrico Granata ""); 2471894f7359SEnrico Granata format.FormatObject(var_value_sp.get(), buffer); 2472894f7359SEnrico Granata var_representation = buffer.c_str(); 2473894f7359SEnrico Granata } 2474894f7359SEnrico Granata else 2475894f7359SEnrico Granata var_representation = var_value_sp->GetValueAsCString(); 24766d3dbf51SGreg Clayton if (arg_idx > 0) 24776d3dbf51SGreg Clayton s.PutCString (", "); 24783b188b17SGreg Clayton if (var_value_sp->GetError().Success()) 2479cc7f9bf5SEnrico Granata { 2480894f7359SEnrico Granata if (var_representation) 2481894f7359SEnrico Granata s.Printf ("%s=%s", var_name, var_representation); 24823b188b17SGreg Clayton else 2483cc7f9bf5SEnrico Granata s.Printf ("%s=%s at %s", var_name, var_value_sp->GetTypeName().GetCString(), var_value_sp->GetLocationAsCString()); 2484cc7f9bf5SEnrico Granata } 2485cc7f9bf5SEnrico Granata else 24863b188b17SGreg Clayton s.Printf ("%s=<unavailable>", var_name); 24876d3dbf51SGreg Clayton } 24886d3dbf51SGreg Clayton 24896d3dbf51SGreg Clayton if (close_paren) 24906d3dbf51SGreg Clayton s.PutCString (close_paren); 24916d3dbf51SGreg Clayton else 24926d3dbf51SGreg Clayton s.PutChar(')'); 24936d3dbf51SGreg Clayton 24946d3dbf51SGreg Clayton } 24956d3dbf51SGreg Clayton else 24966d3dbf51SGreg Clayton { 24976d3dbf51SGreg Clayton s.PutCString(cstr); 24986d3dbf51SGreg Clayton } 24996d3dbf51SGreg Clayton } 25006d3dbf51SGreg Clayton } 25016d3dbf51SGreg Clayton else if (sc->symbol) 25026d3dbf51SGreg Clayton { 25036d3dbf51SGreg Clayton cstr = sc->symbol->GetName().AsCString (NULL); 25046d3dbf51SGreg Clayton if (cstr) 25056d3dbf51SGreg Clayton { 25066d3dbf51SGreg Clayton s.PutCString(cstr); 25076d3dbf51SGreg Clayton var_success = true; 25086d3dbf51SGreg Clayton } 25096d3dbf51SGreg Clayton } 25106d3dbf51SGreg Clayton } 2511aff1b357SJason Molenda else if (IsToken (var_name_begin, "addr-offset}") 2512aff1b357SJason Molenda || IsToken (var_name_begin, "concrete-only-addr-offset-no-padding}")) 25131b654882SGreg Clayton { 2514aff1b357SJason Molenda if (IsToken (var_name_begin, "concrete-only-addr-offset-no-padding}")) 2515aff1b357SJason Molenda { 2516aff1b357SJason Molenda addr_offset_print_with_no_padding = true; 2517aff1b357SJason Molenda addr_offset_concrete_func_only = true; 2518aff1b357SJason Molenda } 25191b654882SGreg Clayton var_success = addr != NULL; 25201b654882SGreg Clayton if (var_success) 25211b654882SGreg Clayton { 25221b654882SGreg Clayton format_addr = *addr; 25231b654882SGreg Clayton calculate_format_addr_function_offset = true; 25241b654882SGreg Clayton } 25251b654882SGreg Clayton } 25260769b2b1SMichael Sartain else if (IsToken (var_name_begin, "line-offset}")) 25271b654882SGreg Clayton { 25281b654882SGreg Clayton var_success = sc->line_entry.range.GetBaseAddress().IsValid(); 25291b654882SGreg Clayton if (var_success) 25301b654882SGreg Clayton { 25311b654882SGreg Clayton format_addr = sc->line_entry.range.GetBaseAddress(); 25321b654882SGreg Clayton calculate_format_addr_function_offset = true; 25331b654882SGreg Clayton } 25341b654882SGreg Clayton } 25350769b2b1SMichael Sartain else if (IsToken (var_name_begin, "pc-offset}")) 25361b654882SGreg Clayton { 2537b57e4a1bSJason Molenda StackFrame *frame = exe_ctx->GetFramePtr(); 2538c14ee32dSGreg Clayton var_success = frame != NULL; 25391b654882SGreg Clayton if (var_success) 25401b654882SGreg Clayton { 2541c14ee32dSGreg Clayton format_addr = frame->GetFrameCodeAddress(); 25421b654882SGreg Clayton calculate_format_addr_function_offset = true; 25431b654882SGreg Clayton } 25441b654882SGreg Clayton } 25451b654882SGreg Clayton } 25461b654882SGreg Clayton } 25471b654882SGreg Clayton break; 25481b654882SGreg Clayton 25491b654882SGreg Clayton case 'l': 25500769b2b1SMichael Sartain if (IsToken (var_name_begin, "line.")) 25511b654882SGreg Clayton { 25521b654882SGreg Clayton if (sc && sc->line_entry.IsValid()) 25531b654882SGreg Clayton { 25541b654882SGreg Clayton var_name_begin += ::strlen ("line."); 25550769b2b1SMichael Sartain if (IsToken (var_name_begin, "file.")) 25561b654882SGreg Clayton { 25571b654882SGreg Clayton var_name_begin += ::strlen ("file."); 25581b654882SGreg Clayton 25590769b2b1SMichael Sartain if (IsToken (var_name_begin, "basename}")) 25601b654882SGreg Clayton { 25611b654882SGreg Clayton format_file_spec.GetFilename() = sc->line_entry.file.GetFilename(); 25629076c0ffSSean Callanan var_success = (bool)format_file_spec; 25631b654882SGreg Clayton } 25640769b2b1SMichael Sartain else if (IsToken (var_name_begin, "fullpath}")) 25651b654882SGreg Clayton { 25661b654882SGreg Clayton format_file_spec = sc->line_entry.file; 25679076c0ffSSean Callanan var_success = (bool)format_file_spec; 25681b654882SGreg Clayton } 25691b654882SGreg Clayton } 25700769b2b1SMichael Sartain else if (IsTokenWithFormat (var_name_begin, "number", token_format, "%" PRIu64, exe_ctx, sc)) 25711b654882SGreg Clayton { 25721b654882SGreg Clayton var_success = true; 25730769b2b1SMichael Sartain s.Printf(token_format.c_str(), (uint64_t)sc->line_entry.line); 25741b654882SGreg Clayton } 25750769b2b1SMichael Sartain else if ((IsToken (var_name_begin, "start-addr}")) || 25760769b2b1SMichael Sartain (IsToken (var_name_begin, "end-addr}"))) 25771b654882SGreg Clayton { 25781b654882SGreg Clayton var_success = sc && sc->line_entry.range.GetBaseAddress().IsValid(); 25791b654882SGreg Clayton if (var_success) 25801b654882SGreg Clayton { 25811b654882SGreg Clayton format_addr = sc->line_entry.range.GetBaseAddress(); 25821b654882SGreg Clayton if (var_name_begin[0] == 'e') 25831b654882SGreg Clayton format_addr.Slide (sc->line_entry.range.GetByteSize()); 25841b654882SGreg Clayton } 25851b654882SGreg Clayton } 25861b654882SGreg Clayton } 25871b654882SGreg Clayton } 25881b654882SGreg Clayton break; 2589aff1b357SJason Molenda case 'c': 2590aff1b357SJason Molenda if (IsToken (var_name_begin, "current-pc-arrow")) 2591aff1b357SJason Molenda { 2592aff1b357SJason Molenda if (addr && exe_ctx && exe_ctx->GetFramePtr()) 2593aff1b357SJason Molenda { 2594aff1b357SJason Molenda RegisterContextSP reg_ctx = exe_ctx->GetFramePtr()->GetRegisterContextSP(); 2595aff1b357SJason Molenda if (reg_ctx.get()) 2596aff1b357SJason Molenda { 2597aff1b357SJason Molenda addr_t pc_loadaddr = reg_ctx->GetPC(); 2598aff1b357SJason Molenda if (pc_loadaddr != LLDB_INVALID_ADDRESS) 2599aff1b357SJason Molenda { 2600aff1b357SJason Molenda Address pc; 2601aff1b357SJason Molenda pc.SetLoadAddress (pc_loadaddr, exe_ctx->GetTargetPtr()); 2602aff1b357SJason Molenda if (pc == *addr) 2603aff1b357SJason Molenda { 2604aff1b357SJason Molenda s.Printf ("->"); 2605aff1b357SJason Molenda var_success = true; 2606aff1b357SJason Molenda } 2607aff1b357SJason Molenda else 2608aff1b357SJason Molenda { 2609aff1b357SJason Molenda s.Printf(" "); 2610aff1b357SJason Molenda var_success = true; 2611aff1b357SJason Molenda } 2612aff1b357SJason Molenda } 2613aff1b357SJason Molenda } 2614aff1b357SJason Molenda } 2615aff1b357SJason Molenda } 2616aff1b357SJason Molenda break; 26171b654882SGreg Clayton } 26181b654882SGreg Clayton 26191b654882SGreg Clayton if (var_success) 26201b654882SGreg Clayton { 26211b654882SGreg Clayton // If format addr is valid, then we need to print an address 26221b654882SGreg Clayton if (reg_num != LLDB_INVALID_REGNUM) 26231b654882SGreg Clayton { 2624b57e4a1bSJason Molenda StackFrame *frame = exe_ctx->GetFramePtr(); 26251b654882SGreg Clayton // We have a register value to display... 26261b654882SGreg Clayton if (reg_num == LLDB_REGNUM_GENERIC_PC && reg_kind == eRegisterKindGeneric) 26271b654882SGreg Clayton { 2628c14ee32dSGreg Clayton format_addr = frame->GetFrameCodeAddress(); 26291b654882SGreg Clayton } 26301b654882SGreg Clayton else 26311b654882SGreg Clayton { 26321b654882SGreg Clayton if (reg_ctx == NULL) 2633c14ee32dSGreg Clayton reg_ctx = frame->GetRegisterContext().get(); 26341b654882SGreg Clayton 26351b654882SGreg Clayton if (reg_ctx) 26361b654882SGreg Clayton { 26371b654882SGreg Clayton if (reg_kind != kNumRegisterKinds) 26381b654882SGreg Clayton reg_num = reg_ctx->ConvertRegisterKindToRegisterNumber(reg_kind, reg_num); 26391b654882SGreg Clayton reg_info = reg_ctx->GetRegisterInfoAtIndex (reg_num); 26401b654882SGreg Clayton var_success = reg_info != NULL; 26411b654882SGreg Clayton } 26421b654882SGreg Clayton } 26431b654882SGreg Clayton } 26441b654882SGreg Clayton 26451b654882SGreg Clayton if (reg_info != NULL) 26461b654882SGreg Clayton { 26477349bd90SGreg Clayton RegisterValue reg_value; 26487349bd90SGreg Clayton var_success = reg_ctx->ReadRegister (reg_info, reg_value); 26497349bd90SGreg Clayton if (var_success) 26501b654882SGreg Clayton { 26519a8fa916SGreg Clayton reg_value.Dump(&s, reg_info, false, false, eFormatDefault); 26521b654882SGreg Clayton } 26531b654882SGreg Clayton } 26541b654882SGreg Clayton 26551b654882SGreg Clayton if (format_file_spec) 26561b654882SGreg Clayton { 26571b654882SGreg Clayton s << format_file_spec; 26581b654882SGreg Clayton } 26591b654882SGreg Clayton 26601b654882SGreg Clayton // If format addr is valid, then we need to print an address 26611b654882SGreg Clayton if (format_addr.IsValid()) 26621b654882SGreg Clayton { 26630603aa9dSGreg Clayton var_success = false; 26640603aa9dSGreg Clayton 26651b654882SGreg Clayton if (calculate_format_addr_function_offset) 26661b654882SGreg Clayton { 26671b654882SGreg Clayton Address func_addr; 26680603aa9dSGreg Clayton 26690603aa9dSGreg Clayton if (sc) 26700603aa9dSGreg Clayton { 26711b654882SGreg Clayton if (sc->function) 26720d9c9934SGreg Clayton { 26731b654882SGreg Clayton func_addr = sc->function->GetAddressRange().GetBaseAddress(); 2674aff1b357SJason Molenda if (sc->block && addr_offset_concrete_func_only == false) 26750d9c9934SGreg Clayton { 26760d9c9934SGreg Clayton // Check to make sure we aren't in an inline 26770d9c9934SGreg Clayton // function. If we are, use the inline block 26780d9c9934SGreg Clayton // range that contains "format_addr" since 26790d9c9934SGreg Clayton // blocks can be discontiguous. 26800d9c9934SGreg Clayton Block *inline_block = sc->block->GetContainingInlinedBlock (); 26810d9c9934SGreg Clayton AddressRange inline_range; 26820d9c9934SGreg Clayton if (inline_block && inline_block->GetRangeContainingAddress (format_addr, inline_range)) 26830d9c9934SGreg Clayton func_addr = inline_range.GetBaseAddress(); 26840d9c9934SGreg Clayton } 26850d9c9934SGreg Clayton } 2686e7612134SGreg Clayton else if (sc->symbol && sc->symbol->ValueIsAddress()) 2687e7612134SGreg Clayton func_addr = sc->symbol->GetAddress(); 26880603aa9dSGreg Clayton } 26891b654882SGreg Clayton 26900603aa9dSGreg Clayton if (func_addr.IsValid()) 26911b654882SGreg Clayton { 2692aff1b357SJason Molenda const char *addr_offset_padding = " "; 2693aff1b357SJason Molenda if (addr_offset_print_with_no_padding) 2694aff1b357SJason Molenda { 2695aff1b357SJason Molenda addr_offset_padding = ""; 2696aff1b357SJason Molenda } 26971b654882SGreg Clayton if (func_addr.GetSection() == format_addr.GetSection()) 26981b654882SGreg Clayton { 26991b654882SGreg Clayton addr_t func_file_addr = func_addr.GetFileAddress(); 27001b654882SGreg Clayton addr_t addr_file_addr = format_addr.GetFileAddress(); 27011b654882SGreg Clayton if (addr_file_addr > func_file_addr) 2702aff1b357SJason Molenda s.Printf("%s+%s%" PRIu64, addr_offset_padding, addr_offset_padding, addr_file_addr - func_file_addr); 27031b654882SGreg Clayton else if (addr_file_addr < func_file_addr) 2704aff1b357SJason Molenda s.Printf("%s-%s%" PRIu64, addr_offset_padding, addr_offset_padding, func_file_addr - addr_file_addr); 27050603aa9dSGreg Clayton var_success = true; 27061b654882SGreg Clayton } 27071b654882SGreg Clayton else 27080603aa9dSGreg Clayton { 27090603aa9dSGreg Clayton Target *target = Target::GetTargetFromContexts (exe_ctx, sc); 27100603aa9dSGreg Clayton if (target) 27110603aa9dSGreg Clayton { 27120603aa9dSGreg Clayton addr_t func_load_addr = func_addr.GetLoadAddress (target); 27130603aa9dSGreg Clayton addr_t addr_load_addr = format_addr.GetLoadAddress (target); 27140603aa9dSGreg Clayton if (addr_load_addr > func_load_addr) 2715aff1b357SJason Molenda s.Printf("%s+%s%" PRIu64, addr_offset_padding, addr_offset_padding, addr_load_addr - func_load_addr); 27160603aa9dSGreg Clayton else if (addr_load_addr < func_load_addr) 2717aff1b357SJason Molenda s.Printf("%s-%s%" PRIu64, addr_offset_padding, addr_offset_padding, func_load_addr - addr_load_addr); 27180603aa9dSGreg Clayton var_success = true; 27190603aa9dSGreg Clayton } 27200603aa9dSGreg Clayton } 27211b654882SGreg Clayton } 27221b654882SGreg Clayton } 27231b654882SGreg Clayton else 27241b654882SGreg Clayton { 27250603aa9dSGreg Clayton Target *target = Target::GetTargetFromContexts (exe_ctx, sc); 27261b654882SGreg Clayton addr_t vaddr = LLDB_INVALID_ADDRESS; 27270603aa9dSGreg Clayton if (exe_ctx && !target->GetSectionLoadList().IsEmpty()) 27280603aa9dSGreg Clayton vaddr = format_addr.GetLoadAddress (target); 27291b654882SGreg Clayton if (vaddr == LLDB_INVALID_ADDRESS) 27301b654882SGreg Clayton vaddr = format_addr.GetFileAddress (); 27311b654882SGreg Clayton 27321b654882SGreg Clayton if (vaddr != LLDB_INVALID_ADDRESS) 27330603aa9dSGreg Clayton { 2734aff1b357SJason Molenda int addr_width = 0; 2735aff1b357SJason Molenda if (exe_ctx && target) 2736aff1b357SJason Molenda { 2737*fd1a9362SEric Christopher addr_width = target->GetArchitecture().GetAddressByteSize() * 2; 2738aff1b357SJason Molenda } 273935f1a0d5SGreg Clayton if (addr_width == 0) 274035f1a0d5SGreg Clayton addr_width = 16; 2741aff1b357SJason Molenda if (print_file_addr_or_load_addr) 2742aff1b357SJason Molenda { 2743aff1b357SJason Molenda format_addr.Dump (&s, exe_ctx ? exe_ctx->GetBestExecutionContextScope() : NULL, Address::DumpStyleLoadAddress, Address::DumpStyleModuleWithFileAddress, 0); 2744aff1b357SJason Molenda } 2745aff1b357SJason Molenda else 2746aff1b357SJason Molenda { 2747d01b2953SDaniel Malea s.Printf("0x%*.*" PRIx64, addr_width, addr_width, vaddr); 2748aff1b357SJason Molenda } 27490603aa9dSGreg Clayton var_success = true; 27500603aa9dSGreg Clayton } 27511b654882SGreg Clayton } 27521b654882SGreg Clayton } 27531b654882SGreg Clayton } 27541b654882SGreg Clayton 27551b654882SGreg Clayton if (var_success == false) 27561b654882SGreg Clayton success = false; 27571b654882SGreg Clayton } 27581b654882SGreg Clayton p = var_name_end; 27591b654882SGreg Clayton } 27601b654882SGreg Clayton else 27611b654882SGreg Clayton break; 27621b654882SGreg Clayton } 27631b654882SGreg Clayton else 27641b654882SGreg Clayton { 27651b654882SGreg Clayton // We got a dollar sign with no '{' after it, it must just be a dollar sign 27661b654882SGreg Clayton s.PutChar(*p); 27671b654882SGreg Clayton } 27681b654882SGreg Clayton } 27691b654882SGreg Clayton else if (*p == '\\') 27701b654882SGreg Clayton { 27711b654882SGreg Clayton ++p; // skip the slash 27721b654882SGreg Clayton switch (*p) 27731b654882SGreg Clayton { 27741b654882SGreg Clayton case 'a': s.PutChar ('\a'); break; 27751b654882SGreg Clayton case 'b': s.PutChar ('\b'); break; 27761b654882SGreg Clayton case 'f': s.PutChar ('\f'); break; 27771b654882SGreg Clayton case 'n': s.PutChar ('\n'); break; 27781b654882SGreg Clayton case 'r': s.PutChar ('\r'); break; 27791b654882SGreg Clayton case 't': s.PutChar ('\t'); break; 27801b654882SGreg Clayton case 'v': s.PutChar ('\v'); break; 27811b654882SGreg Clayton case '\'': s.PutChar ('\''); break; 27821b654882SGreg Clayton case '\\': s.PutChar ('\\'); break; 27831b654882SGreg Clayton case '0': 27841b654882SGreg Clayton // 1 to 3 octal chars 27851b654882SGreg Clayton { 27860603aa9dSGreg Clayton // Make a string that can hold onto the initial zero char, 27870603aa9dSGreg Clayton // up to 3 octal digits, and a terminating NULL. 27880603aa9dSGreg Clayton char oct_str[5] = { 0, 0, 0, 0, 0 }; 27890603aa9dSGreg Clayton 27900603aa9dSGreg Clayton int i; 27910603aa9dSGreg Clayton for (i=0; (p[i] >= '0' && p[i] <= '7') && i<4; ++i) 27920603aa9dSGreg Clayton oct_str[i] = p[i]; 27930603aa9dSGreg Clayton 27940603aa9dSGreg Clayton // We don't want to consume the last octal character since 27950603aa9dSGreg Clayton // the main for loop will do this for us, so we advance p by 27960603aa9dSGreg Clayton // one less than i (even if i is zero) 27970603aa9dSGreg Clayton p += i - 1; 27980603aa9dSGreg Clayton unsigned long octal_value = ::strtoul (oct_str, NULL, 8); 27990603aa9dSGreg Clayton if (octal_value <= UINT8_MAX) 28001b654882SGreg Clayton { 2801c7bece56SGreg Clayton s.PutChar((char)octal_value); 28021b654882SGreg Clayton } 28031b654882SGreg Clayton } 28041b654882SGreg Clayton break; 28051b654882SGreg Clayton 28061b654882SGreg Clayton case 'x': 28071b654882SGreg Clayton // hex number in the format 28080603aa9dSGreg Clayton if (isxdigit(p[1])) 28091b654882SGreg Clayton { 28100603aa9dSGreg Clayton ++p; // Skip the 'x' 28111b654882SGreg Clayton 28120603aa9dSGreg Clayton // Make a string that can hold onto two hex chars plus a 28130603aa9dSGreg Clayton // NULL terminator 28141b654882SGreg Clayton char hex_str[3] = { 0,0,0 }; 28151b654882SGreg Clayton hex_str[0] = *p; 28160603aa9dSGreg Clayton if (isxdigit(p[1])) 28170603aa9dSGreg Clayton { 28180603aa9dSGreg Clayton ++p; // Skip the first of the two hex chars 28191b654882SGreg Clayton hex_str[1] = *p; 28200603aa9dSGreg Clayton } 28210603aa9dSGreg Clayton 28221b654882SGreg Clayton unsigned long hex_value = strtoul (hex_str, NULL, 16); 28230603aa9dSGreg Clayton if (hex_value <= UINT8_MAX) 2824c7bece56SGreg Clayton s.PutChar ((char)hex_value); 28251b654882SGreg Clayton } 28261b654882SGreg Clayton else 28271b654882SGreg Clayton { 28280603aa9dSGreg Clayton s.PutChar('x'); 28291b654882SGreg Clayton } 28301b654882SGreg Clayton break; 28311b654882SGreg Clayton 28321b654882SGreg Clayton default: 28330603aa9dSGreg Clayton // Just desensitize any other character by just printing what 28340603aa9dSGreg Clayton // came after the '\' 28350603aa9dSGreg Clayton s << *p; 28361b654882SGreg Clayton break; 28371b654882SGreg Clayton 28381b654882SGreg Clayton } 28391b654882SGreg Clayton 28401b654882SGreg Clayton } 28411b654882SGreg Clayton } 28421b654882SGreg Clayton if (end) 28431b654882SGreg Clayton *end = p; 28441b654882SGreg Clayton return success; 28451b654882SGreg Clayton } 28461b654882SGreg Clayton 2847c3ce7f27SMichael Sartain bool 2848c3ce7f27SMichael Sartain Debugger::FormatPrompt 2849c3ce7f27SMichael Sartain ( 2850c3ce7f27SMichael Sartain const char *format, 2851c3ce7f27SMichael Sartain const SymbolContext *sc, 2852c3ce7f27SMichael Sartain const ExecutionContext *exe_ctx, 2853c3ce7f27SMichael Sartain const Address *addr, 2854c3ce7f27SMichael Sartain Stream &s, 2855c3ce7f27SMichael Sartain ValueObject* valobj 2856c3ce7f27SMichael Sartain ) 2857c3ce7f27SMichael Sartain { 2858c3ce7f27SMichael Sartain bool use_color = exe_ctx ? exe_ctx->GetTargetRef().GetDebugger().GetUseColor() : true; 2859c3ce7f27SMichael Sartain std::string format_str = lldb_utility::ansi::FormatAnsiTerminalCodes (format, use_color); 2860c3ce7f27SMichael Sartain if (format_str.length()) 2861c3ce7f27SMichael Sartain format = format_str.c_str(); 2862aff1b357SJason Molenda return FormatPromptRecurse (format, sc, exe_ctx, addr, s, NULL, valobj, false, false); 2863c3ce7f27SMichael Sartain } 2864c3ce7f27SMichael Sartain 2865aff1b357SJason Molenda bool 2866aff1b357SJason Molenda Debugger::FormatDisassemblerAddress (const char *format, 2867aff1b357SJason Molenda const SymbolContext *sc, 2868aff1b357SJason Molenda const SymbolContext *prev_sc, 2869aff1b357SJason Molenda const ExecutionContext *exe_ctx, 2870aff1b357SJason Molenda const Address *addr, 2871aff1b357SJason Molenda Stream &s) 2872aff1b357SJason Molenda { 2873aff1b357SJason Molenda if (format == NULL && exe_ctx != NULL && exe_ctx->HasTargetScope()) 2874aff1b357SJason Molenda { 2875aff1b357SJason Molenda format = exe_ctx->GetTargetRef().GetDebugger().GetDisassemblyFormat(); 2876aff1b357SJason Molenda } 2877aff1b357SJason Molenda bool function_changed = false; 2878aff1b357SJason Molenda bool initial_function = false; 2879aff1b357SJason Molenda if (prev_sc && (prev_sc->function || prev_sc->symbol)) 2880aff1b357SJason Molenda { 2881aff1b357SJason Molenda if (sc && (sc->function || sc->symbol)) 2882aff1b357SJason Molenda { 2883aff1b357SJason Molenda if (prev_sc->symbol && sc->symbol) 2884aff1b357SJason Molenda { 2885aff1b357SJason Molenda if (!sc->symbol->Compare (prev_sc->symbol->GetName(), prev_sc->symbol->GetType())) 2886aff1b357SJason Molenda { 2887aff1b357SJason Molenda function_changed = true; 2888aff1b357SJason Molenda } 2889aff1b357SJason Molenda } 2890aff1b357SJason Molenda else if (prev_sc->function && sc->function) 2891aff1b357SJason Molenda { 2892aff1b357SJason Molenda if (prev_sc->function->GetMangled() != sc->function->GetMangled()) 2893aff1b357SJason Molenda { 2894aff1b357SJason Molenda function_changed = true; 2895aff1b357SJason Molenda } 2896aff1b357SJason Molenda } 2897aff1b357SJason Molenda } 2898aff1b357SJason Molenda } 2899aff1b357SJason Molenda // The first context on a list of instructions will have a prev_sc that 2900aff1b357SJason Molenda // has no Function or Symbol -- if SymbolContext had an IsValid() method, it 2901aff1b357SJason Molenda // would return false. But we do get a prev_sc pointer. 2902aff1b357SJason Molenda if ((sc && (sc->function || sc->symbol)) 2903aff1b357SJason Molenda && prev_sc && (prev_sc->function == NULL && prev_sc->symbol == NULL)) 2904aff1b357SJason Molenda { 2905aff1b357SJason Molenda initial_function = true; 2906aff1b357SJason Molenda } 2907aff1b357SJason Molenda return FormatPromptRecurse (format, sc, exe_ctx, addr, s, NULL, NULL, function_changed, initial_function); 2908aff1b357SJason Molenda } 2909aff1b357SJason Molenda 2910aff1b357SJason Molenda 2911228063cdSJim Ingham void 2912228063cdSJim Ingham Debugger::SetLoggingCallback (lldb::LogOutputCallback log_callback, void *baton) 2913228063cdSJim Ingham { 29144f02b22dSJim Ingham // For simplicity's sake, I am not going to deal with how to close down any 29154f02b22dSJim Ingham // open logging streams, I just redirect everything from here on out to the 29164f02b22dSJim Ingham // callback. 2917228063cdSJim Ingham m_log_callback_stream_sp.reset (new StreamCallback (log_callback, baton)); 2918228063cdSJim Ingham } 2919228063cdSJim Ingham 2920228063cdSJim Ingham bool 2921228063cdSJim Ingham Debugger::EnableLog (const char *channel, const char **categories, const char *log_file, uint32_t log_options, Stream &error_stream) 2922228063cdSJim Ingham { 2923228063cdSJim Ingham Log::Callbacks log_callbacks; 2924228063cdSJim Ingham 2925228063cdSJim Ingham StreamSP log_stream_sp; 29269a028519SSean Callanan if (m_log_callback_stream_sp) 2927228063cdSJim Ingham { 2928228063cdSJim Ingham log_stream_sp = m_log_callback_stream_sp; 2929228063cdSJim Ingham // For now when using the callback mode you always get thread & timestamp. 2930228063cdSJim Ingham log_options |= LLDB_LOG_OPTION_PREPEND_TIMESTAMP | LLDB_LOG_OPTION_PREPEND_THREAD_NAME; 2931228063cdSJim Ingham } 2932228063cdSJim Ingham else if (log_file == NULL || *log_file == '\0') 2933228063cdSJim Ingham { 293444d93782SGreg Clayton log_stream_sp = GetOutputFile(); 2935228063cdSJim Ingham } 2936228063cdSJim Ingham else 2937228063cdSJim Ingham { 2938228063cdSJim Ingham LogStreamMap::iterator pos = m_log_streams.find(log_file); 2939c1b2ccfdSGreg Clayton if (pos != m_log_streams.end()) 2940c1b2ccfdSGreg Clayton log_stream_sp = pos->second.lock(); 2941c1b2ccfdSGreg Clayton if (!log_stream_sp) 2942228063cdSJim Ingham { 2943228063cdSJim Ingham log_stream_sp.reset (new StreamFile (log_file)); 2944228063cdSJim Ingham m_log_streams[log_file] = log_stream_sp; 2945228063cdSJim Ingham } 2946228063cdSJim Ingham } 2947228063cdSJim Ingham assert (log_stream_sp.get()); 2948228063cdSJim Ingham 2949228063cdSJim Ingham if (log_options == 0) 2950228063cdSJim Ingham log_options = LLDB_LOG_OPTION_PREPEND_THREAD_NAME | LLDB_LOG_OPTION_THREADSAFE; 2951228063cdSJim Ingham 295257abc5d6SGreg Clayton if (Log::GetLogChannelCallbacks (ConstString(channel), log_callbacks)) 2953228063cdSJim Ingham { 2954228063cdSJim Ingham log_callbacks.enable (log_stream_sp, log_options, categories, &error_stream); 2955228063cdSJim Ingham return true; 2956228063cdSJim Ingham } 2957228063cdSJim Ingham else 2958228063cdSJim Ingham { 2959228063cdSJim Ingham LogChannelSP log_channel_sp (LogChannel::FindPlugin (channel)); 2960228063cdSJim Ingham if (log_channel_sp) 2961228063cdSJim Ingham { 2962228063cdSJim Ingham if (log_channel_sp->Enable (log_stream_sp, log_options, &error_stream, categories)) 2963228063cdSJim Ingham { 2964228063cdSJim Ingham return true; 2965228063cdSJim Ingham } 2966228063cdSJim Ingham else 2967228063cdSJim Ingham { 2968228063cdSJim Ingham error_stream.Printf ("Invalid log channel '%s'.\n", channel); 2969228063cdSJim Ingham return false; 2970228063cdSJim Ingham } 2971228063cdSJim Ingham } 2972228063cdSJim Ingham else 2973228063cdSJim Ingham { 2974228063cdSJim Ingham error_stream.Printf ("Invalid log channel '%s'.\n", channel); 2975228063cdSJim Ingham return false; 2976228063cdSJim Ingham } 2977228063cdSJim Ingham } 2978228063cdSJim Ingham return false; 2979228063cdSJim Ingham } 2980228063cdSJim Ingham 29819585fbfcSGreg Clayton SourceManager & 29829585fbfcSGreg Clayton Debugger::GetSourceManager () 29839585fbfcSGreg Clayton { 29849585fbfcSGreg Clayton if (m_source_manager_ap.get() == NULL) 29859585fbfcSGreg Clayton m_source_manager_ap.reset (new SourceManager (shared_from_this())); 29869585fbfcSGreg Clayton return *m_source_manager_ap; 29879585fbfcSGreg Clayton } 29889585fbfcSGreg Clayton 29899585fbfcSGreg Clayton 299044d93782SGreg Clayton 299144d93782SGreg Clayton // This function handles events that were broadcast by the process. 299244d93782SGreg Clayton void 299344d93782SGreg Clayton Debugger::HandleBreakpointEvent (const EventSP &event_sp) 299444d93782SGreg Clayton { 299544d93782SGreg Clayton using namespace lldb; 299644d93782SGreg Clayton const uint32_t event_type = Breakpoint::BreakpointEventData::GetBreakpointEventTypeFromEvent (event_sp); 299744d93782SGreg Clayton 299844d93782SGreg Clayton // if (event_type & eBreakpointEventTypeAdded 299944d93782SGreg Clayton // || event_type & eBreakpointEventTypeRemoved 300044d93782SGreg Clayton // || event_type & eBreakpointEventTypeEnabled 300144d93782SGreg Clayton // || event_type & eBreakpointEventTypeDisabled 300244d93782SGreg Clayton // || event_type & eBreakpointEventTypeCommandChanged 300344d93782SGreg Clayton // || event_type & eBreakpointEventTypeConditionChanged 300444d93782SGreg Clayton // || event_type & eBreakpointEventTypeIgnoreChanged 300544d93782SGreg Clayton // || event_type & eBreakpointEventTypeLocationsResolved) 300644d93782SGreg Clayton // { 300744d93782SGreg Clayton // // Don't do anything about these events, since the breakpoint commands already echo these actions. 300844d93782SGreg Clayton // } 300944d93782SGreg Clayton // 301044d93782SGreg Clayton if (event_type & eBreakpointEventTypeLocationsAdded) 301144d93782SGreg Clayton { 301244d93782SGreg Clayton uint32_t num_new_locations = Breakpoint::BreakpointEventData::GetNumBreakpointLocationsFromEvent(event_sp); 301344d93782SGreg Clayton if (num_new_locations > 0) 301444d93782SGreg Clayton { 301544d93782SGreg Clayton BreakpointSP breakpoint = Breakpoint::BreakpointEventData::GetBreakpointFromEvent(event_sp); 301644d93782SGreg Clayton StreamFileSP output_sp (GetOutputFile()); 301744d93782SGreg Clayton if (output_sp) 301844d93782SGreg Clayton { 301944d93782SGreg Clayton output_sp->Printf("%d location%s added to breakpoint %d\n", 302044d93782SGreg Clayton num_new_locations, 302144d93782SGreg Clayton num_new_locations == 1 ? "" : "s", 302244d93782SGreg Clayton breakpoint->GetID()); 302344d93782SGreg Clayton RefreshTopIOHandler(); 302444d93782SGreg Clayton } 302544d93782SGreg Clayton } 302644d93782SGreg Clayton } 302744d93782SGreg Clayton // else if (event_type & eBreakpointEventTypeLocationsRemoved) 302844d93782SGreg Clayton // { 302944d93782SGreg Clayton // // These locations just get disabled, not sure it is worth spamming folks about this on the command line. 303044d93782SGreg Clayton // } 303144d93782SGreg Clayton // else if (event_type & eBreakpointEventTypeLocationsResolved) 303244d93782SGreg Clayton // { 303344d93782SGreg Clayton // // This might be an interesting thing to note, but I'm going to leave it quiet for now, it just looked noisy. 303444d93782SGreg Clayton // } 303544d93782SGreg Clayton } 303644d93782SGreg Clayton 303744d93782SGreg Clayton size_t 303844d93782SGreg Clayton Debugger::GetProcessSTDOUT (Process *process, Stream *stream) 303944d93782SGreg Clayton { 304044d93782SGreg Clayton size_t total_bytes = 0; 304144d93782SGreg Clayton if (stream == NULL) 304244d93782SGreg Clayton stream = GetOutputFile().get(); 304344d93782SGreg Clayton 304444d93782SGreg Clayton if (stream) 304544d93782SGreg Clayton { 304644d93782SGreg Clayton // The process has stuff waiting for stdout; get it and write it out to the appropriate place. 304744d93782SGreg Clayton if (process == NULL) 304844d93782SGreg Clayton { 304944d93782SGreg Clayton TargetSP target_sp = GetTargetList().GetSelectedTarget(); 305044d93782SGreg Clayton if (target_sp) 305144d93782SGreg Clayton process = target_sp->GetProcessSP().get(); 305244d93782SGreg Clayton } 305344d93782SGreg Clayton if (process) 305444d93782SGreg Clayton { 305544d93782SGreg Clayton Error error; 305644d93782SGreg Clayton size_t len; 305744d93782SGreg Clayton char stdio_buffer[1024]; 305844d93782SGreg Clayton while ((len = process->GetSTDOUT (stdio_buffer, sizeof (stdio_buffer), error)) > 0) 305944d93782SGreg Clayton { 306044d93782SGreg Clayton stream->Write(stdio_buffer, len); 306144d93782SGreg Clayton total_bytes += len; 306244d93782SGreg Clayton } 306344d93782SGreg Clayton } 306444d93782SGreg Clayton stream->Flush(); 306544d93782SGreg Clayton } 306644d93782SGreg Clayton return total_bytes; 306744d93782SGreg Clayton } 306844d93782SGreg Clayton 306944d93782SGreg Clayton size_t 307044d93782SGreg Clayton Debugger::GetProcessSTDERR (Process *process, Stream *stream) 307144d93782SGreg Clayton { 307244d93782SGreg Clayton size_t total_bytes = 0; 307344d93782SGreg Clayton if (stream == NULL) 307444d93782SGreg Clayton stream = GetOutputFile().get(); 307544d93782SGreg Clayton 307644d93782SGreg Clayton if (stream) 307744d93782SGreg Clayton { 307844d93782SGreg Clayton // The process has stuff waiting for stderr; get it and write it out to the appropriate place. 307944d93782SGreg Clayton if (process == NULL) 308044d93782SGreg Clayton { 308144d93782SGreg Clayton TargetSP target_sp = GetTargetList().GetSelectedTarget(); 308244d93782SGreg Clayton if (target_sp) 308344d93782SGreg Clayton process = target_sp->GetProcessSP().get(); 308444d93782SGreg Clayton } 308544d93782SGreg Clayton if (process) 308644d93782SGreg Clayton { 308744d93782SGreg Clayton Error error; 308844d93782SGreg Clayton size_t len; 308944d93782SGreg Clayton char stdio_buffer[1024]; 309044d93782SGreg Clayton while ((len = process->GetSTDERR (stdio_buffer, sizeof (stdio_buffer), error)) > 0) 309144d93782SGreg Clayton { 309244d93782SGreg Clayton stream->Write(stdio_buffer, len); 309344d93782SGreg Clayton total_bytes += len; 309444d93782SGreg Clayton } 309544d93782SGreg Clayton } 309644d93782SGreg Clayton stream->Flush(); 309744d93782SGreg Clayton } 309844d93782SGreg Clayton return total_bytes; 309944d93782SGreg Clayton } 310044d93782SGreg Clayton 310144d93782SGreg Clayton // This function handles events that were broadcast by the process. 310244d93782SGreg Clayton void 310344d93782SGreg Clayton Debugger::HandleProcessEvent (const EventSP &event_sp) 310444d93782SGreg Clayton { 310544d93782SGreg Clayton using namespace lldb; 310644d93782SGreg Clayton const uint32_t event_type = event_sp->GetType(); 310744d93782SGreg Clayton ProcessSP process_sp = Process::ProcessEventData::GetProcessFromEvent(event_sp.get()); 310844d93782SGreg Clayton 3109b4874f1aSGreg Clayton StreamString output_stream; 3110b4874f1aSGreg Clayton StreamString error_stream; 311144d93782SGreg Clayton const bool gui_enabled = IsForwardingEvents(); 311244d93782SGreg Clayton 3113b4874f1aSGreg Clayton if (!gui_enabled) 3114b4874f1aSGreg Clayton { 3115b4874f1aSGreg Clayton bool pop_process_io_handler = false; 311644d93782SGreg Clayton assert (process_sp); 311744d93782SGreg Clayton 3118b4874f1aSGreg Clayton if (event_type & Process::eBroadcastBitSTDOUT || event_type & Process::eBroadcastBitStateChanged) 311944d93782SGreg Clayton { 3120b4874f1aSGreg Clayton GetProcessSTDOUT (process_sp.get(), &output_stream); 312144d93782SGreg Clayton } 3122b4874f1aSGreg Clayton 3123b4874f1aSGreg Clayton if (event_type & Process::eBroadcastBitSTDERR || event_type & Process::eBroadcastBitStateChanged) 312444d93782SGreg Clayton { 3125b4874f1aSGreg Clayton GetProcessSTDERR (process_sp.get(), &error_stream); 312644d93782SGreg Clayton } 3127b4874f1aSGreg Clayton 3128b4874f1aSGreg Clayton if (event_type & Process::eBroadcastBitStateChanged) 312944d93782SGreg Clayton { 3130b4874f1aSGreg Clayton 313144d93782SGreg Clayton // Drain all stout and stderr so we don't see any output come after 313244d93782SGreg Clayton // we print our prompts 313344d93782SGreg Clayton // Something changed in the process; get the event and report the process's current status and location to 313444d93782SGreg Clayton // the user. 313544d93782SGreg Clayton StateType event_state = Process::ProcessEventData::GetStateFromEvent (event_sp.get()); 313644d93782SGreg Clayton if (event_state == eStateInvalid) 313744d93782SGreg Clayton return; 313844d93782SGreg Clayton 313944d93782SGreg Clayton switch (event_state) 314044d93782SGreg Clayton { 314144d93782SGreg Clayton case eStateInvalid: 314244d93782SGreg Clayton case eStateUnloaded: 314344d93782SGreg Clayton case eStateConnected: 314444d93782SGreg Clayton case eStateAttaching: 314544d93782SGreg Clayton case eStateLaunching: 314644d93782SGreg Clayton case eStateStepping: 314744d93782SGreg Clayton case eStateDetached: 314844d93782SGreg Clayton { 3149b4874f1aSGreg Clayton output_stream.Printf("Process %" PRIu64 " %s\n", 315044d93782SGreg Clayton process_sp->GetID(), 315144d93782SGreg Clayton StateAsCString (event_state)); 3152b4874f1aSGreg Clayton 3153b4874f1aSGreg Clayton if (event_state == eStateDetached) 3154b4874f1aSGreg Clayton pop_process_io_handler = true; 315544d93782SGreg Clayton } 315644d93782SGreg Clayton break; 315744d93782SGreg Clayton 315844d93782SGreg Clayton case eStateRunning: 315944d93782SGreg Clayton // Don't be chatty when we run... 316044d93782SGreg Clayton break; 316144d93782SGreg Clayton 316244d93782SGreg Clayton case eStateExited: 3163b4874f1aSGreg Clayton process_sp->GetStatus(output_stream); 3164b4874f1aSGreg Clayton pop_process_io_handler = true; 316544d93782SGreg Clayton break; 316644d93782SGreg Clayton 316744d93782SGreg Clayton case eStateStopped: 316844d93782SGreg Clayton case eStateCrashed: 316944d93782SGreg Clayton case eStateSuspended: 317044d93782SGreg Clayton // Make sure the program hasn't been auto-restarted: 317144d93782SGreg Clayton if (Process::ProcessEventData::GetRestartedFromEvent (event_sp.get())) 317244d93782SGreg Clayton { 317344d93782SGreg Clayton size_t num_reasons = Process::ProcessEventData::GetNumRestartedReasons(event_sp.get()); 317444d93782SGreg Clayton if (num_reasons > 0) 317544d93782SGreg Clayton { 317644d93782SGreg Clayton // FIXME: Do we want to report this, or would that just be annoyingly chatty? 317744d93782SGreg Clayton if (num_reasons == 1) 317844d93782SGreg Clayton { 317944d93782SGreg Clayton const char *reason = Process::ProcessEventData::GetRestartedReasonAtIndex (event_sp.get(), 0); 3180b4874f1aSGreg Clayton output_stream.Printf("Process %" PRIu64 " stopped and restarted: %s\n", 318144d93782SGreg Clayton process_sp->GetID(), 318244d93782SGreg Clayton reason ? reason : "<UNKNOWN REASON>"); 318344d93782SGreg Clayton } 318444d93782SGreg Clayton else 318544d93782SGreg Clayton { 3186b4874f1aSGreg Clayton output_stream.Printf("Process %" PRIu64 " stopped and restarted, reasons:\n", 318744d93782SGreg Clayton process_sp->GetID()); 318844d93782SGreg Clayton 318944d93782SGreg Clayton 319044d93782SGreg Clayton for (size_t i = 0; i < num_reasons; i++) 319144d93782SGreg Clayton { 319244d93782SGreg Clayton const char *reason = Process::ProcessEventData::GetRestartedReasonAtIndex (event_sp.get(), i); 3193b4874f1aSGreg Clayton output_stream.Printf("\t%s\n", reason ? reason : "<UNKNOWN REASON>"); 319444d93782SGreg Clayton } 319544d93782SGreg Clayton } 319644d93782SGreg Clayton } 319744d93782SGreg Clayton } 319844d93782SGreg Clayton else 319944d93782SGreg Clayton { 32004a65fb1fSJim Ingham // Lock the thread list so it doesn't change on us, this is the scope for the locker: 32014a65fb1fSJim Ingham { 320244d93782SGreg Clayton ThreadList &thread_list = process_sp->GetThreadList(); 320344d93782SGreg Clayton Mutex::Locker locker (thread_list.GetMutex()); 320444d93782SGreg Clayton 320544d93782SGreg Clayton ThreadSP curr_thread (thread_list.GetSelectedThread()); 320644d93782SGreg Clayton ThreadSP thread; 320744d93782SGreg Clayton StopReason curr_thread_stop_reason = eStopReasonInvalid; 320844d93782SGreg Clayton if (curr_thread) 320944d93782SGreg Clayton curr_thread_stop_reason = curr_thread->GetStopReason(); 3210c809cbcfSGreg Clayton if (!curr_thread || 3211c809cbcfSGreg Clayton !curr_thread->IsValid() || 321244d93782SGreg Clayton curr_thread_stop_reason == eStopReasonInvalid || 321344d93782SGreg Clayton curr_thread_stop_reason == eStopReasonNone) 321444d93782SGreg Clayton { 321544d93782SGreg Clayton // Prefer a thread that has just completed its plan over another thread as current thread. 321644d93782SGreg Clayton ThreadSP plan_thread; 321744d93782SGreg Clayton ThreadSP other_thread; 321844d93782SGreg Clayton const size_t num_threads = thread_list.GetSize(); 321944d93782SGreg Clayton size_t i; 322044d93782SGreg Clayton for (i = 0; i < num_threads; ++i) 322144d93782SGreg Clayton { 322244d93782SGreg Clayton thread = thread_list.GetThreadAtIndex(i); 322344d93782SGreg Clayton StopReason thread_stop_reason = thread->GetStopReason(); 322444d93782SGreg Clayton switch (thread_stop_reason) 322544d93782SGreg Clayton { 322644d93782SGreg Clayton case eStopReasonInvalid: 322744d93782SGreg Clayton case eStopReasonNone: 322844d93782SGreg Clayton break; 322944d93782SGreg Clayton 323044d93782SGreg Clayton case eStopReasonTrace: 323144d93782SGreg Clayton case eStopReasonBreakpoint: 323244d93782SGreg Clayton case eStopReasonWatchpoint: 323344d93782SGreg Clayton case eStopReasonSignal: 323444d93782SGreg Clayton case eStopReasonException: 323544d93782SGreg Clayton case eStopReasonExec: 323644d93782SGreg Clayton case eStopReasonThreadExiting: 3237afdf842bSKuba Brecka case eStopReasonInstrumentation: 323844d93782SGreg Clayton if (!other_thread) 323944d93782SGreg Clayton other_thread = thread; 324044d93782SGreg Clayton break; 324144d93782SGreg Clayton case eStopReasonPlanComplete: 324244d93782SGreg Clayton if (!plan_thread) 324344d93782SGreg Clayton plan_thread = thread; 324444d93782SGreg Clayton break; 324544d93782SGreg Clayton } 324644d93782SGreg Clayton } 324744d93782SGreg Clayton if (plan_thread) 324844d93782SGreg Clayton thread_list.SetSelectedThreadByID (plan_thread->GetID()); 324944d93782SGreg Clayton else if (other_thread) 325044d93782SGreg Clayton thread_list.SetSelectedThreadByID (other_thread->GetID()); 325144d93782SGreg Clayton else 325244d93782SGreg Clayton { 32534046a30cSJim Ingham if (curr_thread && curr_thread->IsValid()) 325444d93782SGreg Clayton thread = curr_thread; 325544d93782SGreg Clayton else 325644d93782SGreg Clayton thread = thread_list.GetThreadAtIndex(0); 325744d93782SGreg Clayton 325844d93782SGreg Clayton if (thread) 325944d93782SGreg Clayton thread_list.SetSelectedThreadByID (thread->GetID()); 326044d93782SGreg Clayton } 326144d93782SGreg Clayton } 32624a65fb1fSJim Ingham } 32634a65fb1fSJim Ingham // Drop the ThreadList mutex by here, since GetThreadStatus below might have to run code, 32644a65fb1fSJim Ingham // e.g. for Data formatters, and if we hold the ThreadList mutex, then the process is going to 32654a65fb1fSJim Ingham // have a hard time restarting the process. 326644d93782SGreg Clayton 326744d93782SGreg Clayton if (GetTargetList().GetSelectedTarget().get() == &process_sp->GetTarget()) 326844d93782SGreg Clayton { 326944d93782SGreg Clayton const bool only_threads_with_stop_reason = true; 327044d93782SGreg Clayton const uint32_t start_frame = 0; 327144d93782SGreg Clayton const uint32_t num_frames = 1; 327244d93782SGreg Clayton const uint32_t num_frames_with_source = 1; 3273b4874f1aSGreg Clayton process_sp->GetStatus(output_stream); 3274b4874f1aSGreg Clayton process_sp->GetThreadStatus (output_stream, 327544d93782SGreg Clayton only_threads_with_stop_reason, 327644d93782SGreg Clayton start_frame, 327744d93782SGreg Clayton num_frames, 327844d93782SGreg Clayton num_frames_with_source); 327944d93782SGreg Clayton } 328044d93782SGreg Clayton else 328144d93782SGreg Clayton { 328244d93782SGreg Clayton uint32_t target_idx = GetTargetList().GetIndexOfTarget(process_sp->GetTarget().shared_from_this()); 328344d93782SGreg Clayton if (target_idx != UINT32_MAX) 3284b4874f1aSGreg Clayton output_stream.Printf ("Target %d: (", target_idx); 328544d93782SGreg Clayton else 3286b4874f1aSGreg Clayton output_stream.Printf ("Target <unknown index>: ("); 3287b4874f1aSGreg Clayton process_sp->GetTarget().Dump (&output_stream, eDescriptionLevelBrief); 3288b4874f1aSGreg Clayton output_stream.Printf (") stopped.\n"); 328944d93782SGreg Clayton } 3290b4874f1aSGreg Clayton 3291b4874f1aSGreg Clayton // Pop the process IO handler 3292b4874f1aSGreg Clayton pop_process_io_handler = true; 329344d93782SGreg Clayton } 329444d93782SGreg Clayton break; 329544d93782SGreg Clayton } 329644d93782SGreg Clayton } 3297b4874f1aSGreg Clayton 3298b4874f1aSGreg Clayton if (output_stream.GetSize() || error_stream.GetSize()) 3299b4874f1aSGreg Clayton { 3300b4874f1aSGreg Clayton StreamFileSP error_stream_sp (GetOutputFile()); 33016fea17e8SGreg Clayton bool top_io_handler_hid = false; 33026fea17e8SGreg Clayton 33036fea17e8SGreg Clayton if (process_sp->ProcessIOHandlerIsActive() == false) 33046fea17e8SGreg Clayton top_io_handler_hid = HideTopIOHandler(); 3305b4874f1aSGreg Clayton 3306b4874f1aSGreg Clayton if (output_stream.GetSize()) 3307b4874f1aSGreg Clayton { 3308b4874f1aSGreg Clayton StreamFileSP output_stream_sp (GetOutputFile()); 3309b4874f1aSGreg Clayton if (output_stream_sp) 3310b4874f1aSGreg Clayton output_stream_sp->Write (output_stream.GetData(), output_stream.GetSize()); 3311b4874f1aSGreg Clayton } 3312b4874f1aSGreg Clayton 3313b4874f1aSGreg Clayton if (error_stream.GetSize()) 3314b4874f1aSGreg Clayton { 3315b4874f1aSGreg Clayton StreamFileSP error_stream_sp (GetErrorFile()); 3316b4874f1aSGreg Clayton if (error_stream_sp) 3317b4874f1aSGreg Clayton error_stream_sp->Write (error_stream.GetData(), error_stream.GetSize()); 331844d93782SGreg Clayton } 331944d93782SGreg Clayton 332044d93782SGreg Clayton if (top_io_handler_hid) 332144d93782SGreg Clayton RefreshTopIOHandler(); 332244d93782SGreg Clayton } 332344d93782SGreg Clayton 3324b4874f1aSGreg Clayton if (pop_process_io_handler) 3325b4874f1aSGreg Clayton process_sp->PopProcessIOHandler(); 3326b4874f1aSGreg Clayton } 3327b4874f1aSGreg Clayton } 3328b4874f1aSGreg Clayton 332944d93782SGreg Clayton void 333044d93782SGreg Clayton Debugger::HandleThreadEvent (const EventSP &event_sp) 333144d93782SGreg Clayton { 333244d93782SGreg Clayton // At present the only thread event we handle is the Frame Changed event, 333344d93782SGreg Clayton // and all we do for that is just reprint the thread status for that thread. 333444d93782SGreg Clayton using namespace lldb; 333544d93782SGreg Clayton const uint32_t event_type = event_sp->GetType(); 333644d93782SGreg Clayton if (event_type == Thread::eBroadcastBitStackChanged || 333744d93782SGreg Clayton event_type == Thread::eBroadcastBitThreadSelected ) 333844d93782SGreg Clayton { 333944d93782SGreg Clayton ThreadSP thread_sp (Thread::ThreadEventData::GetThreadFromEvent (event_sp.get())); 334044d93782SGreg Clayton if (thread_sp) 334144d93782SGreg Clayton { 334244d93782SGreg Clayton HideTopIOHandler(); 334344d93782SGreg Clayton StreamFileSP stream_sp (GetOutputFile()); 334444d93782SGreg Clayton thread_sp->GetStatus(*stream_sp, 0, 1, 1); 334544d93782SGreg Clayton RefreshTopIOHandler(); 334644d93782SGreg Clayton } 334744d93782SGreg Clayton } 334844d93782SGreg Clayton } 334944d93782SGreg Clayton 335044d93782SGreg Clayton bool 335144d93782SGreg Clayton Debugger::IsForwardingEvents () 335244d93782SGreg Clayton { 335344d93782SGreg Clayton return (bool)m_forward_listener_sp; 335444d93782SGreg Clayton } 335544d93782SGreg Clayton 335644d93782SGreg Clayton void 335744d93782SGreg Clayton Debugger::EnableForwardEvents (const ListenerSP &listener_sp) 335844d93782SGreg Clayton { 335944d93782SGreg Clayton m_forward_listener_sp = listener_sp; 336044d93782SGreg Clayton } 336144d93782SGreg Clayton 336244d93782SGreg Clayton void 336344d93782SGreg Clayton Debugger::CancelForwardEvents (const ListenerSP &listener_sp) 336444d93782SGreg Clayton { 336544d93782SGreg Clayton m_forward_listener_sp.reset(); 336644d93782SGreg Clayton } 336744d93782SGreg Clayton 336844d93782SGreg Clayton 336944d93782SGreg Clayton void 337044d93782SGreg Clayton Debugger::DefaultEventHandler() 337144d93782SGreg Clayton { 337244d93782SGreg Clayton Listener& listener(GetListener()); 337344d93782SGreg Clayton ConstString broadcaster_class_target(Target::GetStaticBroadcasterClass()); 337444d93782SGreg Clayton ConstString broadcaster_class_process(Process::GetStaticBroadcasterClass()); 337544d93782SGreg Clayton ConstString broadcaster_class_thread(Thread::GetStaticBroadcasterClass()); 337644d93782SGreg Clayton BroadcastEventSpec target_event_spec (broadcaster_class_target, 337744d93782SGreg Clayton Target::eBroadcastBitBreakpointChanged); 337844d93782SGreg Clayton 337944d93782SGreg Clayton BroadcastEventSpec process_event_spec (broadcaster_class_process, 338044d93782SGreg Clayton Process::eBroadcastBitStateChanged | 338144d93782SGreg Clayton Process::eBroadcastBitSTDOUT | 338244d93782SGreg Clayton Process::eBroadcastBitSTDERR); 338344d93782SGreg Clayton 338444d93782SGreg Clayton BroadcastEventSpec thread_event_spec (broadcaster_class_thread, 338544d93782SGreg Clayton Thread::eBroadcastBitStackChanged | 338644d93782SGreg Clayton Thread::eBroadcastBitThreadSelected ); 338744d93782SGreg Clayton 338844d93782SGreg Clayton listener.StartListeningForEventSpec (*this, target_event_spec); 338944d93782SGreg Clayton listener.StartListeningForEventSpec (*this, process_event_spec); 339044d93782SGreg Clayton listener.StartListeningForEventSpec (*this, thread_event_spec); 339144d93782SGreg Clayton listener.StartListeningForEvents (m_command_interpreter_ap.get(), 339244d93782SGreg Clayton CommandInterpreter::eBroadcastBitQuitCommandReceived | 339344d93782SGreg Clayton CommandInterpreter::eBroadcastBitAsynchronousOutputData | 339444d93782SGreg Clayton CommandInterpreter::eBroadcastBitAsynchronousErrorData ); 339544d93782SGreg Clayton 339644d93782SGreg Clayton bool done = false; 339744d93782SGreg Clayton while (!done) 339844d93782SGreg Clayton { 339944d93782SGreg Clayton // Mutex::Locker locker; 340044d93782SGreg Clayton // if (locker.TryLock(m_input_reader_stack.GetMutex())) 340144d93782SGreg Clayton // { 340244d93782SGreg Clayton // if (m_input_reader_stack.IsEmpty()) 340344d93782SGreg Clayton // break; 340444d93782SGreg Clayton // } 340544d93782SGreg Clayton // 340644d93782SGreg Clayton EventSP event_sp; 340744d93782SGreg Clayton if (listener.WaitForEvent(NULL, event_sp)) 340844d93782SGreg Clayton { 340944d93782SGreg Clayton if (event_sp) 341044d93782SGreg Clayton { 341144d93782SGreg Clayton Broadcaster *broadcaster = event_sp->GetBroadcaster(); 341244d93782SGreg Clayton if (broadcaster) 341344d93782SGreg Clayton { 341444d93782SGreg Clayton uint32_t event_type = event_sp->GetType(); 341544d93782SGreg Clayton ConstString broadcaster_class (broadcaster->GetBroadcasterClass()); 341644d93782SGreg Clayton if (broadcaster_class == broadcaster_class_process) 341744d93782SGreg Clayton { 341844d93782SGreg Clayton HandleProcessEvent (event_sp); 341944d93782SGreg Clayton } 342044d93782SGreg Clayton else if (broadcaster_class == broadcaster_class_target) 342144d93782SGreg Clayton { 342244d93782SGreg Clayton if (Breakpoint::BreakpointEventData::GetEventDataFromEvent(event_sp.get())) 342344d93782SGreg Clayton { 342444d93782SGreg Clayton HandleBreakpointEvent (event_sp); 342544d93782SGreg Clayton } 342644d93782SGreg Clayton } 342744d93782SGreg Clayton else if (broadcaster_class == broadcaster_class_thread) 342844d93782SGreg Clayton { 342944d93782SGreg Clayton HandleThreadEvent (event_sp); 343044d93782SGreg Clayton } 343144d93782SGreg Clayton else if (broadcaster == m_command_interpreter_ap.get()) 343244d93782SGreg Clayton { 343344d93782SGreg Clayton if (event_type & CommandInterpreter::eBroadcastBitQuitCommandReceived) 343444d93782SGreg Clayton { 343544d93782SGreg Clayton done = true; 343644d93782SGreg Clayton } 343744d93782SGreg Clayton else if (event_type & CommandInterpreter::eBroadcastBitAsynchronousErrorData) 343844d93782SGreg Clayton { 343944d93782SGreg Clayton const char *data = reinterpret_cast<const char *>(EventDataBytes::GetBytesFromEvent (event_sp.get())); 344044d93782SGreg Clayton if (data && data[0]) 344144d93782SGreg Clayton { 344244d93782SGreg Clayton StreamFileSP error_sp (GetErrorFile()); 344344d93782SGreg Clayton if (error_sp) 344444d93782SGreg Clayton { 344544d93782SGreg Clayton HideTopIOHandler(); 344644d93782SGreg Clayton error_sp->PutCString(data); 344744d93782SGreg Clayton error_sp->Flush(); 344844d93782SGreg Clayton RefreshTopIOHandler(); 344944d93782SGreg Clayton } 345044d93782SGreg Clayton } 345144d93782SGreg Clayton } 345244d93782SGreg Clayton else if (event_type & CommandInterpreter::eBroadcastBitAsynchronousOutputData) 345344d93782SGreg Clayton { 345444d93782SGreg Clayton const char *data = reinterpret_cast<const char *>(EventDataBytes::GetBytesFromEvent (event_sp.get())); 345544d93782SGreg Clayton if (data && data[0]) 345644d93782SGreg Clayton { 345744d93782SGreg Clayton StreamFileSP output_sp (GetOutputFile()); 345844d93782SGreg Clayton if (output_sp) 345944d93782SGreg Clayton { 346044d93782SGreg Clayton HideTopIOHandler(); 346144d93782SGreg Clayton output_sp->PutCString(data); 346244d93782SGreg Clayton output_sp->Flush(); 346344d93782SGreg Clayton RefreshTopIOHandler(); 346444d93782SGreg Clayton } 346544d93782SGreg Clayton } 346644d93782SGreg Clayton } 346744d93782SGreg Clayton } 346844d93782SGreg Clayton } 346944d93782SGreg Clayton 347044d93782SGreg Clayton if (m_forward_listener_sp) 347144d93782SGreg Clayton m_forward_listener_sp->AddEvent(event_sp); 347244d93782SGreg Clayton } 347344d93782SGreg Clayton } 347444d93782SGreg Clayton } 347544d93782SGreg Clayton } 347644d93782SGreg Clayton 347744d93782SGreg Clayton lldb::thread_result_t 347844d93782SGreg Clayton Debugger::EventHandlerThread (lldb::thread_arg_t arg) 347944d93782SGreg Clayton { 348044d93782SGreg Clayton ((Debugger *)arg)->DefaultEventHandler(); 348144d93782SGreg Clayton return NULL; 348244d93782SGreg Clayton } 348344d93782SGreg Clayton 348444d93782SGreg Clayton bool 348544d93782SGreg Clayton Debugger::StartEventHandlerThread() 348644d93782SGreg Clayton { 3487acee96aeSZachary Turner if (!m_event_handler_thread.IsJoinable()) 348839de3110SZachary Turner m_event_handler_thread = ThreadLauncher::LaunchThread("lldb.debugger.event-handler", EventHandlerThread, this, NULL); 3489acee96aeSZachary Turner return m_event_handler_thread.IsJoinable(); 349044d93782SGreg Clayton } 349144d93782SGreg Clayton 349244d93782SGreg Clayton void 349344d93782SGreg Clayton Debugger::StopEventHandlerThread() 349444d93782SGreg Clayton { 3495acee96aeSZachary Turner if (m_event_handler_thread.IsJoinable()) 349644d93782SGreg Clayton { 349744d93782SGreg Clayton GetCommandInterpreter().BroadcastEvent(CommandInterpreter::eBroadcastBitQuitCommandReceived); 349839de3110SZachary Turner m_event_handler_thread.Join(nullptr); 349944d93782SGreg Clayton } 350044d93782SGreg Clayton } 350144d93782SGreg Clayton 350244d93782SGreg Clayton 350344d93782SGreg Clayton lldb::thread_result_t 350444d93782SGreg Clayton Debugger::IOHandlerThread (lldb::thread_arg_t arg) 350544d93782SGreg Clayton { 350644d93782SGreg Clayton Debugger *debugger = (Debugger *)arg; 350744d93782SGreg Clayton debugger->ExecuteIOHanders(); 350844d93782SGreg Clayton debugger->StopEventHandlerThread(); 350944d93782SGreg Clayton return NULL; 351044d93782SGreg Clayton } 351144d93782SGreg Clayton 351244d93782SGreg Clayton bool 351344d93782SGreg Clayton Debugger::StartIOHandlerThread() 351444d93782SGreg Clayton { 3515acee96aeSZachary Turner if (!m_io_handler_thread.IsJoinable()) 351639de3110SZachary Turner m_io_handler_thread = ThreadLauncher::LaunchThread("lldb.debugger.io-handler", IOHandlerThread, this, NULL); 3517acee96aeSZachary Turner return m_io_handler_thread.IsJoinable(); 351844d93782SGreg Clayton } 351944d93782SGreg Clayton 352044d93782SGreg Clayton void 352144d93782SGreg Clayton Debugger::StopIOHandlerThread() 352244d93782SGreg Clayton { 3523acee96aeSZachary Turner if (m_io_handler_thread.IsJoinable()) 352444d93782SGreg Clayton { 352544d93782SGreg Clayton if (m_input_file_sp) 352644d93782SGreg Clayton m_input_file_sp->GetFile().Close(); 352739de3110SZachary Turner m_io_handler_thread.Join(nullptr); 352844d93782SGreg Clayton } 352944d93782SGreg Clayton } 353044d93782SGreg Clayton 353144d93782SGreg Clayton 3532