diff options
author | Enrico Granata <granata.enrico@gmail.com> | 2011-07-15 02:26:42 +0000 |
---|---|---|
committer | Enrico Granata <granata.enrico@gmail.com> | 2011-07-15 02:26:42 +0000 |
commit | f2bbf717f72f7f01b83b1b41b0fd014c9471c8aa (patch) | |
tree | bcbf57281baa4c9e0fe1c4c440087ff2e6c2528c | |
parent | a83b37a9db2880091f4f8e7683c30ca142678fff (diff) | |
download | bcm5719-llvm-f2bbf717f72f7f01b83b1b41b0fd014c9471c8aa.tar.gz bcm5719-llvm-f2bbf717f72f7f01b83b1b41b0fd014c9471c8aa.zip |
Python summary strings:
- you can use a Python script to write a summary string for data-types, in one of
three ways:
-P option and typing the script a line at a time
-s option and passing a one-line Python script
-F option and passing the name of a Python function
these options all work for the "type summary add" command
your Python code (if provided through -P or -s) is wrapped in a function
that accepts two parameters: valobj (a ValueObject) and dict (an LLDB
internal dictionary object). if you use -F and give a function name,
you're expected to define the function on your own and with the right
prototype. your function, however defined, must return a Python string
- test case for the Python summary feature
- a few quirks:
Python summaries cannot have names, and cannot use regex as type names
both issues will be fixed ASAP
major redesign of type summary code:
- type summary working with strings and type summary working with Python code
are two classes, with a common base class SummaryFormat
- SummaryFormat classes now are able to actively format objects rather than
just aggregating data
- cleaner code to print descriptions for summaries
the public API now exports a method to easily navigate a ValueObject hierarchy
New InputReaderEZ and PriorityPointerPair classes
Several minor fixes and improvements
llvm-svn: 135238
33 files changed, 1897 insertions, 277 deletions
diff --git a/lldb/include/lldb/API/SBValue.h b/lldb/include/lldb/API/SBValue.h index 40a461285b2..9fce5bc2876 100644 --- a/lldb/include/lldb/API/SBValue.h +++ b/lldb/include/lldb/API/SBValue.h @@ -167,6 +167,10 @@ public: // classes. lldb::SBValue GetChildMemberWithName (const char *name, lldb::DynamicValueType use_dynamic); + + // Expands nested expressions like .a->b[0].c[1]->d + lldb::SBValue + GetValueForExpressionPath(const char* expr_path); uint32_t GetNumChildren (); @@ -190,12 +194,12 @@ public: bool GetExpressionPath (lldb::SBStream &description, bool qualify_cxx_base_classes); + SBValue (const lldb::ValueObjectSP &value_sp); + protected: friend class SBValueList; friend class SBFrame; - SBValue (const lldb::ValueObjectSP &value_sp); - #ifndef SWIG // Mimic shared pointer... diff --git a/lldb/include/lldb/Core/Debugger.h b/lldb/include/lldb/Core/Debugger.h index f43b842fd3b..ea9a648ee12 100644 --- a/lldb/include/lldb/Core/Debugger.h +++ b/lldb/include/lldb/Core/Debugger.h @@ -576,8 +576,6 @@ public: static uint32_t GetCount(); }; - - }; } // namespace lldb_private diff --git a/lldb/include/lldb/Core/Error.h b/lldb/include/lldb/Core/Error.h index a36d842224e..a0476c8353b 100644 --- a/lldb/include/lldb/Core/Error.h +++ b/lldb/include/lldb/Core/Error.h @@ -69,6 +69,9 @@ public: explicit Error (ValueType err, lldb::ErrorType type = lldb::eErrorTypeGeneric); + explicit + Error (const char* err_str); + Error (const Error &rhs); //------------------------------------------------------------------ /// Assignment operator. diff --git a/lldb/include/lldb/Core/FormatManager.h b/lldb/include/lldb/Core/FormatManager.h index f1bd52cc38b..1fc4756f0bf 100644 --- a/lldb/include/lldb/Core/FormatManager.h +++ b/lldb/include/lldb/Core/FormatManager.h @@ -50,8 +50,10 @@ namespace std #include "lldb/Core/UserID.h" #include "lldb/Core/UserSettingsController.h" #include "lldb/Core/ValueObject.h" +#include "lldb/Interpreter/ScriptInterpreterPython.h" #include "lldb/Target/ExecutionContext.h" #include "lldb/Target/Platform.h" +#include "lldb/Target/StackFrame.h" #include "lldb/Target/TargetList.h" namespace lldb_private { @@ -67,8 +69,263 @@ public: }; +struct ValueFormat +{ + bool m_cascades; + bool m_skip_pointers; + bool m_skip_references; + lldb::Format m_format; + ValueFormat (lldb::Format f = lldb::eFormatInvalid, + bool casc = false, + bool skipptr = false, + bool skipref = false) : + m_cascades(casc), + m_skip_pointers(skipptr), + m_skip_references(skipref), + m_format (f) + { + } + + typedef lldb::SharedPtr<ValueFormat>::Type SharedPointer; + typedef bool(*ValueCallback)(void*, const char*, const ValueFormat::SharedPointer&); + + ~ValueFormat() + { + } + + bool + Cascades() + { + return m_cascades; + } + bool + SkipsPointers() + { + return m_skip_pointers; + } + bool + SkipsReferences() + { + return m_skip_references; + } + + lldb::Format + GetFormat() + { + return m_format; + } + + std::string + FormatObject(lldb::ValueObjectSP object) + { + if (!object.get()) + return "NULL"; + + StreamString sstr; + + if (ClangASTType::DumpTypeValue (object->GetClangAST(), // The clang AST + object->GetClangType(), // The clang type to display + &sstr, + m_format, // Format to display this type with + object->GetDataExtractor(), // Data to extract from + 0, // Byte offset into "data" + object->GetByteSize(), // Byte size of item in "data" + object->GetBitfieldBitSize(), // Bitfield bit size + object->GetBitfieldBitOffset())) // Bitfield bit offset + return (sstr.GetString()); + else + { + return ("unsufficient data for value"); + } + + } + +}; + struct SummaryFormat { + bool m_cascades; + bool m_skip_pointers; + bool m_skip_references; + bool m_dont_show_children; + bool m_dont_show_value; + bool m_show_members_oneliner; + + SummaryFormat(bool casc = false, + bool skipptr = false, + bool skipref = false, + bool nochildren = true, + bool novalue = true, + bool oneliner = false) : + m_cascades(casc), + m_skip_pointers(skipptr), + m_skip_references(skipref), + m_dont_show_children(nochildren), + m_dont_show_value(novalue), + m_show_members_oneliner(oneliner) + { + } + + bool + Cascades() + { + return m_cascades; + } + bool + SkipsPointers() + { + return m_skip_pointers; + } + bool + SkipsReferences() + { + return m_skip_references; + } + + bool + DoesPrintChildren() const + { + return !m_dont_show_children; + } + + bool + DoesPrintValue() const + { + return !m_dont_show_value; + } + + bool + IsOneliner() const + { + return m_show_members_oneliner; + } + + virtual + ~SummaryFormat() + { + } + + virtual std::string + FormatObject(lldb::ValueObjectSP object) = 0; + + virtual std::string + GetDescription() = 0; + + typedef lldb::SharedPtr<SummaryFormat>::Type SharedPointer; + typedef bool(*SummaryCallback)(void*, const char*, const SummaryFormat::SharedPointer&); + typedef bool(*RegexSummaryCallback)(void*, lldb::RegularExpressionSP, const SummaryFormat::SharedPointer&); + +}; + +// simple string-based summaries, using ${var to show data +struct StringSummaryFormat : public SummaryFormat +{ + std::string m_format; + + StringSummaryFormat(bool casc = false, + bool skipptr = false, + bool skipref = false, + bool nochildren = true, + bool novalue = true, + bool oneliner = false, + std::string f = "") : + SummaryFormat(casc,skipptr,skipref,nochildren,novalue,oneliner), + m_format(f) + { + } + + std::string + GetFormat() + { + return m_format; + } + + virtual + ~StringSummaryFormat() + { + } + + virtual std::string + FormatObject(lldb::ValueObjectSP object); + + virtual std::string + GetDescription() + { + StreamString sstr; + sstr.Printf ("`%s`%s%s%s%s%s%s\n", m_format.c_str(), + m_cascades ? "" : " (not cascading)", + m_dont_show_children ? "" : " (show children)", + m_dont_show_value ? " (hide value)" : "", + m_show_members_oneliner ? " (one-line printout)" : "", + m_skip_pointers ? " (skip pointers)" : "", + m_skip_references ? " (skip references)" : ""); + return sstr.GetString(); + } + +}; + +// Python-based summaries, running script code to show data +struct ScriptSummaryFormat : public SummaryFormat +{ + std::string m_function_name; + std::string m_python_script; + + ScriptSummaryFormat(bool casc = false, + bool skipptr = false, + bool skipref = false, + bool nochildren = true, + bool novalue = true, + bool oneliner = false, + std::string fname = "", + std::string pscri = "") : + SummaryFormat(casc,skipptr,skipref,nochildren,novalue,oneliner), + m_function_name(fname), + m_python_script(pscri) + { + } + + std::string + GetFunctionName() + { + return m_function_name; + } + + std::string + GetPythonScript() + { + return m_python_script; + } + + virtual + ~ScriptSummaryFormat() + { + } + + virtual std::string + FormatObject(lldb::ValueObjectSP object) + { + return std::string(ScriptInterpreterPython::CallPythonScriptFunction(m_function_name.c_str(), + object).c_str()); + } + + virtual std::string + GetDescription() + { + StreamString sstr; + sstr.Printf ("%s%s%s\n%s\n", m_cascades ? "" : " (not cascading)", + m_skip_pointers ? " (skip pointers)" : "", + m_skip_references ? " (skip references)" : "", + m_python_script.c_str()); + return sstr.GetString(); + + } + + typedef lldb::SharedPtr<ScriptSummaryFormat>::Type SharedPointer; + +}; + +/*struct SummaryFormat +{ std::string m_format; bool m_dont_show_children; bool m_dont_show_value; @@ -116,32 +373,35 @@ struct SummaryFormat typedef bool(*RegexSummaryCallback)(void*, lldb::RegularExpressionSP, const SummaryFormat::SharedPointer&); }; - -struct ValueFormat + +struct ScriptFormat { - lldb::Format m_format; + std::string m_function_name; + std::string m_python_script; bool m_cascades; bool m_skip_references; bool m_skip_pointers; - ValueFormat (lldb::Format f = lldb::eFormatInvalid, - bool c = false, - bool skipptr = false, - bool skipref = false) : - m_format (f), + ScriptFormat (std::string n, + std::string s = "", + bool c = false, + bool skipptr = false, + bool skipref = false) : + m_function_name (n), + m_python_script(s), m_cascades (c), m_skip_references(skipref), m_skip_pointers(skipptr) { } - typedef lldb::SharedPtr<ValueFormat>::Type SharedPointer; - typedef bool(*ValueCallback)(void*, const char*, const ValueFormat::SharedPointer&); + typedef lldb::SharedPtr<ScriptFormat>::Type SharedPointer; + typedef bool(*ScriptCallback)(void*, const char*, const ScriptFormat::SharedPointer&); - ~ValueFormat() + ~ScriptFormat() { } -}; +};*/ template<typename KeyType, typename ValueType> class FormatNavigator; @@ -457,11 +717,13 @@ private: typedef FormatNavigator<const char*, ValueFormat> ValueNavigator; typedef FormatNavigator<const char*, SummaryFormat> SummaryNavigator; typedef FormatNavigator<lldb::RegularExpressionSP, SummaryFormat> RegexSummaryNavigator; + typedef FormatNavigator<const char*, SummaryFormat> ScriptNavigator; typedef ValueNavigator::MapType ValueMap; typedef SummaryNavigator::MapType SummaryMap; typedef RegexSummaryNavigator::MapType RegexSummaryMap; typedef FormatMap<const char*, SummaryFormat> NamedSummariesMap; + typedef ScriptNavigator::MapType ScriptMap; ValueNavigator m_value_nav; SummaryNavigator m_summary_nav; @@ -469,6 +731,8 @@ private: NamedSummariesMap m_named_summaries_map; + ScriptNavigator m_script_nav; + uint32_t m_last_revision; public: @@ -478,6 +742,7 @@ public: m_summary_nav(this), m_regex_summary_nav(this), m_named_summaries_map(this), + m_script_nav(this), m_last_revision(0) { } @@ -487,6 +752,7 @@ public: SummaryNavigator& Summary() { return m_summary_nav; } RegexSummaryNavigator& RegexSummary() { return m_regex_summary_nav; } NamedSummariesMap& NamedSummary() { return m_named_summaries_map; } + ScriptNavigator& Script() { return m_script_nav; } static bool GetFormatFromCString (const char *format_cstr, diff --git a/lldb/include/lldb/Core/InputReader.h b/lldb/include/lldb/Core/InputReader.h index c1658a296cf..e1cc6aa2c08 100644 --- a/lldb/include/lldb/Core/InputReader.h +++ b/lldb/include/lldb/Core/InputReader.h @@ -12,7 +12,7 @@ #include "lldb/lldb-public.h" #include "lldb/lldb-enumerations.h" -#include "lldb/Core/Debugger.h" +#include "lldb/Core/Error.h" #include "lldb/Host/Predicate.h" @@ -27,6 +27,31 @@ public: lldb::InputReaderAction notification, const char *bytes, size_t bytes_len); + + struct HandlerData + { + InputReader& reader; + const char *bytes; + size_t bytes_len; + void* baton; + + HandlerData(InputReader& r, + const char* b, + size_t l, + void* t) : + reader(r), + bytes(b), + bytes_len(l), + baton(t) + { + } + + lldb::StreamSP + GetOutStream(); + + bool + GetBatchMode(); + }; InputReader (Debugger &debugger); @@ -41,6 +66,41 @@ public: const char *prompt, bool echo); + virtual Error Initialize(void* baton, + lldb::InputReaderGranularity token_size = lldb::eInputReaderGranularityLine, + const char* end_token = "DONE", + const char *prompt = "> ", + bool echo = true) + { + return Error("unimplemented"); + } + + // to use these handlers instead of the Callback function, you must subclass + // InputReaderEZ, and redefine the handlers for the events you care about + virtual void + ActivateHandler(HandlerData&) {} + + virtual void + DeactivateHandler(HandlerData&) {} + + virtual void + ReactivateHandler(HandlerData&) {} + + virtual void + AsynchronousOutputWrittenHandler(HandlerData&) {} + + virtual void + GotTokenHandler(HandlerData&) {} + + virtual void + InterruptHandler(HandlerData&) {} + + virtual void + EOFHandler(HandlerData&) {} + + virtual void + DoneHandler(HandlerData&) {} + bool IsDone () const { diff --git a/lldb/include/lldb/Core/InputReaderEZ.h b/lldb/include/lldb/Core/InputReaderEZ.h new file mode 100644 index 00000000000..95f6af9fc95 --- /dev/null +++ b/lldb/include/lldb/Core/InputReaderEZ.h @@ -0,0 +1,81 @@ +//===-- InputReaderEZ.h -----------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_InputReaderEZ_h_ +#define liblldb_InputReaderEZ_h_ + +#include "lldb/lldb-public.h" +#include "lldb/lldb-enumerations.h" +#include "lldb/Core/Debugger.h" +#include "lldb/Core/InputReader.h" +#include "lldb/Host/Predicate.h" + + +namespace lldb_private { + +class InputReaderEZ : public InputReader +{ + +private: + + static size_t Callback_Impl(void *baton, + InputReader &reader, + lldb::InputReaderAction notification, + const char *bytes, + size_t bytes_len); +public: + + InputReaderEZ (Debugger &debugger) : + InputReader(debugger) + {} + + virtual + ~InputReaderEZ (); + + virtual Error Initialize(void* baton, + lldb::InputReaderGranularity token_size = lldb::eInputReaderGranularityLine, + const char* end_token = "DONE", + const char *prompt = "> ", + bool echo = true); + + virtual void + ActivateHandler(HandlerData&) {} + + virtual void + DeactivateHandler(HandlerData&) {} + + virtual void + ReactivateHandler(HandlerData&) {} + + virtual void + AsynchronousOutputWrittenHandler(HandlerData&) {} + + virtual void + GotTokenHandler(HandlerData&) {} + + virtual void + InterruptHandler(HandlerData&) {} + + virtual void + EOFHandler(HandlerData&) {} + + virtual void + DoneHandler(HandlerData&) {} + +protected: + friend class Debugger; + +private: + DISALLOW_COPY_AND_ASSIGN (InputReaderEZ); + +}; + +} // namespace lldb_private + +#endif // #ifndef liblldb_InputReaderEZ_h_ diff --git a/lldb/include/lldb/Core/StringList.h b/lldb/include/lldb/Core/StringList.h index b080919e87d..c4edb82ba8c 100644 --- a/lldb/include/lldb/Core/StringList.h +++ b/lldb/include/lldb/Core/StringList.h @@ -68,7 +68,17 @@ public: size_t SplitIntoLines (const char *lines, size_t len); + + std::string + CopyList(const char* item_preamble = NULL, + const char* items_sep = "\n"); + + StringList& + operator << (const char* str); + StringList& + operator << (StringList strings); + private: STLStringArray m_strings; diff --git a/lldb/include/lldb/Core/ValueObject.h b/lldb/include/lldb/Core/ValueObject.h index 87f41d90371..d7e39deb5b8 100644 --- a/lldb/include/lldb/Core/ValueObject.h +++ b/lldb/include/lldb/Core/ValueObject.h @@ -27,6 +27,7 @@ #include "lldb/Target/ExecutionContext.h" #include "lldb/Target/ExecutionContextScope.h" #include "lldb/Target/StackID.h" +#include "lldb/Utility/PriorityPointerPair.h" #include "lldb/Utility/SharedCluster.h" namespace lldb_private { @@ -75,7 +76,8 @@ public: { eDisplayValue = 1, eDisplaySummary, - eDisplayLanguageSpecific + eDisplayLanguageSpecific, + eDisplayLocation }; enum ExpressionPathScanEndReason @@ -731,8 +733,8 @@ protected: lldb::Format m_format; uint32_t m_last_format_mgr_revision; lldb::SummaryFormatSP m_last_summary_format; - lldb::ValueFormatSP m_last_value_format; lldb::SummaryFormatSP m_forced_summary_format; + lldb::ValueFormatSP m_last_value_format; lldb::user_id_t m_user_id_of_forced_summary; bool m_value_is_valid:1, m_value_did_change:1, @@ -802,6 +804,9 @@ protected: void SetValueIsValid (bool valid); + + void + ClearUserVisibleData(); public: lldb::addr_t diff --git a/lldb/include/lldb/Interpreter/ScriptInterpreter.h b/lldb/include/lldb/Interpreter/ScriptInterpreter.h index 438222c7456..38ac00eaad2 100644 --- a/lldb/include/lldb/Interpreter/ScriptInterpreter.h +++ b/lldb/include/lldb/Interpreter/ScriptInterpreter.h @@ -26,6 +26,13 @@ public: const char *session_dictionary_name, const lldb::StackFrameSP& frame_sp, const lldb::BreakpointLocationSP &bp_loc_sp); + + typedef + + typedef std::string (*SWIGPythonTypeScriptCallbackFunction) (const char *python_function_name, + const char *session_dictionary_name, + const lldb::ValueObjectSP& valobj_sp); + typedef enum { eCharPtr, @@ -77,6 +84,25 @@ public: { return false; } + + virtual bool + GenerateTypeScriptFunction (StringList &input, StringList &output) + { + return false; + } + + // use this if the function code is just a one-liner script + virtual bool + GenerateTypeScriptFunction (const char* oneliner, StringList &output) + { + return false; + } + + virtual bool + GenerateFunction(std::string& signature, StringList &input, StringList &output) + { + return false; + } virtual void CollectDataForBreakpointCommandCallback (BreakpointOptions *bp_options, @@ -104,7 +130,8 @@ public: static void InitializeInterpreter (SWIGInitCallback python_swig_init_callback, - SWIGBreakpointCallbackFunction python_swig_breakpoint_callback); + SWIGBreakpointCallbackFunction python_swig_breakpoint_callback, + SWIGPythonTypeScriptCallbackFunction python_swig_typescript_callback); static void TerminateInterpreter (); diff --git a/lldb/include/lldb/Interpreter/ScriptInterpreterPython.h b/lldb/include/lldb/Interpreter/ScriptInterpreterPython.h index 4b1c38d5cdc..5d33e7953b7 100644 --- a/lldb/include/lldb/Interpreter/ScriptInterpreterPython.h +++ b/lldb/include/lldb/Interpreter/ScriptInterpreterPython.h @@ -50,6 +50,16 @@ public: ExportFunctionDefinitionToInterpreter (StringList &function_def); bool + GenerateTypeScriptFunction (StringList &input, StringList &output); + + // use this if the function code is just a one-liner script + bool + GenerateTypeScriptFunction (const char* oneliner, StringList &output); + + bool + GenerateFunction(std::string& signature, StringList &input, StringList &output); + + bool GenerateBreakpointCommandCallbackData (StringList &input, StringList &output); static size_t @@ -64,6 +74,10 @@ public: StoppointCallbackContext *context, lldb::user_id_t break_id, lldb::user_id_t break_loc_id); + + static std::string + CallPythonScriptFunction (const char *python_function_name, + lldb::ValueObjectSP valobj); void CollectDataForBreakpointCommandCallback (BreakpointOptions *bp_options, @@ -88,7 +102,8 @@ public: static void InitializeInterpreter (SWIGInitCallback python_swig_init_callback, - SWIGBreakpointCallbackFunction python_swig_breakpoint_callback); + SWIGBreakpointCallbackFunction python_swig_breakpoint_callback, + SWIGPythonTypeScriptCallbackFunction python_swig_typescript_callback); protected: diff --git a/lldb/include/lldb/Utility/PriorityPointerPair.h b/lldb/include/lldb/Utility/PriorityPointerPair.h new file mode 100644 index 00000000000..949173d302e --- /dev/null +++ b/lldb/include/lldb/Utility/PriorityPointerPair.h @@ -0,0 +1,150 @@ +//===-- PriorityPointerPair.h ----------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_PriorityPointerPair_h_ +#define liblldb_PriorityPointerPair_h_ + +#include "lldb/lldb-public.h" +#include "lldb/Utility/SharingPtr.h" + +namespace lldb_utility { + +//---------------------------------------------------------------------- +// A prioritized pair of SharedPtr<T>. One of the two pointers is high +// priority, the other is low priority. +// The Get() method always returns high, if *high != NULL, +// otherwise, low is returned (even if *low == NULL) +//---------------------------------------------------------------------- + +template<typename T> +class PriorityPointerPair +{ +public: + + typedef T& reference_type; + typedef T* pointer_type; + + typedef typename lldb::SharedPtr<T>::Type T_SP; + + PriorityPointerPair() : + m_high(), + m_low() + {} + + PriorityPointerPair(pointer_type high, + pointer_type low) : + m_high(high), + m_low(low) + {} + + PriorityPointerPair(pointer_type low) : + m_high(), + m_low(low) + {} + + PriorityPointerPair(T_SP& high, + T_SP& low) : + m_high(high), + m_low(low) + {} + + PriorityPointerPair(T_SP& low) : + m_high(), + m_low(low) + {} + + void + SwapLow(pointer_type l) + { + m_low.swap(l); + } + + void + SwapHigh(pointer_type h) + { + m_high.swap(h); + } + + void + SwapLow(T_SP l) + { + m_low.swap(l); + } + + void + SwapHigh(T_SP h) + { + m_high.swap(h); + } + + T_SP + GetLow() + { + return m_low; + } + + T_SP + GetHigh() + { + return m_high; + } + + T_SP + Get() + { + if (m_high.get()) + return m_high; + return m_low; + } + + void + ResetHigh() + { + m_high.reset(); + } + + void + ResetLow() + { + m_low.reset(); + } + + void + Reset() + { + ResetLow(); + ResetHigh(); + } + + reference_type + operator*() const + { + return Get().operator*(); + } + + pointer_type + operator->() const + { + return Get().operator->(); + } + + ~PriorityPointerPair(); + +private: + + T_SP m_high; + T_SP m_low; + + DISALLOW_COPY_AND_ASSIGN (PriorityPointerPair); + +}; + +} // namespace lldb_utility + +#endif // #ifndef liblldb_PriorityPointerPair_h_ diff --git a/lldb/include/lldb/Utility/RefCounter.h b/lldb/include/lldb/Utility/RefCounter.h index 7c3e341537e..6daed5498eb 100644 --- a/lldb/include/lldb/Utility/RefCounter.h +++ b/lldb/include/lldb/Utility/RefCounter.h @@ -20,8 +20,6 @@ namespace lldb_utility { // RefCounter ref(ptr); // (of course, the pointer is a shared resource, and must be accessible to // everyone who needs it). Synchronization is handled by RefCounter itself -// To check if more than 1 RefCounter is attached to the same value, you can -// either call shared(), or simply cast ref to bool // The counter is decreased each time a RefCounter to it goes out of scope //---------------------------------------------------------------------- class RefCounter diff --git a/lldb/include/lldb/lldb-forward-rtti.h b/lldb/include/lldb/lldb-forward-rtti.h index b5a02d6d9c0..858e521ebd9 100644 --- a/lldb/include/lldb/lldb-forward-rtti.h +++ b/lldb/include/lldb/lldb-forward-rtti.h @@ -56,11 +56,13 @@ namespace lldb { typedef SharedPtr<lldb_private::RegularExpression>::Type RegularExpressionSP; typedef SharedPtr<lldb_private::Section>::Type SectionSP; typedef SharedPtr<lldb_private::SearchFilter>::Type SearchFilterSP; + typedef SharedPtr<lldb_private::ScriptSummaryFormat>::Type ScriptFormatSP; typedef SharedPtr<lldb_private::StackFrame>::Type StackFrameSP; typedef SharedPtr<lldb_private::StackFrameList>::Type StackFrameListSP; typedef SharedPtr<lldb_private::StopInfo>::Type StopInfoSP; typedef SharedPtr<lldb_private::StoppointLocation>::Type StoppointLocationSP; typedef SharedPtr<lldb_private::Stream>::Type StreamSP; + typedef SharedPtr<lldb_private::StringSummaryFormat>::Type StringSummaryFormatSP; typedef SharedPtr<lldb_private::SummaryFormat>::Type SummaryFormatSP; typedef SharedPtr<lldb_private::SymbolFile>::Type SymbolFileSP; typedef SharedPtr<lldb_private::SymbolContextSpecifier>::Type SymbolContextSpecifierSP; diff --git a/lldb/include/lldb/lldb-forward.h b/lldb/include/lldb/lldb-forward.h index 4b3a97fc4d1..9d616d19cc6 100644 --- a/lldb/include/lldb/lldb-forward.h +++ b/lldb/include/lldb/lldb-forward.h @@ -114,6 +114,7 @@ class RegisterLocationList; class RegisterValue; class RegularExpression; class Scalar; +class ScriptSummaryFormat; class ScriptInterpreter; class ScriptInterpreterPython; class SearchFilter; @@ -131,6 +132,7 @@ class Stream; class StreamFile; class StreamString; class StringList; +class StringSummaryFormat; class SummaryFormat; class Symbol; class SymbolContext; diff --git a/lldb/lldb.xcodeproj/project.pbxproj b/lldb/lldb.xcodeproj/project.pbxproj index 41882a2fca6..47345bfc52c 100644 --- a/lldb/lldb.xcodeproj/project.pbxproj +++ b/lldb/lldb.xcodeproj/project.pbxproj @@ -402,6 +402,7 @@ 4CCA645613B40B82003BDF98 /* AppleObjCTrampolineHandler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CCA644813B40B82003BDF98 /* AppleObjCTrampolineHandler.cpp */; }; 4CCA645813B40B82003BDF98 /* AppleThreadPlanStepThroughObjCTrampoline.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CCA644A13B40B82003BDF98 /* AppleThreadPlanStepThroughObjCTrampoline.cpp */; }; 4CD0BD0F134BFADF00CB44D4 /* ValueObjectDynamicValue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CD0BD0E134BFADF00CB44D4 /* ValueObjectDynamicValue.cpp */; }; + 94031A9E13CF486700DCFF3C /* InputReaderEZ.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 94031A9D13CF486600DCFF3C /* InputReaderEZ.cpp */; }; 9415F61813B2C0EF00A52B36 /* FormatManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9415F61713B2C0EF00A52B36 /* FormatManager.cpp */; }; 94611EB213CCA4A4003A22AF /* RefCounter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 94611EB113CCA4A4003A22AF /* RefCounter.cpp */; }; 9463D4CD13B1798800C230D4 /* CommandObjectType.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9463D4CC13B1798800C230D4 /* CommandObjectType.cpp */; }; @@ -631,8 +632,8 @@ 261B5A5311C3F2AD00AABD0A /* SharingPtr.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SharingPtr.h; path = include/lldb/Utility/SharingPtr.h; sourceTree = "<group>"; }; 26217930133BC8640083B112 /* lldb-private-types.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "lldb-private-types.h"; path = "include/lldb/lldb-private-types.h"; sourceTree = "<group>"; }; 26217932133BCB850083B112 /* lldb-private-enumerations.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "lldb-private-enumerations.h"; path = "include/lldb/lldb-private-enumerations.h"; sourceTree = "<group>"; }; - 263664921140A4930075843B /* Debugger.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Debugger.cpp; path = source/Core/Debugger.cpp; sourceTree = "<group>"; }; - 263664941140A4C10075843B /* Debugger.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Debugger.h; path = include/lldb/Core/Debugger.h; sourceTree = "<group>"; }; + 263664921140A4930075843B /* Debugger.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; name = Debugger.cpp; path = source/Core/Debugger.cpp; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; + 263664941140A4C10075843B /* Debugger.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; name = Debugger.h; path = include/lldb/Core/Debugger.h; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; }; 26368A3B126B697600E8659F /* darwin-debug.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "darwin-debug.cpp"; path = "tools/darwin-debug/darwin-debug.cpp"; sourceTree = "<group>"; }; 263E949D13661AE400E7D1CE /* UnwindAssembly-x86.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = "UnwindAssembly-x86.cpp"; sourceTree = "<group>"; }; 263E949E13661AE400E7D1CE /* UnwindAssembly-x86.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "UnwindAssembly-x86.h"; sourceTree = "<group>"; }; @@ -677,7 +678,7 @@ 266F5CBB12FC846200DFCE33 /* Config.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Config.h; path = include/lldb/Host/Config.h; sourceTree = "<group>"; }; 2671A0CD134825F6003A87BB /* ConnectionMachPort.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ConnectionMachPort.h; path = include/lldb/Core/ConnectionMachPort.h; sourceTree = "<group>"; }; 2671A0CF13482601003A87BB /* ConnectionMachPort.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ConnectionMachPort.cpp; path = source/Core/ConnectionMachPort.cpp; sourceTree = "<group>"; }; - 2672D8461189055500FF4019 /* CommandObjectFrame.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CommandObjectFrame.cpp; path = source/Commands/CommandObjectFrame.cpp; sourceTree = "<group>"; }; + 2672D8461189055500FF4019 /* CommandObjectFrame.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; name = CommandObjectFrame.cpp; path = source/Commands/CommandObjectFrame.cpp; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; 2672D8471189055500FF4019 /* CommandObjectFrame.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CommandObjectFrame.h; path = source/Commands/CommandObjectFrame.h; sourceTree = "<group>"; }; 26744EED1338317700EF765A /* GDBRemoteCommunicationClient.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GDBRemoteCommunicationClient.cpp; sourceTree = "<group>"; }; 26744EEE1338317700EF765A /* GDBRemoteCommunicationClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GDBRemoteCommunicationClient.h; sourceTree = "<group>"; }; @@ -724,7 +725,7 @@ 26A0604811A5D03C00F75969 /* Baton.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Baton.cpp; path = source/Core/Baton.cpp; sourceTree = "<group>"; }; 26A3B4AC1181454800381BC2 /* ObjectContainerBSDArchive.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ObjectContainerBSDArchive.cpp; sourceTree = "<group>"; }; 26A3B4AD1181454800381BC2 /* ObjectContainerBSDArchive.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ObjectContainerBSDArchive.h; sourceTree = "<group>"; }; - 26A4EEB511682AAC007A372A /* LLDBWrapPython.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LLDBWrapPython.cpp; path = source/LLDBWrapPython.cpp; sourceTree = "<group>"; }; + 26A4EEB511682AAC007A372A /* LLDBWrapPython.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; name = LLDBWrapPython.cpp; path = source/LLDBWrapPython.cpp; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; 26A7A034135E6E4200FB369E /* NamedOptionValue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = NamedOptionValue.cpp; path = source/Interpreter/NamedOptionValue.cpp; sourceTree = "<group>"; }; 26A7A036135E6E5300FB369E /* NamedOptionValue.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NamedOptionValue.h; path = include/lldb/Interpreter/NamedOptionValue.h; sourceTree = "<group>"; }; 26B167A41123BF5500DC7B4F /* ThreadSafeValue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ThreadSafeValue.h; path = include/lldb/Core/ThreadSafeValue.h; sourceTree = "<group>"; }; @@ -830,7 +831,7 @@ 26BC7D7E10F1B77400F91463 /* Timer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Timer.h; path = include/lldb/Core/Timer.h; sourceTree = "<group>"; }; 26BC7D8010F1B77400F91463 /* UserID.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = UserID.h; path = include/lldb/Core/UserID.h; sourceTree = "<group>"; }; 26BC7D8110F1B77400F91463 /* Value.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Value.h; path = include/lldb/Core/Value.h; sourceTree = "<group>"; }; - 26BC7D8210F1B77400F91463 /* ValueObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ValueObject.h; path = include/lldb/Core/ValueObject.h; sourceTree = "<group>"; }; + 26BC7D8210F1B77400F91463 /* ValueObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; name = ValueObject.h; path = include/lldb/Core/ValueObject.h; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; }; 26BC7D8310F1B77400F91463 /* ValueObjectChild.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ValueObjectChild.h; path = include/lldb/Core/ValueObjectChild.h; sourceTree = "<group>"; }; 26BC7D8410F1B77400F91463 /* ValueObjectList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ValueObjectList.h; path = include/lldb/Core/ValueObjectList.h; sourceTree = "<group>"; }; 26BC7D8510F1B77400F91463 /* ValueObjectVariable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ValueObjectVariable.h; path = include/lldb/Core/ValueObjectVariable.h; sourceTree = "<group>"; }; @@ -928,7 +929,7 @@ 26BC7E9610F1B85900F91463 /* Timer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Timer.cpp; path = source/Core/Timer.cpp; sourceTree = "<group>"; }; 26BC7E9810F1B85900F91463 /* UserID.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = UserID.cpp; path = source/Core/UserID.cpp; sourceTree = "<group>"; }; 26BC7E9910F1B85900F91463 /* Value.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Value.cpp; path = source/Core/Value.cpp; sourceTree = "<group>"; }; - 26BC7E9A10F1B85900F91463 /* ValueObject.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ValueObject.cpp; path = source/Core/ValueObject.cpp; sourceTree = "<group>"; }; + 26BC7E9A10F1B85900F91463 /* ValueObject.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; name = ValueObject.cpp; path = source/Core/ValueObject.cpp; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; 26BC7E9B10F1B85900F91463 /* ValueObjectChild.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ValueObjectChild.cpp; path = source/Core/ValueObjectChild.cpp; sourceTree = "<group>"; }; 26BC7E9C10F1B85900F91463 /* ValueObjectList.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ValueObjectList.cpp; path = source/Core/ValueObjectList.cpp; sourceTree = "<group>"; }; 26BC7E9D10F1B85900F91463 /* ValueObjectVariable.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ValueObjectVariable.cpp; path = source/Core/ValueObjectVariable.cpp; sourceTree = "<group>"; }; @@ -1019,8 +1020,8 @@ 26DB3E141379E7AD0080DC73 /* ABISysV_x86_64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ABISysV_x86_64.h; sourceTree = "<group>"; }; 26DC6A101337FE6900FF7998 /* lldb-platform */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "lldb-platform"; sourceTree = BUILT_PRODUCTS_DIR; }; 26DC6A1C1337FECA00FF7998 /* lldb-platform.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "lldb-platform.cpp"; path = "tools/lldb-platform/lldb-platform.cpp"; sourceTree = "<group>"; }; - 26DE1E6911616C2E00A093E2 /* lldb-forward-rtti.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "lldb-forward-rtti.h"; path = "include/lldb/lldb-forward-rtti.h"; sourceTree = "<group>"; }; - 26DE1E6A11616C2E00A093E2 /* lldb-forward.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "lldb-forward.h"; path = "include/lldb/lldb-forward.h"; sourceTree = "<group>"; }; + 26DE1E6911616C2E00A093E2 /* lldb-forward-rtti.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; name = "lldb-forward-rtti.h"; path = "include/lldb/lldb-forward-rtti.h"; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; }; + 26DE1E6A11616C2E00A093E2 /* lldb-forward.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; name = "lldb-forward.h"; path = "include/lldb/lldb-forward.h"; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; }; 26DE204011618AB900A093E2 /* SBSymbolContext.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SBSymbolContext.h; path = include/lldb/API/SBSymbolContext.h; sourceTree = "<group>"; }; 26DE204211618ACA00A093E2 /* SBAddress.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SBAddress.h; path = include/lldb/API/SBAddress.h; sourceTree = "<group>"; }; 26DE204411618ADA00A093E2 /* SBAddress.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SBAddress.cpp; path = source/API/SBAddress.cpp; sourceTree = "<group>"; }; @@ -1169,11 +1170,14 @@ 69A01E1E1236C5D400C660B5 /* Mutex.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Mutex.cpp; sourceTree = "<group>"; }; 69A01E1F1236C5D400C660B5 /* Symbols.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Symbols.cpp; sourceTree = "<group>"; }; 69A01E201236C5D400C660B5 /* TimeValue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TimeValue.cpp; sourceTree = "<group>"; }; - 9415F61613B2C0DC00A52B36 /* FormatManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = FormatManager.h; path = include/lldb/Core/FormatManager.h; sourceTree = "<group>"; }; - 9415F61713B2C0EF00A52B36 /* FormatManager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = FormatManager.cpp; path = source/Core/FormatManager.cpp; sourceTree = "<group>"; }; + 94031A9B13CF484600DCFF3C /* InputReaderEZ.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = InputReaderEZ.h; path = include/lldb/Core/InputReaderEZ.h; sourceTree = "<group>"; }; + 94031A9D13CF486600DCFF3C /* InputReaderEZ.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = InputReaderEZ.cpp; path = source/Core/InputReaderEZ.cpp; sourceTree = "<group>"; }; + 94031A9F13CF5B3D00DCFF3C /* PriorityPointerPair.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = PriorityPointerPair.h; path = include/lldb/Utility/PriorityPointerPair.h; sourceTree = "<group>"; }; + 9415F61613B2C0DC00A52B36 /* FormatManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; lineEnding = 0; name = FormatManager.h; path = include/lldb/Core/FormatManager.h; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; }; + 9415F61713B2C0EF00A52B36 /* FormatManager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; name = FormatManager.cpp; path = source/Core/FormatManager.cpp; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; 94611EAF13CCA363003A22AF /* RefCounter.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = RefCounter.h; path = include/lldb/Utility/RefCounter.h; sourceTree = "<group>"; }; 94611EB113CCA4A4003A22AF /* RefCounter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = RefCounter.cpp; path = source/Utility/RefCounter.cpp; sourceTree = "<group>"; }; - 9463D4CC13B1798800C230D4 /* CommandObjectType.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CommandObjectType.cpp; path = source/Commands/CommandObjectType.cpp; sourceTree = "<group>"; }; + 9463D4CC13B1798800C230D4 /* CommandObjectType.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; name = CommandObjectType.cpp; path = source/Commands/CommandObjectType.cpp; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; 9463D4CE13B179A500C230D4 /* CommandObjectType.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = CommandObjectType.h; path = source/Commands/CommandObjectType.h; sourceTree = "<group>"; }; 9467E65113C3D97600B3B6F3 /* TypeHierarchyNavigator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = TypeHierarchyNavigator.cpp; path = source/Symbol/TypeHierarchyNavigator.cpp; sourceTree = "<group>"; }; 9467E65413C3D98900B3B6F3 /* TypeHierarchyNavigator.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = TypeHierarchyNavigator.h; path = include/lldb/Symbol/TypeHierarchyNavigator.h; sourceTree = "<group>"; }; @@ -1797,6 +1801,7 @@ 2676A093119C93C8008A98EF /* StringExtractorGDBRemote.cpp */, 2682F16B115EDA0D00CCFF99 /* PseudoTerminal.h */, 2682F16A115EDA0D00CCFF99 /* PseudoTerminal.cpp */, + 94031A9F13CF5B3D00DCFF3C /* PriorityPointerPair.h */, ); name = Utility; sourceTree = "<group>"; @@ -1929,6 +1934,8 @@ 26F73061139D8FDB00FD51C7 /* History.cpp */, 9AA69DBB118A029E00D753A0 /* InputReader.h */, 9AA69DB5118A027A00D753A0 /* InputReader.cpp */, + 94031A9B13CF484600DCFF3C /* InputReaderEZ.h */, + 94031A9D13CF486600DCFF3C /* InputReaderEZ.cpp */, 9A9E1F0013980943005AC039 /* InputReaderStack.h */, 9A9E1EFE1398086D005AC039 /* InputReaderStack.cpp */, 26BC7D6510F1B77400F91463 /* IOStreamMacros.h */, @@ -3271,6 +3278,7 @@ 26ED3D6D13C563810017D45E /* OptionGroupVariable.cpp in Sources */, 26F4214413C6515B00E04E5E /* DynamicLoaderMacOSXKernel.cpp in Sources */, 94611EB213CCA4A4003A22AF /* RefCounter.cpp in Sources */, + 94031A9E13CF486700DCFF3C /* InputReaderEZ.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/lldb/scripts/lldb.swig b/lldb/scripts/lldb.swig index 9d9cc2547bf..158004c68d1 100644 --- a/lldb/scripts/lldb.swig +++ b/lldb/scripts/lldb.swig @@ -359,4 +359,128 @@ LLDBSwigPythonBreakpointCallbackFunction return stop_at_breakpoint; } +SWIGEXPORT std::string +LLDBSwigPythonCallTypeScript +( + const char *python_function_name, + const char *session_dictionary_name, + const lldb::ValueObjectSP& valobj_sp +) +{ + lldb::SBValue sb_value (valobj_sp); + + std::string retval = ""; + + PyObject *ValObj_PyObj = SWIG_NewPointerObj((void *) &valobj_sp, SWIGTYPE_p_lldb__SBValue, 0); + + if (ValObj_PyObj == NULL) + return retval; + + if (!python_function_name || !session_dictionary_name) + return retval; + + PyObject *pmodule, *main_dict, *session_dict, *pfunc; + PyObject *pargs, *pvalue; + + pmodule = PyImport_AddModule ("__main__"); + if (pmodule != NULL) + { + main_dict = PyModule_GetDict (pmodule); + if (main_dict != NULL) + { + PyObject *key, *value; + Py_ssize_t pos = 0; + + // Find the current session's dictionary in the main module's dictionary. + + if (PyDict_Check (main_dict)) + + { + session_dict = NULL; + while (PyDict_Next (main_dict, &pos, &key, &value)) + { + // We have stolen references to the key and value objects in the dictionary; we need to increment + // them now so that Python's garbage collector doesn't collect them out from under us. + Py_INCREF (key); + Py_INCREF (value); + if (strcmp (PyString_AsString (key), session_dictionary_name) == 0) + { + session_dict = value; + break; + } + } + } + + if (!session_dict || !PyDict_Check (session_dict)) + return retval; + + // Find the function we need to call in the current session's dictionary. + + pos = 0; + pfunc = NULL; + while (PyDict_Next (session_dict, &pos, &key, &value)) + { + if (PyString_Check (key)) + { + // We have stolen references to the key and value objects in the dictionary; we need to increment + // them now so that Python's garbage collector doesn't collect them out from under us. + Py_INCREF (key); + Py_INCREF (value); + if (strcmp (PyString_AsString (key), python_function_name) == 0) + { + pfunc = value; + break; + } + } + } + + // Set up the arguments and call the function. + + if (pfunc && PyCallable_Check (pfunc)) + { + pargs = PyTuple_New (2); + if (pargs == NULL) + { + if (PyErr_Occurred()) + PyErr_Clear(); + return retval; + } + + PyTuple_SetItem (pargs, 0, ValObj_PyObj); // This "steals" a reference to ValObj_PyObj + PyTuple_SetItem (pargs, 1, session_dict); // This "steals" a reference to session_dict + pvalue = PyObject_CallObject (pfunc, pargs); + Py_DECREF (pargs); + + if (pvalue != NULL) + { + if (pvalue != Py_None) + retval = std::string(PyString_AsString(pvalue)); + else + retval = "None"; + Py_DECREF (pvalue); + } + else if (PyErr_Occurred ()) + { + PyErr_Clear(); + } + Py_INCREF (session_dict); + } + else if (PyErr_Occurred()) + { + PyErr_Clear(); + } + } + else if (PyErr_Occurred()) + { + PyErr_Clear(); + } + } + else if (PyErr_Occurred ()) + { + PyErr_Clear (); + } + return retval; +} + + %} diff --git a/lldb/source/API/SBCommandInterpreter.cpp b/lldb/source/API/SBCommandInterpreter.cpp index 0f1914b6f95..97b93141e7d 100644 --- a/lldb/source/API/SBCommandInterpreter.cpp +++ b/lldb/source/API/SBCommandInterpreter.cpp @@ -314,6 +314,15 @@ LLDBSwigPythonBreakpointCallbackFunction const lldb::BreakpointLocationSP& sb_bp_loc ); +extern "C" std::string +LLDBSwigPythonCallTypeScript +( + const char *python_function_name, + const char *session_dictionary_name, + const lldb::ValueObjectSP& valobj_sp +); + + extern "C" void init_lldb(void); void @@ -324,6 +333,7 @@ SBCommandInterpreter::InitializeSWIG () { g_initialized = true; ScriptInterpreter::InitializeInterpreter (init_lldb, - LLDBSwigPythonBreakpointCallbackFunction); + LLDBSwigPythonBreakpointCallbackFunction, + LLDBSwigPythonCallTypeScript); } } diff --git a/lldb/source/API/SBValue.cpp b/lldb/source/API/SBValue.cpp index e51919cacca..aeabb1740bf 100644 --- a/lldb/source/API/SBValue.cpp +++ b/lldb/source/API/SBValue.cpp @@ -472,6 +472,28 @@ SBValue::GetChildMemberWithName (const char *name, lldb::DynamicValueType use_dy return sb_value; } +lldb::SBValue +SBValue::GetValueForExpressionPath(const char* expr_path) +{ + lldb::ValueObjectSP child_sp; + if (m_opaque_sp) + { + if (m_opaque_sp->GetUpdatePoint().GetTarget()) + { + Mutex::Locker api_locker (m_opaque_sp->GetUpdatePoint().GetTarget()->GetAPIMutex()); + // using default values for all the fancy options, just do it if you can + child_sp = m_opaque_sp->GetValueForExpressionPath(expr_path); + } + } + + SBValue sb_value (child_sp); + + LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); + if (log) + log->Printf ("SBValue(%p)::GetValueForExpressionPath (expr_path=\"%s\") => SBValue(%p)", m_opaque_sp.get(), expr_path, sb_value.get()); + + return sb_value; +} uint32_t SBValue::GetNumChildren () diff --git a/lldb/source/Commands/CommandObjectType.cpp b/lldb/source/Commands/CommandObjectType.cpp index c0ffddb62ae..b1e7c12bf46 100644 --- a/lldb/source/Commands/CommandObjectType.cpp +++ b/lldb/source/Commands/CommandObjectType.cpp @@ -15,8 +15,10 @@ #include "lldb/Core/ConstString.h" #include "lldb/Core/Debugger.h" #include "lldb/Core/FormatManager.h" +#include "lldb/Core/InputReaderEZ.h" #include "lldb/Core/RegularExpression.h" #include "lldb/Core/State.h" +#include "lldb/Core/StringList.h" #include "lldb/Interpreter/CommandInterpreter.h" #include "lldb/Interpreter/CommandObject.h" #include "lldb/Interpreter/CommandReturnObject.h" @@ -416,6 +418,162 @@ CommandObjectTypeFormatList_LoopCallback ( // CommandObjectTypeSummaryAdd //------------------------------------------------------------------------- +class ScriptAddOptions +{ + +public: + + bool m_skip_pointers; + bool m_skip_references; + bool m_cascade; + bool m_callback_is_synchronous; + StringList m_target_types; + StringList m_user_source; + + ScriptAddOptions(bool p, + bool r, + bool c) : + m_skip_pointers(p), + m_skip_references(r), + m_cascade(c), + m_target_types(), + m_user_source() + { + } + + typedef lldb::SharedPtr<ScriptAddOptions>::Type SharedPointer; + +}; + +static const char *g_reader_instructions = "Enter your Python command(s). Type 'DONE' to end."; + +class TypeScriptAddInputReader : public InputReaderEZ +{ +private: + DISALLOW_COPY_AND_ASSIGN (TypeScriptAddInputReader); +public: + TypeScriptAddInputReader(Debugger& debugger) : + InputReaderEZ(debugger) + {} + + virtual + ~TypeScriptAddInputReader() + { + } + + virtual void ActivateHandler(HandlerData& data) + { + StreamSP out_stream = data.reader.GetDebugger().GetAsyncOutputStream(); + bool batch_mode = data.reader.GetDebugger().GetCommandInterpreter().GetBatchCommandMode(); + if (!batch_mode) + { + out_stream->Printf ("%s\n", g_reader_instructions); + if (data.reader.GetPrompt()) + out_stream->Printf ("%s", data.reader.GetPrompt()); + out_stream->Flush(); + } + } + + virtual void ReactivateHandler(HandlerData& data) + { + StreamSP out_stream = data.reader.GetDebugger().GetAsyncOutputStream(); + bool batch_mode = data.reader.GetDebugger().GetCommandInterpreter().GetBatchCommandMode(); + if (data.reader.GetPrompt() && !batch_mode) + { + out_stream->Printf ("%s", data.reader.GetPrompt()); + out_stream->Flush(); + } + } + virtual void GotTokenHandler(HandlerData& data) + { + StreamSP out_stream = data.reader.GetDebugger().GetAsyncOutputStream(); + bool batch_mode = data.reader.GetDebugger().GetCommandInterpreter().GetBatchCommandMode(); + if (data.bytes && data.bytes_len && data.baton) + { + ((ScriptAddOptions*)data.baton)->m_user_source.AppendString(data.bytes, data.bytes_len); + } + if (!data.reader.IsDone() && data.reader.GetPrompt() && !batch_mode) + { + out_stream->Printf ("%s", data.reader.GetPrompt()); + out_stream->Flush(); + } + } + virtual void InterruptHandler(HandlerData& data) + { + StreamSP out_stream = data.reader.GetDebugger().GetAsyncOutputStream(); + bool batch_mode = data.reader.GetDebugger().GetCommandInterpreter().GetBatchCommandMode(); + data.reader.SetIsDone (true); + if (!batch_mode) + { + out_stream->Printf ("Warning: No command attached to breakpoint.\n"); + out_stream->Flush(); + } + } + virtual void EOFHandler(HandlerData& data) + { + data.reader.SetIsDone (true); + } + virtual void DoneHandler(HandlerData& data) + { + StreamSP out_stream = data.reader.GetDebugger().GetAsyncOutputStream(); + ScriptAddOptions *options_ptr = ((ScriptAddOptions*)data.baton); + if (!options_ptr) + { + out_stream->Printf ("Internal error #1: no script attached.\n"); + out_stream->Flush(); + return; + } + + ScriptAddOptions::SharedPointer options(options_ptr); // this will ensure that we get rid of the pointer when going out of scope + + ScriptInterpreter *interpreter = data.reader.GetDebugger().GetCommandInterpreter().GetScriptInterpreter(); + if (!interpreter) + { + out_stream->Printf ("Internal error #2: no script attached.\n"); + out_stream->Flush(); + return; + } + StringList funct_name_sl; + if (!interpreter->GenerateTypeScriptFunction (options->m_user_source, + funct_name_sl)) + { + out_stream->Printf ("Internal error #3: no script attached.\n"); + out_stream->Flush(); + return; + } + if (funct_name_sl.GetSize() == 0) + { + out_stream->Printf ("Internal error #4: no script attached.\n"); + out_stream->Flush(); + return; + } + const char *funct_name = funct_name_sl.GetStringAtIndex(0); + if (!funct_name || !funct_name[0]) + { + out_stream->Printf ("Internal error #5: no script attached.\n"); + out_stream->Flush(); + return; + } + // now I have a valid function name, let's add this as script for every type in the list + + SummaryFormatSP script_format; + script_format.reset(new ScriptSummaryFormat(options->m_cascade, + options->m_skip_pointers, + options->m_skip_references, + true, + true, + false, + std::string(funct_name), + options->m_user_source.CopyList(" "))); + + for (int i = 0; i < options->m_target_types.GetSize(); i++) + { + const char *type_name = options->m_target_types.GetStringAtIndex(i); + Debugger::SummaryFormats::Add(ConstString(type_name), script_format); + } + } +}; + class CommandObjectTypeSummaryAdd : public CommandObject { @@ -471,6 +629,17 @@ private: case 'n': m_name = new ConstString(option_arg); break; + case 's': + m_python_script = std::string(option_arg); + m_is_add_script = true; + break; + case 'F': + m_python_function = std::string(option_arg); + m_is_add_script = true; + break; + case 'P': + m_is_add_script = true; + break; default: error.SetErrorStringWithFormat ("Unrecognized option '%c'.\n", short_option); break; @@ -490,6 +659,9 @@ private: m_skip_pointers = false; m_regex = false; m_name = NULL; + m_python_script = ""; + m_python_function = ""; + m_is_add_script = false; } const OptionDefinition* @@ -513,6 +685,9 @@ private: bool m_regex; std::string m_format_string; ConstString* m_name; + std::string m_python_script; + std::string m_python_function; + bool m_is_add_script; }; CommandOptions m_options; @@ -601,9 +776,170 @@ public: { } + void + CollectPythonScript + ( + ScriptAddOptions *options, + CommandReturnObject &result + ) + { + InputReaderSP reader_sp (new TypeScriptAddInputReader(m_interpreter.GetDebugger())); + if (reader_sp && options) + { + + Error err (reader_sp->Initialize (options)); + if (err.Success()) + { + m_interpreter.GetDebugger().PushInputReader (reader_sp); + result.SetStatus (eReturnStatusSuccessFinishNoResult); + } + else + { + result.AppendError (err.AsCString()); + result.SetStatus (eReturnStatusFailed); + } + } + else + { + result.AppendError("out of memory"); + result.SetStatus (eReturnStatusFailed); + } + + } + bool Execute (Args& command, CommandReturnObject &result) { + if (m_options.m_is_add_script) + return Execute_ScriptSummary(command, result); + else + return Execute_StringSummary(command, result); + } + + bool + Execute_ScriptSummary (Args& command, CommandReturnObject &result) + { + const size_t argc = command.GetArgumentCount(); + + if (argc < 1) + { + result.AppendErrorWithFormat ("%s takes one or more args.\n", m_cmd_name.c_str()); + result.SetStatus(eReturnStatusFailed); + return false; + } + + if (!m_options.m_python_function.empty()) // we have a Python function ready to use + { + ScriptInterpreter *interpreter = m_interpreter.GetScriptInterpreter(); + if (!interpreter) + { + result.AppendError ("Internal error #1N: no script attached.\n"); + result.SetStatus (eReturnStatusFailed); + return false; + } + const char *funct_name = m_options.m_python_function.c_str(); + if (!funct_name || !funct_name[0]) + { + result.AppendError ("Internal error #2N: no script attached.\n"); + result.SetStatus (eReturnStatusFailed); + return false; + } + // now I have a valid function name, let's add this as script for every type in the list + + SummaryFormatSP script_format; + script_format.reset(new ScriptSummaryFormat(m_options.m_cascade, + m_options.m_skip_pointers, + m_options.m_skip_references, + true, + true, + false, + std::string(funct_name), + " " + m_options.m_python_function + "(valobj,dict)")); + + for (int i = 0; i < command.GetArgumentCount(); i++) + { + const char *type_name = command.GetArgumentAtIndex(i); + Debugger::SummaryFormats::Add(ConstString(type_name), script_format); + } + } + else if (m_options.m_python_script.empty()) // use an InputReader to grab Python code from the user + { + ScriptAddOptions *options = new ScriptAddOptions(m_options.m_skip_pointers, + m_options.m_skip_references, + m_options.m_cascade); + + for(int i = 0; i < argc; i++) { + const char* typeA = command.GetArgumentAtIndex(i); + if (typeA && *typeA) + options->m_target_types << typeA; + else + { + result.AppendError("empty typenames not allowed"); + result.SetStatus(eReturnStatusFailed); + return false; + } + } + + CollectPythonScript(options,result); + return result.Succeeded(); + } + else // we have a quick 1-line script, just use it + { + ScriptInterpreter *interpreter = m_interpreter.GetScriptInterpreter(); + if (!interpreter) + { + result.AppendError ("Internal error #1Q: no script attached.\n"); + result.SetStatus (eReturnStatusFailed); + return false; + } + StringList funct_sl; + funct_sl << m_options.m_python_script.c_str(); + StringList funct_name_sl; + if (!interpreter->GenerateTypeScriptFunction (funct_sl, + funct_name_sl)) + { + result.AppendError ("Internal error #2Q: no script attached.\n"); + result.SetStatus (eReturnStatusFailed); + return false; + } + if (funct_name_sl.GetSize() == 0) + { + result.AppendError ("Internal error #3Q: no script attached.\n"); + result.SetStatus (eReturnStatusFailed); + return false; + } + const char *funct_name = funct_name_sl.GetStringAtIndex(0); + if (!funct_name || !funct_name[0]) + { + result.AppendError ("Internal error #4Q: no script attached.\n"); + result.SetStatus (eReturnStatusFailed); + return false; + } + // now I have a valid function name, let's add this as script for every type in the list + + ScriptFormatSP script_format; + script_format.reset(new ScriptSummaryFormat(m_options.m_cascade, + m_options.m_skip_pointers, + m_options.m_skip_references, + true, + true, + false, + std::string(funct_name), + " " + m_options.m_python_script)); + + for (int i = 0; i < command.GetArgumentCount(); i++) + { + const char *type_name = command.GetArgumentAtIndex(i); + Debugger::SummaryFormats::Add(ConstString(type_name), script_format); + } + } + + return result.Succeeded(); + } + + bool + Execute_StringSummary (Args& command, CommandReturnObject &result) + { const size_t argc = command.GetArgumentCount(); if (argc < 1 && !m_options.m_name) @@ -624,11 +960,13 @@ public: Error error; - SummaryFormat::SharedPointer entry(new SummaryFormat(format_cstr,m_options.m_cascade, - m_options.m_no_children,m_options.m_no_value, - m_options.m_one_liner, - m_options.m_skip_pointers, - m_options.m_skip_references)); + SummaryFormat::SharedPointer entry(new StringSummaryFormat(m_options.m_cascade, + m_options.m_skip_pointers, + m_options.m_skip_references, + m_options.m_no_children, + m_options.m_no_value, + m_options.m_one_liner, + format_cstr)); if (error.Fail()) { @@ -698,6 +1036,9 @@ CommandObjectTypeSummaryAdd::CommandOptions::g_option_table[] = { LLDB_OPT_SET_2 , true, "format-string", 'f', required_argument, NULL, 0, eArgTypeSummaryString, "Format string used to display text and object contents."}, { LLDB_OPT_SET_2, false, "expand", 'e', no_argument, NULL, 0, eArgTypeBoolean, "Expand aggregate data types to show children on separate lines."}, { LLDB_OPT_SET_2, false, "name", 'n', required_argument, NULL, 0, eArgTypeName, "A name for this summary string."}, + { LLDB_OPT_SET_3, false, "python-script", 's', required_argument, NULL, 0, eArgTypeName, "Give a one-liner Python script as part of the command."}, + { LLDB_OPT_SET_3, false, "python-function", 'F', required_argument, NULL, 0, eArgTypeName, "Give the name of a Python function to use for this type."}, + { LLDB_OPT_SET_3, false, "input-python", 'P', no_argument, NULL, 0, eArgTypeName, "Input Python code to use for this type manually."}, { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } }; @@ -808,8 +1149,8 @@ public: // CommandObjectTypeSummaryList //------------------------------------------------------------------------- -bool CommandObjectTypeSummaryList_LoopCallback(void* pt2self, const char* type, const SummaryFormat::SharedPointer& entry); -bool CommandObjectTypeRXSummaryList_LoopCallback(void* pt2self, lldb::RegularExpressionSP regex, const SummaryFormat::SharedPointer& entry); +bool CommandObjectTypeSummaryList_LoopCallback(void* pt2self, const char* type, const StringSummaryFormat::SharedPointer& entry); +bool CommandObjectTypeRXSummaryList_LoopCallback(void* pt2self, lldb::RegularExpressionSP regex, const StringSummaryFormat::SharedPointer& entry); class CommandObjectTypeSummaryList; @@ -912,16 +1253,7 @@ private: CommandReturnObject *result) { if (regex == NULL || regex->Execute(type)) - { - result->GetOutputStream().Printf ("%s: `%s`%s%s%s%s%s%s\n", type, - entry->m_format.c_str(), - entry->m_cascades ? "" : " (not cascading)", - entry->m_dont_show_children ? "" : " (show children)", - entry->m_dont_show_value ? " (hide value)" : "", - entry->m_show_members_oneliner ? " (one-line printout)" : "", - entry->m_skip_pointers ? " (skip pointers)" : "", - entry->m_skip_references ? " (skip references)" : ""); - } + result->GetOutputStream().Printf ("%s: %s\n", type, entry->GetDescription().c_str()); return true; } @@ -951,8 +1283,6 @@ CommandObjectTypeRXSummaryList_LoopCallback ( } - - class CommandObjectTypeFormat : public CommandObjectMultiword { public: @@ -983,10 +1313,10 @@ public: "A set of commands for editing variable summary display options", "type summary [<sub-command-options>] ") { - LoadSubCommand ("add", CommandObjectSP (new CommandObjectTypeSummaryAdd (interpreter))); - LoadSubCommand ("clear", CommandObjectSP (new CommandObjectTypeSummaryClear (interpreter))); - LoadSubCommand ("delete", CommandObjectSP (new CommandObjectTypeSummaryDelete (interpreter))); - LoadSubCommand ("list", CommandObjectSP (new CommandObjectTypeSummaryList (interpreter))); + LoadSubCommand ("add", CommandObjectSP (new CommandObjectTypeSummaryAdd (interpreter))); + LoadSubCommand ("clear", CommandObjectSP (new CommandObjectTypeSummaryClear (interpreter))); + LoadSubCommand ("delete", CommandObjectSP (new CommandObjectTypeSummaryDelete (interpreter))); + LoadSubCommand ("list", CommandObjectSP (new CommandObjectTypeSummaryList (interpreter))); } diff --git a/lldb/source/Core/Debugger.cpp b/lldb/source/Core/Debugger.cpp index 2c36dbb8c66..029a1d85b53 100644 --- a/lldb/source/Core/Debugger.cpp +++ b/lldb/source/Core/Debugger.cpp @@ -733,6 +733,8 @@ ScanFormatDescriptor(const char* var_name_begin, // if this is a V, print the value using the default format if (*format_name == 'V') *val_obj_display = ValueObject::eDisplayValue; + if (*format_name == 'L') + *val_obj_display = ValueObject::eDisplayLocation; } // a good custom format tells us to print the value using it else diff --git a/lldb/source/Core/Error.cpp b/lldb/source/Core/Error.cpp index 6e21fe7ee2b..61faca464b7 100644 --- a/lldb/source/Core/Error.cpp +++ b/lldb/source/Core/Error.cpp @@ -51,6 +51,14 @@ Error::Error (const Error &rhs) : { } +Error::Error (const char* err_str): + m_code (0), + m_type (eErrorTypeInvalid), + m_string () +{ + SetErrorString(err_str); +} + //---------------------------------------------------------------------- // Assignment operator //---------------------------------------------------------------------- diff --git a/lldb/source/Core/FormatManager.cpp b/lldb/source/Core/FormatManager.cpp index 040b9cd9ebd..7be3791adbb 100644 --- a/lldb/source/Core/FormatManager.cpp +++ b/lldb/source/Core/FormatManager.cpp @@ -14,6 +14,8 @@ // Other libraries and framework includes // Project includes +#include "lldb/Core/Debugger.h" + using namespace lldb; using namespace lldb_private; @@ -217,3 +219,54 @@ FormatManager::GetSingleItemFormat(lldb::Format vector_format) return lldb::eFormatInvalid; } } + +std::string +StringSummaryFormat::FormatObject(lldb::ValueObjectSP object) +{ + if (!object.get()) + return "NULL"; + + StreamString s; + ExecutionContext exe_ctx; + object->GetExecutionContextScope()->CalculateExecutionContext(exe_ctx); + SymbolContext sc; + if (exe_ctx.frame) + sc = exe_ctx.frame->GetSymbolContext(lldb::eSymbolContextEverything); + + if (m_show_members_oneliner) + { + const uint32_t num_children = object->GetNumChildren(); + if (num_children) + { + s.PutChar('('); + + for (uint32_t idx=0; idx<num_children; ++idx) + { + lldb::ValueObjectSP child_sp(object->GetChildAtIndex(idx, true)); + if (child_sp.get()) + { + if (idx) + s.PutCString(", "); + s.PutCString(child_sp.get()->GetName().AsCString()); + s.PutChar('='); + s.PutCString(child_sp.get()->GetPrintableRepresentation()); + } + } + + s.PutChar(')'); + + return s.GetString(); + } + else + return ""; + + } + else + { + if (Debugger::FormatPrompt(m_format.c_str(), &sc, &exe_ctx, &sc.line_entry.range.GetBaseAddress(), s, NULL, object.get())) + return s.GetString(); + else + return ""; + } +} + diff --git a/lldb/source/Core/InputReader.cpp b/lldb/source/Core/InputReader.cpp index c6e90eb54d7..84cd0a15f84 100644 --- a/lldb/source/Core/InputReader.cpp +++ b/lldb/source/Core/InputReader.cpp @@ -370,3 +370,14 @@ InputReader::GranularityAsCString (lldb::InputReaderGranularity granularity) return unknown_state_string; } +bool +InputReader::HandlerData::GetBatchMode() +{ + return reader.GetDebugger().GetCommandInterpreter().GetBatchCommandMode(); +} + +lldb::StreamSP +InputReader::HandlerData::GetOutStream() +{ + return reader.GetDebugger().GetAsyncOutputStream(); +}
\ No newline at end of file diff --git a/lldb/source/Core/InputReaderEZ.cpp b/lldb/source/Core/InputReaderEZ.cpp new file mode 100644 index 00000000000..839d744a5ac --- /dev/null +++ b/lldb/source/Core/InputReaderEZ.cpp @@ -0,0 +1,80 @@ +//===-- InputReaderEZ.cpp ---------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include <string> + +#include "lldb/Core/InputReaderEZ.h" + +#include "lldb/Core/Debugger.h" +#include "lldb/Interpreter/CommandInterpreter.h" + +using namespace lldb; +using namespace lldb_private; + +size_t +InputReaderEZ::Callback_Impl(void *baton, + InputReader &reader, + lldb::InputReaderAction notification, + const char *bytes, + size_t bytes_len) + +{ + HandlerData hand_data(reader, + bytes, + bytes_len, + baton); + + switch (notification) + { + case eInputReaderActivate: + reader.ActivateHandler(hand_data); + break; + case eInputReaderDeactivate: + reader.DeactivateHandler(hand_data); + break; + case eInputReaderReactivate: + reader.ReactivateHandler(hand_data); + break; + case eInputReaderAsynchronousOutputWritten: + reader.AsynchronousOutputWrittenHandler(hand_data); + break; + case eInputReaderGotToken: + reader.GotTokenHandler(hand_data); + break; + case eInputReaderInterrupt: + reader.InterruptHandler(hand_data); + break; + case eInputReaderEndOfFile: + reader.EOFHandler(hand_data); + break; + case eInputReaderDone: + reader.DoneHandler(hand_data); + break; + } + return bytes_len; +} + +Error +InputReaderEZ::Initialize(void* baton, + lldb::InputReaderGranularity token_size, + const char* end_token, + const char *prompt, + bool echo) +{ + return InputReader::Initialize(Callback_Impl, + baton, + token_size, + end_token, + prompt, + echo); +} + +InputReaderEZ::~InputReaderEZ () +{ +}
\ No newline at end of file diff --git a/lldb/source/Core/StringList.cpp b/lldb/source/Core/StringList.cpp index d3392623083..fbe0cfef157 100644 --- a/lldb/source/Core/StringList.cpp +++ b/lldb/source/Core/StringList.cpp @@ -8,6 +8,8 @@ //===----------------------------------------------------------------------===// #include "lldb/Core/StringList.h" + +#include "lldb/Core/StreamString.h" #include "lldb/Host/FileSpec.h" #include <string> @@ -205,3 +207,33 @@ StringList::RemoveBlankLines () idx++; } } + +std::string +StringList::CopyList(const char* item_preamble, + const char* items_sep) +{ + StreamString strm; + for (int i = 0; i < GetSize(); i++) + { + if (i && items_sep && items_sep[0]) + strm << items_sep; + if (item_preamble) + strm << item_preamble; + strm << GetStringAtIndex(i); + } + return std::string(strm.GetData()); +} + +StringList& +StringList::operator << (const char* str) +{ + AppendString(str); + return *this; +} + +StringList& +StringList::operator << (StringList strings) +{ + AppendList(strings); + return *this; +}
\ No newline at end of file diff --git a/lldb/source/Core/ValueObject.cpp b/lldb/source/Core/ValueObject.cpp index d8e0e0f8ef8..ca0b0aca0c6 100644 --- a/lldb/source/Core/ValueObject.cpp +++ b/lldb/source/Core/ValueObject.cpp @@ -29,6 +29,8 @@ #include "lldb/Host/Endian.h" +#include "lldb/Interpreter/ScriptInterpreterPython.h" + #include "lldb/Symbol/ClangASTType.h" #include "lldb/Symbol/ClangASTContext.h" #include "lldb/Symbol/Type.h" @@ -79,8 +81,8 @@ ValueObject::ValueObject (ValueObject &parent) : m_is_array_item_for_pointer(false), m_is_bitfield_for_scalar(false), m_last_format_mgr_revision(0), - m_last_summary_format(), m_last_value_format(), + m_last_summary_format(), m_forced_summary_format(), m_dump_printable_counter(0) { @@ -118,8 +120,8 @@ ValueObject::ValueObject (ExecutionContextScope *exe_scope) : m_is_array_item_for_pointer(false), m_is_bitfield_for_scalar(false), m_last_format_mgr_revision(0), - m_last_summary_format(), m_last_value_format(), + m_last_summary_format(), m_forced_summary_format(), m_dump_printable_counter(0) { @@ -164,10 +166,9 @@ ValueObject::UpdateValueIfNeeded (bool update_format) m_old_value_str.swap (m_value_str); m_value_str.clear(); } - m_location_str.clear(); - m_summary_str.clear(); - m_object_desc_str.clear(); + ClearUserVisibleData(); + const bool value_was_valid = GetValueIsValid(); SetValueDidChange (false); @@ -204,15 +205,15 @@ ValueObject::UpdateFormatsIfNeeded() if (m_last_format_mgr_revision != Debugger::ValueFormats::GetCurrentRevision()) { if (m_last_summary_format.get()) - m_last_summary_format.reset((SummaryFormat*)NULL); + m_last_summary_format.reset((StringSummaryFormat*)NULL); if (m_last_value_format.get()) m_last_value_format.reset((ValueFormat*)NULL); Debugger::ValueFormats::Get(*this, m_last_value_format); if (!Debugger::SummaryFormats::Get(*this, m_last_summary_format)) Debugger::RegexSummaryFormats::Get(*this, m_last_summary_format); m_last_format_mgr_revision = Debugger::ValueFormats::GetCurrentRevision(); - m_value_str.clear(); - m_summary_str.clear(); + + ClearUserVisibleData(); } } @@ -507,221 +508,177 @@ ValueObject::GetSummaryAsCString () { if (m_summary_str.empty()) { - SummaryFormat* summary_format = GetSummaryFormat().get(); + SummaryFormat *summary_format = GetSummaryFormat().get(); if (summary_format) { - StreamString s; - ExecutionContext exe_ctx; - this->GetExecutionContextScope()->CalculateExecutionContext(exe_ctx); - SymbolContext sc; - if (exe_ctx.frame) - sc = exe_ctx.frame->GetSymbolContext(eSymbolContextEverything); - - if (summary_format->m_show_members_oneliner) - { - const uint32_t num_children = GetNumChildren(); - if (num_children) - { - - s.PutChar('('); - - for (uint32_t idx=0; idx<num_children; ++idx) - { - ValueObjectSP child_sp(GetChildAtIndex(idx, true)); - if (child_sp.get()) - { - if (idx) - s.PutCString(", "); - s.PutCString(child_sp.get()->GetName().AsCString()); - s.PutChar('='); - s.PutCString(child_sp.get()->GetPrintableRepresentation()); - } - } - - s.PutChar(')'); - - m_summary_str.swap(s.GetString()); - return m_summary_str.c_str(); - } - else - return "()"; - - } - else - { - if (Debugger::FormatPrompt(summary_format->m_format.c_str(), &sc, &exe_ctx, &sc.line_entry.range.GetBaseAddress(), s, NULL, this)) - { - m_summary_str.swap(s.GetString()); - return m_summary_str.c_str(); - } - else - return NULL; - } + m_summary_str = summary_format->FormatObject(GetSP()); } - - clang_type_t clang_type = GetClangType(); - - // See if this is a pointer to a C string? - if (clang_type) + else { - StreamString sstr; - clang_type_t elem_or_pointee_clang_type; - const Flags type_flags (ClangASTContext::GetTypeInfo (clang_type, - GetClangAST(), - &elem_or_pointee_clang_type)); - - ExecutionContextScope *exe_scope = GetExecutionContextScope(); - if (exe_scope) + clang_type_t clang_type = GetClangType(); + + // See if this is a pointer to a C string? + if (clang_type) { - if (type_flags.AnySet (ClangASTContext::eTypeIsArray | ClangASTContext::eTypeIsPointer) && - ClangASTContext::IsCharType (elem_or_pointee_clang_type)) + StreamString sstr; + clang_type_t elem_or_pointee_clang_type; + const Flags type_flags (ClangASTContext::GetTypeInfo (clang_type, + GetClangAST(), + &elem_or_pointee_clang_type)); + + ExecutionContextScope *exe_scope = GetExecutionContextScope(); + if (exe_scope) { - Target *target = exe_scope->CalculateTarget(); - if (target != NULL) + if (type_flags.AnySet (ClangASTContext::eTypeIsArray | ClangASTContext::eTypeIsPointer) && + ClangASTContext::IsCharType (elem_or_pointee_clang_type)) { - lldb::addr_t cstr_address = LLDB_INVALID_ADDRESS; - AddressType cstr_address_type = eAddressTypeInvalid; - - size_t cstr_len = 0; - bool capped_data = false; - if (type_flags.Test (ClangASTContext::eTypeIsArray)) + Target *target = exe_scope->CalculateTarget(); + if (target != NULL) { - // We have an array - cstr_len = ClangASTContext::GetArraySize (clang_type); - if (cstr_len > 512) // TODO: make cap a setting + lldb::addr_t cstr_address = LLDB_INVALID_ADDRESS; + AddressType cstr_address_type = eAddressTypeInvalid; + + size_t cstr_len = 0; + bool capped_data = false; + if (type_flags.Test (ClangASTContext::eTypeIsArray)) { + // We have an array cstr_len = ClangASTContext::GetArraySize (clang_type); if (cstr_len > 512) // TODO: make cap a setting { - capped_data = true; - cstr_len = 512; + cstr_len = ClangASTContext::GetArraySize (clang_type); + if (cstr_len > 512) // TODO: make cap a setting + { + capped_data = true; + cstr_len = 512; + } } + cstr_address = GetAddressOf (cstr_address_type, true); } - cstr_address = GetAddressOf (cstr_address_type, true); - } - else - { - // We have a pointer - cstr_address = GetPointerValue (cstr_address_type, true); - } - if (cstr_address != LLDB_INVALID_ADDRESS) - { - Address cstr_so_addr (NULL, cstr_address); - DataExtractor data; - size_t bytes_read = 0; - std::vector<char> data_buffer; - Error error; - bool prefer_file_cache = false; - if (cstr_len > 0) + else { - data_buffer.resize(cstr_len); - data.SetData (&data_buffer.front(), data_buffer.size(), lldb::endian::InlHostByteOrder()); - bytes_read = target->ReadMemory (cstr_so_addr, - prefer_file_cache, - &data_buffer.front(), - cstr_len, - error); - if (bytes_read > 0) - { - sstr << '"'; - data.Dump (&sstr, - 0, // Start offset in "data" - eFormatCharArray, // Print as characters - 1, // Size of item (1 byte for a char!) - bytes_read, // How many bytes to print? - UINT32_MAX, // num per line - LLDB_INVALID_ADDRESS,// base address - 0, // bitfield bit size - 0); // bitfield bit offset - if (capped_data) - sstr << "..."; - sstr << '"'; - } + // We have a pointer + cstr_address = GetPointerValue (cstr_address_type, true); } - else + if (cstr_address != LLDB_INVALID_ADDRESS) { - const size_t k_max_buf_size = 256; - data_buffer.resize (k_max_buf_size + 1); - // NULL terminate in case we don't get the entire C string - data_buffer.back() = '\0'; - - sstr << '"'; - - data.SetData (&data_buffer.front(), data_buffer.size(), endian::InlHostByteOrder()); - while ((bytes_read = target->ReadMemory (cstr_so_addr, - prefer_file_cache, - &data_buffer.front(), - k_max_buf_size, - error)) > 0) + Address cstr_so_addr (NULL, cstr_address); + DataExtractor data; + size_t bytes_read = 0; + std::vector<char> data_buffer; + Error error; + bool prefer_file_cache = false; + if (cstr_len > 0) { - size_t len = strlen(&data_buffer.front()); - if (len == 0) - break; - if (len > bytes_read) - len = bytes_read; - - data.Dump (&sstr, - 0, // Start offset in "data" - eFormatCharArray, // Print as characters - 1, // Size of item (1 byte for a char!) - len, // How many bytes to print? - UINT32_MAX, // num per line - LLDB_INVALID_ADDRESS,// base address - 0, // bitfield bit size - 0); // bitfield bit offset - - if (len < k_max_buf_size) - break; - cstr_so_addr.Slide (k_max_buf_size); + data_buffer.resize(cstr_len); + data.SetData (&data_buffer.front(), data_buffer.size(), lldb::endian::InlHostByteOrder()); + bytes_read = target->ReadMemory (cstr_so_addr, + prefer_file_cache, + &data_buffer.front(), + cstr_len, + error); + if (bytes_read > 0) + { + sstr << '"'; + data.Dump (&sstr, + 0, // Start offset in "data" + eFormatCharArray, // Print as characters + 1, // Size of item (1 byte for a char!) + bytes_read, // How many bytes to print? + UINT32_MAX, // num per line + LLDB_INVALID_ADDRESS,// base address + 0, // bitfield bit size + 0); // bitfield bit offset + if (capped_data) + sstr << "..."; + sstr << '"'; + } + } + else + { + const size_t k_max_buf_size = 256; + data_buffer.resize (k_max_buf_size + 1); + // NULL terminate in case we don't get the entire C string + data_buffer.back() = '\0'; + + sstr << '"'; + + data.SetData (&data_buffer.front(), data_buffer.size(), endian::InlHostByteOrder()); + while ((bytes_read = target->ReadMemory (cstr_so_addr, + prefer_file_cache, + &data_buffer.front(), + k_max_buf_size, + error)) > 0) + { + size_t len = strlen(&data_buffer.front()); + if (len == 0) + break; + if (len > bytes_read) + len = bytes_read; + + data.Dump (&sstr, + 0, // Start offset in "data" + eFormatCharArray, // Print as characters + 1, // Size of item (1 byte for a char!) + len, // How many bytes to print? + UINT32_MAX, // num per line + LLDB_INVALID_ADDRESS,// base address + 0, // bitfield bit size + 0); // bitfield bit offset + + if (len < k_max_buf_size) + break; + cstr_so_addr.Slide (k_max_buf_size); + } + sstr << '"'; } - sstr << '"'; } } + + if (sstr.GetSize() > 0) + m_summary_str.assign (sstr.GetData(), sstr.GetSize()); } - - if (sstr.GetSize() > 0) - m_summary_str.assign (sstr.GetData(), sstr.GetSize()); - } - else if (ClangASTContext::IsFunctionPointerType (clang_type)) - { - AddressType func_ptr_address_type = eAddressTypeInvalid; - lldb::addr_t func_ptr_address = GetPointerValue (func_ptr_address_type, true); - - if (func_ptr_address != 0 && func_ptr_address != LLDB_INVALID_ADDRESS) + else if (ClangASTContext::IsFunctionPointerType (clang_type)) { - switch (func_ptr_address_type) - { - case eAddressTypeInvalid: - case eAddressTypeFile: - break; + AddressType func_ptr_address_type = eAddressTypeInvalid; + lldb::addr_t func_ptr_address = GetPointerValue (func_ptr_address_type, true); - case eAddressTypeLoad: + if (func_ptr_address != 0 && func_ptr_address != LLDB_INVALID_ADDRESS) + { + switch (func_ptr_address_type) { - Address so_addr; - Target *target = exe_scope->CalculateTarget(); - if (target && target->GetSectionLoadList().IsEmpty() == false) + case eAddressTypeInvalid: + case eAddressTypeFile: + break; + + case eAddressTypeLoad: { - if (target->GetSectionLoadList().ResolveLoadAddress(func_ptr_address, so_addr)) + Address so_addr; + Target *target = exe_scope->CalculateTarget(); + if (target && target->GetSectionLoadList().IsEmpty() == false) { - so_addr.Dump (&sstr, - exe_scope, - Address::DumpStyleResolvedDescription, - Address::DumpStyleSectionNameOffset); + if (target->GetSectionLoadList().ResolveLoadAddress(func_ptr_address, so_addr)) + { + so_addr.Dump (&sstr, + exe_scope, + Address::DumpStyleResolvedDescription, + Address::DumpStyleSectionNameOffset); + } } } - } - break; + break; - case eAddressTypeHost: - break; + case eAddressTypeHost: + break; + } + } + if (sstr.GetSize() > 0) + { + m_summary_str.assign (1, '('); + m_summary_str.append (sstr.GetData(), sstr.GetSize()); + m_summary_str.append (1, ')'); } - } - if (sstr.GetSize() > 0) - { - m_summary_str.assign (1, '('); - m_summary_str.append (sstr.GetData(), sstr.GetSize()); - m_summary_str.append (1, ')'); } } } @@ -960,34 +917,35 @@ ValueObject::GetValueAsCString () clang_type_t clang_type = GetClangType (); if (clang_type) { - StreamString sstr; - Format format = GetFormat(); - if (format == eFormatDefault) + if (m_last_value_format) { - if (m_last_value_format) - format = m_last_value_format->m_format; - else - // force the system into using unsigned integers for bitfields - format = (m_is_bitfield_for_scalar ? eFormatUnsigned : - ClangASTType::GetFormat(clang_type)); + m_value_str = m_last_value_format->FormatObject(GetSP()); } - - if (ClangASTType::DumpTypeValue (GetClangAST(), // The clang AST - clang_type, // The clang type to display - &sstr, - format, // Format to display this type with - m_data, // Data to extract from - 0, // Byte offset into "m_data" - GetByteSize(), // Byte size of item in "m_data" - GetBitfieldBitSize(), // Bitfield bit size - GetBitfieldBitOffset())) // Bitfield bit offset - m_value_str.swap(sstr.GetString()); else { - m_error.SetErrorStringWithFormat ("unsufficient data for value (only %u of %u bytes available)", - m_data.GetByteSize(), - GetByteSize()); - m_value_str.clear(); + StreamString sstr; + Format format = GetFormat(); + if (format == eFormatDefault) + format = (m_is_bitfield_for_scalar ? eFormatUnsigned : + ClangASTType::GetFormat(clang_type)); + + if (ClangASTType::DumpTypeValue (GetClangAST(), // The clang AST + clang_type, // The clang type to display + &sstr, + format, // Format to display this type with + m_data, // Data to extract from + 0, // Byte offset into "m_data" + GetByteSize(), // Byte size of item in "m_data" + GetBitfieldBitSize(), // Bitfield bit size + GetBitfieldBitOffset())) // Bitfield bit offset + m_value_str.swap(sstr.GetString()); + else + { + m_error.SetErrorStringWithFormat ("unsufficient data for value (only %u of %u bytes available)", + m_data.GetByteSize(), + GetByteSize()); + m_value_str.clear(); + } } } } @@ -1046,6 +1004,9 @@ ValueObject::GetPrintableRepresentation(ValueObjectRepresentationStyle val_obj_d case eDisplayLanguageSpecific: return_value = GetObjectDescription(); break; + case eDisplayLocation: + return_value = GetLocationAsCString(); + break; } // this code snippet might lead to endless recursion, thus we use a RefCounter here to @@ -3221,3 +3182,12 @@ ValueObject::EvaluationPoint::SetContext (ExecutionContextScope *exe_scope) return needs_update; } + +void +ValueObject::ClearUserVisibleData() +{ + m_location_str.clear(); + m_value_str.clear(); + m_summary_str.clear(); + m_object_desc_str.clear(); +}
\ No newline at end of file diff --git a/lldb/source/Interpreter/ScriptInterpreter.cpp b/lldb/source/Interpreter/ScriptInterpreter.cpp index 7011c2e7f2b..294aeec3517 100644 --- a/lldb/source/Interpreter/ScriptInterpreter.cpp +++ b/lldb/source/Interpreter/ScriptInterpreter.cpp @@ -92,10 +92,12 @@ ScriptInterpreter::LanguageToString (lldb::ScriptLanguage language) void ScriptInterpreter::InitializeInterpreter (SWIGInitCallback python_swig_init_callback, - SWIGBreakpointCallbackFunction python_swig_breakpoint_callback) + SWIGBreakpointCallbackFunction python_swig_breakpoint_callback, + SWIGPythonTypeScriptCallbackFunction python_swig_typescript_callback) { ScriptInterpreterPython::InitializeInterpreter (python_swig_init_callback, - python_swig_breakpoint_callback); + python_swig_breakpoint_callback, + python_swig_typescript_callback); } void diff --git a/lldb/source/Interpreter/ScriptInterpreterPython.cpp b/lldb/source/Interpreter/ScriptInterpreterPython.cpp index 610c019cb33..57a5929fc58 100644 --- a/lldb/source/Interpreter/ScriptInterpreterPython.cpp +++ b/lldb/source/Interpreter/ScriptInterpreterPython.cpp @@ -34,6 +34,7 @@ using namespace lldb_private; static ScriptInterpreter::SWIGInitCallback g_swig_init_callback = NULL; static ScriptInterpreter::SWIGBreakpointCallbackFunction g_swig_breakpoint_callback = NULL; +static ScriptInterpreter::SWIGPythonTypeScriptCallbackFunction g_swig_typescript_callback = NULL; static int @@ -1140,6 +1141,117 @@ ScriptInterpreterPython::ExportFunctionDefinitionToInterpreter (StringList &func return ExecuteMultipleLines (function_def_string.c_str()); } +// TODO move both GenerateTypeScriptFunction and GenerateBreakpointCommandCallbackData to actually +// use this code to generate their functions +bool +ScriptInterpreterPython::GenerateFunction(std::string& signature, StringList &input, StringList &output) +{ + int num_lines = input.GetSize (); + if (num_lines == 0) + return false; + StreamString sstr; + StringList auto_generated_function; + auto_generated_function.AppendString (signature.c_str()); + auto_generated_function.AppendString (" global_dict = globals()"); // Grab the global dictionary + auto_generated_function.AppendString (" new_keys = dict.keys()"); // Make a list of keys in the session dict + auto_generated_function.AppendString (" old_keys = global_dict.keys()"); // Save list of keys in global dict + auto_generated_function.AppendString (" global_dict.update (dict)"); // Add the session dictionary to the + // global dictionary. + + // Wrap everything up inside the function, increasing the indentation. + + for (int i = 0; i < num_lines; ++i) + { + sstr.Clear (); + sstr.Printf (" %s", input.GetStringAtIndex (i)); + auto_generated_function.AppendString (sstr.GetData()); + } + auto_generated_function.AppendString (" for key in new_keys:"); // Iterate over all the keys from session dict + auto_generated_function.AppendString (" dict[key] = global_dict[key]"); // Update session dict values + auto_generated_function.AppendString (" if key not in old_keys:"); // If key was not originally in global dict + auto_generated_function.AppendString (" del global_dict[key]"); // ...then remove key/value from global dict + + // Verify that the results are valid Python. + + if (!ExportFunctionDefinitionToInterpreter (auto_generated_function)) + return false; + + return true; + +} + +// this implementation is identical to GenerateBreakpointCommandCallbackData (apart from the name +// given to generated functions, of course) +bool +ScriptInterpreterPython::GenerateTypeScriptFunction (StringList &user_input, StringList &output) +{ + static int num_created_functions = 0; + user_input.RemoveBlankLines (); + int num_lines = user_input.GetSize (); + StreamString sstr; + + // Check to see if we have any data; if not, just return. + if (user_input.GetSize() == 0) + return false; + + // Take what the user wrote, wrap it all up inside one big auto-generated Python function, passing in the + // ValueObject as parameter to the function. + + sstr.Printf ("lldb_autogen_python_type_print_func_%d", num_created_functions); + ++num_created_functions; + std::string auto_generated_function_name = sstr.GetData(); + + sstr.Clear(); + StringList auto_generated_function; + + // Create the function name & definition string. + + sstr.Printf ("def %s (valobj, dict):", auto_generated_function_name.c_str()); + auto_generated_function.AppendString (sstr.GetData()); + + // Pre-pend code for setting up the session dictionary. + + auto_generated_function.AppendString (" global_dict = globals()"); // Grab the global dictionary + auto_generated_function.AppendString (" new_keys = dict.keys()"); // Make a list of keys in the session dict + auto_generated_function.AppendString (" old_keys = global_dict.keys()"); // Save list of keys in global dict + auto_generated_function.AppendString (" global_dict.update (dict)"); // Add the session dictionary to the + // global dictionary. + + // Wrap everything up inside the function, increasing the indentation. + + for (int i = 0; i < num_lines; ++i) + { + sstr.Clear (); + sstr.Printf (" %s", user_input.GetStringAtIndex (i)); + auto_generated_function.AppendString (sstr.GetData()); + } + + // Append code to clean up the global dictionary and update the session dictionary (all updates in the function + // got written to the values in the global dictionary, not the session dictionary). + + auto_generated_function.AppendString (" for key in new_keys:"); // Iterate over all the keys from session dict + auto_generated_function.AppendString (" dict[key] = global_dict[key]"); // Update session dict values + auto_generated_function.AppendString (" if key not in old_keys:"); // If key was not originally in global dict + auto_generated_function.AppendString (" del global_dict[key]"); // ...then remove key/value from global dict + + // Verify that the results are valid Python. + + if (!ExportFunctionDefinitionToInterpreter (auto_generated_function)) + return false; + + // Store the name of the auto-generated function to be called. + + output.AppendString (auto_generated_function_name.c_str()); + return true; +} + +bool +ScriptInterpreterPython::GenerateTypeScriptFunction (const char* oneliner, StringList &output) +{ + StringList input(oneliner); + return GenerateTypeScriptFunction(input, output); +} + bool ScriptInterpreterPython::GenerateBreakpointCommandCallbackData (StringList &user_input, StringList &callback_data) { @@ -1206,6 +1318,63 @@ ScriptInterpreterPython::GenerateBreakpointCommandCallbackData (StringList &user return true; } +std::string +ScriptInterpreterPython::CallPythonScriptFunction (const char *python_function_name, + lldb::ValueObjectSP valobj) +{ + + if (!python_function_name || !(*python_function_name)) + return "<no function>"; + + if (!valobj.get()) + return "<no object>"; + + Target *target = valobj->GetUpdatePoint().GetTarget(); + + if (!target) + return "<no target>"; + + Debugger &debugger = target->GetDebugger(); + ScriptInterpreter *script_interpreter = debugger.GetCommandInterpreter().GetScriptInterpreter(); + ScriptInterpreterPython *python_interpreter = (ScriptInterpreterPython *) script_interpreter; + + if (!script_interpreter) + return "<no python>"; + + std::string ret_val; + + if (python_function_name + && *python_function_name) + { + FILE *tmp_fh = (python_interpreter->m_dbg_stdout ? python_interpreter->m_dbg_stdout : stdout); + if (CurrentThreadHasPythonLock()) + { + python_interpreter->EnterSession (); + ret_val = g_swig_typescript_callback (python_function_name, + python_interpreter->m_dictionary_name.c_str(), + valobj); + python_interpreter->LeaveSession (); + } + else + { + while (!GetPythonLock (1)) + fprintf (tmp_fh, + "Python interpreter locked on another thread; waiting to acquire lock...\n"); + python_interpreter->EnterSession (); + ret_val = g_swig_typescript_callback (python_function_name, + python_interpreter->m_dictionary_name.c_str(), + valobj); + python_interpreter->LeaveSession (); + ReleasePythonLock (); + } + } + else + return "<no function name>"; + + return ret_val; + +} + bool ScriptInterpreterPython::BreakpointCallbackFunction ( @@ -1399,10 +1568,12 @@ ScriptInterpreterPython::RunEmbeddedPythonInterpreter (lldb::thread_arg_t baton) void ScriptInterpreterPython::InitializeInterpreter (SWIGInitCallback python_swig_init_callback, - SWIGBreakpointCallbackFunction python_swig_breakpoint_callback) + SWIGBreakpointCallbackFunction python_swig_breakpoint_callback, + SWIGPythonTypeScriptCallbackFunction python_swig_typescript_callback) { g_swig_init_callback = python_swig_init_callback; - g_swig_breakpoint_callback = python_swig_breakpoint_callback; + g_swig_breakpoint_callback = python_swig_breakpoint_callback; + g_swig_typescript_callback = python_swig_typescript_callback; } void diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp index 0619c107655..9712d6f2ccd 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp @@ -19,6 +19,7 @@ #include "lldb/Core/Log.h" #include "lldb/Core/State.h" #include "lldb/Core/StreamString.h" +#include "lldb/Host/Endian.h" #include "lldb/Host/Host.h" #include "lldb/Host/TimeValue.h" #include "lldb/Target/Process.h" diff --git a/lldb/test/functionalities/data-formatter/data-formatter-script/Makefile b/lldb/test/functionalities/data-formatter/data-formatter-script/Makefile new file mode 100644 index 00000000000..314f1cb2f07 --- /dev/null +++ b/lldb/test/functionalities/data-formatter/data-formatter-script/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../../make + +CXX_SOURCES := main.cpp + +include $(LEVEL)/Makefile.rules diff --git a/lldb/test/functionalities/data-formatter/data-formatter-script/TestDataFormatterScript.py b/lldb/test/functionalities/data-formatter/data-formatter-script/TestDataFormatterScript.py new file mode 100644 index 00000000000..77a0368b7d4 --- /dev/null +++ b/lldb/test/functionalities/data-formatter/data-formatter-script/TestDataFormatterScript.py @@ -0,0 +1,110 @@ +""" +Test lldb data formatter subsystem. +""" + +import os, time +import unittest2 +import lldb +from lldbtest import * + +class DataFormatterTestCase(TestBase): + + mydir = os.path.join("functionalities", "data-formatter", "data-formatter-script") + + @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin") + def test_with_dsym_and_run_command(self): + """Test data formatter commands.""" + self.buildDsym() + self.data_formatter_commands() + + def test_with_dwarf_and_run_command(self): + """Test data formatter commands.""" + self.buildDwarf() + self.data_formatter_commands() + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number to break at. + self.line = line_number('main.cpp', '// Set break point at this line.') + + def data_formatter_commands(self): + """Test that that file and class static variables display correctly.""" + self.runCmd("file a.out", CURRENT_EXECUTABLE_SET) + + self.expect("breakpoint set -f main.cpp -l %d" % self.line, + BREAKPOINT_CREATED, + startstr = "Breakpoint created: 1: file ='main.cpp', line = %d, locations = 1" % + self.line) + + self.runCmd("run", RUN_SUCCEEDED) + + # The stop reason of the thread should be breakpoint. + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs = ['stopped', + 'stop reason = breakpoint']) + + # This is the function to remove the custom formats in order to have a + # clean slate for the next test case. + def cleanup(): + self.runCmd('type format clear', check=False) + self.runCmd('type summary clear', check=False) + + # Execute the cleanup function during test case tear down. + self.addTearDownHook(cleanup) + + # Set the script here to ease the formatting + script = 'a = valobj.GetChildMemberWithName(\'integer\'); a_val = a.GetValue(); str = \'Hello from Python, \' + a_val + \' time\'; return str + (\'!\' if a_val == \'1\' else \'s!\');' + + self.runCmd("type summary add add i_am_cool -s \"%s\"" % script) + + self.expect("frame variable one", + substrs = ['Hello from Python', + '1 time!']) + + self.expect("frame variable two", + substrs = ['Hello from Python', + '4 times!']) + + self.runCmd("n"); # skip ahead to make values change + + self.expect("frame variable three", + substrs = ['Hello from Python, 10 times!', + 'Hello from Python, 4 times!']) + + self.runCmd("n"); # skip ahead to make values change + + self.expect("frame variable two", + substrs = ['Hello from Python', + '1 time!']) + + script = 'a = valobj.GetChildMemberWithName(\'integer\'); a_val = a.GetValue(); str = \'int says \' + a_val; return str;' + + # Check that changes in the script are immediately reflected + self.runCmd("type summary add i_am_cool -s \"%s\"" % script) + + self.expect("frame variable two", + substrs = ['int says 1']) + + # Change the summary + self.runCmd("type summary add -f \"int says ${var.integer}, and float says ${var.floating}\" i_am_cool") + + self.expect("frame variable two", + substrs = ['int says 1', + 'and float says 2.71']) + # Try it for pointers + self.expect("frame variable twoptr", + substrs = ['int says 1', + 'and float says 2.71']) + + # Force a failure for pointers + self.runCmd("type summary add i_am_cool -p -s \"%s\"" % script) + + self.expect("frame variable twoptr", matching=False, + substrs = ['and float says 2.71']) + +if __name__ == '__main__': + import atexit + lldb.SBDebugger.Initialize() + atexit.register(lambda: lldb.SBDebugger.Terminate()) + unittest2.main() diff --git a/lldb/test/functionalities/data-formatter/data-formatter-script/main.cpp b/lldb/test/functionalities/data-formatter/data-formatter-script/main.cpp new file mode 100644 index 00000000000..357062234e1 --- /dev/null +++ b/lldb/test/functionalities/data-formatter/data-formatter-script/main.cpp @@ -0,0 +1,49 @@ +//===-- main.cpp ------------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include <stdio.h> +#include <stdlib.h> +#include <stdint.h> + +struct i_am_cool +{ + int integer; + float floating; + char character; + i_am_cool(int I, float F, char C) : + integer(I), floating(F), character(C) {} + i_am_cool() : integer(1), floating(2), character('3') {} + +}; + +struct i_am_cooler +{ + i_am_cool first_cool; + i_am_cool second_cool; + float floating; + + i_am_cooler(int I1, int I2, float F1, float F2, char C1, char C2) : + first_cool(I1,F1,C1), + second_cool(I2,F2,C2), + floating((F1 + F2)/2) {} +}; + +int main (int argc, const char * argv[]) +{ + i_am_cool one(1,3.14,'E'); + i_am_cool two(4,2.71,'G'); + + i_am_cool* twoptr = &two; + + i_am_cooler three(10,4,1985,1/1/2011,'B','E'); // Set break point at this line. + + two.integer = 1; + + return 0; +}
\ No newline at end of file diff --git a/lldb/www/varformats.html b/lldb/www/varformats.html index b0a1af18dd3..3fd647db18e 100755 --- a/lldb/www/varformats.html +++ b/lldb/www/varformats.html @@ -784,6 +784,17 @@ (i_am_cool) one = x=3<br> </code> </p> + <p>When defining a named summmary, binding it to one or more types becomes optional. + Even if you bind the named summary to a type, and later change the summary string + for that type, the named summary will not be changed by that. You can delete + named summaries by using the <code>type summary delete</code> command, as if the + summary name was the datatype that the summary is applied to</p> + + <p>A summary attached to a variable using the </code>--summary</code> option, + has the same semantics that a custom format attached using the <code>-f</code> + option has: it stays attached till you attach a new one, or till you let + your program run again.</p> + </div> </div> |