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 1221dfcd9dSEnrico Granata #include "lldb/API/SBDebugger.h" 1321dfcd9dSEnrico Granata 144a33d318SGreg Clayton #include "lldb/Core/Debugger.h" 154a33d318SGreg Clayton 164a33d318SGreg Clayton #include <map> 174a33d318SGreg Clayton 184becb37eSEnrico Granata #include "clang/AST/DeclCXX.h" 194becb37eSEnrico Granata #include "clang/AST/Type.h" 204becb37eSEnrico Granata 2130fdc8d8SChris Lattner #include "lldb/lldb-private.h" 2230fdc8d8SChris Lattner #include "lldb/Core/ConnectionFileDescriptor.h" 2330fdc8d8SChris Lattner #include "lldb/Core/InputReader.h" 241f746071SGreg Clayton #include "lldb/Core/Module.h" 25e8cd0c98SGreg Clayton #include "lldb/Core/PluginManager.h" 267349bd90SGreg Clayton #include "lldb/Core/RegisterValue.h" 2730fdc8d8SChris Lattner #include "lldb/Core/State.h" 285b52f0c7SJim Ingham #include "lldb/Core/StreamAsynchronousIO.h" 29228063cdSJim Ingham #include "lldb/Core/StreamCallback.h" 301b654882SGreg Clayton #include "lldb/Core/StreamString.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" 3621dfcd9dSEnrico Granata #include "lldb/Host/DynamicLibrary.h" 37a3406614SGreg Clayton #include "lldb/Host/Terminal.h" 386611103cSGreg Clayton #include "lldb/Interpreter/CommandInterpreter.h" 3967cc0636SGreg Clayton #include "lldb/Interpreter/OptionValueSInt64.h" 4067cc0636SGreg Clayton #include "lldb/Interpreter/OptionValueString.h" 411f746071SGreg Clayton #include "lldb/Symbol/ClangASTContext.h" 421f746071SGreg Clayton #include "lldb/Symbol/CompileUnit.h" 431f746071SGreg Clayton #include "lldb/Symbol/Function.h" 441f746071SGreg Clayton #include "lldb/Symbol/Symbol.h" 456d3dbf51SGreg Clayton #include "lldb/Symbol/VariableList.h" 4630fdc8d8SChris Lattner #include "lldb/Target/TargetList.h" 4730fdc8d8SChris Lattner #include "lldb/Target/Process.h" 481b654882SGreg Clayton #include "lldb/Target/RegisterContext.h" 491b654882SGreg Clayton #include "lldb/Target/StopInfo.h" 5084a53dfbSEnrico Granata #include "lldb/Target/Target.h" 5130fdc8d8SChris Lattner #include "lldb/Target/Thread.h" 525a31471eSGreg Clayton #include "lldb/Utility/AnsiTerminal.h" 5330fdc8d8SChris Lattner 5430fdc8d8SChris Lattner using namespace lldb; 5530fdc8d8SChris Lattner using namespace lldb_private; 5630fdc8d8SChris Lattner 5730fdc8d8SChris Lattner 581b654882SGreg Clayton static uint32_t g_shared_debugger_refcount = 0; 59ebc1bb27SCaroline Tice static lldb::user_id_t g_unique_id = 1; 60ebc1bb27SCaroline Tice 611b654882SGreg Clayton #pragma mark Static Functions 621b654882SGreg Clayton 631b654882SGreg Clayton static Mutex & 641b654882SGreg Clayton GetDebuggerListMutex () 651b654882SGreg Clayton { 661b654882SGreg Clayton static Mutex g_mutex(Mutex::eMutexTypeRecursive); 671b654882SGreg Clayton return g_mutex; 681b654882SGreg Clayton } 691b654882SGreg Clayton 701b654882SGreg Clayton typedef std::vector<DebuggerSP> DebuggerList; 711b654882SGreg Clayton 721b654882SGreg Clayton static DebuggerList & 731b654882SGreg Clayton GetDebuggerList() 741b654882SGreg Clayton { 751b654882SGreg Clayton // hide the static debugger list inside a singleton accessor to avoid 761b654882SGreg Clayton // global init contructors 771b654882SGreg Clayton static DebuggerList g_list; 781b654882SGreg Clayton return g_list; 791b654882SGreg Clayton } 80e372b98dSGreg Clayton 81e372b98dSGreg Clayton OptionEnumValueElement 8267cc0636SGreg Clayton g_show_disassembly_enum_values[] = 83e372b98dSGreg Clayton { 8467cc0636SGreg Clayton { Debugger::eStopDisassemblyTypeNever, "never", "Never show disassembly when displaying a stop context."}, 8567cc0636SGreg Clayton { Debugger::eStopDisassemblyTypeNoSource, "no-source", "Show disassembly when there is no source information, or the source file is missing when displaying a stop context."}, 8667cc0636SGreg Clayton { Debugger::eStopDisassemblyTypeAlways, "always", "Always show disassembly when displaying a stop context."}, 87e372b98dSGreg Clayton { 0, NULL, NULL } 88e372b98dSGreg Clayton }; 89e372b98dSGreg Clayton 9067cc0636SGreg Clayton OptionEnumValueElement 9167cc0636SGreg Clayton g_language_enumerators[] = 9267cc0636SGreg Clayton { 9367cc0636SGreg Clayton { eScriptLanguageNone, "none", "Disable scripting languages."}, 9467cc0636SGreg Clayton { eScriptLanguagePython, "python", "Select python as the default scripting language."}, 9567cc0636SGreg Clayton { eScriptLanguageDefault, "default", "Select the lldb default as the default scripting language."}, 96a12993c9SGreg Clayton { 0, NULL, NULL } 9767cc0636SGreg Clayton }; 98e372b98dSGreg Clayton 9967cc0636SGreg Clayton #define MODULE_WITH_FUNC "{ ${module.file.basename}{`${function.name-with-args}${function.pc-offset}}}" 10067cc0636SGreg Clayton #define FILE_AND_LINE "{ at ${line.file.basename}:${line.number}}" 10167cc0636SGreg Clayton 1020769b2b1SMichael Sartain #define DEFAULT_THREAD_FORMAT "thread #${thread.index}: tid = ${thread.id%tid}"\ 10367cc0636SGreg Clayton "{, ${frame.pc}}"\ 10467cc0636SGreg Clayton MODULE_WITH_FUNC\ 10567cc0636SGreg Clayton FILE_AND_LINE\ 1060769b2b1SMichael Sartain "{, name = '${thread.name}'}"\ 1070769b2b1SMichael Sartain "{, queue = '${thread.queue}'}"\ 10867cc0636SGreg Clayton "{, stop reason = ${thread.stop-reason}}"\ 10967cc0636SGreg Clayton "{\\nReturn value: ${thread.return-value}}"\ 11067cc0636SGreg Clayton "\\n" 11167cc0636SGreg Clayton 11267cc0636SGreg Clayton #define DEFAULT_FRAME_FORMAT "frame #${frame.index}: ${frame.pc}"\ 11367cc0636SGreg Clayton MODULE_WITH_FUNC\ 11467cc0636SGreg Clayton FILE_AND_LINE\ 11567cc0636SGreg Clayton "\\n" 11667cc0636SGreg Clayton 11767cc0636SGreg Clayton 11867cc0636SGreg Clayton 119754a9369SGreg Clayton static PropertyDefinition 120754a9369SGreg Clayton g_properties[] = 12167cc0636SGreg Clayton { 12267cc0636SGreg Clayton { "auto-confirm", OptionValue::eTypeBoolean, true, false, NULL, NULL, "If true all confirmation prompts will receive their default reply." }, 12367cc0636SGreg 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." }, 12467cc0636SGreg Clayton { "notify-void", OptionValue::eTypeBoolean, true, false, NULL, NULL, "Notify the user explicitly if an expression returns void (default: false)." }, 1254c05410fSGreg Clayton { "prompt", OptionValue::eTypeString , true, OptionValueString::eOptionEncodeCharacterEscapeSequences, "(lldb) ", NULL, "The debugger command line prompt displayed for the user." }, 12667cc0636SGreg Clayton { "script-lang", OptionValue::eTypeEnum , true, eScriptLanguagePython, NULL, g_language_enumerators, "The script language to be used for evaluating user-written scripts." }, 12767cc0636SGreg Clayton { "stop-disassembly-count", OptionValue::eTypeSInt64 , true, 4 , NULL, NULL, "The number of disassembly lines to show when displaying a stopped context." }, 12867cc0636SGreg 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." }, 12967cc0636SGreg 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." }, 13067cc0636SGreg 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." }, 13167cc0636SGreg Clayton { "term-width", OptionValue::eTypeSInt64 , true, 80 , NULL, NULL, "The maximum number of columns to use for displaying text." }, 13267cc0636SGreg Clayton { "thread-format", OptionValue::eTypeString , true, 0 , DEFAULT_THREAD_FORMAT, NULL, "The default thread format string to use when displaying thread information." }, 13367cc0636SGreg Clayton { "use-external-editor", OptionValue::eTypeBoolean, true, false, NULL, NULL, "Whether to use an external editor or not." }, 134c3ce7f27SMichael Sartain { "use-color", OptionValue::eTypeBoolean, true, true , NULL, NULL, "Whether to use Ansi color codes or not." }, 135e8cd0c98SGreg Clayton 13667cc0636SGreg Clayton { NULL, OptionValue::eTypeInvalid, true, 0 , NULL, NULL, NULL } 13767cc0636SGreg Clayton }; 13867cc0636SGreg Clayton 13967cc0636SGreg Clayton enum 14067cc0636SGreg Clayton { 14167cc0636SGreg Clayton ePropertyAutoConfirm = 0, 14267cc0636SGreg Clayton ePropertyFrameFormat, 14367cc0636SGreg Clayton ePropertyNotiftVoid, 14467cc0636SGreg Clayton ePropertyPrompt, 14567cc0636SGreg Clayton ePropertyScriptLanguage, 14667cc0636SGreg Clayton ePropertyStopDisassemblyCount, 14767cc0636SGreg Clayton ePropertyStopDisassemblyDisplay, 14867cc0636SGreg Clayton ePropertyStopLineCountAfter, 14967cc0636SGreg Clayton ePropertyStopLineCountBefore, 15067cc0636SGreg Clayton ePropertyTerminalWidth, 15167cc0636SGreg Clayton ePropertyThreadFormat, 152c3ce7f27SMichael Sartain ePropertyUseExternalEditor, 153c3ce7f27SMichael Sartain ePropertyUseColor, 15467cc0636SGreg Clayton }; 15567cc0636SGreg Clayton 15667cc0636SGreg Clayton // 15767cc0636SGreg Clayton //const char * 15867cc0636SGreg Clayton //Debugger::GetFrameFormat() const 15967cc0636SGreg Clayton //{ 16067cc0636SGreg Clayton // return m_properties_sp->GetFrameFormat(); 16167cc0636SGreg Clayton //} 16267cc0636SGreg Clayton //const char * 16367cc0636SGreg Clayton //Debugger::GetThreadFormat() const 16467cc0636SGreg Clayton //{ 16567cc0636SGreg Clayton // return m_properties_sp->GetThreadFormat(); 16667cc0636SGreg Clayton //} 16767cc0636SGreg Clayton // 1684c05410fSGreg Clayton 1694c05410fSGreg Clayton 1704c05410fSGreg Clayton Error 1714c05410fSGreg Clayton Debugger::SetPropertyValue (const ExecutionContext *exe_ctx, 1724c05410fSGreg Clayton VarSetOperationType op, 1734c05410fSGreg Clayton const char *property_path, 1744c05410fSGreg Clayton const char *value) 1754c05410fSGreg Clayton { 17684a53dfbSEnrico Granata bool is_load_script = strcmp(property_path,"target.load-script-from-symbol-file") == 0; 17784a53dfbSEnrico Granata TargetSP target_sp; 178397ddd5fSEnrico Granata LoadScriptFromSymFile load_script_old_value; 17984a53dfbSEnrico Granata if (is_load_script && exe_ctx->GetTargetSP()) 18084a53dfbSEnrico Granata { 18184a53dfbSEnrico Granata target_sp = exe_ctx->GetTargetSP(); 18284a53dfbSEnrico Granata load_script_old_value = target_sp->TargetProperties::GetLoadScriptFromSymbolFile(); 18384a53dfbSEnrico Granata } 1844c05410fSGreg Clayton Error error (Properties::SetPropertyValue (exe_ctx, op, property_path, value)); 1854c05410fSGreg Clayton if (error.Success()) 1864c05410fSGreg Clayton { 18784a53dfbSEnrico Granata // FIXME it would be nice to have "on-change" callbacks for properties 1884c05410fSGreg Clayton if (strcmp(property_path, g_properties[ePropertyPrompt].name) == 0) 1894c05410fSGreg Clayton { 1904c05410fSGreg Clayton const char *new_prompt = GetPrompt(); 191c3ce7f27SMichael Sartain std::string str = lldb_utility::ansi::FormatAnsiTerminalCodes (new_prompt, GetUseColor()); 192c3ce7f27SMichael Sartain if (str.length()) 193c3ce7f27SMichael Sartain new_prompt = str.c_str(); 1944c05410fSGreg Clayton EventSP prompt_change_event_sp (new Event(CommandInterpreter::eBroadcastBitResetPrompt, new EventDataBytes (new_prompt))); 1954c05410fSGreg Clayton GetCommandInterpreter().BroadcastEvent (prompt_change_event_sp); 1964c05410fSGreg Clayton } 197c3ce7f27SMichael Sartain else if (strcmp(property_path, g_properties[ePropertyUseColor].name) == 0) 198c3ce7f27SMichael Sartain { 199c3ce7f27SMichael Sartain // use-color changed. Ping the prompt so it can reset the ansi terminal codes. 200c3ce7f27SMichael Sartain SetPrompt (GetPrompt()); 201c3ce7f27SMichael Sartain } 202397ddd5fSEnrico Granata else if (is_load_script && target_sp && load_script_old_value == eLoadScriptFromSymFileWarn) 20384a53dfbSEnrico Granata { 204397ddd5fSEnrico Granata if (target_sp->TargetProperties::GetLoadScriptFromSymbolFile() == eLoadScriptFromSymFileTrue) 20584a53dfbSEnrico Granata { 20684a53dfbSEnrico Granata std::list<Error> errors; 2079730339bSEnrico Granata StreamString feedback_stream; 2089730339bSEnrico Granata if (!target_sp->LoadScriptingResources(errors,&feedback_stream)) 20984a53dfbSEnrico Granata { 21084a53dfbSEnrico Granata for (auto error : errors) 21184a53dfbSEnrico Granata { 2129730339bSEnrico Granata GetErrorStream().Printf("%s\n",error.AsCString()); 21384a53dfbSEnrico Granata } 2149730339bSEnrico Granata if (feedback_stream.GetSize()) 2159730339bSEnrico Granata GetErrorStream().Printf("%s",feedback_stream.GetData()); 21684a53dfbSEnrico Granata } 21784a53dfbSEnrico Granata } 21884a53dfbSEnrico Granata } 2194c05410fSGreg Clayton } 2204c05410fSGreg Clayton return error; 2214c05410fSGreg Clayton } 2224c05410fSGreg Clayton 22367cc0636SGreg Clayton bool 22467cc0636SGreg Clayton Debugger::GetAutoConfirm () const 22567cc0636SGreg Clayton { 22667cc0636SGreg Clayton const uint32_t idx = ePropertyAutoConfirm; 227754a9369SGreg Clayton return m_collection_sp->GetPropertyAtIndexAsBoolean (NULL, idx, g_properties[idx].default_uint_value != 0); 22867cc0636SGreg Clayton } 22967cc0636SGreg Clayton 23067cc0636SGreg Clayton const char * 23167cc0636SGreg Clayton Debugger::GetFrameFormat() const 23267cc0636SGreg Clayton { 23367cc0636SGreg Clayton const uint32_t idx = ePropertyFrameFormat; 234754a9369SGreg Clayton return m_collection_sp->GetPropertyAtIndexAsString (NULL, idx, g_properties[idx].default_cstr_value); 23567cc0636SGreg Clayton } 23667cc0636SGreg Clayton 23767cc0636SGreg Clayton bool 23867cc0636SGreg Clayton Debugger::GetNotifyVoid () const 23967cc0636SGreg Clayton { 24067cc0636SGreg Clayton const uint32_t idx = ePropertyNotiftVoid; 241754a9369SGreg Clayton return m_collection_sp->GetPropertyAtIndexAsBoolean (NULL, idx, g_properties[idx].default_uint_value != 0); 24267cc0636SGreg Clayton } 24367cc0636SGreg Clayton 24467cc0636SGreg Clayton const char * 24567cc0636SGreg Clayton Debugger::GetPrompt() const 24667cc0636SGreg Clayton { 24767cc0636SGreg Clayton const uint32_t idx = ePropertyPrompt; 248754a9369SGreg Clayton return m_collection_sp->GetPropertyAtIndexAsString (NULL, idx, g_properties[idx].default_cstr_value); 24967cc0636SGreg Clayton } 25067cc0636SGreg Clayton 25167cc0636SGreg Clayton void 25267cc0636SGreg Clayton Debugger::SetPrompt(const char *p) 25367cc0636SGreg Clayton { 25467cc0636SGreg Clayton const uint32_t idx = ePropertyPrompt; 25567cc0636SGreg Clayton m_collection_sp->SetPropertyAtIndexAsString (NULL, idx, p); 25667cc0636SGreg Clayton const char *new_prompt = GetPrompt(); 257c3ce7f27SMichael Sartain std::string str = lldb_utility::ansi::FormatAnsiTerminalCodes (new_prompt, GetUseColor()); 258c3ce7f27SMichael Sartain if (str.length()) 259c3ce7f27SMichael Sartain new_prompt = str.c_str(); 26067cc0636SGreg Clayton EventSP prompt_change_event_sp (new Event(CommandInterpreter::eBroadcastBitResetPrompt, new EventDataBytes (new_prompt)));; 26167cc0636SGreg Clayton GetCommandInterpreter().BroadcastEvent (prompt_change_event_sp); 26267cc0636SGreg Clayton } 26367cc0636SGreg Clayton 26467cc0636SGreg Clayton const char * 26567cc0636SGreg Clayton Debugger::GetThreadFormat() const 26667cc0636SGreg Clayton { 26767cc0636SGreg Clayton const uint32_t idx = ePropertyThreadFormat; 268754a9369SGreg Clayton return m_collection_sp->GetPropertyAtIndexAsString (NULL, idx, g_properties[idx].default_cstr_value); 26967cc0636SGreg Clayton } 27067cc0636SGreg Clayton 27167cc0636SGreg Clayton lldb::ScriptLanguage 27267cc0636SGreg Clayton Debugger::GetScriptLanguage() const 27367cc0636SGreg Clayton { 27467cc0636SGreg Clayton const uint32_t idx = ePropertyScriptLanguage; 275754a9369SGreg Clayton return (lldb::ScriptLanguage)m_collection_sp->GetPropertyAtIndexAsEnumeration (NULL, idx, g_properties[idx].default_uint_value); 27667cc0636SGreg Clayton } 27767cc0636SGreg Clayton 27867cc0636SGreg Clayton bool 27967cc0636SGreg Clayton Debugger::SetScriptLanguage (lldb::ScriptLanguage script_lang) 28067cc0636SGreg Clayton { 28167cc0636SGreg Clayton const uint32_t idx = ePropertyScriptLanguage; 28267cc0636SGreg Clayton return m_collection_sp->SetPropertyAtIndexAsEnumeration (NULL, idx, script_lang); 28367cc0636SGreg Clayton } 28467cc0636SGreg Clayton 28567cc0636SGreg Clayton uint32_t 28667cc0636SGreg Clayton Debugger::GetTerminalWidth () const 28767cc0636SGreg Clayton { 28867cc0636SGreg Clayton const uint32_t idx = ePropertyTerminalWidth; 289754a9369SGreg Clayton return m_collection_sp->GetPropertyAtIndexAsSInt64 (NULL, idx, g_properties[idx].default_uint_value); 29067cc0636SGreg Clayton } 29167cc0636SGreg Clayton 29267cc0636SGreg Clayton bool 29367cc0636SGreg Clayton Debugger::SetTerminalWidth (uint32_t term_width) 29467cc0636SGreg Clayton { 29567cc0636SGreg Clayton const uint32_t idx = ePropertyTerminalWidth; 29667cc0636SGreg Clayton return m_collection_sp->SetPropertyAtIndexAsSInt64 (NULL, idx, term_width); 29767cc0636SGreg Clayton } 29867cc0636SGreg Clayton 29967cc0636SGreg Clayton bool 30067cc0636SGreg Clayton Debugger::GetUseExternalEditor () const 30167cc0636SGreg Clayton { 30267cc0636SGreg Clayton const uint32_t idx = ePropertyUseExternalEditor; 303754a9369SGreg Clayton return m_collection_sp->GetPropertyAtIndexAsBoolean (NULL, idx, g_properties[idx].default_uint_value != 0); 30467cc0636SGreg Clayton } 30567cc0636SGreg Clayton 30667cc0636SGreg Clayton bool 30767cc0636SGreg Clayton Debugger::SetUseExternalEditor (bool b) 30867cc0636SGreg Clayton { 30967cc0636SGreg Clayton const uint32_t idx = ePropertyUseExternalEditor; 31067cc0636SGreg Clayton return m_collection_sp->SetPropertyAtIndexAsBoolean (NULL, idx, b); 31167cc0636SGreg Clayton } 31267cc0636SGreg Clayton 313c3ce7f27SMichael Sartain bool 314c3ce7f27SMichael Sartain Debugger::GetUseColor () const 315c3ce7f27SMichael Sartain { 316c3ce7f27SMichael Sartain const uint32_t idx = ePropertyUseColor; 317c3ce7f27SMichael Sartain return m_collection_sp->GetPropertyAtIndexAsBoolean (NULL, idx, g_properties[idx].default_uint_value != 0); 318c3ce7f27SMichael Sartain } 319c3ce7f27SMichael Sartain 320c3ce7f27SMichael Sartain bool 321c3ce7f27SMichael Sartain Debugger::SetUseColor (bool b) 322c3ce7f27SMichael Sartain { 323c3ce7f27SMichael Sartain const uint32_t idx = ePropertyUseColor; 324c3ce7f27SMichael Sartain bool ret = m_collection_sp->SetPropertyAtIndexAsBoolean (NULL, idx, b); 325c3ce7f27SMichael Sartain SetPrompt (GetPrompt()); 326c3ce7f27SMichael Sartain return ret; 327c3ce7f27SMichael Sartain } 328c3ce7f27SMichael Sartain 32967cc0636SGreg Clayton uint32_t 33067cc0636SGreg Clayton Debugger::GetStopSourceLineCount (bool before) const 33167cc0636SGreg Clayton { 33267cc0636SGreg Clayton const uint32_t idx = before ? ePropertyStopLineCountBefore : ePropertyStopLineCountAfter; 333754a9369SGreg Clayton return m_collection_sp->GetPropertyAtIndexAsSInt64 (NULL, idx, g_properties[idx].default_uint_value); 33467cc0636SGreg Clayton } 33567cc0636SGreg Clayton 33667cc0636SGreg Clayton Debugger::StopDisassemblyType 33767cc0636SGreg Clayton Debugger::GetStopDisassemblyDisplay () const 33867cc0636SGreg Clayton { 33967cc0636SGreg Clayton const uint32_t idx = ePropertyStopDisassemblyDisplay; 340754a9369SGreg Clayton return (Debugger::StopDisassemblyType)m_collection_sp->GetPropertyAtIndexAsEnumeration (NULL, idx, g_properties[idx].default_uint_value); 34167cc0636SGreg Clayton } 34267cc0636SGreg Clayton 34367cc0636SGreg Clayton uint32_t 34467cc0636SGreg Clayton Debugger::GetDisassemblyLineCount () const 34567cc0636SGreg Clayton { 34667cc0636SGreg Clayton const uint32_t idx = ePropertyStopDisassemblyCount; 347754a9369SGreg Clayton return m_collection_sp->GetPropertyAtIndexAsSInt64 (NULL, idx, g_properties[idx].default_uint_value); 34867cc0636SGreg Clayton } 349e372b98dSGreg Clayton 3501b654882SGreg Clayton #pragma mark Debugger 3511b654882SGreg Clayton 35267cc0636SGreg Clayton //const DebuggerPropertiesSP & 35367cc0636SGreg Clayton //Debugger::GetSettings() const 35467cc0636SGreg Clayton //{ 35567cc0636SGreg Clayton // return m_properties_sp; 35667cc0636SGreg Clayton //} 35767cc0636SGreg Clayton // 35899d0faf2SGreg Clayton 3592f88aadfSCaroline Tice int 3602f88aadfSCaroline Tice Debugger::TestDebuggerRefCount () 3612f88aadfSCaroline Tice { 3622f88aadfSCaroline Tice return g_shared_debugger_refcount; 3632f88aadfSCaroline Tice } 3642f88aadfSCaroline Tice 36530fdc8d8SChris Lattner void 36630fdc8d8SChris Lattner Debugger::Initialize () 36730fdc8d8SChris Lattner { 368c15f55e2SGreg Clayton if (g_shared_debugger_refcount++ == 0) 369dbe54508SGreg Clayton lldb_private::Initialize(); 37099d0faf2SGreg Clayton } 37130fdc8d8SChris Lattner 37230fdc8d8SChris Lattner void 37330fdc8d8SChris Lattner Debugger::Terminate () 37430fdc8d8SChris Lattner { 3756611103cSGreg Clayton if (g_shared_debugger_refcount > 0) 3766611103cSGreg Clayton { 37730fdc8d8SChris Lattner g_shared_debugger_refcount--; 37830fdc8d8SChris Lattner if (g_shared_debugger_refcount == 0) 37930fdc8d8SChris Lattner { 380dbe54508SGreg Clayton lldb_private::WillTerminate(); 381dbe54508SGreg Clayton lldb_private::Terminate(); 3826760a517SCaroline Tice 38399d0faf2SGreg Clayton // Clear our master list of debugger objects 38499d0faf2SGreg Clayton Mutex::Locker locker (GetDebuggerListMutex ()); 38599d0faf2SGreg Clayton GetDebuggerList().clear(); 38630fdc8d8SChris Lattner } 3876760a517SCaroline Tice } 3886760a517SCaroline Tice } 38930fdc8d8SChris Lattner 39020bd37f7SCaroline Tice void 39120bd37f7SCaroline Tice Debugger::SettingsInitialize () 39220bd37f7SCaroline Tice { 3936920b52bSGreg Clayton Target::SettingsInitialize (); 39420bd37f7SCaroline Tice } 39520bd37f7SCaroline Tice 39620bd37f7SCaroline Tice void 39720bd37f7SCaroline Tice Debugger::SettingsTerminate () 39820bd37f7SCaroline Tice { 3996920b52bSGreg Clayton Target::SettingsTerminate (); 40020bd37f7SCaroline Tice } 40120bd37f7SCaroline Tice 40221dfcd9dSEnrico Granata bool 403e743c782SEnrico Granata Debugger::LoadPlugin (const FileSpec& spec, Error& error) 40421dfcd9dSEnrico Granata { 40521dfcd9dSEnrico Granata lldb::DynamicLibrarySP dynlib_sp(new lldb_private::DynamicLibrary(spec)); 406e743c782SEnrico Granata if (!dynlib_sp || dynlib_sp->IsValid() == false) 407e743c782SEnrico Granata { 408e743c782SEnrico Granata if (spec.Exists()) 409e743c782SEnrico Granata error.SetErrorString("this file does not represent a loadable dylib"); 410e743c782SEnrico Granata else 411e743c782SEnrico Granata error.SetErrorString("no such file"); 412e743c782SEnrico Granata return false; 413e743c782SEnrico Granata } 41421dfcd9dSEnrico Granata lldb::DebuggerSP debugger_sp(shared_from_this()); 41521dfcd9dSEnrico Granata lldb::SBDebugger debugger_sb(debugger_sp); 4163cf443ddSMichael Sartain // This calls the bool lldb::PluginInitialize(lldb::SBDebugger debugger) function. 41721dfcd9dSEnrico Granata // TODO: mangle this differently for your system - on OSX, the first underscore needs to be removed and the second one stays 41821dfcd9dSEnrico Granata LLDBCommandPluginInit init_func = dynlib_sp->GetSymbol<LLDBCommandPluginInit>("_ZN4lldb16PluginInitializeENS_10SBDebuggerE"); 41921dfcd9dSEnrico Granata if (!init_func) 420e743c782SEnrico Granata { 421e743c782SEnrico Granata error.SetErrorString("cannot find the initialization function lldb::PluginInitialize(lldb::SBDebugger)"); 42221dfcd9dSEnrico Granata return false; 423e743c782SEnrico Granata } 42421dfcd9dSEnrico Granata if (init_func(debugger_sb)) 42521dfcd9dSEnrico Granata { 42621dfcd9dSEnrico Granata m_loaded_plugins.push_back(dynlib_sp); 42721dfcd9dSEnrico Granata return true; 42821dfcd9dSEnrico Granata } 429e743c782SEnrico Granata error.SetErrorString("dylib refused to be loaded"); 43021dfcd9dSEnrico Granata return false; 43121dfcd9dSEnrico Granata } 43221dfcd9dSEnrico Granata 43321dfcd9dSEnrico Granata static FileSpec::EnumerateDirectoryResult 43421dfcd9dSEnrico Granata LoadPluginCallback 43521dfcd9dSEnrico Granata ( 43621dfcd9dSEnrico Granata void *baton, 43721dfcd9dSEnrico Granata FileSpec::FileType file_type, 43821dfcd9dSEnrico Granata const FileSpec &file_spec 43921dfcd9dSEnrico Granata ) 44021dfcd9dSEnrico Granata { 44121dfcd9dSEnrico Granata Error error; 44221dfcd9dSEnrico Granata 44321dfcd9dSEnrico Granata static ConstString g_dylibext("dylib"); 4443cf443ddSMichael Sartain static ConstString g_solibext("so"); 44521dfcd9dSEnrico Granata 44621dfcd9dSEnrico Granata if (!baton) 44721dfcd9dSEnrico Granata return FileSpec::eEnumerateDirectoryResultQuit; 44821dfcd9dSEnrico Granata 44921dfcd9dSEnrico Granata Debugger *debugger = (Debugger*)baton; 45021dfcd9dSEnrico Granata 45121dfcd9dSEnrico Granata // If we have a regular file, a symbolic link or unknown file type, try 45221dfcd9dSEnrico Granata // and process the file. We must handle unknown as sometimes the directory 45321dfcd9dSEnrico Granata // enumeration might be enumerating a file system that doesn't have correct 45421dfcd9dSEnrico Granata // file type information. 45521dfcd9dSEnrico Granata if (file_type == FileSpec::eFileTypeRegular || 45621dfcd9dSEnrico Granata file_type == FileSpec::eFileTypeSymbolicLink || 45721dfcd9dSEnrico Granata file_type == FileSpec::eFileTypeUnknown ) 45821dfcd9dSEnrico Granata { 45921dfcd9dSEnrico Granata FileSpec plugin_file_spec (file_spec); 46021dfcd9dSEnrico Granata plugin_file_spec.ResolvePath (); 46121dfcd9dSEnrico Granata 4623cf443ddSMichael Sartain if (plugin_file_spec.GetFileNameExtension() != g_dylibext && 4633cf443ddSMichael Sartain plugin_file_spec.GetFileNameExtension() != g_solibext) 4643cf443ddSMichael Sartain { 46521dfcd9dSEnrico Granata return FileSpec::eEnumerateDirectoryResultNext; 4663cf443ddSMichael Sartain } 46721dfcd9dSEnrico Granata 468e743c782SEnrico Granata Error plugin_load_error; 469e743c782SEnrico Granata debugger->LoadPlugin (plugin_file_spec, plugin_load_error); 47021dfcd9dSEnrico Granata 47121dfcd9dSEnrico Granata return FileSpec::eEnumerateDirectoryResultNext; 47221dfcd9dSEnrico Granata } 47321dfcd9dSEnrico Granata 47421dfcd9dSEnrico Granata else if (file_type == FileSpec::eFileTypeUnknown || 47521dfcd9dSEnrico Granata file_type == FileSpec::eFileTypeDirectory || 47621dfcd9dSEnrico Granata file_type == FileSpec::eFileTypeSymbolicLink ) 47721dfcd9dSEnrico Granata { 47821dfcd9dSEnrico Granata // Try and recurse into anything that a directory or symbolic link. 47921dfcd9dSEnrico Granata // We must also do this for unknown as sometimes the directory enumeration 48021dfcd9dSEnrico Granata // might be enurating a file system that doesn't have correct file type 48121dfcd9dSEnrico Granata // information. 48221dfcd9dSEnrico Granata return FileSpec::eEnumerateDirectoryResultEnter; 48321dfcd9dSEnrico Granata } 48421dfcd9dSEnrico Granata 48521dfcd9dSEnrico Granata return FileSpec::eEnumerateDirectoryResultNext; 48621dfcd9dSEnrico Granata } 48721dfcd9dSEnrico Granata 48821dfcd9dSEnrico Granata void 48921dfcd9dSEnrico Granata Debugger::InstanceInitialize () 49021dfcd9dSEnrico Granata { 49121dfcd9dSEnrico Granata FileSpec dir_spec; 49221dfcd9dSEnrico Granata const bool find_directories = true; 49321dfcd9dSEnrico Granata const bool find_files = true; 49421dfcd9dSEnrico Granata const bool find_other = true; 49521dfcd9dSEnrico Granata char dir_path[PATH_MAX]; 49621dfcd9dSEnrico Granata if (Host::GetLLDBPath (ePathTypeLLDBSystemPlugins, dir_spec)) 49721dfcd9dSEnrico Granata { 49821dfcd9dSEnrico Granata if (dir_spec.Exists() && dir_spec.GetPath(dir_path, sizeof(dir_path))) 49921dfcd9dSEnrico Granata { 50021dfcd9dSEnrico Granata FileSpec::EnumerateDirectory (dir_path, 50121dfcd9dSEnrico Granata find_directories, 50221dfcd9dSEnrico Granata find_files, 50321dfcd9dSEnrico Granata find_other, 50421dfcd9dSEnrico Granata LoadPluginCallback, 50521dfcd9dSEnrico Granata this); 50621dfcd9dSEnrico Granata } 50721dfcd9dSEnrico Granata } 50821dfcd9dSEnrico Granata 50921dfcd9dSEnrico Granata if (Host::GetLLDBPath (ePathTypeLLDBUserPlugins, dir_spec)) 51021dfcd9dSEnrico Granata { 51121dfcd9dSEnrico Granata if (dir_spec.Exists() && dir_spec.GetPath(dir_path, sizeof(dir_path))) 51221dfcd9dSEnrico Granata { 51321dfcd9dSEnrico Granata FileSpec::EnumerateDirectory (dir_path, 51421dfcd9dSEnrico Granata find_directories, 51521dfcd9dSEnrico Granata find_files, 51621dfcd9dSEnrico Granata find_other, 51721dfcd9dSEnrico Granata LoadPluginCallback, 51821dfcd9dSEnrico Granata this); 51921dfcd9dSEnrico Granata } 52021dfcd9dSEnrico Granata } 521e8cd0c98SGreg Clayton 522e8cd0c98SGreg Clayton PluginManager::DebuggerInitialize (*this); 52321dfcd9dSEnrico Granata } 52421dfcd9dSEnrico Granata 5256611103cSGreg Clayton DebuggerSP 526228063cdSJim Ingham Debugger::CreateInstance (lldb::LogOutputCallback log_callback, void *baton) 5276611103cSGreg Clayton { 528228063cdSJim Ingham DebuggerSP debugger_sp (new Debugger(log_callback, baton)); 529c15f55e2SGreg Clayton if (g_shared_debugger_refcount > 0) 5306611103cSGreg Clayton { 5316611103cSGreg Clayton Mutex::Locker locker (GetDebuggerListMutex ()); 5326611103cSGreg Clayton GetDebuggerList().push_back(debugger_sp); 5336611103cSGreg Clayton } 53421dfcd9dSEnrico Granata debugger_sp->InstanceInitialize (); 5356611103cSGreg Clayton return debugger_sp; 5366611103cSGreg Clayton } 5376611103cSGreg Clayton 538e02657b1SCaroline Tice void 5394d122c40SGreg Clayton Debugger::Destroy (DebuggerSP &debugger_sp) 540e02657b1SCaroline Tice { 541e02657b1SCaroline Tice if (debugger_sp.get() == NULL) 542e02657b1SCaroline Tice return; 543e02657b1SCaroline Tice 5448314c525SJim Ingham debugger_sp->Clear(); 5458314c525SJim Ingham 546c15f55e2SGreg Clayton if (g_shared_debugger_refcount > 0) 547c15f55e2SGreg Clayton { 548e02657b1SCaroline Tice Mutex::Locker locker (GetDebuggerListMutex ()); 549e02657b1SCaroline Tice DebuggerList &debugger_list = GetDebuggerList (); 550e02657b1SCaroline Tice DebuggerList::iterator pos, end = debugger_list.end(); 551e02657b1SCaroline Tice for (pos = debugger_list.begin (); pos != end; ++pos) 552e02657b1SCaroline Tice { 553e02657b1SCaroline Tice if ((*pos).get() == debugger_sp.get()) 554e02657b1SCaroline Tice { 555e02657b1SCaroline Tice debugger_list.erase (pos); 556e02657b1SCaroline Tice return; 557e02657b1SCaroline Tice } 558e02657b1SCaroline Tice } 559e02657b1SCaroline Tice } 560c15f55e2SGreg Clayton } 561e02657b1SCaroline Tice 5624d122c40SGreg Clayton DebuggerSP 5633df9a8dfSCaroline Tice Debugger::FindDebuggerWithInstanceName (const ConstString &instance_name) 5643df9a8dfSCaroline Tice { 5654d122c40SGreg Clayton DebuggerSP debugger_sp; 5666920b52bSGreg Clayton if (g_shared_debugger_refcount > 0) 5676920b52bSGreg Clayton { 5686920b52bSGreg Clayton Mutex::Locker locker (GetDebuggerListMutex ()); 5696920b52bSGreg Clayton DebuggerList &debugger_list = GetDebuggerList(); 5706920b52bSGreg Clayton DebuggerList::iterator pos, end = debugger_list.end(); 5716920b52bSGreg Clayton 5726920b52bSGreg Clayton for (pos = debugger_list.begin(); pos != end; ++pos) 5736920b52bSGreg Clayton { 5746920b52bSGreg Clayton if ((*pos).get()->m_instance_name == instance_name) 5756920b52bSGreg Clayton { 5766920b52bSGreg Clayton debugger_sp = *pos; 5776920b52bSGreg Clayton break; 5786920b52bSGreg Clayton } 5796920b52bSGreg Clayton } 5806920b52bSGreg Clayton } 5813df9a8dfSCaroline Tice return debugger_sp; 5823df9a8dfSCaroline Tice } 5836611103cSGreg Clayton 5846611103cSGreg Clayton TargetSP 5856611103cSGreg Clayton Debugger::FindTargetWithProcessID (lldb::pid_t pid) 5866611103cSGreg Clayton { 5874d122c40SGreg Clayton TargetSP target_sp; 588c15f55e2SGreg Clayton if (g_shared_debugger_refcount > 0) 589c15f55e2SGreg Clayton { 5906611103cSGreg Clayton Mutex::Locker locker (GetDebuggerListMutex ()); 5916611103cSGreg Clayton DebuggerList &debugger_list = GetDebuggerList(); 5926611103cSGreg Clayton DebuggerList::iterator pos, end = debugger_list.end(); 5936611103cSGreg Clayton for (pos = debugger_list.begin(); pos != end; ++pos) 5946611103cSGreg Clayton { 5956611103cSGreg Clayton target_sp = (*pos)->GetTargetList().FindTargetWithProcessID (pid); 5966611103cSGreg Clayton if (target_sp) 5976611103cSGreg Clayton break; 5986611103cSGreg Clayton } 599c15f55e2SGreg Clayton } 6006611103cSGreg Clayton return target_sp; 6016611103cSGreg Clayton } 6026611103cSGreg Clayton 603e4e45924SGreg Clayton TargetSP 604e4e45924SGreg Clayton Debugger::FindTargetWithProcess (Process *process) 605e4e45924SGreg Clayton { 606e4e45924SGreg Clayton TargetSP target_sp; 607c15f55e2SGreg Clayton if (g_shared_debugger_refcount > 0) 608c15f55e2SGreg Clayton { 609e4e45924SGreg Clayton Mutex::Locker locker (GetDebuggerListMutex ()); 610e4e45924SGreg Clayton DebuggerList &debugger_list = GetDebuggerList(); 611e4e45924SGreg Clayton DebuggerList::iterator pos, end = debugger_list.end(); 612e4e45924SGreg Clayton for (pos = debugger_list.begin(); pos != end; ++pos) 613e4e45924SGreg Clayton { 614e4e45924SGreg Clayton target_sp = (*pos)->GetTargetList().FindTargetWithProcess (process); 615e4e45924SGreg Clayton if (target_sp) 616e4e45924SGreg Clayton break; 617e4e45924SGreg Clayton } 618c15f55e2SGreg Clayton } 619e4e45924SGreg Clayton return target_sp; 620e4e45924SGreg Clayton } 621e4e45924SGreg Clayton 622228063cdSJim Ingham Debugger::Debugger (lldb::LogOutputCallback log_callback, void *baton) : 623ebc1bb27SCaroline Tice UserID (g_unique_id++), 62467cc0636SGreg Clayton Properties(OptionValuePropertiesSP(new OptionValueProperties())), 625d46c87a1SGreg Clayton m_input_comm("debugger.input"), 62630fdc8d8SChris Lattner m_input_file (), 62730fdc8d8SChris Lattner m_output_file (), 62830fdc8d8SChris Lattner m_error_file (), 629c5917d9aSJim Ingham m_terminal_state (), 6304bddaeb5SJim Ingham m_target_list (*this), 631ded470d3SGreg Clayton m_platform_list (), 63230fdc8d8SChris Lattner m_listener ("lldb.Debugger"), 6339585fbfcSGreg Clayton m_source_manager_ap(), 634e37d605eSJim Ingham m_source_file_cache(), 6356611103cSGreg Clayton m_command_interpreter_ap (new CommandInterpreter (*this, eScriptLanguageDefault, false)), 636d5a0a01bSCaroline Tice m_input_reader_stack (), 63767cc0636SGreg Clayton m_input_reader_data (), 63867cc0636SGreg Clayton m_instance_name() 63930fdc8d8SChris Lattner { 64067cc0636SGreg Clayton char instance_cstr[256]; 64167cc0636SGreg Clayton snprintf(instance_cstr, sizeof(instance_cstr), "debugger_%d", (int)GetID()); 64267cc0636SGreg Clayton m_instance_name.SetCString(instance_cstr); 643228063cdSJim Ingham if (log_callback) 644228063cdSJim Ingham m_log_callback_stream_sp.reset (new StreamCallback (log_callback, baton)); 6456611103cSGreg Clayton m_command_interpreter_ap->Initialize (); 646ded470d3SGreg Clayton // Always add our default platform to the platform list 647ded470d3SGreg Clayton PlatformSP default_platform_sp (Platform::GetDefaultPlatform()); 648ded470d3SGreg Clayton assert (default_platform_sp.get()); 649ded470d3SGreg Clayton m_platform_list.Append (default_platform_sp, true); 65067cc0636SGreg Clayton 651754a9369SGreg Clayton m_collection_sp->Initialize (g_properties); 65267cc0636SGreg Clayton m_collection_sp->AppendProperty (ConstString("target"), 65367cc0636SGreg Clayton ConstString("Settings specify to debugging targets."), 65467cc0636SGreg Clayton true, 65567cc0636SGreg Clayton Target::GetGlobalProperties()->GetValueProperties()); 656754a9369SGreg Clayton if (m_command_interpreter_ap.get()) 657754a9369SGreg Clayton { 658754a9369SGreg Clayton m_collection_sp->AppendProperty (ConstString("interpreter"), 659754a9369SGreg Clayton ConstString("Settings specify to the debugger's command interpreter."), 660754a9369SGreg Clayton true, 661754a9369SGreg Clayton m_command_interpreter_ap->GetValueProperties()); 662754a9369SGreg Clayton } 66367cc0636SGreg Clayton OptionValueSInt64 *term_width = m_collection_sp->GetPropertyAtIndexAsOptionValueSInt64 (NULL, ePropertyTerminalWidth); 66467cc0636SGreg Clayton term_width->SetMinimumValue(10); 66567cc0636SGreg Clayton term_width->SetMaximumValue(1024); 666c3ce7f27SMichael Sartain 667c3ce7f27SMichael Sartain // Turn off use-color if this is a dumb terminal. 668c3ce7f27SMichael Sartain const char *term = getenv ("TERM"); 669c3ce7f27SMichael Sartain if (term && !strcmp (term, "dumb")) 670c3ce7f27SMichael Sartain SetUseColor (false); 67130fdc8d8SChris Lattner } 67230fdc8d8SChris Lattner 67330fdc8d8SChris Lattner Debugger::~Debugger () 67430fdc8d8SChris Lattner { 6758314c525SJim Ingham Clear(); 6768314c525SJim Ingham } 6778314c525SJim Ingham 6788314c525SJim Ingham void 6798314c525SJim Ingham Debugger::Clear() 6808314c525SJim Ingham { 6813d6086f6SCaroline Tice CleanUpInputReaders(); 6821ed54f50SGreg Clayton m_listener.Clear(); 6836611103cSGreg Clayton int num_targets = m_target_list.GetNumTargets(); 6846611103cSGreg Clayton for (int i = 0; i < num_targets; i++) 6856611103cSGreg Clayton { 686ccbc08e6SGreg Clayton TargetSP target_sp (m_target_list.GetTargetAtIndex (i)); 687ccbc08e6SGreg Clayton if (target_sp) 688ccbc08e6SGreg Clayton { 689ccbc08e6SGreg Clayton ProcessSP process_sp (target_sp->GetProcessSP()); 6906611103cSGreg Clayton if (process_sp) 6911fd07059SJim Ingham process_sp->Finalize(); 692ccbc08e6SGreg Clayton target_sp->Destroy(); 6936611103cSGreg Clayton } 69430fdc8d8SChris Lattner } 6954bddaeb5SJim Ingham BroadcasterManager::Clear (); 69630fdc8d8SChris Lattner 6970d69a3a4SGreg Clayton // Close the input file _before_ we close the input read communications class 6980d69a3a4SGreg Clayton // as it does NOT own the input file, our m_input_file does. 699c5917d9aSJim Ingham m_terminal_state.Clear(); 7000d69a3a4SGreg Clayton GetInputFile().Close (); 7010d69a3a4SGreg Clayton // Now that we have closed m_input_file, we can now tell our input communication 7020d69a3a4SGreg Clayton // class to close down. Its read thread should quickly exit after we close 7030d69a3a4SGreg Clayton // the input file handle above. 7040d69a3a4SGreg Clayton m_input_comm.Clear (); 7058314c525SJim Ingham } 70630fdc8d8SChris Lattner 70730fdc8d8SChris Lattner bool 708fc3f027dSGreg Clayton Debugger::GetCloseInputOnEOF () const 709fc3f027dSGreg Clayton { 710fc3f027dSGreg Clayton return m_input_comm.GetCloseOnEOF(); 711fc3f027dSGreg Clayton } 712fc3f027dSGreg Clayton 713fc3f027dSGreg Clayton void 714fc3f027dSGreg Clayton Debugger::SetCloseInputOnEOF (bool b) 715fc3f027dSGreg Clayton { 716fc3f027dSGreg Clayton m_input_comm.SetCloseOnEOF(b); 717fc3f027dSGreg Clayton } 718fc3f027dSGreg Clayton 719fc3f027dSGreg Clayton bool 72030fdc8d8SChris Lattner Debugger::GetAsyncExecution () 72130fdc8d8SChris Lattner { 7226611103cSGreg Clayton return !m_command_interpreter_ap->GetSynchronous(); 72330fdc8d8SChris Lattner } 72430fdc8d8SChris Lattner 72530fdc8d8SChris Lattner void 72630fdc8d8SChris Lattner Debugger::SetAsyncExecution (bool async_execution) 72730fdc8d8SChris Lattner { 7286611103cSGreg Clayton m_command_interpreter_ap->SetSynchronous (!async_execution); 72930fdc8d8SChris Lattner } 73030fdc8d8SChris Lattner 73130fdc8d8SChris Lattner 73230fdc8d8SChris Lattner void 73330fdc8d8SChris Lattner Debugger::SetInputFileHandle (FILE *fh, bool tranfer_ownership) 73430fdc8d8SChris Lattner { 73551b1e2d2SGreg Clayton File &in_file = GetInputFile(); 73651b1e2d2SGreg Clayton in_file.SetStream (fh, tranfer_ownership); 73751b1e2d2SGreg Clayton if (in_file.IsValid() == false) 73851b1e2d2SGreg Clayton in_file.SetStream (stdin, true); 73930fdc8d8SChris Lattner 74030fdc8d8SChris Lattner // Disconnect from any old connection if we had one 74130fdc8d8SChris Lattner m_input_comm.Disconnect (); 74232720b51SGreg Clayton // Pass false as the second argument to ConnectionFileDescriptor below because 74332720b51SGreg Clayton // our "in_file" above will already take ownership if requested and we don't 74432720b51SGreg Clayton // want to objects trying to own and close a file descriptor. 74532720b51SGreg Clayton m_input_comm.SetConnection (new ConnectionFileDescriptor (in_file.GetDescriptor(), false)); 74630fdc8d8SChris Lattner m_input_comm.SetReadThreadBytesReceivedCallback (Debugger::DispatchInputCallback, this); 74730fdc8d8SChris Lattner 748c5917d9aSJim Ingham // Save away the terminal state if that is relevant, so that we can restore it in RestoreInputState. 749c5917d9aSJim Ingham SaveInputTerminalState (); 750c5917d9aSJim Ingham 75130fdc8d8SChris Lattner Error error; 75230fdc8d8SChris Lattner if (m_input_comm.StartReadThread (&error) == false) 75330fdc8d8SChris Lattner { 75451b1e2d2SGreg Clayton File &err_file = GetErrorFile(); 75551b1e2d2SGreg Clayton 75651b1e2d2SGreg Clayton err_file.Printf ("error: failed to main input read thread: %s", error.AsCString() ? error.AsCString() : "unkown error"); 75730fdc8d8SChris Lattner exit(1); 75830fdc8d8SChris Lattner } 75930fdc8d8SChris Lattner } 76030fdc8d8SChris Lattner 76130fdc8d8SChris Lattner void 76230fdc8d8SChris Lattner Debugger::SetOutputFileHandle (FILE *fh, bool tranfer_ownership) 76330fdc8d8SChris Lattner { 76451b1e2d2SGreg Clayton File &out_file = GetOutputFile(); 76551b1e2d2SGreg Clayton out_file.SetStream (fh, tranfer_ownership); 76651b1e2d2SGreg Clayton if (out_file.IsValid() == false) 76751b1e2d2SGreg Clayton out_file.SetStream (stdout, false); 7682f88aadfSCaroline Tice 769b588726eSEnrico Granata // do not create the ScriptInterpreter just for setting the output file handle 770b588726eSEnrico Granata // as the constructor will know how to do the right thing on its own 771b588726eSEnrico Granata const bool can_create = false; 772b588726eSEnrico Granata ScriptInterpreter* script_interpreter = GetCommandInterpreter().GetScriptInterpreter(can_create); 773b588726eSEnrico Granata if (script_interpreter) 774b588726eSEnrico Granata script_interpreter->ResetOutputFileHandle (fh); 77530fdc8d8SChris Lattner } 77630fdc8d8SChris Lattner 77730fdc8d8SChris Lattner void 77830fdc8d8SChris Lattner Debugger::SetErrorFileHandle (FILE *fh, bool tranfer_ownership) 77930fdc8d8SChris Lattner { 78051b1e2d2SGreg Clayton File &err_file = GetErrorFile(); 78151b1e2d2SGreg Clayton err_file.SetStream (fh, tranfer_ownership); 78251b1e2d2SGreg Clayton if (err_file.IsValid() == false) 78351b1e2d2SGreg Clayton err_file.SetStream (stderr, false); 78430fdc8d8SChris Lattner } 78530fdc8d8SChris Lattner 786c5917d9aSJim Ingham void 787c5917d9aSJim Ingham Debugger::SaveInputTerminalState () 788c5917d9aSJim Ingham { 789c5917d9aSJim Ingham File &in_file = GetInputFile(); 790c5917d9aSJim Ingham if (in_file.GetDescriptor() != File::kInvalidDescriptor) 791c5917d9aSJim Ingham m_terminal_state.Save(in_file.GetDescriptor(), true); 792c5917d9aSJim Ingham } 793c5917d9aSJim Ingham 794c5917d9aSJim Ingham void 795c5917d9aSJim Ingham Debugger::RestoreInputTerminalState () 796c5917d9aSJim Ingham { 797c5917d9aSJim Ingham m_terminal_state.Restore(); 798c5917d9aSJim Ingham } 799c5917d9aSJim Ingham 80030fdc8d8SChris Lattner ExecutionContext 8012976d00aSJim Ingham Debugger::GetSelectedExecutionContext () 80230fdc8d8SChris Lattner { 80330fdc8d8SChris Lattner ExecutionContext exe_ctx; 804c14ee32dSGreg Clayton TargetSP target_sp(GetSelectedTarget()); 805c14ee32dSGreg Clayton exe_ctx.SetTargetSP (target_sp); 80630fdc8d8SChris Lattner 80730fdc8d8SChris Lattner if (target_sp) 80830fdc8d8SChris Lattner { 809c14ee32dSGreg Clayton ProcessSP process_sp (target_sp->GetProcessSP()); 810c14ee32dSGreg Clayton exe_ctx.SetProcessSP (process_sp); 811c14ee32dSGreg Clayton if (process_sp && process_sp->IsRunning() == false) 81230fdc8d8SChris Lattner { 813c14ee32dSGreg Clayton ThreadSP thread_sp (process_sp->GetThreadList().GetSelectedThread()); 814c14ee32dSGreg Clayton if (thread_sp) 81530fdc8d8SChris Lattner { 816c14ee32dSGreg Clayton exe_ctx.SetThreadSP (thread_sp); 817c14ee32dSGreg Clayton exe_ctx.SetFrameSP (thread_sp->GetSelectedFrame()); 818c14ee32dSGreg Clayton if (exe_ctx.GetFramePtr() == NULL) 819c14ee32dSGreg Clayton exe_ctx.SetFrameSP (thread_sp->GetStackFrameAtIndex (0)); 82030fdc8d8SChris Lattner } 82130fdc8d8SChris Lattner } 82230fdc8d8SChris Lattner } 82330fdc8d8SChris Lattner return exe_ctx; 82430fdc8d8SChris Lattner } 82530fdc8d8SChris Lattner 826b44880caSCaroline Tice InputReaderSP 827b44880caSCaroline Tice Debugger::GetCurrentInputReader () 828b44880caSCaroline Tice { 829b44880caSCaroline Tice InputReaderSP reader_sp; 830b44880caSCaroline Tice 831d5a0a01bSCaroline Tice if (!m_input_reader_stack.IsEmpty()) 832b44880caSCaroline Tice { 833b44880caSCaroline Tice // Clear any finished readers from the stack 834b44880caSCaroline Tice while (CheckIfTopInputReaderIsDone()) ; 835b44880caSCaroline Tice 836d5a0a01bSCaroline Tice if (!m_input_reader_stack.IsEmpty()) 837d5a0a01bSCaroline Tice reader_sp = m_input_reader_stack.Top(); 838b44880caSCaroline Tice } 839b44880caSCaroline Tice 840b44880caSCaroline Tice return reader_sp; 841b44880caSCaroline Tice } 842b44880caSCaroline Tice 84330fdc8d8SChris Lattner void 84430fdc8d8SChris Lattner Debugger::DispatchInputCallback (void *baton, const void *bytes, size_t bytes_len) 84530fdc8d8SChris Lattner { 846efed6131SCaroline Tice if (bytes_len > 0) 84730fdc8d8SChris Lattner ((Debugger *)baton)->DispatchInput ((char *)bytes, bytes_len); 848efed6131SCaroline Tice else 849efed6131SCaroline Tice ((Debugger *)baton)->DispatchInputEndOfFile (); 85030fdc8d8SChris Lattner } 85130fdc8d8SChris Lattner 85230fdc8d8SChris Lattner 85330fdc8d8SChris Lattner void 85430fdc8d8SChris Lattner Debugger::DispatchInput (const char *bytes, size_t bytes_len) 85530fdc8d8SChris Lattner { 856efed6131SCaroline Tice if (bytes == NULL || bytes_len == 0) 857efed6131SCaroline Tice return; 85830fdc8d8SChris Lattner 85930fdc8d8SChris Lattner WriteToDefaultReader (bytes, bytes_len); 86030fdc8d8SChris Lattner } 86130fdc8d8SChris Lattner 86230fdc8d8SChris Lattner void 863efed6131SCaroline Tice Debugger::DispatchInputInterrupt () 864efed6131SCaroline Tice { 865efed6131SCaroline Tice m_input_reader_data.clear(); 866efed6131SCaroline Tice 867b44880caSCaroline Tice InputReaderSP reader_sp (GetCurrentInputReader ()); 868efed6131SCaroline Tice if (reader_sp) 869b44880caSCaroline Tice { 870efed6131SCaroline Tice reader_sp->Notify (eInputReaderInterrupt); 871efed6131SCaroline Tice 872b44880caSCaroline Tice // If notifying the reader of the interrupt finished the reader, we should pop it off the stack. 873efed6131SCaroline Tice while (CheckIfTopInputReaderIsDone ()) ; 874efed6131SCaroline Tice } 875efed6131SCaroline Tice } 876efed6131SCaroline Tice 877efed6131SCaroline Tice void 878efed6131SCaroline Tice Debugger::DispatchInputEndOfFile () 879efed6131SCaroline Tice { 880efed6131SCaroline Tice m_input_reader_data.clear(); 881efed6131SCaroline Tice 882b44880caSCaroline Tice InputReaderSP reader_sp (GetCurrentInputReader ()); 883efed6131SCaroline Tice if (reader_sp) 884b44880caSCaroline Tice { 885efed6131SCaroline Tice reader_sp->Notify (eInputReaderEndOfFile); 886efed6131SCaroline Tice 887b44880caSCaroline Tice // If notifying the reader of the end-of-file finished the reader, we should pop it off the stack. 888efed6131SCaroline Tice while (CheckIfTopInputReaderIsDone ()) ; 889efed6131SCaroline Tice } 890efed6131SCaroline Tice } 891efed6131SCaroline Tice 892efed6131SCaroline Tice void 8933d6086f6SCaroline Tice Debugger::CleanUpInputReaders () 8943d6086f6SCaroline Tice { 8953d6086f6SCaroline Tice m_input_reader_data.clear(); 8963d6086f6SCaroline Tice 897b44880caSCaroline Tice // The bottom input reader should be the main debugger input reader. We do not want to close that one here. 898d5a0a01bSCaroline Tice while (m_input_reader_stack.GetSize() > 1) 8993d6086f6SCaroline Tice { 900b44880caSCaroline Tice InputReaderSP reader_sp (GetCurrentInputReader ()); 9013d6086f6SCaroline Tice if (reader_sp) 9023d6086f6SCaroline Tice { 9033d6086f6SCaroline Tice reader_sp->Notify (eInputReaderEndOfFile); 9043d6086f6SCaroline Tice reader_sp->SetIsDone (true); 9053d6086f6SCaroline Tice } 9063d6086f6SCaroline Tice } 9073d6086f6SCaroline Tice } 9083d6086f6SCaroline Tice 9093d6086f6SCaroline Tice void 910969ed3d1SCaroline Tice Debugger::NotifyTopInputReader (InputReaderAction notification) 911969ed3d1SCaroline Tice { 912969ed3d1SCaroline Tice InputReaderSP reader_sp (GetCurrentInputReader()); 913969ed3d1SCaroline Tice if (reader_sp) 914969ed3d1SCaroline Tice { 915969ed3d1SCaroline Tice reader_sp->Notify (notification); 916969ed3d1SCaroline Tice 917969ed3d1SCaroline Tice // Flush out any input readers that are done. 918969ed3d1SCaroline Tice while (CheckIfTopInputReaderIsDone ()) 919969ed3d1SCaroline Tice /* Do nothing. */; 920969ed3d1SCaroline Tice } 921969ed3d1SCaroline Tice } 922969ed3d1SCaroline Tice 9239088b068SCaroline Tice bool 9244d122c40SGreg Clayton Debugger::InputReaderIsTopReader (const InputReaderSP& reader_sp) 9259088b068SCaroline Tice { 9269088b068SCaroline Tice InputReaderSP top_reader_sp (GetCurrentInputReader()); 9279088b068SCaroline Tice 928d61c10bcSCaroline Tice return (reader_sp.get() == top_reader_sp.get()); 9299088b068SCaroline Tice } 9309088b068SCaroline Tice 9319088b068SCaroline Tice 932969ed3d1SCaroline Tice void 93330fdc8d8SChris Lattner Debugger::WriteToDefaultReader (const char *bytes, size_t bytes_len) 93430fdc8d8SChris Lattner { 93530fdc8d8SChris Lattner if (bytes && bytes_len) 93630fdc8d8SChris Lattner m_input_reader_data.append (bytes, bytes_len); 93730fdc8d8SChris Lattner 93830fdc8d8SChris Lattner if (m_input_reader_data.empty()) 93930fdc8d8SChris Lattner return; 94030fdc8d8SChris Lattner 941d5a0a01bSCaroline Tice while (!m_input_reader_stack.IsEmpty() && !m_input_reader_data.empty()) 94230fdc8d8SChris Lattner { 94330fdc8d8SChris Lattner // Get the input reader from the top of the stack 944b44880caSCaroline Tice InputReaderSP reader_sp (GetCurrentInputReader ()); 94530fdc8d8SChris Lattner if (!reader_sp) 94630fdc8d8SChris Lattner break; 94730fdc8d8SChris Lattner 948471b31ceSGreg Clayton size_t bytes_handled = reader_sp->HandleRawBytes (m_input_reader_data.c_str(), 94930fdc8d8SChris Lattner m_input_reader_data.size()); 95030fdc8d8SChris Lattner if (bytes_handled) 95130fdc8d8SChris Lattner { 95230fdc8d8SChris Lattner m_input_reader_data.erase (0, bytes_handled); 95330fdc8d8SChris Lattner } 95430fdc8d8SChris Lattner else 95530fdc8d8SChris Lattner { 95630fdc8d8SChris Lattner // No bytes were handled, we might not have reached our 95730fdc8d8SChris Lattner // granularity, just return and wait for more data 95830fdc8d8SChris Lattner break; 95930fdc8d8SChris Lattner } 96030fdc8d8SChris Lattner } 96130fdc8d8SChris Lattner 962b44880caSCaroline Tice // Flush out any input readers that are done. 96330fdc8d8SChris Lattner while (CheckIfTopInputReaderIsDone ()) 96430fdc8d8SChris Lattner /* Do nothing. */; 96530fdc8d8SChris Lattner 96630fdc8d8SChris Lattner } 96730fdc8d8SChris Lattner 96830fdc8d8SChris Lattner void 96930fdc8d8SChris Lattner Debugger::PushInputReader (const InputReaderSP& reader_sp) 97030fdc8d8SChris Lattner { 97130fdc8d8SChris Lattner if (!reader_sp) 97230fdc8d8SChris Lattner return; 973b44880caSCaroline Tice 97430fdc8d8SChris Lattner // Deactivate the old top reader 975b44880caSCaroline Tice InputReaderSP top_reader_sp (GetCurrentInputReader ()); 976b44880caSCaroline Tice 97730fdc8d8SChris Lattner if (top_reader_sp) 97830fdc8d8SChris Lattner top_reader_sp->Notify (eInputReaderDeactivate); 979b44880caSCaroline Tice 980d5a0a01bSCaroline Tice m_input_reader_stack.Push (reader_sp); 98130fdc8d8SChris Lattner reader_sp->Notify (eInputReaderActivate); 98230fdc8d8SChris Lattner ActivateInputReader (reader_sp); 98330fdc8d8SChris Lattner } 98430fdc8d8SChris Lattner 98530fdc8d8SChris Lattner bool 9864d122c40SGreg Clayton Debugger::PopInputReader (const InputReaderSP& pop_reader_sp) 98730fdc8d8SChris Lattner { 98830fdc8d8SChris Lattner bool result = false; 98930fdc8d8SChris Lattner 99030fdc8d8SChris Lattner // The reader on the stop of the stack is done, so let the next 99130fdc8d8SChris Lattner // read on the stack referesh its prompt and if there is one... 992d5a0a01bSCaroline Tice if (!m_input_reader_stack.IsEmpty()) 99330fdc8d8SChris Lattner { 994b44880caSCaroline Tice // Cannot call GetCurrentInputReader here, as that would cause an infinite loop. 995d5a0a01bSCaroline Tice InputReaderSP reader_sp(m_input_reader_stack.Top()); 99630fdc8d8SChris Lattner 99730fdc8d8SChris Lattner if (!pop_reader_sp || pop_reader_sp.get() == reader_sp.get()) 99830fdc8d8SChris Lattner { 999d5a0a01bSCaroline Tice m_input_reader_stack.Pop (); 100030fdc8d8SChris Lattner reader_sp->Notify (eInputReaderDeactivate); 100130fdc8d8SChris Lattner reader_sp->Notify (eInputReaderDone); 100230fdc8d8SChris Lattner result = true; 100330fdc8d8SChris Lattner 1004d5a0a01bSCaroline Tice if (!m_input_reader_stack.IsEmpty()) 100530fdc8d8SChris Lattner { 1006d5a0a01bSCaroline Tice reader_sp = m_input_reader_stack.Top(); 100730fdc8d8SChris Lattner if (reader_sp) 100830fdc8d8SChris Lattner { 100930fdc8d8SChris Lattner ActivateInputReader (reader_sp); 101030fdc8d8SChris Lattner reader_sp->Notify (eInputReaderReactivate); 101130fdc8d8SChris Lattner } 101230fdc8d8SChris Lattner } 101330fdc8d8SChris Lattner } 101430fdc8d8SChris Lattner } 101530fdc8d8SChris Lattner return result; 101630fdc8d8SChris Lattner } 101730fdc8d8SChris Lattner 101830fdc8d8SChris Lattner bool 101930fdc8d8SChris Lattner Debugger::CheckIfTopInputReaderIsDone () 102030fdc8d8SChris Lattner { 102130fdc8d8SChris Lattner bool result = false; 1022d5a0a01bSCaroline Tice if (!m_input_reader_stack.IsEmpty()) 102330fdc8d8SChris Lattner { 1024b44880caSCaroline Tice // Cannot call GetCurrentInputReader here, as that would cause an infinite loop. 1025d5a0a01bSCaroline Tice InputReaderSP reader_sp(m_input_reader_stack.Top()); 102630fdc8d8SChris Lattner 102730fdc8d8SChris Lattner if (reader_sp && reader_sp->IsDone()) 102830fdc8d8SChris Lattner { 102930fdc8d8SChris Lattner result = true; 103030fdc8d8SChris Lattner PopInputReader (reader_sp); 103130fdc8d8SChris Lattner } 103230fdc8d8SChris Lattner } 103330fdc8d8SChris Lattner return result; 103430fdc8d8SChris Lattner } 103530fdc8d8SChris Lattner 103630fdc8d8SChris Lattner void 103730fdc8d8SChris Lattner Debugger::ActivateInputReader (const InputReaderSP &reader_sp) 103830fdc8d8SChris Lattner { 103951b1e2d2SGreg Clayton int input_fd = m_input_file.GetFile().GetDescriptor(); 104030fdc8d8SChris Lattner 104151b1e2d2SGreg Clayton if (input_fd >= 0) 104230fdc8d8SChris Lattner { 104351b1e2d2SGreg Clayton Terminal tty(input_fd); 1044a3406614SGreg Clayton 1045a3406614SGreg Clayton tty.SetEcho(reader_sp->GetEcho()); 104630fdc8d8SChris Lattner 104730fdc8d8SChris Lattner switch (reader_sp->GetGranularity()) 104830fdc8d8SChris Lattner { 104930fdc8d8SChris Lattner case eInputReaderGranularityByte: 105030fdc8d8SChris Lattner case eInputReaderGranularityWord: 1051a3406614SGreg Clayton tty.SetCanonical (false); 105230fdc8d8SChris Lattner break; 105330fdc8d8SChris Lattner 105430fdc8d8SChris Lattner case eInputReaderGranularityLine: 105530fdc8d8SChris Lattner case eInputReaderGranularityAll: 1056a3406614SGreg Clayton tty.SetCanonical (true); 105730fdc8d8SChris Lattner break; 105830fdc8d8SChris Lattner 105930fdc8d8SChris Lattner default: 106030fdc8d8SChris Lattner break; 106130fdc8d8SChris Lattner } 106230fdc8d8SChris Lattner } 106330fdc8d8SChris Lattner } 10646611103cSGreg Clayton 10655b52f0c7SJim Ingham StreamSP 10665b52f0c7SJim Ingham Debugger::GetAsyncOutputStream () 10675b52f0c7SJim Ingham { 10685b52f0c7SJim Ingham return StreamSP (new StreamAsynchronousIO (GetCommandInterpreter(), 10695b52f0c7SJim Ingham CommandInterpreter::eBroadcastBitAsynchronousOutputData)); 10705b52f0c7SJim Ingham } 10715b52f0c7SJim Ingham 10725b52f0c7SJim Ingham StreamSP 10735b52f0c7SJim Ingham Debugger::GetAsyncErrorStream () 10745b52f0c7SJim Ingham { 10755b52f0c7SJim Ingham return StreamSP (new StreamAsynchronousIO (GetCommandInterpreter(), 10765b52f0c7SJim Ingham CommandInterpreter::eBroadcastBitAsynchronousErrorData)); 10775b52f0c7SJim Ingham } 10785b52f0c7SJim Ingham 1079c7bece56SGreg Clayton size_t 1080061858ceSEnrico Granata Debugger::GetNumDebuggers() 1081061858ceSEnrico Granata { 1082c15f55e2SGreg Clayton if (g_shared_debugger_refcount > 0) 1083c15f55e2SGreg Clayton { 1084061858ceSEnrico Granata Mutex::Locker locker (GetDebuggerListMutex ()); 1085061858ceSEnrico Granata return GetDebuggerList().size(); 1086061858ceSEnrico Granata } 1087c15f55e2SGreg Clayton return 0; 1088c15f55e2SGreg Clayton } 1089061858ceSEnrico Granata 1090061858ceSEnrico Granata lldb::DebuggerSP 1091c7bece56SGreg Clayton Debugger::GetDebuggerAtIndex (size_t index) 1092061858ceSEnrico Granata { 1093061858ceSEnrico Granata DebuggerSP debugger_sp; 1094061858ceSEnrico Granata 1095c15f55e2SGreg Clayton if (g_shared_debugger_refcount > 0) 1096c15f55e2SGreg Clayton { 1097061858ceSEnrico Granata Mutex::Locker locker (GetDebuggerListMutex ()); 1098061858ceSEnrico Granata DebuggerList &debugger_list = GetDebuggerList(); 1099061858ceSEnrico Granata 1100061858ceSEnrico Granata if (index < debugger_list.size()) 1101061858ceSEnrico Granata debugger_sp = debugger_list[index]; 1102c15f55e2SGreg Clayton } 1103061858ceSEnrico Granata 1104061858ceSEnrico Granata return debugger_sp; 1105061858ceSEnrico Granata } 1106061858ceSEnrico Granata 1107ebc1bb27SCaroline Tice DebuggerSP 1108ebc1bb27SCaroline Tice Debugger::FindDebuggerWithID (lldb::user_id_t id) 1109ebc1bb27SCaroline Tice { 11104d122c40SGreg Clayton DebuggerSP debugger_sp; 1111ebc1bb27SCaroline Tice 1112c15f55e2SGreg Clayton if (g_shared_debugger_refcount > 0) 1113c15f55e2SGreg Clayton { 1114ebc1bb27SCaroline Tice Mutex::Locker locker (GetDebuggerListMutex ()); 1115ebc1bb27SCaroline Tice DebuggerList &debugger_list = GetDebuggerList(); 1116ebc1bb27SCaroline Tice DebuggerList::iterator pos, end = debugger_list.end(); 1117ebc1bb27SCaroline Tice for (pos = debugger_list.begin(); pos != end; ++pos) 1118ebc1bb27SCaroline Tice { 1119ebc1bb27SCaroline Tice if ((*pos).get()->GetID() == id) 1120ebc1bb27SCaroline Tice { 1121ebc1bb27SCaroline Tice debugger_sp = *pos; 1122ebc1bb27SCaroline Tice break; 1123ebc1bb27SCaroline Tice } 1124ebc1bb27SCaroline Tice } 1125c15f55e2SGreg Clayton } 1126ebc1bb27SCaroline Tice return debugger_sp; 1127ebc1bb27SCaroline Tice } 11283df9a8dfSCaroline Tice 11291b654882SGreg Clayton static void 11301b654882SGreg Clayton TestPromptFormats (StackFrame *frame) 11311b654882SGreg Clayton { 11321b654882SGreg Clayton if (frame == NULL) 11331b654882SGreg Clayton return; 11341b654882SGreg Clayton 11351b654882SGreg Clayton StreamString s; 11361b654882SGreg Clayton const char *prompt_format = 11371b654882SGreg Clayton "{addr = '${addr}'\n}" 11381b654882SGreg Clayton "{process.id = '${process.id}'\n}" 11391b654882SGreg Clayton "{process.name = '${process.name}'\n}" 11401b654882SGreg Clayton "{process.file.basename = '${process.file.basename}'\n}" 11411b654882SGreg Clayton "{process.file.fullpath = '${process.file.fullpath}'\n}" 11421b654882SGreg Clayton "{thread.id = '${thread.id}'\n}" 11431b654882SGreg Clayton "{thread.index = '${thread.index}'\n}" 11441b654882SGreg Clayton "{thread.name = '${thread.name}'\n}" 11451b654882SGreg Clayton "{thread.queue = '${thread.queue}'\n}" 11461b654882SGreg Clayton "{thread.stop-reason = '${thread.stop-reason}'\n}" 11471b654882SGreg Clayton "{target.arch = '${target.arch}'\n}" 11481b654882SGreg Clayton "{module.file.basename = '${module.file.basename}'\n}" 11491b654882SGreg Clayton "{module.file.fullpath = '${module.file.fullpath}'\n}" 11501b654882SGreg Clayton "{file.basename = '${file.basename}'\n}" 11511b654882SGreg Clayton "{file.fullpath = '${file.fullpath}'\n}" 11521b654882SGreg Clayton "{frame.index = '${frame.index}'\n}" 11531b654882SGreg Clayton "{frame.pc = '${frame.pc}'\n}" 11541b654882SGreg Clayton "{frame.sp = '${frame.sp}'\n}" 11551b654882SGreg Clayton "{frame.fp = '${frame.fp}'\n}" 11561b654882SGreg Clayton "{frame.flags = '${frame.flags}'\n}" 11571b654882SGreg Clayton "{frame.reg.rdi = '${frame.reg.rdi}'\n}" 11581b654882SGreg Clayton "{frame.reg.rip = '${frame.reg.rip}'\n}" 11591b654882SGreg Clayton "{frame.reg.rsp = '${frame.reg.rsp}'\n}" 11601b654882SGreg Clayton "{frame.reg.rbp = '${frame.reg.rbp}'\n}" 11611b654882SGreg Clayton "{frame.reg.rflags = '${frame.reg.rflags}'\n}" 11621b654882SGreg Clayton "{frame.reg.xmm0 = '${frame.reg.xmm0}'\n}" 11631b654882SGreg Clayton "{frame.reg.carp = '${frame.reg.carp}'\n}" 11641b654882SGreg Clayton "{function.id = '${function.id}'\n}" 11651b654882SGreg Clayton "{function.name = '${function.name}'\n}" 1166ccbc08e6SGreg Clayton "{function.name-with-args = '${function.name-with-args}'\n}" 11671b654882SGreg Clayton "{function.addr-offset = '${function.addr-offset}'\n}" 11681b654882SGreg Clayton "{function.line-offset = '${function.line-offset}'\n}" 11691b654882SGreg Clayton "{function.pc-offset = '${function.pc-offset}'\n}" 11701b654882SGreg Clayton "{line.file.basename = '${line.file.basename}'\n}" 11711b654882SGreg Clayton "{line.file.fullpath = '${line.file.fullpath}'\n}" 11721b654882SGreg Clayton "{line.number = '${line.number}'\n}" 11731b654882SGreg Clayton "{line.start-addr = '${line.start-addr}'\n}" 11741b654882SGreg Clayton "{line.end-addr = '${line.end-addr}'\n}" 11751b654882SGreg Clayton ; 11761b654882SGreg Clayton 11771b654882SGreg Clayton SymbolContext sc (frame->GetSymbolContext(eSymbolContextEverything)); 11781b654882SGreg Clayton ExecutionContext exe_ctx; 11790603aa9dSGreg Clayton frame->CalculateExecutionContext(exe_ctx); 1180c3ce7f27SMichael Sartain if (Debugger::FormatPrompt (prompt_format, &sc, &exe_ctx, &sc.line_entry.range.GetBaseAddress(), s)) 11811b654882SGreg Clayton { 11821b654882SGreg Clayton printf("%s\n", s.GetData()); 11831b654882SGreg Clayton } 11841b654882SGreg Clayton else 11851b654882SGreg Clayton { 11861b654882SGreg Clayton printf ("what we got: %s\n", s.GetData()); 11871b654882SGreg Clayton } 11881b654882SGreg Clayton } 11891b654882SGreg Clayton 11909fc1944eSEnrico Granata static bool 11919fc1944eSEnrico Granata ScanFormatDescriptor (const char* var_name_begin, 11929fc1944eSEnrico Granata const char* var_name_end, 11939fc1944eSEnrico Granata const char** var_name_final, 11949fc1944eSEnrico Granata const char** percent_position, 11954d122c40SGreg Clayton Format* custom_format, 11969fc1944eSEnrico Granata ValueObject::ValueObjectRepresentationStyle* val_obj_display) 11979fc1944eSEnrico Granata { 11985160ce5cSGreg Clayton Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES)); 11999fc1944eSEnrico Granata *percent_position = ::strchr(var_name_begin,'%'); 12009fc1944eSEnrico Granata if (!*percent_position || *percent_position > var_name_end) 1201e992a089SEnrico Granata { 1202e992a089SEnrico Granata if (log) 1203d228483dSEnrico Granata log->Printf("[ScanFormatDescriptor] no format descriptor in string, skipping"); 12049fc1944eSEnrico Granata *var_name_final = var_name_end; 1205e992a089SEnrico Granata } 12069fc1944eSEnrico Granata else 12079fc1944eSEnrico Granata { 12089fc1944eSEnrico Granata *var_name_final = *percent_position; 120936aa5ae6SEnrico Granata std::string format_name(*var_name_final+1, var_name_end-*var_name_final-1); 1210e992a089SEnrico Granata if (log) 121168ae4117SEnrico Granata log->Printf("[ScanFormatDescriptor] parsing %s as a format descriptor", format_name.c_str()); 121236aa5ae6SEnrico Granata if ( !FormatManager::GetFormatFromCString(format_name.c_str(), 12139fc1944eSEnrico Granata true, 12149fc1944eSEnrico Granata *custom_format) ) 12159fc1944eSEnrico Granata { 1216e992a089SEnrico Granata if (log) 121768ae4117SEnrico Granata log->Printf("[ScanFormatDescriptor] %s is an unknown format", format_name.c_str()); 121836aa5ae6SEnrico Granata 121936aa5ae6SEnrico Granata switch (format_name.front()) 122036aa5ae6SEnrico Granata { 122136aa5ae6SEnrico Granata case '@': // if this is an @ sign, print ObjC description 122286cc9829SEnrico Granata *val_obj_display = ValueObject::eValueObjectRepresentationStyleLanguageSpecific; 122336aa5ae6SEnrico Granata break; 122436aa5ae6SEnrico Granata case 'V': // if this is a V, print the value using the default format 122586cc9829SEnrico Granata *val_obj_display = ValueObject::eValueObjectRepresentationStyleValue; 122636aa5ae6SEnrico Granata break; 122736aa5ae6SEnrico Granata case 'L': // if this is an L, print the location of the value 122886cc9829SEnrico Granata *val_obj_display = ValueObject::eValueObjectRepresentationStyleLocation; 122936aa5ae6SEnrico Granata break; 123036aa5ae6SEnrico Granata case 'S': // if this is an S, print the summary after all 123186cc9829SEnrico Granata *val_obj_display = ValueObject::eValueObjectRepresentationStyleSummary; 123236aa5ae6SEnrico Granata break; 123336aa5ae6SEnrico Granata case '#': // if this is a '#', print the number of children 123486cc9829SEnrico Granata *val_obj_display = ValueObject::eValueObjectRepresentationStyleChildrenCount; 123536aa5ae6SEnrico Granata break; 123636aa5ae6SEnrico Granata case 'T': // if this is a 'T', print the type 123786cc9829SEnrico Granata *val_obj_display = ValueObject::eValueObjectRepresentationStyleType; 123836aa5ae6SEnrico Granata break; 12392c75f11eSEnrico Granata case 'N': // if this is a 'N', print the name 12402c75f11eSEnrico Granata *val_obj_display = ValueObject::eValueObjectRepresentationStyleName; 12412c75f11eSEnrico Granata break; 12422c75f11eSEnrico Granata case '>': // if this is a '>', print the name 12432c75f11eSEnrico Granata *val_obj_display = ValueObject::eValueObjectRepresentationStyleExpressionPath; 12442c75f11eSEnrico Granata break; 124536aa5ae6SEnrico Granata default: 12465c42d8a8SJim Ingham if (log) 124736aa5ae6SEnrico Granata log->Printf("ScanFormatDescriptor] %s is an error, leaving the previous value alone", format_name.c_str()); 124836aa5ae6SEnrico Granata break; 124936aa5ae6SEnrico Granata } 12509fc1944eSEnrico Granata } 12519fc1944eSEnrico Granata // a good custom format tells us to print the value using it 12529fc1944eSEnrico Granata else 1253e992a089SEnrico Granata { 1254e992a089SEnrico Granata if (log) 125568ae4117SEnrico Granata log->Printf("[ScanFormatDescriptor] will display value for this VO"); 125686cc9829SEnrico Granata *val_obj_display = ValueObject::eValueObjectRepresentationStyleValue; 1257e992a089SEnrico Granata } 12589fc1944eSEnrico Granata } 1259e992a089SEnrico Granata if (log) 126068ae4117SEnrico Granata log->Printf("[ScanFormatDescriptor] final format description outcome: custom_format = %d, val_obj_display = %d", 1261e992a089SEnrico Granata *custom_format, 1262e992a089SEnrico Granata *val_obj_display); 12639fc1944eSEnrico Granata return true; 12649fc1944eSEnrico Granata } 12659fc1944eSEnrico Granata 12669fc1944eSEnrico Granata static bool 12679fc1944eSEnrico Granata ScanBracketedRange (const char* var_name_begin, 12689fc1944eSEnrico Granata const char* var_name_end, 12699fc1944eSEnrico Granata const char* var_name_final, 12709fc1944eSEnrico Granata const char** open_bracket_position, 12719fc1944eSEnrico Granata const char** separator_position, 12729fc1944eSEnrico Granata const char** close_bracket_position, 12739fc1944eSEnrico Granata const char** var_name_final_if_array_range, 12749fc1944eSEnrico Granata int64_t* index_lower, 12759fc1944eSEnrico Granata int64_t* index_higher) 12769fc1944eSEnrico Granata { 12775160ce5cSGreg Clayton Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES)); 12789fc1944eSEnrico Granata *open_bracket_position = ::strchr(var_name_begin,'['); 12799fc1944eSEnrico Granata if (*open_bracket_position && *open_bracket_position < var_name_final) 12809fc1944eSEnrico Granata { 12819fc1944eSEnrico Granata *separator_position = ::strchr(*open_bracket_position,'-'); // might be NULL if this is a simple var[N] bitfield 12829fc1944eSEnrico Granata *close_bracket_position = ::strchr(*open_bracket_position,']'); 12839fc1944eSEnrico Granata // as usual, we assume that [] will come before % 12849fc1944eSEnrico Granata //printf("trying to expand a []\n"); 12859fc1944eSEnrico Granata *var_name_final_if_array_range = *open_bracket_position; 12869fc1944eSEnrico Granata if (*close_bracket_position - *open_bracket_position == 1) 12879fc1944eSEnrico Granata { 1288e992a089SEnrico Granata if (log) 1289d228483dSEnrico Granata log->Printf("[ScanBracketedRange] '[]' detected.. going from 0 to end of data"); 12909fc1944eSEnrico Granata *index_lower = 0; 12919fc1944eSEnrico Granata } 12929fc1944eSEnrico Granata else if (*separator_position == NULL || *separator_position > var_name_end) 12939fc1944eSEnrico Granata { 12949fc1944eSEnrico Granata char *end = NULL; 12959fc1944eSEnrico Granata *index_lower = ::strtoul (*open_bracket_position+1, &end, 0); 12969fc1944eSEnrico Granata *index_higher = *index_lower; 1297e992a089SEnrico Granata if (log) 1298d01b2953SDaniel Malea log->Printf("[ScanBracketedRange] [%" PRId64 "] detected, high index is same", *index_lower); 12999fc1944eSEnrico Granata } 13009fc1944eSEnrico Granata else if (*close_bracket_position && *close_bracket_position < var_name_end) 13019fc1944eSEnrico Granata { 13029fc1944eSEnrico Granata char *end = NULL; 13039fc1944eSEnrico Granata *index_lower = ::strtoul (*open_bracket_position+1, &end, 0); 13049fc1944eSEnrico Granata *index_higher = ::strtoul (*separator_position+1, &end, 0); 1305e992a089SEnrico Granata if (log) 1306d01b2953SDaniel Malea log->Printf("[ScanBracketedRange] [%" PRId64 "-%" PRId64 "] detected", *index_lower, *index_higher); 13079fc1944eSEnrico Granata } 13089fc1944eSEnrico Granata else 1309e992a089SEnrico Granata { 1310e992a089SEnrico Granata if (log) 1311d228483dSEnrico Granata log->Printf("[ScanBracketedRange] expression is erroneous, cannot extract indices out of it"); 13129fc1944eSEnrico Granata return false; 1313e992a089SEnrico Granata } 13149fc1944eSEnrico Granata if (*index_lower > *index_higher && *index_higher > 0) 13159fc1944eSEnrico Granata { 1316e992a089SEnrico Granata if (log) 1317d228483dSEnrico Granata log->Printf("[ScanBracketedRange] swapping indices"); 1318c7bece56SGreg Clayton int64_t temp = *index_lower; 13199fc1944eSEnrico Granata *index_lower = *index_higher; 13209fc1944eSEnrico Granata *index_higher = temp; 13219fc1944eSEnrico Granata } 13229fc1944eSEnrico Granata } 1323e992a089SEnrico Granata else if (log) 1324d228483dSEnrico Granata log->Printf("[ScanBracketedRange] no bracketed range, skipping entirely"); 13259fc1944eSEnrico Granata return true; 13269fc1944eSEnrico Granata } 13279fc1944eSEnrico Granata 13280769b2b1SMichael Sartain template <typename T> 13290769b2b1SMichael Sartain static bool RunScriptFormatKeyword(Stream &s, ScriptInterpreter *script_interpreter, T t, const std::string& script_name) 13300769b2b1SMichael Sartain { 13310769b2b1SMichael Sartain if (script_interpreter) 13320769b2b1SMichael Sartain { 13330769b2b1SMichael Sartain Error script_error; 13340769b2b1SMichael Sartain std::string script_output; 13350769b2b1SMichael Sartain 13360769b2b1SMichael Sartain if (script_interpreter->RunScriptFormatKeyword(script_name.c_str(), t, script_output, script_error) && script_error.Success()) 13370769b2b1SMichael Sartain { 13380769b2b1SMichael Sartain s.Printf("%s", script_output.c_str()); 13390769b2b1SMichael Sartain return true; 13400769b2b1SMichael Sartain } 13410769b2b1SMichael Sartain else 13420769b2b1SMichael Sartain { 13430769b2b1SMichael Sartain s.Printf("<error: %s>",script_error.AsCString()); 13440769b2b1SMichael Sartain } 13450769b2b1SMichael Sartain } 13460769b2b1SMichael Sartain return false; 13470769b2b1SMichael Sartain } 13480769b2b1SMichael Sartain 13499fc1944eSEnrico Granata static ValueObjectSP 1350c482a192SEnrico Granata ExpandIndexedExpression (ValueObject* valobj, 1351c7bece56SGreg Clayton size_t index, 13529fc1944eSEnrico Granata StackFrame* frame, 1353fc7a7f3bSEnrico Granata bool deref_pointer) 13549fc1944eSEnrico Granata { 13555160ce5cSGreg Clayton Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES)); 1356fc7a7f3bSEnrico Granata const char* ptr_deref_format = "[%d]"; 1357599171adSEnrico Granata std::string ptr_deref_buffer(10,0); 1358599171adSEnrico Granata ::sprintf(&ptr_deref_buffer[0], ptr_deref_format, index); 1359e992a089SEnrico Granata if (log) 1360599171adSEnrico Granata log->Printf("[ExpandIndexedExpression] name to deref: %s",ptr_deref_buffer.c_str()); 1361fc7a7f3bSEnrico Granata const char* first_unparsed; 1362fc7a7f3bSEnrico Granata ValueObject::GetValueForExpressionPathOptions options; 1363fc7a7f3bSEnrico Granata ValueObject::ExpressionPathEndResultType final_value_type; 1364fc7a7f3bSEnrico Granata ValueObject::ExpressionPathScanEndReason reason_to_stop; 136586cc9829SEnrico Granata ValueObject::ExpressionPathAftermath what_next = (deref_pointer ? ValueObject::eExpressionPathAftermathDereference : ValueObject::eExpressionPathAftermathNothing); 1366599171adSEnrico Granata ValueObjectSP item = valobj->GetValueForExpressionPath (ptr_deref_buffer.c_str(), 1367fc7a7f3bSEnrico Granata &first_unparsed, 1368fc7a7f3bSEnrico Granata &reason_to_stop, 1369fc7a7f3bSEnrico Granata &final_value_type, 1370fc7a7f3bSEnrico Granata options, 1371fc7a7f3bSEnrico Granata &what_next); 1372fc7a7f3bSEnrico Granata if (!item) 1373fc7a7f3bSEnrico Granata { 1374e992a089SEnrico Granata if (log) 1375d228483dSEnrico Granata log->Printf("[ExpandIndexedExpression] ERROR: unparsed portion = %s, why stopping = %d," 1376e992a089SEnrico Granata " final_value_type %d", 1377fc7a7f3bSEnrico Granata first_unparsed, reason_to_stop, final_value_type); 1378fc7a7f3bSEnrico Granata } 13799fc1944eSEnrico Granata else 13809fc1944eSEnrico Granata { 1381e992a089SEnrico Granata if (log) 1382d228483dSEnrico Granata log->Printf("[ExpandIndexedExpression] ALL RIGHT: unparsed portion = %s, why stopping = %d," 1383e992a089SEnrico Granata " final_value_type %d", 1384fc7a7f3bSEnrico Granata first_unparsed, reason_to_stop, final_value_type); 13859fc1944eSEnrico Granata } 13869fc1944eSEnrico Granata return item; 13879fc1944eSEnrico Granata } 13889fc1944eSEnrico Granata 13890769b2b1SMichael Sartain static inline bool 13900769b2b1SMichael Sartain IsToken(const char *var_name_begin, const char *var) 13910769b2b1SMichael Sartain { 13920769b2b1SMichael Sartain return (::strncmp (var_name_begin, var, strlen(var)) == 0); 13930769b2b1SMichael Sartain } 13940769b2b1SMichael Sartain 13950769b2b1SMichael Sartain static bool 13960769b2b1SMichael Sartain IsTokenWithFormat(const char *var_name_begin, const char *var, std::string &format, const char *default_format, 13970769b2b1SMichael Sartain const ExecutionContext *exe_ctx_ptr, const SymbolContext *sc_ptr) 13980769b2b1SMichael Sartain { 13990769b2b1SMichael Sartain int var_len = strlen(var); 14000769b2b1SMichael Sartain if (::strncmp (var_name_begin, var, var_len) == 0) 14010769b2b1SMichael Sartain { 14020769b2b1SMichael Sartain var_name_begin += var_len; 14030769b2b1SMichael Sartain if (*var_name_begin == '}') 14040769b2b1SMichael Sartain { 14050769b2b1SMichael Sartain format = default_format; 14060769b2b1SMichael Sartain return true; 14070769b2b1SMichael Sartain } 14080769b2b1SMichael Sartain else if (*var_name_begin == '%') 14090769b2b1SMichael Sartain { 14100769b2b1SMichael Sartain // Allow format specifiers: x|X|u with optional width specifiers. 14110769b2b1SMichael Sartain // ${thread.id%x} ; hex 14120769b2b1SMichael Sartain // ${thread.id%X} ; uppercase hex 14130769b2b1SMichael Sartain // ${thread.id%u} ; unsigned decimal 14140769b2b1SMichael Sartain // ${thread.id%8.8X} ; width.precision + specifier 14150769b2b1SMichael Sartain // ${thread.id%tid} ; unsigned on FreeBSD/Linux, otherwise default_format (0x%4.4x for thread.id) 14160769b2b1SMichael Sartain int dot_count = 0; 14170769b2b1SMichael Sartain const char *specifier = NULL; 14180769b2b1SMichael Sartain int width_precision_length = 0; 14190769b2b1SMichael Sartain const char *width_precision = ++var_name_begin; 14200769b2b1SMichael Sartain while (isdigit(*var_name_begin) || *var_name_begin == '.') 14210769b2b1SMichael Sartain { 14220769b2b1SMichael Sartain dot_count += (*var_name_begin == '.'); 14230769b2b1SMichael Sartain if (dot_count > 1) 14240769b2b1SMichael Sartain break; 14250769b2b1SMichael Sartain var_name_begin++; 14260769b2b1SMichael Sartain width_precision_length++; 14270769b2b1SMichael Sartain } 14280769b2b1SMichael Sartain 14290769b2b1SMichael Sartain if (IsToken (var_name_begin, "tid}")) 14300769b2b1SMichael Sartain { 14310769b2b1SMichael Sartain Target *target = Target::GetTargetFromContexts (exe_ctx_ptr, sc_ptr); 14320769b2b1SMichael Sartain if (target) 14330769b2b1SMichael Sartain { 14340769b2b1SMichael Sartain ArchSpec arch (target->GetArchitecture ()); 14350769b2b1SMichael Sartain llvm::Triple::OSType ostype = arch.IsValid() ? arch.GetTriple().getOS() : llvm::Triple::UnknownOS; 14360769b2b1SMichael Sartain if ((ostype == llvm::Triple::FreeBSD) || (ostype == llvm::Triple::Linux)) 14370769b2b1SMichael Sartain specifier = PRIu64; 14380769b2b1SMichael Sartain } 14390769b2b1SMichael Sartain if (!specifier) 14400769b2b1SMichael Sartain { 14410769b2b1SMichael Sartain format = default_format; 14420769b2b1SMichael Sartain return true; 14430769b2b1SMichael Sartain } 14440769b2b1SMichael Sartain } 14450769b2b1SMichael Sartain else if (IsToken (var_name_begin, "x}")) 14460769b2b1SMichael Sartain specifier = PRIx64; 14470769b2b1SMichael Sartain else if (IsToken (var_name_begin, "X}")) 14480769b2b1SMichael Sartain specifier = PRIX64; 14490769b2b1SMichael Sartain else if (IsToken (var_name_begin, "u}")) 14500769b2b1SMichael Sartain specifier = PRIu64; 14510769b2b1SMichael Sartain 14520769b2b1SMichael Sartain if (specifier) 14530769b2b1SMichael Sartain { 14540769b2b1SMichael Sartain format = "%"; 14550769b2b1SMichael Sartain if (width_precision_length) 14560769b2b1SMichael Sartain format += std::string(width_precision, width_precision_length); 14570769b2b1SMichael Sartain format += specifier; 14580769b2b1SMichael Sartain return true; 14590769b2b1SMichael Sartain } 14600769b2b1SMichael Sartain } 14610769b2b1SMichael Sartain } 14620769b2b1SMichael Sartain return false; 14630769b2b1SMichael Sartain } 14640769b2b1SMichael Sartain 1465c3ce7f27SMichael Sartain static bool 1466c3ce7f27SMichael Sartain FormatPromptRecurse 14671b654882SGreg Clayton ( 14681b654882SGreg Clayton const char *format, 14691b654882SGreg Clayton const SymbolContext *sc, 14701b654882SGreg Clayton const ExecutionContext *exe_ctx, 14711b654882SGreg Clayton const Address *addr, 14721b654882SGreg Clayton Stream &s, 14734becb37eSEnrico Granata const char **end, 1474c482a192SEnrico Granata ValueObject* valobj 14751b654882SGreg Clayton ) 14761b654882SGreg Clayton { 1477c482a192SEnrico Granata ValueObject* realvalobj = NULL; // makes it super-easy to parse pointers 14781b654882SGreg Clayton bool success = true; 14791b654882SGreg Clayton const char *p; 14805160ce5cSGreg Clayton Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES)); 1481c3ce7f27SMichael Sartain 14821b654882SGreg Clayton for (p = format; *p != '\0'; ++p) 14831b654882SGreg Clayton { 1484c482a192SEnrico Granata if (realvalobj) 14854becb37eSEnrico Granata { 1486c482a192SEnrico Granata valobj = realvalobj; 1487c482a192SEnrico Granata realvalobj = NULL; 14884becb37eSEnrico Granata } 14891b654882SGreg Clayton size_t non_special_chars = ::strcspn (p, "${}\\"); 14901b654882SGreg Clayton if (non_special_chars > 0) 14911b654882SGreg Clayton { 14921b654882SGreg Clayton if (success) 14931b654882SGreg Clayton s.Write (p, non_special_chars); 14941b654882SGreg Clayton p += non_special_chars; 14951b654882SGreg Clayton } 14961b654882SGreg Clayton 14971b654882SGreg Clayton if (*p == '\0') 14981b654882SGreg Clayton { 14991b654882SGreg Clayton break; 15001b654882SGreg Clayton } 15011b654882SGreg Clayton else if (*p == '{') 15021b654882SGreg Clayton { 15031b654882SGreg Clayton // Start a new scope that must have everything it needs if it is to 15041b654882SGreg Clayton // to make it into the final output stream "s". If you want to make 15051b654882SGreg Clayton // a format that only prints out the function or symbol name if there 15061b654882SGreg Clayton // is one in the symbol context you can use: 15071b654882SGreg Clayton // "{function =${function.name}}" 15081b654882SGreg Clayton // The first '{' starts a new scope that end with the matching '}' at 15091b654882SGreg Clayton // the end of the string. The contents "function =${function.name}" 15101b654882SGreg Clayton // will then be evaluated and only be output if there is a function 15111b654882SGreg Clayton // or symbol with a valid name. 15121b654882SGreg Clayton StreamString sub_strm; 15131b654882SGreg Clayton 15141b654882SGreg Clayton ++p; // Skip the '{' 15151b654882SGreg Clayton 1516c3ce7f27SMichael Sartain if (FormatPromptRecurse (p, sc, exe_ctx, addr, sub_strm, &p, valobj)) 15171b654882SGreg Clayton { 15181b654882SGreg Clayton // The stream had all it needed 15191b654882SGreg Clayton s.Write(sub_strm.GetData(), sub_strm.GetSize()); 15201b654882SGreg Clayton } 15211b654882SGreg Clayton if (*p != '}') 15221b654882SGreg Clayton { 15231b654882SGreg Clayton success = false; 15241b654882SGreg Clayton break; 15251b654882SGreg Clayton } 15261b654882SGreg Clayton } 15271b654882SGreg Clayton else if (*p == '}') 15281b654882SGreg Clayton { 15291b654882SGreg Clayton // End of a enclosing scope 15301b654882SGreg Clayton break; 15311b654882SGreg Clayton } 15321b654882SGreg Clayton else if (*p == '$') 15331b654882SGreg Clayton { 15341b654882SGreg Clayton // We have a prompt variable to print 15351b654882SGreg Clayton ++p; 15361b654882SGreg Clayton if (*p == '{') 15371b654882SGreg Clayton { 15381b654882SGreg Clayton ++p; 15391b654882SGreg Clayton const char *var_name_begin = p; 15401b654882SGreg Clayton const char *var_name_end = ::strchr (p, '}'); 15411b654882SGreg Clayton 15421b654882SGreg Clayton if (var_name_end && var_name_begin < var_name_end) 15431b654882SGreg Clayton { 15441b654882SGreg Clayton // if we have already failed to parse, skip this variable 15451b654882SGreg Clayton if (success) 15461b654882SGreg Clayton { 15471b654882SGreg Clayton const char *cstr = NULL; 15480769b2b1SMichael Sartain std::string token_format; 15491b654882SGreg Clayton Address format_addr; 15501b654882SGreg Clayton bool calculate_format_addr_function_offset = false; 15511b654882SGreg Clayton // Set reg_kind and reg_num to invalid values 15521b654882SGreg Clayton RegisterKind reg_kind = kNumRegisterKinds; 15531b654882SGreg Clayton uint32_t reg_num = LLDB_INVALID_REGNUM; 15541b654882SGreg Clayton FileSpec format_file_spec; 1555e0d378b3SGreg Clayton const RegisterInfo *reg_info = NULL; 15561b654882SGreg Clayton RegisterContext *reg_ctx = NULL; 15579fc1944eSEnrico Granata bool do_deref_pointer = false; 155886cc9829SEnrico Granata ValueObject::ExpressionPathScanEndReason reason_to_stop = ValueObject::eExpressionPathScanEndReasonEndOfString; 155986cc9829SEnrico Granata ValueObject::ExpressionPathEndResultType final_value_type = ValueObject::eExpressionPathEndResultTypePlain; 15601b654882SGreg Clayton 15611b654882SGreg Clayton // Each variable must set success to true below... 15621b654882SGreg Clayton bool var_success = false; 15631b654882SGreg Clayton switch (var_name_begin[0]) 15641b654882SGreg Clayton { 15654becb37eSEnrico Granata case '*': 15666f3533fbSEnrico Granata case 'v': 15676f3533fbSEnrico Granata case 's': 15684becb37eSEnrico Granata { 1569c482a192SEnrico Granata if (!valobj) 157034132754SGreg Clayton break; 15716f3533fbSEnrico Granata 1572c3e320a7SEnrico Granata if (log) 1573d228483dSEnrico Granata log->Printf("[Debugger::FormatPrompt] initial string: %s",var_name_begin); 1574c3e320a7SEnrico Granata 15756f3533fbSEnrico Granata // check for *var and *svar 15766f3533fbSEnrico Granata if (*var_name_begin == '*') 15776f3533fbSEnrico Granata { 15789fc1944eSEnrico Granata do_deref_pointer = true; 15799fc1944eSEnrico Granata var_name_begin++; 1580c3e320a7SEnrico Granata if (log) 158168ae4117SEnrico Granata log->Printf("[Debugger::FormatPrompt] found a deref, new string is: %s",var_name_begin); 158268ae4117SEnrico Granata } 1583c3e320a7SEnrico Granata 15846f3533fbSEnrico Granata if (*var_name_begin == 's') 15854becb37eSEnrico Granata { 1586c5bc412cSEnrico Granata if (!valobj->IsSynthetic()) 158786cc9829SEnrico Granata valobj = valobj->GetSyntheticValue().get(); 158886cc9829SEnrico Granata if (!valobj) 158986cc9829SEnrico Granata break; 15906f3533fbSEnrico Granata var_name_begin++; 1591c3e320a7SEnrico Granata if (log) 159268ae4117SEnrico Granata log->Printf("[Debugger::FormatPrompt] found a synthetic, new string is: %s",var_name_begin); 159368ae4117SEnrico Granata } 1594c3e320a7SEnrico Granata 15956f3533fbSEnrico Granata // should be a 'v' by now 15966f3533fbSEnrico Granata if (*var_name_begin != 'v') 15976f3533fbSEnrico Granata break; 15986f3533fbSEnrico Granata 1599c3e320a7SEnrico Granata if (log) 160068ae4117SEnrico Granata log->Printf("[Debugger::FormatPrompt] string I am working with: %s",var_name_begin); 1601c3e320a7SEnrico Granata 1602fc7a7f3bSEnrico Granata ValueObject::ExpressionPathAftermath what_next = (do_deref_pointer ? 160386cc9829SEnrico Granata ValueObject::eExpressionPathAftermathDereference : ValueObject::eExpressionPathAftermathNothing); 1604fc7a7f3bSEnrico Granata ValueObject::GetValueForExpressionPathOptions options; 16058c9d3560SEnrico Granata options.DontCheckDotVsArrowSyntax().DoAllowBitfieldSyntax().DoAllowFragileIVar().DoAllowSyntheticChildren(); 160686cc9829SEnrico Granata ValueObject::ValueObjectRepresentationStyle val_obj_display = ValueObject::eValueObjectRepresentationStyleSummary; 160734132754SGreg Clayton ValueObject* target = NULL; 16084d122c40SGreg Clayton Format custom_format = eFormatInvalid; 160934132754SGreg Clayton const char* var_name_final = NULL; 16109fc1944eSEnrico Granata const char* var_name_final_if_array_range = NULL; 161134132754SGreg Clayton const char* close_bracket_position = NULL; 161234132754SGreg Clayton int64_t index_lower = -1; 161334132754SGreg Clayton int64_t index_higher = -1; 16149fc1944eSEnrico Granata bool is_array_range = false; 1615fc7a7f3bSEnrico Granata const char* first_unparsed; 161685933ed4SEnrico Granata bool was_plain_var = false; 161785933ed4SEnrico Granata bool was_var_format = false; 1618a777dc2aSEnrico Granata bool was_var_indexed = false; 1619fc7a7f3bSEnrico Granata 1620c482a192SEnrico Granata if (!valobj) break; 1621c482a192SEnrico Granata // simplest case ${var}, just print valobj's value 16220769b2b1SMichael Sartain if (IsToken (var_name_begin, "var}")) 16230a3958e0SEnrico Granata { 162485933ed4SEnrico Granata was_plain_var = true; 1625c482a192SEnrico Granata target = valobj; 162686cc9829SEnrico Granata val_obj_display = ValueObject::eValueObjectRepresentationStyleValue; 16270a3958e0SEnrico Granata } 16280769b2b1SMichael Sartain else if (IsToken (var_name_begin,"var%")) 16299fc1944eSEnrico Granata { 163085933ed4SEnrico Granata was_var_format = true; 16319fc1944eSEnrico Granata // this is a variable with some custom format applied to it 16329fc1944eSEnrico Granata const char* percent_position; 1633c482a192SEnrico Granata target = valobj; 163486cc9829SEnrico Granata val_obj_display = ValueObject::eValueObjectRepresentationStyleValue; 16359fc1944eSEnrico Granata ScanFormatDescriptor (var_name_begin, 16369fc1944eSEnrico Granata var_name_end, 16379fc1944eSEnrico Granata &var_name_final, 16389fc1944eSEnrico Granata &percent_position, 16399fc1944eSEnrico Granata &custom_format, 16409fc1944eSEnrico Granata &val_obj_display); 16410a3958e0SEnrico Granata } 16429fc1944eSEnrico Granata // this is ${var.something} or multiple .something nested 16430769b2b1SMichael Sartain else if (IsToken (var_name_begin, "var")) 16449fc1944eSEnrico Granata { 16450769b2b1SMichael Sartain if (IsToken (var_name_begin, "var[")) 1646a777dc2aSEnrico Granata was_var_indexed = true; 16479fc1944eSEnrico Granata const char* percent_position; 16489fc1944eSEnrico Granata ScanFormatDescriptor (var_name_begin, 16499fc1944eSEnrico Granata var_name_end, 16509fc1944eSEnrico Granata &var_name_final, 16519fc1944eSEnrico Granata &percent_position, 16529fc1944eSEnrico Granata &custom_format, 16539fc1944eSEnrico Granata &val_obj_display); 16549fc1944eSEnrico Granata 16559fc1944eSEnrico Granata const char* open_bracket_position; 16569fc1944eSEnrico Granata const char* separator_position; 16579fc1944eSEnrico Granata ScanBracketedRange (var_name_begin, 16589fc1944eSEnrico Granata var_name_end, 16599fc1944eSEnrico Granata var_name_final, 16609fc1944eSEnrico Granata &open_bracket_position, 16619fc1944eSEnrico Granata &separator_position, 16629fc1944eSEnrico Granata &close_bracket_position, 16639fc1944eSEnrico Granata &var_name_final_if_array_range, 16649fc1944eSEnrico Granata &index_lower, 16659fc1944eSEnrico Granata &index_higher); 16669fc1944eSEnrico Granata 16679fc1944eSEnrico Granata Error error; 16689fc1944eSEnrico Granata 1669599171adSEnrico Granata std::string expr_path(var_name_final-var_name_begin-1,0); 1670599171adSEnrico Granata memcpy(&expr_path[0], var_name_begin+3,var_name_final-var_name_begin-3); 1671fc7a7f3bSEnrico Granata 1672e992a089SEnrico Granata if (log) 1673599171adSEnrico Granata log->Printf("[Debugger::FormatPrompt] symbol to expand: %s",expr_path.c_str()); 1674fc7a7f3bSEnrico Granata 1675599171adSEnrico Granata target = valobj->GetValueForExpressionPath(expr_path.c_str(), 1676fc7a7f3bSEnrico Granata &first_unparsed, 1677fc7a7f3bSEnrico Granata &reason_to_stop, 1678fc7a7f3bSEnrico Granata &final_value_type, 1679fc7a7f3bSEnrico Granata options, 1680fc7a7f3bSEnrico Granata &what_next).get(); 1681fc7a7f3bSEnrico Granata 1682fc7a7f3bSEnrico Granata if (!target) 16839fc1944eSEnrico Granata { 1684e992a089SEnrico Granata if (log) 1685d228483dSEnrico Granata log->Printf("[Debugger::FormatPrompt] ERROR: unparsed portion = %s, why stopping = %d," 1686e992a089SEnrico Granata " final_value_type %d", 1687fc7a7f3bSEnrico Granata first_unparsed, reason_to_stop, final_value_type); 1688fc7a7f3bSEnrico Granata break; 16890a3958e0SEnrico Granata } 1690a7187d00SEnrico Granata else 1691fc7a7f3bSEnrico Granata { 1692e992a089SEnrico Granata if (log) 1693d228483dSEnrico Granata log->Printf("[Debugger::FormatPrompt] ALL RIGHT: unparsed portion = %s, why stopping = %d," 1694e992a089SEnrico Granata " final_value_type %d", 1695fc7a7f3bSEnrico Granata first_unparsed, reason_to_stop, final_value_type); 1696a7187d00SEnrico Granata } 16970a3958e0SEnrico Granata } 16980a3958e0SEnrico Granata else 16990a3958e0SEnrico Granata break; 17009fc1944eSEnrico Granata 170186cc9829SEnrico Granata is_array_range = (final_value_type == ValueObject::eExpressionPathEndResultTypeBoundedRange || 170286cc9829SEnrico Granata final_value_type == ValueObject::eExpressionPathEndResultTypeUnboundedRange); 1703fc7a7f3bSEnrico Granata 170486cc9829SEnrico Granata do_deref_pointer = (what_next == ValueObject::eExpressionPathAftermathDereference); 1705fc7a7f3bSEnrico Granata 1706a7187d00SEnrico Granata if (do_deref_pointer && !is_array_range) 17070a3958e0SEnrico Granata { 17089fc1944eSEnrico Granata // I have not deref-ed yet, let's do it 17099fc1944eSEnrico Granata // this happens when we are not going through GetValueForVariableExpressionPath 17109fc1944eSEnrico Granata // to get to the target ValueObject 17119fc1944eSEnrico Granata Error error; 17129fc1944eSEnrico Granata target = target->Dereference(error).get(); 1713dc940730SEnrico Granata if (error.Fail()) 1714dc940730SEnrico Granata { 1715dc940730SEnrico Granata if (log) 1716d228483dSEnrico Granata log->Printf("[Debugger::FormatPrompt] ERROR: %s\n", error.AsCString("unknown")); \ 1717dc940730SEnrico Granata break; 1718dc940730SEnrico Granata } 17199fc1944eSEnrico Granata do_deref_pointer = false; 17200a3958e0SEnrico Granata } 17210a3958e0SEnrico Granata 1722a777dc2aSEnrico Granata // we do not want to use the summary for a bitfield of type T:n 1723a777dc2aSEnrico Granata // if we were originally dealing with just a T - that would get 1724a777dc2aSEnrico Granata // us into an endless recursion 1725a777dc2aSEnrico Granata if (target->IsBitfield() && was_var_indexed) 1726a777dc2aSEnrico Granata { 1727a777dc2aSEnrico Granata // TODO: check for a (T:n)-specific summary - we should still obey that 1728a777dc2aSEnrico Granata StreamString bitfield_name; 1729a777dc2aSEnrico Granata bitfield_name.Printf("%s:%d", target->GetTypeName().AsCString(), target->GetBitfieldBitSize()); 1730a777dc2aSEnrico Granata lldb::TypeNameSpecifierImplSP type_sp(new TypeNameSpecifierImpl(bitfield_name.GetData(),false)); 1731a777dc2aSEnrico Granata if (!DataVisualization::GetSummaryForType(type_sp)) 1732a777dc2aSEnrico Granata val_obj_display = ValueObject::eValueObjectRepresentationStyleValue; 1733a777dc2aSEnrico Granata } 1734a777dc2aSEnrico Granata 173585933ed4SEnrico Granata // TODO use flags for these 173657ee3067SGreg Clayton const uint32_t type_info_flags = target->GetClangType().GetTypeInfo(NULL); 173757ee3067SGreg Clayton bool is_array = (type_info_flags & ClangASTType::eTypeIsArray) != 0; 173857ee3067SGreg Clayton bool is_pointer = (type_info_flags & ClangASTType::eTypeIsPointer) != 0; 173957ee3067SGreg Clayton bool is_aggregate = target->GetClangType().IsAggregateType(); 1740f4efecd9SEnrico Granata 174186cc9829SEnrico Granata if ((is_array || is_pointer) && (!is_array_range) && val_obj_display == ValueObject::eValueObjectRepresentationStyleValue) // this should be wrong, but there are some exceptions 1742f4efecd9SEnrico Granata { 174385933ed4SEnrico Granata StreamString str_temp; 1744e992a089SEnrico Granata if (log) 1745d228483dSEnrico Granata log->Printf("[Debugger::FormatPrompt] I am into array || pointer && !range"); 1746d64d0bc0SEnrico Granata 17475088c486SGreg Clayton if (target->HasSpecialPrintableRepresentation(val_obj_display, custom_format)) 1748d64d0bc0SEnrico Granata { 1749f4efecd9SEnrico Granata // try to use the special cases 175085933ed4SEnrico Granata var_success = target->DumpPrintableRepresentation(str_temp, 175185933ed4SEnrico Granata val_obj_display, 175285933ed4SEnrico Granata custom_format); 1753e992a089SEnrico Granata if (log) 1754d228483dSEnrico Granata log->Printf("[Debugger::FormatPrompt] special cases did%s match", var_success ? "" : "n't"); 1755d64d0bc0SEnrico Granata 1756d64d0bc0SEnrico Granata // should not happen 17575088c486SGreg Clayton if (var_success) 175885933ed4SEnrico Granata s << str_temp.GetData(); 1759d64d0bc0SEnrico Granata var_success = true; 1760d64d0bc0SEnrico Granata break; 1761d64d0bc0SEnrico Granata } 1762d64d0bc0SEnrico Granata else 1763d64d0bc0SEnrico Granata { 176488da35f8SEnrico Granata if (was_plain_var) // if ${var} 1765d64d0bc0SEnrico Granata { 1766d64d0bc0SEnrico Granata s << target->GetTypeName() << " @ " << target->GetLocationAsCString(); 1767d64d0bc0SEnrico Granata } 176888da35f8SEnrico Granata else if (is_pointer) // if pointer, value is the address stored 176988da35f8SEnrico Granata { 177023f59509SGreg Clayton target->DumpPrintableRepresentation (s, 177188da35f8SEnrico Granata val_obj_display, 177286cc9829SEnrico Granata custom_format, 177386cc9829SEnrico Granata ValueObject::ePrintableRepresentationSpecialCasesDisable); 177488da35f8SEnrico Granata } 1775d64d0bc0SEnrico Granata var_success = true; 1776d64d0bc0SEnrico Granata break; 1777d64d0bc0SEnrico Granata } 1778d64d0bc0SEnrico Granata } 1779d64d0bc0SEnrico Granata 1780d64d0bc0SEnrico Granata // if directly trying to print ${var}, and this is an aggregate, display a nice 1781d64d0bc0SEnrico Granata // type @ location message 1782d64d0bc0SEnrico Granata if (is_aggregate && was_plain_var) 1783d64d0bc0SEnrico Granata { 1784d64d0bc0SEnrico Granata s << target->GetTypeName() << " @ " << target->GetLocationAsCString(); 1785d64d0bc0SEnrico Granata var_success = true; 178685933ed4SEnrico Granata break; 178785933ed4SEnrico Granata } 178885933ed4SEnrico Granata 1789d64d0bc0SEnrico Granata // if directly trying to print ${var%V}, and this is an aggregate, do not let the user do it 179086cc9829SEnrico Granata if (is_aggregate && ((was_var_format && val_obj_display == ValueObject::eValueObjectRepresentationStyleValue))) 179185933ed4SEnrico Granata { 179285933ed4SEnrico Granata s << "<invalid use of aggregate type>"; 179385933ed4SEnrico Granata var_success = true; 1794f4efecd9SEnrico Granata break; 1795f4efecd9SEnrico Granata } 1796f4efecd9SEnrico Granata 17979fc1944eSEnrico Granata if (!is_array_range) 1798e992a089SEnrico Granata { 1799e992a089SEnrico Granata if (log) 1800d228483dSEnrico Granata log->Printf("[Debugger::FormatPrompt] dumping ordinary printable output"); 18019fc1944eSEnrico Granata var_success = target->DumpPrintableRepresentation(s,val_obj_display, custom_format); 1802e992a089SEnrico Granata } 18039fc1944eSEnrico Granata else 18049fc1944eSEnrico Granata { 1805e992a089SEnrico Granata if (log) 1806d228483dSEnrico Granata log->Printf("[Debugger::FormatPrompt] checking if I can handle as array"); 18079fc1944eSEnrico Granata if (!is_array && !is_pointer) 18089fc1944eSEnrico Granata break; 1809e992a089SEnrico Granata if (log) 1810d228483dSEnrico Granata log->Printf("[Debugger::FormatPrompt] handle as array"); 1811fc7a7f3bSEnrico Granata const char* special_directions = NULL; 1812fc7a7f3bSEnrico Granata StreamString special_directions_writer; 18130a3958e0SEnrico Granata if (close_bracket_position && (var_name_end-close_bracket_position > 1)) 18140a3958e0SEnrico Granata { 1815fc7a7f3bSEnrico Granata ConstString additional_data; 1816fc7a7f3bSEnrico Granata additional_data.SetCStringWithLength(close_bracket_position+1, var_name_end-close_bracket_position-1); 1817fc7a7f3bSEnrico Granata special_directions_writer.Printf("${%svar%s}", 1818fc7a7f3bSEnrico Granata do_deref_pointer ? "*" : "", 1819fc7a7f3bSEnrico Granata additional_data.GetCString()); 1820fc7a7f3bSEnrico Granata special_directions = special_directions_writer.GetData(); 18210a3958e0SEnrico Granata } 18220a3958e0SEnrico Granata 18230a3958e0SEnrico Granata // let us display items index_lower thru index_higher of this array 18240a3958e0SEnrico Granata s.PutChar('['); 18250a3958e0SEnrico Granata var_success = true; 18260a3958e0SEnrico Granata 18279fc1944eSEnrico Granata if (index_higher < 0) 1828c482a192SEnrico Granata index_higher = valobj->GetNumChildren() - 1; 18290a3958e0SEnrico Granata 1830cc4d0146SGreg Clayton uint32_t max_num_children = target->GetTargetSP()->GetMaximumNumberOfChildrenToDisplay(); 183122c55d18SEnrico Granata 18320a3958e0SEnrico Granata for (;index_lower<=index_higher;index_lower++) 18330a3958e0SEnrico Granata { 1834fc7a7f3bSEnrico Granata ValueObject* item = ExpandIndexedExpression (target, 18359fc1944eSEnrico Granata index_lower, 1836c14ee32dSGreg Clayton exe_ctx->GetFramePtr(), 1837fc7a7f3bSEnrico Granata false).get(); 18380a3958e0SEnrico Granata 1839fc7a7f3bSEnrico Granata if (!item) 1840fc7a7f3bSEnrico Granata { 1841e992a089SEnrico Granata if (log) 1842d01b2953SDaniel Malea log->Printf("[Debugger::FormatPrompt] ERROR in getting child item at index %" PRId64, index_lower); 1843fc7a7f3bSEnrico Granata } 1844fc7a7f3bSEnrico Granata else 1845fc7a7f3bSEnrico Granata { 1846e992a089SEnrico Granata if (log) 1847d228483dSEnrico Granata log->Printf("[Debugger::FormatPrompt] special_directions for child item: %s",special_directions); 1848fc7a7f3bSEnrico Granata } 1849fc7a7f3bSEnrico Granata 18500a3958e0SEnrico Granata if (!special_directions) 18519fc1944eSEnrico Granata var_success &= item->DumpPrintableRepresentation(s,val_obj_display, custom_format); 18520a3958e0SEnrico Granata else 1853c3ce7f27SMichael Sartain var_success &= FormatPromptRecurse(special_directions, sc, exe_ctx, addr, s, NULL, item); 18540a3958e0SEnrico Granata 185522c55d18SEnrico Granata if (--max_num_children == 0) 185622c55d18SEnrico Granata { 185722c55d18SEnrico Granata s.PutCString(", ..."); 185822c55d18SEnrico Granata break; 185922c55d18SEnrico Granata } 186022c55d18SEnrico Granata 18610a3958e0SEnrico Granata if (index_lower < index_higher) 18620a3958e0SEnrico Granata s.PutChar(','); 18630a3958e0SEnrico Granata } 18640a3958e0SEnrico Granata s.PutChar(']'); 18654becb37eSEnrico Granata } 18664becb37eSEnrico Granata } 186734132754SGreg Clayton break; 18681b654882SGreg Clayton case 'a': 18690769b2b1SMichael Sartain if (IsToken (var_name_begin, "addr}")) 18701b654882SGreg Clayton { 18711b654882SGreg Clayton if (addr && addr->IsValid()) 18721b654882SGreg Clayton { 18731b654882SGreg Clayton var_success = true; 18741b654882SGreg Clayton format_addr = *addr; 18751b654882SGreg Clayton } 18761b654882SGreg Clayton } 18771b654882SGreg Clayton break; 18781b654882SGreg Clayton 18791b654882SGreg Clayton case 'p': 18800769b2b1SMichael Sartain if (IsToken (var_name_begin, "process.")) 18811b654882SGreg Clayton { 1882c14ee32dSGreg Clayton if (exe_ctx) 1883c14ee32dSGreg Clayton { 1884c14ee32dSGreg Clayton Process *process = exe_ctx->GetProcessPtr(); 1885c14ee32dSGreg Clayton if (process) 18861b654882SGreg Clayton { 18871b654882SGreg Clayton var_name_begin += ::strlen ("process."); 18880769b2b1SMichael Sartain if (IsTokenWithFormat (var_name_begin, "id", token_format, "%" PRIu64, exe_ctx, sc)) 18891b654882SGreg Clayton { 18900769b2b1SMichael Sartain s.Printf(token_format.c_str(), process->GetID()); 18911b654882SGreg Clayton var_success = true; 18921b654882SGreg Clayton } 18930769b2b1SMichael Sartain else if ((IsToken (var_name_begin, "name}")) || 18940769b2b1SMichael Sartain (IsToken (var_name_begin, "file.basename}")) || 18950769b2b1SMichael Sartain (IsToken (var_name_begin, "file.fullpath}"))) 18961b654882SGreg Clayton { 1897c14ee32dSGreg Clayton Module *exe_module = process->GetTarget().GetExecutableModulePointer(); 1898aa149cbdSGreg Clayton if (exe_module) 18991b654882SGreg Clayton { 19001b654882SGreg Clayton if (var_name_begin[0] == 'n' || var_name_begin[5] == 'f') 19011b654882SGreg Clayton { 1902aa149cbdSGreg Clayton format_file_spec.GetFilename() = exe_module->GetFileSpec().GetFilename(); 19031b654882SGreg Clayton var_success = format_file_spec; 19041b654882SGreg Clayton } 19051b654882SGreg Clayton else 19061b654882SGreg Clayton { 1907aa149cbdSGreg Clayton format_file_spec = exe_module->GetFileSpec(); 19081b654882SGreg Clayton var_success = format_file_spec; 19091b654882SGreg Clayton } 19101b654882SGreg Clayton } 19111b654882SGreg Clayton } 19120769b2b1SMichael Sartain else if (IsToken (var_name_begin, "script:")) 1913aad8e480SEnrico Granata { 1914aad8e480SEnrico Granata var_name_begin += ::strlen("script:"); 1915aad8e480SEnrico Granata std::string script_name(var_name_begin,var_name_end); 1916aad8e480SEnrico Granata ScriptInterpreter* script_interpreter = process->GetTarget().GetDebugger().GetCommandInterpreter().GetScriptInterpreter(); 19170769b2b1SMichael Sartain if (RunScriptFormatKeyword (s, script_interpreter, process, script_name)) 1918aad8e480SEnrico Granata var_success = true; 1919aad8e480SEnrico Granata } 19201b654882SGreg Clayton } 19211b654882SGreg Clayton } 1922c14ee32dSGreg Clayton } 19231b654882SGreg Clayton break; 19241b654882SGreg Clayton 19251b654882SGreg Clayton case 't': 19260769b2b1SMichael Sartain if (IsToken (var_name_begin, "thread.")) 19271b654882SGreg Clayton { 1928c14ee32dSGreg Clayton if (exe_ctx) 1929c14ee32dSGreg Clayton { 1930c14ee32dSGreg Clayton Thread *thread = exe_ctx->GetThreadPtr(); 1931c14ee32dSGreg Clayton if (thread) 19321b654882SGreg Clayton { 19331b654882SGreg Clayton var_name_begin += ::strlen ("thread."); 19340769b2b1SMichael Sartain if (IsTokenWithFormat (var_name_begin, "id", token_format, "0x%4.4" PRIx64, exe_ctx, sc)) 19351b654882SGreg Clayton { 19360769b2b1SMichael Sartain s.Printf(token_format.c_str(), thread->GetID()); 19371b654882SGreg Clayton var_success = true; 19381b654882SGreg Clayton } 19390769b2b1SMichael Sartain else if (IsTokenWithFormat (var_name_begin, "protocol_id", token_format, "0x%4.4" PRIx64, exe_ctx, sc)) 1940160c9d81SGreg Clayton { 19410769b2b1SMichael Sartain s.Printf(token_format.c_str(), thread->GetProtocolID()); 1942160c9d81SGreg Clayton var_success = true; 1943160c9d81SGreg Clayton } 19440769b2b1SMichael Sartain else if (IsTokenWithFormat (var_name_begin, "index", token_format, "%" PRIu64, exe_ctx, sc)) 19451b654882SGreg Clayton { 19460769b2b1SMichael Sartain s.Printf(token_format.c_str(), (uint64_t)thread->GetIndexID()); 19471b654882SGreg Clayton var_success = true; 19481b654882SGreg Clayton } 19490769b2b1SMichael Sartain else if (IsToken (var_name_begin, "name}")) 19501b654882SGreg Clayton { 1951c14ee32dSGreg Clayton cstr = thread->GetName(); 19521b654882SGreg Clayton var_success = cstr && cstr[0]; 19531b654882SGreg Clayton if (var_success) 19541b654882SGreg Clayton s.PutCString(cstr); 19551b654882SGreg Clayton } 19560769b2b1SMichael Sartain else if (IsToken (var_name_begin, "queue}")) 19571b654882SGreg Clayton { 1958c14ee32dSGreg Clayton cstr = thread->GetQueueName(); 19591b654882SGreg Clayton var_success = cstr && cstr[0]; 19601b654882SGreg Clayton if (var_success) 19611b654882SGreg Clayton s.PutCString(cstr); 19621b654882SGreg Clayton } 19630769b2b1SMichael Sartain else if (IsToken (var_name_begin, "stop-reason}")) 19641b654882SGreg Clayton { 1965c14ee32dSGreg Clayton StopInfoSP stop_info_sp = thread->GetStopInfo (); 19665d88a068SJim Ingham if (stop_info_sp && stop_info_sp->IsValid()) 19671b654882SGreg Clayton { 1968b15bfc75SJim Ingham cstr = stop_info_sp->GetDescription(); 19691b654882SGreg Clayton if (cstr && cstr[0]) 19701b654882SGreg Clayton { 19711b654882SGreg Clayton s.PutCString(cstr); 19721b654882SGreg Clayton var_success = true; 19731b654882SGreg Clayton } 19741b654882SGreg Clayton } 19751b654882SGreg Clayton } 19760769b2b1SMichael Sartain else if (IsToken (var_name_begin, "return-value}")) 197773ca05a2SJim Ingham { 197873ca05a2SJim Ingham StopInfoSP stop_info_sp = thread->GetStopInfo (); 19795d88a068SJim Ingham if (stop_info_sp && stop_info_sp->IsValid()) 198073ca05a2SJim Ingham { 198173ca05a2SJim Ingham ValueObjectSP return_valobj_sp = StopInfo::GetReturnValueObject (stop_info_sp); 198273ca05a2SJim Ingham if (return_valobj_sp) 198373ca05a2SJim Ingham { 1984*4d93b8cdSEnrico Granata return_valobj_sp->Dump(s); 198573ca05a2SJim Ingham var_success = true; 198673ca05a2SJim Ingham } 198773ca05a2SJim Ingham } 198873ca05a2SJim Ingham } 19890769b2b1SMichael Sartain else if (IsToken (var_name_begin, "script:")) 1990aad8e480SEnrico Granata { 1991aad8e480SEnrico Granata var_name_begin += ::strlen("script:"); 1992aad8e480SEnrico Granata std::string script_name(var_name_begin,var_name_end); 1993aad8e480SEnrico Granata ScriptInterpreter* script_interpreter = thread->GetProcess()->GetTarget().GetDebugger().GetCommandInterpreter().GetScriptInterpreter(); 19940769b2b1SMichael Sartain if (RunScriptFormatKeyword (s, script_interpreter, thread, script_name)) 1995aad8e480SEnrico Granata var_success = true; 1996aad8e480SEnrico Granata } 1997aad8e480SEnrico Granata } 1998aad8e480SEnrico Granata } 199973ca05a2SJim Ingham } 20000769b2b1SMichael Sartain else if (IsToken (var_name_begin, "target.")) 20011b654882SGreg Clayton { 200267cc0636SGreg Clayton // TODO: hookup properties 200367cc0636SGreg Clayton // if (!target_properties_sp) 200467cc0636SGreg Clayton // { 200567cc0636SGreg Clayton // Target *target = Target::GetTargetFromContexts (exe_ctx, sc); 200667cc0636SGreg Clayton // if (target) 200767cc0636SGreg Clayton // target_properties_sp = target->GetProperties(); 200867cc0636SGreg Clayton // } 200967cc0636SGreg Clayton // 201067cc0636SGreg Clayton // if (target_properties_sp) 201167cc0636SGreg Clayton // { 201267cc0636SGreg Clayton // var_name_begin += ::strlen ("target."); 201367cc0636SGreg Clayton // const char *end_property = strchr(var_name_begin, '}'); 201467cc0636SGreg Clayton // if (end_property) 201567cc0636SGreg Clayton // { 201667cc0636SGreg Clayton // ConstString property_name(var_name_begin, end_property - var_name_begin); 201767cc0636SGreg Clayton // std::string property_value (target_properties_sp->GetPropertyValue(property_name)); 201867cc0636SGreg Clayton // if (!property_value.empty()) 201967cc0636SGreg Clayton // { 202067cc0636SGreg Clayton // s.PutCString (property_value.c_str()); 202167cc0636SGreg Clayton // var_success = true; 202267cc0636SGreg Clayton // } 202367cc0636SGreg Clayton // } 202467cc0636SGreg Clayton // } 20250603aa9dSGreg Clayton Target *target = Target::GetTargetFromContexts (exe_ctx, sc); 20260603aa9dSGreg Clayton if (target) 20271b654882SGreg Clayton { 20281b654882SGreg Clayton var_name_begin += ::strlen ("target."); 20290769b2b1SMichael Sartain if (IsToken (var_name_begin, "arch}")) 20301b654882SGreg Clayton { 20311b654882SGreg Clayton ArchSpec arch (target->GetArchitecture ()); 20321b654882SGreg Clayton if (arch.IsValid()) 20331b654882SGreg Clayton { 203464195a2cSGreg Clayton s.PutCString (arch.GetArchitectureName()); 20351b654882SGreg Clayton var_success = true; 20361b654882SGreg Clayton } 20371b654882SGreg Clayton } 20380769b2b1SMichael Sartain else if (IsToken (var_name_begin, "script:")) 2039aad8e480SEnrico Granata { 2040aad8e480SEnrico Granata var_name_begin += ::strlen("script:"); 2041aad8e480SEnrico Granata std::string script_name(var_name_begin,var_name_end); 2042aad8e480SEnrico Granata ScriptInterpreter* script_interpreter = target->GetDebugger().GetCommandInterpreter().GetScriptInterpreter(); 20430769b2b1SMichael Sartain if (RunScriptFormatKeyword (s, script_interpreter, target, script_name)) 2044aad8e480SEnrico Granata var_success = true; 2045aad8e480SEnrico Granata } 20461b654882SGreg Clayton } 20471b654882SGreg Clayton } 20481b654882SGreg Clayton break; 20491b654882SGreg Clayton 20501b654882SGreg Clayton 20511b654882SGreg Clayton case 'm': 20520769b2b1SMichael Sartain if (IsToken (var_name_begin, "module.")) 20531b654882SGreg Clayton { 20540603aa9dSGreg Clayton if (sc && sc->module_sp.get()) 20551b654882SGreg Clayton { 20560603aa9dSGreg Clayton Module *module = sc->module_sp.get(); 20571b654882SGreg Clayton var_name_begin += ::strlen ("module."); 20581b654882SGreg Clayton 20590769b2b1SMichael Sartain if (IsToken (var_name_begin, "file.")) 20601b654882SGreg Clayton { 20611b654882SGreg Clayton if (module->GetFileSpec()) 20621b654882SGreg Clayton { 20631b654882SGreg Clayton var_name_begin += ::strlen ("file."); 20641b654882SGreg Clayton 20650769b2b1SMichael Sartain if (IsToken (var_name_begin, "basename}")) 20661b654882SGreg Clayton { 20671b654882SGreg Clayton format_file_spec.GetFilename() = module->GetFileSpec().GetFilename(); 20681b654882SGreg Clayton var_success = format_file_spec; 20691b654882SGreg Clayton } 20700769b2b1SMichael Sartain else if (IsToken (var_name_begin, "fullpath}")) 20711b654882SGreg Clayton { 20721b654882SGreg Clayton format_file_spec = module->GetFileSpec(); 20731b654882SGreg Clayton var_success = format_file_spec; 20741b654882SGreg Clayton } 20751b654882SGreg Clayton } 20761b654882SGreg Clayton } 20771b654882SGreg Clayton } 20781b654882SGreg Clayton } 20791b654882SGreg Clayton break; 20801b654882SGreg Clayton 20811b654882SGreg Clayton 20821b654882SGreg Clayton case 'f': 20830769b2b1SMichael Sartain if (IsToken (var_name_begin, "file.")) 20841b654882SGreg Clayton { 20851b654882SGreg Clayton if (sc && sc->comp_unit != NULL) 20861b654882SGreg Clayton { 20871b654882SGreg Clayton var_name_begin += ::strlen ("file."); 20881b654882SGreg Clayton 20890769b2b1SMichael Sartain if (IsToken (var_name_begin, "basename}")) 20901b654882SGreg Clayton { 20911b654882SGreg Clayton format_file_spec.GetFilename() = sc->comp_unit->GetFilename(); 20921b654882SGreg Clayton var_success = format_file_spec; 20931b654882SGreg Clayton } 20940769b2b1SMichael Sartain else if (IsToken (var_name_begin, "fullpath}")) 20951b654882SGreg Clayton { 20961b654882SGreg Clayton format_file_spec = *sc->comp_unit; 20971b654882SGreg Clayton var_success = format_file_spec; 20981b654882SGreg Clayton } 20991b654882SGreg Clayton } 21001b654882SGreg Clayton } 21010769b2b1SMichael Sartain else if (IsToken (var_name_begin, "frame.")) 21021b654882SGreg Clayton { 2103c14ee32dSGreg Clayton if (exe_ctx) 2104c14ee32dSGreg Clayton { 2105c14ee32dSGreg Clayton StackFrame *frame = exe_ctx->GetFramePtr(); 2106c14ee32dSGreg Clayton if (frame) 21071b654882SGreg Clayton { 21081b654882SGreg Clayton var_name_begin += ::strlen ("frame."); 21090769b2b1SMichael Sartain if (IsToken (var_name_begin, "index}")) 21101b654882SGreg Clayton { 2111c14ee32dSGreg Clayton s.Printf("%u", frame->GetFrameIndex()); 21121b654882SGreg Clayton var_success = true; 21131b654882SGreg Clayton } 21140769b2b1SMichael Sartain else if (IsToken (var_name_begin, "pc}")) 21151b654882SGreg Clayton { 21161b654882SGreg Clayton reg_kind = eRegisterKindGeneric; 21171b654882SGreg Clayton reg_num = LLDB_REGNUM_GENERIC_PC; 21181b654882SGreg Clayton var_success = true; 21191b654882SGreg Clayton } 21200769b2b1SMichael Sartain else if (IsToken (var_name_begin, "sp}")) 21211b654882SGreg Clayton { 21221b654882SGreg Clayton reg_kind = eRegisterKindGeneric; 21231b654882SGreg Clayton reg_num = LLDB_REGNUM_GENERIC_SP; 21241b654882SGreg Clayton var_success = true; 21251b654882SGreg Clayton } 21260769b2b1SMichael Sartain else if (IsToken (var_name_begin, "fp}")) 21271b654882SGreg Clayton { 21281b654882SGreg Clayton reg_kind = eRegisterKindGeneric; 21291b654882SGreg Clayton reg_num = LLDB_REGNUM_GENERIC_FP; 21301b654882SGreg Clayton var_success = true; 21311b654882SGreg Clayton } 21320769b2b1SMichael Sartain else if (IsToken (var_name_begin, "flags}")) 21331b654882SGreg Clayton { 21341b654882SGreg Clayton reg_kind = eRegisterKindGeneric; 21351b654882SGreg Clayton reg_num = LLDB_REGNUM_GENERIC_FLAGS; 21361b654882SGreg Clayton var_success = true; 21371b654882SGreg Clayton } 21380769b2b1SMichael Sartain else if (IsToken (var_name_begin, "reg.")) 21391b654882SGreg Clayton { 2140c14ee32dSGreg Clayton reg_ctx = frame->GetRegisterContext().get(); 21411b654882SGreg Clayton if (reg_ctx) 21421b654882SGreg Clayton { 21431b654882SGreg Clayton var_name_begin += ::strlen ("reg."); 21441b654882SGreg Clayton if (var_name_begin < var_name_end) 21451b654882SGreg Clayton { 21461b654882SGreg Clayton std::string reg_name (var_name_begin, var_name_end); 21471b654882SGreg Clayton reg_info = reg_ctx->GetRegisterInfoByName (reg_name.c_str()); 21481b654882SGreg Clayton if (reg_info) 21491b654882SGreg Clayton var_success = true; 21501b654882SGreg Clayton } 21511b654882SGreg Clayton } 21521b654882SGreg Clayton } 21530769b2b1SMichael Sartain else if (IsToken (var_name_begin, "script:")) 2154aad8e480SEnrico Granata { 2155aad8e480SEnrico Granata var_name_begin += ::strlen("script:"); 2156aad8e480SEnrico Granata std::string script_name(var_name_begin,var_name_end); 2157aad8e480SEnrico Granata ScriptInterpreter* script_interpreter = frame->GetThread()->GetProcess()->GetTarget().GetDebugger().GetCommandInterpreter().GetScriptInterpreter(); 21580769b2b1SMichael Sartain if (RunScriptFormatKeyword (s, script_interpreter, frame, script_name)) 2159aad8e480SEnrico Granata var_success = true; 2160aad8e480SEnrico Granata } 2161aad8e480SEnrico Granata } 2162aad8e480SEnrico Granata } 21631b654882SGreg Clayton } 21640769b2b1SMichael Sartain else if (IsToken (var_name_begin, "function.")) 21651b654882SGreg Clayton { 21661b654882SGreg Clayton if (sc && (sc->function != NULL || sc->symbol != NULL)) 21671b654882SGreg Clayton { 21681b654882SGreg Clayton var_name_begin += ::strlen ("function."); 21690769b2b1SMichael Sartain if (IsToken (var_name_begin, "id}")) 21701b654882SGreg Clayton { 21711b654882SGreg Clayton if (sc->function) 2172d01b2953SDaniel Malea s.Printf("function{0x%8.8" PRIx64 "}", sc->function->GetID()); 21731b654882SGreg Clayton else 21741b654882SGreg Clayton s.Printf("symbol[%u]", sc->symbol->GetID()); 21751b654882SGreg Clayton 21761b654882SGreg Clayton var_success = true; 21771b654882SGreg Clayton } 21780769b2b1SMichael Sartain else if (IsToken (var_name_begin, "name}")) 21791b654882SGreg Clayton { 21801b654882SGreg Clayton if (sc->function) 21811b654882SGreg Clayton cstr = sc->function->GetName().AsCString (NULL); 21821b654882SGreg Clayton else if (sc->symbol) 21831b654882SGreg Clayton cstr = sc->symbol->GetName().AsCString (NULL); 21841b654882SGreg Clayton if (cstr) 21851b654882SGreg Clayton { 21861b654882SGreg Clayton s.PutCString(cstr); 21870d9c9934SGreg Clayton 21880d9c9934SGreg Clayton if (sc->block) 21890d9c9934SGreg Clayton { 21900d9c9934SGreg Clayton Block *inline_block = sc->block->GetContainingInlinedBlock (); 21910d9c9934SGreg Clayton if (inline_block) 21920d9c9934SGreg Clayton { 21930d9c9934SGreg Clayton const InlineFunctionInfo *inline_info = sc->block->GetInlinedFunctionInfo(); 21940d9c9934SGreg Clayton if (inline_info) 21950d9c9934SGreg Clayton { 21960d9c9934SGreg Clayton s.PutCString(" [inlined] "); 21970d9c9934SGreg Clayton inline_info->GetName().Dump(&s); 21980d9c9934SGreg Clayton } 21990d9c9934SGreg Clayton } 22000d9c9934SGreg Clayton } 22011b654882SGreg Clayton var_success = true; 22021b654882SGreg Clayton } 22031b654882SGreg Clayton } 22040769b2b1SMichael Sartain else if (IsToken (var_name_begin, "name-with-args}")) 22056d3dbf51SGreg Clayton { 22066d3dbf51SGreg Clayton // Print the function name with arguments in it 22076d3dbf51SGreg Clayton 22086d3dbf51SGreg Clayton if (sc->function) 22096d3dbf51SGreg Clayton { 22106d3dbf51SGreg Clayton var_success = true; 22116d3dbf51SGreg Clayton ExecutionContextScope *exe_scope = exe_ctx ? exe_ctx->GetBestExecutionContextScope() : NULL; 22126d3dbf51SGreg Clayton cstr = sc->function->GetName().AsCString (NULL); 22136d3dbf51SGreg Clayton if (cstr) 22146d3dbf51SGreg Clayton { 22156d3dbf51SGreg Clayton const InlineFunctionInfo *inline_info = NULL; 22166d3dbf51SGreg Clayton VariableListSP variable_list_sp; 22176d3dbf51SGreg Clayton bool get_function_vars = true; 22186d3dbf51SGreg Clayton if (sc->block) 22196d3dbf51SGreg Clayton { 22206d3dbf51SGreg Clayton Block *inline_block = sc->block->GetContainingInlinedBlock (); 22216d3dbf51SGreg Clayton 22226d3dbf51SGreg Clayton if (inline_block) 22236d3dbf51SGreg Clayton { 22246d3dbf51SGreg Clayton get_function_vars = false; 22256d3dbf51SGreg Clayton inline_info = sc->block->GetInlinedFunctionInfo(); 22266d3dbf51SGreg Clayton if (inline_info) 22276d3dbf51SGreg Clayton variable_list_sp = inline_block->GetBlockVariableList (true); 22286d3dbf51SGreg Clayton } 22296d3dbf51SGreg Clayton } 22306d3dbf51SGreg Clayton 22316d3dbf51SGreg Clayton if (get_function_vars) 22326d3dbf51SGreg Clayton { 22336d3dbf51SGreg Clayton variable_list_sp = sc->function->GetBlock(true).GetBlockVariableList (true); 22346d3dbf51SGreg Clayton } 22356d3dbf51SGreg Clayton 22366d3dbf51SGreg Clayton if (inline_info) 22376d3dbf51SGreg Clayton { 22386d3dbf51SGreg Clayton s.PutCString (cstr); 22396d3dbf51SGreg Clayton s.PutCString (" [inlined] "); 22406d3dbf51SGreg Clayton cstr = inline_info->GetName().GetCString(); 22416d3dbf51SGreg Clayton } 22426d3dbf51SGreg Clayton 22436d3dbf51SGreg Clayton VariableList args; 22446d3dbf51SGreg Clayton if (variable_list_sp) 2245cc7f9bf5SEnrico Granata variable_list_sp->AppendVariablesWithScope(eValueTypeVariableArgument, args); 22466d3dbf51SGreg Clayton if (args.GetSize() > 0) 22476d3dbf51SGreg Clayton { 22486d3dbf51SGreg Clayton const char *open_paren = strchr (cstr, '('); 22496d3dbf51SGreg Clayton const char *close_paren = NULL; 22506d3dbf51SGreg Clayton if (open_paren) 2251855958caSGreg Clayton { 22520769b2b1SMichael Sartain if (IsToken (open_paren, "(anonymous namespace)")) 2253855958caSGreg Clayton { 2254855958caSGreg Clayton open_paren = strchr (open_paren + strlen("(anonymous namespace)"), '('); 2255855958caSGreg Clayton if (open_paren) 22566d3dbf51SGreg Clayton close_paren = strchr (open_paren, ')'); 2257855958caSGreg Clayton } 2258855958caSGreg Clayton else 2259855958caSGreg Clayton close_paren = strchr (open_paren, ')'); 2260855958caSGreg Clayton } 22616d3dbf51SGreg Clayton 22626d3dbf51SGreg Clayton if (open_paren) 22636d3dbf51SGreg Clayton s.Write(cstr, open_paren - cstr + 1); 22646d3dbf51SGreg Clayton else 22656d3dbf51SGreg Clayton { 22666d3dbf51SGreg Clayton s.PutCString (cstr); 22676d3dbf51SGreg Clayton s.PutChar ('('); 22686d3dbf51SGreg Clayton } 22695b6889b1SGreg Clayton const size_t num_args = args.GetSize(); 22706d3dbf51SGreg Clayton for (size_t arg_idx = 0; arg_idx < num_args; ++arg_idx) 22716d3dbf51SGreg Clayton { 22726d3dbf51SGreg Clayton VariableSP var_sp (args.GetVariableAtIndex (arg_idx)); 22736d3dbf51SGreg Clayton ValueObjectSP var_value_sp (ValueObjectVariable::Create (exe_scope, var_sp)); 22746d3dbf51SGreg Clayton const char *var_name = var_value_sp->GetName().GetCString(); 22756d3dbf51SGreg Clayton const char *var_value = var_value_sp->GetValueAsCString(); 22766d3dbf51SGreg Clayton if (arg_idx > 0) 22776d3dbf51SGreg Clayton s.PutCString (", "); 22783b188b17SGreg Clayton if (var_value_sp->GetError().Success()) 2279cc7f9bf5SEnrico Granata { 2280cc7f9bf5SEnrico Granata if (var_value) 22816d3dbf51SGreg Clayton s.Printf ("%s=%s", var_name, var_value); 22823b188b17SGreg Clayton else 2283cc7f9bf5SEnrico Granata s.Printf ("%s=%s at %s", var_name, var_value_sp->GetTypeName().GetCString(), var_value_sp->GetLocationAsCString()); 2284cc7f9bf5SEnrico Granata } 2285cc7f9bf5SEnrico Granata else 22863b188b17SGreg Clayton s.Printf ("%s=<unavailable>", var_name); 22876d3dbf51SGreg Clayton } 22886d3dbf51SGreg Clayton 22896d3dbf51SGreg Clayton if (close_paren) 22906d3dbf51SGreg Clayton s.PutCString (close_paren); 22916d3dbf51SGreg Clayton else 22926d3dbf51SGreg Clayton s.PutChar(')'); 22936d3dbf51SGreg Clayton 22946d3dbf51SGreg Clayton } 22956d3dbf51SGreg Clayton else 22966d3dbf51SGreg Clayton { 22976d3dbf51SGreg Clayton s.PutCString(cstr); 22986d3dbf51SGreg Clayton } 22996d3dbf51SGreg Clayton } 23006d3dbf51SGreg Clayton } 23016d3dbf51SGreg Clayton else if (sc->symbol) 23026d3dbf51SGreg Clayton { 23036d3dbf51SGreg Clayton cstr = sc->symbol->GetName().AsCString (NULL); 23046d3dbf51SGreg Clayton if (cstr) 23056d3dbf51SGreg Clayton { 23066d3dbf51SGreg Clayton s.PutCString(cstr); 23076d3dbf51SGreg Clayton var_success = true; 23086d3dbf51SGreg Clayton } 23096d3dbf51SGreg Clayton } 23106d3dbf51SGreg Clayton } 23110769b2b1SMichael Sartain else if (IsToken (var_name_begin, "addr-offset}")) 23121b654882SGreg Clayton { 23131b654882SGreg Clayton var_success = addr != NULL; 23141b654882SGreg Clayton if (var_success) 23151b654882SGreg Clayton { 23161b654882SGreg Clayton format_addr = *addr; 23171b654882SGreg Clayton calculate_format_addr_function_offset = true; 23181b654882SGreg Clayton } 23191b654882SGreg Clayton } 23200769b2b1SMichael Sartain else if (IsToken (var_name_begin, "line-offset}")) 23211b654882SGreg Clayton { 23221b654882SGreg Clayton var_success = sc->line_entry.range.GetBaseAddress().IsValid(); 23231b654882SGreg Clayton if (var_success) 23241b654882SGreg Clayton { 23251b654882SGreg Clayton format_addr = sc->line_entry.range.GetBaseAddress(); 23261b654882SGreg Clayton calculate_format_addr_function_offset = true; 23271b654882SGreg Clayton } 23281b654882SGreg Clayton } 23290769b2b1SMichael Sartain else if (IsToken (var_name_begin, "pc-offset}")) 23301b654882SGreg Clayton { 2331c14ee32dSGreg Clayton StackFrame *frame = exe_ctx->GetFramePtr(); 2332c14ee32dSGreg Clayton var_success = frame != NULL; 23331b654882SGreg Clayton if (var_success) 23341b654882SGreg Clayton { 2335c14ee32dSGreg Clayton format_addr = frame->GetFrameCodeAddress(); 23361b654882SGreg Clayton calculate_format_addr_function_offset = true; 23371b654882SGreg Clayton } 23381b654882SGreg Clayton } 23391b654882SGreg Clayton } 23401b654882SGreg Clayton } 23411b654882SGreg Clayton break; 23421b654882SGreg Clayton 23431b654882SGreg Clayton case 'l': 23440769b2b1SMichael Sartain if (IsToken (var_name_begin, "line.")) 23451b654882SGreg Clayton { 23461b654882SGreg Clayton if (sc && sc->line_entry.IsValid()) 23471b654882SGreg Clayton { 23481b654882SGreg Clayton var_name_begin += ::strlen ("line."); 23490769b2b1SMichael Sartain if (IsToken (var_name_begin, "file.")) 23501b654882SGreg Clayton { 23511b654882SGreg Clayton var_name_begin += ::strlen ("file."); 23521b654882SGreg Clayton 23530769b2b1SMichael Sartain if (IsToken (var_name_begin, "basename}")) 23541b654882SGreg Clayton { 23551b654882SGreg Clayton format_file_spec.GetFilename() = sc->line_entry.file.GetFilename(); 23561b654882SGreg Clayton var_success = format_file_spec; 23571b654882SGreg Clayton } 23580769b2b1SMichael Sartain else if (IsToken (var_name_begin, "fullpath}")) 23591b654882SGreg Clayton { 23601b654882SGreg Clayton format_file_spec = sc->line_entry.file; 23611b654882SGreg Clayton var_success = format_file_spec; 23621b654882SGreg Clayton } 23631b654882SGreg Clayton } 23640769b2b1SMichael Sartain else if (IsTokenWithFormat (var_name_begin, "number", token_format, "%" PRIu64, exe_ctx, sc)) 23651b654882SGreg Clayton { 23661b654882SGreg Clayton var_success = true; 23670769b2b1SMichael Sartain s.Printf(token_format.c_str(), (uint64_t)sc->line_entry.line); 23681b654882SGreg Clayton } 23690769b2b1SMichael Sartain else if ((IsToken (var_name_begin, "start-addr}")) || 23700769b2b1SMichael Sartain (IsToken (var_name_begin, "end-addr}"))) 23711b654882SGreg Clayton { 23721b654882SGreg Clayton var_success = sc && sc->line_entry.range.GetBaseAddress().IsValid(); 23731b654882SGreg Clayton if (var_success) 23741b654882SGreg Clayton { 23751b654882SGreg Clayton format_addr = sc->line_entry.range.GetBaseAddress(); 23761b654882SGreg Clayton if (var_name_begin[0] == 'e') 23771b654882SGreg Clayton format_addr.Slide (sc->line_entry.range.GetByteSize()); 23781b654882SGreg Clayton } 23791b654882SGreg Clayton } 23801b654882SGreg Clayton } 23811b654882SGreg Clayton } 23821b654882SGreg Clayton break; 23831b654882SGreg Clayton } 23841b654882SGreg Clayton 23851b654882SGreg Clayton if (var_success) 23861b654882SGreg Clayton { 23871b654882SGreg Clayton // If format addr is valid, then we need to print an address 23881b654882SGreg Clayton if (reg_num != LLDB_INVALID_REGNUM) 23891b654882SGreg Clayton { 2390c14ee32dSGreg Clayton StackFrame *frame = exe_ctx->GetFramePtr(); 23911b654882SGreg Clayton // We have a register value to display... 23921b654882SGreg Clayton if (reg_num == LLDB_REGNUM_GENERIC_PC && reg_kind == eRegisterKindGeneric) 23931b654882SGreg Clayton { 2394c14ee32dSGreg Clayton format_addr = frame->GetFrameCodeAddress(); 23951b654882SGreg Clayton } 23961b654882SGreg Clayton else 23971b654882SGreg Clayton { 23981b654882SGreg Clayton if (reg_ctx == NULL) 2399c14ee32dSGreg Clayton reg_ctx = frame->GetRegisterContext().get(); 24001b654882SGreg Clayton 24011b654882SGreg Clayton if (reg_ctx) 24021b654882SGreg Clayton { 24031b654882SGreg Clayton if (reg_kind != kNumRegisterKinds) 24041b654882SGreg Clayton reg_num = reg_ctx->ConvertRegisterKindToRegisterNumber(reg_kind, reg_num); 24051b654882SGreg Clayton reg_info = reg_ctx->GetRegisterInfoAtIndex (reg_num); 24061b654882SGreg Clayton var_success = reg_info != NULL; 24071b654882SGreg Clayton } 24081b654882SGreg Clayton } 24091b654882SGreg Clayton } 24101b654882SGreg Clayton 24111b654882SGreg Clayton if (reg_info != NULL) 24121b654882SGreg Clayton { 24137349bd90SGreg Clayton RegisterValue reg_value; 24147349bd90SGreg Clayton var_success = reg_ctx->ReadRegister (reg_info, reg_value); 24157349bd90SGreg Clayton if (var_success) 24161b654882SGreg Clayton { 24179a8fa916SGreg Clayton reg_value.Dump(&s, reg_info, false, false, eFormatDefault); 24181b654882SGreg Clayton } 24191b654882SGreg Clayton } 24201b654882SGreg Clayton 24211b654882SGreg Clayton if (format_file_spec) 24221b654882SGreg Clayton { 24231b654882SGreg Clayton s << format_file_spec; 24241b654882SGreg Clayton } 24251b654882SGreg Clayton 24261b654882SGreg Clayton // If format addr is valid, then we need to print an address 24271b654882SGreg Clayton if (format_addr.IsValid()) 24281b654882SGreg Clayton { 24290603aa9dSGreg Clayton var_success = false; 24300603aa9dSGreg Clayton 24311b654882SGreg Clayton if (calculate_format_addr_function_offset) 24321b654882SGreg Clayton { 24331b654882SGreg Clayton Address func_addr; 24340603aa9dSGreg Clayton 24350603aa9dSGreg Clayton if (sc) 24360603aa9dSGreg Clayton { 24371b654882SGreg Clayton if (sc->function) 24380d9c9934SGreg Clayton { 24391b654882SGreg Clayton func_addr = sc->function->GetAddressRange().GetBaseAddress(); 24400d9c9934SGreg Clayton if (sc->block) 24410d9c9934SGreg Clayton { 24420d9c9934SGreg Clayton // Check to make sure we aren't in an inline 24430d9c9934SGreg Clayton // function. If we are, use the inline block 24440d9c9934SGreg Clayton // range that contains "format_addr" since 24450d9c9934SGreg Clayton // blocks can be discontiguous. 24460d9c9934SGreg Clayton Block *inline_block = sc->block->GetContainingInlinedBlock (); 24470d9c9934SGreg Clayton AddressRange inline_range; 24480d9c9934SGreg Clayton if (inline_block && inline_block->GetRangeContainingAddress (format_addr, inline_range)) 24490d9c9934SGreg Clayton func_addr = inline_range.GetBaseAddress(); 24500d9c9934SGreg Clayton } 24510d9c9934SGreg Clayton } 2452e7612134SGreg Clayton else if (sc->symbol && sc->symbol->ValueIsAddress()) 2453e7612134SGreg Clayton func_addr = sc->symbol->GetAddress(); 24540603aa9dSGreg Clayton } 24551b654882SGreg Clayton 24560603aa9dSGreg Clayton if (func_addr.IsValid()) 24571b654882SGreg Clayton { 24581b654882SGreg Clayton if (func_addr.GetSection() == format_addr.GetSection()) 24591b654882SGreg Clayton { 24601b654882SGreg Clayton addr_t func_file_addr = func_addr.GetFileAddress(); 24611b654882SGreg Clayton addr_t addr_file_addr = format_addr.GetFileAddress(); 24621b654882SGreg Clayton if (addr_file_addr > func_file_addr) 2463d01b2953SDaniel Malea s.Printf(" + %" PRIu64, addr_file_addr - func_file_addr); 24641b654882SGreg Clayton else if (addr_file_addr < func_file_addr) 2465d01b2953SDaniel Malea s.Printf(" - %" PRIu64, func_file_addr - addr_file_addr); 24660603aa9dSGreg Clayton var_success = true; 24671b654882SGreg Clayton } 24681b654882SGreg Clayton else 24690603aa9dSGreg Clayton { 24700603aa9dSGreg Clayton Target *target = Target::GetTargetFromContexts (exe_ctx, sc); 24710603aa9dSGreg Clayton if (target) 24720603aa9dSGreg Clayton { 24730603aa9dSGreg Clayton addr_t func_load_addr = func_addr.GetLoadAddress (target); 24740603aa9dSGreg Clayton addr_t addr_load_addr = format_addr.GetLoadAddress (target); 24750603aa9dSGreg Clayton if (addr_load_addr > func_load_addr) 2476d01b2953SDaniel Malea s.Printf(" + %" PRIu64, addr_load_addr - func_load_addr); 24770603aa9dSGreg Clayton else if (addr_load_addr < func_load_addr) 2478d01b2953SDaniel Malea s.Printf(" - %" PRIu64, func_load_addr - addr_load_addr); 24790603aa9dSGreg Clayton var_success = true; 24800603aa9dSGreg Clayton } 24810603aa9dSGreg Clayton } 24821b654882SGreg Clayton } 24831b654882SGreg Clayton } 24841b654882SGreg Clayton else 24851b654882SGreg Clayton { 24860603aa9dSGreg Clayton Target *target = Target::GetTargetFromContexts (exe_ctx, sc); 24871b654882SGreg Clayton addr_t vaddr = LLDB_INVALID_ADDRESS; 24880603aa9dSGreg Clayton if (exe_ctx && !target->GetSectionLoadList().IsEmpty()) 24890603aa9dSGreg Clayton vaddr = format_addr.GetLoadAddress (target); 24901b654882SGreg Clayton if (vaddr == LLDB_INVALID_ADDRESS) 24911b654882SGreg Clayton vaddr = format_addr.GetFileAddress (); 24921b654882SGreg Clayton 24931b654882SGreg Clayton if (vaddr != LLDB_INVALID_ADDRESS) 24940603aa9dSGreg Clayton { 2495514487e8SGreg Clayton int addr_width = target->GetArchitecture().GetAddressByteSize() * 2; 249635f1a0d5SGreg Clayton if (addr_width == 0) 249735f1a0d5SGreg Clayton addr_width = 16; 2498d01b2953SDaniel Malea s.Printf("0x%*.*" PRIx64, addr_width, addr_width, vaddr); 24990603aa9dSGreg Clayton var_success = true; 25000603aa9dSGreg Clayton } 25011b654882SGreg Clayton } 25021b654882SGreg Clayton } 25031b654882SGreg Clayton } 25041b654882SGreg Clayton 25051b654882SGreg Clayton if (var_success == false) 25061b654882SGreg Clayton success = false; 25071b654882SGreg Clayton } 25081b654882SGreg Clayton p = var_name_end; 25091b654882SGreg Clayton } 25101b654882SGreg Clayton else 25111b654882SGreg Clayton break; 25121b654882SGreg Clayton } 25131b654882SGreg Clayton else 25141b654882SGreg Clayton { 25151b654882SGreg Clayton // We got a dollar sign with no '{' after it, it must just be a dollar sign 25161b654882SGreg Clayton s.PutChar(*p); 25171b654882SGreg Clayton } 25181b654882SGreg Clayton } 25191b654882SGreg Clayton else if (*p == '\\') 25201b654882SGreg Clayton { 25211b654882SGreg Clayton ++p; // skip the slash 25221b654882SGreg Clayton switch (*p) 25231b654882SGreg Clayton { 25241b654882SGreg Clayton case 'a': s.PutChar ('\a'); break; 25251b654882SGreg Clayton case 'b': s.PutChar ('\b'); break; 25261b654882SGreg Clayton case 'f': s.PutChar ('\f'); break; 25271b654882SGreg Clayton case 'n': s.PutChar ('\n'); break; 25281b654882SGreg Clayton case 'r': s.PutChar ('\r'); break; 25291b654882SGreg Clayton case 't': s.PutChar ('\t'); break; 25301b654882SGreg Clayton case 'v': s.PutChar ('\v'); break; 25311b654882SGreg Clayton case '\'': s.PutChar ('\''); break; 25321b654882SGreg Clayton case '\\': s.PutChar ('\\'); break; 25331b654882SGreg Clayton case '0': 25341b654882SGreg Clayton // 1 to 3 octal chars 25351b654882SGreg Clayton { 25360603aa9dSGreg Clayton // Make a string that can hold onto the initial zero char, 25370603aa9dSGreg Clayton // up to 3 octal digits, and a terminating NULL. 25380603aa9dSGreg Clayton char oct_str[5] = { 0, 0, 0, 0, 0 }; 25390603aa9dSGreg Clayton 25400603aa9dSGreg Clayton int i; 25410603aa9dSGreg Clayton for (i=0; (p[i] >= '0' && p[i] <= '7') && i<4; ++i) 25420603aa9dSGreg Clayton oct_str[i] = p[i]; 25430603aa9dSGreg Clayton 25440603aa9dSGreg Clayton // We don't want to consume the last octal character since 25450603aa9dSGreg Clayton // the main for loop will do this for us, so we advance p by 25460603aa9dSGreg Clayton // one less than i (even if i is zero) 25470603aa9dSGreg Clayton p += i - 1; 25480603aa9dSGreg Clayton unsigned long octal_value = ::strtoul (oct_str, NULL, 8); 25490603aa9dSGreg Clayton if (octal_value <= UINT8_MAX) 25501b654882SGreg Clayton { 2551c7bece56SGreg Clayton s.PutChar((char)octal_value); 25521b654882SGreg Clayton } 25531b654882SGreg Clayton } 25541b654882SGreg Clayton break; 25551b654882SGreg Clayton 25561b654882SGreg Clayton case 'x': 25571b654882SGreg Clayton // hex number in the format 25580603aa9dSGreg Clayton if (isxdigit(p[1])) 25591b654882SGreg Clayton { 25600603aa9dSGreg Clayton ++p; // Skip the 'x' 25611b654882SGreg Clayton 25620603aa9dSGreg Clayton // Make a string that can hold onto two hex chars plus a 25630603aa9dSGreg Clayton // NULL terminator 25641b654882SGreg Clayton char hex_str[3] = { 0,0,0 }; 25651b654882SGreg Clayton hex_str[0] = *p; 25660603aa9dSGreg Clayton if (isxdigit(p[1])) 25670603aa9dSGreg Clayton { 25680603aa9dSGreg Clayton ++p; // Skip the first of the two hex chars 25691b654882SGreg Clayton hex_str[1] = *p; 25700603aa9dSGreg Clayton } 25710603aa9dSGreg Clayton 25721b654882SGreg Clayton unsigned long hex_value = strtoul (hex_str, NULL, 16); 25730603aa9dSGreg Clayton if (hex_value <= UINT8_MAX) 2574c7bece56SGreg Clayton s.PutChar ((char)hex_value); 25751b654882SGreg Clayton } 25761b654882SGreg Clayton else 25771b654882SGreg Clayton { 25780603aa9dSGreg Clayton s.PutChar('x'); 25791b654882SGreg Clayton } 25801b654882SGreg Clayton break; 25811b654882SGreg Clayton 25821b654882SGreg Clayton default: 25830603aa9dSGreg Clayton // Just desensitize any other character by just printing what 25840603aa9dSGreg Clayton // came after the '\' 25850603aa9dSGreg Clayton s << *p; 25861b654882SGreg Clayton break; 25871b654882SGreg Clayton 25881b654882SGreg Clayton } 25891b654882SGreg Clayton 25901b654882SGreg Clayton } 25911b654882SGreg Clayton } 25921b654882SGreg Clayton if (end) 25931b654882SGreg Clayton *end = p; 25941b654882SGreg Clayton return success; 25951b654882SGreg Clayton } 25961b654882SGreg Clayton 2597c3ce7f27SMichael Sartain bool 2598c3ce7f27SMichael Sartain Debugger::FormatPrompt 2599c3ce7f27SMichael Sartain ( 2600c3ce7f27SMichael Sartain const char *format, 2601c3ce7f27SMichael Sartain const SymbolContext *sc, 2602c3ce7f27SMichael Sartain const ExecutionContext *exe_ctx, 2603c3ce7f27SMichael Sartain const Address *addr, 2604c3ce7f27SMichael Sartain Stream &s, 2605c3ce7f27SMichael Sartain ValueObject* valobj 2606c3ce7f27SMichael Sartain ) 2607c3ce7f27SMichael Sartain { 2608c3ce7f27SMichael Sartain bool use_color = exe_ctx ? exe_ctx->GetTargetRef().GetDebugger().GetUseColor() : true; 2609c3ce7f27SMichael Sartain std::string format_str = lldb_utility::ansi::FormatAnsiTerminalCodes (format, use_color); 2610c3ce7f27SMichael Sartain if (format_str.length()) 2611c3ce7f27SMichael Sartain format = format_str.c_str(); 2612c3ce7f27SMichael Sartain return FormatPromptRecurse (format, sc, exe_ctx, addr, s, NULL, valobj); 2613c3ce7f27SMichael Sartain } 2614c3ce7f27SMichael Sartain 2615228063cdSJim Ingham void 2616228063cdSJim Ingham Debugger::SetLoggingCallback (lldb::LogOutputCallback log_callback, void *baton) 2617228063cdSJim Ingham { 26184f02b22dSJim Ingham // For simplicity's sake, I am not going to deal with how to close down any 26194f02b22dSJim Ingham // open logging streams, I just redirect everything from here on out to the 26204f02b22dSJim Ingham // callback. 2621228063cdSJim Ingham m_log_callback_stream_sp.reset (new StreamCallback (log_callback, baton)); 2622228063cdSJim Ingham } 2623228063cdSJim Ingham 2624228063cdSJim Ingham bool 2625228063cdSJim Ingham Debugger::EnableLog (const char *channel, const char **categories, const char *log_file, uint32_t log_options, Stream &error_stream) 2626228063cdSJim Ingham { 2627228063cdSJim Ingham Log::Callbacks log_callbacks; 2628228063cdSJim Ingham 2629228063cdSJim Ingham StreamSP log_stream_sp; 26309a028519SSean Callanan if (m_log_callback_stream_sp) 2631228063cdSJim Ingham { 2632228063cdSJim Ingham log_stream_sp = m_log_callback_stream_sp; 2633228063cdSJim Ingham // For now when using the callback mode you always get thread & timestamp. 2634228063cdSJim Ingham log_options |= LLDB_LOG_OPTION_PREPEND_TIMESTAMP | LLDB_LOG_OPTION_PREPEND_THREAD_NAME; 2635228063cdSJim Ingham } 2636228063cdSJim Ingham else if (log_file == NULL || *log_file == '\0') 2637228063cdSJim Ingham { 2638228063cdSJim Ingham log_stream_sp.reset(new StreamFile(GetOutputFile().GetDescriptor(), false)); 2639228063cdSJim Ingham } 2640228063cdSJim Ingham else 2641228063cdSJim Ingham { 2642228063cdSJim Ingham LogStreamMap::iterator pos = m_log_streams.find(log_file); 2643c1b2ccfdSGreg Clayton if (pos != m_log_streams.end()) 2644c1b2ccfdSGreg Clayton log_stream_sp = pos->second.lock(); 2645c1b2ccfdSGreg Clayton if (!log_stream_sp) 2646228063cdSJim Ingham { 2647228063cdSJim Ingham log_stream_sp.reset (new StreamFile (log_file)); 2648228063cdSJim Ingham m_log_streams[log_file] = log_stream_sp; 2649228063cdSJim Ingham } 2650228063cdSJim Ingham } 2651228063cdSJim Ingham assert (log_stream_sp.get()); 2652228063cdSJim Ingham 2653228063cdSJim Ingham if (log_options == 0) 2654228063cdSJim Ingham log_options = LLDB_LOG_OPTION_PREPEND_THREAD_NAME | LLDB_LOG_OPTION_THREADSAFE; 2655228063cdSJim Ingham 265657abc5d6SGreg Clayton if (Log::GetLogChannelCallbacks (ConstString(channel), log_callbacks)) 2657228063cdSJim Ingham { 2658228063cdSJim Ingham log_callbacks.enable (log_stream_sp, log_options, categories, &error_stream); 2659228063cdSJim Ingham return true; 2660228063cdSJim Ingham } 2661228063cdSJim Ingham else 2662228063cdSJim Ingham { 2663228063cdSJim Ingham LogChannelSP log_channel_sp (LogChannel::FindPlugin (channel)); 2664228063cdSJim Ingham if (log_channel_sp) 2665228063cdSJim Ingham { 2666228063cdSJim Ingham if (log_channel_sp->Enable (log_stream_sp, log_options, &error_stream, categories)) 2667228063cdSJim Ingham { 2668228063cdSJim Ingham return true; 2669228063cdSJim Ingham } 2670228063cdSJim Ingham else 2671228063cdSJim Ingham { 2672228063cdSJim Ingham error_stream.Printf ("Invalid log channel '%s'.\n", channel); 2673228063cdSJim Ingham return false; 2674228063cdSJim Ingham } 2675228063cdSJim Ingham } 2676228063cdSJim Ingham else 2677228063cdSJim Ingham { 2678228063cdSJim Ingham error_stream.Printf ("Invalid log channel '%s'.\n", channel); 2679228063cdSJim Ingham return false; 2680228063cdSJim Ingham } 2681228063cdSJim Ingham } 2682228063cdSJim Ingham return false; 2683228063cdSJim Ingham } 2684228063cdSJim Ingham 26859585fbfcSGreg Clayton SourceManager & 26869585fbfcSGreg Clayton Debugger::GetSourceManager () 26879585fbfcSGreg Clayton { 26889585fbfcSGreg Clayton if (m_source_manager_ap.get() == NULL) 26899585fbfcSGreg Clayton m_source_manager_ap.reset (new SourceManager (shared_from_this())); 26909585fbfcSGreg Clayton return *m_source_manager_ap; 26919585fbfcSGreg Clayton } 26929585fbfcSGreg Clayton 26939585fbfcSGreg Clayton 2694