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" 23a777dc2aSEnrico Granata #include "lldb/Core/DataVisualization.h" 244a33d318SGreg Clayton #include "lldb/Core/FormatManager.h" 2530fdc8d8SChris Lattner #include "lldb/Core/InputReader.h" 261f746071SGreg Clayton #include "lldb/Core/Module.h" 27e8cd0c98SGreg Clayton #include "lldb/Core/PluginManager.h" 287349bd90SGreg Clayton #include "lldb/Core/RegisterValue.h" 2930fdc8d8SChris Lattner #include "lldb/Core/State.h" 305b52f0c7SJim Ingham #include "lldb/Core/StreamAsynchronousIO.h" 31228063cdSJim Ingham #include "lldb/Core/StreamCallback.h" 321b654882SGreg Clayton #include "lldb/Core/StreamString.h" 3330fdc8d8SChris Lattner #include "lldb/Core/Timer.h" 344becb37eSEnrico Granata #include "lldb/Core/ValueObject.h" 356d3dbf51SGreg Clayton #include "lldb/Core/ValueObjectVariable.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" 5030fdc8d8SChris Lattner #include "lldb/Target/Thread.h" 515a31471eSGreg Clayton #include "lldb/Utility/AnsiTerminal.h" 5230fdc8d8SChris Lattner 5330fdc8d8SChris Lattner using namespace lldb; 5430fdc8d8SChris Lattner using namespace lldb_private; 5530fdc8d8SChris Lattner 5630fdc8d8SChris Lattner 571b654882SGreg Clayton static uint32_t g_shared_debugger_refcount = 0; 58ebc1bb27SCaroline Tice static lldb::user_id_t g_unique_id = 1; 59ebc1bb27SCaroline Tice 601b654882SGreg Clayton #pragma mark Static Functions 611b654882SGreg Clayton 621b654882SGreg Clayton static Mutex & 631b654882SGreg Clayton GetDebuggerListMutex () 641b654882SGreg Clayton { 651b654882SGreg Clayton static Mutex g_mutex(Mutex::eMutexTypeRecursive); 661b654882SGreg Clayton return g_mutex; 671b654882SGreg Clayton } 681b654882SGreg Clayton 691b654882SGreg Clayton typedef std::vector<DebuggerSP> DebuggerList; 701b654882SGreg Clayton 711b654882SGreg Clayton static DebuggerList & 721b654882SGreg Clayton GetDebuggerList() 731b654882SGreg Clayton { 741b654882SGreg Clayton // hide the static debugger list inside a singleton accessor to avoid 751b654882SGreg Clayton // global init contructors 761b654882SGreg Clayton static DebuggerList g_list; 771b654882SGreg Clayton return g_list; 781b654882SGreg Clayton } 79e372b98dSGreg Clayton 80e372b98dSGreg Clayton OptionEnumValueElement 8167cc0636SGreg Clayton g_show_disassembly_enum_values[] = 82e372b98dSGreg Clayton { 8367cc0636SGreg Clayton { Debugger::eStopDisassemblyTypeNever, "never", "Never show disassembly when displaying a stop context."}, 8467cc0636SGreg Clayton { Debugger::eStopDisassemblyTypeNoSource, "no-source", "Show disassembly when there is no source information, or the source file is missing when displaying a stop context."}, 8567cc0636SGreg Clayton { Debugger::eStopDisassemblyTypeAlways, "always", "Always show disassembly when displaying a stop context."}, 86e372b98dSGreg Clayton { 0, NULL, NULL } 87e372b98dSGreg Clayton }; 88e372b98dSGreg Clayton 8967cc0636SGreg Clayton OptionEnumValueElement 9067cc0636SGreg Clayton g_language_enumerators[] = 9167cc0636SGreg Clayton { 9267cc0636SGreg Clayton { eScriptLanguageNone, "none", "Disable scripting languages."}, 9367cc0636SGreg Clayton { eScriptLanguagePython, "python", "Select python as the default scripting language."}, 9467cc0636SGreg Clayton { eScriptLanguageDefault, "default", "Select the lldb default as the default scripting language."}, 95a12993c9SGreg Clayton { 0, NULL, NULL } 9667cc0636SGreg Clayton }; 97e372b98dSGreg Clayton 9867cc0636SGreg Clayton #define MODULE_WITH_FUNC "{ ${module.file.basename}{`${function.name-with-args}${function.pc-offset}}}" 9967cc0636SGreg Clayton #define FILE_AND_LINE "{ at ${line.file.basename}:${line.number}}" 10067cc0636SGreg Clayton 10167cc0636SGreg Clayton #define DEFAULT_THREAD_FORMAT "thread #${thread.index}: tid = ${thread.id}"\ 10267cc0636SGreg Clayton "{, ${frame.pc}}"\ 10367cc0636SGreg Clayton MODULE_WITH_FUNC\ 10467cc0636SGreg Clayton FILE_AND_LINE\ 10567cc0636SGreg Clayton "{, stop reason = ${thread.stop-reason}}"\ 10667cc0636SGreg Clayton "{\\nReturn value: ${thread.return-value}}"\ 10767cc0636SGreg Clayton "\\n" 10867cc0636SGreg Clayton 10967cc0636SGreg Clayton #define DEFAULT_FRAME_FORMAT "frame #${frame.index}: ${frame.pc}"\ 11067cc0636SGreg Clayton MODULE_WITH_FUNC\ 11167cc0636SGreg Clayton FILE_AND_LINE\ 11267cc0636SGreg Clayton "\\n" 11367cc0636SGreg Clayton 11467cc0636SGreg Clayton 11567cc0636SGreg Clayton 116754a9369SGreg Clayton static PropertyDefinition 117754a9369SGreg Clayton g_properties[] = 11867cc0636SGreg Clayton { 11967cc0636SGreg Clayton { "auto-confirm", OptionValue::eTypeBoolean, true, false, NULL, NULL, "If true all confirmation prompts will receive their default reply." }, 12067cc0636SGreg 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." }, 12167cc0636SGreg Clayton { "notify-void", OptionValue::eTypeBoolean, true, false, NULL, NULL, "Notify the user explicitly if an expression returns void (default: false)." }, 1224c05410fSGreg Clayton { "prompt", OptionValue::eTypeString , true, OptionValueString::eOptionEncodeCharacterEscapeSequences, "(lldb) ", NULL, "The debugger command line prompt displayed for the user." }, 12367cc0636SGreg Clayton { "script-lang", OptionValue::eTypeEnum , true, eScriptLanguagePython, NULL, g_language_enumerators, "The script language to be used for evaluating user-written scripts." }, 12467cc0636SGreg Clayton { "stop-disassembly-count", OptionValue::eTypeSInt64 , true, 4 , NULL, NULL, "The number of disassembly lines to show when displaying a stopped context." }, 12567cc0636SGreg 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." }, 12667cc0636SGreg 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." }, 12767cc0636SGreg 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." }, 12867cc0636SGreg Clayton { "term-width", OptionValue::eTypeSInt64 , true, 80 , NULL, NULL, "The maximum number of columns to use for displaying text." }, 12967cc0636SGreg Clayton { "thread-format", OptionValue::eTypeString , true, 0 , DEFAULT_THREAD_FORMAT, NULL, "The default thread format string to use when displaying thread information." }, 13067cc0636SGreg Clayton { "use-external-editor", OptionValue::eTypeBoolean, true, false, NULL, NULL, "Whether to use an external editor or not." }, 131e8cd0c98SGreg Clayton 13267cc0636SGreg Clayton { NULL, OptionValue::eTypeInvalid, true, 0 , NULL, NULL, NULL } 13367cc0636SGreg Clayton }; 13467cc0636SGreg Clayton 13567cc0636SGreg Clayton enum 13667cc0636SGreg Clayton { 13767cc0636SGreg Clayton ePropertyAutoConfirm = 0, 13867cc0636SGreg Clayton ePropertyFrameFormat, 13967cc0636SGreg Clayton ePropertyNotiftVoid, 14067cc0636SGreg Clayton ePropertyPrompt, 14167cc0636SGreg Clayton ePropertyScriptLanguage, 14267cc0636SGreg Clayton ePropertyStopDisassemblyCount, 14367cc0636SGreg Clayton ePropertyStopDisassemblyDisplay, 14467cc0636SGreg Clayton ePropertyStopLineCountAfter, 14567cc0636SGreg Clayton ePropertyStopLineCountBefore, 14667cc0636SGreg Clayton ePropertyTerminalWidth, 14767cc0636SGreg Clayton ePropertyThreadFormat, 14867cc0636SGreg Clayton ePropertyUseExternalEditor 14967cc0636SGreg Clayton }; 15067cc0636SGreg Clayton 15167cc0636SGreg Clayton // 15267cc0636SGreg Clayton //const char * 15367cc0636SGreg Clayton //Debugger::GetFrameFormat() const 15467cc0636SGreg Clayton //{ 15567cc0636SGreg Clayton // return m_properties_sp->GetFrameFormat(); 15667cc0636SGreg Clayton //} 15767cc0636SGreg Clayton //const char * 15867cc0636SGreg Clayton //Debugger::GetThreadFormat() const 15967cc0636SGreg Clayton //{ 16067cc0636SGreg Clayton // return m_properties_sp->GetThreadFormat(); 16167cc0636SGreg Clayton //} 16267cc0636SGreg Clayton // 1634c05410fSGreg Clayton 1644c05410fSGreg Clayton 1654c05410fSGreg Clayton Error 1664c05410fSGreg Clayton Debugger::SetPropertyValue (const ExecutionContext *exe_ctx, 1674c05410fSGreg Clayton VarSetOperationType op, 1684c05410fSGreg Clayton const char *property_path, 1694c05410fSGreg Clayton const char *value) 1704c05410fSGreg Clayton { 1714c05410fSGreg Clayton Error error (Properties::SetPropertyValue (exe_ctx, op, property_path, value)); 1724c05410fSGreg Clayton if (error.Success()) 1734c05410fSGreg Clayton { 1744c05410fSGreg Clayton if (strcmp(property_path, g_properties[ePropertyPrompt].name) == 0) 1754c05410fSGreg Clayton { 1764c05410fSGreg Clayton const char *new_prompt = GetPrompt(); 1774c05410fSGreg Clayton EventSP prompt_change_event_sp (new Event(CommandInterpreter::eBroadcastBitResetPrompt, new EventDataBytes (new_prompt))); 1784c05410fSGreg Clayton GetCommandInterpreter().BroadcastEvent (prompt_change_event_sp); 1794c05410fSGreg Clayton } 1804c05410fSGreg Clayton } 1814c05410fSGreg Clayton return error; 1824c05410fSGreg Clayton } 1834c05410fSGreg Clayton 18467cc0636SGreg Clayton bool 18567cc0636SGreg Clayton Debugger::GetAutoConfirm () const 18667cc0636SGreg Clayton { 18767cc0636SGreg Clayton const uint32_t idx = ePropertyAutoConfirm; 188754a9369SGreg Clayton return m_collection_sp->GetPropertyAtIndexAsBoolean (NULL, idx, g_properties[idx].default_uint_value != 0); 18967cc0636SGreg Clayton } 19067cc0636SGreg Clayton 19167cc0636SGreg Clayton const char * 19267cc0636SGreg Clayton Debugger::GetFrameFormat() const 19367cc0636SGreg Clayton { 19467cc0636SGreg Clayton const uint32_t idx = ePropertyFrameFormat; 195754a9369SGreg Clayton return m_collection_sp->GetPropertyAtIndexAsString (NULL, idx, g_properties[idx].default_cstr_value); 19667cc0636SGreg Clayton } 19767cc0636SGreg Clayton 19867cc0636SGreg Clayton bool 19967cc0636SGreg Clayton Debugger::GetNotifyVoid () const 20067cc0636SGreg Clayton { 20167cc0636SGreg Clayton const uint32_t idx = ePropertyNotiftVoid; 202754a9369SGreg Clayton return m_collection_sp->GetPropertyAtIndexAsBoolean (NULL, idx, g_properties[idx].default_uint_value != 0); 20367cc0636SGreg Clayton } 20467cc0636SGreg Clayton 20567cc0636SGreg Clayton const char * 20667cc0636SGreg Clayton Debugger::GetPrompt() const 20767cc0636SGreg Clayton { 20867cc0636SGreg Clayton const uint32_t idx = ePropertyPrompt; 209754a9369SGreg Clayton return m_collection_sp->GetPropertyAtIndexAsString (NULL, idx, g_properties[idx].default_cstr_value); 21067cc0636SGreg Clayton } 21167cc0636SGreg Clayton 21267cc0636SGreg Clayton void 21367cc0636SGreg Clayton Debugger::SetPrompt(const char *p) 21467cc0636SGreg Clayton { 21567cc0636SGreg Clayton const uint32_t idx = ePropertyPrompt; 21667cc0636SGreg Clayton m_collection_sp->SetPropertyAtIndexAsString (NULL, idx, p); 21767cc0636SGreg Clayton const char *new_prompt = GetPrompt(); 21867cc0636SGreg Clayton EventSP prompt_change_event_sp (new Event(CommandInterpreter::eBroadcastBitResetPrompt, new EventDataBytes (new_prompt)));; 21967cc0636SGreg Clayton GetCommandInterpreter().BroadcastEvent (prompt_change_event_sp); 22067cc0636SGreg Clayton } 22167cc0636SGreg Clayton 22267cc0636SGreg Clayton const char * 22367cc0636SGreg Clayton Debugger::GetThreadFormat() const 22467cc0636SGreg Clayton { 22567cc0636SGreg Clayton const uint32_t idx = ePropertyThreadFormat; 226754a9369SGreg Clayton return m_collection_sp->GetPropertyAtIndexAsString (NULL, idx, g_properties[idx].default_cstr_value); 22767cc0636SGreg Clayton } 22867cc0636SGreg Clayton 22967cc0636SGreg Clayton lldb::ScriptLanguage 23067cc0636SGreg Clayton Debugger::GetScriptLanguage() const 23167cc0636SGreg Clayton { 23267cc0636SGreg Clayton const uint32_t idx = ePropertyScriptLanguage; 233754a9369SGreg Clayton return (lldb::ScriptLanguage)m_collection_sp->GetPropertyAtIndexAsEnumeration (NULL, idx, g_properties[idx].default_uint_value); 23467cc0636SGreg Clayton } 23567cc0636SGreg Clayton 23667cc0636SGreg Clayton bool 23767cc0636SGreg Clayton Debugger::SetScriptLanguage (lldb::ScriptLanguage script_lang) 23867cc0636SGreg Clayton { 23967cc0636SGreg Clayton const uint32_t idx = ePropertyScriptLanguage; 24067cc0636SGreg Clayton return m_collection_sp->SetPropertyAtIndexAsEnumeration (NULL, idx, script_lang); 24167cc0636SGreg Clayton } 24267cc0636SGreg Clayton 24367cc0636SGreg Clayton uint32_t 24467cc0636SGreg Clayton Debugger::GetTerminalWidth () const 24567cc0636SGreg Clayton { 24667cc0636SGreg Clayton const uint32_t idx = ePropertyTerminalWidth; 247754a9369SGreg Clayton return m_collection_sp->GetPropertyAtIndexAsSInt64 (NULL, idx, g_properties[idx].default_uint_value); 24867cc0636SGreg Clayton } 24967cc0636SGreg Clayton 25067cc0636SGreg Clayton bool 25167cc0636SGreg Clayton Debugger::SetTerminalWidth (uint32_t term_width) 25267cc0636SGreg Clayton { 25367cc0636SGreg Clayton const uint32_t idx = ePropertyTerminalWidth; 25467cc0636SGreg Clayton return m_collection_sp->SetPropertyAtIndexAsSInt64 (NULL, idx, term_width); 25567cc0636SGreg Clayton } 25667cc0636SGreg Clayton 25767cc0636SGreg Clayton bool 25867cc0636SGreg Clayton Debugger::GetUseExternalEditor () const 25967cc0636SGreg Clayton { 26067cc0636SGreg Clayton const uint32_t idx = ePropertyUseExternalEditor; 261754a9369SGreg Clayton return m_collection_sp->GetPropertyAtIndexAsBoolean (NULL, idx, g_properties[idx].default_uint_value != 0); 26267cc0636SGreg Clayton } 26367cc0636SGreg Clayton 26467cc0636SGreg Clayton bool 26567cc0636SGreg Clayton Debugger::SetUseExternalEditor (bool b) 26667cc0636SGreg Clayton { 26767cc0636SGreg Clayton const uint32_t idx = ePropertyUseExternalEditor; 26867cc0636SGreg Clayton return m_collection_sp->SetPropertyAtIndexAsBoolean (NULL, idx, b); 26967cc0636SGreg Clayton } 27067cc0636SGreg Clayton 27167cc0636SGreg Clayton uint32_t 27267cc0636SGreg Clayton Debugger::GetStopSourceLineCount (bool before) const 27367cc0636SGreg Clayton { 27467cc0636SGreg Clayton const uint32_t idx = before ? ePropertyStopLineCountBefore : ePropertyStopLineCountAfter; 275754a9369SGreg Clayton return m_collection_sp->GetPropertyAtIndexAsSInt64 (NULL, idx, g_properties[idx].default_uint_value); 27667cc0636SGreg Clayton } 27767cc0636SGreg Clayton 27867cc0636SGreg Clayton Debugger::StopDisassemblyType 27967cc0636SGreg Clayton Debugger::GetStopDisassemblyDisplay () const 28067cc0636SGreg Clayton { 28167cc0636SGreg Clayton const uint32_t idx = ePropertyStopDisassemblyDisplay; 282754a9369SGreg Clayton return (Debugger::StopDisassemblyType)m_collection_sp->GetPropertyAtIndexAsEnumeration (NULL, idx, g_properties[idx].default_uint_value); 28367cc0636SGreg Clayton } 28467cc0636SGreg Clayton 28567cc0636SGreg Clayton uint32_t 28667cc0636SGreg Clayton Debugger::GetDisassemblyLineCount () const 28767cc0636SGreg Clayton { 28867cc0636SGreg Clayton const uint32_t idx = ePropertyStopDisassemblyCount; 289754a9369SGreg Clayton return m_collection_sp->GetPropertyAtIndexAsSInt64 (NULL, idx, g_properties[idx].default_uint_value); 29067cc0636SGreg Clayton } 291e372b98dSGreg Clayton 2921b654882SGreg Clayton #pragma mark Debugger 2931b654882SGreg Clayton 29467cc0636SGreg Clayton //const DebuggerPropertiesSP & 29567cc0636SGreg Clayton //Debugger::GetSettings() const 29667cc0636SGreg Clayton //{ 29767cc0636SGreg Clayton // return m_properties_sp; 29867cc0636SGreg Clayton //} 29967cc0636SGreg Clayton // 30099d0faf2SGreg Clayton 3012f88aadfSCaroline Tice int 3022f88aadfSCaroline Tice Debugger::TestDebuggerRefCount () 3032f88aadfSCaroline Tice { 3042f88aadfSCaroline Tice return g_shared_debugger_refcount; 3052f88aadfSCaroline Tice } 3062f88aadfSCaroline Tice 30730fdc8d8SChris Lattner void 30830fdc8d8SChris Lattner Debugger::Initialize () 30930fdc8d8SChris Lattner { 310c15f55e2SGreg Clayton if (g_shared_debugger_refcount++ == 0) 311dbe54508SGreg Clayton lldb_private::Initialize(); 31299d0faf2SGreg Clayton } 31330fdc8d8SChris Lattner 31430fdc8d8SChris Lattner void 31530fdc8d8SChris Lattner Debugger::Terminate () 31630fdc8d8SChris Lattner { 3176611103cSGreg Clayton if (g_shared_debugger_refcount > 0) 3186611103cSGreg Clayton { 31930fdc8d8SChris Lattner g_shared_debugger_refcount--; 32030fdc8d8SChris Lattner if (g_shared_debugger_refcount == 0) 32130fdc8d8SChris Lattner { 322dbe54508SGreg Clayton lldb_private::WillTerminate(); 323dbe54508SGreg Clayton lldb_private::Terminate(); 3246760a517SCaroline Tice 32599d0faf2SGreg Clayton // Clear our master list of debugger objects 32699d0faf2SGreg Clayton Mutex::Locker locker (GetDebuggerListMutex ()); 32799d0faf2SGreg Clayton GetDebuggerList().clear(); 32830fdc8d8SChris Lattner } 3296760a517SCaroline Tice } 3306760a517SCaroline Tice } 33130fdc8d8SChris Lattner 33220bd37f7SCaroline Tice void 33320bd37f7SCaroline Tice Debugger::SettingsInitialize () 33420bd37f7SCaroline Tice { 3356920b52bSGreg Clayton Target::SettingsInitialize (); 33620bd37f7SCaroline Tice } 33720bd37f7SCaroline Tice 33820bd37f7SCaroline Tice void 33920bd37f7SCaroline Tice Debugger::SettingsTerminate () 34020bd37f7SCaroline Tice { 3416920b52bSGreg Clayton Target::SettingsTerminate (); 34220bd37f7SCaroline Tice } 34320bd37f7SCaroline Tice 34421dfcd9dSEnrico Granata bool 34521dfcd9dSEnrico Granata Debugger::LoadPlugin (const FileSpec& spec) 34621dfcd9dSEnrico Granata { 34721dfcd9dSEnrico Granata lldb::DynamicLibrarySP dynlib_sp(new lldb_private::DynamicLibrary(spec)); 34821dfcd9dSEnrico Granata lldb::DebuggerSP debugger_sp(shared_from_this()); 34921dfcd9dSEnrico Granata lldb::SBDebugger debugger_sb(debugger_sp); 35021dfcd9dSEnrico Granata // TODO: mangle this differently for your system - on OSX, the first underscore needs to be removed and the second one stays 35121dfcd9dSEnrico Granata LLDBCommandPluginInit init_func = dynlib_sp->GetSymbol<LLDBCommandPluginInit>("_ZN4lldb16PluginInitializeENS_10SBDebuggerE"); 35221dfcd9dSEnrico Granata if (!init_func) 35321dfcd9dSEnrico Granata return false; 35421dfcd9dSEnrico Granata if (init_func(debugger_sb)) 35521dfcd9dSEnrico Granata { 35621dfcd9dSEnrico Granata m_loaded_plugins.push_back(dynlib_sp); 35721dfcd9dSEnrico Granata return true; 35821dfcd9dSEnrico Granata } 35921dfcd9dSEnrico Granata return false; 36021dfcd9dSEnrico Granata } 36121dfcd9dSEnrico Granata 36221dfcd9dSEnrico Granata static FileSpec::EnumerateDirectoryResult 36321dfcd9dSEnrico Granata LoadPluginCallback 36421dfcd9dSEnrico Granata ( 36521dfcd9dSEnrico Granata void *baton, 36621dfcd9dSEnrico Granata FileSpec::FileType file_type, 36721dfcd9dSEnrico Granata const FileSpec &file_spec 36821dfcd9dSEnrico Granata ) 36921dfcd9dSEnrico Granata { 37021dfcd9dSEnrico Granata Error error; 37121dfcd9dSEnrico Granata 37221dfcd9dSEnrico Granata static ConstString g_dylibext("dylib"); 37321dfcd9dSEnrico Granata 37421dfcd9dSEnrico Granata if (!baton) 37521dfcd9dSEnrico Granata return FileSpec::eEnumerateDirectoryResultQuit; 37621dfcd9dSEnrico Granata 37721dfcd9dSEnrico Granata Debugger *debugger = (Debugger*)baton; 37821dfcd9dSEnrico Granata 37921dfcd9dSEnrico Granata // If we have a regular file, a symbolic link or unknown file type, try 38021dfcd9dSEnrico Granata // and process the file. We must handle unknown as sometimes the directory 38121dfcd9dSEnrico Granata // enumeration might be enumerating a file system that doesn't have correct 38221dfcd9dSEnrico Granata // file type information. 38321dfcd9dSEnrico Granata if (file_type == FileSpec::eFileTypeRegular || 38421dfcd9dSEnrico Granata file_type == FileSpec::eFileTypeSymbolicLink || 38521dfcd9dSEnrico Granata file_type == FileSpec::eFileTypeUnknown ) 38621dfcd9dSEnrico Granata { 38721dfcd9dSEnrico Granata FileSpec plugin_file_spec (file_spec); 38821dfcd9dSEnrico Granata plugin_file_spec.ResolvePath (); 38921dfcd9dSEnrico Granata 39021dfcd9dSEnrico Granata if (plugin_file_spec.GetFileNameExtension() != g_dylibext) 39121dfcd9dSEnrico Granata return FileSpec::eEnumerateDirectoryResultNext; 39221dfcd9dSEnrico Granata 39321dfcd9dSEnrico Granata debugger->LoadPlugin (plugin_file_spec); 39421dfcd9dSEnrico Granata 39521dfcd9dSEnrico Granata return FileSpec::eEnumerateDirectoryResultNext; 39621dfcd9dSEnrico Granata } 39721dfcd9dSEnrico Granata 39821dfcd9dSEnrico Granata else if (file_type == FileSpec::eFileTypeUnknown || 39921dfcd9dSEnrico Granata file_type == FileSpec::eFileTypeDirectory || 40021dfcd9dSEnrico Granata file_type == FileSpec::eFileTypeSymbolicLink ) 40121dfcd9dSEnrico Granata { 40221dfcd9dSEnrico Granata // Try and recurse into anything that a directory or symbolic link. 40321dfcd9dSEnrico Granata // We must also do this for unknown as sometimes the directory enumeration 40421dfcd9dSEnrico Granata // might be enurating a file system that doesn't have correct file type 40521dfcd9dSEnrico Granata // information. 40621dfcd9dSEnrico Granata return FileSpec::eEnumerateDirectoryResultEnter; 40721dfcd9dSEnrico Granata } 40821dfcd9dSEnrico Granata 40921dfcd9dSEnrico Granata return FileSpec::eEnumerateDirectoryResultNext; 41021dfcd9dSEnrico Granata } 41121dfcd9dSEnrico Granata 41221dfcd9dSEnrico Granata void 41321dfcd9dSEnrico Granata Debugger::InstanceInitialize () 41421dfcd9dSEnrico Granata { 41521dfcd9dSEnrico Granata FileSpec dir_spec; 41621dfcd9dSEnrico Granata const bool find_directories = true; 41721dfcd9dSEnrico Granata const bool find_files = true; 41821dfcd9dSEnrico Granata const bool find_other = true; 41921dfcd9dSEnrico Granata char dir_path[PATH_MAX]; 42021dfcd9dSEnrico Granata if (Host::GetLLDBPath (ePathTypeLLDBSystemPlugins, dir_spec)) 42121dfcd9dSEnrico Granata { 42221dfcd9dSEnrico Granata if (dir_spec.Exists() && dir_spec.GetPath(dir_path, sizeof(dir_path))) 42321dfcd9dSEnrico Granata { 42421dfcd9dSEnrico Granata FileSpec::EnumerateDirectory (dir_path, 42521dfcd9dSEnrico Granata find_directories, 42621dfcd9dSEnrico Granata find_files, 42721dfcd9dSEnrico Granata find_other, 42821dfcd9dSEnrico Granata LoadPluginCallback, 42921dfcd9dSEnrico Granata this); 43021dfcd9dSEnrico Granata } 43121dfcd9dSEnrico Granata } 43221dfcd9dSEnrico Granata 43321dfcd9dSEnrico Granata if (Host::GetLLDBPath (ePathTypeLLDBUserPlugins, dir_spec)) 43421dfcd9dSEnrico Granata { 43521dfcd9dSEnrico Granata if (dir_spec.Exists() && dir_spec.GetPath(dir_path, sizeof(dir_path))) 43621dfcd9dSEnrico Granata { 43721dfcd9dSEnrico Granata FileSpec::EnumerateDirectory (dir_path, 43821dfcd9dSEnrico Granata find_directories, 43921dfcd9dSEnrico Granata find_files, 44021dfcd9dSEnrico Granata find_other, 44121dfcd9dSEnrico Granata LoadPluginCallback, 44221dfcd9dSEnrico Granata this); 44321dfcd9dSEnrico Granata } 44421dfcd9dSEnrico Granata } 445e8cd0c98SGreg Clayton 446e8cd0c98SGreg Clayton PluginManager::DebuggerInitialize (*this); 44721dfcd9dSEnrico Granata } 44821dfcd9dSEnrico Granata 4496611103cSGreg Clayton DebuggerSP 450228063cdSJim Ingham Debugger::CreateInstance (lldb::LogOutputCallback log_callback, void *baton) 4516611103cSGreg Clayton { 452228063cdSJim Ingham DebuggerSP debugger_sp (new Debugger(log_callback, baton)); 453c15f55e2SGreg Clayton if (g_shared_debugger_refcount > 0) 4546611103cSGreg Clayton { 4556611103cSGreg Clayton Mutex::Locker locker (GetDebuggerListMutex ()); 4566611103cSGreg Clayton GetDebuggerList().push_back(debugger_sp); 4576611103cSGreg Clayton } 45821dfcd9dSEnrico Granata debugger_sp->InstanceInitialize (); 4596611103cSGreg Clayton return debugger_sp; 4606611103cSGreg Clayton } 4616611103cSGreg Clayton 462e02657b1SCaroline Tice void 4634d122c40SGreg Clayton Debugger::Destroy (DebuggerSP &debugger_sp) 464e02657b1SCaroline Tice { 465e02657b1SCaroline Tice if (debugger_sp.get() == NULL) 466e02657b1SCaroline Tice return; 467e02657b1SCaroline Tice 4688314c525SJim Ingham debugger_sp->Clear(); 4698314c525SJim Ingham 470c15f55e2SGreg Clayton if (g_shared_debugger_refcount > 0) 471c15f55e2SGreg Clayton { 472e02657b1SCaroline Tice Mutex::Locker locker (GetDebuggerListMutex ()); 473e02657b1SCaroline Tice DebuggerList &debugger_list = GetDebuggerList (); 474e02657b1SCaroline Tice DebuggerList::iterator pos, end = debugger_list.end(); 475e02657b1SCaroline Tice for (pos = debugger_list.begin (); pos != end; ++pos) 476e02657b1SCaroline Tice { 477e02657b1SCaroline Tice if ((*pos).get() == debugger_sp.get()) 478e02657b1SCaroline Tice { 479e02657b1SCaroline Tice debugger_list.erase (pos); 480e02657b1SCaroline Tice return; 481e02657b1SCaroline Tice } 482e02657b1SCaroline Tice } 483e02657b1SCaroline Tice } 484c15f55e2SGreg Clayton } 485e02657b1SCaroline Tice 4864d122c40SGreg Clayton DebuggerSP 4873df9a8dfSCaroline Tice Debugger::FindDebuggerWithInstanceName (const ConstString &instance_name) 4883df9a8dfSCaroline Tice { 4894d122c40SGreg Clayton DebuggerSP debugger_sp; 4906920b52bSGreg Clayton if (g_shared_debugger_refcount > 0) 4916920b52bSGreg Clayton { 4926920b52bSGreg Clayton Mutex::Locker locker (GetDebuggerListMutex ()); 4936920b52bSGreg Clayton DebuggerList &debugger_list = GetDebuggerList(); 4946920b52bSGreg Clayton DebuggerList::iterator pos, end = debugger_list.end(); 4956920b52bSGreg Clayton 4966920b52bSGreg Clayton for (pos = debugger_list.begin(); pos != end; ++pos) 4976920b52bSGreg Clayton { 4986920b52bSGreg Clayton if ((*pos).get()->m_instance_name == instance_name) 4996920b52bSGreg Clayton { 5006920b52bSGreg Clayton debugger_sp = *pos; 5016920b52bSGreg Clayton break; 5026920b52bSGreg Clayton } 5036920b52bSGreg Clayton } 5046920b52bSGreg Clayton } 5053df9a8dfSCaroline Tice return debugger_sp; 5063df9a8dfSCaroline Tice } 5076611103cSGreg Clayton 5086611103cSGreg Clayton TargetSP 5096611103cSGreg Clayton Debugger::FindTargetWithProcessID (lldb::pid_t pid) 5106611103cSGreg Clayton { 5114d122c40SGreg Clayton TargetSP target_sp; 512c15f55e2SGreg Clayton if (g_shared_debugger_refcount > 0) 513c15f55e2SGreg Clayton { 5146611103cSGreg Clayton Mutex::Locker locker (GetDebuggerListMutex ()); 5156611103cSGreg Clayton DebuggerList &debugger_list = GetDebuggerList(); 5166611103cSGreg Clayton DebuggerList::iterator pos, end = debugger_list.end(); 5176611103cSGreg Clayton for (pos = debugger_list.begin(); pos != end; ++pos) 5186611103cSGreg Clayton { 5196611103cSGreg Clayton target_sp = (*pos)->GetTargetList().FindTargetWithProcessID (pid); 5206611103cSGreg Clayton if (target_sp) 5216611103cSGreg Clayton break; 5226611103cSGreg Clayton } 523c15f55e2SGreg Clayton } 5246611103cSGreg Clayton return target_sp; 5256611103cSGreg Clayton } 5266611103cSGreg Clayton 527e4e45924SGreg Clayton TargetSP 528e4e45924SGreg Clayton Debugger::FindTargetWithProcess (Process *process) 529e4e45924SGreg Clayton { 530e4e45924SGreg Clayton TargetSP target_sp; 531c15f55e2SGreg Clayton if (g_shared_debugger_refcount > 0) 532c15f55e2SGreg Clayton { 533e4e45924SGreg Clayton Mutex::Locker locker (GetDebuggerListMutex ()); 534e4e45924SGreg Clayton DebuggerList &debugger_list = GetDebuggerList(); 535e4e45924SGreg Clayton DebuggerList::iterator pos, end = debugger_list.end(); 536e4e45924SGreg Clayton for (pos = debugger_list.begin(); pos != end; ++pos) 537e4e45924SGreg Clayton { 538e4e45924SGreg Clayton target_sp = (*pos)->GetTargetList().FindTargetWithProcess (process); 539e4e45924SGreg Clayton if (target_sp) 540e4e45924SGreg Clayton break; 541e4e45924SGreg Clayton } 542c15f55e2SGreg Clayton } 543e4e45924SGreg Clayton return target_sp; 544e4e45924SGreg Clayton } 545e4e45924SGreg Clayton 546228063cdSJim Ingham Debugger::Debugger (lldb::LogOutputCallback log_callback, void *baton) : 547ebc1bb27SCaroline Tice UserID (g_unique_id++), 54867cc0636SGreg Clayton Properties(OptionValuePropertiesSP(new OptionValueProperties())), 549d46c87a1SGreg Clayton m_input_comm("debugger.input"), 55030fdc8d8SChris Lattner m_input_file (), 55130fdc8d8SChris Lattner m_output_file (), 55230fdc8d8SChris Lattner m_error_file (), 553c5917d9aSJim Ingham m_terminal_state (), 5544bddaeb5SJim Ingham m_target_list (*this), 555ded470d3SGreg Clayton m_platform_list (), 55630fdc8d8SChris Lattner m_listener ("lldb.Debugger"), 557e37d605eSJim Ingham m_source_manager(*this), 558e37d605eSJim Ingham m_source_file_cache(), 5596611103cSGreg Clayton m_command_interpreter_ap (new CommandInterpreter (*this, eScriptLanguageDefault, false)), 560d5a0a01bSCaroline Tice m_input_reader_stack (), 56167cc0636SGreg Clayton m_input_reader_data (), 56267cc0636SGreg Clayton m_instance_name() 56330fdc8d8SChris Lattner { 56467cc0636SGreg Clayton char instance_cstr[256]; 56567cc0636SGreg Clayton snprintf(instance_cstr, sizeof(instance_cstr), "debugger_%d", (int)GetID()); 56667cc0636SGreg Clayton m_instance_name.SetCString(instance_cstr); 567228063cdSJim Ingham if (log_callback) 568228063cdSJim Ingham m_log_callback_stream_sp.reset (new StreamCallback (log_callback, baton)); 5696611103cSGreg Clayton m_command_interpreter_ap->Initialize (); 570ded470d3SGreg Clayton // Always add our default platform to the platform list 571ded470d3SGreg Clayton PlatformSP default_platform_sp (Platform::GetDefaultPlatform()); 572ded470d3SGreg Clayton assert (default_platform_sp.get()); 573ded470d3SGreg Clayton m_platform_list.Append (default_platform_sp, true); 57467cc0636SGreg Clayton 575754a9369SGreg Clayton m_collection_sp->Initialize (g_properties); 57667cc0636SGreg Clayton m_collection_sp->AppendProperty (ConstString("target"), 57767cc0636SGreg Clayton ConstString("Settings specify to debugging targets."), 57867cc0636SGreg Clayton true, 57967cc0636SGreg Clayton Target::GetGlobalProperties()->GetValueProperties()); 580754a9369SGreg Clayton if (m_command_interpreter_ap.get()) 581754a9369SGreg Clayton { 582754a9369SGreg Clayton m_collection_sp->AppendProperty (ConstString("interpreter"), 583754a9369SGreg Clayton ConstString("Settings specify to the debugger's command interpreter."), 584754a9369SGreg Clayton true, 585754a9369SGreg Clayton m_command_interpreter_ap->GetValueProperties()); 586754a9369SGreg Clayton } 58767cc0636SGreg Clayton OptionValueSInt64 *term_width = m_collection_sp->GetPropertyAtIndexAsOptionValueSInt64 (NULL, ePropertyTerminalWidth); 58867cc0636SGreg Clayton term_width->SetMinimumValue(10); 58967cc0636SGreg Clayton term_width->SetMaximumValue(1024); 59030fdc8d8SChris Lattner } 59130fdc8d8SChris Lattner 59230fdc8d8SChris Lattner Debugger::~Debugger () 59330fdc8d8SChris Lattner { 5948314c525SJim Ingham Clear(); 5958314c525SJim Ingham } 5968314c525SJim Ingham 5978314c525SJim Ingham void 5988314c525SJim Ingham Debugger::Clear() 5998314c525SJim Ingham { 6003d6086f6SCaroline Tice CleanUpInputReaders(); 6011ed54f50SGreg Clayton m_listener.Clear(); 6026611103cSGreg Clayton int num_targets = m_target_list.GetNumTargets(); 6036611103cSGreg Clayton for (int i = 0; i < num_targets; i++) 6046611103cSGreg Clayton { 605ccbc08e6SGreg Clayton TargetSP target_sp (m_target_list.GetTargetAtIndex (i)); 606ccbc08e6SGreg Clayton if (target_sp) 607ccbc08e6SGreg Clayton { 608ccbc08e6SGreg Clayton ProcessSP process_sp (target_sp->GetProcessSP()); 6096611103cSGreg Clayton if (process_sp) 6108314c525SJim Ingham { 611e24c4acfSGreg Clayton if (process_sp->GetShouldDetach()) 6128314c525SJim Ingham process_sp->Detach(); 613ccbc08e6SGreg Clayton } 614ccbc08e6SGreg Clayton target_sp->Destroy(); 6156611103cSGreg Clayton } 61630fdc8d8SChris Lattner } 6174bddaeb5SJim Ingham BroadcasterManager::Clear (); 61830fdc8d8SChris Lattner 6190d69a3a4SGreg Clayton // Close the input file _before_ we close the input read communications class 6200d69a3a4SGreg Clayton // as it does NOT own the input file, our m_input_file does. 621c5917d9aSJim Ingham m_terminal_state.Clear(); 6220d69a3a4SGreg Clayton GetInputFile().Close (); 6230d69a3a4SGreg Clayton // Now that we have closed m_input_file, we can now tell our input communication 6240d69a3a4SGreg Clayton // class to close down. Its read thread should quickly exit after we close 6250d69a3a4SGreg Clayton // the input file handle above. 6260d69a3a4SGreg Clayton m_input_comm.Clear (); 6278314c525SJim Ingham } 62830fdc8d8SChris Lattner 62930fdc8d8SChris Lattner bool 630fc3f027dSGreg Clayton Debugger::GetCloseInputOnEOF () const 631fc3f027dSGreg Clayton { 632fc3f027dSGreg Clayton return m_input_comm.GetCloseOnEOF(); 633fc3f027dSGreg Clayton } 634fc3f027dSGreg Clayton 635fc3f027dSGreg Clayton void 636fc3f027dSGreg Clayton Debugger::SetCloseInputOnEOF (bool b) 637fc3f027dSGreg Clayton { 638fc3f027dSGreg Clayton m_input_comm.SetCloseOnEOF(b); 639fc3f027dSGreg Clayton } 640fc3f027dSGreg Clayton 641fc3f027dSGreg Clayton bool 64230fdc8d8SChris Lattner Debugger::GetAsyncExecution () 64330fdc8d8SChris Lattner { 6446611103cSGreg Clayton return !m_command_interpreter_ap->GetSynchronous(); 64530fdc8d8SChris Lattner } 64630fdc8d8SChris Lattner 64730fdc8d8SChris Lattner void 64830fdc8d8SChris Lattner Debugger::SetAsyncExecution (bool async_execution) 64930fdc8d8SChris Lattner { 6506611103cSGreg Clayton m_command_interpreter_ap->SetSynchronous (!async_execution); 65130fdc8d8SChris Lattner } 65230fdc8d8SChris Lattner 65330fdc8d8SChris Lattner 65430fdc8d8SChris Lattner void 65530fdc8d8SChris Lattner Debugger::SetInputFileHandle (FILE *fh, bool tranfer_ownership) 65630fdc8d8SChris Lattner { 65751b1e2d2SGreg Clayton File &in_file = GetInputFile(); 65851b1e2d2SGreg Clayton in_file.SetStream (fh, tranfer_ownership); 65951b1e2d2SGreg Clayton if (in_file.IsValid() == false) 66051b1e2d2SGreg Clayton in_file.SetStream (stdin, true); 66130fdc8d8SChris Lattner 66230fdc8d8SChris Lattner // Disconnect from any old connection if we had one 66330fdc8d8SChris Lattner m_input_comm.Disconnect (); 66432720b51SGreg Clayton // Pass false as the second argument to ConnectionFileDescriptor below because 66532720b51SGreg Clayton // our "in_file" above will already take ownership if requested and we don't 66632720b51SGreg Clayton // want to objects trying to own and close a file descriptor. 66732720b51SGreg Clayton m_input_comm.SetConnection (new ConnectionFileDescriptor (in_file.GetDescriptor(), false)); 66830fdc8d8SChris Lattner m_input_comm.SetReadThreadBytesReceivedCallback (Debugger::DispatchInputCallback, this); 66930fdc8d8SChris Lattner 670c5917d9aSJim Ingham // Save away the terminal state if that is relevant, so that we can restore it in RestoreInputState. 671c5917d9aSJim Ingham SaveInputTerminalState (); 672c5917d9aSJim Ingham 67330fdc8d8SChris Lattner Error error; 67430fdc8d8SChris Lattner if (m_input_comm.StartReadThread (&error) == false) 67530fdc8d8SChris Lattner { 67651b1e2d2SGreg Clayton File &err_file = GetErrorFile(); 67751b1e2d2SGreg Clayton 67851b1e2d2SGreg Clayton err_file.Printf ("error: failed to main input read thread: %s", error.AsCString() ? error.AsCString() : "unkown error"); 67930fdc8d8SChris Lattner exit(1); 68030fdc8d8SChris Lattner } 68130fdc8d8SChris Lattner } 68230fdc8d8SChris Lattner 68330fdc8d8SChris Lattner void 68430fdc8d8SChris Lattner Debugger::SetOutputFileHandle (FILE *fh, bool tranfer_ownership) 68530fdc8d8SChris Lattner { 68651b1e2d2SGreg Clayton File &out_file = GetOutputFile(); 68751b1e2d2SGreg Clayton out_file.SetStream (fh, tranfer_ownership); 68851b1e2d2SGreg Clayton if (out_file.IsValid() == false) 68951b1e2d2SGreg Clayton out_file.SetStream (stdout, false); 6902f88aadfSCaroline Tice 691b588726eSEnrico Granata // do not create the ScriptInterpreter just for setting the output file handle 692b588726eSEnrico Granata // as the constructor will know how to do the right thing on its own 693b588726eSEnrico Granata const bool can_create = false; 694b588726eSEnrico Granata ScriptInterpreter* script_interpreter = GetCommandInterpreter().GetScriptInterpreter(can_create); 695b588726eSEnrico Granata if (script_interpreter) 696b588726eSEnrico Granata script_interpreter->ResetOutputFileHandle (fh); 69730fdc8d8SChris Lattner } 69830fdc8d8SChris Lattner 69930fdc8d8SChris Lattner void 70030fdc8d8SChris Lattner Debugger::SetErrorFileHandle (FILE *fh, bool tranfer_ownership) 70130fdc8d8SChris Lattner { 70251b1e2d2SGreg Clayton File &err_file = GetErrorFile(); 70351b1e2d2SGreg Clayton err_file.SetStream (fh, tranfer_ownership); 70451b1e2d2SGreg Clayton if (err_file.IsValid() == false) 70551b1e2d2SGreg Clayton err_file.SetStream (stderr, false); 70630fdc8d8SChris Lattner } 70730fdc8d8SChris Lattner 708c5917d9aSJim Ingham void 709c5917d9aSJim Ingham Debugger::SaveInputTerminalState () 710c5917d9aSJim Ingham { 711c5917d9aSJim Ingham File &in_file = GetInputFile(); 712c5917d9aSJim Ingham if (in_file.GetDescriptor() != File::kInvalidDescriptor) 713c5917d9aSJim Ingham m_terminal_state.Save(in_file.GetDescriptor(), true); 714c5917d9aSJim Ingham } 715c5917d9aSJim Ingham 716c5917d9aSJim Ingham void 717c5917d9aSJim Ingham Debugger::RestoreInputTerminalState () 718c5917d9aSJim Ingham { 719c5917d9aSJim Ingham m_terminal_state.Restore(); 720c5917d9aSJim Ingham } 721c5917d9aSJim Ingham 72230fdc8d8SChris Lattner ExecutionContext 7232976d00aSJim Ingham Debugger::GetSelectedExecutionContext () 72430fdc8d8SChris Lattner { 72530fdc8d8SChris Lattner ExecutionContext exe_ctx; 726c14ee32dSGreg Clayton TargetSP target_sp(GetSelectedTarget()); 727c14ee32dSGreg Clayton exe_ctx.SetTargetSP (target_sp); 72830fdc8d8SChris Lattner 72930fdc8d8SChris Lattner if (target_sp) 73030fdc8d8SChris Lattner { 731c14ee32dSGreg Clayton ProcessSP process_sp (target_sp->GetProcessSP()); 732c14ee32dSGreg Clayton exe_ctx.SetProcessSP (process_sp); 733c14ee32dSGreg Clayton if (process_sp && process_sp->IsRunning() == false) 73430fdc8d8SChris Lattner { 735c14ee32dSGreg Clayton ThreadSP thread_sp (process_sp->GetThreadList().GetSelectedThread()); 736c14ee32dSGreg Clayton if (thread_sp) 73730fdc8d8SChris Lattner { 738c14ee32dSGreg Clayton exe_ctx.SetThreadSP (thread_sp); 739c14ee32dSGreg Clayton exe_ctx.SetFrameSP (thread_sp->GetSelectedFrame()); 740c14ee32dSGreg Clayton if (exe_ctx.GetFramePtr() == NULL) 741c14ee32dSGreg Clayton exe_ctx.SetFrameSP (thread_sp->GetStackFrameAtIndex (0)); 74230fdc8d8SChris Lattner } 74330fdc8d8SChris Lattner } 74430fdc8d8SChris Lattner } 74530fdc8d8SChris Lattner return exe_ctx; 74630fdc8d8SChris Lattner 74730fdc8d8SChris Lattner } 74830fdc8d8SChris Lattner 749b44880caSCaroline Tice InputReaderSP 750b44880caSCaroline Tice Debugger::GetCurrentInputReader () 751b44880caSCaroline Tice { 752b44880caSCaroline Tice InputReaderSP reader_sp; 753b44880caSCaroline Tice 754d5a0a01bSCaroline Tice if (!m_input_reader_stack.IsEmpty()) 755b44880caSCaroline Tice { 756b44880caSCaroline Tice // Clear any finished readers from the stack 757b44880caSCaroline Tice while (CheckIfTopInputReaderIsDone()) ; 758b44880caSCaroline Tice 759d5a0a01bSCaroline Tice if (!m_input_reader_stack.IsEmpty()) 760d5a0a01bSCaroline Tice reader_sp = m_input_reader_stack.Top(); 761b44880caSCaroline Tice } 762b44880caSCaroline Tice 763b44880caSCaroline Tice return reader_sp; 764b44880caSCaroline Tice } 765b44880caSCaroline Tice 76630fdc8d8SChris Lattner void 76730fdc8d8SChris Lattner Debugger::DispatchInputCallback (void *baton, const void *bytes, size_t bytes_len) 76830fdc8d8SChris Lattner { 769efed6131SCaroline Tice if (bytes_len > 0) 77030fdc8d8SChris Lattner ((Debugger *)baton)->DispatchInput ((char *)bytes, bytes_len); 771efed6131SCaroline Tice else 772efed6131SCaroline Tice ((Debugger *)baton)->DispatchInputEndOfFile (); 77330fdc8d8SChris Lattner } 77430fdc8d8SChris Lattner 77530fdc8d8SChris Lattner 77630fdc8d8SChris Lattner void 77730fdc8d8SChris Lattner Debugger::DispatchInput (const char *bytes, size_t bytes_len) 77830fdc8d8SChris Lattner { 779efed6131SCaroline Tice if (bytes == NULL || bytes_len == 0) 780efed6131SCaroline Tice return; 78130fdc8d8SChris Lattner 78230fdc8d8SChris Lattner WriteToDefaultReader (bytes, bytes_len); 78330fdc8d8SChris Lattner } 78430fdc8d8SChris Lattner 78530fdc8d8SChris Lattner void 786efed6131SCaroline Tice Debugger::DispatchInputInterrupt () 787efed6131SCaroline Tice { 788efed6131SCaroline Tice m_input_reader_data.clear(); 789efed6131SCaroline Tice 790b44880caSCaroline Tice InputReaderSP reader_sp (GetCurrentInputReader ()); 791efed6131SCaroline Tice if (reader_sp) 792b44880caSCaroline Tice { 793efed6131SCaroline Tice reader_sp->Notify (eInputReaderInterrupt); 794efed6131SCaroline Tice 795b44880caSCaroline Tice // If notifying the reader of the interrupt finished the reader, we should pop it off the stack. 796efed6131SCaroline Tice while (CheckIfTopInputReaderIsDone ()) ; 797efed6131SCaroline Tice } 798efed6131SCaroline Tice } 799efed6131SCaroline Tice 800efed6131SCaroline Tice void 801efed6131SCaroline Tice Debugger::DispatchInputEndOfFile () 802efed6131SCaroline Tice { 803efed6131SCaroline Tice m_input_reader_data.clear(); 804efed6131SCaroline Tice 805b44880caSCaroline Tice InputReaderSP reader_sp (GetCurrentInputReader ()); 806efed6131SCaroline Tice if (reader_sp) 807b44880caSCaroline Tice { 808efed6131SCaroline Tice reader_sp->Notify (eInputReaderEndOfFile); 809efed6131SCaroline Tice 810b44880caSCaroline Tice // If notifying the reader of the end-of-file finished the reader, we should pop it off the stack. 811efed6131SCaroline Tice while (CheckIfTopInputReaderIsDone ()) ; 812efed6131SCaroline Tice } 813efed6131SCaroline Tice } 814efed6131SCaroline Tice 815efed6131SCaroline Tice void 8163d6086f6SCaroline Tice Debugger::CleanUpInputReaders () 8173d6086f6SCaroline Tice { 8183d6086f6SCaroline Tice m_input_reader_data.clear(); 8193d6086f6SCaroline Tice 820b44880caSCaroline Tice // The bottom input reader should be the main debugger input reader. We do not want to close that one here. 821d5a0a01bSCaroline Tice while (m_input_reader_stack.GetSize() > 1) 8223d6086f6SCaroline Tice { 823b44880caSCaroline Tice InputReaderSP reader_sp (GetCurrentInputReader ()); 8243d6086f6SCaroline Tice if (reader_sp) 8253d6086f6SCaroline Tice { 8263d6086f6SCaroline Tice reader_sp->Notify (eInputReaderEndOfFile); 8273d6086f6SCaroline Tice reader_sp->SetIsDone (true); 8283d6086f6SCaroline Tice } 8293d6086f6SCaroline Tice } 8303d6086f6SCaroline Tice } 8313d6086f6SCaroline Tice 8323d6086f6SCaroline Tice void 833969ed3d1SCaroline Tice Debugger::NotifyTopInputReader (InputReaderAction notification) 834969ed3d1SCaroline Tice { 835969ed3d1SCaroline Tice InputReaderSP reader_sp (GetCurrentInputReader()); 836969ed3d1SCaroline Tice if (reader_sp) 837969ed3d1SCaroline Tice { 838969ed3d1SCaroline Tice reader_sp->Notify (notification); 839969ed3d1SCaroline Tice 840969ed3d1SCaroline Tice // Flush out any input readers that are done. 841969ed3d1SCaroline Tice while (CheckIfTopInputReaderIsDone ()) 842969ed3d1SCaroline Tice /* Do nothing. */; 843969ed3d1SCaroline Tice } 844969ed3d1SCaroline Tice } 845969ed3d1SCaroline Tice 8469088b068SCaroline Tice bool 8474d122c40SGreg Clayton Debugger::InputReaderIsTopReader (const InputReaderSP& reader_sp) 8489088b068SCaroline Tice { 8499088b068SCaroline Tice InputReaderSP top_reader_sp (GetCurrentInputReader()); 8509088b068SCaroline Tice 851d61c10bcSCaroline Tice return (reader_sp.get() == top_reader_sp.get()); 8529088b068SCaroline Tice } 8539088b068SCaroline Tice 8549088b068SCaroline Tice 855969ed3d1SCaroline Tice void 85630fdc8d8SChris Lattner Debugger::WriteToDefaultReader (const char *bytes, size_t bytes_len) 85730fdc8d8SChris Lattner { 85830fdc8d8SChris Lattner if (bytes && bytes_len) 85930fdc8d8SChris Lattner m_input_reader_data.append (bytes, bytes_len); 86030fdc8d8SChris Lattner 86130fdc8d8SChris Lattner if (m_input_reader_data.empty()) 86230fdc8d8SChris Lattner return; 86330fdc8d8SChris Lattner 864d5a0a01bSCaroline Tice while (!m_input_reader_stack.IsEmpty() && !m_input_reader_data.empty()) 86530fdc8d8SChris Lattner { 86630fdc8d8SChris Lattner // Get the input reader from the top of the stack 867b44880caSCaroline Tice InputReaderSP reader_sp (GetCurrentInputReader ()); 86830fdc8d8SChris Lattner if (!reader_sp) 86930fdc8d8SChris Lattner break; 87030fdc8d8SChris Lattner 871471b31ceSGreg Clayton size_t bytes_handled = reader_sp->HandleRawBytes (m_input_reader_data.c_str(), 87230fdc8d8SChris Lattner m_input_reader_data.size()); 87330fdc8d8SChris Lattner if (bytes_handled) 87430fdc8d8SChris Lattner { 87530fdc8d8SChris Lattner m_input_reader_data.erase (0, bytes_handled); 87630fdc8d8SChris Lattner } 87730fdc8d8SChris Lattner else 87830fdc8d8SChris Lattner { 87930fdc8d8SChris Lattner // No bytes were handled, we might not have reached our 88030fdc8d8SChris Lattner // granularity, just return and wait for more data 88130fdc8d8SChris Lattner break; 88230fdc8d8SChris Lattner } 88330fdc8d8SChris Lattner } 88430fdc8d8SChris Lattner 885b44880caSCaroline Tice // Flush out any input readers that are done. 88630fdc8d8SChris Lattner while (CheckIfTopInputReaderIsDone ()) 88730fdc8d8SChris Lattner /* Do nothing. */; 88830fdc8d8SChris Lattner 88930fdc8d8SChris Lattner } 89030fdc8d8SChris Lattner 89130fdc8d8SChris Lattner void 89230fdc8d8SChris Lattner Debugger::PushInputReader (const InputReaderSP& reader_sp) 89330fdc8d8SChris Lattner { 89430fdc8d8SChris Lattner if (!reader_sp) 89530fdc8d8SChris Lattner return; 896b44880caSCaroline Tice 89730fdc8d8SChris Lattner // Deactivate the old top reader 898b44880caSCaroline Tice InputReaderSP top_reader_sp (GetCurrentInputReader ()); 899b44880caSCaroline Tice 90030fdc8d8SChris Lattner if (top_reader_sp) 90130fdc8d8SChris Lattner top_reader_sp->Notify (eInputReaderDeactivate); 902b44880caSCaroline Tice 903d5a0a01bSCaroline Tice m_input_reader_stack.Push (reader_sp); 90430fdc8d8SChris Lattner reader_sp->Notify (eInputReaderActivate); 90530fdc8d8SChris Lattner ActivateInputReader (reader_sp); 90630fdc8d8SChris Lattner } 90730fdc8d8SChris Lattner 90830fdc8d8SChris Lattner bool 9094d122c40SGreg Clayton Debugger::PopInputReader (const InputReaderSP& pop_reader_sp) 91030fdc8d8SChris Lattner { 91130fdc8d8SChris Lattner bool result = false; 91230fdc8d8SChris Lattner 91330fdc8d8SChris Lattner // The reader on the stop of the stack is done, so let the next 91430fdc8d8SChris Lattner // read on the stack referesh its prompt and if there is one... 915d5a0a01bSCaroline Tice if (!m_input_reader_stack.IsEmpty()) 91630fdc8d8SChris Lattner { 917b44880caSCaroline Tice // Cannot call GetCurrentInputReader here, as that would cause an infinite loop. 918d5a0a01bSCaroline Tice InputReaderSP reader_sp(m_input_reader_stack.Top()); 91930fdc8d8SChris Lattner 92030fdc8d8SChris Lattner if (!pop_reader_sp || pop_reader_sp.get() == reader_sp.get()) 92130fdc8d8SChris Lattner { 922d5a0a01bSCaroline Tice m_input_reader_stack.Pop (); 92330fdc8d8SChris Lattner reader_sp->Notify (eInputReaderDeactivate); 92430fdc8d8SChris Lattner reader_sp->Notify (eInputReaderDone); 92530fdc8d8SChris Lattner result = true; 92630fdc8d8SChris Lattner 927d5a0a01bSCaroline Tice if (!m_input_reader_stack.IsEmpty()) 92830fdc8d8SChris Lattner { 929d5a0a01bSCaroline Tice reader_sp = m_input_reader_stack.Top(); 93030fdc8d8SChris Lattner if (reader_sp) 93130fdc8d8SChris Lattner { 93230fdc8d8SChris Lattner ActivateInputReader (reader_sp); 93330fdc8d8SChris Lattner reader_sp->Notify (eInputReaderReactivate); 93430fdc8d8SChris Lattner } 93530fdc8d8SChris Lattner } 93630fdc8d8SChris Lattner } 93730fdc8d8SChris Lattner } 93830fdc8d8SChris Lattner return result; 93930fdc8d8SChris Lattner } 94030fdc8d8SChris Lattner 94130fdc8d8SChris Lattner bool 94230fdc8d8SChris Lattner Debugger::CheckIfTopInputReaderIsDone () 94330fdc8d8SChris Lattner { 94430fdc8d8SChris Lattner bool result = false; 945d5a0a01bSCaroline Tice if (!m_input_reader_stack.IsEmpty()) 94630fdc8d8SChris Lattner { 947b44880caSCaroline Tice // Cannot call GetCurrentInputReader here, as that would cause an infinite loop. 948d5a0a01bSCaroline Tice InputReaderSP reader_sp(m_input_reader_stack.Top()); 94930fdc8d8SChris Lattner 95030fdc8d8SChris Lattner if (reader_sp && reader_sp->IsDone()) 95130fdc8d8SChris Lattner { 95230fdc8d8SChris Lattner result = true; 95330fdc8d8SChris Lattner PopInputReader (reader_sp); 95430fdc8d8SChris Lattner } 95530fdc8d8SChris Lattner } 95630fdc8d8SChris Lattner return result; 95730fdc8d8SChris Lattner } 95830fdc8d8SChris Lattner 95930fdc8d8SChris Lattner void 96030fdc8d8SChris Lattner Debugger::ActivateInputReader (const InputReaderSP &reader_sp) 96130fdc8d8SChris Lattner { 96251b1e2d2SGreg Clayton int input_fd = m_input_file.GetFile().GetDescriptor(); 96330fdc8d8SChris Lattner 96451b1e2d2SGreg Clayton if (input_fd >= 0) 96530fdc8d8SChris Lattner { 96651b1e2d2SGreg Clayton Terminal tty(input_fd); 967a3406614SGreg Clayton 968a3406614SGreg Clayton tty.SetEcho(reader_sp->GetEcho()); 96930fdc8d8SChris Lattner 97030fdc8d8SChris Lattner switch (reader_sp->GetGranularity()) 97130fdc8d8SChris Lattner { 97230fdc8d8SChris Lattner case eInputReaderGranularityByte: 97330fdc8d8SChris Lattner case eInputReaderGranularityWord: 974a3406614SGreg Clayton tty.SetCanonical (false); 97530fdc8d8SChris Lattner break; 97630fdc8d8SChris Lattner 97730fdc8d8SChris Lattner case eInputReaderGranularityLine: 97830fdc8d8SChris Lattner case eInputReaderGranularityAll: 979a3406614SGreg Clayton tty.SetCanonical (true); 98030fdc8d8SChris Lattner break; 98130fdc8d8SChris Lattner 98230fdc8d8SChris Lattner default: 98330fdc8d8SChris Lattner break; 98430fdc8d8SChris Lattner } 98530fdc8d8SChris Lattner } 98630fdc8d8SChris Lattner } 9876611103cSGreg Clayton 9885b52f0c7SJim Ingham StreamSP 9895b52f0c7SJim Ingham Debugger::GetAsyncOutputStream () 9905b52f0c7SJim Ingham { 9915b52f0c7SJim Ingham return StreamSP (new StreamAsynchronousIO (GetCommandInterpreter(), 9925b52f0c7SJim Ingham CommandInterpreter::eBroadcastBitAsynchronousOutputData)); 9935b52f0c7SJim Ingham } 9945b52f0c7SJim Ingham 9955b52f0c7SJim Ingham StreamSP 9965b52f0c7SJim Ingham Debugger::GetAsyncErrorStream () 9975b52f0c7SJim Ingham { 9985b52f0c7SJim Ingham return StreamSP (new StreamAsynchronousIO (GetCommandInterpreter(), 9995b52f0c7SJim Ingham CommandInterpreter::eBroadcastBitAsynchronousErrorData)); 10005b52f0c7SJim Ingham } 10015b52f0c7SJim Ingham 1002061858ceSEnrico Granata uint32_t 1003061858ceSEnrico Granata Debugger::GetNumDebuggers() 1004061858ceSEnrico Granata { 1005c15f55e2SGreg Clayton if (g_shared_debugger_refcount > 0) 1006c15f55e2SGreg Clayton { 1007061858ceSEnrico Granata Mutex::Locker locker (GetDebuggerListMutex ()); 1008061858ceSEnrico Granata return GetDebuggerList().size(); 1009061858ceSEnrico Granata } 1010c15f55e2SGreg Clayton return 0; 1011c15f55e2SGreg Clayton } 1012061858ceSEnrico Granata 1013061858ceSEnrico Granata lldb::DebuggerSP 1014061858ceSEnrico Granata Debugger::GetDebuggerAtIndex (uint32_t index) 1015061858ceSEnrico Granata { 1016061858ceSEnrico Granata DebuggerSP debugger_sp; 1017061858ceSEnrico Granata 1018c15f55e2SGreg Clayton if (g_shared_debugger_refcount > 0) 1019c15f55e2SGreg Clayton { 1020061858ceSEnrico Granata Mutex::Locker locker (GetDebuggerListMutex ()); 1021061858ceSEnrico Granata DebuggerList &debugger_list = GetDebuggerList(); 1022061858ceSEnrico Granata 1023061858ceSEnrico Granata if (index < debugger_list.size()) 1024061858ceSEnrico Granata debugger_sp = debugger_list[index]; 1025c15f55e2SGreg Clayton } 1026061858ceSEnrico Granata 1027061858ceSEnrico Granata return debugger_sp; 1028061858ceSEnrico Granata } 1029061858ceSEnrico Granata 1030ebc1bb27SCaroline Tice DebuggerSP 1031ebc1bb27SCaroline Tice Debugger::FindDebuggerWithID (lldb::user_id_t id) 1032ebc1bb27SCaroline Tice { 10334d122c40SGreg Clayton DebuggerSP debugger_sp; 1034ebc1bb27SCaroline Tice 1035c15f55e2SGreg Clayton if (g_shared_debugger_refcount > 0) 1036c15f55e2SGreg Clayton { 1037ebc1bb27SCaroline Tice Mutex::Locker locker (GetDebuggerListMutex ()); 1038ebc1bb27SCaroline Tice DebuggerList &debugger_list = GetDebuggerList(); 1039ebc1bb27SCaroline Tice DebuggerList::iterator pos, end = debugger_list.end(); 1040ebc1bb27SCaroline Tice for (pos = debugger_list.begin(); pos != end; ++pos) 1041ebc1bb27SCaroline Tice { 1042ebc1bb27SCaroline Tice if ((*pos).get()->GetID() == id) 1043ebc1bb27SCaroline Tice { 1044ebc1bb27SCaroline Tice debugger_sp = *pos; 1045ebc1bb27SCaroline Tice break; 1046ebc1bb27SCaroline Tice } 1047ebc1bb27SCaroline Tice } 1048c15f55e2SGreg Clayton } 1049ebc1bb27SCaroline Tice return debugger_sp; 1050ebc1bb27SCaroline Tice } 10513df9a8dfSCaroline Tice 10521b654882SGreg Clayton static void 10531b654882SGreg Clayton TestPromptFormats (StackFrame *frame) 10541b654882SGreg Clayton { 10551b654882SGreg Clayton if (frame == NULL) 10561b654882SGreg Clayton return; 10571b654882SGreg Clayton 10581b654882SGreg Clayton StreamString s; 10591b654882SGreg Clayton const char *prompt_format = 10601b654882SGreg Clayton "{addr = '${addr}'\n}" 10611b654882SGreg Clayton "{process.id = '${process.id}'\n}" 10621b654882SGreg Clayton "{process.name = '${process.name}'\n}" 10631b654882SGreg Clayton "{process.file.basename = '${process.file.basename}'\n}" 10641b654882SGreg Clayton "{process.file.fullpath = '${process.file.fullpath}'\n}" 10651b654882SGreg Clayton "{thread.id = '${thread.id}'\n}" 10661b654882SGreg Clayton "{thread.index = '${thread.index}'\n}" 10671b654882SGreg Clayton "{thread.name = '${thread.name}'\n}" 10681b654882SGreg Clayton "{thread.queue = '${thread.queue}'\n}" 10691b654882SGreg Clayton "{thread.stop-reason = '${thread.stop-reason}'\n}" 10701b654882SGreg Clayton "{target.arch = '${target.arch}'\n}" 10711b654882SGreg Clayton "{module.file.basename = '${module.file.basename}'\n}" 10721b654882SGreg Clayton "{module.file.fullpath = '${module.file.fullpath}'\n}" 10731b654882SGreg Clayton "{file.basename = '${file.basename}'\n}" 10741b654882SGreg Clayton "{file.fullpath = '${file.fullpath}'\n}" 10751b654882SGreg Clayton "{frame.index = '${frame.index}'\n}" 10761b654882SGreg Clayton "{frame.pc = '${frame.pc}'\n}" 10771b654882SGreg Clayton "{frame.sp = '${frame.sp}'\n}" 10781b654882SGreg Clayton "{frame.fp = '${frame.fp}'\n}" 10791b654882SGreg Clayton "{frame.flags = '${frame.flags}'\n}" 10801b654882SGreg Clayton "{frame.reg.rdi = '${frame.reg.rdi}'\n}" 10811b654882SGreg Clayton "{frame.reg.rip = '${frame.reg.rip}'\n}" 10821b654882SGreg Clayton "{frame.reg.rsp = '${frame.reg.rsp}'\n}" 10831b654882SGreg Clayton "{frame.reg.rbp = '${frame.reg.rbp}'\n}" 10841b654882SGreg Clayton "{frame.reg.rflags = '${frame.reg.rflags}'\n}" 10851b654882SGreg Clayton "{frame.reg.xmm0 = '${frame.reg.xmm0}'\n}" 10861b654882SGreg Clayton "{frame.reg.carp = '${frame.reg.carp}'\n}" 10871b654882SGreg Clayton "{function.id = '${function.id}'\n}" 10881b654882SGreg Clayton "{function.name = '${function.name}'\n}" 1089ccbc08e6SGreg Clayton "{function.name-with-args = '${function.name-with-args}'\n}" 10901b654882SGreg Clayton "{function.addr-offset = '${function.addr-offset}'\n}" 10911b654882SGreg Clayton "{function.line-offset = '${function.line-offset}'\n}" 10921b654882SGreg Clayton "{function.pc-offset = '${function.pc-offset}'\n}" 10931b654882SGreg Clayton "{line.file.basename = '${line.file.basename}'\n}" 10941b654882SGreg Clayton "{line.file.fullpath = '${line.file.fullpath}'\n}" 10951b654882SGreg Clayton "{line.number = '${line.number}'\n}" 10961b654882SGreg Clayton "{line.start-addr = '${line.start-addr}'\n}" 10971b654882SGreg Clayton "{line.end-addr = '${line.end-addr}'\n}" 10981b654882SGreg Clayton ; 10991b654882SGreg Clayton 11001b654882SGreg Clayton SymbolContext sc (frame->GetSymbolContext(eSymbolContextEverything)); 11011b654882SGreg Clayton ExecutionContext exe_ctx; 11020603aa9dSGreg Clayton frame->CalculateExecutionContext(exe_ctx); 11031b654882SGreg Clayton const char *end = NULL; 11041b654882SGreg Clayton if (Debugger::FormatPrompt (prompt_format, &sc, &exe_ctx, &sc.line_entry.range.GetBaseAddress(), s, &end)) 11051b654882SGreg Clayton { 11061b654882SGreg Clayton printf("%s\n", s.GetData()); 11071b654882SGreg Clayton } 11081b654882SGreg Clayton else 11091b654882SGreg Clayton { 11101b654882SGreg Clayton printf ("error: at '%s'\n", end); 11111b654882SGreg Clayton printf ("what we got: %s\n", s.GetData()); 11121b654882SGreg Clayton } 11131b654882SGreg Clayton } 11141b654882SGreg Clayton 11159fc1944eSEnrico Granata static bool 11169fc1944eSEnrico Granata ScanFormatDescriptor (const char* var_name_begin, 11179fc1944eSEnrico Granata const char* var_name_end, 11189fc1944eSEnrico Granata const char** var_name_final, 11199fc1944eSEnrico Granata const char** percent_position, 11204d122c40SGreg Clayton Format* custom_format, 11219fc1944eSEnrico Granata ValueObject::ValueObjectRepresentationStyle* val_obj_display) 11229fc1944eSEnrico Granata { 1123e992a089SEnrico Granata LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES)); 11249fc1944eSEnrico Granata *percent_position = ::strchr(var_name_begin,'%'); 11259fc1944eSEnrico Granata if (!*percent_position || *percent_position > var_name_end) 1126e992a089SEnrico Granata { 1127e992a089SEnrico Granata if (log) 1128d228483dSEnrico Granata log->Printf("[ScanFormatDescriptor] no format descriptor in string, skipping"); 11299fc1944eSEnrico Granata *var_name_final = var_name_end; 1130e992a089SEnrico Granata } 11319fc1944eSEnrico Granata else 11329fc1944eSEnrico Granata { 11339fc1944eSEnrico Granata *var_name_final = *percent_position; 11349fc1944eSEnrico Granata char* format_name = new char[var_name_end-*var_name_final]; format_name[var_name_end-*var_name_final-1] = '\0'; 11359fc1944eSEnrico Granata memcpy(format_name, *var_name_final+1, var_name_end-*var_name_final-1); 1136e992a089SEnrico Granata if (log) 1137d228483dSEnrico Granata log->Printf("ScanFormatDescriptor] parsing %s as a format descriptor", format_name); 11389fc1944eSEnrico Granata if ( !FormatManager::GetFormatFromCString(format_name, 11399fc1944eSEnrico Granata true, 11409fc1944eSEnrico Granata *custom_format) ) 11419fc1944eSEnrico Granata { 1142e992a089SEnrico Granata if (log) 1143d228483dSEnrico Granata log->Printf("ScanFormatDescriptor] %s is an unknown format", format_name); 11449fc1944eSEnrico Granata // if this is an @ sign, print ObjC description 11459fc1944eSEnrico Granata if (*format_name == '@') 114686cc9829SEnrico Granata *val_obj_display = ValueObject::eValueObjectRepresentationStyleLanguageSpecific; 11479fc1944eSEnrico Granata // if this is a V, print the value using the default format 1148e992a089SEnrico Granata else if (*format_name == 'V') 114986cc9829SEnrico Granata *val_obj_display = ValueObject::eValueObjectRepresentationStyleValue; 1150d55546b2SEnrico Granata // if this is an L, print the location of the value 1151e992a089SEnrico Granata else if (*format_name == 'L') 115286cc9829SEnrico Granata *val_obj_display = ValueObject::eValueObjectRepresentationStyleLocation; 1153d55546b2SEnrico Granata // if this is an S, print the summary after all 1154e992a089SEnrico Granata else if (*format_name == 'S') 115586cc9829SEnrico Granata *val_obj_display = ValueObject::eValueObjectRepresentationStyleSummary; 11565dfd49ccSEnrico Granata else if (*format_name == '#') 115786cc9829SEnrico Granata *val_obj_display = ValueObject::eValueObjectRepresentationStyleChildrenCount; 1158d64d0bc0SEnrico Granata else if (*format_name == 'T') 115986cc9829SEnrico Granata *val_obj_display = ValueObject::eValueObjectRepresentationStyleType; 1160e992a089SEnrico Granata else if (log) 1161d228483dSEnrico Granata log->Printf("ScanFormatDescriptor] %s is an error, leaving the previous value alone", format_name); 11629fc1944eSEnrico Granata } 11639fc1944eSEnrico Granata // a good custom format tells us to print the value using it 11649fc1944eSEnrico Granata else 1165e992a089SEnrico Granata { 1166e992a089SEnrico Granata if (log) 1167d228483dSEnrico Granata log->Printf("ScanFormatDescriptor] will display value for this VO"); 116886cc9829SEnrico Granata *val_obj_display = ValueObject::eValueObjectRepresentationStyleValue; 1169e992a089SEnrico Granata } 11709fc1944eSEnrico Granata delete format_name; 11719fc1944eSEnrico Granata } 1172e992a089SEnrico Granata if (log) 1173d228483dSEnrico Granata log->Printf("ScanFormatDescriptor] final format description outcome: custom_format = %d, val_obj_display = %d", 1174e992a089SEnrico Granata *custom_format, 1175e992a089SEnrico Granata *val_obj_display); 11769fc1944eSEnrico Granata return true; 11779fc1944eSEnrico Granata } 11789fc1944eSEnrico Granata 11799fc1944eSEnrico Granata static bool 11809fc1944eSEnrico Granata ScanBracketedRange (const char* var_name_begin, 11819fc1944eSEnrico Granata const char* var_name_end, 11829fc1944eSEnrico Granata const char* var_name_final, 11839fc1944eSEnrico Granata const char** open_bracket_position, 11849fc1944eSEnrico Granata const char** separator_position, 11859fc1944eSEnrico Granata const char** close_bracket_position, 11869fc1944eSEnrico Granata const char** var_name_final_if_array_range, 11879fc1944eSEnrico Granata int64_t* index_lower, 11889fc1944eSEnrico Granata int64_t* index_higher) 11899fc1944eSEnrico Granata { 1190e992a089SEnrico Granata LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES)); 11919fc1944eSEnrico Granata *open_bracket_position = ::strchr(var_name_begin,'['); 11929fc1944eSEnrico Granata if (*open_bracket_position && *open_bracket_position < var_name_final) 11939fc1944eSEnrico Granata { 11949fc1944eSEnrico Granata *separator_position = ::strchr(*open_bracket_position,'-'); // might be NULL if this is a simple var[N] bitfield 11959fc1944eSEnrico Granata *close_bracket_position = ::strchr(*open_bracket_position,']'); 11969fc1944eSEnrico Granata // as usual, we assume that [] will come before % 11979fc1944eSEnrico Granata //printf("trying to expand a []\n"); 11989fc1944eSEnrico Granata *var_name_final_if_array_range = *open_bracket_position; 11999fc1944eSEnrico Granata if (*close_bracket_position - *open_bracket_position == 1) 12009fc1944eSEnrico Granata { 1201e992a089SEnrico Granata if (log) 1202d228483dSEnrico Granata log->Printf("[ScanBracketedRange] '[]' detected.. going from 0 to end of data"); 12039fc1944eSEnrico Granata *index_lower = 0; 12049fc1944eSEnrico Granata } 12059fc1944eSEnrico Granata else if (*separator_position == NULL || *separator_position > var_name_end) 12069fc1944eSEnrico Granata { 12079fc1944eSEnrico Granata char *end = NULL; 12089fc1944eSEnrico Granata *index_lower = ::strtoul (*open_bracket_position+1, &end, 0); 12099fc1944eSEnrico Granata *index_higher = *index_lower; 1210e992a089SEnrico Granata if (log) 1211d01b2953SDaniel Malea log->Printf("[ScanBracketedRange] [%" PRId64 "] detected, high index is same", *index_lower); 12129fc1944eSEnrico Granata } 12139fc1944eSEnrico Granata else if (*close_bracket_position && *close_bracket_position < var_name_end) 12149fc1944eSEnrico Granata { 12159fc1944eSEnrico Granata char *end = NULL; 12169fc1944eSEnrico Granata *index_lower = ::strtoul (*open_bracket_position+1, &end, 0); 12179fc1944eSEnrico Granata *index_higher = ::strtoul (*separator_position+1, &end, 0); 1218e992a089SEnrico Granata if (log) 1219d01b2953SDaniel Malea log->Printf("[ScanBracketedRange] [%" PRId64 "-%" PRId64 "] detected", *index_lower, *index_higher); 12209fc1944eSEnrico Granata } 12219fc1944eSEnrico Granata else 1222e992a089SEnrico Granata { 1223e992a089SEnrico Granata if (log) 1224d228483dSEnrico Granata log->Printf("[ScanBracketedRange] expression is erroneous, cannot extract indices out of it"); 12259fc1944eSEnrico Granata return false; 1226e992a089SEnrico Granata } 12279fc1944eSEnrico Granata if (*index_lower > *index_higher && *index_higher > 0) 12289fc1944eSEnrico Granata { 1229e992a089SEnrico Granata if (log) 1230d228483dSEnrico Granata log->Printf("[ScanBracketedRange] swapping indices"); 12319fc1944eSEnrico Granata int temp = *index_lower; 12329fc1944eSEnrico Granata *index_lower = *index_higher; 12339fc1944eSEnrico Granata *index_higher = temp; 12349fc1944eSEnrico Granata } 12359fc1944eSEnrico Granata } 1236e992a089SEnrico Granata else if (log) 1237d228483dSEnrico Granata log->Printf("[ScanBracketedRange] no bracketed range, skipping entirely"); 12389fc1944eSEnrico Granata return true; 12399fc1944eSEnrico Granata } 12409fc1944eSEnrico Granata 12419fc1944eSEnrico Granata static ValueObjectSP 1242c482a192SEnrico Granata ExpandIndexedExpression (ValueObject* valobj, 12439fc1944eSEnrico Granata uint32_t index, 12449fc1944eSEnrico Granata StackFrame* frame, 1245fc7a7f3bSEnrico Granata bool deref_pointer) 12469fc1944eSEnrico Granata { 1247e992a089SEnrico Granata LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES)); 1248fc7a7f3bSEnrico Granata const char* ptr_deref_format = "[%d]"; 1249fc7a7f3bSEnrico Granata std::auto_ptr<char> ptr_deref_buffer(new char[10]); 1250fc7a7f3bSEnrico Granata ::sprintf(ptr_deref_buffer.get(), ptr_deref_format, index); 1251e992a089SEnrico Granata if (log) 1252d228483dSEnrico Granata log->Printf("[ExpandIndexedExpression] name to deref: %s",ptr_deref_buffer.get()); 1253fc7a7f3bSEnrico Granata const char* first_unparsed; 1254fc7a7f3bSEnrico Granata ValueObject::GetValueForExpressionPathOptions options; 1255fc7a7f3bSEnrico Granata ValueObject::ExpressionPathEndResultType final_value_type; 1256fc7a7f3bSEnrico Granata ValueObject::ExpressionPathScanEndReason reason_to_stop; 125786cc9829SEnrico Granata ValueObject::ExpressionPathAftermath what_next = (deref_pointer ? ValueObject::eExpressionPathAftermathDereference : ValueObject::eExpressionPathAftermathNothing); 1258c482a192SEnrico Granata ValueObjectSP item = valobj->GetValueForExpressionPath (ptr_deref_buffer.get(), 1259fc7a7f3bSEnrico Granata &first_unparsed, 1260fc7a7f3bSEnrico Granata &reason_to_stop, 1261fc7a7f3bSEnrico Granata &final_value_type, 1262fc7a7f3bSEnrico Granata options, 1263fc7a7f3bSEnrico Granata &what_next); 1264fc7a7f3bSEnrico Granata if (!item) 1265fc7a7f3bSEnrico Granata { 1266e992a089SEnrico Granata if (log) 1267d228483dSEnrico Granata log->Printf("[ExpandIndexedExpression] ERROR: unparsed portion = %s, why stopping = %d," 1268e992a089SEnrico Granata " final_value_type %d", 1269fc7a7f3bSEnrico Granata first_unparsed, reason_to_stop, final_value_type); 1270fc7a7f3bSEnrico Granata } 12719fc1944eSEnrico Granata else 12729fc1944eSEnrico Granata { 1273e992a089SEnrico Granata if (log) 1274d228483dSEnrico Granata log->Printf("[ExpandIndexedExpression] ALL RIGHT: unparsed portion = %s, why stopping = %d," 1275e992a089SEnrico Granata " final_value_type %d", 1276fc7a7f3bSEnrico Granata first_unparsed, reason_to_stop, final_value_type); 12779fc1944eSEnrico Granata } 12789fc1944eSEnrico Granata return item; 12799fc1944eSEnrico Granata } 12809fc1944eSEnrico Granata 12811b654882SGreg Clayton bool 12821b654882SGreg Clayton Debugger::FormatPrompt 12831b654882SGreg Clayton ( 12841b654882SGreg Clayton const char *format, 12851b654882SGreg Clayton const SymbolContext *sc, 12861b654882SGreg Clayton const ExecutionContext *exe_ctx, 12871b654882SGreg Clayton const Address *addr, 12881b654882SGreg Clayton Stream &s, 12894becb37eSEnrico Granata const char **end, 1290c482a192SEnrico Granata ValueObject* valobj 12911b654882SGreg Clayton ) 12921b654882SGreg Clayton { 1293c482a192SEnrico Granata ValueObject* realvalobj = NULL; // makes it super-easy to parse pointers 12941b654882SGreg Clayton bool success = true; 12951b654882SGreg Clayton const char *p; 1296e992a089SEnrico Granata LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES)); 12971b654882SGreg Clayton for (p = format; *p != '\0'; ++p) 12981b654882SGreg Clayton { 1299c482a192SEnrico Granata if (realvalobj) 13004becb37eSEnrico Granata { 1301c482a192SEnrico Granata valobj = realvalobj; 1302c482a192SEnrico Granata realvalobj = NULL; 13034becb37eSEnrico Granata } 13041b654882SGreg Clayton size_t non_special_chars = ::strcspn (p, "${}\\"); 13051b654882SGreg Clayton if (non_special_chars > 0) 13061b654882SGreg Clayton { 13071b654882SGreg Clayton if (success) 13081b654882SGreg Clayton s.Write (p, non_special_chars); 13091b654882SGreg Clayton p += non_special_chars; 13101b654882SGreg Clayton } 13111b654882SGreg Clayton 13121b654882SGreg Clayton if (*p == '\0') 13131b654882SGreg Clayton { 13141b654882SGreg Clayton break; 13151b654882SGreg Clayton } 13161b654882SGreg Clayton else if (*p == '{') 13171b654882SGreg Clayton { 13181b654882SGreg Clayton // Start a new scope that must have everything it needs if it is to 13191b654882SGreg Clayton // to make it into the final output stream "s". If you want to make 13201b654882SGreg Clayton // a format that only prints out the function or symbol name if there 13211b654882SGreg Clayton // is one in the symbol context you can use: 13221b654882SGreg Clayton // "{function =${function.name}}" 13231b654882SGreg Clayton // The first '{' starts a new scope that end with the matching '}' at 13241b654882SGreg Clayton // the end of the string. The contents "function =${function.name}" 13251b654882SGreg Clayton // will then be evaluated and only be output if there is a function 13261b654882SGreg Clayton // or symbol with a valid name. 13271b654882SGreg Clayton StreamString sub_strm; 13281b654882SGreg Clayton 13291b654882SGreg Clayton ++p; // Skip the '{' 13301b654882SGreg Clayton 1331c482a192SEnrico Granata if (FormatPrompt (p, sc, exe_ctx, addr, sub_strm, &p, valobj)) 13321b654882SGreg Clayton { 13331b654882SGreg Clayton // The stream had all it needed 13341b654882SGreg Clayton s.Write(sub_strm.GetData(), sub_strm.GetSize()); 13351b654882SGreg Clayton } 13361b654882SGreg Clayton if (*p != '}') 13371b654882SGreg Clayton { 13381b654882SGreg Clayton success = false; 13391b654882SGreg Clayton break; 13401b654882SGreg Clayton } 13411b654882SGreg Clayton } 13421b654882SGreg Clayton else if (*p == '}') 13431b654882SGreg Clayton { 13441b654882SGreg Clayton // End of a enclosing scope 13451b654882SGreg Clayton break; 13461b654882SGreg Clayton } 13471b654882SGreg Clayton else if (*p == '$') 13481b654882SGreg Clayton { 13491b654882SGreg Clayton // We have a prompt variable to print 13501b654882SGreg Clayton ++p; 13511b654882SGreg Clayton if (*p == '{') 13521b654882SGreg Clayton { 13531b654882SGreg Clayton ++p; 13541b654882SGreg Clayton const char *var_name_begin = p; 13551b654882SGreg Clayton const char *var_name_end = ::strchr (p, '}'); 13561b654882SGreg Clayton 13571b654882SGreg Clayton if (var_name_end && var_name_begin < var_name_end) 13581b654882SGreg Clayton { 13591b654882SGreg Clayton // if we have already failed to parse, skip this variable 13601b654882SGreg Clayton if (success) 13611b654882SGreg Clayton { 13621b654882SGreg Clayton const char *cstr = NULL; 13631b654882SGreg Clayton Address format_addr; 13641b654882SGreg Clayton bool calculate_format_addr_function_offset = false; 13651b654882SGreg Clayton // Set reg_kind and reg_num to invalid values 13661b654882SGreg Clayton RegisterKind reg_kind = kNumRegisterKinds; 13671b654882SGreg Clayton uint32_t reg_num = LLDB_INVALID_REGNUM; 13681b654882SGreg Clayton FileSpec format_file_spec; 1369e0d378b3SGreg Clayton const RegisterInfo *reg_info = NULL; 13701b654882SGreg Clayton RegisterContext *reg_ctx = NULL; 13719fc1944eSEnrico Granata bool do_deref_pointer = false; 137286cc9829SEnrico Granata ValueObject::ExpressionPathScanEndReason reason_to_stop = ValueObject::eExpressionPathScanEndReasonEndOfString; 137386cc9829SEnrico Granata ValueObject::ExpressionPathEndResultType final_value_type = ValueObject::eExpressionPathEndResultTypePlain; 13741b654882SGreg Clayton 13751b654882SGreg Clayton // Each variable must set success to true below... 13761b654882SGreg Clayton bool var_success = false; 13771b654882SGreg Clayton switch (var_name_begin[0]) 13781b654882SGreg Clayton { 13794becb37eSEnrico Granata case '*': 13806f3533fbSEnrico Granata case 'v': 13816f3533fbSEnrico Granata case 's': 13824becb37eSEnrico Granata { 1383c482a192SEnrico Granata if (!valobj) 138434132754SGreg Clayton break; 13856f3533fbSEnrico Granata 1386c3e320a7SEnrico Granata if (log) 1387d228483dSEnrico Granata log->Printf("[Debugger::FormatPrompt] initial string: %s",var_name_begin); 1388c3e320a7SEnrico Granata 13896f3533fbSEnrico Granata // check for *var and *svar 13906f3533fbSEnrico Granata if (*var_name_begin == '*') 13916f3533fbSEnrico Granata { 13929fc1944eSEnrico Granata do_deref_pointer = true; 13939fc1944eSEnrico Granata var_name_begin++; 13949fc1944eSEnrico Granata } 1395c3e320a7SEnrico Granata 1396c3e320a7SEnrico Granata if (log) 1397d228483dSEnrico Granata log->Printf("[Debugger::FormatPrompt] initial string: %s",var_name_begin); 1398c3e320a7SEnrico Granata 13996f3533fbSEnrico Granata if (*var_name_begin == 's') 14004becb37eSEnrico Granata { 1401c5bc412cSEnrico Granata if (!valobj->IsSynthetic()) 140286cc9829SEnrico Granata valobj = valobj->GetSyntheticValue().get(); 140386cc9829SEnrico Granata if (!valobj) 140486cc9829SEnrico Granata break; 14056f3533fbSEnrico Granata var_name_begin++; 14066f3533fbSEnrico Granata } 14076f3533fbSEnrico Granata 1408c3e320a7SEnrico Granata if (log) 1409d228483dSEnrico Granata log->Printf("[Debugger::FormatPrompt] initial string: %s",var_name_begin); 1410c3e320a7SEnrico Granata 14116f3533fbSEnrico Granata // should be a 'v' by now 14126f3533fbSEnrico Granata if (*var_name_begin != 'v') 14136f3533fbSEnrico Granata break; 14146f3533fbSEnrico Granata 1415c3e320a7SEnrico Granata if (log) 1416d228483dSEnrico Granata log->Printf("[Debugger::FormatPrompt] initial string: %s",var_name_begin); 1417c3e320a7SEnrico Granata 1418fc7a7f3bSEnrico Granata ValueObject::ExpressionPathAftermath what_next = (do_deref_pointer ? 141986cc9829SEnrico Granata ValueObject::eExpressionPathAftermathDereference : ValueObject::eExpressionPathAftermathNothing); 1420fc7a7f3bSEnrico Granata ValueObject::GetValueForExpressionPathOptions options; 14218c9d3560SEnrico Granata options.DontCheckDotVsArrowSyntax().DoAllowBitfieldSyntax().DoAllowFragileIVar().DoAllowSyntheticChildren(); 142286cc9829SEnrico Granata ValueObject::ValueObjectRepresentationStyle val_obj_display = ValueObject::eValueObjectRepresentationStyleSummary; 142334132754SGreg Clayton ValueObject* target = NULL; 14244d122c40SGreg Clayton Format custom_format = eFormatInvalid; 142534132754SGreg Clayton const char* var_name_final = NULL; 14269fc1944eSEnrico Granata const char* var_name_final_if_array_range = NULL; 142734132754SGreg Clayton const char* close_bracket_position = NULL; 142834132754SGreg Clayton int64_t index_lower = -1; 142934132754SGreg Clayton int64_t index_higher = -1; 14309fc1944eSEnrico Granata bool is_array_range = false; 1431fc7a7f3bSEnrico Granata const char* first_unparsed; 143285933ed4SEnrico Granata bool was_plain_var = false; 143385933ed4SEnrico Granata bool was_var_format = false; 1434a777dc2aSEnrico Granata bool was_var_indexed = false; 1435fc7a7f3bSEnrico Granata 1436c482a192SEnrico Granata if (!valobj) break; 1437c482a192SEnrico Granata // simplest case ${var}, just print valobj's value 14389fc1944eSEnrico Granata if (::strncmp (var_name_begin, "var}", strlen("var}")) == 0) 14390a3958e0SEnrico Granata { 144085933ed4SEnrico Granata was_plain_var = true; 1441c482a192SEnrico Granata target = valobj; 144286cc9829SEnrico Granata val_obj_display = ValueObject::eValueObjectRepresentationStyleValue; 14430a3958e0SEnrico Granata } 14449fc1944eSEnrico Granata else if (::strncmp(var_name_begin,"var%",strlen("var%")) == 0) 14459fc1944eSEnrico Granata { 144685933ed4SEnrico Granata was_var_format = true; 14479fc1944eSEnrico Granata // this is a variable with some custom format applied to it 14489fc1944eSEnrico Granata const char* percent_position; 1449c482a192SEnrico Granata target = valobj; 145086cc9829SEnrico Granata val_obj_display = ValueObject::eValueObjectRepresentationStyleValue; 14519fc1944eSEnrico Granata ScanFormatDescriptor (var_name_begin, 14529fc1944eSEnrico Granata var_name_end, 14539fc1944eSEnrico Granata &var_name_final, 14549fc1944eSEnrico Granata &percent_position, 14559fc1944eSEnrico Granata &custom_format, 14569fc1944eSEnrico Granata &val_obj_display); 14570a3958e0SEnrico Granata } 14589fc1944eSEnrico Granata // this is ${var.something} or multiple .something nested 14599fc1944eSEnrico Granata else if (::strncmp (var_name_begin, "var", strlen("var")) == 0) 14609fc1944eSEnrico Granata { 1461a777dc2aSEnrico Granata if (::strncmp(var_name_begin, "var[", strlen("var[")) == 0) 1462a777dc2aSEnrico Granata was_var_indexed = true; 14639fc1944eSEnrico Granata const char* percent_position; 14649fc1944eSEnrico Granata ScanFormatDescriptor (var_name_begin, 14659fc1944eSEnrico Granata var_name_end, 14669fc1944eSEnrico Granata &var_name_final, 14679fc1944eSEnrico Granata &percent_position, 14689fc1944eSEnrico Granata &custom_format, 14699fc1944eSEnrico Granata &val_obj_display); 14709fc1944eSEnrico Granata 14719fc1944eSEnrico Granata const char* open_bracket_position; 14729fc1944eSEnrico Granata const char* separator_position; 14739fc1944eSEnrico Granata ScanBracketedRange (var_name_begin, 14749fc1944eSEnrico Granata var_name_end, 14759fc1944eSEnrico Granata var_name_final, 14769fc1944eSEnrico Granata &open_bracket_position, 14779fc1944eSEnrico Granata &separator_position, 14789fc1944eSEnrico Granata &close_bracket_position, 14799fc1944eSEnrico Granata &var_name_final_if_array_range, 14809fc1944eSEnrico Granata &index_lower, 14819fc1944eSEnrico Granata &index_higher); 14829fc1944eSEnrico Granata 14839fc1944eSEnrico Granata Error error; 14849fc1944eSEnrico Granata 1485fc7a7f3bSEnrico Granata std::auto_ptr<char> expr_path(new char[var_name_final-var_name_begin-1]); 1486fc7a7f3bSEnrico Granata ::memset(expr_path.get(), 0, var_name_final-var_name_begin-1); 1487fc7a7f3bSEnrico Granata memcpy(expr_path.get(), var_name_begin+3,var_name_final-var_name_begin-3); 1488fc7a7f3bSEnrico Granata 1489e992a089SEnrico Granata if (log) 1490d228483dSEnrico Granata log->Printf("[Debugger::FormatPrompt] symbol to expand: %s",expr_path.get()); 1491fc7a7f3bSEnrico Granata 1492c482a192SEnrico Granata target = valobj->GetValueForExpressionPath(expr_path.get(), 1493fc7a7f3bSEnrico Granata &first_unparsed, 1494fc7a7f3bSEnrico Granata &reason_to_stop, 1495fc7a7f3bSEnrico Granata &final_value_type, 1496fc7a7f3bSEnrico Granata options, 1497fc7a7f3bSEnrico Granata &what_next).get(); 1498fc7a7f3bSEnrico Granata 1499fc7a7f3bSEnrico Granata if (!target) 15009fc1944eSEnrico Granata { 1501e992a089SEnrico Granata if (log) 1502d228483dSEnrico Granata log->Printf("[Debugger::FormatPrompt] ERROR: unparsed portion = %s, why stopping = %d," 1503e992a089SEnrico Granata " final_value_type %d", 1504fc7a7f3bSEnrico Granata first_unparsed, reason_to_stop, final_value_type); 1505fc7a7f3bSEnrico Granata break; 15060a3958e0SEnrico Granata } 1507a7187d00SEnrico Granata else 1508fc7a7f3bSEnrico Granata { 1509e992a089SEnrico Granata if (log) 1510d228483dSEnrico Granata log->Printf("[Debugger::FormatPrompt] ALL RIGHT: unparsed portion = %s, why stopping = %d," 1511e992a089SEnrico Granata " final_value_type %d", 1512fc7a7f3bSEnrico Granata first_unparsed, reason_to_stop, final_value_type); 1513a7187d00SEnrico Granata } 15140a3958e0SEnrico Granata } 15150a3958e0SEnrico Granata else 15160a3958e0SEnrico Granata break; 15179fc1944eSEnrico Granata 151886cc9829SEnrico Granata is_array_range = (final_value_type == ValueObject::eExpressionPathEndResultTypeBoundedRange || 151986cc9829SEnrico Granata final_value_type == ValueObject::eExpressionPathEndResultTypeUnboundedRange); 1520fc7a7f3bSEnrico Granata 152186cc9829SEnrico Granata do_deref_pointer = (what_next == ValueObject::eExpressionPathAftermathDereference); 1522fc7a7f3bSEnrico Granata 1523a7187d00SEnrico Granata if (do_deref_pointer && !is_array_range) 15240a3958e0SEnrico Granata { 15259fc1944eSEnrico Granata // I have not deref-ed yet, let's do it 15269fc1944eSEnrico Granata // this happens when we are not going through GetValueForVariableExpressionPath 15279fc1944eSEnrico Granata // to get to the target ValueObject 15289fc1944eSEnrico Granata Error error; 15299fc1944eSEnrico Granata target = target->Dereference(error).get(); 1530dc940730SEnrico Granata if (error.Fail()) 1531dc940730SEnrico Granata { 1532dc940730SEnrico Granata if (log) 1533d228483dSEnrico Granata log->Printf("[Debugger::FormatPrompt] ERROR: %s\n", error.AsCString("unknown")); \ 1534dc940730SEnrico Granata break; 1535dc940730SEnrico Granata } 15369fc1944eSEnrico Granata do_deref_pointer = false; 15370a3958e0SEnrico Granata } 15380a3958e0SEnrico Granata 1539a777dc2aSEnrico Granata // <rdar://problem/11338654> 1540a777dc2aSEnrico Granata // we do not want to use the summary for a bitfield of type T:n 1541a777dc2aSEnrico Granata // if we were originally dealing with just a T - that would get 1542a777dc2aSEnrico Granata // us into an endless recursion 1543a777dc2aSEnrico Granata if (target->IsBitfield() && was_var_indexed) 1544a777dc2aSEnrico Granata { 1545a777dc2aSEnrico Granata // TODO: check for a (T:n)-specific summary - we should still obey that 1546a777dc2aSEnrico Granata StreamString bitfield_name; 1547a777dc2aSEnrico Granata bitfield_name.Printf("%s:%d", target->GetTypeName().AsCString(), target->GetBitfieldBitSize()); 1548a777dc2aSEnrico Granata lldb::TypeNameSpecifierImplSP type_sp(new TypeNameSpecifierImpl(bitfield_name.GetData(),false)); 1549a777dc2aSEnrico Granata if (!DataVisualization::GetSummaryForType(type_sp)) 1550a777dc2aSEnrico Granata val_obj_display = ValueObject::eValueObjectRepresentationStyleValue; 1551a777dc2aSEnrico Granata } 1552a777dc2aSEnrico Granata 155385933ed4SEnrico Granata // TODO use flags for these 15544ef877f5SGreg Clayton bool is_array = ClangASTContext::IsArrayType(target->GetClangType(), NULL, NULL, NULL); 1555f4efecd9SEnrico Granata bool is_pointer = ClangASTContext::IsPointerType(target->GetClangType()); 155685933ed4SEnrico Granata bool is_aggregate = ClangASTContext::IsAggregateType(target->GetClangType()); 1557f4efecd9SEnrico Granata 155886cc9829SEnrico Granata if ((is_array || is_pointer) && (!is_array_range) && val_obj_display == ValueObject::eValueObjectRepresentationStyleValue) // this should be wrong, but there are some exceptions 1559f4efecd9SEnrico Granata { 156085933ed4SEnrico Granata StreamString str_temp; 1561e992a089SEnrico Granata if (log) 1562d228483dSEnrico Granata log->Printf("[Debugger::FormatPrompt] I am into array || pointer && !range"); 1563d64d0bc0SEnrico Granata 156486cc9829SEnrico Granata if (target->HasSpecialPrintableRepresentation(val_obj_display, 1565d64d0bc0SEnrico Granata custom_format)) 1566d64d0bc0SEnrico Granata { 1567f4efecd9SEnrico Granata // try to use the special cases 156885933ed4SEnrico Granata var_success = target->DumpPrintableRepresentation(str_temp, 156985933ed4SEnrico Granata val_obj_display, 157085933ed4SEnrico Granata custom_format); 1571e992a089SEnrico Granata if (log) 1572d228483dSEnrico Granata log->Printf("[Debugger::FormatPrompt] special cases did%s match", var_success ? "" : "n't"); 1573d64d0bc0SEnrico Granata 1574d64d0bc0SEnrico Granata // should not happen 157585933ed4SEnrico Granata if (!var_success) 157685933ed4SEnrico Granata s << "<invalid usage of pointer value as object>"; 157785933ed4SEnrico Granata else 157885933ed4SEnrico Granata s << str_temp.GetData(); 1579d64d0bc0SEnrico Granata var_success = true; 1580d64d0bc0SEnrico Granata break; 1581d64d0bc0SEnrico Granata } 1582d64d0bc0SEnrico Granata else 1583d64d0bc0SEnrico Granata { 158488da35f8SEnrico Granata if (was_plain_var) // if ${var} 1585d64d0bc0SEnrico Granata { 1586d64d0bc0SEnrico Granata s << target->GetTypeName() << " @ " << target->GetLocationAsCString(); 1587d64d0bc0SEnrico Granata } 158888da35f8SEnrico Granata else if (is_pointer) // if pointer, value is the address stored 158988da35f8SEnrico Granata { 159023f59509SGreg Clayton target->DumpPrintableRepresentation (s, 159188da35f8SEnrico Granata val_obj_display, 159286cc9829SEnrico Granata custom_format, 159386cc9829SEnrico Granata ValueObject::ePrintableRepresentationSpecialCasesDisable); 159488da35f8SEnrico Granata } 1595d64d0bc0SEnrico Granata else 1596d64d0bc0SEnrico Granata { 1597d64d0bc0SEnrico Granata s << "<invalid usage of pointer value as object>"; 1598d64d0bc0SEnrico Granata } 1599d64d0bc0SEnrico Granata var_success = true; 1600d64d0bc0SEnrico Granata break; 1601d64d0bc0SEnrico Granata } 1602d64d0bc0SEnrico Granata } 1603d64d0bc0SEnrico Granata 1604d64d0bc0SEnrico Granata // if directly trying to print ${var}, and this is an aggregate, display a nice 1605d64d0bc0SEnrico Granata // type @ location message 1606d64d0bc0SEnrico Granata if (is_aggregate && was_plain_var) 1607d64d0bc0SEnrico Granata { 1608d64d0bc0SEnrico Granata s << target->GetTypeName() << " @ " << target->GetLocationAsCString(); 1609d64d0bc0SEnrico Granata var_success = true; 161085933ed4SEnrico Granata break; 161185933ed4SEnrico Granata } 161285933ed4SEnrico Granata 1613d64d0bc0SEnrico Granata // if directly trying to print ${var%V}, and this is an aggregate, do not let the user do it 161486cc9829SEnrico Granata if (is_aggregate && ((was_var_format && val_obj_display == ValueObject::eValueObjectRepresentationStyleValue))) 161585933ed4SEnrico Granata { 161685933ed4SEnrico Granata s << "<invalid use of aggregate type>"; 161785933ed4SEnrico Granata var_success = true; 1618f4efecd9SEnrico Granata break; 1619f4efecd9SEnrico Granata } 1620f4efecd9SEnrico Granata 16219fc1944eSEnrico Granata if (!is_array_range) 1622e992a089SEnrico Granata { 1623e992a089SEnrico Granata if (log) 1624d228483dSEnrico Granata log->Printf("[Debugger::FormatPrompt] dumping ordinary printable output"); 16259fc1944eSEnrico Granata var_success = target->DumpPrintableRepresentation(s,val_obj_display, custom_format); 1626e992a089SEnrico Granata } 16279fc1944eSEnrico Granata else 16289fc1944eSEnrico Granata { 1629e992a089SEnrico Granata if (log) 1630d228483dSEnrico Granata log->Printf("[Debugger::FormatPrompt] checking if I can handle as array"); 16319fc1944eSEnrico Granata if (!is_array && !is_pointer) 16329fc1944eSEnrico Granata break; 1633e992a089SEnrico Granata if (log) 1634d228483dSEnrico Granata log->Printf("[Debugger::FormatPrompt] handle as array"); 1635fc7a7f3bSEnrico Granata const char* special_directions = NULL; 1636fc7a7f3bSEnrico Granata StreamString special_directions_writer; 16370a3958e0SEnrico Granata if (close_bracket_position && (var_name_end-close_bracket_position > 1)) 16380a3958e0SEnrico Granata { 1639fc7a7f3bSEnrico Granata ConstString additional_data; 1640fc7a7f3bSEnrico Granata additional_data.SetCStringWithLength(close_bracket_position+1, var_name_end-close_bracket_position-1); 1641fc7a7f3bSEnrico Granata special_directions_writer.Printf("${%svar%s}", 1642fc7a7f3bSEnrico Granata do_deref_pointer ? "*" : "", 1643fc7a7f3bSEnrico Granata additional_data.GetCString()); 1644fc7a7f3bSEnrico Granata special_directions = special_directions_writer.GetData(); 16450a3958e0SEnrico Granata } 16460a3958e0SEnrico Granata 16470a3958e0SEnrico Granata // let us display items index_lower thru index_higher of this array 16480a3958e0SEnrico Granata s.PutChar('['); 16490a3958e0SEnrico Granata var_success = true; 16500a3958e0SEnrico Granata 16519fc1944eSEnrico Granata if (index_higher < 0) 1652c482a192SEnrico Granata index_higher = valobj->GetNumChildren() - 1; 16530a3958e0SEnrico Granata 1654cc4d0146SGreg Clayton uint32_t max_num_children = target->GetTargetSP()->GetMaximumNumberOfChildrenToDisplay(); 165522c55d18SEnrico Granata 16560a3958e0SEnrico Granata for (;index_lower<=index_higher;index_lower++) 16570a3958e0SEnrico Granata { 1658fc7a7f3bSEnrico Granata ValueObject* item = ExpandIndexedExpression (target, 16599fc1944eSEnrico Granata index_lower, 1660c14ee32dSGreg Clayton exe_ctx->GetFramePtr(), 1661fc7a7f3bSEnrico Granata false).get(); 16620a3958e0SEnrico Granata 1663fc7a7f3bSEnrico Granata if (!item) 1664fc7a7f3bSEnrico Granata { 1665e992a089SEnrico Granata if (log) 1666d01b2953SDaniel Malea log->Printf("[Debugger::FormatPrompt] ERROR in getting child item at index %" PRId64, index_lower); 1667fc7a7f3bSEnrico Granata } 1668fc7a7f3bSEnrico Granata else 1669fc7a7f3bSEnrico Granata { 1670e992a089SEnrico Granata if (log) 1671d228483dSEnrico Granata log->Printf("[Debugger::FormatPrompt] special_directions for child item: %s",special_directions); 1672fc7a7f3bSEnrico Granata } 1673fc7a7f3bSEnrico Granata 16740a3958e0SEnrico Granata if (!special_directions) 16759fc1944eSEnrico Granata var_success &= item->DumpPrintableRepresentation(s,val_obj_display, custom_format); 16760a3958e0SEnrico Granata else 16770a3958e0SEnrico Granata var_success &= FormatPrompt(special_directions, sc, exe_ctx, addr, s, NULL, item); 16780a3958e0SEnrico Granata 167922c55d18SEnrico Granata if (--max_num_children == 0) 168022c55d18SEnrico Granata { 168122c55d18SEnrico Granata s.PutCString(", ..."); 168222c55d18SEnrico Granata break; 168322c55d18SEnrico Granata } 168422c55d18SEnrico Granata 16850a3958e0SEnrico Granata if (index_lower < index_higher) 16860a3958e0SEnrico Granata s.PutChar(','); 16870a3958e0SEnrico Granata } 16880a3958e0SEnrico Granata s.PutChar(']'); 16894becb37eSEnrico Granata } 16904becb37eSEnrico Granata } 169134132754SGreg Clayton break; 16921b654882SGreg Clayton case 'a': 16931b654882SGreg Clayton if (::strncmp (var_name_begin, "addr}", strlen("addr}")) == 0) 16941b654882SGreg Clayton { 16951b654882SGreg Clayton if (addr && addr->IsValid()) 16961b654882SGreg Clayton { 16971b654882SGreg Clayton var_success = true; 16981b654882SGreg Clayton format_addr = *addr; 16991b654882SGreg Clayton } 17001b654882SGreg Clayton } 17015a31471eSGreg Clayton else if (::strncmp (var_name_begin, "ansi.", strlen("ansi.")) == 0) 17025a31471eSGreg Clayton { 17035a31471eSGreg Clayton var_success = true; 17045a31471eSGreg Clayton var_name_begin += strlen("ansi."); // Skip the "ansi." 17055a31471eSGreg Clayton if (::strncmp (var_name_begin, "fg.", strlen("fg.")) == 0) 17065a31471eSGreg Clayton { 17075a31471eSGreg Clayton var_name_begin += strlen("fg."); // Skip the "fg." 17085a31471eSGreg Clayton if (::strncmp (var_name_begin, "black}", strlen("black}")) == 0) 17095a31471eSGreg Clayton { 17105a31471eSGreg Clayton s.Printf ("%s%s%s", 17115a31471eSGreg Clayton lldb_utility::ansi::k_escape_start, 17125a31471eSGreg Clayton lldb_utility::ansi::k_fg_black, 17135a31471eSGreg Clayton lldb_utility::ansi::k_escape_end); 17145a31471eSGreg Clayton } 17155a31471eSGreg Clayton else if (::strncmp (var_name_begin, "red}", strlen("red}")) == 0) 17165a31471eSGreg Clayton { 17175a31471eSGreg Clayton s.Printf ("%s%s%s", 17185a31471eSGreg Clayton lldb_utility::ansi::k_escape_start, 17195a31471eSGreg Clayton lldb_utility::ansi::k_fg_red, 17205a31471eSGreg Clayton lldb_utility::ansi::k_escape_end); 17215a31471eSGreg Clayton } 17225a31471eSGreg Clayton else if (::strncmp (var_name_begin, "green}", strlen("green}")) == 0) 17235a31471eSGreg Clayton { 17245a31471eSGreg Clayton s.Printf ("%s%s%s", 17255a31471eSGreg Clayton lldb_utility::ansi::k_escape_start, 17265a31471eSGreg Clayton lldb_utility::ansi::k_fg_green, 17275a31471eSGreg Clayton lldb_utility::ansi::k_escape_end); 17285a31471eSGreg Clayton } 17295a31471eSGreg Clayton else if (::strncmp (var_name_begin, "yellow}", strlen("yellow}")) == 0) 17305a31471eSGreg Clayton { 17315a31471eSGreg Clayton s.Printf ("%s%s%s", 17325a31471eSGreg Clayton lldb_utility::ansi::k_escape_start, 17335a31471eSGreg Clayton lldb_utility::ansi::k_fg_yellow, 17345a31471eSGreg Clayton lldb_utility::ansi::k_escape_end); 17355a31471eSGreg Clayton } 17365a31471eSGreg Clayton else if (::strncmp (var_name_begin, "blue}", strlen("blue}")) == 0) 17375a31471eSGreg Clayton { 17385a31471eSGreg Clayton s.Printf ("%s%s%s", 17395a31471eSGreg Clayton lldb_utility::ansi::k_escape_start, 17405a31471eSGreg Clayton lldb_utility::ansi::k_fg_blue, 17415a31471eSGreg Clayton lldb_utility::ansi::k_escape_end); 17425a31471eSGreg Clayton } 17435a31471eSGreg Clayton else if (::strncmp (var_name_begin, "purple}", strlen("purple}")) == 0) 17445a31471eSGreg Clayton { 17455a31471eSGreg Clayton s.Printf ("%s%s%s", 17465a31471eSGreg Clayton lldb_utility::ansi::k_escape_start, 17475a31471eSGreg Clayton lldb_utility::ansi::k_fg_purple, 17485a31471eSGreg Clayton lldb_utility::ansi::k_escape_end); 17495a31471eSGreg Clayton } 17505a31471eSGreg Clayton else if (::strncmp (var_name_begin, "cyan}", strlen("cyan}")) == 0) 17515a31471eSGreg Clayton { 17525a31471eSGreg Clayton s.Printf ("%s%s%s", 17535a31471eSGreg Clayton lldb_utility::ansi::k_escape_start, 17545a31471eSGreg Clayton lldb_utility::ansi::k_fg_cyan, 17555a31471eSGreg Clayton lldb_utility::ansi::k_escape_end); 17565a31471eSGreg Clayton } 17575a31471eSGreg Clayton else if (::strncmp (var_name_begin, "white}", strlen("white}")) == 0) 17585a31471eSGreg Clayton { 17595a31471eSGreg Clayton s.Printf ("%s%s%s", 17605a31471eSGreg Clayton lldb_utility::ansi::k_escape_start, 17615a31471eSGreg Clayton lldb_utility::ansi::k_fg_white, 17625a31471eSGreg Clayton lldb_utility::ansi::k_escape_end); 17635a31471eSGreg Clayton } 17645a31471eSGreg Clayton else 17655a31471eSGreg Clayton { 17665a31471eSGreg Clayton var_success = false; 17675a31471eSGreg Clayton } 17685a31471eSGreg Clayton } 17695a31471eSGreg Clayton else if (::strncmp (var_name_begin, "bg.", strlen("bg.")) == 0) 17705a31471eSGreg Clayton { 17715a31471eSGreg Clayton var_name_begin += strlen("bg."); // Skip the "bg." 17725a31471eSGreg Clayton if (::strncmp (var_name_begin, "black}", strlen("black}")) == 0) 17735a31471eSGreg Clayton { 17745a31471eSGreg Clayton s.Printf ("%s%s%s", 17755a31471eSGreg Clayton lldb_utility::ansi::k_escape_start, 17765a31471eSGreg Clayton lldb_utility::ansi::k_bg_black, 17775a31471eSGreg Clayton lldb_utility::ansi::k_escape_end); 17785a31471eSGreg Clayton } 17795a31471eSGreg Clayton else if (::strncmp (var_name_begin, "red}", strlen("red}")) == 0) 17805a31471eSGreg Clayton { 17815a31471eSGreg Clayton s.Printf ("%s%s%s", 17825a31471eSGreg Clayton lldb_utility::ansi::k_escape_start, 17835a31471eSGreg Clayton lldb_utility::ansi::k_bg_red, 17845a31471eSGreg Clayton lldb_utility::ansi::k_escape_end); 17855a31471eSGreg Clayton } 17865a31471eSGreg Clayton else if (::strncmp (var_name_begin, "green}", strlen("green}")) == 0) 17875a31471eSGreg Clayton { 17885a31471eSGreg Clayton s.Printf ("%s%s%s", 17895a31471eSGreg Clayton lldb_utility::ansi::k_escape_start, 17905a31471eSGreg Clayton lldb_utility::ansi::k_bg_green, 17915a31471eSGreg Clayton lldb_utility::ansi::k_escape_end); 17925a31471eSGreg Clayton } 17935a31471eSGreg Clayton else if (::strncmp (var_name_begin, "yellow}", strlen("yellow}")) == 0) 17945a31471eSGreg Clayton { 17955a31471eSGreg Clayton s.Printf ("%s%s%s", 17965a31471eSGreg Clayton lldb_utility::ansi::k_escape_start, 17975a31471eSGreg Clayton lldb_utility::ansi::k_bg_yellow, 17985a31471eSGreg Clayton lldb_utility::ansi::k_escape_end); 17995a31471eSGreg Clayton } 18005a31471eSGreg Clayton else if (::strncmp (var_name_begin, "blue}", strlen("blue}")) == 0) 18015a31471eSGreg Clayton { 18025a31471eSGreg Clayton s.Printf ("%s%s%s", 18035a31471eSGreg Clayton lldb_utility::ansi::k_escape_start, 18045a31471eSGreg Clayton lldb_utility::ansi::k_bg_blue, 18055a31471eSGreg Clayton lldb_utility::ansi::k_escape_end); 18065a31471eSGreg Clayton } 18075a31471eSGreg Clayton else if (::strncmp (var_name_begin, "purple}", strlen("purple}")) == 0) 18085a31471eSGreg Clayton { 18095a31471eSGreg Clayton s.Printf ("%s%s%s", 18105a31471eSGreg Clayton lldb_utility::ansi::k_escape_start, 18115a31471eSGreg Clayton lldb_utility::ansi::k_bg_purple, 18125a31471eSGreg Clayton lldb_utility::ansi::k_escape_end); 18135a31471eSGreg Clayton } 18145a31471eSGreg Clayton else if (::strncmp (var_name_begin, "cyan}", strlen("cyan}")) == 0) 18155a31471eSGreg Clayton { 18165a31471eSGreg Clayton s.Printf ("%s%s%s", 18175a31471eSGreg Clayton lldb_utility::ansi::k_escape_start, 18185a31471eSGreg Clayton lldb_utility::ansi::k_bg_cyan, 18195a31471eSGreg Clayton lldb_utility::ansi::k_escape_end); 18205a31471eSGreg Clayton } 18215a31471eSGreg Clayton else if (::strncmp (var_name_begin, "white}", strlen("white}")) == 0) 18225a31471eSGreg Clayton { 18235a31471eSGreg Clayton s.Printf ("%s%s%s", 18245a31471eSGreg Clayton lldb_utility::ansi::k_escape_start, 18255a31471eSGreg Clayton lldb_utility::ansi::k_bg_white, 18265a31471eSGreg Clayton lldb_utility::ansi::k_escape_end); 18275a31471eSGreg Clayton } 18285a31471eSGreg Clayton else 18295a31471eSGreg Clayton { 18305a31471eSGreg Clayton var_success = false; 18315a31471eSGreg Clayton } 18325a31471eSGreg Clayton } 18335a31471eSGreg Clayton else if (::strncmp (var_name_begin, "normal}", strlen ("normal}")) == 0) 18345a31471eSGreg Clayton { 18355a31471eSGreg Clayton s.Printf ("%s%s%s", 18365a31471eSGreg Clayton lldb_utility::ansi::k_escape_start, 18375a31471eSGreg Clayton lldb_utility::ansi::k_ctrl_normal, 18385a31471eSGreg Clayton lldb_utility::ansi::k_escape_end); 18395a31471eSGreg Clayton } 18405a31471eSGreg Clayton else if (::strncmp (var_name_begin, "bold}", strlen("bold}")) == 0) 18415a31471eSGreg Clayton { 18425a31471eSGreg Clayton s.Printf ("%s%s%s", 18435a31471eSGreg Clayton lldb_utility::ansi::k_escape_start, 18445a31471eSGreg Clayton lldb_utility::ansi::k_ctrl_bold, 18455a31471eSGreg Clayton lldb_utility::ansi::k_escape_end); 18465a31471eSGreg Clayton } 18475a31471eSGreg Clayton else if (::strncmp (var_name_begin, "faint}", strlen("faint}")) == 0) 18485a31471eSGreg Clayton { 18495a31471eSGreg Clayton s.Printf ("%s%s%s", 18505a31471eSGreg Clayton lldb_utility::ansi::k_escape_start, 18515a31471eSGreg Clayton lldb_utility::ansi::k_ctrl_faint, 18525a31471eSGreg Clayton lldb_utility::ansi::k_escape_end); 18535a31471eSGreg Clayton } 18545a31471eSGreg Clayton else if (::strncmp (var_name_begin, "italic}", strlen("italic}")) == 0) 18555a31471eSGreg Clayton { 18565a31471eSGreg Clayton s.Printf ("%s%s%s", 18575a31471eSGreg Clayton lldb_utility::ansi::k_escape_start, 18585a31471eSGreg Clayton lldb_utility::ansi::k_ctrl_italic, 18595a31471eSGreg Clayton lldb_utility::ansi::k_escape_end); 18605a31471eSGreg Clayton } 18615a31471eSGreg Clayton else if (::strncmp (var_name_begin, "underline}", strlen("underline}")) == 0) 18625a31471eSGreg Clayton { 18635a31471eSGreg Clayton s.Printf ("%s%s%s", 18645a31471eSGreg Clayton lldb_utility::ansi::k_escape_start, 18655a31471eSGreg Clayton lldb_utility::ansi::k_ctrl_underline, 18665a31471eSGreg Clayton lldb_utility::ansi::k_escape_end); 18675a31471eSGreg Clayton } 18685a31471eSGreg Clayton else if (::strncmp (var_name_begin, "slow-blink}", strlen("slow-blink}")) == 0) 18695a31471eSGreg Clayton { 18705a31471eSGreg Clayton s.Printf ("%s%s%s", 18715a31471eSGreg Clayton lldb_utility::ansi::k_escape_start, 18725a31471eSGreg Clayton lldb_utility::ansi::k_ctrl_slow_blink, 18735a31471eSGreg Clayton lldb_utility::ansi::k_escape_end); 18745a31471eSGreg Clayton } 18755a31471eSGreg Clayton else if (::strncmp (var_name_begin, "fast-blink}", strlen("fast-blink}")) == 0) 18765a31471eSGreg Clayton { 18775a31471eSGreg Clayton s.Printf ("%s%s%s", 18785a31471eSGreg Clayton lldb_utility::ansi::k_escape_start, 18795a31471eSGreg Clayton lldb_utility::ansi::k_ctrl_fast_blink, 18805a31471eSGreg Clayton lldb_utility::ansi::k_escape_end); 18815a31471eSGreg Clayton } 18825a31471eSGreg Clayton else if (::strncmp (var_name_begin, "negative}", strlen("negative}")) == 0) 18835a31471eSGreg Clayton { 18845a31471eSGreg Clayton s.Printf ("%s%s%s", 18855a31471eSGreg Clayton lldb_utility::ansi::k_escape_start, 18865a31471eSGreg Clayton lldb_utility::ansi::k_ctrl_negative, 18875a31471eSGreg Clayton lldb_utility::ansi::k_escape_end); 18885a31471eSGreg Clayton } 18895a31471eSGreg Clayton else if (::strncmp (var_name_begin, "conceal}", strlen("conceal}")) == 0) 18905a31471eSGreg Clayton { 18915a31471eSGreg Clayton s.Printf ("%s%s%s", 18925a31471eSGreg Clayton lldb_utility::ansi::k_escape_start, 18935a31471eSGreg Clayton lldb_utility::ansi::k_ctrl_conceal, 18945a31471eSGreg Clayton lldb_utility::ansi::k_escape_end); 18955a31471eSGreg Clayton 18965a31471eSGreg Clayton } 18975a31471eSGreg Clayton else if (::strncmp (var_name_begin, "crossed-out}", strlen("crossed-out}")) == 0) 18985a31471eSGreg Clayton { 18995a31471eSGreg Clayton s.Printf ("%s%s%s", 19005a31471eSGreg Clayton lldb_utility::ansi::k_escape_start, 19015a31471eSGreg Clayton lldb_utility::ansi::k_ctrl_crossed_out, 19025a31471eSGreg Clayton lldb_utility::ansi::k_escape_end); 19035a31471eSGreg Clayton } 19045a31471eSGreg Clayton else 19055a31471eSGreg Clayton { 19065a31471eSGreg Clayton var_success = false; 19075a31471eSGreg Clayton } 19085a31471eSGreg Clayton } 19091b654882SGreg Clayton break; 19101b654882SGreg Clayton 19111b654882SGreg Clayton case 'p': 19121b654882SGreg Clayton if (::strncmp (var_name_begin, "process.", strlen("process.")) == 0) 19131b654882SGreg Clayton { 1914c14ee32dSGreg Clayton if (exe_ctx) 1915c14ee32dSGreg Clayton { 1916c14ee32dSGreg Clayton Process *process = exe_ctx->GetProcessPtr(); 1917c14ee32dSGreg Clayton if (process) 19181b654882SGreg Clayton { 19191b654882SGreg Clayton var_name_begin += ::strlen ("process."); 19201b654882SGreg Clayton if (::strncmp (var_name_begin, "id}", strlen("id}")) == 0) 19211b654882SGreg Clayton { 1922d01b2953SDaniel Malea s.Printf("%" PRIu64, process->GetID()); 19231b654882SGreg Clayton var_success = true; 19241b654882SGreg Clayton } 19251b654882SGreg Clayton else if ((::strncmp (var_name_begin, "name}", strlen("name}")) == 0) || 19261b654882SGreg Clayton (::strncmp (var_name_begin, "file.basename}", strlen("file.basename}")) == 0) || 19271b654882SGreg Clayton (::strncmp (var_name_begin, "file.fullpath}", strlen("file.fullpath}")) == 0)) 19281b654882SGreg Clayton { 1929c14ee32dSGreg Clayton Module *exe_module = process->GetTarget().GetExecutableModulePointer(); 1930aa149cbdSGreg Clayton if (exe_module) 19311b654882SGreg Clayton { 19321b654882SGreg Clayton if (var_name_begin[0] == 'n' || var_name_begin[5] == 'f') 19331b654882SGreg Clayton { 1934aa149cbdSGreg Clayton format_file_spec.GetFilename() = exe_module->GetFileSpec().GetFilename(); 19351b654882SGreg Clayton var_success = format_file_spec; 19361b654882SGreg Clayton } 19371b654882SGreg Clayton else 19381b654882SGreg Clayton { 1939aa149cbdSGreg Clayton format_file_spec = exe_module->GetFileSpec(); 19401b654882SGreg Clayton var_success = format_file_spec; 19411b654882SGreg Clayton } 19421b654882SGreg Clayton } 19431b654882SGreg Clayton } 19441b654882SGreg Clayton } 19451b654882SGreg Clayton } 1946c14ee32dSGreg Clayton } 19471b654882SGreg Clayton break; 19481b654882SGreg Clayton 19491b654882SGreg Clayton case 't': 19501b654882SGreg Clayton if (::strncmp (var_name_begin, "thread.", strlen("thread.")) == 0) 19511b654882SGreg Clayton { 1952c14ee32dSGreg Clayton if (exe_ctx) 1953c14ee32dSGreg Clayton { 1954c14ee32dSGreg Clayton Thread *thread = exe_ctx->GetThreadPtr(); 1955c14ee32dSGreg Clayton if (thread) 19561b654882SGreg Clayton { 19571b654882SGreg Clayton var_name_begin += ::strlen ("thread."); 19581b654882SGreg Clayton if (::strncmp (var_name_begin, "id}", strlen("id}")) == 0) 19591b654882SGreg Clayton { 1960d01b2953SDaniel Malea s.Printf("0x%4.4" PRIx64, thread->GetID()); 19611b654882SGreg Clayton var_success = true; 19621b654882SGreg Clayton } 19631b654882SGreg Clayton else if (::strncmp (var_name_begin, "index}", strlen("index}")) == 0) 19641b654882SGreg Clayton { 1965c14ee32dSGreg Clayton s.Printf("%u", thread->GetIndexID()); 19661b654882SGreg Clayton var_success = true; 19671b654882SGreg Clayton } 19681b654882SGreg Clayton else if (::strncmp (var_name_begin, "name}", strlen("name}")) == 0) 19691b654882SGreg Clayton { 1970c14ee32dSGreg Clayton cstr = thread->GetName(); 19711b654882SGreg Clayton var_success = cstr && cstr[0]; 19721b654882SGreg Clayton if (var_success) 19731b654882SGreg Clayton s.PutCString(cstr); 19741b654882SGreg Clayton } 19751b654882SGreg Clayton else if (::strncmp (var_name_begin, "queue}", strlen("queue}")) == 0) 19761b654882SGreg Clayton { 1977c14ee32dSGreg Clayton cstr = thread->GetQueueName(); 19781b654882SGreg Clayton var_success = cstr && cstr[0]; 19791b654882SGreg Clayton if (var_success) 19801b654882SGreg Clayton s.PutCString(cstr); 19811b654882SGreg Clayton } 19821b654882SGreg Clayton else if (::strncmp (var_name_begin, "stop-reason}", strlen("stop-reason}")) == 0) 19831b654882SGreg Clayton { 1984c14ee32dSGreg Clayton StopInfoSP stop_info_sp = thread->GetStopInfo (); 19855d88a068SJim Ingham if (stop_info_sp && stop_info_sp->IsValid()) 19861b654882SGreg Clayton { 1987b15bfc75SJim Ingham cstr = stop_info_sp->GetDescription(); 19881b654882SGreg Clayton if (cstr && cstr[0]) 19891b654882SGreg Clayton { 19901b654882SGreg Clayton s.PutCString(cstr); 19911b654882SGreg Clayton var_success = true; 19921b654882SGreg Clayton } 19931b654882SGreg Clayton } 19941b654882SGreg Clayton } 199573ca05a2SJim Ingham else if (::strncmp (var_name_begin, "return-value}", strlen("return-value}")) == 0) 199673ca05a2SJim Ingham { 199773ca05a2SJim Ingham StopInfoSP stop_info_sp = thread->GetStopInfo (); 19985d88a068SJim Ingham if (stop_info_sp && stop_info_sp->IsValid()) 199973ca05a2SJim Ingham { 200073ca05a2SJim Ingham ValueObjectSP return_valobj_sp = StopInfo::GetReturnValueObject (stop_info_sp); 200173ca05a2SJim Ingham if (return_valobj_sp) 200273ca05a2SJim Ingham { 2003ef651600SJim Ingham ValueObject::DumpValueObjectOptions dump_options; 2004ef651600SJim Ingham ValueObject::DumpValueObject (s, return_valobj_sp.get(), dump_options); 200573ca05a2SJim Ingham var_success = true; 200673ca05a2SJim Ingham } 200773ca05a2SJim Ingham } 200873ca05a2SJim Ingham } 200973ca05a2SJim Ingham } 20101b654882SGreg Clayton } 20111b654882SGreg Clayton } 20121b654882SGreg Clayton else if (::strncmp (var_name_begin, "target.", strlen("target.")) == 0) 20131b654882SGreg Clayton { 201467cc0636SGreg Clayton // TODO: hookup properties 201567cc0636SGreg Clayton // if (!target_properties_sp) 201667cc0636SGreg Clayton // { 201767cc0636SGreg Clayton // Target *target = Target::GetTargetFromContexts (exe_ctx, sc); 201867cc0636SGreg Clayton // if (target) 201967cc0636SGreg Clayton // target_properties_sp = target->GetProperties(); 202067cc0636SGreg Clayton // } 202167cc0636SGreg Clayton // 202267cc0636SGreg Clayton // if (target_properties_sp) 202367cc0636SGreg Clayton // { 202467cc0636SGreg Clayton // var_name_begin += ::strlen ("target."); 202567cc0636SGreg Clayton // const char *end_property = strchr(var_name_begin, '}'); 202667cc0636SGreg Clayton // if (end_property) 202767cc0636SGreg Clayton // { 202867cc0636SGreg Clayton // ConstString property_name(var_name_begin, end_property - var_name_begin); 202967cc0636SGreg Clayton // std::string property_value (target_properties_sp->GetPropertyValue(property_name)); 203067cc0636SGreg Clayton // if (!property_value.empty()) 203167cc0636SGreg Clayton // { 203267cc0636SGreg Clayton // s.PutCString (property_value.c_str()); 203367cc0636SGreg Clayton // var_success = true; 203467cc0636SGreg Clayton // } 203567cc0636SGreg Clayton // } 203667cc0636SGreg Clayton // } 20370603aa9dSGreg Clayton Target *target = Target::GetTargetFromContexts (exe_ctx, sc); 20380603aa9dSGreg Clayton if (target) 20391b654882SGreg Clayton { 20401b654882SGreg Clayton var_name_begin += ::strlen ("target."); 20411b654882SGreg Clayton if (::strncmp (var_name_begin, "arch}", strlen("arch}")) == 0) 20421b654882SGreg Clayton { 20431b654882SGreg Clayton ArchSpec arch (target->GetArchitecture ()); 20441b654882SGreg Clayton if (arch.IsValid()) 20451b654882SGreg Clayton { 204664195a2cSGreg Clayton s.PutCString (arch.GetArchitectureName()); 20471b654882SGreg Clayton var_success = true; 20481b654882SGreg Clayton } 20491b654882SGreg Clayton } 20501b654882SGreg Clayton } 20511b654882SGreg Clayton } 20521b654882SGreg Clayton break; 20531b654882SGreg Clayton 20541b654882SGreg Clayton 20551b654882SGreg Clayton case 'm': 20561b654882SGreg Clayton if (::strncmp (var_name_begin, "module.", strlen("module.")) == 0) 20571b654882SGreg Clayton { 20580603aa9dSGreg Clayton if (sc && sc->module_sp.get()) 20591b654882SGreg Clayton { 20600603aa9dSGreg Clayton Module *module = sc->module_sp.get(); 20611b654882SGreg Clayton var_name_begin += ::strlen ("module."); 20621b654882SGreg Clayton 20631b654882SGreg Clayton if (::strncmp (var_name_begin, "file.", strlen("file.")) == 0) 20641b654882SGreg Clayton { 20651b654882SGreg Clayton if (module->GetFileSpec()) 20661b654882SGreg Clayton { 20671b654882SGreg Clayton var_name_begin += ::strlen ("file."); 20681b654882SGreg Clayton 20691b654882SGreg Clayton if (::strncmp (var_name_begin, "basename}", strlen("basename}")) == 0) 20701b654882SGreg Clayton { 20711b654882SGreg Clayton format_file_spec.GetFilename() = module->GetFileSpec().GetFilename(); 20721b654882SGreg Clayton var_success = format_file_spec; 20731b654882SGreg Clayton } 20741b654882SGreg Clayton else if (::strncmp (var_name_begin, "fullpath}", strlen("fullpath}")) == 0) 20751b654882SGreg Clayton { 20761b654882SGreg Clayton format_file_spec = module->GetFileSpec(); 20771b654882SGreg Clayton var_success = format_file_spec; 20781b654882SGreg Clayton } 20791b654882SGreg Clayton } 20801b654882SGreg Clayton } 20811b654882SGreg Clayton } 20821b654882SGreg Clayton } 20831b654882SGreg Clayton break; 20841b654882SGreg Clayton 20851b654882SGreg Clayton 20861b654882SGreg Clayton case 'f': 20871b654882SGreg Clayton if (::strncmp (var_name_begin, "file.", strlen("file.")) == 0) 20881b654882SGreg Clayton { 20891b654882SGreg Clayton if (sc && sc->comp_unit != NULL) 20901b654882SGreg Clayton { 20911b654882SGreg Clayton var_name_begin += ::strlen ("file."); 20921b654882SGreg Clayton 20931b654882SGreg Clayton if (::strncmp (var_name_begin, "basename}", strlen("basename}")) == 0) 20941b654882SGreg Clayton { 20951b654882SGreg Clayton format_file_spec.GetFilename() = sc->comp_unit->GetFilename(); 20961b654882SGreg Clayton var_success = format_file_spec; 20971b654882SGreg Clayton } 20981b654882SGreg Clayton else if (::strncmp (var_name_begin, "fullpath}", strlen("fullpath}")) == 0) 20991b654882SGreg Clayton { 21001b654882SGreg Clayton format_file_spec = *sc->comp_unit; 21011b654882SGreg Clayton var_success = format_file_spec; 21021b654882SGreg Clayton } 21031b654882SGreg Clayton } 21041b654882SGreg Clayton } 21051b654882SGreg Clayton else if (::strncmp (var_name_begin, "frame.", strlen("frame.")) == 0) 21061b654882SGreg Clayton { 2107c14ee32dSGreg Clayton if (exe_ctx) 2108c14ee32dSGreg Clayton { 2109c14ee32dSGreg Clayton StackFrame *frame = exe_ctx->GetFramePtr(); 2110c14ee32dSGreg Clayton if (frame) 21111b654882SGreg Clayton { 21121b654882SGreg Clayton var_name_begin += ::strlen ("frame."); 21131b654882SGreg Clayton if (::strncmp (var_name_begin, "index}", strlen("index}")) == 0) 21141b654882SGreg Clayton { 2115c14ee32dSGreg Clayton s.Printf("%u", frame->GetFrameIndex()); 21161b654882SGreg Clayton var_success = true; 21171b654882SGreg Clayton } 21181b654882SGreg Clayton else if (::strncmp (var_name_begin, "pc}", strlen("pc}")) == 0) 21191b654882SGreg Clayton { 21201b654882SGreg Clayton reg_kind = eRegisterKindGeneric; 21211b654882SGreg Clayton reg_num = LLDB_REGNUM_GENERIC_PC; 21221b654882SGreg Clayton var_success = true; 21231b654882SGreg Clayton } 21241b654882SGreg Clayton else if (::strncmp (var_name_begin, "sp}", strlen("sp}")) == 0) 21251b654882SGreg Clayton { 21261b654882SGreg Clayton reg_kind = eRegisterKindGeneric; 21271b654882SGreg Clayton reg_num = LLDB_REGNUM_GENERIC_SP; 21281b654882SGreg Clayton var_success = true; 21291b654882SGreg Clayton } 21301b654882SGreg Clayton else if (::strncmp (var_name_begin, "fp}", strlen("fp}")) == 0) 21311b654882SGreg Clayton { 21321b654882SGreg Clayton reg_kind = eRegisterKindGeneric; 21331b654882SGreg Clayton reg_num = LLDB_REGNUM_GENERIC_FP; 21341b654882SGreg Clayton var_success = true; 21351b654882SGreg Clayton } 21361b654882SGreg Clayton else if (::strncmp (var_name_begin, "flags}", strlen("flags}")) == 0) 21371b654882SGreg Clayton { 21381b654882SGreg Clayton reg_kind = eRegisterKindGeneric; 21391b654882SGreg Clayton reg_num = LLDB_REGNUM_GENERIC_FLAGS; 21401b654882SGreg Clayton var_success = true; 21411b654882SGreg Clayton } 21421b654882SGreg Clayton else if (::strncmp (var_name_begin, "reg.", strlen ("reg.")) == 0) 21431b654882SGreg Clayton { 2144c14ee32dSGreg Clayton reg_ctx = frame->GetRegisterContext().get(); 21451b654882SGreg Clayton if (reg_ctx) 21461b654882SGreg Clayton { 21471b654882SGreg Clayton var_name_begin += ::strlen ("reg."); 21481b654882SGreg Clayton if (var_name_begin < var_name_end) 21491b654882SGreg Clayton { 21501b654882SGreg Clayton std::string reg_name (var_name_begin, var_name_end); 21511b654882SGreg Clayton reg_info = reg_ctx->GetRegisterInfoByName (reg_name.c_str()); 21521b654882SGreg Clayton if (reg_info) 21531b654882SGreg Clayton var_success = true; 21541b654882SGreg Clayton } 21551b654882SGreg Clayton } 21561b654882SGreg Clayton } 21571b654882SGreg Clayton } 21581b654882SGreg Clayton } 2159c14ee32dSGreg Clayton } 21601b654882SGreg Clayton else if (::strncmp (var_name_begin, "function.", strlen("function.")) == 0) 21611b654882SGreg Clayton { 21621b654882SGreg Clayton if (sc && (sc->function != NULL || sc->symbol != NULL)) 21631b654882SGreg Clayton { 21641b654882SGreg Clayton var_name_begin += ::strlen ("function."); 21651b654882SGreg Clayton if (::strncmp (var_name_begin, "id}", strlen("id}")) == 0) 21661b654882SGreg Clayton { 21671b654882SGreg Clayton if (sc->function) 2168d01b2953SDaniel Malea s.Printf("function{0x%8.8" PRIx64 "}", sc->function->GetID()); 21691b654882SGreg Clayton else 21701b654882SGreg Clayton s.Printf("symbol[%u]", sc->symbol->GetID()); 21711b654882SGreg Clayton 21721b654882SGreg Clayton var_success = true; 21731b654882SGreg Clayton } 21741b654882SGreg Clayton else if (::strncmp (var_name_begin, "name}", strlen("name}")) == 0) 21751b654882SGreg Clayton { 21761b654882SGreg Clayton if (sc->function) 21771b654882SGreg Clayton cstr = sc->function->GetName().AsCString (NULL); 21781b654882SGreg Clayton else if (sc->symbol) 21791b654882SGreg Clayton cstr = sc->symbol->GetName().AsCString (NULL); 21801b654882SGreg Clayton if (cstr) 21811b654882SGreg Clayton { 21821b654882SGreg Clayton s.PutCString(cstr); 21830d9c9934SGreg Clayton 21840d9c9934SGreg Clayton if (sc->block) 21850d9c9934SGreg Clayton { 21860d9c9934SGreg Clayton Block *inline_block = sc->block->GetContainingInlinedBlock (); 21870d9c9934SGreg Clayton if (inline_block) 21880d9c9934SGreg Clayton { 21890d9c9934SGreg Clayton const InlineFunctionInfo *inline_info = sc->block->GetInlinedFunctionInfo(); 21900d9c9934SGreg Clayton if (inline_info) 21910d9c9934SGreg Clayton { 21920d9c9934SGreg Clayton s.PutCString(" [inlined] "); 21930d9c9934SGreg Clayton inline_info->GetName().Dump(&s); 21940d9c9934SGreg Clayton } 21950d9c9934SGreg Clayton } 21960d9c9934SGreg Clayton } 21971b654882SGreg Clayton var_success = true; 21981b654882SGreg Clayton } 21991b654882SGreg Clayton } 22006d3dbf51SGreg Clayton else if (::strncmp (var_name_begin, "name-with-args}", strlen("name-with-args}")) == 0) 22016d3dbf51SGreg Clayton { 22026d3dbf51SGreg Clayton // Print the function name with arguments in it 22036d3dbf51SGreg Clayton 22046d3dbf51SGreg Clayton if (sc->function) 22056d3dbf51SGreg Clayton { 22066d3dbf51SGreg Clayton var_success = true; 22076d3dbf51SGreg Clayton ExecutionContextScope *exe_scope = exe_ctx ? exe_ctx->GetBestExecutionContextScope() : NULL; 22086d3dbf51SGreg Clayton cstr = sc->function->GetName().AsCString (NULL); 22096d3dbf51SGreg Clayton if (cstr) 22106d3dbf51SGreg Clayton { 22116d3dbf51SGreg Clayton const InlineFunctionInfo *inline_info = NULL; 22126d3dbf51SGreg Clayton VariableListSP variable_list_sp; 22136d3dbf51SGreg Clayton bool get_function_vars = true; 22146d3dbf51SGreg Clayton if (sc->block) 22156d3dbf51SGreg Clayton { 22166d3dbf51SGreg Clayton Block *inline_block = sc->block->GetContainingInlinedBlock (); 22176d3dbf51SGreg Clayton 22186d3dbf51SGreg Clayton if (inline_block) 22196d3dbf51SGreg Clayton { 22206d3dbf51SGreg Clayton get_function_vars = false; 22216d3dbf51SGreg Clayton inline_info = sc->block->GetInlinedFunctionInfo(); 22226d3dbf51SGreg Clayton if (inline_info) 22236d3dbf51SGreg Clayton variable_list_sp = inline_block->GetBlockVariableList (true); 22246d3dbf51SGreg Clayton } 22256d3dbf51SGreg Clayton } 22266d3dbf51SGreg Clayton 22276d3dbf51SGreg Clayton if (get_function_vars) 22286d3dbf51SGreg Clayton { 22296d3dbf51SGreg Clayton variable_list_sp = sc->function->GetBlock(true).GetBlockVariableList (true); 22306d3dbf51SGreg Clayton } 22316d3dbf51SGreg Clayton 22326d3dbf51SGreg Clayton if (inline_info) 22336d3dbf51SGreg Clayton { 22346d3dbf51SGreg Clayton s.PutCString (cstr); 22356d3dbf51SGreg Clayton s.PutCString (" [inlined] "); 22366d3dbf51SGreg Clayton cstr = inline_info->GetName().GetCString(); 22376d3dbf51SGreg Clayton } 22386d3dbf51SGreg Clayton 22396d3dbf51SGreg Clayton VariableList args; 22406d3dbf51SGreg Clayton if (variable_list_sp) 22416d3dbf51SGreg Clayton { 22426d3dbf51SGreg Clayton const size_t num_variables = variable_list_sp->GetSize(); 22436d3dbf51SGreg Clayton for (size_t var_idx = 0; var_idx < num_variables; ++var_idx) 22446d3dbf51SGreg Clayton { 22456d3dbf51SGreg Clayton VariableSP var_sp (variable_list_sp->GetVariableAtIndex(var_idx)); 22466d3dbf51SGreg Clayton if (var_sp->GetScope() == eValueTypeVariableArgument) 22476d3dbf51SGreg Clayton args.AddVariable (var_sp); 22486d3dbf51SGreg Clayton } 22496d3dbf51SGreg Clayton 22506d3dbf51SGreg Clayton } 22516d3dbf51SGreg Clayton if (args.GetSize() > 0) 22526d3dbf51SGreg Clayton { 22536d3dbf51SGreg Clayton const char *open_paren = strchr (cstr, '('); 22546d3dbf51SGreg Clayton const char *close_paren = NULL; 22556d3dbf51SGreg Clayton if (open_paren) 22566d3dbf51SGreg Clayton close_paren = strchr (open_paren, ')'); 22576d3dbf51SGreg Clayton 22586d3dbf51SGreg Clayton if (open_paren) 22596d3dbf51SGreg Clayton s.Write(cstr, open_paren - cstr + 1); 22606d3dbf51SGreg Clayton else 22616d3dbf51SGreg Clayton { 22626d3dbf51SGreg Clayton s.PutCString (cstr); 22636d3dbf51SGreg Clayton s.PutChar ('('); 22646d3dbf51SGreg Clayton } 22655b6889b1SGreg Clayton const size_t num_args = args.GetSize(); 22666d3dbf51SGreg Clayton for (size_t arg_idx = 0; arg_idx < num_args; ++arg_idx) 22676d3dbf51SGreg Clayton { 22686d3dbf51SGreg Clayton VariableSP var_sp (args.GetVariableAtIndex (arg_idx)); 22696d3dbf51SGreg Clayton ValueObjectSP var_value_sp (ValueObjectVariable::Create (exe_scope, var_sp)); 22706d3dbf51SGreg Clayton const char *var_name = var_value_sp->GetName().GetCString(); 22716d3dbf51SGreg Clayton const char *var_value = var_value_sp->GetValueAsCString(); 22726d3dbf51SGreg Clayton if (arg_idx > 0) 22736d3dbf51SGreg Clayton s.PutCString (", "); 22743b188b17SGreg Clayton if (var_value_sp->GetError().Success()) 22756d3dbf51SGreg Clayton s.Printf ("%s=%s", var_name, var_value); 22763b188b17SGreg Clayton else 22773b188b17SGreg Clayton s.Printf ("%s=<unavailable>", var_name); 22786d3dbf51SGreg Clayton } 22796d3dbf51SGreg Clayton 22806d3dbf51SGreg Clayton if (close_paren) 22816d3dbf51SGreg Clayton s.PutCString (close_paren); 22826d3dbf51SGreg Clayton else 22836d3dbf51SGreg Clayton s.PutChar(')'); 22846d3dbf51SGreg Clayton 22856d3dbf51SGreg Clayton } 22866d3dbf51SGreg Clayton else 22876d3dbf51SGreg Clayton { 22886d3dbf51SGreg Clayton s.PutCString(cstr); 22896d3dbf51SGreg Clayton } 22906d3dbf51SGreg Clayton } 22916d3dbf51SGreg Clayton } 22926d3dbf51SGreg Clayton else if (sc->symbol) 22936d3dbf51SGreg Clayton { 22946d3dbf51SGreg Clayton cstr = sc->symbol->GetName().AsCString (NULL); 22956d3dbf51SGreg Clayton if (cstr) 22966d3dbf51SGreg Clayton { 22976d3dbf51SGreg Clayton s.PutCString(cstr); 22986d3dbf51SGreg Clayton var_success = true; 22996d3dbf51SGreg Clayton } 23006d3dbf51SGreg Clayton } 23016d3dbf51SGreg Clayton } 23021b654882SGreg Clayton else if (::strncmp (var_name_begin, "addr-offset}", strlen("addr-offset}")) == 0) 23031b654882SGreg Clayton { 23041b654882SGreg Clayton var_success = addr != NULL; 23051b654882SGreg Clayton if (var_success) 23061b654882SGreg Clayton { 23071b654882SGreg Clayton format_addr = *addr; 23081b654882SGreg Clayton calculate_format_addr_function_offset = true; 23091b654882SGreg Clayton } 23101b654882SGreg Clayton } 23111b654882SGreg Clayton else if (::strncmp (var_name_begin, "line-offset}", strlen("line-offset}")) == 0) 23121b654882SGreg Clayton { 23131b654882SGreg Clayton var_success = sc->line_entry.range.GetBaseAddress().IsValid(); 23141b654882SGreg Clayton if (var_success) 23151b654882SGreg Clayton { 23161b654882SGreg Clayton format_addr = sc->line_entry.range.GetBaseAddress(); 23171b654882SGreg Clayton calculate_format_addr_function_offset = true; 23181b654882SGreg Clayton } 23191b654882SGreg Clayton } 23201b654882SGreg Clayton else if (::strncmp (var_name_begin, "pc-offset}", strlen("pc-offset}")) == 0) 23211b654882SGreg Clayton { 2322c14ee32dSGreg Clayton StackFrame *frame = exe_ctx->GetFramePtr(); 2323c14ee32dSGreg Clayton var_success = frame != NULL; 23241b654882SGreg Clayton if (var_success) 23251b654882SGreg Clayton { 2326c14ee32dSGreg Clayton format_addr = frame->GetFrameCodeAddress(); 23271b654882SGreg Clayton calculate_format_addr_function_offset = true; 23281b654882SGreg Clayton } 23291b654882SGreg Clayton } 23301b654882SGreg Clayton } 23311b654882SGreg Clayton } 23321b654882SGreg Clayton break; 23331b654882SGreg Clayton 23341b654882SGreg Clayton case 'l': 23351b654882SGreg Clayton if (::strncmp (var_name_begin, "line.", strlen("line.")) == 0) 23361b654882SGreg Clayton { 23371b654882SGreg Clayton if (sc && sc->line_entry.IsValid()) 23381b654882SGreg Clayton { 23391b654882SGreg Clayton var_name_begin += ::strlen ("line."); 23401b654882SGreg Clayton if (::strncmp (var_name_begin, "file.", strlen("file.")) == 0) 23411b654882SGreg Clayton { 23421b654882SGreg Clayton var_name_begin += ::strlen ("file."); 23431b654882SGreg Clayton 23441b654882SGreg Clayton if (::strncmp (var_name_begin, "basename}", strlen("basename}")) == 0) 23451b654882SGreg Clayton { 23461b654882SGreg Clayton format_file_spec.GetFilename() = sc->line_entry.file.GetFilename(); 23471b654882SGreg Clayton var_success = format_file_spec; 23481b654882SGreg Clayton } 23491b654882SGreg Clayton else if (::strncmp (var_name_begin, "fullpath}", strlen("fullpath}")) == 0) 23501b654882SGreg Clayton { 23511b654882SGreg Clayton format_file_spec = sc->line_entry.file; 23521b654882SGreg Clayton var_success = format_file_spec; 23531b654882SGreg Clayton } 23541b654882SGreg Clayton } 23551b654882SGreg Clayton else if (::strncmp (var_name_begin, "number}", strlen("number}")) == 0) 23561b654882SGreg Clayton { 23571b654882SGreg Clayton var_success = true; 23581b654882SGreg Clayton s.Printf("%u", sc->line_entry.line); 23591b654882SGreg Clayton } 23601b654882SGreg Clayton else if ((::strncmp (var_name_begin, "start-addr}", strlen("start-addr}")) == 0) || 23611b654882SGreg Clayton (::strncmp (var_name_begin, "end-addr}", strlen("end-addr}")) == 0)) 23621b654882SGreg Clayton { 23631b654882SGreg Clayton var_success = sc && sc->line_entry.range.GetBaseAddress().IsValid(); 23641b654882SGreg Clayton if (var_success) 23651b654882SGreg Clayton { 23661b654882SGreg Clayton format_addr = sc->line_entry.range.GetBaseAddress(); 23671b654882SGreg Clayton if (var_name_begin[0] == 'e') 23681b654882SGreg Clayton format_addr.Slide (sc->line_entry.range.GetByteSize()); 23691b654882SGreg Clayton } 23701b654882SGreg Clayton } 23711b654882SGreg Clayton } 23721b654882SGreg Clayton } 23731b654882SGreg Clayton break; 23741b654882SGreg Clayton } 23751b654882SGreg Clayton 23761b654882SGreg Clayton if (var_success) 23771b654882SGreg Clayton { 23781b654882SGreg Clayton // If format addr is valid, then we need to print an address 23791b654882SGreg Clayton if (reg_num != LLDB_INVALID_REGNUM) 23801b654882SGreg Clayton { 2381c14ee32dSGreg Clayton StackFrame *frame = exe_ctx->GetFramePtr(); 23821b654882SGreg Clayton // We have a register value to display... 23831b654882SGreg Clayton if (reg_num == LLDB_REGNUM_GENERIC_PC && reg_kind == eRegisterKindGeneric) 23841b654882SGreg Clayton { 2385c14ee32dSGreg Clayton format_addr = frame->GetFrameCodeAddress(); 23861b654882SGreg Clayton } 23871b654882SGreg Clayton else 23881b654882SGreg Clayton { 23891b654882SGreg Clayton if (reg_ctx == NULL) 2390c14ee32dSGreg Clayton reg_ctx = frame->GetRegisterContext().get(); 23911b654882SGreg Clayton 23921b654882SGreg Clayton if (reg_ctx) 23931b654882SGreg Clayton { 23941b654882SGreg Clayton if (reg_kind != kNumRegisterKinds) 23951b654882SGreg Clayton reg_num = reg_ctx->ConvertRegisterKindToRegisterNumber(reg_kind, reg_num); 23961b654882SGreg Clayton reg_info = reg_ctx->GetRegisterInfoAtIndex (reg_num); 23971b654882SGreg Clayton var_success = reg_info != NULL; 23981b654882SGreg Clayton } 23991b654882SGreg Clayton } 24001b654882SGreg Clayton } 24011b654882SGreg Clayton 24021b654882SGreg Clayton if (reg_info != NULL) 24031b654882SGreg Clayton { 24047349bd90SGreg Clayton RegisterValue reg_value; 24057349bd90SGreg Clayton var_success = reg_ctx->ReadRegister (reg_info, reg_value); 24067349bd90SGreg Clayton if (var_success) 24071b654882SGreg Clayton { 24089a8fa916SGreg Clayton reg_value.Dump(&s, reg_info, false, false, eFormatDefault); 24091b654882SGreg Clayton } 24101b654882SGreg Clayton } 24111b654882SGreg Clayton 24121b654882SGreg Clayton if (format_file_spec) 24131b654882SGreg Clayton { 24141b654882SGreg Clayton s << format_file_spec; 24151b654882SGreg Clayton } 24161b654882SGreg Clayton 24171b654882SGreg Clayton // If format addr is valid, then we need to print an address 24181b654882SGreg Clayton if (format_addr.IsValid()) 24191b654882SGreg Clayton { 24200603aa9dSGreg Clayton var_success = false; 24210603aa9dSGreg Clayton 24221b654882SGreg Clayton if (calculate_format_addr_function_offset) 24231b654882SGreg Clayton { 24241b654882SGreg Clayton Address func_addr; 24250603aa9dSGreg Clayton 24260603aa9dSGreg Clayton if (sc) 24270603aa9dSGreg Clayton { 24281b654882SGreg Clayton if (sc->function) 24290d9c9934SGreg Clayton { 24301b654882SGreg Clayton func_addr = sc->function->GetAddressRange().GetBaseAddress(); 24310d9c9934SGreg Clayton if (sc->block) 24320d9c9934SGreg Clayton { 24330d9c9934SGreg Clayton // Check to make sure we aren't in an inline 24340d9c9934SGreg Clayton // function. If we are, use the inline block 24350d9c9934SGreg Clayton // range that contains "format_addr" since 24360d9c9934SGreg Clayton // blocks can be discontiguous. 24370d9c9934SGreg Clayton Block *inline_block = sc->block->GetContainingInlinedBlock (); 24380d9c9934SGreg Clayton AddressRange inline_range; 24390d9c9934SGreg Clayton if (inline_block && inline_block->GetRangeContainingAddress (format_addr, inline_range)) 24400d9c9934SGreg Clayton func_addr = inline_range.GetBaseAddress(); 24410d9c9934SGreg Clayton } 24420d9c9934SGreg Clayton } 2443e7612134SGreg Clayton else if (sc->symbol && sc->symbol->ValueIsAddress()) 2444e7612134SGreg Clayton func_addr = sc->symbol->GetAddress(); 24450603aa9dSGreg Clayton } 24461b654882SGreg Clayton 24470603aa9dSGreg Clayton if (func_addr.IsValid()) 24481b654882SGreg Clayton { 24491b654882SGreg Clayton if (func_addr.GetSection() == format_addr.GetSection()) 24501b654882SGreg Clayton { 24511b654882SGreg Clayton addr_t func_file_addr = func_addr.GetFileAddress(); 24521b654882SGreg Clayton addr_t addr_file_addr = format_addr.GetFileAddress(); 24531b654882SGreg Clayton if (addr_file_addr > func_file_addr) 2454d01b2953SDaniel Malea s.Printf(" + %" PRIu64, addr_file_addr - func_file_addr); 24551b654882SGreg Clayton else if (addr_file_addr < func_file_addr) 2456d01b2953SDaniel Malea s.Printf(" - %" PRIu64, func_file_addr - addr_file_addr); 24570603aa9dSGreg Clayton var_success = true; 24581b654882SGreg Clayton } 24591b654882SGreg Clayton else 24600603aa9dSGreg Clayton { 24610603aa9dSGreg Clayton Target *target = Target::GetTargetFromContexts (exe_ctx, sc); 24620603aa9dSGreg Clayton if (target) 24630603aa9dSGreg Clayton { 24640603aa9dSGreg Clayton addr_t func_load_addr = func_addr.GetLoadAddress (target); 24650603aa9dSGreg Clayton addr_t addr_load_addr = format_addr.GetLoadAddress (target); 24660603aa9dSGreg Clayton if (addr_load_addr > func_load_addr) 2467d01b2953SDaniel Malea s.Printf(" + %" PRIu64, addr_load_addr - func_load_addr); 24680603aa9dSGreg Clayton else if (addr_load_addr < func_load_addr) 2469d01b2953SDaniel Malea s.Printf(" - %" PRIu64, func_load_addr - addr_load_addr); 24700603aa9dSGreg Clayton var_success = true; 24710603aa9dSGreg Clayton } 24720603aa9dSGreg Clayton } 24731b654882SGreg Clayton } 24741b654882SGreg Clayton } 24751b654882SGreg Clayton else 24761b654882SGreg Clayton { 24770603aa9dSGreg Clayton Target *target = Target::GetTargetFromContexts (exe_ctx, sc); 24781b654882SGreg Clayton addr_t vaddr = LLDB_INVALID_ADDRESS; 24790603aa9dSGreg Clayton if (exe_ctx && !target->GetSectionLoadList().IsEmpty()) 24800603aa9dSGreg Clayton vaddr = format_addr.GetLoadAddress (target); 24811b654882SGreg Clayton if (vaddr == LLDB_INVALID_ADDRESS) 24821b654882SGreg Clayton vaddr = format_addr.GetFileAddress (); 24831b654882SGreg Clayton 24841b654882SGreg Clayton if (vaddr != LLDB_INVALID_ADDRESS) 24850603aa9dSGreg Clayton { 2486514487e8SGreg Clayton int addr_width = target->GetArchitecture().GetAddressByteSize() * 2; 248735f1a0d5SGreg Clayton if (addr_width == 0) 248835f1a0d5SGreg Clayton addr_width = 16; 2489d01b2953SDaniel Malea s.Printf("0x%*.*" PRIx64, addr_width, addr_width, vaddr); 24900603aa9dSGreg Clayton var_success = true; 24910603aa9dSGreg Clayton } 24921b654882SGreg Clayton } 24931b654882SGreg Clayton } 24941b654882SGreg Clayton } 24951b654882SGreg Clayton 24961b654882SGreg Clayton if (var_success == false) 24971b654882SGreg Clayton success = false; 24981b654882SGreg Clayton } 24991b654882SGreg Clayton p = var_name_end; 25001b654882SGreg Clayton } 25011b654882SGreg Clayton else 25021b654882SGreg Clayton break; 25031b654882SGreg Clayton } 25041b654882SGreg Clayton else 25051b654882SGreg Clayton { 25061b654882SGreg Clayton // We got a dollar sign with no '{' after it, it must just be a dollar sign 25071b654882SGreg Clayton s.PutChar(*p); 25081b654882SGreg Clayton } 25091b654882SGreg Clayton } 25101b654882SGreg Clayton else if (*p == '\\') 25111b654882SGreg Clayton { 25121b654882SGreg Clayton ++p; // skip the slash 25131b654882SGreg Clayton switch (*p) 25141b654882SGreg Clayton { 25151b654882SGreg Clayton case 'a': s.PutChar ('\a'); break; 25161b654882SGreg Clayton case 'b': s.PutChar ('\b'); break; 25171b654882SGreg Clayton case 'f': s.PutChar ('\f'); break; 25181b654882SGreg Clayton case 'n': s.PutChar ('\n'); break; 25191b654882SGreg Clayton case 'r': s.PutChar ('\r'); break; 25201b654882SGreg Clayton case 't': s.PutChar ('\t'); break; 25211b654882SGreg Clayton case 'v': s.PutChar ('\v'); break; 25221b654882SGreg Clayton case '\'': s.PutChar ('\''); break; 25231b654882SGreg Clayton case '\\': s.PutChar ('\\'); break; 25241b654882SGreg Clayton case '0': 25251b654882SGreg Clayton // 1 to 3 octal chars 25261b654882SGreg Clayton { 25270603aa9dSGreg Clayton // Make a string that can hold onto the initial zero char, 25280603aa9dSGreg Clayton // up to 3 octal digits, and a terminating NULL. 25290603aa9dSGreg Clayton char oct_str[5] = { 0, 0, 0, 0, 0 }; 25300603aa9dSGreg Clayton 25310603aa9dSGreg Clayton int i; 25320603aa9dSGreg Clayton for (i=0; (p[i] >= '0' && p[i] <= '7') && i<4; ++i) 25330603aa9dSGreg Clayton oct_str[i] = p[i]; 25340603aa9dSGreg Clayton 25350603aa9dSGreg Clayton // We don't want to consume the last octal character since 25360603aa9dSGreg Clayton // the main for loop will do this for us, so we advance p by 25370603aa9dSGreg Clayton // one less than i (even if i is zero) 25380603aa9dSGreg Clayton p += i - 1; 25390603aa9dSGreg Clayton unsigned long octal_value = ::strtoul (oct_str, NULL, 8); 25400603aa9dSGreg Clayton if (octal_value <= UINT8_MAX) 25411b654882SGreg Clayton { 25420603aa9dSGreg Clayton char octal_char = octal_value; 25430603aa9dSGreg Clayton s.Write (&octal_char, 1); 25441b654882SGreg Clayton } 25451b654882SGreg Clayton } 25461b654882SGreg Clayton break; 25471b654882SGreg Clayton 25481b654882SGreg Clayton case 'x': 25491b654882SGreg Clayton // hex number in the format 25500603aa9dSGreg Clayton if (isxdigit(p[1])) 25511b654882SGreg Clayton { 25520603aa9dSGreg Clayton ++p; // Skip the 'x' 25531b654882SGreg Clayton 25540603aa9dSGreg Clayton // Make a string that can hold onto two hex chars plus a 25550603aa9dSGreg Clayton // NULL terminator 25561b654882SGreg Clayton char hex_str[3] = { 0,0,0 }; 25571b654882SGreg Clayton hex_str[0] = *p; 25580603aa9dSGreg Clayton if (isxdigit(p[1])) 25590603aa9dSGreg Clayton { 25600603aa9dSGreg Clayton ++p; // Skip the first of the two hex chars 25611b654882SGreg Clayton hex_str[1] = *p; 25620603aa9dSGreg Clayton } 25630603aa9dSGreg Clayton 25641b654882SGreg Clayton unsigned long hex_value = strtoul (hex_str, NULL, 16); 25650603aa9dSGreg Clayton if (hex_value <= UINT8_MAX) 25661b654882SGreg Clayton s.PutChar (hex_value); 25671b654882SGreg Clayton } 25681b654882SGreg Clayton else 25691b654882SGreg Clayton { 25700603aa9dSGreg Clayton s.PutChar('x'); 25711b654882SGreg Clayton } 25721b654882SGreg Clayton break; 25731b654882SGreg Clayton 25741b654882SGreg Clayton default: 25750603aa9dSGreg Clayton // Just desensitize any other character by just printing what 25760603aa9dSGreg Clayton // came after the '\' 25770603aa9dSGreg Clayton s << *p; 25781b654882SGreg Clayton break; 25791b654882SGreg Clayton 25801b654882SGreg Clayton } 25811b654882SGreg Clayton 25821b654882SGreg Clayton } 25831b654882SGreg Clayton } 25841b654882SGreg Clayton if (end) 25851b654882SGreg Clayton *end = p; 25861b654882SGreg Clayton return success; 25871b654882SGreg Clayton } 25881b654882SGreg Clayton 2589228063cdSJim Ingham void 2590228063cdSJim Ingham Debugger::SetLoggingCallback (lldb::LogOutputCallback log_callback, void *baton) 2591228063cdSJim Ingham { 25924f02b22dSJim Ingham // For simplicity's sake, I am not going to deal with how to close down any 25934f02b22dSJim Ingham // open logging streams, I just redirect everything from here on out to the 25944f02b22dSJim Ingham // callback. 2595228063cdSJim Ingham m_log_callback_stream_sp.reset (new StreamCallback (log_callback, baton)); 2596228063cdSJim Ingham } 2597228063cdSJim Ingham 2598228063cdSJim Ingham bool 2599228063cdSJim Ingham Debugger::EnableLog (const char *channel, const char **categories, const char *log_file, uint32_t log_options, Stream &error_stream) 2600228063cdSJim Ingham { 2601228063cdSJim Ingham Log::Callbacks log_callbacks; 2602228063cdSJim Ingham 2603228063cdSJim Ingham StreamSP log_stream_sp; 26049a028519SSean Callanan if (m_log_callback_stream_sp) 2605228063cdSJim Ingham { 2606228063cdSJim Ingham log_stream_sp = m_log_callback_stream_sp; 2607228063cdSJim Ingham // For now when using the callback mode you always get thread & timestamp. 2608228063cdSJim Ingham log_options |= LLDB_LOG_OPTION_PREPEND_TIMESTAMP | LLDB_LOG_OPTION_PREPEND_THREAD_NAME; 2609228063cdSJim Ingham } 2610228063cdSJim Ingham else if (log_file == NULL || *log_file == '\0') 2611228063cdSJim Ingham { 2612228063cdSJim Ingham log_stream_sp.reset(new StreamFile(GetOutputFile().GetDescriptor(), false)); 2613228063cdSJim Ingham } 2614228063cdSJim Ingham else 2615228063cdSJim Ingham { 2616228063cdSJim Ingham LogStreamMap::iterator pos = m_log_streams.find(log_file); 2617*c1b2ccfdSGreg Clayton if (pos != m_log_streams.end()) 2618*c1b2ccfdSGreg Clayton log_stream_sp = pos->second.lock(); 2619*c1b2ccfdSGreg Clayton if (!log_stream_sp) 2620228063cdSJim Ingham { 2621228063cdSJim Ingham log_stream_sp.reset (new StreamFile (log_file)); 2622228063cdSJim Ingham m_log_streams[log_file] = log_stream_sp; 2623228063cdSJim Ingham } 2624228063cdSJim Ingham } 2625228063cdSJim Ingham assert (log_stream_sp.get()); 2626228063cdSJim Ingham 2627228063cdSJim Ingham if (log_options == 0) 2628228063cdSJim Ingham log_options = LLDB_LOG_OPTION_PREPEND_THREAD_NAME | LLDB_LOG_OPTION_THREADSAFE; 2629228063cdSJim Ingham 2630228063cdSJim Ingham if (Log::GetLogChannelCallbacks (channel, log_callbacks)) 2631228063cdSJim Ingham { 2632228063cdSJim Ingham log_callbacks.enable (log_stream_sp, log_options, categories, &error_stream); 2633228063cdSJim Ingham return true; 2634228063cdSJim Ingham } 2635228063cdSJim Ingham else 2636228063cdSJim Ingham { 2637228063cdSJim Ingham LogChannelSP log_channel_sp (LogChannel::FindPlugin (channel)); 2638228063cdSJim Ingham if (log_channel_sp) 2639228063cdSJim Ingham { 2640228063cdSJim Ingham if (log_channel_sp->Enable (log_stream_sp, log_options, &error_stream, categories)) 2641228063cdSJim Ingham { 2642228063cdSJim Ingham return true; 2643228063cdSJim Ingham } 2644228063cdSJim Ingham else 2645228063cdSJim Ingham { 2646228063cdSJim Ingham error_stream.Printf ("Invalid log channel '%s'.\n", channel); 2647228063cdSJim Ingham return false; 2648228063cdSJim Ingham } 2649228063cdSJim Ingham } 2650228063cdSJim Ingham else 2651228063cdSJim Ingham { 2652228063cdSJim Ingham error_stream.Printf ("Invalid log channel '%s'.\n", channel); 2653228063cdSJim Ingham return false; 2654228063cdSJim Ingham } 2655228063cdSJim Ingham } 2656228063cdSJim Ingham return false; 2657228063cdSJim Ingham } 2658228063cdSJim Ingham 2659