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" 18*705b1809SJason Molenda #include "llvm/ADT/StringRef.h" 194becb37eSEnrico Granata 2030fdc8d8SChris Lattner #include "lldb/lldb-private.h" 2130fdc8d8SChris Lattner #include "lldb/Core/ConnectionFileDescriptor.h" 221f746071SGreg Clayton #include "lldb/Core/Module.h" 23e8cd0c98SGreg Clayton #include "lldb/Core/PluginManager.h" 247349bd90SGreg Clayton #include "lldb/Core/RegisterValue.h" 2530fdc8d8SChris Lattner #include "lldb/Core/State.h" 265b52f0c7SJim Ingham #include "lldb/Core/StreamAsynchronousIO.h" 27228063cdSJim Ingham #include "lldb/Core/StreamCallback.h" 2844d93782SGreg Clayton #include "lldb/Core/StreamFile.h" 291b654882SGreg Clayton #include "lldb/Core/StreamString.h" 30*705b1809SJason Molenda #include "lldb/Core/StructuredData.h" 3130fdc8d8SChris Lattner #include "lldb/Core/Timer.h" 324becb37eSEnrico Granata #include "lldb/Core/ValueObject.h" 336d3dbf51SGreg Clayton #include "lldb/Core/ValueObjectVariable.h" 345548cb50SEnrico Granata #include "lldb/DataFormatters/DataVisualization.h" 355548cb50SEnrico Granata #include "lldb/DataFormatters/FormatManager.h" 36894f7359SEnrico Granata #include "lldb/DataFormatters/TypeSummary.h" 3721dfcd9dSEnrico Granata #include "lldb/Host/DynamicLibrary.h" 38a3406614SGreg Clayton #include "lldb/Host/Terminal.h" 396611103cSGreg Clayton #include "lldb/Interpreter/CommandInterpreter.h" 4067cc0636SGreg Clayton #include "lldb/Interpreter/OptionValueSInt64.h" 4167cc0636SGreg Clayton #include "lldb/Interpreter/OptionValueString.h" 421f746071SGreg Clayton #include "lldb/Symbol/ClangASTContext.h" 431f746071SGreg Clayton #include "lldb/Symbol/CompileUnit.h" 441f746071SGreg Clayton #include "lldb/Symbol/Function.h" 451f746071SGreg Clayton #include "lldb/Symbol/Symbol.h" 466d3dbf51SGreg Clayton #include "lldb/Symbol/VariableList.h" 4730fdc8d8SChris Lattner #include "lldb/Target/TargetList.h" 4830fdc8d8SChris Lattner #include "lldb/Target/Process.h" 491b654882SGreg Clayton #include "lldb/Target/RegisterContext.h" 505fb8f797SGreg Clayton #include "lldb/Target/SectionLoadList.h" 511b654882SGreg Clayton #include "lldb/Target/StopInfo.h" 5284a53dfbSEnrico Granata #include "lldb/Target/Target.h" 5330fdc8d8SChris Lattner #include "lldb/Target/Thread.h" 545a31471eSGreg Clayton #include "lldb/Utility/AnsiTerminal.h" 5530fdc8d8SChris Lattner 5630fdc8d8SChris Lattner using namespace lldb; 5730fdc8d8SChris Lattner using namespace lldb_private; 5830fdc8d8SChris Lattner 5930fdc8d8SChris Lattner 601b654882SGreg Clayton static uint32_t g_shared_debugger_refcount = 0; 61ebc1bb27SCaroline Tice static lldb::user_id_t g_unique_id = 1; 62ebc1bb27SCaroline Tice 631b654882SGreg Clayton #pragma mark Static Functions 641b654882SGreg Clayton 651b654882SGreg Clayton static Mutex & 661b654882SGreg Clayton GetDebuggerListMutex () 671b654882SGreg Clayton { 681b654882SGreg Clayton static Mutex g_mutex(Mutex::eMutexTypeRecursive); 691b654882SGreg Clayton return g_mutex; 701b654882SGreg Clayton } 711b654882SGreg Clayton 721b654882SGreg Clayton typedef std::vector<DebuggerSP> DebuggerList; 731b654882SGreg Clayton 741b654882SGreg Clayton static DebuggerList & 751b654882SGreg Clayton GetDebuggerList() 761b654882SGreg Clayton { 771b654882SGreg Clayton // hide the static debugger list inside a singleton accessor to avoid 781b654882SGreg Clayton // global init contructors 791b654882SGreg Clayton static DebuggerList g_list; 801b654882SGreg Clayton return g_list; 811b654882SGreg Clayton } 82e372b98dSGreg Clayton 83e372b98dSGreg Clayton OptionEnumValueElement 8467cc0636SGreg Clayton g_show_disassembly_enum_values[] = 85e372b98dSGreg Clayton { 8667cc0636SGreg Clayton { Debugger::eStopDisassemblyTypeNever, "never", "Never show disassembly when displaying a stop context."}, 8767cc0636SGreg Clayton { Debugger::eStopDisassemblyTypeNoSource, "no-source", "Show disassembly when there is no source information, or the source file is missing when displaying a stop context."}, 8867cc0636SGreg Clayton { Debugger::eStopDisassemblyTypeAlways, "always", "Always show disassembly when displaying a stop context."}, 89e372b98dSGreg Clayton { 0, NULL, NULL } 90e372b98dSGreg Clayton }; 91e372b98dSGreg Clayton 9267cc0636SGreg Clayton OptionEnumValueElement 9367cc0636SGreg Clayton g_language_enumerators[] = 9467cc0636SGreg Clayton { 9567cc0636SGreg Clayton { eScriptLanguageNone, "none", "Disable scripting languages."}, 9667cc0636SGreg Clayton { eScriptLanguagePython, "python", "Select python as the default scripting language."}, 9767cc0636SGreg Clayton { eScriptLanguageDefault, "default", "Select the lldb default as the default scripting language."}, 98a12993c9SGreg Clayton { 0, NULL, NULL } 9967cc0636SGreg Clayton }; 100e372b98dSGreg Clayton 10167cc0636SGreg Clayton #define MODULE_WITH_FUNC "{ ${module.file.basename}{`${function.name-with-args}${function.pc-offset}}}" 10267cc0636SGreg Clayton #define FILE_AND_LINE "{ at ${line.file.basename}:${line.number}}" 10367cc0636SGreg Clayton 1040769b2b1SMichael Sartain #define DEFAULT_THREAD_FORMAT "thread #${thread.index}: tid = ${thread.id%tid}"\ 10567cc0636SGreg Clayton "{, ${frame.pc}}"\ 10667cc0636SGreg Clayton MODULE_WITH_FUNC\ 10767cc0636SGreg Clayton FILE_AND_LINE\ 1080769b2b1SMichael Sartain "{, name = '${thread.name}'}"\ 1090769b2b1SMichael Sartain "{, queue = '${thread.queue}'}"\ 110*705b1809SJason Molenda "{, activity = '${thread.info.activity.name}'}" \ 111*705b1809SJason Molenda "{, ${thread.info.trace_messages} messages}" \ 11267cc0636SGreg Clayton "{, stop reason = ${thread.stop-reason}}"\ 11367cc0636SGreg Clayton "{\\nReturn value: ${thread.return-value}}"\ 11467cc0636SGreg Clayton "\\n" 11567cc0636SGreg Clayton 11667cc0636SGreg Clayton #define DEFAULT_FRAME_FORMAT "frame #${frame.index}: ${frame.pc}"\ 11767cc0636SGreg Clayton MODULE_WITH_FUNC\ 11867cc0636SGreg Clayton FILE_AND_LINE\ 11967cc0636SGreg Clayton "\\n" 12067cc0636SGreg Clayton 12167cc0636SGreg Clayton 12267cc0636SGreg Clayton 123754a9369SGreg Clayton static PropertyDefinition 124754a9369SGreg Clayton g_properties[] = 12567cc0636SGreg Clayton { 12667cc0636SGreg Clayton { "auto-confirm", OptionValue::eTypeBoolean, true, false, NULL, NULL, "If true all confirmation prompts will receive their default reply." }, 12767cc0636SGreg 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." }, 12867cc0636SGreg Clayton { "notify-void", OptionValue::eTypeBoolean, true, false, NULL, NULL, "Notify the user explicitly if an expression returns void (default: false)." }, 1294c05410fSGreg Clayton { "prompt", OptionValue::eTypeString , true, OptionValueString::eOptionEncodeCharacterEscapeSequences, "(lldb) ", NULL, "The debugger command line prompt displayed for the user." }, 13067cc0636SGreg Clayton { "script-lang", OptionValue::eTypeEnum , true, eScriptLanguagePython, NULL, g_language_enumerators, "The script language to be used for evaluating user-written scripts." }, 13167cc0636SGreg Clayton { "stop-disassembly-count", OptionValue::eTypeSInt64 , true, 4 , NULL, NULL, "The number of disassembly lines to show when displaying a stopped context." }, 13267cc0636SGreg 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." }, 13367cc0636SGreg 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." }, 13467cc0636SGreg 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." }, 13567cc0636SGreg Clayton { "term-width", OptionValue::eTypeSInt64 , true, 80 , NULL, NULL, "The maximum number of columns to use for displaying text." }, 13667cc0636SGreg Clayton { "thread-format", OptionValue::eTypeString , true, 0 , DEFAULT_THREAD_FORMAT, NULL, "The default thread format string to use when displaying thread information." }, 13767cc0636SGreg Clayton { "use-external-editor", OptionValue::eTypeBoolean, true, false, NULL, NULL, "Whether to use an external editor or not." }, 138c3ce7f27SMichael Sartain { "use-color", OptionValue::eTypeBoolean, true, true , NULL, NULL, "Whether to use Ansi color codes or not." }, 13990a8db30SEnrico 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)." }, 140e8cd0c98SGreg Clayton 14167cc0636SGreg Clayton { NULL, OptionValue::eTypeInvalid, true, 0 , NULL, NULL, NULL } 14267cc0636SGreg Clayton }; 14367cc0636SGreg Clayton 14467cc0636SGreg Clayton enum 14567cc0636SGreg Clayton { 14667cc0636SGreg Clayton ePropertyAutoConfirm = 0, 14767cc0636SGreg Clayton ePropertyFrameFormat, 14867cc0636SGreg Clayton ePropertyNotiftVoid, 14967cc0636SGreg Clayton ePropertyPrompt, 15067cc0636SGreg Clayton ePropertyScriptLanguage, 15167cc0636SGreg Clayton ePropertyStopDisassemblyCount, 15267cc0636SGreg Clayton ePropertyStopDisassemblyDisplay, 15367cc0636SGreg Clayton ePropertyStopLineCountAfter, 15467cc0636SGreg Clayton ePropertyStopLineCountBefore, 15567cc0636SGreg Clayton ePropertyTerminalWidth, 15667cc0636SGreg Clayton ePropertyThreadFormat, 157c3ce7f27SMichael Sartain ePropertyUseExternalEditor, 158c3ce7f27SMichael Sartain ePropertyUseColor, 15990a8db30SEnrico Granata ePropertyAutoOneLineSummaries 16067cc0636SGreg Clayton }; 16167cc0636SGreg Clayton 1625fb8f797SGreg Clayton Debugger::LoadPluginCallbackType Debugger::g_load_plugin_callback = NULL; 1634c05410fSGreg Clayton 1644c05410fSGreg Clayton Error 1654c05410fSGreg Clayton Debugger::SetPropertyValue (const ExecutionContext *exe_ctx, 1664c05410fSGreg Clayton VarSetOperationType op, 1674c05410fSGreg Clayton const char *property_path, 1684c05410fSGreg Clayton const char *value) 1694c05410fSGreg Clayton { 17084a53dfbSEnrico Granata bool is_load_script = strcmp(property_path,"target.load-script-from-symbol-file") == 0; 17184a53dfbSEnrico Granata TargetSP target_sp; 172397ddd5fSEnrico Granata LoadScriptFromSymFile load_script_old_value; 17384a53dfbSEnrico Granata if (is_load_script && exe_ctx->GetTargetSP()) 17484a53dfbSEnrico Granata { 17584a53dfbSEnrico Granata target_sp = exe_ctx->GetTargetSP(); 17684a53dfbSEnrico Granata load_script_old_value = target_sp->TargetProperties::GetLoadScriptFromSymbolFile(); 17784a53dfbSEnrico Granata } 1784c05410fSGreg Clayton Error error (Properties::SetPropertyValue (exe_ctx, op, property_path, value)); 1794c05410fSGreg Clayton if (error.Success()) 1804c05410fSGreg Clayton { 18184a53dfbSEnrico Granata // FIXME it would be nice to have "on-change" callbacks for properties 1824c05410fSGreg Clayton if (strcmp(property_path, g_properties[ePropertyPrompt].name) == 0) 1834c05410fSGreg Clayton { 1844c05410fSGreg Clayton const char *new_prompt = GetPrompt(); 185c3ce7f27SMichael Sartain std::string str = lldb_utility::ansi::FormatAnsiTerminalCodes (new_prompt, GetUseColor()); 186c3ce7f27SMichael Sartain if (str.length()) 187c3ce7f27SMichael Sartain new_prompt = str.c_str(); 18844d93782SGreg Clayton GetCommandInterpreter().UpdatePrompt(new_prompt); 1894c05410fSGreg Clayton EventSP prompt_change_event_sp (new Event(CommandInterpreter::eBroadcastBitResetPrompt, new EventDataBytes (new_prompt))); 1904c05410fSGreg Clayton GetCommandInterpreter().BroadcastEvent (prompt_change_event_sp); 1914c05410fSGreg Clayton } 192c3ce7f27SMichael Sartain else if (strcmp(property_path, g_properties[ePropertyUseColor].name) == 0) 193c3ce7f27SMichael Sartain { 194c3ce7f27SMichael Sartain // use-color changed. Ping the prompt so it can reset the ansi terminal codes. 195c3ce7f27SMichael Sartain SetPrompt (GetPrompt()); 196c3ce7f27SMichael Sartain } 197397ddd5fSEnrico Granata else if (is_load_script && target_sp && load_script_old_value == eLoadScriptFromSymFileWarn) 19884a53dfbSEnrico Granata { 199397ddd5fSEnrico Granata if (target_sp->TargetProperties::GetLoadScriptFromSymbolFile() == eLoadScriptFromSymFileTrue) 20084a53dfbSEnrico Granata { 20184a53dfbSEnrico Granata std::list<Error> errors; 2029730339bSEnrico Granata StreamString feedback_stream; 2039730339bSEnrico Granata if (!target_sp->LoadScriptingResources(errors,&feedback_stream)) 20484a53dfbSEnrico Granata { 20544d93782SGreg Clayton StreamFileSP stream_sp (GetErrorFile()); 20644d93782SGreg Clayton if (stream_sp) 20744d93782SGreg Clayton { 20884a53dfbSEnrico Granata for (auto error : errors) 20984a53dfbSEnrico Granata { 21044d93782SGreg Clayton stream_sp->Printf("%s\n",error.AsCString()); 21184a53dfbSEnrico Granata } 2129730339bSEnrico Granata if (feedback_stream.GetSize()) 21344d93782SGreg Clayton stream_sp->Printf("%s",feedback_stream.GetData()); 21444d93782SGreg Clayton } 21584a53dfbSEnrico Granata } 21684a53dfbSEnrico Granata } 21784a53dfbSEnrico Granata } 2184c05410fSGreg Clayton } 2194c05410fSGreg Clayton return error; 2204c05410fSGreg Clayton } 2214c05410fSGreg Clayton 22267cc0636SGreg Clayton bool 22367cc0636SGreg Clayton Debugger::GetAutoConfirm () const 22467cc0636SGreg Clayton { 22567cc0636SGreg Clayton const uint32_t idx = ePropertyAutoConfirm; 226754a9369SGreg Clayton return m_collection_sp->GetPropertyAtIndexAsBoolean (NULL, idx, g_properties[idx].default_uint_value != 0); 22767cc0636SGreg Clayton } 22867cc0636SGreg Clayton 22967cc0636SGreg Clayton const char * 23067cc0636SGreg Clayton Debugger::GetFrameFormat() const 23167cc0636SGreg Clayton { 23267cc0636SGreg Clayton const uint32_t idx = ePropertyFrameFormat; 233754a9369SGreg Clayton return m_collection_sp->GetPropertyAtIndexAsString (NULL, idx, g_properties[idx].default_cstr_value); 23467cc0636SGreg Clayton } 23567cc0636SGreg Clayton 23667cc0636SGreg Clayton bool 23767cc0636SGreg Clayton Debugger::GetNotifyVoid () const 23867cc0636SGreg Clayton { 23967cc0636SGreg Clayton const uint32_t idx = ePropertyNotiftVoid; 240754a9369SGreg Clayton return m_collection_sp->GetPropertyAtIndexAsBoolean (NULL, idx, g_properties[idx].default_uint_value != 0); 24167cc0636SGreg Clayton } 24267cc0636SGreg Clayton 24367cc0636SGreg Clayton const char * 24467cc0636SGreg Clayton Debugger::GetPrompt() const 24567cc0636SGreg Clayton { 24667cc0636SGreg Clayton const uint32_t idx = ePropertyPrompt; 247754a9369SGreg Clayton return m_collection_sp->GetPropertyAtIndexAsString (NULL, idx, g_properties[idx].default_cstr_value); 24867cc0636SGreg Clayton } 24967cc0636SGreg Clayton 25067cc0636SGreg Clayton void 25167cc0636SGreg Clayton Debugger::SetPrompt(const char *p) 25267cc0636SGreg Clayton { 25367cc0636SGreg Clayton const uint32_t idx = ePropertyPrompt; 25467cc0636SGreg Clayton m_collection_sp->SetPropertyAtIndexAsString (NULL, idx, p); 25567cc0636SGreg Clayton const char *new_prompt = GetPrompt(); 256c3ce7f27SMichael Sartain std::string str = lldb_utility::ansi::FormatAnsiTerminalCodes (new_prompt, GetUseColor()); 257c3ce7f27SMichael Sartain if (str.length()) 258c3ce7f27SMichael Sartain new_prompt = str.c_str(); 25944d93782SGreg Clayton GetCommandInterpreter().UpdatePrompt(new_prompt); 26067cc0636SGreg Clayton } 26167cc0636SGreg Clayton 26267cc0636SGreg Clayton const char * 26367cc0636SGreg Clayton Debugger::GetThreadFormat() const 26467cc0636SGreg Clayton { 26567cc0636SGreg Clayton const uint32_t idx = ePropertyThreadFormat; 266754a9369SGreg Clayton return m_collection_sp->GetPropertyAtIndexAsString (NULL, idx, g_properties[idx].default_cstr_value); 26767cc0636SGreg Clayton } 26867cc0636SGreg Clayton 26967cc0636SGreg Clayton lldb::ScriptLanguage 27067cc0636SGreg Clayton Debugger::GetScriptLanguage() const 27167cc0636SGreg Clayton { 27267cc0636SGreg Clayton const uint32_t idx = ePropertyScriptLanguage; 273754a9369SGreg Clayton return (lldb::ScriptLanguage)m_collection_sp->GetPropertyAtIndexAsEnumeration (NULL, idx, g_properties[idx].default_uint_value); 27467cc0636SGreg Clayton } 27567cc0636SGreg Clayton 27667cc0636SGreg Clayton bool 27767cc0636SGreg Clayton Debugger::SetScriptLanguage (lldb::ScriptLanguage script_lang) 27867cc0636SGreg Clayton { 27967cc0636SGreg Clayton const uint32_t idx = ePropertyScriptLanguage; 28067cc0636SGreg Clayton return m_collection_sp->SetPropertyAtIndexAsEnumeration (NULL, idx, script_lang); 28167cc0636SGreg Clayton } 28267cc0636SGreg Clayton 28367cc0636SGreg Clayton uint32_t 28467cc0636SGreg Clayton Debugger::GetTerminalWidth () const 28567cc0636SGreg Clayton { 28667cc0636SGreg Clayton const uint32_t idx = ePropertyTerminalWidth; 287754a9369SGreg Clayton return m_collection_sp->GetPropertyAtIndexAsSInt64 (NULL, idx, g_properties[idx].default_uint_value); 28867cc0636SGreg Clayton } 28967cc0636SGreg Clayton 29067cc0636SGreg Clayton bool 29167cc0636SGreg Clayton Debugger::SetTerminalWidth (uint32_t term_width) 29267cc0636SGreg Clayton { 29367cc0636SGreg Clayton const uint32_t idx = ePropertyTerminalWidth; 29467cc0636SGreg Clayton return m_collection_sp->SetPropertyAtIndexAsSInt64 (NULL, idx, term_width); 29567cc0636SGreg Clayton } 29667cc0636SGreg Clayton 29767cc0636SGreg Clayton bool 29867cc0636SGreg Clayton Debugger::GetUseExternalEditor () const 29967cc0636SGreg Clayton { 30067cc0636SGreg Clayton const uint32_t idx = ePropertyUseExternalEditor; 301754a9369SGreg Clayton return m_collection_sp->GetPropertyAtIndexAsBoolean (NULL, idx, g_properties[idx].default_uint_value != 0); 30267cc0636SGreg Clayton } 30367cc0636SGreg Clayton 30467cc0636SGreg Clayton bool 30567cc0636SGreg Clayton Debugger::SetUseExternalEditor (bool b) 30667cc0636SGreg Clayton { 30767cc0636SGreg Clayton const uint32_t idx = ePropertyUseExternalEditor; 30867cc0636SGreg Clayton return m_collection_sp->SetPropertyAtIndexAsBoolean (NULL, idx, b); 30967cc0636SGreg Clayton } 31067cc0636SGreg Clayton 311c3ce7f27SMichael Sartain bool 312c3ce7f27SMichael Sartain Debugger::GetUseColor () const 313c3ce7f27SMichael Sartain { 314c3ce7f27SMichael Sartain const uint32_t idx = ePropertyUseColor; 315c3ce7f27SMichael Sartain return m_collection_sp->GetPropertyAtIndexAsBoolean (NULL, idx, g_properties[idx].default_uint_value != 0); 316c3ce7f27SMichael Sartain } 317c3ce7f27SMichael Sartain 318c3ce7f27SMichael Sartain bool 319c3ce7f27SMichael Sartain Debugger::SetUseColor (bool b) 320c3ce7f27SMichael Sartain { 321c3ce7f27SMichael Sartain const uint32_t idx = ePropertyUseColor; 322c3ce7f27SMichael Sartain bool ret = m_collection_sp->SetPropertyAtIndexAsBoolean (NULL, idx, b); 323c3ce7f27SMichael Sartain SetPrompt (GetPrompt()); 324c3ce7f27SMichael Sartain return ret; 325c3ce7f27SMichael Sartain } 326c3ce7f27SMichael Sartain 32767cc0636SGreg Clayton uint32_t 32867cc0636SGreg Clayton Debugger::GetStopSourceLineCount (bool before) const 32967cc0636SGreg Clayton { 33067cc0636SGreg Clayton const uint32_t idx = before ? ePropertyStopLineCountBefore : ePropertyStopLineCountAfter; 331754a9369SGreg Clayton return m_collection_sp->GetPropertyAtIndexAsSInt64 (NULL, idx, g_properties[idx].default_uint_value); 33267cc0636SGreg Clayton } 33367cc0636SGreg Clayton 33467cc0636SGreg Clayton Debugger::StopDisassemblyType 33567cc0636SGreg Clayton Debugger::GetStopDisassemblyDisplay () const 33667cc0636SGreg Clayton { 33767cc0636SGreg Clayton const uint32_t idx = ePropertyStopDisassemblyDisplay; 338754a9369SGreg Clayton return (Debugger::StopDisassemblyType)m_collection_sp->GetPropertyAtIndexAsEnumeration (NULL, idx, g_properties[idx].default_uint_value); 33967cc0636SGreg Clayton } 34067cc0636SGreg Clayton 34167cc0636SGreg Clayton uint32_t 34267cc0636SGreg Clayton Debugger::GetDisassemblyLineCount () const 34367cc0636SGreg Clayton { 34467cc0636SGreg Clayton const uint32_t idx = ePropertyStopDisassemblyCount; 345754a9369SGreg Clayton return m_collection_sp->GetPropertyAtIndexAsSInt64 (NULL, idx, g_properties[idx].default_uint_value); 34667cc0636SGreg Clayton } 347e372b98dSGreg Clayton 348553fad5cSEnrico Granata bool 34990a8db30SEnrico Granata Debugger::GetAutoOneLineSummaries () const 350553fad5cSEnrico Granata { 35190a8db30SEnrico Granata const uint32_t idx = ePropertyAutoOneLineSummaries; 352553fad5cSEnrico Granata return m_collection_sp->GetPropertyAtIndexAsBoolean (NULL, idx, true); 353553fad5cSEnrico Granata 354553fad5cSEnrico Granata } 355553fad5cSEnrico Granata 3561b654882SGreg Clayton #pragma mark Debugger 3571b654882SGreg Clayton 35867cc0636SGreg Clayton //const DebuggerPropertiesSP & 35967cc0636SGreg Clayton //Debugger::GetSettings() const 36067cc0636SGreg Clayton //{ 36167cc0636SGreg Clayton // return m_properties_sp; 36267cc0636SGreg Clayton //} 36367cc0636SGreg Clayton // 36499d0faf2SGreg Clayton 3652f88aadfSCaroline Tice int 3662f88aadfSCaroline Tice Debugger::TestDebuggerRefCount () 3672f88aadfSCaroline Tice { 3682f88aadfSCaroline Tice return g_shared_debugger_refcount; 3692f88aadfSCaroline Tice } 3702f88aadfSCaroline Tice 37130fdc8d8SChris Lattner void 3725fb8f797SGreg Clayton Debugger::Initialize (LoadPluginCallbackType load_plugin_callback) 37330fdc8d8SChris Lattner { 3745fb8f797SGreg Clayton g_load_plugin_callback = load_plugin_callback; 375c15f55e2SGreg Clayton if (g_shared_debugger_refcount++ == 0) 376dbe54508SGreg Clayton lldb_private::Initialize(); 37799d0faf2SGreg Clayton } 37830fdc8d8SChris Lattner 37930fdc8d8SChris Lattner void 38030fdc8d8SChris Lattner Debugger::Terminate () 38130fdc8d8SChris Lattner { 3826611103cSGreg Clayton if (g_shared_debugger_refcount > 0) 3836611103cSGreg Clayton { 38430fdc8d8SChris Lattner g_shared_debugger_refcount--; 38530fdc8d8SChris Lattner if (g_shared_debugger_refcount == 0) 38630fdc8d8SChris Lattner { 387dbe54508SGreg Clayton lldb_private::WillTerminate(); 388dbe54508SGreg Clayton lldb_private::Terminate(); 3896760a517SCaroline Tice 39099d0faf2SGreg Clayton // Clear our master list of debugger objects 39199d0faf2SGreg Clayton Mutex::Locker locker (GetDebuggerListMutex ()); 39299d0faf2SGreg Clayton GetDebuggerList().clear(); 39330fdc8d8SChris Lattner } 3946760a517SCaroline Tice } 3956760a517SCaroline Tice } 39630fdc8d8SChris Lattner 39720bd37f7SCaroline Tice void 39820bd37f7SCaroline Tice Debugger::SettingsInitialize () 39920bd37f7SCaroline Tice { 4006920b52bSGreg Clayton Target::SettingsInitialize (); 40120bd37f7SCaroline Tice } 40220bd37f7SCaroline Tice 40320bd37f7SCaroline Tice void 40420bd37f7SCaroline Tice Debugger::SettingsTerminate () 40520bd37f7SCaroline Tice { 4066920b52bSGreg Clayton Target::SettingsTerminate (); 40720bd37f7SCaroline Tice } 40820bd37f7SCaroline Tice 40921dfcd9dSEnrico Granata bool 410e743c782SEnrico Granata Debugger::LoadPlugin (const FileSpec& spec, Error& error) 41121dfcd9dSEnrico Granata { 4125fb8f797SGreg Clayton if (g_load_plugin_callback) 413e743c782SEnrico Granata { 4145fb8f797SGreg Clayton lldb::DynamicLibrarySP dynlib_sp = g_load_plugin_callback (shared_from_this(), spec, error); 4155fb8f797SGreg Clayton if (dynlib_sp) 41621dfcd9dSEnrico Granata { 41721dfcd9dSEnrico Granata m_loaded_plugins.push_back(dynlib_sp); 41821dfcd9dSEnrico Granata return true; 41921dfcd9dSEnrico Granata } 4205fb8f797SGreg Clayton } 4215fb8f797SGreg Clayton else 4225fb8f797SGreg Clayton { 4235fb8f797SGreg Clayton // The g_load_plugin_callback is registered in SBDebugger::Initialize() 4245fb8f797SGreg Clayton // and if the public API layer isn't available (code is linking against 4255fb8f797SGreg Clayton // all of the internal LLDB static libraries), then we can't load plugins 4265fb8f797SGreg Clayton error.SetErrorString("Public API layer is not available"); 4275fb8f797SGreg Clayton } 42821dfcd9dSEnrico Granata return false; 42921dfcd9dSEnrico Granata } 43021dfcd9dSEnrico Granata 43121dfcd9dSEnrico Granata static FileSpec::EnumerateDirectoryResult 43221dfcd9dSEnrico Granata LoadPluginCallback 43321dfcd9dSEnrico Granata ( 43421dfcd9dSEnrico Granata void *baton, 43521dfcd9dSEnrico Granata FileSpec::FileType file_type, 43621dfcd9dSEnrico Granata const FileSpec &file_spec 43721dfcd9dSEnrico Granata ) 43821dfcd9dSEnrico Granata { 43921dfcd9dSEnrico Granata Error error; 44021dfcd9dSEnrico Granata 44121dfcd9dSEnrico Granata static ConstString g_dylibext("dylib"); 4423cf443ddSMichael Sartain static ConstString g_solibext("so"); 44321dfcd9dSEnrico Granata 44421dfcd9dSEnrico Granata if (!baton) 44521dfcd9dSEnrico Granata return FileSpec::eEnumerateDirectoryResultQuit; 44621dfcd9dSEnrico Granata 44721dfcd9dSEnrico Granata Debugger *debugger = (Debugger*)baton; 44821dfcd9dSEnrico Granata 44921dfcd9dSEnrico Granata // If we have a regular file, a symbolic link or unknown file type, try 45021dfcd9dSEnrico Granata // and process the file. We must handle unknown as sometimes the directory 45121dfcd9dSEnrico Granata // enumeration might be enumerating a file system that doesn't have correct 45221dfcd9dSEnrico Granata // file type information. 45321dfcd9dSEnrico Granata if (file_type == FileSpec::eFileTypeRegular || 45421dfcd9dSEnrico Granata file_type == FileSpec::eFileTypeSymbolicLink || 45521dfcd9dSEnrico Granata file_type == FileSpec::eFileTypeUnknown ) 45621dfcd9dSEnrico Granata { 45721dfcd9dSEnrico Granata FileSpec plugin_file_spec (file_spec); 45821dfcd9dSEnrico Granata plugin_file_spec.ResolvePath (); 45921dfcd9dSEnrico Granata 4603cf443ddSMichael Sartain if (plugin_file_spec.GetFileNameExtension() != g_dylibext && 4613cf443ddSMichael Sartain plugin_file_spec.GetFileNameExtension() != g_solibext) 4623cf443ddSMichael Sartain { 46321dfcd9dSEnrico Granata return FileSpec::eEnumerateDirectoryResultNext; 4643cf443ddSMichael Sartain } 46521dfcd9dSEnrico Granata 466e743c782SEnrico Granata Error plugin_load_error; 467e743c782SEnrico Granata debugger->LoadPlugin (plugin_file_spec, plugin_load_error); 46821dfcd9dSEnrico Granata 46921dfcd9dSEnrico Granata return FileSpec::eEnumerateDirectoryResultNext; 47021dfcd9dSEnrico Granata } 47121dfcd9dSEnrico Granata 47221dfcd9dSEnrico Granata else if (file_type == FileSpec::eFileTypeUnknown || 47321dfcd9dSEnrico Granata file_type == FileSpec::eFileTypeDirectory || 47421dfcd9dSEnrico Granata file_type == FileSpec::eFileTypeSymbolicLink ) 47521dfcd9dSEnrico Granata { 47621dfcd9dSEnrico Granata // Try and recurse into anything that a directory or symbolic link. 47721dfcd9dSEnrico Granata // We must also do this for unknown as sometimes the directory enumeration 47821dfcd9dSEnrico Granata // might be enurating a file system that doesn't have correct file type 47921dfcd9dSEnrico Granata // information. 48021dfcd9dSEnrico Granata return FileSpec::eEnumerateDirectoryResultEnter; 48121dfcd9dSEnrico Granata } 48221dfcd9dSEnrico Granata 48321dfcd9dSEnrico Granata return FileSpec::eEnumerateDirectoryResultNext; 48421dfcd9dSEnrico Granata } 48521dfcd9dSEnrico Granata 48621dfcd9dSEnrico Granata void 48721dfcd9dSEnrico Granata Debugger::InstanceInitialize () 48821dfcd9dSEnrico Granata { 48921dfcd9dSEnrico Granata FileSpec dir_spec; 49021dfcd9dSEnrico Granata const bool find_directories = true; 49121dfcd9dSEnrico Granata const bool find_files = true; 49221dfcd9dSEnrico Granata const bool find_other = true; 49321dfcd9dSEnrico Granata char dir_path[PATH_MAX]; 49421dfcd9dSEnrico Granata if (Host::GetLLDBPath (ePathTypeLLDBSystemPlugins, dir_spec)) 49521dfcd9dSEnrico Granata { 49621dfcd9dSEnrico Granata if (dir_spec.Exists() && dir_spec.GetPath(dir_path, sizeof(dir_path))) 49721dfcd9dSEnrico Granata { 49821dfcd9dSEnrico Granata FileSpec::EnumerateDirectory (dir_path, 49921dfcd9dSEnrico Granata find_directories, 50021dfcd9dSEnrico Granata find_files, 50121dfcd9dSEnrico Granata find_other, 50221dfcd9dSEnrico Granata LoadPluginCallback, 50321dfcd9dSEnrico Granata this); 50421dfcd9dSEnrico Granata } 50521dfcd9dSEnrico Granata } 50621dfcd9dSEnrico Granata 50721dfcd9dSEnrico Granata if (Host::GetLLDBPath (ePathTypeLLDBUserPlugins, dir_spec)) 50821dfcd9dSEnrico Granata { 50921dfcd9dSEnrico Granata if (dir_spec.Exists() && dir_spec.GetPath(dir_path, sizeof(dir_path))) 51021dfcd9dSEnrico Granata { 51121dfcd9dSEnrico Granata FileSpec::EnumerateDirectory (dir_path, 51221dfcd9dSEnrico Granata find_directories, 51321dfcd9dSEnrico Granata find_files, 51421dfcd9dSEnrico Granata find_other, 51521dfcd9dSEnrico Granata LoadPluginCallback, 51621dfcd9dSEnrico Granata this); 51721dfcd9dSEnrico Granata } 51821dfcd9dSEnrico Granata } 519e8cd0c98SGreg Clayton 520e8cd0c98SGreg Clayton PluginManager::DebuggerInitialize (*this); 52121dfcd9dSEnrico Granata } 52221dfcd9dSEnrico Granata 5236611103cSGreg Clayton DebuggerSP 524228063cdSJim Ingham Debugger::CreateInstance (lldb::LogOutputCallback log_callback, void *baton) 5256611103cSGreg Clayton { 526228063cdSJim Ingham DebuggerSP debugger_sp (new Debugger(log_callback, baton)); 527c15f55e2SGreg Clayton if (g_shared_debugger_refcount > 0) 5286611103cSGreg Clayton { 5296611103cSGreg Clayton Mutex::Locker locker (GetDebuggerListMutex ()); 5306611103cSGreg Clayton GetDebuggerList().push_back(debugger_sp); 5316611103cSGreg Clayton } 53221dfcd9dSEnrico Granata debugger_sp->InstanceInitialize (); 5336611103cSGreg Clayton return debugger_sp; 5346611103cSGreg Clayton } 5356611103cSGreg Clayton 536e02657b1SCaroline Tice void 5374d122c40SGreg Clayton Debugger::Destroy (DebuggerSP &debugger_sp) 538e02657b1SCaroline Tice { 539e02657b1SCaroline Tice if (debugger_sp.get() == NULL) 540e02657b1SCaroline Tice return; 541e02657b1SCaroline Tice 5428314c525SJim Ingham debugger_sp->Clear(); 5438314c525SJim Ingham 544c15f55e2SGreg Clayton if (g_shared_debugger_refcount > 0) 545c15f55e2SGreg Clayton { 546e02657b1SCaroline Tice Mutex::Locker locker (GetDebuggerListMutex ()); 547e02657b1SCaroline Tice DebuggerList &debugger_list = GetDebuggerList (); 548e02657b1SCaroline Tice DebuggerList::iterator pos, end = debugger_list.end(); 549e02657b1SCaroline Tice for (pos = debugger_list.begin (); pos != end; ++pos) 550e02657b1SCaroline Tice { 551e02657b1SCaroline Tice if ((*pos).get() == debugger_sp.get()) 552e02657b1SCaroline Tice { 553e02657b1SCaroline Tice debugger_list.erase (pos); 554e02657b1SCaroline Tice return; 555e02657b1SCaroline Tice } 556e02657b1SCaroline Tice } 557e02657b1SCaroline Tice } 558c15f55e2SGreg Clayton } 559e02657b1SCaroline Tice 5604d122c40SGreg Clayton DebuggerSP 5613df9a8dfSCaroline Tice Debugger::FindDebuggerWithInstanceName (const ConstString &instance_name) 5623df9a8dfSCaroline Tice { 5634d122c40SGreg Clayton DebuggerSP debugger_sp; 5646920b52bSGreg Clayton if (g_shared_debugger_refcount > 0) 5656920b52bSGreg Clayton { 5666920b52bSGreg Clayton Mutex::Locker locker (GetDebuggerListMutex ()); 5676920b52bSGreg Clayton DebuggerList &debugger_list = GetDebuggerList(); 5686920b52bSGreg Clayton DebuggerList::iterator pos, end = debugger_list.end(); 5696920b52bSGreg Clayton 5706920b52bSGreg Clayton for (pos = debugger_list.begin(); pos != end; ++pos) 5716920b52bSGreg Clayton { 5726920b52bSGreg Clayton if ((*pos).get()->m_instance_name == instance_name) 5736920b52bSGreg Clayton { 5746920b52bSGreg Clayton debugger_sp = *pos; 5756920b52bSGreg Clayton break; 5766920b52bSGreg Clayton } 5776920b52bSGreg Clayton } 5786920b52bSGreg Clayton } 5793df9a8dfSCaroline Tice return debugger_sp; 5803df9a8dfSCaroline Tice } 5816611103cSGreg Clayton 5826611103cSGreg Clayton TargetSP 5836611103cSGreg Clayton Debugger::FindTargetWithProcessID (lldb::pid_t pid) 5846611103cSGreg Clayton { 5854d122c40SGreg Clayton TargetSP target_sp; 586c15f55e2SGreg Clayton if (g_shared_debugger_refcount > 0) 587c15f55e2SGreg Clayton { 5886611103cSGreg Clayton Mutex::Locker locker (GetDebuggerListMutex ()); 5896611103cSGreg Clayton DebuggerList &debugger_list = GetDebuggerList(); 5906611103cSGreg Clayton DebuggerList::iterator pos, end = debugger_list.end(); 5916611103cSGreg Clayton for (pos = debugger_list.begin(); pos != end; ++pos) 5926611103cSGreg Clayton { 5936611103cSGreg Clayton target_sp = (*pos)->GetTargetList().FindTargetWithProcessID (pid); 5946611103cSGreg Clayton if (target_sp) 5956611103cSGreg Clayton break; 5966611103cSGreg Clayton } 597c15f55e2SGreg Clayton } 5986611103cSGreg Clayton return target_sp; 5996611103cSGreg Clayton } 6006611103cSGreg Clayton 601e4e45924SGreg Clayton TargetSP 602e4e45924SGreg Clayton Debugger::FindTargetWithProcess (Process *process) 603e4e45924SGreg Clayton { 604e4e45924SGreg Clayton TargetSP target_sp; 605c15f55e2SGreg Clayton if (g_shared_debugger_refcount > 0) 606c15f55e2SGreg Clayton { 607e4e45924SGreg Clayton Mutex::Locker locker (GetDebuggerListMutex ()); 608e4e45924SGreg Clayton DebuggerList &debugger_list = GetDebuggerList(); 609e4e45924SGreg Clayton DebuggerList::iterator pos, end = debugger_list.end(); 610e4e45924SGreg Clayton for (pos = debugger_list.begin(); pos != end; ++pos) 611e4e45924SGreg Clayton { 612e4e45924SGreg Clayton target_sp = (*pos)->GetTargetList().FindTargetWithProcess (process); 613e4e45924SGreg Clayton if (target_sp) 614e4e45924SGreg Clayton break; 615e4e45924SGreg Clayton } 616c15f55e2SGreg Clayton } 617e4e45924SGreg Clayton return target_sp; 618e4e45924SGreg Clayton } 619e4e45924SGreg Clayton 620228063cdSJim Ingham Debugger::Debugger (lldb::LogOutputCallback log_callback, void *baton) : 621ebc1bb27SCaroline Tice UserID (g_unique_id++), 62267cc0636SGreg Clayton Properties(OptionValuePropertiesSP(new OptionValueProperties())), 62344d93782SGreg Clayton m_input_file_sp (new StreamFile (stdin, false)), 62444d93782SGreg Clayton m_output_file_sp (new StreamFile (stdout, false)), 62544d93782SGreg Clayton m_error_file_sp (new StreamFile (stderr, false)), 626c5917d9aSJim Ingham m_terminal_state (), 6274bddaeb5SJim Ingham m_target_list (*this), 628ded470d3SGreg Clayton m_platform_list (), 62930fdc8d8SChris Lattner m_listener ("lldb.Debugger"), 6309585fbfcSGreg Clayton m_source_manager_ap(), 631e37d605eSJim Ingham m_source_file_cache(), 6326611103cSGreg Clayton m_command_interpreter_ap (new CommandInterpreter (*this, eScriptLanguageDefault, false)), 633d5a0a01bSCaroline Tice m_input_reader_stack (), 63444d93782SGreg Clayton m_instance_name (), 63544d93782SGreg Clayton m_loaded_plugins (), 63644d93782SGreg Clayton m_event_handler_thread (LLDB_INVALID_HOST_THREAD), 637b4874f1aSGreg Clayton m_io_handler_thread (LLDB_INVALID_HOST_THREAD) 63830fdc8d8SChris Lattner { 63967cc0636SGreg Clayton char instance_cstr[256]; 64067cc0636SGreg Clayton snprintf(instance_cstr, sizeof(instance_cstr), "debugger_%d", (int)GetID()); 64167cc0636SGreg Clayton m_instance_name.SetCString(instance_cstr); 642228063cdSJim Ingham if (log_callback) 643228063cdSJim Ingham m_log_callback_stream_sp.reset (new StreamCallback (log_callback, baton)); 6446611103cSGreg Clayton m_command_interpreter_ap->Initialize (); 645ded470d3SGreg Clayton // Always add our default platform to the platform list 646ded470d3SGreg Clayton PlatformSP default_platform_sp (Platform::GetDefaultPlatform()); 647ded470d3SGreg Clayton assert (default_platform_sp.get()); 648ded470d3SGreg Clayton m_platform_list.Append (default_platform_sp, true); 64967cc0636SGreg Clayton 650754a9369SGreg Clayton m_collection_sp->Initialize (g_properties); 65167cc0636SGreg Clayton m_collection_sp->AppendProperty (ConstString("target"), 65267cc0636SGreg Clayton ConstString("Settings specify to debugging targets."), 65367cc0636SGreg Clayton true, 65467cc0636SGreg Clayton Target::GetGlobalProperties()->GetValueProperties()); 655754a9369SGreg Clayton if (m_command_interpreter_ap.get()) 656754a9369SGreg Clayton { 657754a9369SGreg Clayton m_collection_sp->AppendProperty (ConstString("interpreter"), 658754a9369SGreg Clayton ConstString("Settings specify to the debugger's command interpreter."), 659754a9369SGreg Clayton true, 660754a9369SGreg Clayton m_command_interpreter_ap->GetValueProperties()); 661754a9369SGreg Clayton } 66267cc0636SGreg Clayton OptionValueSInt64 *term_width = m_collection_sp->GetPropertyAtIndexAsOptionValueSInt64 (NULL, ePropertyTerminalWidth); 66367cc0636SGreg Clayton term_width->SetMinimumValue(10); 66467cc0636SGreg Clayton term_width->SetMaximumValue(1024); 665c3ce7f27SMichael Sartain 666c3ce7f27SMichael Sartain // Turn off use-color if this is a dumb terminal. 667c3ce7f27SMichael Sartain const char *term = getenv ("TERM"); 668c3ce7f27SMichael Sartain if (term && !strcmp (term, "dumb")) 669c3ce7f27SMichael Sartain SetUseColor (false); 67030fdc8d8SChris Lattner } 67130fdc8d8SChris Lattner 67230fdc8d8SChris Lattner Debugger::~Debugger () 67330fdc8d8SChris Lattner { 6748314c525SJim Ingham Clear(); 6758314c525SJim Ingham } 6768314c525SJim Ingham 6778314c525SJim Ingham void 6788314c525SJim Ingham Debugger::Clear() 6798314c525SJim Ingham { 68044d93782SGreg Clayton ClearIOHandlers(); 68144d93782SGreg Clayton StopIOHandlerThread(); 68244d93782SGreg Clayton StopEventHandlerThread(); 6831ed54f50SGreg Clayton m_listener.Clear(); 6846611103cSGreg Clayton int num_targets = m_target_list.GetNumTargets(); 6856611103cSGreg Clayton for (int i = 0; i < num_targets; i++) 6866611103cSGreg Clayton { 687ccbc08e6SGreg Clayton TargetSP target_sp (m_target_list.GetTargetAtIndex (i)); 688ccbc08e6SGreg Clayton if (target_sp) 689ccbc08e6SGreg Clayton { 690ccbc08e6SGreg Clayton ProcessSP process_sp (target_sp->GetProcessSP()); 6916611103cSGreg Clayton if (process_sp) 6921fd07059SJim Ingham process_sp->Finalize(); 693ccbc08e6SGreg Clayton target_sp->Destroy(); 6946611103cSGreg Clayton } 69530fdc8d8SChris Lattner } 6964bddaeb5SJim Ingham BroadcasterManager::Clear (); 69730fdc8d8SChris Lattner 6980d69a3a4SGreg Clayton // Close the input file _before_ we close the input read communications class 6990d69a3a4SGreg Clayton // as it does NOT own the input file, our m_input_file does. 700c5917d9aSJim Ingham m_terminal_state.Clear(); 70144d93782SGreg Clayton if (m_input_file_sp) 70244d93782SGreg Clayton m_input_file_sp->GetFile().Close (); 7030c4129f2SGreg Clayton 7040c4129f2SGreg Clayton m_command_interpreter_ap->Clear(); 7058314c525SJim Ingham } 70630fdc8d8SChris Lattner 70730fdc8d8SChris Lattner bool 708fc3f027dSGreg Clayton Debugger::GetCloseInputOnEOF () const 709fc3f027dSGreg Clayton { 71044d93782SGreg Clayton // return m_input_comm.GetCloseOnEOF(); 71144d93782SGreg Clayton return false; 712fc3f027dSGreg Clayton } 713fc3f027dSGreg Clayton 714fc3f027dSGreg Clayton void 715fc3f027dSGreg Clayton Debugger::SetCloseInputOnEOF (bool b) 716fc3f027dSGreg Clayton { 71744d93782SGreg Clayton // m_input_comm.SetCloseOnEOF(b); 718fc3f027dSGreg Clayton } 719fc3f027dSGreg Clayton 720fc3f027dSGreg Clayton bool 72130fdc8d8SChris Lattner Debugger::GetAsyncExecution () 72230fdc8d8SChris Lattner { 7236611103cSGreg Clayton return !m_command_interpreter_ap->GetSynchronous(); 72430fdc8d8SChris Lattner } 72530fdc8d8SChris Lattner 72630fdc8d8SChris Lattner void 72730fdc8d8SChris Lattner Debugger::SetAsyncExecution (bool async_execution) 72830fdc8d8SChris Lattner { 7296611103cSGreg Clayton m_command_interpreter_ap->SetSynchronous (!async_execution); 73030fdc8d8SChris Lattner } 73130fdc8d8SChris Lattner 73230fdc8d8SChris Lattner 73330fdc8d8SChris Lattner void 73430fdc8d8SChris Lattner Debugger::SetInputFileHandle (FILE *fh, bool tranfer_ownership) 73530fdc8d8SChris Lattner { 73644d93782SGreg Clayton if (m_input_file_sp) 73744d93782SGreg Clayton m_input_file_sp->GetFile().SetStream (fh, tranfer_ownership); 73844d93782SGreg Clayton else 73944d93782SGreg Clayton m_input_file_sp.reset (new StreamFile (fh, tranfer_ownership)); 74044d93782SGreg Clayton 74144d93782SGreg Clayton File &in_file = m_input_file_sp->GetFile(); 74251b1e2d2SGreg Clayton if (in_file.IsValid() == false) 74351b1e2d2SGreg Clayton in_file.SetStream (stdin, true); 74430fdc8d8SChris Lattner 745c5917d9aSJim Ingham // Save away the terminal state if that is relevant, so that we can restore it in RestoreInputState. 746c5917d9aSJim Ingham SaveInputTerminalState (); 74730fdc8d8SChris Lattner } 74830fdc8d8SChris Lattner 74930fdc8d8SChris Lattner void 75030fdc8d8SChris Lattner Debugger::SetOutputFileHandle (FILE *fh, bool tranfer_ownership) 75130fdc8d8SChris Lattner { 75244d93782SGreg Clayton if (m_output_file_sp) 75344d93782SGreg Clayton m_output_file_sp->GetFile().SetStream (fh, tranfer_ownership); 75444d93782SGreg Clayton else 75544d93782SGreg Clayton m_output_file_sp.reset (new StreamFile (fh, tranfer_ownership)); 75644d93782SGreg Clayton 75744d93782SGreg Clayton File &out_file = m_output_file_sp->GetFile(); 75851b1e2d2SGreg Clayton if (out_file.IsValid() == false) 75951b1e2d2SGreg Clayton out_file.SetStream (stdout, false); 7602f88aadfSCaroline Tice 761b588726eSEnrico Granata // do not create the ScriptInterpreter just for setting the output file handle 762b588726eSEnrico Granata // as the constructor will know how to do the right thing on its own 763b588726eSEnrico Granata const bool can_create = false; 764b588726eSEnrico Granata ScriptInterpreter* script_interpreter = GetCommandInterpreter().GetScriptInterpreter(can_create); 765b588726eSEnrico Granata if (script_interpreter) 766b588726eSEnrico Granata script_interpreter->ResetOutputFileHandle (fh); 76730fdc8d8SChris Lattner } 76830fdc8d8SChris Lattner 76930fdc8d8SChris Lattner void 77030fdc8d8SChris Lattner Debugger::SetErrorFileHandle (FILE *fh, bool tranfer_ownership) 77130fdc8d8SChris Lattner { 77244d93782SGreg Clayton if (m_error_file_sp) 77344d93782SGreg Clayton m_error_file_sp->GetFile().SetStream (fh, tranfer_ownership); 77444d93782SGreg Clayton else 77544d93782SGreg Clayton m_error_file_sp.reset (new StreamFile (fh, tranfer_ownership)); 77644d93782SGreg Clayton 77744d93782SGreg Clayton File &err_file = m_error_file_sp->GetFile(); 77851b1e2d2SGreg Clayton if (err_file.IsValid() == false) 77951b1e2d2SGreg Clayton err_file.SetStream (stderr, false); 78030fdc8d8SChris Lattner } 78130fdc8d8SChris Lattner 782c5917d9aSJim Ingham void 783c5917d9aSJim Ingham Debugger::SaveInputTerminalState () 784c5917d9aSJim Ingham { 78544d93782SGreg Clayton if (m_input_file_sp) 78644d93782SGreg Clayton { 78744d93782SGreg Clayton File &in_file = m_input_file_sp->GetFile(); 788c5917d9aSJim Ingham if (in_file.GetDescriptor() != File::kInvalidDescriptor) 789c5917d9aSJim Ingham m_terminal_state.Save(in_file.GetDescriptor(), true); 790c5917d9aSJim Ingham } 79144d93782SGreg Clayton } 792c5917d9aSJim Ingham 793c5917d9aSJim Ingham void 794c5917d9aSJim Ingham Debugger::RestoreInputTerminalState () 795c5917d9aSJim Ingham { 796c5917d9aSJim Ingham m_terminal_state.Restore(); 797c5917d9aSJim Ingham } 798c5917d9aSJim Ingham 79930fdc8d8SChris Lattner ExecutionContext 8002976d00aSJim Ingham Debugger::GetSelectedExecutionContext () 80130fdc8d8SChris Lattner { 80230fdc8d8SChris Lattner ExecutionContext exe_ctx; 803c14ee32dSGreg Clayton TargetSP target_sp(GetSelectedTarget()); 804c14ee32dSGreg Clayton exe_ctx.SetTargetSP (target_sp); 80530fdc8d8SChris Lattner 80630fdc8d8SChris Lattner if (target_sp) 80730fdc8d8SChris Lattner { 808c14ee32dSGreg Clayton ProcessSP process_sp (target_sp->GetProcessSP()); 809c14ee32dSGreg Clayton exe_ctx.SetProcessSP (process_sp); 810c14ee32dSGreg Clayton if (process_sp && process_sp->IsRunning() == false) 81130fdc8d8SChris Lattner { 812c14ee32dSGreg Clayton ThreadSP thread_sp (process_sp->GetThreadList().GetSelectedThread()); 813c14ee32dSGreg Clayton if (thread_sp) 81430fdc8d8SChris Lattner { 815c14ee32dSGreg Clayton exe_ctx.SetThreadSP (thread_sp); 816c14ee32dSGreg Clayton exe_ctx.SetFrameSP (thread_sp->GetSelectedFrame()); 817c14ee32dSGreg Clayton if (exe_ctx.GetFramePtr() == NULL) 818c14ee32dSGreg Clayton exe_ctx.SetFrameSP (thread_sp->GetStackFrameAtIndex (0)); 81930fdc8d8SChris Lattner } 82030fdc8d8SChris Lattner } 82130fdc8d8SChris Lattner } 82230fdc8d8SChris Lattner return exe_ctx; 82330fdc8d8SChris Lattner } 82430fdc8d8SChris Lattner 82530fdc8d8SChris Lattner void 826efed6131SCaroline Tice Debugger::DispatchInputInterrupt () 827efed6131SCaroline Tice { 82844d93782SGreg Clayton Mutex::Locker locker (m_input_reader_stack.GetMutex()); 82944d93782SGreg Clayton IOHandlerSP reader_sp (m_input_reader_stack.Top()); 830efed6131SCaroline Tice if (reader_sp) 83144d93782SGreg Clayton reader_sp->Interrupt(); 832efed6131SCaroline Tice } 833efed6131SCaroline Tice 834efed6131SCaroline Tice void 835efed6131SCaroline Tice Debugger::DispatchInputEndOfFile () 836efed6131SCaroline Tice { 83744d93782SGreg Clayton Mutex::Locker locker (m_input_reader_stack.GetMutex()); 83844d93782SGreg Clayton IOHandlerSP reader_sp (m_input_reader_stack.Top()); 839efed6131SCaroline Tice if (reader_sp) 84044d93782SGreg Clayton reader_sp->GotEOF(); 841efed6131SCaroline Tice } 842efed6131SCaroline Tice 843efed6131SCaroline Tice void 84444d93782SGreg Clayton Debugger::ClearIOHandlers () 8453d6086f6SCaroline Tice { 846b44880caSCaroline Tice // The bottom input reader should be the main debugger input reader. We do not want to close that one here. 84744d93782SGreg Clayton Mutex::Locker locker (m_input_reader_stack.GetMutex()); 848d5a0a01bSCaroline Tice while (m_input_reader_stack.GetSize() > 1) 8493d6086f6SCaroline Tice { 85044d93782SGreg Clayton IOHandlerSP reader_sp (m_input_reader_stack.Top()); 8513d6086f6SCaroline Tice if (reader_sp) 8523d6086f6SCaroline Tice { 85344d93782SGreg Clayton m_input_reader_stack.Pop(); 8543d6086f6SCaroline Tice reader_sp->SetIsDone(true); 855e68f5d6bSGreg Clayton reader_sp->Cancel(); 8563d6086f6SCaroline Tice } 8573d6086f6SCaroline Tice } 8583d6086f6SCaroline Tice } 8593d6086f6SCaroline Tice 8603d6086f6SCaroline Tice void 86144d93782SGreg Clayton Debugger::ExecuteIOHanders() 862969ed3d1SCaroline Tice { 86344d93782SGreg Clayton 86444d93782SGreg Clayton while (1) 865969ed3d1SCaroline Tice { 86644d93782SGreg Clayton IOHandlerSP reader_sp(m_input_reader_stack.Top()); 86730fdc8d8SChris Lattner if (!reader_sp) 86830fdc8d8SChris Lattner break; 86930fdc8d8SChris Lattner 87044d93782SGreg Clayton reader_sp->Activate(); 87144d93782SGreg Clayton reader_sp->Run(); 87244d93782SGreg Clayton reader_sp->Deactivate(); 87344d93782SGreg Clayton 87444d93782SGreg Clayton // Remove all input readers that are done from the top of the stack 87544d93782SGreg Clayton while (1) 87630fdc8d8SChris Lattner { 87744d93782SGreg Clayton IOHandlerSP top_reader_sp = m_input_reader_stack.Top(); 87844d93782SGreg Clayton if (top_reader_sp && top_reader_sp->GetIsDone()) 87944d93782SGreg Clayton m_input_reader_stack.Pop(); 88030fdc8d8SChris Lattner else 88130fdc8d8SChris Lattner break; 88230fdc8d8SChris Lattner } 88330fdc8d8SChris Lattner } 88444d93782SGreg Clayton ClearIOHandlers(); 88544d93782SGreg Clayton } 88630fdc8d8SChris Lattner 88744d93782SGreg Clayton bool 88844d93782SGreg Clayton Debugger::IsTopIOHandler (const lldb::IOHandlerSP& reader_sp) 88944d93782SGreg Clayton { 89044d93782SGreg Clayton return m_input_reader_stack.IsTop (reader_sp); 89144d93782SGreg Clayton } 89230fdc8d8SChris Lattner 89344d93782SGreg Clayton 89444d93782SGreg Clayton ConstString 89544d93782SGreg Clayton Debugger::GetTopIOHandlerControlSequence(char ch) 89644d93782SGreg Clayton { 89744d93782SGreg Clayton return m_input_reader_stack.GetTopIOHandlerControlSequence (ch); 89830fdc8d8SChris Lattner } 89930fdc8d8SChris Lattner 90030fdc8d8SChris Lattner void 90144d93782SGreg Clayton Debugger::RunIOHandler (const IOHandlerSP& reader_sp) 90244d93782SGreg Clayton { 90344d93782SGreg Clayton Mutex::Locker locker (m_input_reader_stack.GetMutex()); 90444d93782SGreg Clayton PushIOHandler (reader_sp); 90544d93782SGreg Clayton reader_sp->Activate(); 90644d93782SGreg Clayton reader_sp->Run(); 90744d93782SGreg Clayton PopIOHandler (reader_sp); 90844d93782SGreg Clayton } 90944d93782SGreg Clayton 91044d93782SGreg Clayton void 91144d93782SGreg Clayton Debugger::AdoptTopIOHandlerFilesIfInvalid (StreamFileSP &in, StreamFileSP &out, StreamFileSP &err) 91244d93782SGreg Clayton { 91344d93782SGreg Clayton // Before an IOHandler runs, it must have in/out/err streams. 91444d93782SGreg Clayton // This function is called when one ore more of the streams 91544d93782SGreg Clayton // are NULL. We use the top input reader's in/out/err streams, 91644d93782SGreg Clayton // or fall back to the debugger file handles, or we fall back 91744d93782SGreg Clayton // onto stdin/stdout/stderr as a last resort. 91844d93782SGreg Clayton 91944d93782SGreg Clayton Mutex::Locker locker (m_input_reader_stack.GetMutex()); 92044d93782SGreg Clayton IOHandlerSP top_reader_sp (m_input_reader_stack.Top()); 92144d93782SGreg Clayton // If no STDIN has been set, then set it appropriately 92244d93782SGreg Clayton if (!in) 92344d93782SGreg Clayton { 92444d93782SGreg Clayton if (top_reader_sp) 92544d93782SGreg Clayton in = top_reader_sp->GetInputStreamFile(); 92644d93782SGreg Clayton else 92744d93782SGreg Clayton in = GetInputFile(); 92844d93782SGreg Clayton 92944d93782SGreg Clayton // If there is nothing, use stdin 93044d93782SGreg Clayton if (!in) 93144d93782SGreg Clayton in = StreamFileSP(new StreamFile(stdin, false)); 93244d93782SGreg Clayton } 93344d93782SGreg Clayton // If no STDOUT has been set, then set it appropriately 93444d93782SGreg Clayton if (!out) 93544d93782SGreg Clayton { 93644d93782SGreg Clayton if (top_reader_sp) 93744d93782SGreg Clayton out = top_reader_sp->GetOutputStreamFile(); 93844d93782SGreg Clayton else 93944d93782SGreg Clayton out = GetOutputFile(); 94044d93782SGreg Clayton 94144d93782SGreg Clayton // If there is nothing, use stdout 94244d93782SGreg Clayton if (!out) 94344d93782SGreg Clayton out = StreamFileSP(new StreamFile(stdout, false)); 94444d93782SGreg Clayton } 94544d93782SGreg Clayton // If no STDERR has been set, then set it appropriately 94644d93782SGreg Clayton if (!err) 94744d93782SGreg Clayton { 94844d93782SGreg Clayton if (top_reader_sp) 94944d93782SGreg Clayton err = top_reader_sp->GetErrorStreamFile(); 95044d93782SGreg Clayton else 95144d93782SGreg Clayton err = GetErrorFile(); 95244d93782SGreg Clayton 95344d93782SGreg Clayton // If there is nothing, use stderr 95444d93782SGreg Clayton if (!err) 95544d93782SGreg Clayton err = StreamFileSP(new StreamFile(stdout, false)); 95644d93782SGreg Clayton 95744d93782SGreg Clayton } 95844d93782SGreg Clayton } 95944d93782SGreg Clayton 96044d93782SGreg Clayton void 96144d93782SGreg Clayton Debugger::PushIOHandler (const IOHandlerSP& reader_sp) 96230fdc8d8SChris Lattner { 96330fdc8d8SChris Lattner if (!reader_sp) 96430fdc8d8SChris Lattner return; 965b44880caSCaroline Tice 96644d93782SGreg Clayton // Got the current top input reader... 96744d93782SGreg Clayton IOHandlerSP top_reader_sp (m_input_reader_stack.Top()); 968b44880caSCaroline Tice 969b4874f1aSGreg Clayton // Don't push the same IO handler twice... 970b4874f1aSGreg Clayton if (reader_sp.get() != top_reader_sp.get()) 971b4874f1aSGreg Clayton { 97244d93782SGreg Clayton // Push our new input reader 973d5a0a01bSCaroline Tice m_input_reader_stack.Push (reader_sp); 97444d93782SGreg Clayton 97544d93782SGreg Clayton // Interrupt the top input reader to it will exit its Run() function 97644d93782SGreg Clayton // and let this new input reader take over 97744d93782SGreg Clayton if (top_reader_sp) 97844d93782SGreg Clayton top_reader_sp->Deactivate(); 97930fdc8d8SChris Lattner } 980b4874f1aSGreg Clayton } 98130fdc8d8SChris Lattner 98230fdc8d8SChris Lattner bool 98344d93782SGreg Clayton Debugger::PopIOHandler (const IOHandlerSP& pop_reader_sp) 98430fdc8d8SChris Lattner { 98530fdc8d8SChris Lattner bool result = false; 98630fdc8d8SChris Lattner 98744d93782SGreg Clayton Mutex::Locker locker (m_input_reader_stack.GetMutex()); 98844d93782SGreg Clayton 98930fdc8d8SChris Lattner // The reader on the stop of the stack is done, so let the next 99030fdc8d8SChris Lattner // read on the stack referesh its prompt and if there is one... 991d5a0a01bSCaroline Tice if (!m_input_reader_stack.IsEmpty()) 99230fdc8d8SChris Lattner { 99344d93782SGreg Clayton IOHandlerSP reader_sp(m_input_reader_stack.Top()); 99430fdc8d8SChris Lattner 99530fdc8d8SChris Lattner if (!pop_reader_sp || pop_reader_sp.get() == reader_sp.get()) 99630fdc8d8SChris Lattner { 99744d93782SGreg Clayton reader_sp->Deactivate(); 998b4874f1aSGreg Clayton reader_sp->Cancel(); 999d5a0a01bSCaroline Tice m_input_reader_stack.Pop (); 100030fdc8d8SChris Lattner 1001d5a0a01bSCaroline Tice reader_sp = m_input_reader_stack.Top(); 100230fdc8d8SChris Lattner if (reader_sp) 100344d93782SGreg Clayton reader_sp->Activate(); 100444d93782SGreg Clayton 100544d93782SGreg Clayton result = true; 100630fdc8d8SChris Lattner } 100730fdc8d8SChris Lattner } 100830fdc8d8SChris Lattner return result; 100930fdc8d8SChris Lattner } 101030fdc8d8SChris Lattner 101130fdc8d8SChris Lattner bool 101244d93782SGreg Clayton Debugger::HideTopIOHandler() 101330fdc8d8SChris Lattner { 101444d93782SGreg Clayton Mutex::Locker locker; 101530fdc8d8SChris Lattner 101644d93782SGreg Clayton if (locker.TryLock(m_input_reader_stack.GetMutex())) 101730fdc8d8SChris Lattner { 101844d93782SGreg Clayton IOHandlerSP reader_sp(m_input_reader_stack.Top()); 101944d93782SGreg Clayton if (reader_sp) 102044d93782SGreg Clayton reader_sp->Hide(); 102144d93782SGreg Clayton return true; 102230fdc8d8SChris Lattner } 102344d93782SGreg Clayton return false; 102430fdc8d8SChris Lattner } 102530fdc8d8SChris Lattner 102630fdc8d8SChris Lattner void 102744d93782SGreg Clayton Debugger::RefreshTopIOHandler() 102830fdc8d8SChris Lattner { 102944d93782SGreg Clayton IOHandlerSP reader_sp(m_input_reader_stack.Top()); 103044d93782SGreg Clayton if (reader_sp) 103144d93782SGreg Clayton reader_sp->Refresh(); 103230fdc8d8SChris Lattner } 103344d93782SGreg Clayton 10346611103cSGreg Clayton 10355b52f0c7SJim Ingham StreamSP 10365b52f0c7SJim Ingham Debugger::GetAsyncOutputStream () 10375b52f0c7SJim Ingham { 10385b52f0c7SJim Ingham return StreamSP (new StreamAsynchronousIO (GetCommandInterpreter(), 10395b52f0c7SJim Ingham CommandInterpreter::eBroadcastBitAsynchronousOutputData)); 10405b52f0c7SJim Ingham } 10415b52f0c7SJim Ingham 10425b52f0c7SJim Ingham StreamSP 10435b52f0c7SJim Ingham Debugger::GetAsyncErrorStream () 10445b52f0c7SJim Ingham { 10455b52f0c7SJim Ingham return StreamSP (new StreamAsynchronousIO (GetCommandInterpreter(), 10465b52f0c7SJim Ingham CommandInterpreter::eBroadcastBitAsynchronousErrorData)); 10475b52f0c7SJim Ingham } 10485b52f0c7SJim Ingham 1049c7bece56SGreg Clayton size_t 1050061858ceSEnrico Granata Debugger::GetNumDebuggers() 1051061858ceSEnrico Granata { 1052c15f55e2SGreg Clayton if (g_shared_debugger_refcount > 0) 1053c15f55e2SGreg Clayton { 1054061858ceSEnrico Granata Mutex::Locker locker (GetDebuggerListMutex ()); 1055061858ceSEnrico Granata return GetDebuggerList().size(); 1056061858ceSEnrico Granata } 1057c15f55e2SGreg Clayton return 0; 1058c15f55e2SGreg Clayton } 1059061858ceSEnrico Granata 1060061858ceSEnrico Granata lldb::DebuggerSP 1061c7bece56SGreg Clayton Debugger::GetDebuggerAtIndex (size_t index) 1062061858ceSEnrico Granata { 1063061858ceSEnrico Granata DebuggerSP debugger_sp; 1064061858ceSEnrico Granata 1065c15f55e2SGreg Clayton if (g_shared_debugger_refcount > 0) 1066c15f55e2SGreg Clayton { 1067061858ceSEnrico Granata Mutex::Locker locker (GetDebuggerListMutex ()); 1068061858ceSEnrico Granata DebuggerList &debugger_list = GetDebuggerList(); 1069061858ceSEnrico Granata 1070061858ceSEnrico Granata if (index < debugger_list.size()) 1071061858ceSEnrico Granata debugger_sp = debugger_list[index]; 1072c15f55e2SGreg Clayton } 1073061858ceSEnrico Granata 1074061858ceSEnrico Granata return debugger_sp; 1075061858ceSEnrico Granata } 1076061858ceSEnrico Granata 1077ebc1bb27SCaroline Tice DebuggerSP 1078ebc1bb27SCaroline Tice Debugger::FindDebuggerWithID (lldb::user_id_t id) 1079ebc1bb27SCaroline Tice { 10804d122c40SGreg Clayton DebuggerSP debugger_sp; 1081ebc1bb27SCaroline Tice 1082c15f55e2SGreg Clayton if (g_shared_debugger_refcount > 0) 1083c15f55e2SGreg Clayton { 1084ebc1bb27SCaroline Tice Mutex::Locker locker (GetDebuggerListMutex ()); 1085ebc1bb27SCaroline Tice DebuggerList &debugger_list = GetDebuggerList(); 1086ebc1bb27SCaroline Tice DebuggerList::iterator pos, end = debugger_list.end(); 1087ebc1bb27SCaroline Tice for (pos = debugger_list.begin(); pos != end; ++pos) 1088ebc1bb27SCaroline Tice { 1089ebc1bb27SCaroline Tice if ((*pos).get()->GetID() == id) 1090ebc1bb27SCaroline Tice { 1091ebc1bb27SCaroline Tice debugger_sp = *pos; 1092ebc1bb27SCaroline Tice break; 1093ebc1bb27SCaroline Tice } 1094ebc1bb27SCaroline Tice } 1095c15f55e2SGreg Clayton } 1096ebc1bb27SCaroline Tice return debugger_sp; 1097ebc1bb27SCaroline Tice } 10983df9a8dfSCaroline Tice 10992643b905SSaleem Abdulrasool #if 0 11001b654882SGreg Clayton static void 1101b57e4a1bSJason Molenda TestPromptFormats (StackFrame *frame) 11021b654882SGreg Clayton { 11031b654882SGreg Clayton if (frame == NULL) 11041b654882SGreg Clayton return; 11051b654882SGreg Clayton 11061b654882SGreg Clayton StreamString s; 11071b654882SGreg Clayton const char *prompt_format = 11081b654882SGreg Clayton "{addr = '${addr}'\n}" 11091b654882SGreg Clayton "{process.id = '${process.id}'\n}" 11101b654882SGreg Clayton "{process.name = '${process.name}'\n}" 11111b654882SGreg Clayton "{process.file.basename = '${process.file.basename}'\n}" 11121b654882SGreg Clayton "{process.file.fullpath = '${process.file.fullpath}'\n}" 11131b654882SGreg Clayton "{thread.id = '${thread.id}'\n}" 11141b654882SGreg Clayton "{thread.index = '${thread.index}'\n}" 11151b654882SGreg Clayton "{thread.name = '${thread.name}'\n}" 11161b654882SGreg Clayton "{thread.queue = '${thread.queue}'\n}" 11171b654882SGreg Clayton "{thread.stop-reason = '${thread.stop-reason}'\n}" 11181b654882SGreg Clayton "{target.arch = '${target.arch}'\n}" 11191b654882SGreg Clayton "{module.file.basename = '${module.file.basename}'\n}" 11201b654882SGreg Clayton "{module.file.fullpath = '${module.file.fullpath}'\n}" 11211b654882SGreg Clayton "{file.basename = '${file.basename}'\n}" 11221b654882SGreg Clayton "{file.fullpath = '${file.fullpath}'\n}" 11231b654882SGreg Clayton "{frame.index = '${frame.index}'\n}" 11241b654882SGreg Clayton "{frame.pc = '${frame.pc}'\n}" 11251b654882SGreg Clayton "{frame.sp = '${frame.sp}'\n}" 11261b654882SGreg Clayton "{frame.fp = '${frame.fp}'\n}" 11271b654882SGreg Clayton "{frame.flags = '${frame.flags}'\n}" 11281b654882SGreg Clayton "{frame.reg.rdi = '${frame.reg.rdi}'\n}" 11291b654882SGreg Clayton "{frame.reg.rip = '${frame.reg.rip}'\n}" 11301b654882SGreg Clayton "{frame.reg.rsp = '${frame.reg.rsp}'\n}" 11311b654882SGreg Clayton "{frame.reg.rbp = '${frame.reg.rbp}'\n}" 11321b654882SGreg Clayton "{frame.reg.rflags = '${frame.reg.rflags}'\n}" 11331b654882SGreg Clayton "{frame.reg.xmm0 = '${frame.reg.xmm0}'\n}" 11341b654882SGreg Clayton "{frame.reg.carp = '${frame.reg.carp}'\n}" 11351b654882SGreg Clayton "{function.id = '${function.id}'\n}" 11361b654882SGreg Clayton "{function.name = '${function.name}'\n}" 1137ccbc08e6SGreg Clayton "{function.name-with-args = '${function.name-with-args}'\n}" 11381b654882SGreg Clayton "{function.addr-offset = '${function.addr-offset}'\n}" 11391b654882SGreg Clayton "{function.line-offset = '${function.line-offset}'\n}" 11401b654882SGreg Clayton "{function.pc-offset = '${function.pc-offset}'\n}" 11411b654882SGreg Clayton "{line.file.basename = '${line.file.basename}'\n}" 11421b654882SGreg Clayton "{line.file.fullpath = '${line.file.fullpath}'\n}" 11431b654882SGreg Clayton "{line.number = '${line.number}'\n}" 11441b654882SGreg Clayton "{line.start-addr = '${line.start-addr}'\n}" 11451b654882SGreg Clayton "{line.end-addr = '${line.end-addr}'\n}" 11461b654882SGreg Clayton ; 11471b654882SGreg Clayton 11481b654882SGreg Clayton SymbolContext sc (frame->GetSymbolContext(eSymbolContextEverything)); 11491b654882SGreg Clayton ExecutionContext exe_ctx; 11500603aa9dSGreg Clayton frame->CalculateExecutionContext(exe_ctx); 1151c3ce7f27SMichael Sartain if (Debugger::FormatPrompt (prompt_format, &sc, &exe_ctx, &sc.line_entry.range.GetBaseAddress(), s)) 11521b654882SGreg Clayton { 11531b654882SGreg Clayton printf("%s\n", s.GetData()); 11541b654882SGreg Clayton } 11551b654882SGreg Clayton else 11561b654882SGreg Clayton { 11571b654882SGreg Clayton printf ("what we got: %s\n", s.GetData()); 11581b654882SGreg Clayton } 11591b654882SGreg Clayton } 11602643b905SSaleem Abdulrasool #endif 11611b654882SGreg Clayton 11629fc1944eSEnrico Granata static bool 11639fc1944eSEnrico Granata ScanFormatDescriptor (const char* var_name_begin, 11649fc1944eSEnrico Granata const char* var_name_end, 11659fc1944eSEnrico Granata const char** var_name_final, 11669fc1944eSEnrico Granata const char** percent_position, 11674d122c40SGreg Clayton Format* custom_format, 11689fc1944eSEnrico Granata ValueObject::ValueObjectRepresentationStyle* val_obj_display) 11699fc1944eSEnrico Granata { 11705160ce5cSGreg Clayton Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES)); 11719fc1944eSEnrico Granata *percent_position = ::strchr(var_name_begin,'%'); 11729fc1944eSEnrico Granata if (!*percent_position || *percent_position > var_name_end) 1173e992a089SEnrico Granata { 1174e992a089SEnrico Granata if (log) 1175d228483dSEnrico Granata log->Printf("[ScanFormatDescriptor] no format descriptor in string, skipping"); 11769fc1944eSEnrico Granata *var_name_final = var_name_end; 1177e992a089SEnrico Granata } 11789fc1944eSEnrico Granata else 11799fc1944eSEnrico Granata { 11809fc1944eSEnrico Granata *var_name_final = *percent_position; 118136aa5ae6SEnrico Granata std::string format_name(*var_name_final+1, var_name_end-*var_name_final-1); 1182e992a089SEnrico Granata if (log) 118368ae4117SEnrico Granata log->Printf("[ScanFormatDescriptor] parsing %s as a format descriptor", format_name.c_str()); 118436aa5ae6SEnrico Granata if ( !FormatManager::GetFormatFromCString(format_name.c_str(), 11859fc1944eSEnrico Granata true, 11869fc1944eSEnrico Granata *custom_format) ) 11879fc1944eSEnrico Granata { 1188e992a089SEnrico Granata if (log) 118968ae4117SEnrico Granata log->Printf("[ScanFormatDescriptor] %s is an unknown format", format_name.c_str()); 119036aa5ae6SEnrico Granata 119136aa5ae6SEnrico Granata switch (format_name.front()) 119236aa5ae6SEnrico Granata { 119336aa5ae6SEnrico Granata case '@': // if this is an @ sign, print ObjC description 119486cc9829SEnrico Granata *val_obj_display = ValueObject::eValueObjectRepresentationStyleLanguageSpecific; 119536aa5ae6SEnrico Granata break; 119636aa5ae6SEnrico Granata case 'V': // if this is a V, print the value using the default format 119786cc9829SEnrico Granata *val_obj_display = ValueObject::eValueObjectRepresentationStyleValue; 119836aa5ae6SEnrico Granata break; 119936aa5ae6SEnrico Granata case 'L': // if this is an L, print the location of the value 120086cc9829SEnrico Granata *val_obj_display = ValueObject::eValueObjectRepresentationStyleLocation; 120136aa5ae6SEnrico Granata break; 120236aa5ae6SEnrico Granata case 'S': // if this is an S, print the summary after all 120386cc9829SEnrico Granata *val_obj_display = ValueObject::eValueObjectRepresentationStyleSummary; 120436aa5ae6SEnrico Granata break; 120536aa5ae6SEnrico Granata case '#': // if this is a '#', print the number of children 120686cc9829SEnrico Granata *val_obj_display = ValueObject::eValueObjectRepresentationStyleChildrenCount; 120736aa5ae6SEnrico Granata break; 120836aa5ae6SEnrico Granata case 'T': // if this is a 'T', print the type 120986cc9829SEnrico Granata *val_obj_display = ValueObject::eValueObjectRepresentationStyleType; 121036aa5ae6SEnrico Granata break; 12112c75f11eSEnrico Granata case 'N': // if this is a 'N', print the name 12122c75f11eSEnrico Granata *val_obj_display = ValueObject::eValueObjectRepresentationStyleName; 12132c75f11eSEnrico Granata break; 12142c75f11eSEnrico Granata case '>': // if this is a '>', print the name 12152c75f11eSEnrico Granata *val_obj_display = ValueObject::eValueObjectRepresentationStyleExpressionPath; 12162c75f11eSEnrico Granata break; 121736aa5ae6SEnrico Granata default: 12185c42d8a8SJim Ingham if (log) 121936aa5ae6SEnrico Granata log->Printf("ScanFormatDescriptor] %s is an error, leaving the previous value alone", format_name.c_str()); 122036aa5ae6SEnrico Granata break; 122136aa5ae6SEnrico Granata } 12229fc1944eSEnrico Granata } 12239fc1944eSEnrico Granata // a good custom format tells us to print the value using it 12249fc1944eSEnrico Granata else 1225e992a089SEnrico Granata { 1226e992a089SEnrico Granata if (log) 122768ae4117SEnrico Granata log->Printf("[ScanFormatDescriptor] will display value for this VO"); 122886cc9829SEnrico Granata *val_obj_display = ValueObject::eValueObjectRepresentationStyleValue; 1229e992a089SEnrico Granata } 12309fc1944eSEnrico Granata } 1231e992a089SEnrico Granata if (log) 123268ae4117SEnrico Granata log->Printf("[ScanFormatDescriptor] final format description outcome: custom_format = %d, val_obj_display = %d", 1233e992a089SEnrico Granata *custom_format, 1234e992a089SEnrico Granata *val_obj_display); 12359fc1944eSEnrico Granata return true; 12369fc1944eSEnrico Granata } 12379fc1944eSEnrico Granata 12389fc1944eSEnrico Granata static bool 12399fc1944eSEnrico Granata ScanBracketedRange (const char* var_name_begin, 12409fc1944eSEnrico Granata const char* var_name_end, 12419fc1944eSEnrico Granata const char* var_name_final, 12429fc1944eSEnrico Granata const char** open_bracket_position, 12439fc1944eSEnrico Granata const char** separator_position, 12449fc1944eSEnrico Granata const char** close_bracket_position, 12459fc1944eSEnrico Granata const char** var_name_final_if_array_range, 12469fc1944eSEnrico Granata int64_t* index_lower, 12479fc1944eSEnrico Granata int64_t* index_higher) 12489fc1944eSEnrico Granata { 12495160ce5cSGreg Clayton Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES)); 12509fc1944eSEnrico Granata *open_bracket_position = ::strchr(var_name_begin,'['); 12519fc1944eSEnrico Granata if (*open_bracket_position && *open_bracket_position < var_name_final) 12529fc1944eSEnrico Granata { 12539fc1944eSEnrico Granata *separator_position = ::strchr(*open_bracket_position,'-'); // might be NULL if this is a simple var[N] bitfield 12549fc1944eSEnrico Granata *close_bracket_position = ::strchr(*open_bracket_position,']'); 12559fc1944eSEnrico Granata // as usual, we assume that [] will come before % 12569fc1944eSEnrico Granata //printf("trying to expand a []\n"); 12579fc1944eSEnrico Granata *var_name_final_if_array_range = *open_bracket_position; 12589fc1944eSEnrico Granata if (*close_bracket_position - *open_bracket_position == 1) 12599fc1944eSEnrico Granata { 1260e992a089SEnrico Granata if (log) 1261d228483dSEnrico Granata log->Printf("[ScanBracketedRange] '[]' detected.. going from 0 to end of data"); 12629fc1944eSEnrico Granata *index_lower = 0; 12639fc1944eSEnrico Granata } 12649fc1944eSEnrico Granata else if (*separator_position == NULL || *separator_position > var_name_end) 12659fc1944eSEnrico Granata { 12669fc1944eSEnrico Granata char *end = NULL; 12679fc1944eSEnrico Granata *index_lower = ::strtoul (*open_bracket_position+1, &end, 0); 12689fc1944eSEnrico Granata *index_higher = *index_lower; 1269e992a089SEnrico Granata if (log) 1270d01b2953SDaniel Malea log->Printf("[ScanBracketedRange] [%" PRId64 "] detected, high index is same", *index_lower); 12719fc1944eSEnrico Granata } 12729fc1944eSEnrico Granata else if (*close_bracket_position && *close_bracket_position < var_name_end) 12739fc1944eSEnrico Granata { 12749fc1944eSEnrico Granata char *end = NULL; 12759fc1944eSEnrico Granata *index_lower = ::strtoul (*open_bracket_position+1, &end, 0); 12769fc1944eSEnrico Granata *index_higher = ::strtoul (*separator_position+1, &end, 0); 1277e992a089SEnrico Granata if (log) 1278d01b2953SDaniel Malea log->Printf("[ScanBracketedRange] [%" PRId64 "-%" PRId64 "] detected", *index_lower, *index_higher); 12799fc1944eSEnrico Granata } 12809fc1944eSEnrico Granata else 1281e992a089SEnrico Granata { 1282e992a089SEnrico Granata if (log) 1283d228483dSEnrico Granata log->Printf("[ScanBracketedRange] expression is erroneous, cannot extract indices out of it"); 12849fc1944eSEnrico Granata return false; 1285e992a089SEnrico Granata } 12869fc1944eSEnrico Granata if (*index_lower > *index_higher && *index_higher > 0) 12879fc1944eSEnrico Granata { 1288e992a089SEnrico Granata if (log) 1289d228483dSEnrico Granata log->Printf("[ScanBracketedRange] swapping indices"); 1290c7bece56SGreg Clayton int64_t temp = *index_lower; 12919fc1944eSEnrico Granata *index_lower = *index_higher; 12929fc1944eSEnrico Granata *index_higher = temp; 12939fc1944eSEnrico Granata } 12949fc1944eSEnrico Granata } 1295e992a089SEnrico Granata else if (log) 1296d228483dSEnrico Granata log->Printf("[ScanBracketedRange] no bracketed range, skipping entirely"); 12979fc1944eSEnrico Granata return true; 12989fc1944eSEnrico Granata } 12999fc1944eSEnrico Granata 13000769b2b1SMichael Sartain template <typename T> 13010769b2b1SMichael Sartain static bool RunScriptFormatKeyword(Stream &s, ScriptInterpreter *script_interpreter, T t, const std::string& script_name) 13020769b2b1SMichael Sartain { 13030769b2b1SMichael Sartain if (script_interpreter) 13040769b2b1SMichael Sartain { 13050769b2b1SMichael Sartain Error script_error; 13060769b2b1SMichael Sartain std::string script_output; 13070769b2b1SMichael Sartain 13080769b2b1SMichael Sartain if (script_interpreter->RunScriptFormatKeyword(script_name.c_str(), t, script_output, script_error) && script_error.Success()) 13090769b2b1SMichael Sartain { 13100769b2b1SMichael Sartain s.Printf("%s", script_output.c_str()); 13110769b2b1SMichael Sartain return true; 13120769b2b1SMichael Sartain } 13130769b2b1SMichael Sartain else 13140769b2b1SMichael Sartain { 13150769b2b1SMichael Sartain s.Printf("<error: %s>",script_error.AsCString()); 13160769b2b1SMichael Sartain } 13170769b2b1SMichael Sartain } 13180769b2b1SMichael Sartain return false; 13190769b2b1SMichael Sartain } 13200769b2b1SMichael Sartain 13219fc1944eSEnrico Granata static ValueObjectSP 1322c482a192SEnrico Granata ExpandIndexedExpression (ValueObject* valobj, 1323c7bece56SGreg Clayton size_t index, 1324b57e4a1bSJason Molenda StackFrame* frame, 1325fc7a7f3bSEnrico Granata bool deref_pointer) 13269fc1944eSEnrico Granata { 13275160ce5cSGreg Clayton Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES)); 1328fc7a7f3bSEnrico Granata const char* ptr_deref_format = "[%d]"; 1329599171adSEnrico Granata std::string ptr_deref_buffer(10,0); 1330599171adSEnrico Granata ::sprintf(&ptr_deref_buffer[0], ptr_deref_format, index); 1331e992a089SEnrico Granata if (log) 1332599171adSEnrico Granata log->Printf("[ExpandIndexedExpression] name to deref: %s",ptr_deref_buffer.c_str()); 1333fc7a7f3bSEnrico Granata const char* first_unparsed; 1334fc7a7f3bSEnrico Granata ValueObject::GetValueForExpressionPathOptions options; 1335fc7a7f3bSEnrico Granata ValueObject::ExpressionPathEndResultType final_value_type; 1336fc7a7f3bSEnrico Granata ValueObject::ExpressionPathScanEndReason reason_to_stop; 133786cc9829SEnrico Granata ValueObject::ExpressionPathAftermath what_next = (deref_pointer ? ValueObject::eExpressionPathAftermathDereference : ValueObject::eExpressionPathAftermathNothing); 1338599171adSEnrico Granata ValueObjectSP item = valobj->GetValueForExpressionPath (ptr_deref_buffer.c_str(), 1339fc7a7f3bSEnrico Granata &first_unparsed, 1340fc7a7f3bSEnrico Granata &reason_to_stop, 1341fc7a7f3bSEnrico Granata &final_value_type, 1342fc7a7f3bSEnrico Granata options, 1343fc7a7f3bSEnrico Granata &what_next); 1344fc7a7f3bSEnrico Granata if (!item) 1345fc7a7f3bSEnrico Granata { 1346e992a089SEnrico Granata if (log) 1347d228483dSEnrico Granata log->Printf("[ExpandIndexedExpression] ERROR: unparsed portion = %s, why stopping = %d," 1348e992a089SEnrico Granata " final_value_type %d", 1349fc7a7f3bSEnrico Granata first_unparsed, reason_to_stop, final_value_type); 1350fc7a7f3bSEnrico Granata } 13519fc1944eSEnrico Granata else 13529fc1944eSEnrico Granata { 1353e992a089SEnrico Granata if (log) 1354d228483dSEnrico Granata log->Printf("[ExpandIndexedExpression] ALL RIGHT: unparsed portion = %s, why stopping = %d," 1355e992a089SEnrico Granata " final_value_type %d", 1356fc7a7f3bSEnrico Granata first_unparsed, reason_to_stop, final_value_type); 13579fc1944eSEnrico Granata } 13589fc1944eSEnrico Granata return item; 13599fc1944eSEnrico Granata } 13609fc1944eSEnrico Granata 13610769b2b1SMichael Sartain static inline bool 13620769b2b1SMichael Sartain IsToken(const char *var_name_begin, const char *var) 13630769b2b1SMichael Sartain { 13640769b2b1SMichael Sartain return (::strncmp (var_name_begin, var, strlen(var)) == 0); 13650769b2b1SMichael Sartain } 13660769b2b1SMichael Sartain 13670769b2b1SMichael Sartain static bool 13680769b2b1SMichael Sartain IsTokenWithFormat(const char *var_name_begin, const char *var, std::string &format, const char *default_format, 13690769b2b1SMichael Sartain const ExecutionContext *exe_ctx_ptr, const SymbolContext *sc_ptr) 13700769b2b1SMichael Sartain { 13710769b2b1SMichael Sartain int var_len = strlen(var); 13720769b2b1SMichael Sartain if (::strncmp (var_name_begin, var, var_len) == 0) 13730769b2b1SMichael Sartain { 13740769b2b1SMichael Sartain var_name_begin += var_len; 13750769b2b1SMichael Sartain if (*var_name_begin == '}') 13760769b2b1SMichael Sartain { 13770769b2b1SMichael Sartain format = default_format; 13780769b2b1SMichael Sartain return true; 13790769b2b1SMichael Sartain } 13800769b2b1SMichael Sartain else if (*var_name_begin == '%') 13810769b2b1SMichael Sartain { 13820769b2b1SMichael Sartain // Allow format specifiers: x|X|u with optional width specifiers. 13830769b2b1SMichael Sartain // ${thread.id%x} ; hex 13840769b2b1SMichael Sartain // ${thread.id%X} ; uppercase hex 13850769b2b1SMichael Sartain // ${thread.id%u} ; unsigned decimal 13860769b2b1SMichael Sartain // ${thread.id%8.8X} ; width.precision + specifier 13870769b2b1SMichael Sartain // ${thread.id%tid} ; unsigned on FreeBSD/Linux, otherwise default_format (0x%4.4x for thread.id) 13880769b2b1SMichael Sartain int dot_count = 0; 13890769b2b1SMichael Sartain const char *specifier = NULL; 13900769b2b1SMichael Sartain int width_precision_length = 0; 13910769b2b1SMichael Sartain const char *width_precision = ++var_name_begin; 13920769b2b1SMichael Sartain while (isdigit(*var_name_begin) || *var_name_begin == '.') 13930769b2b1SMichael Sartain { 13940769b2b1SMichael Sartain dot_count += (*var_name_begin == '.'); 13950769b2b1SMichael Sartain if (dot_count > 1) 13960769b2b1SMichael Sartain break; 13970769b2b1SMichael Sartain var_name_begin++; 13980769b2b1SMichael Sartain width_precision_length++; 13990769b2b1SMichael Sartain } 14000769b2b1SMichael Sartain 14010769b2b1SMichael Sartain if (IsToken (var_name_begin, "tid}")) 14020769b2b1SMichael Sartain { 14030769b2b1SMichael Sartain Target *target = Target::GetTargetFromContexts (exe_ctx_ptr, sc_ptr); 14040769b2b1SMichael Sartain if (target) 14050769b2b1SMichael Sartain { 14060769b2b1SMichael Sartain ArchSpec arch (target->GetArchitecture ()); 14070769b2b1SMichael Sartain llvm::Triple::OSType ostype = arch.IsValid() ? arch.GetTriple().getOS() : llvm::Triple::UnknownOS; 14080769b2b1SMichael Sartain if ((ostype == llvm::Triple::FreeBSD) || (ostype == llvm::Triple::Linux)) 14090769b2b1SMichael Sartain specifier = PRIu64; 14100769b2b1SMichael Sartain } 14110769b2b1SMichael Sartain if (!specifier) 14120769b2b1SMichael Sartain { 14130769b2b1SMichael Sartain format = default_format; 14140769b2b1SMichael Sartain return true; 14150769b2b1SMichael Sartain } 14160769b2b1SMichael Sartain } 14170769b2b1SMichael Sartain else if (IsToken (var_name_begin, "x}")) 14180769b2b1SMichael Sartain specifier = PRIx64; 14190769b2b1SMichael Sartain else if (IsToken (var_name_begin, "X}")) 14200769b2b1SMichael Sartain specifier = PRIX64; 14210769b2b1SMichael Sartain else if (IsToken (var_name_begin, "u}")) 14220769b2b1SMichael Sartain specifier = PRIu64; 14230769b2b1SMichael Sartain 14240769b2b1SMichael Sartain if (specifier) 14250769b2b1SMichael Sartain { 14260769b2b1SMichael Sartain format = "%"; 14270769b2b1SMichael Sartain if (width_precision_length) 14280769b2b1SMichael Sartain format += std::string(width_precision, width_precision_length); 14290769b2b1SMichael Sartain format += specifier; 14300769b2b1SMichael Sartain return true; 14310769b2b1SMichael Sartain } 14320769b2b1SMichael Sartain } 14330769b2b1SMichael Sartain } 14340769b2b1SMichael Sartain return false; 14350769b2b1SMichael Sartain } 14360769b2b1SMichael Sartain 1437*705b1809SJason Molenda // Find information for the "thread.info.*" specifiers in a format string 1438*705b1809SJason Molenda static bool 1439*705b1809SJason Molenda FormatThreadExtendedInfoRecurse 1440*705b1809SJason Molenda ( 1441*705b1809SJason Molenda const char *var_name_begin, 1442*705b1809SJason Molenda StructuredData::ObjectSP thread_info_dictionary, 1443*705b1809SJason Molenda const SymbolContext *sc, 1444*705b1809SJason Molenda const ExecutionContext *exe_ctx, 1445*705b1809SJason Molenda Stream &s 1446*705b1809SJason Molenda ) 1447*705b1809SJason Molenda { 1448*705b1809SJason Molenda bool var_success = false; 1449*705b1809SJason Molenda std::string token_format; 1450*705b1809SJason Molenda 1451*705b1809SJason Molenda llvm::StringRef var_name(var_name_begin); 1452*705b1809SJason Molenda size_t percent_idx = var_name.find('%'); 1453*705b1809SJason Molenda size_t close_curly_idx = var_name.find('}'); 1454*705b1809SJason Molenda llvm::StringRef path = var_name; 1455*705b1809SJason Molenda llvm::StringRef formatter = var_name; 1456*705b1809SJason Molenda 1457*705b1809SJason Molenda // 'path' will be the dot separated list of objects to transverse up until we hit 1458*705b1809SJason Molenda // a close curly brace, a percent sign, or an end of string. 1459*705b1809SJason Molenda if (percent_idx != llvm::StringRef::npos || close_curly_idx != llvm::StringRef::npos) 1460*705b1809SJason Molenda { 1461*705b1809SJason Molenda if (percent_idx != llvm::StringRef::npos && close_curly_idx != llvm::StringRef::npos) 1462*705b1809SJason Molenda { 1463*705b1809SJason Molenda if (percent_idx < close_curly_idx) 1464*705b1809SJason Molenda { 1465*705b1809SJason Molenda path = var_name.slice(0, percent_idx); 1466*705b1809SJason Molenda formatter = var_name.substr (percent_idx); 1467*705b1809SJason Molenda } 1468*705b1809SJason Molenda else 1469*705b1809SJason Molenda { 1470*705b1809SJason Molenda path = var_name.slice(0, close_curly_idx); 1471*705b1809SJason Molenda formatter = var_name.substr (close_curly_idx); 1472*705b1809SJason Molenda } 1473*705b1809SJason Molenda } 1474*705b1809SJason Molenda else if (percent_idx != llvm::StringRef::npos) 1475*705b1809SJason Molenda { 1476*705b1809SJason Molenda path = var_name.slice(0, percent_idx); 1477*705b1809SJason Molenda formatter = var_name.substr (percent_idx); 1478*705b1809SJason Molenda } 1479*705b1809SJason Molenda else if (close_curly_idx != llvm::StringRef::npos) 1480*705b1809SJason Molenda { 1481*705b1809SJason Molenda path = var_name.slice(0, close_curly_idx); 1482*705b1809SJason Molenda formatter = var_name.substr (close_curly_idx); 1483*705b1809SJason Molenda } 1484*705b1809SJason Molenda } 1485*705b1809SJason Molenda 1486*705b1809SJason Molenda StructuredData::ObjectSP value = thread_info_dictionary->GetObjectForDotSeparatedPath (path); 1487*705b1809SJason Molenda 1488*705b1809SJason Molenda if (value.get()) 1489*705b1809SJason Molenda { 1490*705b1809SJason Molenda if (value->GetType() == StructuredData::Type::eTypeInteger) 1491*705b1809SJason Molenda { 1492*705b1809SJason Molenda if (IsTokenWithFormat (formatter.str().c_str(), "", token_format, "0x%4.4" PRIx64, exe_ctx, sc)) 1493*705b1809SJason Molenda { 1494*705b1809SJason Molenda s.Printf(token_format.c_str(), value->GetAsInteger()->GetValue()); 1495*705b1809SJason Molenda var_success = true; 1496*705b1809SJason Molenda } 1497*705b1809SJason Molenda } 1498*705b1809SJason Molenda else if (value->GetType() == StructuredData::Type::eTypeFloat) 1499*705b1809SJason Molenda { 1500*705b1809SJason Molenda s.Printf ("%f", value->GetAsFloat()->GetValue()); 1501*705b1809SJason Molenda var_success = true; 1502*705b1809SJason Molenda } 1503*705b1809SJason Molenda else if (value->GetType() == StructuredData::Type::eTypeString) 1504*705b1809SJason Molenda { 1505*705b1809SJason Molenda s.Printf("%s", value->GetAsString()->GetValue().c_str()); 1506*705b1809SJason Molenda var_success = true; 1507*705b1809SJason Molenda } 1508*705b1809SJason Molenda else if (value->GetType() == StructuredData::Type::eTypeArray) 1509*705b1809SJason Molenda { 1510*705b1809SJason Molenda if (value->GetAsArray()->GetSize() > 0) 1511*705b1809SJason Molenda { 1512*705b1809SJason Molenda s.Printf ("%zu", value->GetAsArray()->GetSize()); 1513*705b1809SJason Molenda var_success = true; 1514*705b1809SJason Molenda } 1515*705b1809SJason Molenda } 1516*705b1809SJason Molenda else if (value->GetType() == StructuredData::Type::eTypeDictionary) 1517*705b1809SJason Molenda { 1518*705b1809SJason Molenda s.Printf ("%zu", value->GetAsDictionary()->GetKeys()->GetAsArray()->GetSize()); 1519*705b1809SJason Molenda var_success = true; 1520*705b1809SJason Molenda } 1521*705b1809SJason Molenda } 1522*705b1809SJason Molenda 1523*705b1809SJason Molenda return var_success; 1524*705b1809SJason Molenda } 1525*705b1809SJason Molenda 1526*705b1809SJason Molenda 1527c3ce7f27SMichael Sartain static bool 1528c3ce7f27SMichael Sartain FormatPromptRecurse 15291b654882SGreg Clayton ( 15301b654882SGreg Clayton const char *format, 15311b654882SGreg Clayton const SymbolContext *sc, 15321b654882SGreg Clayton const ExecutionContext *exe_ctx, 15331b654882SGreg Clayton const Address *addr, 15341b654882SGreg Clayton Stream &s, 15354becb37eSEnrico Granata const char **end, 1536c482a192SEnrico Granata ValueObject* valobj 15371b654882SGreg Clayton ) 15381b654882SGreg Clayton { 1539c482a192SEnrico Granata ValueObject* realvalobj = NULL; // makes it super-easy to parse pointers 15401b654882SGreg Clayton bool success = true; 15411b654882SGreg Clayton const char *p; 15425160ce5cSGreg Clayton Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES)); 1543c3ce7f27SMichael Sartain 15441b654882SGreg Clayton for (p = format; *p != '\0'; ++p) 15451b654882SGreg Clayton { 1546c482a192SEnrico Granata if (realvalobj) 15474becb37eSEnrico Granata { 1548c482a192SEnrico Granata valobj = realvalobj; 1549c482a192SEnrico Granata realvalobj = NULL; 15504becb37eSEnrico Granata } 15511b654882SGreg Clayton size_t non_special_chars = ::strcspn (p, "${}\\"); 15521b654882SGreg Clayton if (non_special_chars > 0) 15531b654882SGreg Clayton { 15541b654882SGreg Clayton if (success) 15551b654882SGreg Clayton s.Write (p, non_special_chars); 15561b654882SGreg Clayton p += non_special_chars; 15571b654882SGreg Clayton } 15581b654882SGreg Clayton 15591b654882SGreg Clayton if (*p == '\0') 15601b654882SGreg Clayton { 15611b654882SGreg Clayton break; 15621b654882SGreg Clayton } 15631b654882SGreg Clayton else if (*p == '{') 15641b654882SGreg Clayton { 15651b654882SGreg Clayton // Start a new scope that must have everything it needs if it is to 15661b654882SGreg Clayton // to make it into the final output stream "s". If you want to make 15671b654882SGreg Clayton // a format that only prints out the function or symbol name if there 15681b654882SGreg Clayton // is one in the symbol context you can use: 15691b654882SGreg Clayton // "{function =${function.name}}" 15701b654882SGreg Clayton // The first '{' starts a new scope that end with the matching '}' at 15711b654882SGreg Clayton // the end of the string. The contents "function =${function.name}" 15721b654882SGreg Clayton // will then be evaluated and only be output if there is a function 15731b654882SGreg Clayton // or symbol with a valid name. 15741b654882SGreg Clayton StreamString sub_strm; 15751b654882SGreg Clayton 15761b654882SGreg Clayton ++p; // Skip the '{' 15771b654882SGreg Clayton 1578c3ce7f27SMichael Sartain if (FormatPromptRecurse (p, sc, exe_ctx, addr, sub_strm, &p, valobj)) 15791b654882SGreg Clayton { 15801b654882SGreg Clayton // The stream had all it needed 15811b654882SGreg Clayton s.Write(sub_strm.GetData(), sub_strm.GetSize()); 15821b654882SGreg Clayton } 15831b654882SGreg Clayton if (*p != '}') 15841b654882SGreg Clayton { 15851b654882SGreg Clayton success = false; 15861b654882SGreg Clayton break; 15871b654882SGreg Clayton } 15881b654882SGreg Clayton } 15891b654882SGreg Clayton else if (*p == '}') 15901b654882SGreg Clayton { 15911b654882SGreg Clayton // End of a enclosing scope 15921b654882SGreg Clayton break; 15931b654882SGreg Clayton } 15941b654882SGreg Clayton else if (*p == '$') 15951b654882SGreg Clayton { 15961b654882SGreg Clayton // We have a prompt variable to print 15971b654882SGreg Clayton ++p; 15981b654882SGreg Clayton if (*p == '{') 15991b654882SGreg Clayton { 16001b654882SGreg Clayton ++p; 16011b654882SGreg Clayton const char *var_name_begin = p; 16021b654882SGreg Clayton const char *var_name_end = ::strchr (p, '}'); 16031b654882SGreg Clayton 16041b654882SGreg Clayton if (var_name_end && var_name_begin < var_name_end) 16051b654882SGreg Clayton { 16061b654882SGreg Clayton // if we have already failed to parse, skip this variable 16071b654882SGreg Clayton if (success) 16081b654882SGreg Clayton { 16091b654882SGreg Clayton const char *cstr = NULL; 16100769b2b1SMichael Sartain std::string token_format; 16111b654882SGreg Clayton Address format_addr; 16121b654882SGreg Clayton bool calculate_format_addr_function_offset = false; 16131b654882SGreg Clayton // Set reg_kind and reg_num to invalid values 16141b654882SGreg Clayton RegisterKind reg_kind = kNumRegisterKinds; 16151b654882SGreg Clayton uint32_t reg_num = LLDB_INVALID_REGNUM; 16161b654882SGreg Clayton FileSpec format_file_spec; 1617e0d378b3SGreg Clayton const RegisterInfo *reg_info = NULL; 16181b654882SGreg Clayton RegisterContext *reg_ctx = NULL; 16199fc1944eSEnrico Granata bool do_deref_pointer = false; 162086cc9829SEnrico Granata ValueObject::ExpressionPathScanEndReason reason_to_stop = ValueObject::eExpressionPathScanEndReasonEndOfString; 162186cc9829SEnrico Granata ValueObject::ExpressionPathEndResultType final_value_type = ValueObject::eExpressionPathEndResultTypePlain; 16221b654882SGreg Clayton 16231b654882SGreg Clayton // Each variable must set success to true below... 16241b654882SGreg Clayton bool var_success = false; 16251b654882SGreg Clayton switch (var_name_begin[0]) 16261b654882SGreg Clayton { 16274becb37eSEnrico Granata case '*': 16286f3533fbSEnrico Granata case 'v': 16296f3533fbSEnrico Granata case 's': 16304becb37eSEnrico Granata { 1631c482a192SEnrico Granata if (!valobj) 163234132754SGreg Clayton break; 16336f3533fbSEnrico Granata 1634c3e320a7SEnrico Granata if (log) 1635d228483dSEnrico Granata log->Printf("[Debugger::FormatPrompt] initial string: %s",var_name_begin); 1636c3e320a7SEnrico Granata 16376f3533fbSEnrico Granata // check for *var and *svar 16386f3533fbSEnrico Granata if (*var_name_begin == '*') 16396f3533fbSEnrico Granata { 16409fc1944eSEnrico Granata do_deref_pointer = true; 16419fc1944eSEnrico Granata var_name_begin++; 1642c3e320a7SEnrico Granata if (log) 164368ae4117SEnrico Granata log->Printf("[Debugger::FormatPrompt] found a deref, new string is: %s",var_name_begin); 164468ae4117SEnrico Granata } 1645c3e320a7SEnrico Granata 16466f3533fbSEnrico Granata if (*var_name_begin == 's') 16474becb37eSEnrico Granata { 1648c5bc412cSEnrico Granata if (!valobj->IsSynthetic()) 164986cc9829SEnrico Granata valobj = valobj->GetSyntheticValue().get(); 165086cc9829SEnrico Granata if (!valobj) 165186cc9829SEnrico Granata break; 16526f3533fbSEnrico Granata var_name_begin++; 1653c3e320a7SEnrico Granata if (log) 165468ae4117SEnrico Granata log->Printf("[Debugger::FormatPrompt] found a synthetic, new string is: %s",var_name_begin); 165568ae4117SEnrico Granata } 1656c3e320a7SEnrico Granata 16576f3533fbSEnrico Granata // should be a 'v' by now 16586f3533fbSEnrico Granata if (*var_name_begin != 'v') 16596f3533fbSEnrico Granata break; 16606f3533fbSEnrico Granata 1661c3e320a7SEnrico Granata if (log) 166268ae4117SEnrico Granata log->Printf("[Debugger::FormatPrompt] string I am working with: %s",var_name_begin); 1663c3e320a7SEnrico Granata 1664fc7a7f3bSEnrico Granata ValueObject::ExpressionPathAftermath what_next = (do_deref_pointer ? 166586cc9829SEnrico Granata ValueObject::eExpressionPathAftermathDereference : ValueObject::eExpressionPathAftermathNothing); 1666fc7a7f3bSEnrico Granata ValueObject::GetValueForExpressionPathOptions options; 16678c9d3560SEnrico Granata options.DontCheckDotVsArrowSyntax().DoAllowBitfieldSyntax().DoAllowFragileIVar().DoAllowSyntheticChildren(); 166886cc9829SEnrico Granata ValueObject::ValueObjectRepresentationStyle val_obj_display = ValueObject::eValueObjectRepresentationStyleSummary; 166934132754SGreg Clayton ValueObject* target = NULL; 16704d122c40SGreg Clayton Format custom_format = eFormatInvalid; 167134132754SGreg Clayton const char* var_name_final = NULL; 16729fc1944eSEnrico Granata const char* var_name_final_if_array_range = NULL; 167334132754SGreg Clayton const char* close_bracket_position = NULL; 167434132754SGreg Clayton int64_t index_lower = -1; 167534132754SGreg Clayton int64_t index_higher = -1; 16769fc1944eSEnrico Granata bool is_array_range = false; 1677fc7a7f3bSEnrico Granata const char* first_unparsed; 167885933ed4SEnrico Granata bool was_plain_var = false; 167985933ed4SEnrico Granata bool was_var_format = false; 1680a777dc2aSEnrico Granata bool was_var_indexed = false; 1681fc7a7f3bSEnrico Granata 1682c482a192SEnrico Granata if (!valobj) break; 1683c482a192SEnrico Granata // simplest case ${var}, just print valobj's value 16840769b2b1SMichael Sartain if (IsToken (var_name_begin, "var}")) 16850a3958e0SEnrico Granata { 168685933ed4SEnrico Granata was_plain_var = true; 1687c482a192SEnrico Granata target = valobj; 168886cc9829SEnrico Granata val_obj_display = ValueObject::eValueObjectRepresentationStyleValue; 16890a3958e0SEnrico Granata } 16900769b2b1SMichael Sartain else if (IsToken (var_name_begin,"var%")) 16919fc1944eSEnrico Granata { 169285933ed4SEnrico Granata was_var_format = true; 16939fc1944eSEnrico Granata // this is a variable with some custom format applied to it 16949fc1944eSEnrico Granata const char* percent_position; 1695c482a192SEnrico Granata target = valobj; 169686cc9829SEnrico Granata val_obj_display = ValueObject::eValueObjectRepresentationStyleValue; 16979fc1944eSEnrico Granata ScanFormatDescriptor (var_name_begin, 16989fc1944eSEnrico Granata var_name_end, 16999fc1944eSEnrico Granata &var_name_final, 17009fc1944eSEnrico Granata &percent_position, 17019fc1944eSEnrico Granata &custom_format, 17029fc1944eSEnrico Granata &val_obj_display); 17030a3958e0SEnrico Granata } 17049fc1944eSEnrico Granata // this is ${var.something} or multiple .something nested 17050769b2b1SMichael Sartain else if (IsToken (var_name_begin, "var")) 17069fc1944eSEnrico Granata { 17070769b2b1SMichael Sartain if (IsToken (var_name_begin, "var[")) 1708a777dc2aSEnrico Granata was_var_indexed = true; 17099fc1944eSEnrico Granata const char* percent_position; 17109fc1944eSEnrico Granata ScanFormatDescriptor (var_name_begin, 17119fc1944eSEnrico Granata var_name_end, 17129fc1944eSEnrico Granata &var_name_final, 17139fc1944eSEnrico Granata &percent_position, 17149fc1944eSEnrico Granata &custom_format, 17159fc1944eSEnrico Granata &val_obj_display); 17169fc1944eSEnrico Granata 17179fc1944eSEnrico Granata const char* open_bracket_position; 17189fc1944eSEnrico Granata const char* separator_position; 17199fc1944eSEnrico Granata ScanBracketedRange (var_name_begin, 17209fc1944eSEnrico Granata var_name_end, 17219fc1944eSEnrico Granata var_name_final, 17229fc1944eSEnrico Granata &open_bracket_position, 17239fc1944eSEnrico Granata &separator_position, 17249fc1944eSEnrico Granata &close_bracket_position, 17259fc1944eSEnrico Granata &var_name_final_if_array_range, 17269fc1944eSEnrico Granata &index_lower, 17279fc1944eSEnrico Granata &index_higher); 17289fc1944eSEnrico Granata 17299fc1944eSEnrico Granata Error error; 17309fc1944eSEnrico Granata 1731599171adSEnrico Granata std::string expr_path(var_name_final-var_name_begin-1,0); 1732599171adSEnrico Granata memcpy(&expr_path[0], var_name_begin+3,var_name_final-var_name_begin-3); 1733fc7a7f3bSEnrico Granata 1734e992a089SEnrico Granata if (log) 1735599171adSEnrico Granata log->Printf("[Debugger::FormatPrompt] symbol to expand: %s",expr_path.c_str()); 1736fc7a7f3bSEnrico Granata 1737599171adSEnrico Granata target = valobj->GetValueForExpressionPath(expr_path.c_str(), 1738fc7a7f3bSEnrico Granata &first_unparsed, 1739fc7a7f3bSEnrico Granata &reason_to_stop, 1740fc7a7f3bSEnrico Granata &final_value_type, 1741fc7a7f3bSEnrico Granata options, 1742fc7a7f3bSEnrico Granata &what_next).get(); 1743fc7a7f3bSEnrico Granata 1744fc7a7f3bSEnrico Granata if (!target) 17459fc1944eSEnrico Granata { 1746e992a089SEnrico Granata if (log) 1747d228483dSEnrico Granata log->Printf("[Debugger::FormatPrompt] ERROR: unparsed portion = %s, why stopping = %d," 1748e992a089SEnrico Granata " final_value_type %d", 1749fc7a7f3bSEnrico Granata first_unparsed, reason_to_stop, final_value_type); 1750fc7a7f3bSEnrico Granata break; 17510a3958e0SEnrico Granata } 1752a7187d00SEnrico Granata else 1753fc7a7f3bSEnrico Granata { 1754e992a089SEnrico Granata if (log) 1755d228483dSEnrico Granata log->Printf("[Debugger::FormatPrompt] ALL RIGHT: unparsed portion = %s, why stopping = %d," 1756e992a089SEnrico Granata " final_value_type %d", 1757fc7a7f3bSEnrico Granata first_unparsed, reason_to_stop, final_value_type); 1758a7187d00SEnrico Granata } 17590a3958e0SEnrico Granata } 17600a3958e0SEnrico Granata else 17610a3958e0SEnrico Granata break; 17629fc1944eSEnrico Granata 176386cc9829SEnrico Granata is_array_range = (final_value_type == ValueObject::eExpressionPathEndResultTypeBoundedRange || 176486cc9829SEnrico Granata final_value_type == ValueObject::eExpressionPathEndResultTypeUnboundedRange); 1765fc7a7f3bSEnrico Granata 176686cc9829SEnrico Granata do_deref_pointer = (what_next == ValueObject::eExpressionPathAftermathDereference); 1767fc7a7f3bSEnrico Granata 1768a7187d00SEnrico Granata if (do_deref_pointer && !is_array_range) 17690a3958e0SEnrico Granata { 17709fc1944eSEnrico Granata // I have not deref-ed yet, let's do it 17719fc1944eSEnrico Granata // this happens when we are not going through GetValueForVariableExpressionPath 17729fc1944eSEnrico Granata // to get to the target ValueObject 17739fc1944eSEnrico Granata Error error; 17749fc1944eSEnrico Granata target = target->Dereference(error).get(); 1775dc940730SEnrico Granata if (error.Fail()) 1776dc940730SEnrico Granata { 1777dc940730SEnrico Granata if (log) 1778d228483dSEnrico Granata log->Printf("[Debugger::FormatPrompt] ERROR: %s\n", error.AsCString("unknown")); \ 1779dc940730SEnrico Granata break; 1780dc940730SEnrico Granata } 17819fc1944eSEnrico Granata do_deref_pointer = false; 17820a3958e0SEnrico Granata } 17830a3958e0SEnrico Granata 1784f164d940SJim Ingham if (!target) 1785f164d940SJim Ingham { 1786f164d940SJim Ingham if (log) 1787f164d940SJim Ingham log->Printf("[Debugger::FormatPrompt] could not calculate target for prompt expression"); 1788f164d940SJim Ingham break; 1789f164d940SJim Ingham } 1790f164d940SJim Ingham 1791a777dc2aSEnrico Granata // we do not want to use the summary for a bitfield of type T:n 1792a777dc2aSEnrico Granata // if we were originally dealing with just a T - that would get 1793a777dc2aSEnrico Granata // us into an endless recursion 1794a777dc2aSEnrico Granata if (target->IsBitfield() && was_var_indexed) 1795a777dc2aSEnrico Granata { 1796a777dc2aSEnrico Granata // TODO: check for a (T:n)-specific summary - we should still obey that 1797a777dc2aSEnrico Granata StreamString bitfield_name; 1798a777dc2aSEnrico Granata bitfield_name.Printf("%s:%d", target->GetTypeName().AsCString(), target->GetBitfieldBitSize()); 1799a777dc2aSEnrico Granata lldb::TypeNameSpecifierImplSP type_sp(new TypeNameSpecifierImpl(bitfield_name.GetData(),false)); 1800a777dc2aSEnrico Granata if (!DataVisualization::GetSummaryForType(type_sp)) 1801a777dc2aSEnrico Granata val_obj_display = ValueObject::eValueObjectRepresentationStyleValue; 1802a777dc2aSEnrico Granata } 1803a777dc2aSEnrico Granata 180485933ed4SEnrico Granata // TODO use flags for these 180557ee3067SGreg Clayton const uint32_t type_info_flags = target->GetClangType().GetTypeInfo(NULL); 180657ee3067SGreg Clayton bool is_array = (type_info_flags & ClangASTType::eTypeIsArray) != 0; 180757ee3067SGreg Clayton bool is_pointer = (type_info_flags & ClangASTType::eTypeIsPointer) != 0; 180857ee3067SGreg Clayton bool is_aggregate = target->GetClangType().IsAggregateType(); 1809f4efecd9SEnrico Granata 181086cc9829SEnrico Granata if ((is_array || is_pointer) && (!is_array_range) && val_obj_display == ValueObject::eValueObjectRepresentationStyleValue) // this should be wrong, but there are some exceptions 1811f4efecd9SEnrico Granata { 181285933ed4SEnrico Granata StreamString str_temp; 1813e992a089SEnrico Granata if (log) 1814d228483dSEnrico Granata log->Printf("[Debugger::FormatPrompt] I am into array || pointer && !range"); 1815d64d0bc0SEnrico Granata 18165088c486SGreg Clayton if (target->HasSpecialPrintableRepresentation(val_obj_display, custom_format)) 1817d64d0bc0SEnrico Granata { 1818f4efecd9SEnrico Granata // try to use the special cases 181985933ed4SEnrico Granata var_success = target->DumpPrintableRepresentation(str_temp, 182085933ed4SEnrico Granata val_obj_display, 182185933ed4SEnrico Granata custom_format); 1822e992a089SEnrico Granata if (log) 1823d228483dSEnrico Granata log->Printf("[Debugger::FormatPrompt] special cases did%s match", var_success ? "" : "n't"); 1824d64d0bc0SEnrico Granata 1825d64d0bc0SEnrico Granata // should not happen 18265088c486SGreg Clayton if (var_success) 182785933ed4SEnrico Granata s << str_temp.GetData(); 1828d64d0bc0SEnrico Granata var_success = true; 1829d64d0bc0SEnrico Granata break; 1830d64d0bc0SEnrico Granata } 1831d64d0bc0SEnrico Granata else 1832d64d0bc0SEnrico Granata { 183388da35f8SEnrico Granata if (was_plain_var) // if ${var} 1834d64d0bc0SEnrico Granata { 1835d64d0bc0SEnrico Granata s << target->GetTypeName() << " @ " << target->GetLocationAsCString(); 1836d64d0bc0SEnrico Granata } 183788da35f8SEnrico Granata else if (is_pointer) // if pointer, value is the address stored 183888da35f8SEnrico Granata { 183923f59509SGreg Clayton target->DumpPrintableRepresentation (s, 184088da35f8SEnrico Granata val_obj_display, 184186cc9829SEnrico Granata custom_format, 184286cc9829SEnrico Granata ValueObject::ePrintableRepresentationSpecialCasesDisable); 184388da35f8SEnrico Granata } 1844d64d0bc0SEnrico Granata var_success = true; 1845d64d0bc0SEnrico Granata break; 1846d64d0bc0SEnrico Granata } 1847d64d0bc0SEnrico Granata } 1848d64d0bc0SEnrico Granata 1849d64d0bc0SEnrico Granata // if directly trying to print ${var}, and this is an aggregate, display a nice 1850d64d0bc0SEnrico Granata // type @ location message 1851d64d0bc0SEnrico Granata if (is_aggregate && was_plain_var) 1852d64d0bc0SEnrico Granata { 1853d64d0bc0SEnrico Granata s << target->GetTypeName() << " @ " << target->GetLocationAsCString(); 1854d64d0bc0SEnrico Granata var_success = true; 185585933ed4SEnrico Granata break; 185685933ed4SEnrico Granata } 185785933ed4SEnrico Granata 1858d64d0bc0SEnrico Granata // if directly trying to print ${var%V}, and this is an aggregate, do not let the user do it 185986cc9829SEnrico Granata if (is_aggregate && ((was_var_format && val_obj_display == ValueObject::eValueObjectRepresentationStyleValue))) 186085933ed4SEnrico Granata { 186185933ed4SEnrico Granata s << "<invalid use of aggregate type>"; 186285933ed4SEnrico Granata var_success = true; 1863f4efecd9SEnrico Granata break; 1864f4efecd9SEnrico Granata } 1865f4efecd9SEnrico Granata 18669fc1944eSEnrico Granata if (!is_array_range) 1867e992a089SEnrico Granata { 1868e992a089SEnrico Granata if (log) 1869d228483dSEnrico Granata log->Printf("[Debugger::FormatPrompt] dumping ordinary printable output"); 18709fc1944eSEnrico Granata var_success = target->DumpPrintableRepresentation(s,val_obj_display, custom_format); 1871e992a089SEnrico Granata } 18729fc1944eSEnrico Granata else 18739fc1944eSEnrico Granata { 1874e992a089SEnrico Granata if (log) 1875d228483dSEnrico Granata log->Printf("[Debugger::FormatPrompt] checking if I can handle as array"); 18769fc1944eSEnrico Granata if (!is_array && !is_pointer) 18779fc1944eSEnrico Granata break; 1878e992a089SEnrico Granata if (log) 1879d228483dSEnrico Granata log->Printf("[Debugger::FormatPrompt] handle as array"); 1880fc7a7f3bSEnrico Granata const char* special_directions = NULL; 1881fc7a7f3bSEnrico Granata StreamString special_directions_writer; 18820a3958e0SEnrico Granata if (close_bracket_position && (var_name_end-close_bracket_position > 1)) 18830a3958e0SEnrico Granata { 1884fc7a7f3bSEnrico Granata ConstString additional_data; 1885fc7a7f3bSEnrico Granata additional_data.SetCStringWithLength(close_bracket_position+1, var_name_end-close_bracket_position-1); 1886fc7a7f3bSEnrico Granata special_directions_writer.Printf("${%svar%s}", 1887fc7a7f3bSEnrico Granata do_deref_pointer ? "*" : "", 1888fc7a7f3bSEnrico Granata additional_data.GetCString()); 1889fc7a7f3bSEnrico Granata special_directions = special_directions_writer.GetData(); 18900a3958e0SEnrico Granata } 18910a3958e0SEnrico Granata 18920a3958e0SEnrico Granata // let us display items index_lower thru index_higher of this array 18930a3958e0SEnrico Granata s.PutChar('['); 18940a3958e0SEnrico Granata var_success = true; 18950a3958e0SEnrico Granata 18969fc1944eSEnrico Granata if (index_higher < 0) 1897c482a192SEnrico Granata index_higher = valobj->GetNumChildren() - 1; 18980a3958e0SEnrico Granata 1899cc4d0146SGreg Clayton uint32_t max_num_children = target->GetTargetSP()->GetMaximumNumberOfChildrenToDisplay(); 190022c55d18SEnrico Granata 19010a3958e0SEnrico Granata for (;index_lower<=index_higher;index_lower++) 19020a3958e0SEnrico Granata { 1903fc7a7f3bSEnrico Granata ValueObject* item = ExpandIndexedExpression (target, 19049fc1944eSEnrico Granata index_lower, 1905c14ee32dSGreg Clayton exe_ctx->GetFramePtr(), 1906fc7a7f3bSEnrico Granata false).get(); 19070a3958e0SEnrico Granata 1908fc7a7f3bSEnrico Granata if (!item) 1909fc7a7f3bSEnrico Granata { 1910e992a089SEnrico Granata if (log) 1911d01b2953SDaniel Malea log->Printf("[Debugger::FormatPrompt] ERROR in getting child item at index %" PRId64, index_lower); 1912fc7a7f3bSEnrico Granata } 1913fc7a7f3bSEnrico Granata else 1914fc7a7f3bSEnrico Granata { 1915e992a089SEnrico Granata if (log) 1916d228483dSEnrico Granata log->Printf("[Debugger::FormatPrompt] special_directions for child item: %s",special_directions); 1917fc7a7f3bSEnrico Granata } 1918fc7a7f3bSEnrico Granata 19190a3958e0SEnrico Granata if (!special_directions) 19209fc1944eSEnrico Granata var_success &= item->DumpPrintableRepresentation(s,val_obj_display, custom_format); 19210a3958e0SEnrico Granata else 1922c3ce7f27SMichael Sartain var_success &= FormatPromptRecurse(special_directions, sc, exe_ctx, addr, s, NULL, item); 19230a3958e0SEnrico Granata 192422c55d18SEnrico Granata if (--max_num_children == 0) 192522c55d18SEnrico Granata { 192622c55d18SEnrico Granata s.PutCString(", ..."); 192722c55d18SEnrico Granata break; 192822c55d18SEnrico Granata } 192922c55d18SEnrico Granata 19300a3958e0SEnrico Granata if (index_lower < index_higher) 19310a3958e0SEnrico Granata s.PutChar(','); 19320a3958e0SEnrico Granata } 19330a3958e0SEnrico Granata s.PutChar(']'); 19344becb37eSEnrico Granata } 19354becb37eSEnrico Granata } 193634132754SGreg Clayton break; 19371b654882SGreg Clayton case 'a': 19380769b2b1SMichael Sartain if (IsToken (var_name_begin, "addr}")) 19391b654882SGreg Clayton { 19401b654882SGreg Clayton if (addr && addr->IsValid()) 19411b654882SGreg Clayton { 19421b654882SGreg Clayton var_success = true; 19431b654882SGreg Clayton format_addr = *addr; 19441b654882SGreg Clayton } 19451b654882SGreg Clayton } 19461b654882SGreg Clayton break; 19471b654882SGreg Clayton 19481b654882SGreg Clayton case 'p': 19490769b2b1SMichael Sartain if (IsToken (var_name_begin, "process.")) 19501b654882SGreg Clayton { 1951c14ee32dSGreg Clayton if (exe_ctx) 1952c14ee32dSGreg Clayton { 1953c14ee32dSGreg Clayton Process *process = exe_ctx->GetProcessPtr(); 1954c14ee32dSGreg Clayton if (process) 19551b654882SGreg Clayton { 19561b654882SGreg Clayton var_name_begin += ::strlen ("process."); 19570769b2b1SMichael Sartain if (IsTokenWithFormat (var_name_begin, "id", token_format, "%" PRIu64, exe_ctx, sc)) 19581b654882SGreg Clayton { 19590769b2b1SMichael Sartain s.Printf(token_format.c_str(), process->GetID()); 19601b654882SGreg Clayton var_success = true; 19611b654882SGreg Clayton } 19620769b2b1SMichael Sartain else if ((IsToken (var_name_begin, "name}")) || 19630769b2b1SMichael Sartain (IsToken (var_name_begin, "file.basename}")) || 19640769b2b1SMichael Sartain (IsToken (var_name_begin, "file.fullpath}"))) 19651b654882SGreg Clayton { 1966c14ee32dSGreg Clayton Module *exe_module = process->GetTarget().GetExecutableModulePointer(); 1967aa149cbdSGreg Clayton if (exe_module) 19681b654882SGreg Clayton { 19691b654882SGreg Clayton if (var_name_begin[0] == 'n' || var_name_begin[5] == 'f') 19701b654882SGreg Clayton { 1971aa149cbdSGreg Clayton format_file_spec.GetFilename() = exe_module->GetFileSpec().GetFilename(); 19729076c0ffSSean Callanan var_success = (bool)format_file_spec; 19731b654882SGreg Clayton } 19741b654882SGreg Clayton else 19751b654882SGreg Clayton { 1976aa149cbdSGreg Clayton format_file_spec = exe_module->GetFileSpec(); 19779076c0ffSSean Callanan var_success = (bool)format_file_spec; 19781b654882SGreg Clayton } 19791b654882SGreg Clayton } 19801b654882SGreg Clayton } 19810769b2b1SMichael Sartain else if (IsToken (var_name_begin, "script:")) 1982aad8e480SEnrico Granata { 1983aad8e480SEnrico Granata var_name_begin += ::strlen("script:"); 1984aad8e480SEnrico Granata std::string script_name(var_name_begin,var_name_end); 1985aad8e480SEnrico Granata ScriptInterpreter* script_interpreter = process->GetTarget().GetDebugger().GetCommandInterpreter().GetScriptInterpreter(); 19860769b2b1SMichael Sartain if (RunScriptFormatKeyword (s, script_interpreter, process, script_name)) 1987aad8e480SEnrico Granata var_success = true; 1988aad8e480SEnrico Granata } 19891b654882SGreg Clayton } 19901b654882SGreg Clayton } 1991c14ee32dSGreg Clayton } 19921b654882SGreg Clayton break; 19931b654882SGreg Clayton 19941b654882SGreg Clayton case 't': 19950769b2b1SMichael Sartain if (IsToken (var_name_begin, "thread.")) 19961b654882SGreg Clayton { 1997c14ee32dSGreg Clayton if (exe_ctx) 1998c14ee32dSGreg Clayton { 1999c14ee32dSGreg Clayton Thread *thread = exe_ctx->GetThreadPtr(); 2000c14ee32dSGreg Clayton if (thread) 20011b654882SGreg Clayton { 20021b654882SGreg Clayton var_name_begin += ::strlen ("thread."); 20030769b2b1SMichael Sartain if (IsTokenWithFormat (var_name_begin, "id", token_format, "0x%4.4" PRIx64, exe_ctx, sc)) 20041b654882SGreg Clayton { 20050769b2b1SMichael Sartain s.Printf(token_format.c_str(), thread->GetID()); 20061b654882SGreg Clayton var_success = true; 20071b654882SGreg Clayton } 20080769b2b1SMichael Sartain else if (IsTokenWithFormat (var_name_begin, "protocol_id", token_format, "0x%4.4" PRIx64, exe_ctx, sc)) 2009160c9d81SGreg Clayton { 20100769b2b1SMichael Sartain s.Printf(token_format.c_str(), thread->GetProtocolID()); 2011160c9d81SGreg Clayton var_success = true; 2012160c9d81SGreg Clayton } 20130769b2b1SMichael Sartain else if (IsTokenWithFormat (var_name_begin, "index", token_format, "%" PRIu64, exe_ctx, sc)) 20141b654882SGreg Clayton { 20150769b2b1SMichael Sartain s.Printf(token_format.c_str(), (uint64_t)thread->GetIndexID()); 20161b654882SGreg Clayton var_success = true; 20171b654882SGreg Clayton } 20180769b2b1SMichael Sartain else if (IsToken (var_name_begin, "name}")) 20191b654882SGreg Clayton { 2020c14ee32dSGreg Clayton cstr = thread->GetName(); 20211b654882SGreg Clayton var_success = cstr && cstr[0]; 20221b654882SGreg Clayton if (var_success) 20231b654882SGreg Clayton s.PutCString(cstr); 20241b654882SGreg Clayton } 20250769b2b1SMichael Sartain else if (IsToken (var_name_begin, "queue}")) 20261b654882SGreg Clayton { 2027c14ee32dSGreg Clayton cstr = thread->GetQueueName(); 20281b654882SGreg Clayton var_success = cstr && cstr[0]; 20291b654882SGreg Clayton if (var_success) 20301b654882SGreg Clayton s.PutCString(cstr); 20311b654882SGreg Clayton } 20320769b2b1SMichael Sartain else if (IsToken (var_name_begin, "stop-reason}")) 20331b654882SGreg Clayton { 2034c14ee32dSGreg Clayton StopInfoSP stop_info_sp = thread->GetStopInfo (); 20355d88a068SJim Ingham if (stop_info_sp && stop_info_sp->IsValid()) 20361b654882SGreg Clayton { 2037b15bfc75SJim Ingham cstr = stop_info_sp->GetDescription(); 20381b654882SGreg Clayton if (cstr && cstr[0]) 20391b654882SGreg Clayton { 20401b654882SGreg Clayton s.PutCString(cstr); 20411b654882SGreg Clayton var_success = true; 20421b654882SGreg Clayton } 20431b654882SGreg Clayton } 20441b654882SGreg Clayton } 20450769b2b1SMichael Sartain else if (IsToken (var_name_begin, "return-value}")) 204673ca05a2SJim Ingham { 204773ca05a2SJim Ingham StopInfoSP stop_info_sp = thread->GetStopInfo (); 20485d88a068SJim Ingham if (stop_info_sp && stop_info_sp->IsValid()) 204973ca05a2SJim Ingham { 205073ca05a2SJim Ingham ValueObjectSP return_valobj_sp = StopInfo::GetReturnValueObject (stop_info_sp); 205173ca05a2SJim Ingham if (return_valobj_sp) 205273ca05a2SJim Ingham { 20534d93b8cdSEnrico Granata return_valobj_sp->Dump(s); 205473ca05a2SJim Ingham var_success = true; 205573ca05a2SJim Ingham } 205673ca05a2SJim Ingham } 205773ca05a2SJim Ingham } 20580769b2b1SMichael Sartain else if (IsToken (var_name_begin, "script:")) 2059aad8e480SEnrico Granata { 2060aad8e480SEnrico Granata var_name_begin += ::strlen("script:"); 2061aad8e480SEnrico Granata std::string script_name(var_name_begin,var_name_end); 2062aad8e480SEnrico Granata ScriptInterpreter* script_interpreter = thread->GetProcess()->GetTarget().GetDebugger().GetCommandInterpreter().GetScriptInterpreter(); 20630769b2b1SMichael Sartain if (RunScriptFormatKeyword (s, script_interpreter, thread, script_name)) 2064aad8e480SEnrico Granata var_success = true; 2065aad8e480SEnrico Granata } 2066*705b1809SJason Molenda else if (IsToken (var_name_begin, "info.")) 2067*705b1809SJason Molenda { 2068*705b1809SJason Molenda var_name_begin += ::strlen("info."); 2069*705b1809SJason Molenda StructuredData::ObjectSP object_sp = thread->GetExtendedInfo(); 2070*705b1809SJason Molenda if (object_sp && object_sp->GetType() == StructuredData::Type::eTypeDictionary) 2071*705b1809SJason Molenda { 2072*705b1809SJason Molenda var_success = FormatThreadExtendedInfoRecurse (var_name_begin, object_sp, sc, exe_ctx, s); 2073*705b1809SJason Molenda } 2074*705b1809SJason Molenda } 2075aad8e480SEnrico Granata } 2076aad8e480SEnrico Granata } 207773ca05a2SJim Ingham } 20780769b2b1SMichael Sartain else if (IsToken (var_name_begin, "target.")) 20791b654882SGreg Clayton { 208067cc0636SGreg Clayton // TODO: hookup properties 208167cc0636SGreg Clayton // if (!target_properties_sp) 208267cc0636SGreg Clayton // { 208367cc0636SGreg Clayton // Target *target = Target::GetTargetFromContexts (exe_ctx, sc); 208467cc0636SGreg Clayton // if (target) 208567cc0636SGreg Clayton // target_properties_sp = target->GetProperties(); 208667cc0636SGreg Clayton // } 208767cc0636SGreg Clayton // 208867cc0636SGreg Clayton // if (target_properties_sp) 208967cc0636SGreg Clayton // { 209067cc0636SGreg Clayton // var_name_begin += ::strlen ("target."); 209167cc0636SGreg Clayton // const char *end_property = strchr(var_name_begin, '}'); 209267cc0636SGreg Clayton // if (end_property) 209367cc0636SGreg Clayton // { 209467cc0636SGreg Clayton // ConstString property_name(var_name_begin, end_property - var_name_begin); 209567cc0636SGreg Clayton // std::string property_value (target_properties_sp->GetPropertyValue(property_name)); 209667cc0636SGreg Clayton // if (!property_value.empty()) 209767cc0636SGreg Clayton // { 209867cc0636SGreg Clayton // s.PutCString (property_value.c_str()); 209967cc0636SGreg Clayton // var_success = true; 210067cc0636SGreg Clayton // } 210167cc0636SGreg Clayton // } 210267cc0636SGreg Clayton // } 21030603aa9dSGreg Clayton Target *target = Target::GetTargetFromContexts (exe_ctx, sc); 21040603aa9dSGreg Clayton if (target) 21051b654882SGreg Clayton { 21061b654882SGreg Clayton var_name_begin += ::strlen ("target."); 21070769b2b1SMichael Sartain if (IsToken (var_name_begin, "arch}")) 21081b654882SGreg Clayton { 21091b654882SGreg Clayton ArchSpec arch (target->GetArchitecture ()); 21101b654882SGreg Clayton if (arch.IsValid()) 21111b654882SGreg Clayton { 211264195a2cSGreg Clayton s.PutCString (arch.GetArchitectureName()); 21131b654882SGreg Clayton var_success = true; 21141b654882SGreg Clayton } 21151b654882SGreg Clayton } 21160769b2b1SMichael Sartain else if (IsToken (var_name_begin, "script:")) 2117aad8e480SEnrico Granata { 2118aad8e480SEnrico Granata var_name_begin += ::strlen("script:"); 2119aad8e480SEnrico Granata std::string script_name(var_name_begin,var_name_end); 2120aad8e480SEnrico Granata ScriptInterpreter* script_interpreter = target->GetDebugger().GetCommandInterpreter().GetScriptInterpreter(); 21210769b2b1SMichael Sartain if (RunScriptFormatKeyword (s, script_interpreter, target, script_name)) 2122aad8e480SEnrico Granata var_success = true; 2123aad8e480SEnrico Granata } 21241b654882SGreg Clayton } 21251b654882SGreg Clayton } 21261b654882SGreg Clayton break; 21271b654882SGreg Clayton 21281b654882SGreg Clayton 21291b654882SGreg Clayton case 'm': 21300769b2b1SMichael Sartain if (IsToken (var_name_begin, "module.")) 21311b654882SGreg Clayton { 21320603aa9dSGreg Clayton if (sc && sc->module_sp.get()) 21331b654882SGreg Clayton { 21340603aa9dSGreg Clayton Module *module = sc->module_sp.get(); 21351b654882SGreg Clayton var_name_begin += ::strlen ("module."); 21361b654882SGreg Clayton 21370769b2b1SMichael Sartain if (IsToken (var_name_begin, "file.")) 21381b654882SGreg Clayton { 21391b654882SGreg Clayton if (module->GetFileSpec()) 21401b654882SGreg Clayton { 21411b654882SGreg Clayton var_name_begin += ::strlen ("file."); 21421b654882SGreg Clayton 21430769b2b1SMichael Sartain if (IsToken (var_name_begin, "basename}")) 21441b654882SGreg Clayton { 21451b654882SGreg Clayton format_file_spec.GetFilename() = module->GetFileSpec().GetFilename(); 21469076c0ffSSean Callanan var_success = (bool)format_file_spec; 21471b654882SGreg Clayton } 21480769b2b1SMichael Sartain else if (IsToken (var_name_begin, "fullpath}")) 21491b654882SGreg Clayton { 21501b654882SGreg Clayton format_file_spec = module->GetFileSpec(); 21519076c0ffSSean Callanan var_success = (bool)format_file_spec; 21521b654882SGreg Clayton } 21531b654882SGreg Clayton } 21541b654882SGreg Clayton } 21551b654882SGreg Clayton } 21561b654882SGreg Clayton } 21571b654882SGreg Clayton break; 21581b654882SGreg Clayton 21591b654882SGreg Clayton 21601b654882SGreg Clayton case 'f': 21610769b2b1SMichael Sartain if (IsToken (var_name_begin, "file.")) 21621b654882SGreg Clayton { 21631b654882SGreg Clayton if (sc && sc->comp_unit != NULL) 21641b654882SGreg Clayton { 21651b654882SGreg Clayton var_name_begin += ::strlen ("file."); 21661b654882SGreg Clayton 21670769b2b1SMichael Sartain if (IsToken (var_name_begin, "basename}")) 21681b654882SGreg Clayton { 21691b654882SGreg Clayton format_file_spec.GetFilename() = sc->comp_unit->GetFilename(); 21709076c0ffSSean Callanan var_success = (bool)format_file_spec; 21711b654882SGreg Clayton } 21720769b2b1SMichael Sartain else if (IsToken (var_name_begin, "fullpath}")) 21731b654882SGreg Clayton { 21741b654882SGreg Clayton format_file_spec = *sc->comp_unit; 21759076c0ffSSean Callanan var_success = (bool)format_file_spec; 21761b654882SGreg Clayton } 21771b654882SGreg Clayton } 21781b654882SGreg Clayton } 21790769b2b1SMichael Sartain else if (IsToken (var_name_begin, "frame.")) 21801b654882SGreg Clayton { 2181c14ee32dSGreg Clayton if (exe_ctx) 2182c14ee32dSGreg Clayton { 2183b57e4a1bSJason Molenda StackFrame *frame = exe_ctx->GetFramePtr(); 2184c14ee32dSGreg Clayton if (frame) 21851b654882SGreg Clayton { 21861b654882SGreg Clayton var_name_begin += ::strlen ("frame."); 21870769b2b1SMichael Sartain if (IsToken (var_name_begin, "index}")) 21881b654882SGreg Clayton { 2189c14ee32dSGreg Clayton s.Printf("%u", frame->GetFrameIndex()); 21901b654882SGreg Clayton var_success = true; 21911b654882SGreg Clayton } 21920769b2b1SMichael Sartain else if (IsToken (var_name_begin, "pc}")) 21931b654882SGreg Clayton { 21941b654882SGreg Clayton reg_kind = eRegisterKindGeneric; 21951b654882SGreg Clayton reg_num = LLDB_REGNUM_GENERIC_PC; 21961b654882SGreg Clayton var_success = true; 21971b654882SGreg Clayton } 21980769b2b1SMichael Sartain else if (IsToken (var_name_begin, "sp}")) 21991b654882SGreg Clayton { 22001b654882SGreg Clayton reg_kind = eRegisterKindGeneric; 22011b654882SGreg Clayton reg_num = LLDB_REGNUM_GENERIC_SP; 22021b654882SGreg Clayton var_success = true; 22031b654882SGreg Clayton } 22040769b2b1SMichael Sartain else if (IsToken (var_name_begin, "fp}")) 22051b654882SGreg Clayton { 22061b654882SGreg Clayton reg_kind = eRegisterKindGeneric; 22071b654882SGreg Clayton reg_num = LLDB_REGNUM_GENERIC_FP; 22081b654882SGreg Clayton var_success = true; 22091b654882SGreg Clayton } 22100769b2b1SMichael Sartain else if (IsToken (var_name_begin, "flags}")) 22111b654882SGreg Clayton { 22121b654882SGreg Clayton reg_kind = eRegisterKindGeneric; 22131b654882SGreg Clayton reg_num = LLDB_REGNUM_GENERIC_FLAGS; 22141b654882SGreg Clayton var_success = true; 22151b654882SGreg Clayton } 22160769b2b1SMichael Sartain else if (IsToken (var_name_begin, "reg.")) 22171b654882SGreg Clayton { 2218c14ee32dSGreg Clayton reg_ctx = frame->GetRegisterContext().get(); 22191b654882SGreg Clayton if (reg_ctx) 22201b654882SGreg Clayton { 22211b654882SGreg Clayton var_name_begin += ::strlen ("reg."); 22221b654882SGreg Clayton if (var_name_begin < var_name_end) 22231b654882SGreg Clayton { 22241b654882SGreg Clayton std::string reg_name (var_name_begin, var_name_end); 22251b654882SGreg Clayton reg_info = reg_ctx->GetRegisterInfoByName (reg_name.c_str()); 22261b654882SGreg Clayton if (reg_info) 22271b654882SGreg Clayton var_success = true; 22281b654882SGreg Clayton } 22291b654882SGreg Clayton } 22301b654882SGreg Clayton } 22310769b2b1SMichael Sartain else if (IsToken (var_name_begin, "script:")) 2232aad8e480SEnrico Granata { 2233aad8e480SEnrico Granata var_name_begin += ::strlen("script:"); 2234aad8e480SEnrico Granata std::string script_name(var_name_begin,var_name_end); 2235aad8e480SEnrico Granata ScriptInterpreter* script_interpreter = frame->GetThread()->GetProcess()->GetTarget().GetDebugger().GetCommandInterpreter().GetScriptInterpreter(); 22360769b2b1SMichael Sartain if (RunScriptFormatKeyword (s, script_interpreter, frame, script_name)) 2237aad8e480SEnrico Granata var_success = true; 2238aad8e480SEnrico Granata } 2239aad8e480SEnrico Granata } 2240aad8e480SEnrico Granata } 22411b654882SGreg Clayton } 22420769b2b1SMichael Sartain else if (IsToken (var_name_begin, "function.")) 22431b654882SGreg Clayton { 22441b654882SGreg Clayton if (sc && (sc->function != NULL || sc->symbol != NULL)) 22451b654882SGreg Clayton { 22461b654882SGreg Clayton var_name_begin += ::strlen ("function."); 22470769b2b1SMichael Sartain if (IsToken (var_name_begin, "id}")) 22481b654882SGreg Clayton { 22491b654882SGreg Clayton if (sc->function) 2250d01b2953SDaniel Malea s.Printf("function{0x%8.8" PRIx64 "}", sc->function->GetID()); 22511b654882SGreg Clayton else 22521b654882SGreg Clayton s.Printf("symbol[%u]", sc->symbol->GetID()); 22531b654882SGreg Clayton 22541b654882SGreg Clayton var_success = true; 22551b654882SGreg Clayton } 22560769b2b1SMichael Sartain else if (IsToken (var_name_begin, "name}")) 22571b654882SGreg Clayton { 22581b654882SGreg Clayton if (sc->function) 22591b654882SGreg Clayton cstr = sc->function->GetName().AsCString (NULL); 22601b654882SGreg Clayton else if (sc->symbol) 22611b654882SGreg Clayton cstr = sc->symbol->GetName().AsCString (NULL); 22621b654882SGreg Clayton if (cstr) 22631b654882SGreg Clayton { 22641b654882SGreg Clayton s.PutCString(cstr); 22650d9c9934SGreg Clayton 22660d9c9934SGreg Clayton if (sc->block) 22670d9c9934SGreg Clayton { 22680d9c9934SGreg Clayton Block *inline_block = sc->block->GetContainingInlinedBlock (); 22690d9c9934SGreg Clayton if (inline_block) 22700d9c9934SGreg Clayton { 22710d9c9934SGreg Clayton const InlineFunctionInfo *inline_info = sc->block->GetInlinedFunctionInfo(); 22720d9c9934SGreg Clayton if (inline_info) 22730d9c9934SGreg Clayton { 22740d9c9934SGreg Clayton s.PutCString(" [inlined] "); 22750d9c9934SGreg Clayton inline_info->GetName().Dump(&s); 22760d9c9934SGreg Clayton } 22770d9c9934SGreg Clayton } 22780d9c9934SGreg Clayton } 22791b654882SGreg Clayton var_success = true; 22801b654882SGreg Clayton } 22811b654882SGreg Clayton } 22820769b2b1SMichael Sartain else if (IsToken (var_name_begin, "name-with-args}")) 22836d3dbf51SGreg Clayton { 22846d3dbf51SGreg Clayton // Print the function name with arguments in it 22856d3dbf51SGreg Clayton 22866d3dbf51SGreg Clayton if (sc->function) 22876d3dbf51SGreg Clayton { 22886d3dbf51SGreg Clayton var_success = true; 22896d3dbf51SGreg Clayton ExecutionContextScope *exe_scope = exe_ctx ? exe_ctx->GetBestExecutionContextScope() : NULL; 22906d3dbf51SGreg Clayton cstr = sc->function->GetName().AsCString (NULL); 22916d3dbf51SGreg Clayton if (cstr) 22926d3dbf51SGreg Clayton { 22936d3dbf51SGreg Clayton const InlineFunctionInfo *inline_info = NULL; 22946d3dbf51SGreg Clayton VariableListSP variable_list_sp; 22956d3dbf51SGreg Clayton bool get_function_vars = true; 22966d3dbf51SGreg Clayton if (sc->block) 22976d3dbf51SGreg Clayton { 22986d3dbf51SGreg Clayton Block *inline_block = sc->block->GetContainingInlinedBlock (); 22996d3dbf51SGreg Clayton 23006d3dbf51SGreg Clayton if (inline_block) 23016d3dbf51SGreg Clayton { 23026d3dbf51SGreg Clayton get_function_vars = false; 23036d3dbf51SGreg Clayton inline_info = sc->block->GetInlinedFunctionInfo(); 23046d3dbf51SGreg Clayton if (inline_info) 23056d3dbf51SGreg Clayton variable_list_sp = inline_block->GetBlockVariableList (true); 23066d3dbf51SGreg Clayton } 23076d3dbf51SGreg Clayton } 23086d3dbf51SGreg Clayton 23096d3dbf51SGreg Clayton if (get_function_vars) 23106d3dbf51SGreg Clayton { 23116d3dbf51SGreg Clayton variable_list_sp = sc->function->GetBlock(true).GetBlockVariableList (true); 23126d3dbf51SGreg Clayton } 23136d3dbf51SGreg Clayton 23146d3dbf51SGreg Clayton if (inline_info) 23156d3dbf51SGreg Clayton { 23166d3dbf51SGreg Clayton s.PutCString (cstr); 23176d3dbf51SGreg Clayton s.PutCString (" [inlined] "); 23186d3dbf51SGreg Clayton cstr = inline_info->GetName().GetCString(); 23196d3dbf51SGreg Clayton } 23206d3dbf51SGreg Clayton 23216d3dbf51SGreg Clayton VariableList args; 23226d3dbf51SGreg Clayton if (variable_list_sp) 2323cc7f9bf5SEnrico Granata variable_list_sp->AppendVariablesWithScope(eValueTypeVariableArgument, args); 23246d3dbf51SGreg Clayton if (args.GetSize() > 0) 23256d3dbf51SGreg Clayton { 23266d3dbf51SGreg Clayton const char *open_paren = strchr (cstr, '('); 23276d3dbf51SGreg Clayton const char *close_paren = NULL; 23286d3dbf51SGreg Clayton if (open_paren) 2329855958caSGreg Clayton { 23300769b2b1SMichael Sartain if (IsToken (open_paren, "(anonymous namespace)")) 2331855958caSGreg Clayton { 2332855958caSGreg Clayton open_paren = strchr (open_paren + strlen("(anonymous namespace)"), '('); 2333855958caSGreg Clayton if (open_paren) 23346d3dbf51SGreg Clayton close_paren = strchr (open_paren, ')'); 2335855958caSGreg Clayton } 2336855958caSGreg Clayton else 2337855958caSGreg Clayton close_paren = strchr (open_paren, ')'); 2338855958caSGreg Clayton } 23396d3dbf51SGreg Clayton 23406d3dbf51SGreg Clayton if (open_paren) 23416d3dbf51SGreg Clayton s.Write(cstr, open_paren - cstr + 1); 23426d3dbf51SGreg Clayton else 23436d3dbf51SGreg Clayton { 23446d3dbf51SGreg Clayton s.PutCString (cstr); 23456d3dbf51SGreg Clayton s.PutChar ('('); 23466d3dbf51SGreg Clayton } 23475b6889b1SGreg Clayton const size_t num_args = args.GetSize(); 23486d3dbf51SGreg Clayton for (size_t arg_idx = 0; arg_idx < num_args; ++arg_idx) 23496d3dbf51SGreg Clayton { 2350894f7359SEnrico Granata std::string buffer; 2351894f7359SEnrico Granata 23526d3dbf51SGreg Clayton VariableSP var_sp (args.GetVariableAtIndex (arg_idx)); 23536d3dbf51SGreg Clayton ValueObjectSP var_value_sp (ValueObjectVariable::Create (exe_scope, var_sp)); 2354894f7359SEnrico Granata const char *var_representation = nullptr; 23556d3dbf51SGreg Clayton const char *var_name = var_value_sp->GetName().GetCString(); 2356894f7359SEnrico Granata if (var_value_sp->GetClangType().IsAggregateType() && 2357894f7359SEnrico Granata DataVisualization::ShouldPrintAsOneLiner(*var_value_sp.get())) 2358894f7359SEnrico Granata { 2359894f7359SEnrico Granata static StringSummaryFormat format(TypeSummaryImpl::Flags() 2360894f7359SEnrico Granata .SetHideItemNames(false) 2361894f7359SEnrico Granata .SetShowMembersOneLiner(true), 2362894f7359SEnrico Granata ""); 2363894f7359SEnrico Granata format.FormatObject(var_value_sp.get(), buffer); 2364894f7359SEnrico Granata var_representation = buffer.c_str(); 2365894f7359SEnrico Granata } 2366894f7359SEnrico Granata else 2367894f7359SEnrico Granata var_representation = var_value_sp->GetValueAsCString(); 23686d3dbf51SGreg Clayton if (arg_idx > 0) 23696d3dbf51SGreg Clayton s.PutCString (", "); 23703b188b17SGreg Clayton if (var_value_sp->GetError().Success()) 2371cc7f9bf5SEnrico Granata { 2372894f7359SEnrico Granata if (var_representation) 2373894f7359SEnrico Granata s.Printf ("%s=%s", var_name, var_representation); 23743b188b17SGreg Clayton else 2375cc7f9bf5SEnrico Granata s.Printf ("%s=%s at %s", var_name, var_value_sp->GetTypeName().GetCString(), var_value_sp->GetLocationAsCString()); 2376cc7f9bf5SEnrico Granata } 2377cc7f9bf5SEnrico Granata else 23783b188b17SGreg Clayton s.Printf ("%s=<unavailable>", var_name); 23796d3dbf51SGreg Clayton } 23806d3dbf51SGreg Clayton 23816d3dbf51SGreg Clayton if (close_paren) 23826d3dbf51SGreg Clayton s.PutCString (close_paren); 23836d3dbf51SGreg Clayton else 23846d3dbf51SGreg Clayton s.PutChar(')'); 23856d3dbf51SGreg Clayton 23866d3dbf51SGreg Clayton } 23876d3dbf51SGreg Clayton else 23886d3dbf51SGreg Clayton { 23896d3dbf51SGreg Clayton s.PutCString(cstr); 23906d3dbf51SGreg Clayton } 23916d3dbf51SGreg Clayton } 23926d3dbf51SGreg Clayton } 23936d3dbf51SGreg Clayton else if (sc->symbol) 23946d3dbf51SGreg Clayton { 23956d3dbf51SGreg Clayton cstr = sc->symbol->GetName().AsCString (NULL); 23966d3dbf51SGreg Clayton if (cstr) 23976d3dbf51SGreg Clayton { 23986d3dbf51SGreg Clayton s.PutCString(cstr); 23996d3dbf51SGreg Clayton var_success = true; 24006d3dbf51SGreg Clayton } 24016d3dbf51SGreg Clayton } 24026d3dbf51SGreg Clayton } 24030769b2b1SMichael Sartain else if (IsToken (var_name_begin, "addr-offset}")) 24041b654882SGreg Clayton { 24051b654882SGreg Clayton var_success = addr != NULL; 24061b654882SGreg Clayton if (var_success) 24071b654882SGreg Clayton { 24081b654882SGreg Clayton format_addr = *addr; 24091b654882SGreg Clayton calculate_format_addr_function_offset = true; 24101b654882SGreg Clayton } 24111b654882SGreg Clayton } 24120769b2b1SMichael Sartain else if (IsToken (var_name_begin, "line-offset}")) 24131b654882SGreg Clayton { 24141b654882SGreg Clayton var_success = sc->line_entry.range.GetBaseAddress().IsValid(); 24151b654882SGreg Clayton if (var_success) 24161b654882SGreg Clayton { 24171b654882SGreg Clayton format_addr = sc->line_entry.range.GetBaseAddress(); 24181b654882SGreg Clayton calculate_format_addr_function_offset = true; 24191b654882SGreg Clayton } 24201b654882SGreg Clayton } 24210769b2b1SMichael Sartain else if (IsToken (var_name_begin, "pc-offset}")) 24221b654882SGreg Clayton { 2423b57e4a1bSJason Molenda StackFrame *frame = exe_ctx->GetFramePtr(); 2424c14ee32dSGreg Clayton var_success = frame != NULL; 24251b654882SGreg Clayton if (var_success) 24261b654882SGreg Clayton { 2427c14ee32dSGreg Clayton format_addr = frame->GetFrameCodeAddress(); 24281b654882SGreg Clayton calculate_format_addr_function_offset = true; 24291b654882SGreg Clayton } 24301b654882SGreg Clayton } 24311b654882SGreg Clayton } 24321b654882SGreg Clayton } 24331b654882SGreg Clayton break; 24341b654882SGreg Clayton 24351b654882SGreg Clayton case 'l': 24360769b2b1SMichael Sartain if (IsToken (var_name_begin, "line.")) 24371b654882SGreg Clayton { 24381b654882SGreg Clayton if (sc && sc->line_entry.IsValid()) 24391b654882SGreg Clayton { 24401b654882SGreg Clayton var_name_begin += ::strlen ("line."); 24410769b2b1SMichael Sartain if (IsToken (var_name_begin, "file.")) 24421b654882SGreg Clayton { 24431b654882SGreg Clayton var_name_begin += ::strlen ("file."); 24441b654882SGreg Clayton 24450769b2b1SMichael Sartain if (IsToken (var_name_begin, "basename}")) 24461b654882SGreg Clayton { 24471b654882SGreg Clayton format_file_spec.GetFilename() = sc->line_entry.file.GetFilename(); 24489076c0ffSSean Callanan var_success = (bool)format_file_spec; 24491b654882SGreg Clayton } 24500769b2b1SMichael Sartain else if (IsToken (var_name_begin, "fullpath}")) 24511b654882SGreg Clayton { 24521b654882SGreg Clayton format_file_spec = sc->line_entry.file; 24539076c0ffSSean Callanan var_success = (bool)format_file_spec; 24541b654882SGreg Clayton } 24551b654882SGreg Clayton } 24560769b2b1SMichael Sartain else if (IsTokenWithFormat (var_name_begin, "number", token_format, "%" PRIu64, exe_ctx, sc)) 24571b654882SGreg Clayton { 24581b654882SGreg Clayton var_success = true; 24590769b2b1SMichael Sartain s.Printf(token_format.c_str(), (uint64_t)sc->line_entry.line); 24601b654882SGreg Clayton } 24610769b2b1SMichael Sartain else if ((IsToken (var_name_begin, "start-addr}")) || 24620769b2b1SMichael Sartain (IsToken (var_name_begin, "end-addr}"))) 24631b654882SGreg Clayton { 24641b654882SGreg Clayton var_success = sc && sc->line_entry.range.GetBaseAddress().IsValid(); 24651b654882SGreg Clayton if (var_success) 24661b654882SGreg Clayton { 24671b654882SGreg Clayton format_addr = sc->line_entry.range.GetBaseAddress(); 24681b654882SGreg Clayton if (var_name_begin[0] == 'e') 24691b654882SGreg Clayton format_addr.Slide (sc->line_entry.range.GetByteSize()); 24701b654882SGreg Clayton } 24711b654882SGreg Clayton } 24721b654882SGreg Clayton } 24731b654882SGreg Clayton } 24741b654882SGreg Clayton break; 24751b654882SGreg Clayton } 24761b654882SGreg Clayton 24771b654882SGreg Clayton if (var_success) 24781b654882SGreg Clayton { 24791b654882SGreg Clayton // If format addr is valid, then we need to print an address 24801b654882SGreg Clayton if (reg_num != LLDB_INVALID_REGNUM) 24811b654882SGreg Clayton { 2482b57e4a1bSJason Molenda StackFrame *frame = exe_ctx->GetFramePtr(); 24831b654882SGreg Clayton // We have a register value to display... 24841b654882SGreg Clayton if (reg_num == LLDB_REGNUM_GENERIC_PC && reg_kind == eRegisterKindGeneric) 24851b654882SGreg Clayton { 2486c14ee32dSGreg Clayton format_addr = frame->GetFrameCodeAddress(); 24871b654882SGreg Clayton } 24881b654882SGreg Clayton else 24891b654882SGreg Clayton { 24901b654882SGreg Clayton if (reg_ctx == NULL) 2491c14ee32dSGreg Clayton reg_ctx = frame->GetRegisterContext().get(); 24921b654882SGreg Clayton 24931b654882SGreg Clayton if (reg_ctx) 24941b654882SGreg Clayton { 24951b654882SGreg Clayton if (reg_kind != kNumRegisterKinds) 24961b654882SGreg Clayton reg_num = reg_ctx->ConvertRegisterKindToRegisterNumber(reg_kind, reg_num); 24971b654882SGreg Clayton reg_info = reg_ctx->GetRegisterInfoAtIndex (reg_num); 24981b654882SGreg Clayton var_success = reg_info != NULL; 24991b654882SGreg Clayton } 25001b654882SGreg Clayton } 25011b654882SGreg Clayton } 25021b654882SGreg Clayton 25031b654882SGreg Clayton if (reg_info != NULL) 25041b654882SGreg Clayton { 25057349bd90SGreg Clayton RegisterValue reg_value; 25067349bd90SGreg Clayton var_success = reg_ctx->ReadRegister (reg_info, reg_value); 25077349bd90SGreg Clayton if (var_success) 25081b654882SGreg Clayton { 25099a8fa916SGreg Clayton reg_value.Dump(&s, reg_info, false, false, eFormatDefault); 25101b654882SGreg Clayton } 25111b654882SGreg Clayton } 25121b654882SGreg Clayton 25131b654882SGreg Clayton if (format_file_spec) 25141b654882SGreg Clayton { 25151b654882SGreg Clayton s << format_file_spec; 25161b654882SGreg Clayton } 25171b654882SGreg Clayton 25181b654882SGreg Clayton // If format addr is valid, then we need to print an address 25191b654882SGreg Clayton if (format_addr.IsValid()) 25201b654882SGreg Clayton { 25210603aa9dSGreg Clayton var_success = false; 25220603aa9dSGreg Clayton 25231b654882SGreg Clayton if (calculate_format_addr_function_offset) 25241b654882SGreg Clayton { 25251b654882SGreg Clayton Address func_addr; 25260603aa9dSGreg Clayton 25270603aa9dSGreg Clayton if (sc) 25280603aa9dSGreg Clayton { 25291b654882SGreg Clayton if (sc->function) 25300d9c9934SGreg Clayton { 25311b654882SGreg Clayton func_addr = sc->function->GetAddressRange().GetBaseAddress(); 25320d9c9934SGreg Clayton if (sc->block) 25330d9c9934SGreg Clayton { 25340d9c9934SGreg Clayton // Check to make sure we aren't in an inline 25350d9c9934SGreg Clayton // function. If we are, use the inline block 25360d9c9934SGreg Clayton // range that contains "format_addr" since 25370d9c9934SGreg Clayton // blocks can be discontiguous. 25380d9c9934SGreg Clayton Block *inline_block = sc->block->GetContainingInlinedBlock (); 25390d9c9934SGreg Clayton AddressRange inline_range; 25400d9c9934SGreg Clayton if (inline_block && inline_block->GetRangeContainingAddress (format_addr, inline_range)) 25410d9c9934SGreg Clayton func_addr = inline_range.GetBaseAddress(); 25420d9c9934SGreg Clayton } 25430d9c9934SGreg Clayton } 2544e7612134SGreg Clayton else if (sc->symbol && sc->symbol->ValueIsAddress()) 2545e7612134SGreg Clayton func_addr = sc->symbol->GetAddress(); 25460603aa9dSGreg Clayton } 25471b654882SGreg Clayton 25480603aa9dSGreg Clayton if (func_addr.IsValid()) 25491b654882SGreg Clayton { 25501b654882SGreg Clayton if (func_addr.GetSection() == format_addr.GetSection()) 25511b654882SGreg Clayton { 25521b654882SGreg Clayton addr_t func_file_addr = func_addr.GetFileAddress(); 25531b654882SGreg Clayton addr_t addr_file_addr = format_addr.GetFileAddress(); 25541b654882SGreg Clayton if (addr_file_addr > func_file_addr) 2555d01b2953SDaniel Malea s.Printf(" + %" PRIu64, addr_file_addr - func_file_addr); 25561b654882SGreg Clayton else if (addr_file_addr < func_file_addr) 2557d01b2953SDaniel Malea s.Printf(" - %" PRIu64, func_file_addr - addr_file_addr); 25580603aa9dSGreg Clayton var_success = true; 25591b654882SGreg Clayton } 25601b654882SGreg Clayton else 25610603aa9dSGreg Clayton { 25620603aa9dSGreg Clayton Target *target = Target::GetTargetFromContexts (exe_ctx, sc); 25630603aa9dSGreg Clayton if (target) 25640603aa9dSGreg Clayton { 25650603aa9dSGreg Clayton addr_t func_load_addr = func_addr.GetLoadAddress (target); 25660603aa9dSGreg Clayton addr_t addr_load_addr = format_addr.GetLoadAddress (target); 25670603aa9dSGreg Clayton if (addr_load_addr > func_load_addr) 2568d01b2953SDaniel Malea s.Printf(" + %" PRIu64, addr_load_addr - func_load_addr); 25690603aa9dSGreg Clayton else if (addr_load_addr < func_load_addr) 2570d01b2953SDaniel Malea s.Printf(" - %" PRIu64, func_load_addr - addr_load_addr); 25710603aa9dSGreg Clayton var_success = true; 25720603aa9dSGreg Clayton } 25730603aa9dSGreg Clayton } 25741b654882SGreg Clayton } 25751b654882SGreg Clayton } 25761b654882SGreg Clayton else 25771b654882SGreg Clayton { 25780603aa9dSGreg Clayton Target *target = Target::GetTargetFromContexts (exe_ctx, sc); 25791b654882SGreg Clayton addr_t vaddr = LLDB_INVALID_ADDRESS; 25800603aa9dSGreg Clayton if (exe_ctx && !target->GetSectionLoadList().IsEmpty()) 25810603aa9dSGreg Clayton vaddr = format_addr.GetLoadAddress (target); 25821b654882SGreg Clayton if (vaddr == LLDB_INVALID_ADDRESS) 25831b654882SGreg Clayton vaddr = format_addr.GetFileAddress (); 25841b654882SGreg Clayton 25851b654882SGreg Clayton if (vaddr != LLDB_INVALID_ADDRESS) 25860603aa9dSGreg Clayton { 2587514487e8SGreg Clayton int addr_width = target->GetArchitecture().GetAddressByteSize() * 2; 258835f1a0d5SGreg Clayton if (addr_width == 0) 258935f1a0d5SGreg Clayton addr_width = 16; 2590d01b2953SDaniel Malea s.Printf("0x%*.*" PRIx64, addr_width, addr_width, vaddr); 25910603aa9dSGreg Clayton var_success = true; 25920603aa9dSGreg Clayton } 25931b654882SGreg Clayton } 25941b654882SGreg Clayton } 25951b654882SGreg Clayton } 25961b654882SGreg Clayton 25971b654882SGreg Clayton if (var_success == false) 25981b654882SGreg Clayton success = false; 25991b654882SGreg Clayton } 26001b654882SGreg Clayton p = var_name_end; 26011b654882SGreg Clayton } 26021b654882SGreg Clayton else 26031b654882SGreg Clayton break; 26041b654882SGreg Clayton } 26051b654882SGreg Clayton else 26061b654882SGreg Clayton { 26071b654882SGreg Clayton // We got a dollar sign with no '{' after it, it must just be a dollar sign 26081b654882SGreg Clayton s.PutChar(*p); 26091b654882SGreg Clayton } 26101b654882SGreg Clayton } 26111b654882SGreg Clayton else if (*p == '\\') 26121b654882SGreg Clayton { 26131b654882SGreg Clayton ++p; // skip the slash 26141b654882SGreg Clayton switch (*p) 26151b654882SGreg Clayton { 26161b654882SGreg Clayton case 'a': s.PutChar ('\a'); break; 26171b654882SGreg Clayton case 'b': s.PutChar ('\b'); break; 26181b654882SGreg Clayton case 'f': s.PutChar ('\f'); break; 26191b654882SGreg Clayton case 'n': s.PutChar ('\n'); break; 26201b654882SGreg Clayton case 'r': s.PutChar ('\r'); break; 26211b654882SGreg Clayton case 't': s.PutChar ('\t'); break; 26221b654882SGreg Clayton case 'v': s.PutChar ('\v'); break; 26231b654882SGreg Clayton case '\'': s.PutChar ('\''); break; 26241b654882SGreg Clayton case '\\': s.PutChar ('\\'); break; 26251b654882SGreg Clayton case '0': 26261b654882SGreg Clayton // 1 to 3 octal chars 26271b654882SGreg Clayton { 26280603aa9dSGreg Clayton // Make a string that can hold onto the initial zero char, 26290603aa9dSGreg Clayton // up to 3 octal digits, and a terminating NULL. 26300603aa9dSGreg Clayton char oct_str[5] = { 0, 0, 0, 0, 0 }; 26310603aa9dSGreg Clayton 26320603aa9dSGreg Clayton int i; 26330603aa9dSGreg Clayton for (i=0; (p[i] >= '0' && p[i] <= '7') && i<4; ++i) 26340603aa9dSGreg Clayton oct_str[i] = p[i]; 26350603aa9dSGreg Clayton 26360603aa9dSGreg Clayton // We don't want to consume the last octal character since 26370603aa9dSGreg Clayton // the main for loop will do this for us, so we advance p by 26380603aa9dSGreg Clayton // one less than i (even if i is zero) 26390603aa9dSGreg Clayton p += i - 1; 26400603aa9dSGreg Clayton unsigned long octal_value = ::strtoul (oct_str, NULL, 8); 26410603aa9dSGreg Clayton if (octal_value <= UINT8_MAX) 26421b654882SGreg Clayton { 2643c7bece56SGreg Clayton s.PutChar((char)octal_value); 26441b654882SGreg Clayton } 26451b654882SGreg Clayton } 26461b654882SGreg Clayton break; 26471b654882SGreg Clayton 26481b654882SGreg Clayton case 'x': 26491b654882SGreg Clayton // hex number in the format 26500603aa9dSGreg Clayton if (isxdigit(p[1])) 26511b654882SGreg Clayton { 26520603aa9dSGreg Clayton ++p; // Skip the 'x' 26531b654882SGreg Clayton 26540603aa9dSGreg Clayton // Make a string that can hold onto two hex chars plus a 26550603aa9dSGreg Clayton // NULL terminator 26561b654882SGreg Clayton char hex_str[3] = { 0,0,0 }; 26571b654882SGreg Clayton hex_str[0] = *p; 26580603aa9dSGreg Clayton if (isxdigit(p[1])) 26590603aa9dSGreg Clayton { 26600603aa9dSGreg Clayton ++p; // Skip the first of the two hex chars 26611b654882SGreg Clayton hex_str[1] = *p; 26620603aa9dSGreg Clayton } 26630603aa9dSGreg Clayton 26641b654882SGreg Clayton unsigned long hex_value = strtoul (hex_str, NULL, 16); 26650603aa9dSGreg Clayton if (hex_value <= UINT8_MAX) 2666c7bece56SGreg Clayton s.PutChar ((char)hex_value); 26671b654882SGreg Clayton } 26681b654882SGreg Clayton else 26691b654882SGreg Clayton { 26700603aa9dSGreg Clayton s.PutChar('x'); 26711b654882SGreg Clayton } 26721b654882SGreg Clayton break; 26731b654882SGreg Clayton 26741b654882SGreg Clayton default: 26750603aa9dSGreg Clayton // Just desensitize any other character by just printing what 26760603aa9dSGreg Clayton // came after the '\' 26770603aa9dSGreg Clayton s << *p; 26781b654882SGreg Clayton break; 26791b654882SGreg Clayton 26801b654882SGreg Clayton } 26811b654882SGreg Clayton 26821b654882SGreg Clayton } 26831b654882SGreg Clayton } 26841b654882SGreg Clayton if (end) 26851b654882SGreg Clayton *end = p; 26861b654882SGreg Clayton return success; 26871b654882SGreg Clayton } 26881b654882SGreg Clayton 2689c3ce7f27SMichael Sartain bool 2690c3ce7f27SMichael Sartain Debugger::FormatPrompt 2691c3ce7f27SMichael Sartain ( 2692c3ce7f27SMichael Sartain const char *format, 2693c3ce7f27SMichael Sartain const SymbolContext *sc, 2694c3ce7f27SMichael Sartain const ExecutionContext *exe_ctx, 2695c3ce7f27SMichael Sartain const Address *addr, 2696c3ce7f27SMichael Sartain Stream &s, 2697c3ce7f27SMichael Sartain ValueObject* valobj 2698c3ce7f27SMichael Sartain ) 2699c3ce7f27SMichael Sartain { 2700c3ce7f27SMichael Sartain bool use_color = exe_ctx ? exe_ctx->GetTargetRef().GetDebugger().GetUseColor() : true; 2701c3ce7f27SMichael Sartain std::string format_str = lldb_utility::ansi::FormatAnsiTerminalCodes (format, use_color); 2702c3ce7f27SMichael Sartain if (format_str.length()) 2703c3ce7f27SMichael Sartain format = format_str.c_str(); 2704c3ce7f27SMichael Sartain return FormatPromptRecurse (format, sc, exe_ctx, addr, s, NULL, valobj); 2705c3ce7f27SMichael Sartain } 2706c3ce7f27SMichael Sartain 2707228063cdSJim Ingham void 2708228063cdSJim Ingham Debugger::SetLoggingCallback (lldb::LogOutputCallback log_callback, void *baton) 2709228063cdSJim Ingham { 27104f02b22dSJim Ingham // For simplicity's sake, I am not going to deal with how to close down any 27114f02b22dSJim Ingham // open logging streams, I just redirect everything from here on out to the 27124f02b22dSJim Ingham // callback. 2713228063cdSJim Ingham m_log_callback_stream_sp.reset (new StreamCallback (log_callback, baton)); 2714228063cdSJim Ingham } 2715228063cdSJim Ingham 2716228063cdSJim Ingham bool 2717228063cdSJim Ingham Debugger::EnableLog (const char *channel, const char **categories, const char *log_file, uint32_t log_options, Stream &error_stream) 2718228063cdSJim Ingham { 2719228063cdSJim Ingham Log::Callbacks log_callbacks; 2720228063cdSJim Ingham 2721228063cdSJim Ingham StreamSP log_stream_sp; 27229a028519SSean Callanan if (m_log_callback_stream_sp) 2723228063cdSJim Ingham { 2724228063cdSJim Ingham log_stream_sp = m_log_callback_stream_sp; 2725228063cdSJim Ingham // For now when using the callback mode you always get thread & timestamp. 2726228063cdSJim Ingham log_options |= LLDB_LOG_OPTION_PREPEND_TIMESTAMP | LLDB_LOG_OPTION_PREPEND_THREAD_NAME; 2727228063cdSJim Ingham } 2728228063cdSJim Ingham else if (log_file == NULL || *log_file == '\0') 2729228063cdSJim Ingham { 273044d93782SGreg Clayton log_stream_sp = GetOutputFile(); 2731228063cdSJim Ingham } 2732228063cdSJim Ingham else 2733228063cdSJim Ingham { 2734228063cdSJim Ingham LogStreamMap::iterator pos = m_log_streams.find(log_file); 2735c1b2ccfdSGreg Clayton if (pos != m_log_streams.end()) 2736c1b2ccfdSGreg Clayton log_stream_sp = pos->second.lock(); 2737c1b2ccfdSGreg Clayton if (!log_stream_sp) 2738228063cdSJim Ingham { 2739228063cdSJim Ingham log_stream_sp.reset (new StreamFile (log_file)); 2740228063cdSJim Ingham m_log_streams[log_file] = log_stream_sp; 2741228063cdSJim Ingham } 2742228063cdSJim Ingham } 2743228063cdSJim Ingham assert (log_stream_sp.get()); 2744228063cdSJim Ingham 2745228063cdSJim Ingham if (log_options == 0) 2746228063cdSJim Ingham log_options = LLDB_LOG_OPTION_PREPEND_THREAD_NAME | LLDB_LOG_OPTION_THREADSAFE; 2747228063cdSJim Ingham 274857abc5d6SGreg Clayton if (Log::GetLogChannelCallbacks (ConstString(channel), log_callbacks)) 2749228063cdSJim Ingham { 2750228063cdSJim Ingham log_callbacks.enable (log_stream_sp, log_options, categories, &error_stream); 2751228063cdSJim Ingham return true; 2752228063cdSJim Ingham } 2753228063cdSJim Ingham else 2754228063cdSJim Ingham { 2755228063cdSJim Ingham LogChannelSP log_channel_sp (LogChannel::FindPlugin (channel)); 2756228063cdSJim Ingham if (log_channel_sp) 2757228063cdSJim Ingham { 2758228063cdSJim Ingham if (log_channel_sp->Enable (log_stream_sp, log_options, &error_stream, categories)) 2759228063cdSJim Ingham { 2760228063cdSJim Ingham return true; 2761228063cdSJim Ingham } 2762228063cdSJim Ingham else 2763228063cdSJim Ingham { 2764228063cdSJim Ingham error_stream.Printf ("Invalid log channel '%s'.\n", channel); 2765228063cdSJim Ingham return false; 2766228063cdSJim Ingham } 2767228063cdSJim Ingham } 2768228063cdSJim Ingham else 2769228063cdSJim Ingham { 2770228063cdSJim Ingham error_stream.Printf ("Invalid log channel '%s'.\n", channel); 2771228063cdSJim Ingham return false; 2772228063cdSJim Ingham } 2773228063cdSJim Ingham } 2774228063cdSJim Ingham return false; 2775228063cdSJim Ingham } 2776228063cdSJim Ingham 27779585fbfcSGreg Clayton SourceManager & 27789585fbfcSGreg Clayton Debugger::GetSourceManager () 27799585fbfcSGreg Clayton { 27809585fbfcSGreg Clayton if (m_source_manager_ap.get() == NULL) 27819585fbfcSGreg Clayton m_source_manager_ap.reset (new SourceManager (shared_from_this())); 27829585fbfcSGreg Clayton return *m_source_manager_ap; 27839585fbfcSGreg Clayton } 27849585fbfcSGreg Clayton 27859585fbfcSGreg Clayton 278644d93782SGreg Clayton 278744d93782SGreg Clayton // This function handles events that were broadcast by the process. 278844d93782SGreg Clayton void 278944d93782SGreg Clayton Debugger::HandleBreakpointEvent (const EventSP &event_sp) 279044d93782SGreg Clayton { 279144d93782SGreg Clayton using namespace lldb; 279244d93782SGreg Clayton const uint32_t event_type = Breakpoint::BreakpointEventData::GetBreakpointEventTypeFromEvent (event_sp); 279344d93782SGreg Clayton 279444d93782SGreg Clayton // if (event_type & eBreakpointEventTypeAdded 279544d93782SGreg Clayton // || event_type & eBreakpointEventTypeRemoved 279644d93782SGreg Clayton // || event_type & eBreakpointEventTypeEnabled 279744d93782SGreg Clayton // || event_type & eBreakpointEventTypeDisabled 279844d93782SGreg Clayton // || event_type & eBreakpointEventTypeCommandChanged 279944d93782SGreg Clayton // || event_type & eBreakpointEventTypeConditionChanged 280044d93782SGreg Clayton // || event_type & eBreakpointEventTypeIgnoreChanged 280144d93782SGreg Clayton // || event_type & eBreakpointEventTypeLocationsResolved) 280244d93782SGreg Clayton // { 280344d93782SGreg Clayton // // Don't do anything about these events, since the breakpoint commands already echo these actions. 280444d93782SGreg Clayton // } 280544d93782SGreg Clayton // 280644d93782SGreg Clayton if (event_type & eBreakpointEventTypeLocationsAdded) 280744d93782SGreg Clayton { 280844d93782SGreg Clayton uint32_t num_new_locations = Breakpoint::BreakpointEventData::GetNumBreakpointLocationsFromEvent(event_sp); 280944d93782SGreg Clayton if (num_new_locations > 0) 281044d93782SGreg Clayton { 281144d93782SGreg Clayton BreakpointSP breakpoint = Breakpoint::BreakpointEventData::GetBreakpointFromEvent(event_sp); 281244d93782SGreg Clayton StreamFileSP output_sp (GetOutputFile()); 281344d93782SGreg Clayton if (output_sp) 281444d93782SGreg Clayton { 281544d93782SGreg Clayton output_sp->Printf("%d location%s added to breakpoint %d\n", 281644d93782SGreg Clayton num_new_locations, 281744d93782SGreg Clayton num_new_locations == 1 ? "" : "s", 281844d93782SGreg Clayton breakpoint->GetID()); 281944d93782SGreg Clayton RefreshTopIOHandler(); 282044d93782SGreg Clayton } 282144d93782SGreg Clayton } 282244d93782SGreg Clayton } 282344d93782SGreg Clayton // else if (event_type & eBreakpointEventTypeLocationsRemoved) 282444d93782SGreg Clayton // { 282544d93782SGreg Clayton // // These locations just get disabled, not sure it is worth spamming folks about this on the command line. 282644d93782SGreg Clayton // } 282744d93782SGreg Clayton // else if (event_type & eBreakpointEventTypeLocationsResolved) 282844d93782SGreg Clayton // { 282944d93782SGreg Clayton // // This might be an interesting thing to note, but I'm going to leave it quiet for now, it just looked noisy. 283044d93782SGreg Clayton // } 283144d93782SGreg Clayton } 283244d93782SGreg Clayton 283344d93782SGreg Clayton size_t 283444d93782SGreg Clayton Debugger::GetProcessSTDOUT (Process *process, Stream *stream) 283544d93782SGreg Clayton { 283644d93782SGreg Clayton size_t total_bytes = 0; 283744d93782SGreg Clayton if (stream == NULL) 283844d93782SGreg Clayton stream = GetOutputFile().get(); 283944d93782SGreg Clayton 284044d93782SGreg Clayton if (stream) 284144d93782SGreg Clayton { 284244d93782SGreg Clayton // The process has stuff waiting for stdout; get it and write it out to the appropriate place. 284344d93782SGreg Clayton if (process == NULL) 284444d93782SGreg Clayton { 284544d93782SGreg Clayton TargetSP target_sp = GetTargetList().GetSelectedTarget(); 284644d93782SGreg Clayton if (target_sp) 284744d93782SGreg Clayton process = target_sp->GetProcessSP().get(); 284844d93782SGreg Clayton } 284944d93782SGreg Clayton if (process) 285044d93782SGreg Clayton { 285144d93782SGreg Clayton Error error; 285244d93782SGreg Clayton size_t len; 285344d93782SGreg Clayton char stdio_buffer[1024]; 285444d93782SGreg Clayton while ((len = process->GetSTDOUT (stdio_buffer, sizeof (stdio_buffer), error)) > 0) 285544d93782SGreg Clayton { 285644d93782SGreg Clayton stream->Write(stdio_buffer, len); 285744d93782SGreg Clayton total_bytes += len; 285844d93782SGreg Clayton } 285944d93782SGreg Clayton } 286044d93782SGreg Clayton stream->Flush(); 286144d93782SGreg Clayton } 286244d93782SGreg Clayton return total_bytes; 286344d93782SGreg Clayton } 286444d93782SGreg Clayton 286544d93782SGreg Clayton size_t 286644d93782SGreg Clayton Debugger::GetProcessSTDERR (Process *process, Stream *stream) 286744d93782SGreg Clayton { 286844d93782SGreg Clayton size_t total_bytes = 0; 286944d93782SGreg Clayton if (stream == NULL) 287044d93782SGreg Clayton stream = GetOutputFile().get(); 287144d93782SGreg Clayton 287244d93782SGreg Clayton if (stream) 287344d93782SGreg Clayton { 287444d93782SGreg Clayton // The process has stuff waiting for stderr; get it and write it out to the appropriate place. 287544d93782SGreg Clayton if (process == NULL) 287644d93782SGreg Clayton { 287744d93782SGreg Clayton TargetSP target_sp = GetTargetList().GetSelectedTarget(); 287844d93782SGreg Clayton if (target_sp) 287944d93782SGreg Clayton process = target_sp->GetProcessSP().get(); 288044d93782SGreg Clayton } 288144d93782SGreg Clayton if (process) 288244d93782SGreg Clayton { 288344d93782SGreg Clayton Error error; 288444d93782SGreg Clayton size_t len; 288544d93782SGreg Clayton char stdio_buffer[1024]; 288644d93782SGreg Clayton while ((len = process->GetSTDERR (stdio_buffer, sizeof (stdio_buffer), error)) > 0) 288744d93782SGreg Clayton { 288844d93782SGreg Clayton stream->Write(stdio_buffer, len); 288944d93782SGreg Clayton total_bytes += len; 289044d93782SGreg Clayton } 289144d93782SGreg Clayton } 289244d93782SGreg Clayton stream->Flush(); 289344d93782SGreg Clayton } 289444d93782SGreg Clayton return total_bytes; 289544d93782SGreg Clayton } 289644d93782SGreg Clayton 289744d93782SGreg Clayton // This function handles events that were broadcast by the process. 289844d93782SGreg Clayton void 289944d93782SGreg Clayton Debugger::HandleProcessEvent (const EventSP &event_sp) 290044d93782SGreg Clayton { 290144d93782SGreg Clayton using namespace lldb; 290244d93782SGreg Clayton const uint32_t event_type = event_sp->GetType(); 290344d93782SGreg Clayton ProcessSP process_sp = Process::ProcessEventData::GetProcessFromEvent(event_sp.get()); 290444d93782SGreg Clayton 2905b4874f1aSGreg Clayton StreamString output_stream; 2906b4874f1aSGreg Clayton StreamString error_stream; 290744d93782SGreg Clayton const bool gui_enabled = IsForwardingEvents(); 290844d93782SGreg Clayton 2909b4874f1aSGreg Clayton if (!gui_enabled) 2910b4874f1aSGreg Clayton { 2911b4874f1aSGreg Clayton bool pop_process_io_handler = false; 291244d93782SGreg Clayton assert (process_sp); 291344d93782SGreg Clayton 2914b4874f1aSGreg Clayton if (event_type & Process::eBroadcastBitSTDOUT || event_type & Process::eBroadcastBitStateChanged) 291544d93782SGreg Clayton { 2916b4874f1aSGreg Clayton GetProcessSTDOUT (process_sp.get(), &output_stream); 291744d93782SGreg Clayton } 2918b4874f1aSGreg Clayton 2919b4874f1aSGreg Clayton if (event_type & Process::eBroadcastBitSTDERR || event_type & Process::eBroadcastBitStateChanged) 292044d93782SGreg Clayton { 2921b4874f1aSGreg Clayton GetProcessSTDERR (process_sp.get(), &error_stream); 292244d93782SGreg Clayton } 2923b4874f1aSGreg Clayton 2924b4874f1aSGreg Clayton if (event_type & Process::eBroadcastBitStateChanged) 292544d93782SGreg Clayton { 2926b4874f1aSGreg Clayton 292744d93782SGreg Clayton // Drain all stout and stderr so we don't see any output come after 292844d93782SGreg Clayton // we print our prompts 292944d93782SGreg Clayton // Something changed in the process; get the event and report the process's current status and location to 293044d93782SGreg Clayton // the user. 293144d93782SGreg Clayton StateType event_state = Process::ProcessEventData::GetStateFromEvent (event_sp.get()); 293244d93782SGreg Clayton if (event_state == eStateInvalid) 293344d93782SGreg Clayton return; 293444d93782SGreg Clayton 293544d93782SGreg Clayton switch (event_state) 293644d93782SGreg Clayton { 293744d93782SGreg Clayton case eStateInvalid: 293844d93782SGreg Clayton case eStateUnloaded: 293944d93782SGreg Clayton case eStateConnected: 294044d93782SGreg Clayton case eStateAttaching: 294144d93782SGreg Clayton case eStateLaunching: 294244d93782SGreg Clayton case eStateStepping: 294344d93782SGreg Clayton case eStateDetached: 294444d93782SGreg Clayton { 2945b4874f1aSGreg Clayton output_stream.Printf("Process %" PRIu64 " %s\n", 294644d93782SGreg Clayton process_sp->GetID(), 294744d93782SGreg Clayton StateAsCString (event_state)); 2948b4874f1aSGreg Clayton 2949b4874f1aSGreg Clayton if (event_state == eStateDetached) 2950b4874f1aSGreg Clayton pop_process_io_handler = true; 295144d93782SGreg Clayton } 295244d93782SGreg Clayton break; 295344d93782SGreg Clayton 295444d93782SGreg Clayton case eStateRunning: 295544d93782SGreg Clayton // Don't be chatty when we run... 295644d93782SGreg Clayton break; 295744d93782SGreg Clayton 295844d93782SGreg Clayton case eStateExited: 2959b4874f1aSGreg Clayton process_sp->GetStatus(output_stream); 2960b4874f1aSGreg Clayton pop_process_io_handler = true; 296144d93782SGreg Clayton break; 296244d93782SGreg Clayton 296344d93782SGreg Clayton case eStateStopped: 296444d93782SGreg Clayton case eStateCrashed: 296544d93782SGreg Clayton case eStateSuspended: 296644d93782SGreg Clayton // Make sure the program hasn't been auto-restarted: 296744d93782SGreg Clayton if (Process::ProcessEventData::GetRestartedFromEvent (event_sp.get())) 296844d93782SGreg Clayton { 296944d93782SGreg Clayton size_t num_reasons = Process::ProcessEventData::GetNumRestartedReasons(event_sp.get()); 297044d93782SGreg Clayton if (num_reasons > 0) 297144d93782SGreg Clayton { 297244d93782SGreg Clayton // FIXME: Do we want to report this, or would that just be annoyingly chatty? 297344d93782SGreg Clayton if (num_reasons == 1) 297444d93782SGreg Clayton { 297544d93782SGreg Clayton const char *reason = Process::ProcessEventData::GetRestartedReasonAtIndex (event_sp.get(), 0); 2976b4874f1aSGreg Clayton output_stream.Printf("Process %" PRIu64 " stopped and restarted: %s\n", 297744d93782SGreg Clayton process_sp->GetID(), 297844d93782SGreg Clayton reason ? reason : "<UNKNOWN REASON>"); 297944d93782SGreg Clayton } 298044d93782SGreg Clayton else 298144d93782SGreg Clayton { 2982b4874f1aSGreg Clayton output_stream.Printf("Process %" PRIu64 " stopped and restarted, reasons:\n", 298344d93782SGreg Clayton process_sp->GetID()); 298444d93782SGreg Clayton 298544d93782SGreg Clayton 298644d93782SGreg Clayton for (size_t i = 0; i < num_reasons; i++) 298744d93782SGreg Clayton { 298844d93782SGreg Clayton const char *reason = Process::ProcessEventData::GetRestartedReasonAtIndex (event_sp.get(), i); 2989b4874f1aSGreg Clayton output_stream.Printf("\t%s\n", reason ? reason : "<UNKNOWN REASON>"); 299044d93782SGreg Clayton } 299144d93782SGreg Clayton } 299244d93782SGreg Clayton } 299344d93782SGreg Clayton } 299444d93782SGreg Clayton else 299544d93782SGreg Clayton { 29964a65fb1fSJim Ingham // Lock the thread list so it doesn't change on us, this is the scope for the locker: 29974a65fb1fSJim Ingham { 299844d93782SGreg Clayton ThreadList &thread_list = process_sp->GetThreadList(); 299944d93782SGreg Clayton Mutex::Locker locker (thread_list.GetMutex()); 300044d93782SGreg Clayton 300144d93782SGreg Clayton ThreadSP curr_thread (thread_list.GetSelectedThread()); 300244d93782SGreg Clayton ThreadSP thread; 300344d93782SGreg Clayton StopReason curr_thread_stop_reason = eStopReasonInvalid; 300444d93782SGreg Clayton if (curr_thread) 300544d93782SGreg Clayton curr_thread_stop_reason = curr_thread->GetStopReason(); 3006c809cbcfSGreg Clayton if (!curr_thread || 3007c809cbcfSGreg Clayton !curr_thread->IsValid() || 300844d93782SGreg Clayton curr_thread_stop_reason == eStopReasonInvalid || 300944d93782SGreg Clayton curr_thread_stop_reason == eStopReasonNone) 301044d93782SGreg Clayton { 301144d93782SGreg Clayton // Prefer a thread that has just completed its plan over another thread as current thread. 301244d93782SGreg Clayton ThreadSP plan_thread; 301344d93782SGreg Clayton ThreadSP other_thread; 301444d93782SGreg Clayton const size_t num_threads = thread_list.GetSize(); 301544d93782SGreg Clayton size_t i; 301644d93782SGreg Clayton for (i = 0; i < num_threads; ++i) 301744d93782SGreg Clayton { 301844d93782SGreg Clayton thread = thread_list.GetThreadAtIndex(i); 301944d93782SGreg Clayton StopReason thread_stop_reason = thread->GetStopReason(); 302044d93782SGreg Clayton switch (thread_stop_reason) 302144d93782SGreg Clayton { 302244d93782SGreg Clayton case eStopReasonInvalid: 302344d93782SGreg Clayton case eStopReasonNone: 302444d93782SGreg Clayton break; 302544d93782SGreg Clayton 302644d93782SGreg Clayton case eStopReasonTrace: 302744d93782SGreg Clayton case eStopReasonBreakpoint: 302844d93782SGreg Clayton case eStopReasonWatchpoint: 302944d93782SGreg Clayton case eStopReasonSignal: 303044d93782SGreg Clayton case eStopReasonException: 303144d93782SGreg Clayton case eStopReasonExec: 303244d93782SGreg Clayton case eStopReasonThreadExiting: 303344d93782SGreg Clayton if (!other_thread) 303444d93782SGreg Clayton other_thread = thread; 303544d93782SGreg Clayton break; 303644d93782SGreg Clayton case eStopReasonPlanComplete: 303744d93782SGreg Clayton if (!plan_thread) 303844d93782SGreg Clayton plan_thread = thread; 303944d93782SGreg Clayton break; 304044d93782SGreg Clayton } 304144d93782SGreg Clayton } 304244d93782SGreg Clayton if (plan_thread) 304344d93782SGreg Clayton thread_list.SetSelectedThreadByID (plan_thread->GetID()); 304444d93782SGreg Clayton else if (other_thread) 304544d93782SGreg Clayton thread_list.SetSelectedThreadByID (other_thread->GetID()); 304644d93782SGreg Clayton else 304744d93782SGreg Clayton { 30484046a30cSJim Ingham if (curr_thread && curr_thread->IsValid()) 304944d93782SGreg Clayton thread = curr_thread; 305044d93782SGreg Clayton else 305144d93782SGreg Clayton thread = thread_list.GetThreadAtIndex(0); 305244d93782SGreg Clayton 305344d93782SGreg Clayton if (thread) 305444d93782SGreg Clayton thread_list.SetSelectedThreadByID (thread->GetID()); 305544d93782SGreg Clayton } 305644d93782SGreg Clayton } 30574a65fb1fSJim Ingham } 30584a65fb1fSJim Ingham // Drop the ThreadList mutex by here, since GetThreadStatus below might have to run code, 30594a65fb1fSJim Ingham // e.g. for Data formatters, and if we hold the ThreadList mutex, then the process is going to 30604a65fb1fSJim Ingham // have a hard time restarting the process. 306144d93782SGreg Clayton 306244d93782SGreg Clayton if (GetTargetList().GetSelectedTarget().get() == &process_sp->GetTarget()) 306344d93782SGreg Clayton { 306444d93782SGreg Clayton const bool only_threads_with_stop_reason = true; 306544d93782SGreg Clayton const uint32_t start_frame = 0; 306644d93782SGreg Clayton const uint32_t num_frames = 1; 306744d93782SGreg Clayton const uint32_t num_frames_with_source = 1; 3068b4874f1aSGreg Clayton process_sp->GetStatus(output_stream); 3069b4874f1aSGreg Clayton process_sp->GetThreadStatus (output_stream, 307044d93782SGreg Clayton only_threads_with_stop_reason, 307144d93782SGreg Clayton start_frame, 307244d93782SGreg Clayton num_frames, 307344d93782SGreg Clayton num_frames_with_source); 307444d93782SGreg Clayton } 307544d93782SGreg Clayton else 307644d93782SGreg Clayton { 307744d93782SGreg Clayton uint32_t target_idx = GetTargetList().GetIndexOfTarget(process_sp->GetTarget().shared_from_this()); 307844d93782SGreg Clayton if (target_idx != UINT32_MAX) 3079b4874f1aSGreg Clayton output_stream.Printf ("Target %d: (", target_idx); 308044d93782SGreg Clayton else 3081b4874f1aSGreg Clayton output_stream.Printf ("Target <unknown index>: ("); 3082b4874f1aSGreg Clayton process_sp->GetTarget().Dump (&output_stream, eDescriptionLevelBrief); 3083b4874f1aSGreg Clayton output_stream.Printf (") stopped.\n"); 308444d93782SGreg Clayton } 3085b4874f1aSGreg Clayton 3086b4874f1aSGreg Clayton // Pop the process IO handler 3087b4874f1aSGreg Clayton pop_process_io_handler = true; 308844d93782SGreg Clayton } 308944d93782SGreg Clayton break; 309044d93782SGreg Clayton } 309144d93782SGreg Clayton } 3092b4874f1aSGreg Clayton 3093b4874f1aSGreg Clayton if (output_stream.GetSize() || error_stream.GetSize()) 3094b4874f1aSGreg Clayton { 3095b4874f1aSGreg Clayton StreamFileSP error_stream_sp (GetOutputFile()); 30966fea17e8SGreg Clayton bool top_io_handler_hid = false; 30976fea17e8SGreg Clayton 30986fea17e8SGreg Clayton if (process_sp->ProcessIOHandlerIsActive() == false) 30996fea17e8SGreg Clayton top_io_handler_hid = HideTopIOHandler(); 3100b4874f1aSGreg Clayton 3101b4874f1aSGreg Clayton if (output_stream.GetSize()) 3102b4874f1aSGreg Clayton { 3103b4874f1aSGreg Clayton StreamFileSP output_stream_sp (GetOutputFile()); 3104b4874f1aSGreg Clayton if (output_stream_sp) 3105b4874f1aSGreg Clayton output_stream_sp->Write (output_stream.GetData(), output_stream.GetSize()); 3106b4874f1aSGreg Clayton } 3107b4874f1aSGreg Clayton 3108b4874f1aSGreg Clayton if (error_stream.GetSize()) 3109b4874f1aSGreg Clayton { 3110b4874f1aSGreg Clayton StreamFileSP error_stream_sp (GetErrorFile()); 3111b4874f1aSGreg Clayton if (error_stream_sp) 3112b4874f1aSGreg Clayton error_stream_sp->Write (error_stream.GetData(), error_stream.GetSize()); 311344d93782SGreg Clayton } 311444d93782SGreg Clayton 311544d93782SGreg Clayton if (top_io_handler_hid) 311644d93782SGreg Clayton RefreshTopIOHandler(); 311744d93782SGreg Clayton } 311844d93782SGreg Clayton 3119b4874f1aSGreg Clayton if (pop_process_io_handler) 3120b4874f1aSGreg Clayton process_sp->PopProcessIOHandler(); 3121b4874f1aSGreg Clayton } 3122b4874f1aSGreg Clayton } 3123b4874f1aSGreg Clayton 312444d93782SGreg Clayton void 312544d93782SGreg Clayton Debugger::HandleThreadEvent (const EventSP &event_sp) 312644d93782SGreg Clayton { 312744d93782SGreg Clayton // At present the only thread event we handle is the Frame Changed event, 312844d93782SGreg Clayton // and all we do for that is just reprint the thread status for that thread. 312944d93782SGreg Clayton using namespace lldb; 313044d93782SGreg Clayton const uint32_t event_type = event_sp->GetType(); 313144d93782SGreg Clayton if (event_type == Thread::eBroadcastBitStackChanged || 313244d93782SGreg Clayton event_type == Thread::eBroadcastBitThreadSelected ) 313344d93782SGreg Clayton { 313444d93782SGreg Clayton ThreadSP thread_sp (Thread::ThreadEventData::GetThreadFromEvent (event_sp.get())); 313544d93782SGreg Clayton if (thread_sp) 313644d93782SGreg Clayton { 313744d93782SGreg Clayton HideTopIOHandler(); 313844d93782SGreg Clayton StreamFileSP stream_sp (GetOutputFile()); 313944d93782SGreg Clayton thread_sp->GetStatus(*stream_sp, 0, 1, 1); 314044d93782SGreg Clayton RefreshTopIOHandler(); 314144d93782SGreg Clayton } 314244d93782SGreg Clayton } 314344d93782SGreg Clayton } 314444d93782SGreg Clayton 314544d93782SGreg Clayton bool 314644d93782SGreg Clayton Debugger::IsForwardingEvents () 314744d93782SGreg Clayton { 314844d93782SGreg Clayton return (bool)m_forward_listener_sp; 314944d93782SGreg Clayton } 315044d93782SGreg Clayton 315144d93782SGreg Clayton void 315244d93782SGreg Clayton Debugger::EnableForwardEvents (const ListenerSP &listener_sp) 315344d93782SGreg Clayton { 315444d93782SGreg Clayton m_forward_listener_sp = listener_sp; 315544d93782SGreg Clayton } 315644d93782SGreg Clayton 315744d93782SGreg Clayton void 315844d93782SGreg Clayton Debugger::CancelForwardEvents (const ListenerSP &listener_sp) 315944d93782SGreg Clayton { 316044d93782SGreg Clayton m_forward_listener_sp.reset(); 316144d93782SGreg Clayton } 316244d93782SGreg Clayton 316344d93782SGreg Clayton 316444d93782SGreg Clayton void 316544d93782SGreg Clayton Debugger::DefaultEventHandler() 316644d93782SGreg Clayton { 316744d93782SGreg Clayton Listener& listener(GetListener()); 316844d93782SGreg Clayton ConstString broadcaster_class_target(Target::GetStaticBroadcasterClass()); 316944d93782SGreg Clayton ConstString broadcaster_class_process(Process::GetStaticBroadcasterClass()); 317044d93782SGreg Clayton ConstString broadcaster_class_thread(Thread::GetStaticBroadcasterClass()); 317144d93782SGreg Clayton BroadcastEventSpec target_event_spec (broadcaster_class_target, 317244d93782SGreg Clayton Target::eBroadcastBitBreakpointChanged); 317344d93782SGreg Clayton 317444d93782SGreg Clayton BroadcastEventSpec process_event_spec (broadcaster_class_process, 317544d93782SGreg Clayton Process::eBroadcastBitStateChanged | 317644d93782SGreg Clayton Process::eBroadcastBitSTDOUT | 317744d93782SGreg Clayton Process::eBroadcastBitSTDERR); 317844d93782SGreg Clayton 317944d93782SGreg Clayton BroadcastEventSpec thread_event_spec (broadcaster_class_thread, 318044d93782SGreg Clayton Thread::eBroadcastBitStackChanged | 318144d93782SGreg Clayton Thread::eBroadcastBitThreadSelected ); 318244d93782SGreg Clayton 318344d93782SGreg Clayton listener.StartListeningForEventSpec (*this, target_event_spec); 318444d93782SGreg Clayton listener.StartListeningForEventSpec (*this, process_event_spec); 318544d93782SGreg Clayton listener.StartListeningForEventSpec (*this, thread_event_spec); 318644d93782SGreg Clayton listener.StartListeningForEvents (m_command_interpreter_ap.get(), 318744d93782SGreg Clayton CommandInterpreter::eBroadcastBitQuitCommandReceived | 318844d93782SGreg Clayton CommandInterpreter::eBroadcastBitAsynchronousOutputData | 318944d93782SGreg Clayton CommandInterpreter::eBroadcastBitAsynchronousErrorData ); 319044d93782SGreg Clayton 319144d93782SGreg Clayton bool done = false; 319244d93782SGreg Clayton while (!done) 319344d93782SGreg Clayton { 319444d93782SGreg Clayton // Mutex::Locker locker; 319544d93782SGreg Clayton // if (locker.TryLock(m_input_reader_stack.GetMutex())) 319644d93782SGreg Clayton // { 319744d93782SGreg Clayton // if (m_input_reader_stack.IsEmpty()) 319844d93782SGreg Clayton // break; 319944d93782SGreg Clayton // } 320044d93782SGreg Clayton // 320144d93782SGreg Clayton EventSP event_sp; 320244d93782SGreg Clayton if (listener.WaitForEvent(NULL, event_sp)) 320344d93782SGreg Clayton { 320444d93782SGreg Clayton if (event_sp) 320544d93782SGreg Clayton { 320644d93782SGreg Clayton Broadcaster *broadcaster = event_sp->GetBroadcaster(); 320744d93782SGreg Clayton if (broadcaster) 320844d93782SGreg Clayton { 320944d93782SGreg Clayton uint32_t event_type = event_sp->GetType(); 321044d93782SGreg Clayton ConstString broadcaster_class (broadcaster->GetBroadcasterClass()); 321144d93782SGreg Clayton if (broadcaster_class == broadcaster_class_process) 321244d93782SGreg Clayton { 321344d93782SGreg Clayton HandleProcessEvent (event_sp); 321444d93782SGreg Clayton } 321544d93782SGreg Clayton else if (broadcaster_class == broadcaster_class_target) 321644d93782SGreg Clayton { 321744d93782SGreg Clayton if (Breakpoint::BreakpointEventData::GetEventDataFromEvent(event_sp.get())) 321844d93782SGreg Clayton { 321944d93782SGreg Clayton HandleBreakpointEvent (event_sp); 322044d93782SGreg Clayton } 322144d93782SGreg Clayton } 322244d93782SGreg Clayton else if (broadcaster_class == broadcaster_class_thread) 322344d93782SGreg Clayton { 322444d93782SGreg Clayton HandleThreadEvent (event_sp); 322544d93782SGreg Clayton } 322644d93782SGreg Clayton else if (broadcaster == m_command_interpreter_ap.get()) 322744d93782SGreg Clayton { 322844d93782SGreg Clayton if (event_type & CommandInterpreter::eBroadcastBitQuitCommandReceived) 322944d93782SGreg Clayton { 323044d93782SGreg Clayton done = true; 323144d93782SGreg Clayton } 323244d93782SGreg Clayton else if (event_type & CommandInterpreter::eBroadcastBitAsynchronousErrorData) 323344d93782SGreg Clayton { 323444d93782SGreg Clayton const char *data = reinterpret_cast<const char *>(EventDataBytes::GetBytesFromEvent (event_sp.get())); 323544d93782SGreg Clayton if (data && data[0]) 323644d93782SGreg Clayton { 323744d93782SGreg Clayton StreamFileSP error_sp (GetErrorFile()); 323844d93782SGreg Clayton if (error_sp) 323944d93782SGreg Clayton { 324044d93782SGreg Clayton HideTopIOHandler(); 324144d93782SGreg Clayton error_sp->PutCString(data); 324244d93782SGreg Clayton error_sp->Flush(); 324344d93782SGreg Clayton RefreshTopIOHandler(); 324444d93782SGreg Clayton } 324544d93782SGreg Clayton } 324644d93782SGreg Clayton } 324744d93782SGreg Clayton else if (event_type & CommandInterpreter::eBroadcastBitAsynchronousOutputData) 324844d93782SGreg Clayton { 324944d93782SGreg Clayton const char *data = reinterpret_cast<const char *>(EventDataBytes::GetBytesFromEvent (event_sp.get())); 325044d93782SGreg Clayton if (data && data[0]) 325144d93782SGreg Clayton { 325244d93782SGreg Clayton StreamFileSP output_sp (GetOutputFile()); 325344d93782SGreg Clayton if (output_sp) 325444d93782SGreg Clayton { 325544d93782SGreg Clayton HideTopIOHandler(); 325644d93782SGreg Clayton output_sp->PutCString(data); 325744d93782SGreg Clayton output_sp->Flush(); 325844d93782SGreg Clayton RefreshTopIOHandler(); 325944d93782SGreg Clayton } 326044d93782SGreg Clayton } 326144d93782SGreg Clayton } 326244d93782SGreg Clayton } 326344d93782SGreg Clayton } 326444d93782SGreg Clayton 326544d93782SGreg Clayton if (m_forward_listener_sp) 326644d93782SGreg Clayton m_forward_listener_sp->AddEvent(event_sp); 326744d93782SGreg Clayton } 326844d93782SGreg Clayton } 326944d93782SGreg Clayton } 327044d93782SGreg Clayton } 327144d93782SGreg Clayton 327244d93782SGreg Clayton lldb::thread_result_t 327344d93782SGreg Clayton Debugger::EventHandlerThread (lldb::thread_arg_t arg) 327444d93782SGreg Clayton { 327544d93782SGreg Clayton ((Debugger *)arg)->DefaultEventHandler(); 327644d93782SGreg Clayton return NULL; 327744d93782SGreg Clayton } 327844d93782SGreg Clayton 327944d93782SGreg Clayton bool 328044d93782SGreg Clayton Debugger::StartEventHandlerThread() 328144d93782SGreg Clayton { 328244d93782SGreg Clayton if (!IS_VALID_LLDB_HOST_THREAD(m_event_handler_thread)) 328344d93782SGreg Clayton m_event_handler_thread = Host::ThreadCreate("lldb.debugger.event-handler", EventHandlerThread, this, NULL); 328444d93782SGreg Clayton return IS_VALID_LLDB_HOST_THREAD(m_event_handler_thread); 328544d93782SGreg Clayton } 328644d93782SGreg Clayton 328744d93782SGreg Clayton void 328844d93782SGreg Clayton Debugger::StopEventHandlerThread() 328944d93782SGreg Clayton { 329044d93782SGreg Clayton if (IS_VALID_LLDB_HOST_THREAD(m_event_handler_thread)) 329144d93782SGreg Clayton { 329244d93782SGreg Clayton GetCommandInterpreter().BroadcastEvent(CommandInterpreter::eBroadcastBitQuitCommandReceived); 329344d93782SGreg Clayton Host::ThreadJoin(m_event_handler_thread, NULL, NULL); 329444d93782SGreg Clayton m_event_handler_thread = LLDB_INVALID_HOST_THREAD; 329544d93782SGreg Clayton } 329644d93782SGreg Clayton } 329744d93782SGreg Clayton 329844d93782SGreg Clayton 329944d93782SGreg Clayton lldb::thread_result_t 330044d93782SGreg Clayton Debugger::IOHandlerThread (lldb::thread_arg_t arg) 330144d93782SGreg Clayton { 330244d93782SGreg Clayton Debugger *debugger = (Debugger *)arg; 330344d93782SGreg Clayton debugger->ExecuteIOHanders(); 330444d93782SGreg Clayton debugger->StopEventHandlerThread(); 330544d93782SGreg Clayton return NULL; 330644d93782SGreg Clayton } 330744d93782SGreg Clayton 330844d93782SGreg Clayton bool 330944d93782SGreg Clayton Debugger::StartIOHandlerThread() 331044d93782SGreg Clayton { 331144d93782SGreg Clayton if (!IS_VALID_LLDB_HOST_THREAD(m_io_handler_thread)) 331244d93782SGreg Clayton m_io_handler_thread = Host::ThreadCreate("lldb.debugger.io-handler", IOHandlerThread, this, NULL); 331344d93782SGreg Clayton return IS_VALID_LLDB_HOST_THREAD(m_io_handler_thread); 331444d93782SGreg Clayton } 331544d93782SGreg Clayton 331644d93782SGreg Clayton void 331744d93782SGreg Clayton Debugger::StopIOHandlerThread() 331844d93782SGreg Clayton { 331944d93782SGreg Clayton if (IS_VALID_LLDB_HOST_THREAD(m_io_handler_thread)) 332044d93782SGreg Clayton { 332144d93782SGreg Clayton if (m_input_file_sp) 332244d93782SGreg Clayton m_input_file_sp->GetFile().Close(); 332344d93782SGreg Clayton Host::ThreadJoin(m_io_handler_thread, NULL, NULL); 332444d93782SGreg Clayton m_io_handler_thread = LLDB_INVALID_HOST_THREAD; 332544d93782SGreg Clayton } 332644d93782SGreg Clayton } 332744d93782SGreg Clayton 332844d93782SGreg Clayton 3329