[Lldb-commits] [lldb] r281273 - This is the main part of a change to add breakpoint save and restore to lldb.
Zachary Turner via lldb-commits
lldb-commits at lists.llvm.org
Mon Sep 12 16:57:50 PDT 2016
On Mon, Sep 12, 2016 at 4:19 PM Jim Ingham via lldb-commits <
lldb-commits at lists.llvm.org> wrote:
> Author: jingham
> Date: Mon Sep 12 18:10:56 2016
> New Revision: 281273
>
> URL: http://llvm.org/viewvc/llvm-project?rev=281273&view=rev
> Log:
> This is the main part of a change to add breakpoint save and restore to
> lldb.
>
> Still to come:
> 1) SB API's
> 2) Testcases
> 3) Loose ends:
> a) serialize Thread options
> b) serialize Exception resolvers
> 4) "break list --file" should list breakpoints contained in a file and
> "break read -f 1 3 5" should then read in only those breakpoints.
>
> <rdar://problem/12611863>
>
> Modified:
> lldb/trunk/include/lldb/Breakpoint/Breakpoint.h
> lldb/trunk/include/lldb/Breakpoint/BreakpointOptions.h
> lldb/trunk/include/lldb/Breakpoint/BreakpointResolver.h
> lldb/trunk/include/lldb/Breakpoint/BreakpointResolverAddress.h
> lldb/trunk/include/lldb/Breakpoint/BreakpointResolverFileLine.h
> lldb/trunk/include/lldb/Breakpoint/BreakpointResolverFileRegex.h
> lldb/trunk/include/lldb/Breakpoint/BreakpointResolverName.h
> lldb/trunk/include/lldb/Core/SearchFilter.h
> lldb/trunk/include/lldb/Core/StructuredData.h
> lldb/trunk/include/lldb/Target/LanguageRuntime.h
> lldb/trunk/source/Breakpoint/Breakpoint.cpp
> lldb/trunk/source/Breakpoint/BreakpointOptions.cpp
> lldb/trunk/source/Breakpoint/BreakpointResolver.cpp
> lldb/trunk/source/Breakpoint/BreakpointResolverAddress.cpp
> lldb/trunk/source/Breakpoint/BreakpointResolverFileLine.cpp
> lldb/trunk/source/Breakpoint/BreakpointResolverFileRegex.cpp
> lldb/trunk/source/Breakpoint/BreakpointResolverName.cpp
> lldb/trunk/source/Commands/CommandObjectBreakpoint.cpp
> lldb/trunk/source/Commands/CommandObjectBreakpointCommand.cpp
> lldb/trunk/source/Core/SearchFilter.cpp
> lldb/trunk/source/Core/StructuredData.cpp
>
> lldb/trunk/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp
> lldb/trunk/source/Target/LanguageRuntime.cpp
>
> Modified: lldb/trunk/include/lldb/Breakpoint/Breakpoint.h
> URL:
> http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Breakpoint/Breakpoint.h?rev=281273&r1=281272&r2=281273&view=diff
>
> ==============================================================================
> --- lldb/trunk/include/lldb/Breakpoint/Breakpoint.h (original)
> +++ lldb/trunk/include/lldb/Breakpoint/Breakpoint.h Mon Sep 12 18:10:56
> 2016
> @@ -27,6 +27,7 @@
> #include "lldb/Core/Event.h"
> #include "lldb/Core/SearchFilter.h"
> #include "lldb/Core/StringList.h"
> +#include "lldb/Core/StructuredData.h"
>
> namespace lldb_private {
>
> @@ -164,6 +165,13 @@ public:
>
> typedef std::shared_ptr<BreakpointPrecondition>
> BreakpointPreconditionSP;
>
> + // Saving & restoring breakpoints:
> + static lldb::BreakpointSP CreateFromStructuredData(
> + Target &target, StructuredData::ObjectSP &data_object_sp, Error
> &error);
> +
> + virtual StructuredData::ObjectSP SerializeToStructuredData();
> +
> + static const char *GetSerializationKey() { return "Breakpoint"; }
//------------------------------------------------------------------
> /// Destructor.
> ///
> @@ -717,7 +725,8 @@ private:
> // to skip certain breakpoint hits. For instance, exception breakpoints
> // use this to limit the stop to certain exception classes, while
> leaving
> // the condition & callback free for user specification.
> - BreakpointOptions m_options; // Settable breakpoint options
> + std::unique_ptr<BreakpointOptions>
> + m_options_up; // Settable breakpoint options
> BreakpointLocationList
> m_locations; // The list of locations currently found for this
> breakpoint.
> std::string m_kind_description;
>
> Modified: lldb/trunk/include/lldb/Breakpoint/BreakpointOptions.h
> URL:
> http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Breakpoint/BreakpointOptions.h?rev=281273&r1=281272&r2=281273&view=diff
>
> ==============================================================================
> --- lldb/trunk/include/lldb/Breakpoint/BreakpointOptions.h (original)
> +++ lldb/trunk/include/lldb/Breakpoint/BreakpointOptions.h Mon Sep 12
> 18:10:56 2016
> @@ -19,6 +19,7 @@
> // Project includes
> #include "lldb/Core/Baton.h"
> #include "lldb/Core/StringList.h"
> +#include "lldb/Core/StructuredData.h"
> #include "lldb/lldb-private.h"
>
> namespace lldb_private {
> @@ -32,6 +33,52 @@ namespace lldb_private {
>
> class BreakpointOptions {
> public:
> + struct CommandData {
> + CommandData() : user_source(), script_source(), stop_on_error(true) {}
> +
> + ~CommandData() = default;
> +
> + static const char *GetSerializationKey() { return "BKPTCMDData"; }
> +
> + StructuredData::ObjectSP SerializeToStructuredData();
> +
> + static CommandData *
> + CreateFromStructuredData(StructuredData::Dictionary &options_dict,
> + Error &error);
>
This should probably return a unique_ptr to prevent memory leaks. And the
dictionary should be const.
> +
> + StringList user_source;
> + std::string script_source;
> + bool stop_on_error;
> +
> + private:
> + enum OptionNames {
> + UserSource = 0,
> + ScriptSource,
> + StopOnError,
> + LastOptionName
> + };
> +
> + static const char *g_option_names[LastOptionName];
> +
> + static const char *GetKey(enum OptionNames enum_value) {
> + return g_option_names[enum_value];
> + }
> + };
> +
> + class CommandBaton : public Baton {
> + public:
> + CommandBaton(CommandData *data) : Baton(data) {}
> +
> + ~CommandBaton() override {
> + delete ((CommandData *)m_data);
> + m_data = nullptr;
> + }
> +
> + void GetDescription(Stream *s, lldb::DescriptionLevel level) const
> override;
> + };
> +
> + typedef std::shared_ptr<CommandBaton> CommandBatonSP;
> +
>
Seems like it might be useful to have a PtrBaton<T> class that holds a
unique_ptr<T>, then you wouldn't need to even make a new class for each
type of Baton, they could all just used PtrBaton<T>
> //------------------------------------------------------------------
> // Constructors and Destructors
> //------------------------------------------------------------------
> @@ -43,35 +90,34 @@ public:
> BreakpointOptions(const BreakpointOptions &rhs);
>
> static BreakpointOptions *CopyOptionsNoCallback(BreakpointOptions &rhs);
> +
> //------------------------------------------------------------------
> - /// This constructor allows you to specify all the breakpoint options.
> + /// This constructor allows you to specify all the breakpoint options
> + /// except the callback. That one is more complicated, and better
> + /// to do by hand.
> ///
> /// @param[in] condition
> /// The expression which if it evaluates to \b true if we are to stop
> ///
> - /// @param[in] callback
> - /// This is the plugin for some code that gets run, returns \b true
> if we
> - /// are to stop.
> - ///
> - /// @param[in] baton
> - /// Client data that will get passed to the callback.
> - ///
> /// @param[in] enabled
> /// Is this breakpoint enabled.
> ///
> /// @param[in] ignore
> /// How many breakpoint hits we should ignore before stopping.
> ///
> - /// @param[in] thread_id
> - /// Only stop if \a thread_id hits the breakpoint.
> //------------------------------------------------------------------
> - BreakpointOptions(void *condition, BreakpointHitCallback callback,
> - void *baton, bool enabled = true, int32_t ignore = 0,
> - lldb::tid_t thread_id = LLDB_INVALID_THREAD_ID,
> - bool one_shot = false);
> + BreakpointOptions(const char *condition, bool enabled = true,
> + int32_t ignore = 0, bool one_shot = false);
>
StringRef condition
>
> virtual ~BreakpointOptions();
>
> + static BreakpointOptions *
> + CreateFromStructuredData(StructuredData::Dictionary &data_dict, Error
> &error);
>
unique_ptr<BreakpointOptions>
> +
> + virtual StructuredData::ObjectSP SerializeToStructuredData();
> +
> + static const char *GetSerializationKey() { return "BKPTOptions"; }
>
StringRef GetSerializationKey
> +
> //------------------------------------------------------------------
> // Operators
> //------------------------------------------------------------------
> @@ -131,6 +177,10 @@ public:
> void SetCallback(BreakpointHitCallback callback,
> const lldb::BatonSP &baton_sp, bool synchronous =
> false);
>
> + void SetCallback(BreakpointHitCallback callback,
> + const BreakpointOptions::CommandBatonSP
> &command_baton_sp,
> + bool synchronous = false);
> +
> //------------------------------------------------------------------
> /// Remove the callback from this option set.
> //------------------------------------------------------------------
> @@ -279,40 +329,39 @@ public:
>
> //------------------------------------------------------------------
> /// This is the default empty callback.
> - /// @return
> - /// The thread id for which the breakpoint hit will stop,
> - /// LLDB_INVALID_THREAD_ID for all threads.
> //------------------------------------------------------------------
> static bool NullCallback(void *baton, StoppointCallbackContext *context,
> lldb::user_id_t break_id,
> lldb::user_id_t break_loc_id);
>
> - struct CommandData {
> - CommandData() : user_source(), script_source(), stop_on_error(true) {}
> -
> - ~CommandData() = default;
> -
> - StringList user_source;
> - std::string script_source;
> - bool stop_on_error;
> - };
> -
> - class CommandBaton : public Baton {
> - public:
> - CommandBaton(CommandData *data) : Baton(data) {}
> -
> - ~CommandBaton() override {
> - delete ((CommandData *)m_data);
> - m_data = nullptr;
> - }
> -
> - void GetDescription(Stream *s, lldb::DescriptionLevel level) const
> override;
> - };
> + //------------------------------------------------------------------
> + /// Set a callback based on BreakpointOptions::CommandData.
> + /// @param[in] cmd_data
> + /// A new'ed CommandData object. The breakpoint will take ownership
> + /// of this object.
> + //------------------------------------------------------------------
> + void SetCommandDataCallback(CommandData *cmd_data);
>
> protected:
> //------------------------------------------------------------------
> // Classes that inherit from BreakpointOptions can see and modify these
> //------------------------------------------------------------------
> + enum OptionNames {
> + ConditionText = 0,
> + IgnoreCount,
> + EnabledState,
> + OneShotState,
> + LastOptionName
> + };
> + static const char *g_option_names[LastOptionName];
> +
> + static const char *GetKey(enum OptionNames enum_value) {
> + return g_option_names[enum_value];
> + }
>
static StringRef GetKey().
Also this can be an enum class if you use llvm/ADT/BitmaskEnu.h
> +
> + static bool BreakpointOptionsCallbackFunction(
> + void *baton, StoppointCallbackContext *context, lldb::user_id_t
> break_id,
> + lldb::user_id_t break_loc_id);
>
> private:
> //------------------------------------------------------------------
> @@ -320,6 +369,7 @@ private:
> //------------------------------------------------------------------
> BreakpointHitCallback m_callback; // This is the callback function
> pointer
> lldb::BatonSP m_callback_baton_sp; // This is the client data for the
> callback
> + bool m_baton_is_command_baton;
> bool m_callback_is_synchronous;
> bool m_enabled;
> bool m_one_shot;
>
> Modified: lldb/trunk/include/lldb/Breakpoint/BreakpointResolver.h
> URL:
> http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Breakpoint/BreakpointResolver.h?rev=281273&r1=281272&r2=281273&view=diff
>
> ==============================================================================
> --- lldb/trunk/include/lldb/Breakpoint/BreakpointResolver.h (original)
> +++ lldb/trunk/include/lldb/Breakpoint/BreakpointResolver.h Mon Sep 12
> 18:10:56 2016
> @@ -136,30 +136,96 @@ public:
> //------------------------------------------------------------------
> virtual void Dump(Stream *s) const = 0;
>
> + /// This section handles serializing and deserializing from
> StructuredData
> + /// objects.
> +
> + static lldb::BreakpointResolverSP
> + CreateFromStructuredData(StructuredData::Dictionary &resolver_dict,
> + Error &error);
> +
> + virtual StructuredData::ObjectSP SerializeToStructuredData() {
> + return StructuredData::ObjectSP();
> + }
> +
> + static const char *GetSerializationKey() { return "BKPTResolver"; }
> +
> + static const char *GetSerializationSubclassKey() { return "Type"; }
> +
> + static const char *GetSerializationSubclassOptionsKey() { return
> "Options"; }
>
More StringRef opportunities. This makes it very convenient to do
comparisons and searching on the return values without resorting to CRT
functions.
> +
> + StructuredData::DictionarySP
> + WrapOptionsDict(StructuredData::DictionarySP options_dict_sp);
> +
> + //------------------------------------------------------------------
> //------------------------------------------------------------------
> /// An enumeration for keeping track of the concrete subclass that
> /// is actually instantiated. Values of this enumeration are kept in the
> /// BreakpointResolver's SubclassID field. They are used for concrete
> type
> /// identification.
> enum ResolverTy {
> - FileLineResolver, // This is an instance of BreakpointResolverFileLine
> - AddressResolver, // This is an instance of BreakpointResolverAddress
> - NameResolver, // This is an instance of BreakpointResolverName
> + FileLineResolver = 0, // This is an instance of
> BreakpointResolverFileLine
> + AddressResolver, // This is an instance of
> BreakpointResolverAddress
> + NameResolver, // This is an instance of BreakpointResolverName
> FileRegexResolver,
> ExceptionResolver,
> - LastKnownResolverType = ExceptionResolver
> + LastKnownResolverType = ExceptionResolver,
> + UnknownResolver
> };
>
> + // Translate the Ty to name for serialization,
> + // the "+2" is one for size vrs. index, and one for UnknownResolver.
> + static const char *g_ty_to_name[LastKnownResolverType + 2];
> +
> //------------------------------------------------------------------
> /// getResolverID - Return an ID for the concrete type of this object.
> This
> /// is used to implement the LLVM classof checks. This should not be
> used
> /// for any other purpose, as the values may change as LLDB evolves.
> unsigned getResolverID() const { return SubclassID; }
>
> + enum ResolverTy GetResolverTy() {
> + if (SubclassID > ResolverTy::LastKnownResolverType)
> + return ResolverTy::UnknownResolver;
> + else
> + return (enum ResolverTy)SubclassID;
> + }
> +
> + const char *GetResolverName() { return
> ResolverTyToName(GetResolverTy()); }
> +
> + static const char *ResolverTyToName(enum ResolverTy);
> +
> + static ResolverTy NameToResolverTy(const char *name);
> +
> virtual lldb::BreakpointResolverSP
> CopyForBreakpoint(Breakpoint &breakpoint) = 0;
>
> protected:
> + // Used for serializing resolver options:
> + // The options in this enum and the strings in the
> + // g_option_names must be kept in sync.
> + enum OptionNames {
> + AddressOffset = 0,
> + ExactMatch,
> + FileName,
> + Inlines,
> + LanguageName,
> + LineNumber,
> + ModuleName,
> + NameMaskArray,
> + Offset,
> + RegexString,
> + SectionName,
> + SkipPrologue,
> + SymbolNameArray,
> + LastOptionName
> + };
> + static const char *g_option_names[LastOptionName];
> +
> +public:
> + static const char *GetKey(enum OptionNames enum_value) {
> + return g_option_names[enum_value];
> + }
> +
> +protected:
> //------------------------------------------------------------------
> /// SetSCMatchesByLine - Takes a symbol context list of matches which
> /// supposedly represent the same file and
>
> Modified: lldb/trunk/include/lldb/Breakpoint/BreakpointResolverAddress.h
> URL:
> http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Breakpoint/BreakpointResolverAddress.h?rev=281273&r1=281272&r2=281273&view=diff
>
> ==============================================================================
> --- lldb/trunk/include/lldb/Breakpoint/BreakpointResolverAddress.h
> (original)
> +++ lldb/trunk/include/lldb/Breakpoint/BreakpointResolverAddress.h Mon Sep
> 12 18:10:56 2016
> @@ -36,6 +36,11 @@ public:
>
> ~BreakpointResolverAddress() override;
>
> + static BreakpointResolver *CreateFromStructuredData(
> + Breakpoint *bkpt, StructuredData::Dictionary &options_dict, Error
> &error);
> +
> + StructuredData::ObjectSP SerializeToStructuredData() override;
> +
> void ResolveBreakpoint(SearchFilter &filter) override;
>
> void ResolveBreakpointInModules(SearchFilter &filter,
>
> Modified: lldb/trunk/include/lldb/Breakpoint/BreakpointResolverFileLine.h
> URL:
> http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Breakpoint/BreakpointResolverFileLine.h?rev=281273&r1=281272&r2=281273&view=diff
>
> ==============================================================================
> --- lldb/trunk/include/lldb/Breakpoint/BreakpointResolverFileLine.h
> (original)
> +++ lldb/trunk/include/lldb/Breakpoint/BreakpointResolverFileLine.h Mon
> Sep 12 18:10:56 2016
> @@ -33,6 +33,12 @@ public:
> bool check_inlines, bool skip_prologue,
> bool exact_match);
>
> + static BreakpointResolver *
> + CreateFromStructuredData(Breakpoint *bkpt,
> + StructuredData::Dictionary &data_dict, Error
> &error);
> +
> + StructuredData::ObjectSP SerializeToStructuredData() override;
> +
> ~BreakpointResolverFileLine() override;
>
> Searcher::CallbackReturn SearchCallback(SearchFilter &filter,
>
> Modified: lldb/trunk/include/lldb/Breakpoint/BreakpointResolverFileRegex.h
> URL:
> http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Breakpoint/BreakpointResolverFileRegex.h?rev=281273&r1=281272&r2=281273&view=diff
>
> ==============================================================================
> --- lldb/trunk/include/lldb/Breakpoint/BreakpointResolverFileRegex.h
> (original)
> +++ lldb/trunk/include/lldb/Breakpoint/BreakpointResolverFileRegex.h Mon
> Sep 12 18:10:56 2016
> @@ -35,6 +35,11 @@ public:
> Breakpoint *bkpt, RegularExpression ®ex,
> const std::unordered_set<std::string> &func_name_set, bool
> exact_match);
>
> + static BreakpointResolver *CreateFromStructuredData(
> + Breakpoint *bkpt, StructuredData::Dictionary &options_dict, Error
> &error);
> +
> + StructuredData::ObjectSP SerializeToStructuredData() override;
> +
> ~BreakpointResolverFileRegex() override;
>
> Searcher::CallbackReturn SearchCallback(SearchFilter &filter,
>
> Modified: lldb/trunk/include/lldb/Breakpoint/BreakpointResolverName.h
> URL:
> http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Breakpoint/BreakpointResolverName.h?rev=281273&r1=281272&r2=281273&view=diff
>
> ==============================================================================
> --- lldb/trunk/include/lldb/Breakpoint/BreakpointResolverName.h (original)
> +++ lldb/trunk/include/lldb/Breakpoint/BreakpointResolverName.h Mon Sep 12
> 18:10:56 2016
> @@ -54,9 +54,11 @@ public:
> lldb::LanguageType language, lldb::addr_t offset,
> bool skip_prologue);
>
> - BreakpointResolverName(Breakpoint *bkpt, const char *class_name,
> - const char *method, Breakpoint::MatchType type,
> - lldb::addr_t offset, bool skip_prologue);
> + static BreakpointResolver *
> + CreateFromStructuredData(Breakpoint *bkpt,
> + StructuredData::Dictionary &data_dict, Error
> &error);
> +
> + StructuredData::ObjectSP SerializeToStructuredData() override;
>
> ~BreakpointResolverName() override;
>
>
> Modified: lldb/trunk/include/lldb/Core/SearchFilter.h
> URL:
> http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/SearchFilter.h?rev=281273&r1=281272&r2=281273&view=diff
>
> ==============================================================================
> --- lldb/trunk/include/lldb/Core/SearchFilter.h (original)
> +++ lldb/trunk/include/lldb/Core/SearchFilter.h Mon Sep 12 18:10:56 2016
> @@ -15,6 +15,7 @@
> // Other libraries and framework includes
> // Project includes
> #include "lldb/Core/FileSpecList.h"
> +#include "lldb/Core/StructuredData.h"
> #include "lldb/lldb-private.h"
>
> namespace lldb_private {
> @@ -101,6 +102,8 @@ public:
>
> SearchFilter(const SearchFilter &rhs);
>
> + SearchFilter(const lldb::TargetSP &target_sp, unsigned char filterType);
> +
> virtual ~SearchFilter();
>
> SearchFilter &operator=(const SearchFilter &rhs);
> @@ -213,7 +216,60 @@ public:
>
> lldb::SearchFilterSP CopyForBreakpoint(Breakpoint &breakpoint);
>
> + static SearchFilter *
> + CreateFromStructuredData(Target &target,
> + StructuredData::Dictionary &data_dict, Error
> &error);
> +
> + virtual StructuredData::ObjectSP SerializeToStructuredData() {
> + return StructuredData::ObjectSP();
> + }
> +
> + static const char *GetSerializationKey() { return "SearchFilter"; }
> +
> + static const char *GetSerializationSubclassKey() { return "Type"; }
> +
> + static const char *GetSerializationSubclassOptionsKey() { return
> "Options"; }
> +
> + enum FilterTy {
> + Unconstrained = 0,
> + Exception,
> + ByModule,
> + ByModules,
> + ByModulesAndCU,
> + LastKnownFilterType = ByModulesAndCU,
> + UnknownFilter
> + };
> +
> + static const char *g_ty_to_name[LastKnownFilterType + 2];
> +
> + enum FilterTy GetFilterTy() {
> + if (SubclassID > FilterTy::LastKnownFilterType)
> + return FilterTy::UnknownFilter;
> + else
> + return (enum FilterTy)SubclassID;
> + }
> +
> + const char *GetFilterName() { return FilterTyToName(GetFilterTy()); }
> +
> + static const char *FilterTyToName(enum FilterTy);
> +
> + static FilterTy NameToFilterTy(const char *name);
> +
> protected:
> + // Serialization of SearchFilter options:
> + enum OptionNames { ModList = 0, CUList, LanguageName, LastOptionName };
> + static const char *g_option_names[LastOptionName];
> +
> + static const char *GetKey(enum OptionNames enum_value) {
> + return g_option_names[enum_value];
> + }
> +
> + StructuredData::DictionarySP
> + WrapOptionsDict(StructuredData::DictionarySP options_dict_sp);
> +
> + void SerializeFileSpecList(StructuredData::DictionarySP
> &options_dict_sp,
> + OptionNames name, FileSpecList &file_list);
>
A reference to a shared_ptr<> seems odd, is this intended?
> +
> // These are utility functions to assist with the search iteration.
> They are
> // used by the
> // default Search method.
> @@ -239,6 +295,8 @@ protected:
> lldb::TargetSP
> m_target_sp; // Every filter has to be associated with a target for
> // now since you need a starting place for the search.
> +private:
> + unsigned char SubclassID;
>
};
>
> //----------------------------------------------------------------------
> @@ -250,13 +308,20 @@ protected:
> class SearchFilterForUnconstrainedSearches : public SearchFilter {
> public:
> SearchFilterForUnconstrainedSearches(const lldb::TargetSP &target_sp)
> - : SearchFilter(target_sp) {}
> + : SearchFilter(target_sp, FilterTy::Unconstrained) {}
> +
> ~SearchFilterForUnconstrainedSearches() override = default;
>
> bool ModulePasses(const FileSpec &module_spec) override;
>
> bool ModulePasses(const lldb::ModuleSP &module_sp) override;
>
> + static SearchFilter *
> + CreateFromStructuredData(Target &target,
> + StructuredData::Dictionary &data_dict, Error
> &error);
> +
> + StructuredData::ObjectSP SerializeToStructuredData() override;
> +
> protected:
> lldb::SearchFilterSP DoCopyForBreakpoint(Breakpoint &breakpoint)
> override;
> };
> @@ -304,6 +369,12 @@ public:
>
> void Search(Searcher &searcher) override;
>
> + static SearchFilter *
> + CreateFromStructuredData(Target &target,
> + StructuredData::Dictionary &data_dict, Error
> &error);
> +
> + StructuredData::ObjectSP SerializeToStructuredData() override;
> +
> protected:
> lldb::SearchFilterSP DoCopyForBreakpoint(Breakpoint &breakpoint)
> override;
>
> @@ -326,6 +397,10 @@ public:
> SearchFilterByModuleList(const lldb::TargetSP &targetSP,
> const FileSpecList &module_list);
>
> + SearchFilterByModuleList(const lldb::TargetSP &targetSP,
> + const FileSpecList &module_list,
> + enum FilterTy filter_ty);
> +
> SearchFilterByModuleList(const SearchFilterByModuleList &rhs);
>
> ~SearchFilterByModuleList() override;
> @@ -350,6 +425,14 @@ public:
>
> void Search(Searcher &searcher) override;
>
> + static SearchFilter *
> + CreateFromStructuredData(Target &target,
> + StructuredData::Dictionary &data_dict, Error
> &error);
> +
> + StructuredData::ObjectSP SerializeToStructuredData() override;
> +
> + void SerializeUnwrapped(StructuredData::DictionarySP &options_dict_sp);
> +
> protected:
> lldb::SearchFilterSP DoCopyForBreakpoint(Breakpoint &breakpoint)
> override;
>
> @@ -394,6 +477,12 @@ public:
>
> void Search(Searcher &searcher) override;
>
> + static SearchFilter *
> + CreateFromStructuredData(Target &target,
> + StructuredData::Dictionary &data_dict, Error
> &error);
> +
> + StructuredData::ObjectSP SerializeToStructuredData() override;
> +
> protected:
> lldb::SearchFilterSP DoCopyForBreakpoint(Breakpoint &breakpoint)
> override;
>
>
> Modified: lldb/trunk/include/lldb/Core/StructuredData.h
> URL:
> http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/StructuredData.h?rev=281273&r1=281272&r2=281273&view=diff
>
> ==============================================================================
> --- lldb/trunk/include/lldb/Core/StructuredData.h (original)
> +++ lldb/trunk/include/lldb/Core/StructuredData.h Mon Sep 12 18:10:56 2016
> @@ -390,6 +390,18 @@ public:
> return value_sp;
> }
>
> + bool GetValueForKeyAsBoolean(llvm::StringRef key, bool &result) const
> {
> + bool success = false;
> + ObjectSP value_sp = GetValueForKey(key);
> + if (value_sp.get()) {
>
Not a big deal since this is a short function, but LLVM style is to use
early return on failure.
> + Boolean *result_ptr = value_sp->GetAsBoolean();
> + if (result_ptr) {
> + result = result_ptr->GetValue();
> + success = true;
> + }
> + }
> + return success;
> + }
> template <class IntType>
> bool GetValueForKeyAsInteger(llvm::StringRef key, IntType &result)
> const {
> ObjectSP value_sp = GetValueForKey(key);
> @@ -539,6 +551,8 @@ public:
> };
>
> static ObjectSP ParseJSON(std::string json_text);
> +
> + static ObjectSP ParseJSONFromFile(FileSpec &file, Error &error);
>
const FileSpec
> };
>
> } // namespace lldb_private
>
> Modified: lldb/trunk/include/lldb/Target/LanguageRuntime.h
> URL:
> http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Target/LanguageRuntime.h?rev=281273&r1=281272&r2=281273&view=diff
>
> ==============================================================================
> --- lldb/trunk/include/lldb/Target/LanguageRuntime.h (original)
> +++ lldb/trunk/include/lldb/Target/LanguageRuntime.h Mon Sep 12 18:10:56
> 2016
> @@ -1,5 +1,5 @@
> //===-- LanguageRuntime.h
> ---------------------------------------------------*-
> -//C++ -*-===//
> +// C++ -*-===//
> //
> // The LLVM Compiler Infrastructure
> //
> @@ -29,6 +29,38 @@
>
> namespace lldb_private {
>
> +class ExceptionSearchFilter : public SearchFilter {
> +public:
> + ExceptionSearchFilter(const lldb::TargetSP &target_sp,
> + lldb::LanguageType language,
> + bool update_module_list = true);
> +
> + ~ExceptionSearchFilter() override = default;
> +
> + bool ModulePasses(const lldb::ModuleSP &module_sp) override;
>
Another shared_ptr reference, shouldn't we just pass the shared_ptr by
value or the value by reference?
> +
> + bool ModulePasses(const FileSpec &spec) override;
> +
> + void Search(Searcher &searcher) override;
> +
> + void GetDescription(Stream *s) override;
> +
> + static SearchFilter *
> + CreateFromStructuredData(Target &target,
> + StructuredData::Dictionary &data_dict, Error
> &error);
> +
> + StructuredData::ObjectSP SerializeToStructuredData() override;
> +
> +protected:
> + lldb::LanguageType m_language;
> + LanguageRuntime *m_language_runtime;
> + lldb::SearchFilterSP m_filter_sp;
> +
> + lldb::SearchFilterSP DoCopyForBreakpoint(Breakpoint &breakpoint)
> override;
> +
> + void UpdateModuleListIfNeeded();
> +};
> +
> class LanguageRuntime : public PluginInterface {
> public:
> ~LanguageRuntime() override;
>
> Modified: lldb/trunk/source/Breakpoint/Breakpoint.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Breakpoint/Breakpoint.cpp?rev=281273&r1=281272&r2=281273&view=diff
>
> ==============================================================================
> --- lldb/trunk/source/Breakpoint/Breakpoint.cpp (original)
> +++ lldb/trunk/source/Breakpoint/Breakpoint.cpp Mon Sep 12 18:10:56 2016
> @@ -48,16 +48,17 @@ Breakpoint::Breakpoint(Target &target, S
> BreakpointResolverSP &resolver_sp, bool hardware,
> bool resolve_indirect_symbols)
> : m_being_created(true), m_hardware(hardware), m_target(target),
> - m_filter_sp(filter_sp), m_resolver_sp(resolver_sp), m_options(),
> - m_locations(*this),
> m_resolve_indirect_symbols(resolve_indirect_symbols),
> - m_hit_count(0) {
> + m_filter_sp(filter_sp), m_resolver_sp(resolver_sp),
> + m_options_up(new BreakpointOptions()), m_locations(*this),
> + m_resolve_indirect_symbols(resolve_indirect_symbols),
> m_hit_count(0) {
> m_being_created = false;
> }
>
> Breakpoint::Breakpoint(Target &new_target, Breakpoint &source_bp)
> : m_being_created(true), m_hardware(source_bp.m_hardware),
> m_target(new_target), m_name_list(source_bp.m_name_list),
> - m_options(source_bp.m_options), m_locations(*this),
> + m_options_up(new BreakpointOptions(*source_bp.m_options_up.get())),
> + m_locations(*this),
> m_resolve_indirect_symbols(source_bp.m_resolve_indirect_symbols),
> m_hit_count(0) {
> // Now go through and copy the filter & resolver:
> @@ -70,6 +71,115 @@ Breakpoint::Breakpoint(Target &new_targe
> //----------------------------------------------------------------------
> Breakpoint::~Breakpoint() = default;
>
> +//----------------------------------------------------------------------
> +// Serialization
> +//----------------------------------------------------------------------
> +StructuredData::ObjectSP Breakpoint::SerializeToStructuredData() {
> + // Serialize the resolver:
> + StructuredData::DictionarySP breakpoint_dict_sp(
> + new StructuredData::Dictionary());
> + StructuredData::DictionarySP breakpoint_contents_sp(
> + new StructuredData::Dictionary());
> +
> + StructuredData::ObjectSP resolver_dict_sp(
> + m_resolver_sp->SerializeToStructuredData());
> + if (!resolver_dict_sp)
> + return StructuredData::ObjectSP();
> +
> +
> breakpoint_contents_sp->AddItem(BreakpointResolver::GetSerializationKey(),
> + resolver_dict_sp);
> +
> + StructuredData::ObjectSP filter_dict_sp(
> + m_filter_sp->SerializeToStructuredData());
> + if (!filter_dict_sp)
> + return StructuredData::ObjectSP();
> +
> + breakpoint_contents_sp->AddItem(SearchFilter::GetSerializationKey(),
> + filter_dict_sp);
> +
> + StructuredData::ObjectSP options_dict_sp(
> + m_options_up->SerializeToStructuredData());
> + if (!options_dict_sp)
> + return StructuredData::ObjectSP();
> +
> +
> breakpoint_contents_sp->AddItem(BreakpointOptions::GetSerializationKey(),
> + options_dict_sp);
> +
> + breakpoint_dict_sp->AddItem(GetSerializationKey(),
> breakpoint_contents_sp);
> + return breakpoint_dict_sp;
> +}
> +
> +lldb::BreakpointSP Breakpoint::CreateFromStructuredData(
> + Target &target, StructuredData::ObjectSP &object_data, Error &error) {
> + BreakpointSP result_sp;
> +
> + StructuredData::Dictionary *breakpoint_dict =
> object_data->GetAsDictionary();
> +
> + if (!breakpoint_dict || !breakpoint_dict->IsValid()) {
> + error.SetErrorString("Can't deserialize from an invalid data
> object.");
> + return result_sp;
> + }
> +
> + StructuredData::Dictionary *resolver_dict;
> + bool success = breakpoint_dict->GetValueForKeyAsDictionary(
> + BreakpointResolver::GetSerializationKey(), resolver_dict);
> + if (!success) {
> + error.SetErrorStringWithFormat(
> + "Breakpoint data missing toplevel resolver key");
> + return result_sp;
> + }
> +
> + Error create_error;
> + BreakpointResolverSP resolver_sp =
> + BreakpointResolver::CreateFromStructuredData(*resolver_dict,
> + create_error);
> + if (create_error.Fail()) {
> + error.SetErrorStringWithFormat(
> + "Error creating breakpoint resolver from data: %s.",
> + create_error.AsCString());
> + return result_sp;
> + }
> +
> + StructuredData::Dictionary *filter_dict;
> + success = breakpoint_dict->GetValueForKeyAsDictionary(
> + SearchFilter::GetSerializationKey(), filter_dict);
> + SearchFilterSP filter_sp;
> + if (!success)
>
+ filter_sp.reset(
> + new
> SearchFilterForUnconstrainedSearches(target.shared_from_this()));
>
std::make_shared is preferable to this pattern. There's a similar pattern
for make_unique<>, but it's especially useful for shared_ptr's since it can
allocate the object as well as the shared_ptr's control block with a single
allocation. As a general principle, it is also more resilient in the face
of exceptions in the constructor, although this doesn't matter for us since
we disable exceptions.
> + else {
> + filter_sp.reset(SearchFilter::CreateFromStructuredData(target,
> *filter_dict,
> + create_error));
> + if (create_error.Fail()) {
> + error.SetErrorStringWithFormat(
> + "Error creating breakpoint filter from data: %s.",
> + create_error.AsCString());
> + return result_sp;
> + }
> + }
> +
> + BreakpointOptions *options = nullptr;
> + StructuredData::Dictionary *options_dict;
> + success = breakpoint_dict->GetValueForKeyAsDictionary(
> + BreakpointOptions::GetSerializationKey(), options_dict);
> + if (success) {
> + options = BreakpointOptions::CreateFromStructuredData(*options_dict,
> + create_error);
> + if (create_error.Fail()) {
> + error.SetErrorStringWithFormat(
> + "Error creating breakpoint options from data: %s.",
> + create_error.AsCString());
> + return result_sp;
> + }
> + }
> + result_sp =
> + target.CreateBreakpoint(filter_sp, resolver_sp, false, false, true);
> + if (result_sp && options) {
> + result_sp->m_options_up.reset(options);
> + }
> + return result_sp;
> +}
> +
> const lldb::TargetSP Breakpoint::GetTargetSP() {
> return m_target.shared_from_this();
> }
> @@ -111,10 +221,10 @@ void Breakpoint::RemoveInvalidLocations(
> // up the individual settings.
>
> void Breakpoint::SetEnabled(bool enable) {
> - if (enable == m_options.IsEnabled())
> + if (enable == m_options_up->IsEnabled())
> return;
>
> - m_options.SetEnabled(enable);
> + m_options_up->SetEnabled(enable);
> if (enable)
> m_locations.ResolveAllBreakpointSites();
> else
> @@ -124,24 +234,24 @@ void Breakpoint::SetEnabled(bool enable)
> : eBreakpointEventTypeDisabled);
> }
>
> -bool Breakpoint::IsEnabled() { return m_options.IsEnabled(); }
> +bool Breakpoint::IsEnabled() { return m_options_up->IsEnabled(); }
>
const member function?
>
> void Breakpoint::SetIgnoreCount(uint32_t n) {
> - if (m_options.GetIgnoreCount() == n)
> + if (m_options_up->GetIgnoreCount() == n)
> return;
>
> - m_options.SetIgnoreCount(n);
> + m_options_up->SetIgnoreCount(n);
> SendBreakpointChangedEvent(eBreakpointEventTypeIgnoreChanged);
> }
>
> void Breakpoint::DecrementIgnoreCount() {
> - uint32_t ignore = m_options.GetIgnoreCount();
> + uint32_t ignore = m_options_up->GetIgnoreCount();
> if (ignore != 0)
> - m_options.SetIgnoreCount(ignore - 1);
> + m_options_up->SetIgnoreCount(ignore - 1);
> }
>
> uint32_t Breakpoint::GetIgnoreCount() const {
> - return m_options.GetIgnoreCount();
> + return m_options_up->GetIgnoreCount();
> }
>
> bool Breakpoint::IgnoreCountShouldStop() {
> @@ -160,79 +270,81 @@ bool Breakpoint::IgnoreCountShouldStop()
>
> uint32_t Breakpoint::GetHitCount() const { return m_hit_count; }
>
> -bool Breakpoint::IsOneShot() const { return m_options.IsOneShot(); }
> +bool Breakpoint::IsOneShot() const { return m_options_up->IsOneShot(); }
>
> -void Breakpoint::SetOneShot(bool one_shot) {
> m_options.SetOneShot(one_shot); }
> +void Breakpoint::SetOneShot(bool one_shot) {
> + m_options_up->SetOneShot(one_shot);
> +}
>
> void Breakpoint::SetThreadID(lldb::tid_t thread_id) {
> - if (m_options.GetThreadSpec()->GetTID() == thread_id)
> + if (m_options_up->GetThreadSpec()->GetTID() == thread_id)
> return;
>
> - m_options.GetThreadSpec()->SetTID(thread_id);
> + m_options_up->GetThreadSpec()->SetTID(thread_id);
> SendBreakpointChangedEvent(eBreakpointEventTypeThreadChanged);
> }
>
> lldb::tid_t Breakpoint::GetThreadID() const {
> - if (m_options.GetThreadSpecNoCreate() == nullptr)
> + if (m_options_up->GetThreadSpecNoCreate() == nullptr)
> return LLDB_INVALID_THREAD_ID;
> else
> - return m_options.GetThreadSpecNoCreate()->GetTID();
> + return m_options_up->GetThreadSpecNoCreate()->GetTID();
> }
>
> void Breakpoint::SetThreadIndex(uint32_t index) {
> - if (m_options.GetThreadSpec()->GetIndex() == index)
> + if (m_options_up->GetThreadSpec()->GetIndex() == index)
> return;
>
> - m_options.GetThreadSpec()->SetIndex(index);
> + m_options_up->GetThreadSpec()->SetIndex(index);
> SendBreakpointChangedEvent(eBreakpointEventTypeThreadChanged);
> }
>
> uint32_t Breakpoint::GetThreadIndex() const {
> - if (m_options.GetThreadSpecNoCreate() == nullptr)
> + if (m_options_up->GetThreadSpecNoCreate() == nullptr)
> return 0;
> else
> - return m_options.GetThreadSpecNoCreate()->GetIndex();
> + return m_options_up->GetThreadSpecNoCreate()->GetIndex();
> }
>
> void Breakpoint::SetThreadName(const char *thread_name) {
> - if (m_options.GetThreadSpec()->GetName() != nullptr &&
> - ::strcmp(m_options.GetThreadSpec()->GetName(), thread_name) == 0)
> + if (m_options_up->GetThreadSpec()->GetName() != nullptr &&
> + ::strcmp(m_options_up->GetThreadSpec()->GetName(), thread_name) ==
> 0)
> return;
>
Good opportunity to use a StringRef (for both the parameter as well as
ThreadSpec::GetName())
>
> - m_options.GetThreadSpec()->SetName(thread_name);
> + m_options_up->GetThreadSpec()->SetName(thread_name);
> SendBreakpointChangedEvent(eBreakpointEventTypeThreadChanged);
> }
>
> const char *Breakpoint::GetThreadName() const {
> - if (m_options.GetThreadSpecNoCreate() == nullptr)
> + if (m_options_up->GetThreadSpecNoCreate() == nullptr)
> return nullptr;
> else
> - return m_options.GetThreadSpecNoCreate()->GetName();
> + return m_options_up->GetThreadSpecNoCreate()->GetName();
> }
>
StringRef.
>
> void Breakpoint::SetQueueName(const char *queue_name) {
>
StringRef.
> - if (m_options.GetThreadSpec()->GetQueueName() != nullptr &&
> - ::strcmp(m_options.GetThreadSpec()->GetQueueName(), queue_name) ==
> 0)
> + if (m_options_up->GetThreadSpec()->GetQueueName() != nullptr &&
> + ::strcmp(m_options_up->GetThreadSpec()->GetQueueName(), queue_name)
> == 0)
> return;
>
> - m_options.GetThreadSpec()->SetQueueName(queue_name);
> + m_options_up->GetThreadSpec()->SetQueueName(queue_name);
> SendBreakpointChangedEvent(eBreakpointEventTypeThreadChanged);
> }
>
> const char *Breakpoint::GetQueueName() const {
>
StringRef
>
> - if (m_options.GetThreadSpecNoCreate() == nullptr)
> + if (m_options_up->GetThreadSpecNoCreate() == nullptr)
> return nullptr;
> else
> - return m_options.GetThreadSpecNoCreate()->GetQueueName();
> + return m_options_up->GetThreadSpecNoCreate()->GetQueueName();
> }
>
> void Breakpoint::SetCondition(const char *condition) {
>
StringRef.
> - m_options.SetCondition(condition);
> + m_options_up->SetCondition(condition);
> SendBreakpointChangedEvent(eBreakpointEventTypeConditionChanged);
> }
>
> const char *Breakpoint::GetConditionText() const {
> - return m_options.GetConditionText();
> + return m_options_up->GetConditionText();
> }
>
StringRef.
>
> // This function is used when "baton" doesn't need to be freed
> @@ -240,7 +352,8 @@ void Breakpoint::SetCallback(BreakpointH
> bool is_synchronous) {
> // The default "Baton" class will keep a copy of "baton" and won't free
> // or delete it when it goes goes out of scope.
> - m_options.SetCallback(callback, BatonSP(new Baton(baton)),
> is_synchronous);
> + m_options_up->SetCallback(callback, BatonSP(new Baton(baton)),
> + is_synchronous);
>
> SendBreakpointChangedEvent(eBreakpointEventTypeCommandChanged);
> }
> @@ -250,17 +363,17 @@ void Breakpoint::SetCallback(BreakpointH
> void Breakpoint::SetCallback(BreakpointHitCallback callback,
> const BatonSP &callback_baton_sp,
> bool is_synchronous) {
> - m_options.SetCallback(callback, callback_baton_sp, is_synchronous);
> + m_options_up->SetCallback(callback, callback_baton_sp, is_synchronous);
> }
>
> -void Breakpoint::ClearCallback() { m_options.ClearCallback(); }
> +void Breakpoint::ClearCallback() { m_options_up->ClearCallback(); }
>
> bool Breakpoint::InvokeCallback(StoppointCallbackContext *context,
> break_id_t bp_loc_id) {
> - return m_options.InvokeCallback(context, GetID(), bp_loc_id);
> + return m_options_up->InvokeCallback(context, GetID(), bp_loc_id);
> }
>
> -BreakpointOptions *Breakpoint::GetOptions() { return &m_options; }
> +BreakpointOptions *Breakpoint::GetOptions() { return m_options_up.get(); }
>
> void Breakpoint::ResolveBreakpoint() {
> if (m_resolver_sp)
>
> Modified: lldb/trunk/source/Breakpoint/BreakpointOptions.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Breakpoint/BreakpointOptions.cpp?rev=281273&r1=281272&r2=281273&view=diff
>
> ==============================================================================
> --- lldb/trunk/source/Breakpoint/BreakpointOptions.cpp (original)
> +++ lldb/trunk/source/Breakpoint/BreakpointOptions.cpp Mon Sep 12 18:10:56
> 2016
> @@ -17,6 +17,8 @@
> #include "lldb/Core/Stream.h"
> #include "lldb/Core/StringList.h"
> #include "lldb/Core/Value.h"
> +#include "lldb/Interpreter/CommandInterpreter.h"
> +#include "lldb/Interpreter/CommandReturnObject.h"
> #include "lldb/Target/Process.h"
> #include "lldb/Target/Target.h"
> #include "lldb/Target/ThreadSpec.h"
> @@ -24,6 +26,71 @@
> using namespace lldb;
> using namespace lldb_private;
>
> +const char *BreakpointOptions::CommandData::g_option_names
> + [BreakpointOptions::CommandData::OptionNames::LastOptionName]{
> + "UserSource", "ScriptSource", "StopOnError"};
> +
> +StructuredData::ObjectSP
> +BreakpointOptions::CommandData::SerializeToStructuredData() {
> + size_t num_strings = user_source.GetSize();
> + if (num_strings == 0 && script_source.empty()) {
> + // We shouldn't serialize commands if there aren't any, return an
> empty sp
> + // to indicate this.
> + return StructuredData::ObjectSP();
> + }
> +
> + StructuredData::DictionarySP options_dict_sp(
> + new StructuredData::Dictionary());
> + options_dict_sp->AddBooleanItem(GetKey(OptionNames::StopOnError),
> + stop_on_error);
> +
> + StructuredData::ArraySP user_source_sp(new StructuredData::Array());
> + if (num_strings > 0) {
>
Is this necessary? The loop just won't do anything if it's equal to 0.
> + for (size_t i = 0; i < num_strings; i++) {
> + StructuredData::StringSP item_sp(
> + new StructuredData::String(user_source[i]));
> + user_source_sp->AddItem(item_sp);
> + options_dict_sp->AddItem(GetKey(OptionNames::UserSource),
> user_source_sp);
> + }
> + }
> +
> + if (!script_source.empty()) {
> + StructuredData::StringSP item_sp(new
> StructuredData::String(script_source));
> + options_dict_sp->AddItem(GetKey(OptionNames::ScriptSource),
> user_source_sp);
> + }
> + return options_dict_sp;
> +}
> +
> +BreakpointOptions::CommandData *
> +BreakpointOptions::CommandData::CreateFromStructuredData(
> + StructuredData::Dictionary &options_dict, Error &error) {
> + std::string script_source;
> + CommandData *data = new CommandData();
> + bool success = options_dict.GetValueForKeyAsBoolean(
> + GetKey(OptionNames::StopOnError), data->stop_on_error);
> +
> + success = options_dict.GetValueForKeyAsString(
> + GetKey(OptionNames::ScriptSource), data->script_source);
> +
> + StructuredData::Array *user_source;
> + success =
> options_dict.GetValueForKeyAsArray(GetKey(OptionNames::UserSource),
> + user_source);
> + if (success) {
>
Early return.
> + size_t num_elems = user_source->GetSize();
> + for (size_t i = 0; i < num_elems; i++) {
> + std::string elem_string;
> + success = user_source->GetItemAtIndexAsString(i, elem_string);
> + if (success)
> + data->user_source.AppendString(elem_string);
> + }
> + }
> + return data;
> +}
> +
> +const char *BreakpointOptions::g_option_names
> + [BreakpointOptions::OptionNames::LastOptionName]{
> + "ConditionText", "IgnoreCount", "EnabledState", "OneShotState"};
> +
> bool BreakpointOptions::NullCallback(void *baton,
> StoppointCallbackContext *context,
> lldb::user_id_t break_id,
> @@ -36,15 +103,25 @@ bool BreakpointOptions::NullCallback(voi
> //----------------------------------------------------------------------
> BreakpointOptions::BreakpointOptions()
> : m_callback(BreakpointOptions::NullCallback), m_callback_baton_sp(),
> - m_callback_is_synchronous(false), m_enabled(true),
> m_one_shot(false),
> - m_ignore_count(0), m_thread_spec_ap(), m_condition_text(),
> - m_condition_text_hash(0) {}
> + m_baton_is_command_baton(false), m_callback_is_synchronous(false),
> + m_enabled(true), m_one_shot(false), m_ignore_count(0),
> m_thread_spec_ap(),
> + m_condition_text(), m_condition_text_hash(0) {}
> +
> +BreakpointOptions::BreakpointOptions(const char *condition, bool enabled,
> + int32_t ignore, bool one_shot)
> + : m_callback(nullptr), m_baton_is_command_baton(false),
> + m_callback_is_synchronous(false), m_enabled(enabled),
> + m_one_shot(one_shot), m_ignore_count(ignore),
> m_condition_text(condition),
> + m_condition_text_hash(0)
> +
> +{}
>
> //----------------------------------------------------------------------
> // BreakpointOptions copy constructor
> //----------------------------------------------------------------------
> BreakpointOptions::BreakpointOptions(const BreakpointOptions &rhs)
> : m_callback(rhs.m_callback),
> m_callback_baton_sp(rhs.m_callback_baton_sp),
> + m_baton_is_command_baton(rhs.m_baton_is_command_baton),
> m_callback_is_synchronous(rhs.m_callback_is_synchronous),
> m_enabled(rhs.m_enabled), m_one_shot(rhs.m_one_shot),
> m_ignore_count(rhs.m_ignore_count), m_thread_spec_ap() {
> @@ -61,6 +138,7 @@ const BreakpointOptions &BreakpointOptio
> operator=(const BreakpointOptions &rhs) {
> m_callback = rhs.m_callback;
> m_callback_baton_sp = rhs.m_callback_baton_sp;
> + m_baton_is_command_baton = rhs.m_baton_is_command_baton;
> m_callback_is_synchronous = rhs.m_callback_is_synchronous;
> m_enabled = rhs.m_enabled;
> m_one_shot = rhs.m_one_shot;
> @@ -91,21 +169,109 @@ BreakpointOptions::CopyOptionsNoCallback
> //----------------------------------------------------------------------
> BreakpointOptions::~BreakpointOptions() = default;
>
> +BreakpointOptions *BreakpointOptions::CreateFromStructuredData(
> + StructuredData::Dictionary &options_dict, Error &error) {
> + bool enabled = true;
> + bool one_shot = false;
> + int32_t ignore_count = 0;
> + std::string condition_text;
> +
> + bool success = options_dict.GetValueForKeyAsBoolean(
> + GetKey(OptionNames::EnabledState), enabled);
> + if (!success) {
> + error.SetErrorStringWithFormat("%s key is not a boolean.",
> + GetKey(OptionNames::EnabledState));
> + return nullptr;
> + }
> +
> + success = options_dict.GetValueForKeyAsBoolean(
> + GetKey(OptionNames::OneShotState), one_shot);
> + if (!success) {
> + error.SetErrorStringWithFormat("%s key is not a boolean.",
> + GetKey(OptionNames::OneShotState));
> + return nullptr;
> + }
> + success = options_dict.GetValueForKeyAsInteger(
> + GetKey(OptionNames::IgnoreCount), ignore_count);
> + if (!success) {
> + error.SetErrorStringWithFormat("%s key is not an integer.",
> + GetKey(OptionNames::IgnoreCount));
> + return nullptr;
> + }
> +
> + BreakpointOptions::CommandData *cmd_data = nullptr;
> + StructuredData::Dictionary *cmds_dict;
> + success = options_dict.GetValueForKeyAsDictionary(
> + CommandData::GetSerializationKey(), cmds_dict);
> + if (success && cmds_dict) {
> + Error cmds_error;
> + cmd_data = CommandData::CreateFromStructuredData(*cmds_dict,
> cmds_error);
> + if (cmds_error.Fail()) {
> + error.SetErrorStringWithFormat(
> + "Failed to deserialize breakpoint command options: %s.",
> + cmds_error.AsCString());
> + return nullptr;
> + }
> + }
> +
> + BreakpointOptions *bp_options = new BreakpointOptions(
> + condition_text.c_str(), enabled, ignore_count, one_shot);
> + if (cmd_data)
> + bp_options->SetCommandDataCallback(cmd_data);
> + return bp_options;
> +}
>
This should return a unique_ptr.
> +
> +StructuredData::ObjectSP BreakpointOptions::SerializeToStructuredData() {
> + StructuredData::DictionarySP options_dict_sp(
> + new StructuredData::Dictionary());
> + options_dict_sp->AddBooleanItem(GetKey(OptionNames::EnabledState),
> m_enabled);
> + options_dict_sp->AddBooleanItem(GetKey(OptionNames::OneShotState),
> + m_one_shot);
> + options_dict_sp->AddIntegerItem(GetKey(OptionNames::IgnoreCount),
> + m_ignore_count);
> + options_dict_sp->AddStringItem(GetKey(OptionNames::ConditionText),
> + m_condition_text);
> + if (m_baton_is_command_baton) {
> + CommandData *cmd_data =
> + static_cast<CommandData *>(m_callback_baton_sp->m_data);
> + StructuredData::ObjectSP commands_sp =
> + cmd_data->SerializeToStructuredData();
> + if (commands_sp) {
> + options_dict_sp->AddItem(
> + BreakpointOptions::CommandData::GetSerializationKey(),
> commands_sp);
> + }
> + }
> + // FIXME: Need to serialize thread filter...
> + return options_dict_sp;
> +}
> +
> //------------------------------------------------------------------
> // Callbacks
> //------------------------------------------------------------------
> void BreakpointOptions::SetCallback(BreakpointHitCallback callback,
> - const BatonSP &callback_baton_sp,
> + const lldb::BatonSP
> &callback_baton_sp,
> bool callback_is_synchronous) {
> m_callback_is_synchronous = callback_is_synchronous;
> m_callback = callback;
> m_callback_baton_sp = callback_baton_sp;
> + m_baton_is_command_baton = false;
> +}
> +
> +void BreakpointOptions::SetCallback(
> + BreakpointHitCallback callback,
> + const BreakpointOptions::CommandBatonSP &callback_baton_sp,
> + bool callback_is_synchronous) {
> + m_callback_is_synchronous = callback_is_synchronous;
> + m_callback = callback;
> + m_callback_baton_sp = callback_baton_sp;
> + m_baton_is_command_baton = true;
> }
>
> void BreakpointOptions::ClearCallback() {
> m_callback = BreakpointOptions::NullCallback;
> m_callback_is_synchronous = false;
> m_callback_baton_sp.reset();
> + m_baton_is_command_baton = false;
> }
>
> Baton *BreakpointOptions::GetBaton() { return m_callback_baton_sp.get(); }
> @@ -239,3 +405,49 @@ void BreakpointOptions::CommandBaton::Ge
> s->IndentLess();
> s->IndentLess();
> }
> +
> +void BreakpointOptions::SetCommandDataCallback(CommandData *cmd_data) {
> + CommandBatonSP baton_sp(new CommandBaton(cmd_data));
> + SetCallback(BreakpointOptions::BreakpointOptionsCallbackFunction,
> baton_sp);
> +}
> +
> +bool BreakpointOptions::BreakpointOptionsCallbackFunction(
> + void *baton, StoppointCallbackContext *context, lldb::user_id_t
> break_id,
> + lldb::user_id_t break_loc_id) {
> + bool ret_value = true;
> + if (baton == nullptr)
> + return true;
> +
> + CommandData *data = (CommandData *)baton;
> + StringList &commands = data->user_source;
> +
> + if (commands.GetSize() > 0) {
> + ExecutionContext exe_ctx(context->exe_ctx_ref);
> + Target *target = exe_ctx.GetTargetPtr();
> + if (target) {
> + CommandReturnObject result;
> + Debugger &debugger = target->GetDebugger();
> + // Rig up the results secondary output stream to the debugger's, so
> the
> + // output will come out synchronously
> + // if the debugger is set up that way.
> +
> + StreamSP output_stream(debugger.GetAsyncOutputStream());
> + StreamSP error_stream(debugger.GetAsyncErrorStream());
> + result.SetImmediateOutputStream(output_stream);
> + result.SetImmediateErrorStream(error_stream);
> +
> + CommandInterpreterRunOptions options;
> + options.SetStopOnContinue(true);
> + options.SetStopOnError(data->stop_on_error);
> + options.SetEchoCommands(true);
> + options.SetPrintResults(true);
> + options.SetAddToHistory(false);
> +
> + debugger.GetCommandInterpreter().HandleCommands(commands, &exe_ctx,
> + options, result);
> + result.GetImmediateOutputStream()->Flush();
> + result.GetImmediateErrorStream()->Flush();
> + }
> + }
> + return ret_value;
> +}
>
> Modified: lldb/trunk/source/Breakpoint/BreakpointResolver.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Breakpoint/BreakpointResolver.cpp?rev=281273&r1=281272&r2=281273&view=diff
>
> ==============================================================================
> --- lldb/trunk/source/Breakpoint/BreakpointResolver.cpp (original)
> +++ lldb/trunk/source/Breakpoint/BreakpointResolver.cpp Mon Sep 12
> 18:10:56 2016
> @@ -15,6 +15,12 @@
> // Project includes
> #include "lldb/Breakpoint/Breakpoint.h"
> #include "lldb/Breakpoint/BreakpointLocation.h"
> +// Have to include the other breakpoint resolver types here so the static
> create
> +// from StructuredData can call them.
> +#include "lldb/Breakpoint/BreakpointResolverAddress.h"
> +#include "lldb/Breakpoint/BreakpointResolverFileLine.h"
> +#include "lldb/Breakpoint/BreakpointResolverFileRegex.h"
> +#include "lldb/Breakpoint/BreakpointResolverName.h"
> #include "lldb/Core/Address.h"
> #include "lldb/Core/Log.h"
> #include "lldb/Core/ModuleList.h"
> @@ -32,6 +38,32 @@ using namespace lldb;
> //----------------------------------------------------------------------
> // BreakpointResolver:
> //----------------------------------------------------------------------
> +const char *BreakpointResolver::g_ty_to_name[] = {"FileAndLine",
> "Address",
> + "SymbolName",
> "SourceRegex",
> + "Exception",
> "Unknown"};
> +
> +const char *BreakpointResolver::g_option_names
> + [BreakpointResolver::OptionNames::LastOptionName] = {
> + "AddressOffset", "Exact", "FileName", "Inlines",
> "Language",
> + "LineNumber", "ModuleName", "NameMask", "Offset", "Regex",
> + "SectionName", "SkipPrologue", "SymbolNames"};
> +
> +const char *BreakpointResolver::ResolverTyToName(enum ResolverTy type) {
> + if (type > LastKnownResolverType)
> + return g_ty_to_name[UnknownResolver];
> +
> + return g_ty_to_name[type];
> +}
> +
> +BreakpointResolver::ResolverTy
> +BreakpointResolver::NameToResolverTy(const char *name) {
>
+ for (size_t i = 0; i < LastKnownResolverType; i++) {
> + if (strcmp(name, g_ty_to_name[i]) == 0)
>
Function parameter should be StringRef so we can use operator==.
+ return (ResolverTy)i;
> + }
> + return UnknownResolver;
> +}
> +
> BreakpointResolver::BreakpointResolver(Breakpoint *bkpt,
> const unsigned char resolverTy,
> lldb::addr_t offset)
> @@ -39,6 +71,98 @@ BreakpointResolver::BreakpointResolver(B
>
> BreakpointResolver::~BreakpointResolver() {}
>
> +BreakpointResolverSP BreakpointResolver::CreateFromStructuredData(
> + StructuredData::Dictionary &resolver_dict, Error &error) {
>
const dictionary
> + BreakpointResolverSP result_sp;
> + if (!resolver_dict.IsValid()) {
> + error.SetErrorString("Can't deserialize from an invalid data
> object.");
> + return result_sp;
> + }
> +
> + std::string subclass_name;
> +
> + bool success = resolver_dict.GetValueForKeyAsString(
> + GetSerializationSubclassKey(), subclass_name);
> +
> + if (!success) {
> + error.SetErrorStringWithFormat(
> + "Resolver data missing subclass resolver key");
> + return result_sp;
> + }
> +
> + ResolverTy resolver_type = NameToResolverTy(subclass_name.c_str());
> + if (resolver_type == UnknownResolver) {
> + error.SetErrorStringWithFormat("Unknown resolver type: %s.",
> + subclass_name.c_str());
> + return result_sp;
> + }
> +
> + StructuredData::Dictionary *subclass_options = nullptr;
> + success = resolver_dict.GetValueForKeyAsDictionary(
> + GetSerializationSubclassOptionsKey(), subclass_options);
> + if (!success || !subclass_options || !subclass_options->IsValid()) {
> + error.SetErrorString("Resolver data missing subclass options key.");
> + return result_sp;
> + }
> +
> + lldb::addr_t offset;
> + success = subclass_options->GetValueForKeyAsInteger(
> + GetKey(OptionNames::Offset), offset);
> + if (!success) {
> + error.SetErrorString("Resolver data missing offset options key.");
> + return result_sp;
> + }
> +
> + BreakpointResolver *resolver;
> +
> + switch (resolver_type) {
> + case FileLineResolver:
> + resolver = BreakpointResolverFileLine::CreateFromStructuredData(
> + nullptr, *subclass_options, error);
> + break;
> + case AddressResolver:
> + resolver = BreakpointResolverAddress::CreateFromStructuredData(
> + nullptr, *subclass_options, error);
> + break;
> + case NameResolver:
> + resolver = BreakpointResolverName::CreateFromStructuredData(
> + nullptr, *subclass_options, error);
> + break;
> + case FileRegexResolver:
> + resolver = BreakpointResolverFileRegex::CreateFromStructuredData(
> + nullptr, *subclass_options, error);
> + break;
> + case ExceptionResolver:
> + error.SetErrorString("Exception resolvers are hard.");
> + break;
> + default:
> + llvm_unreachable("Should never get an unresolvable resolver type.");
> + }
> +
> + if (!error.Success()) {
> + return result_sp;
> + } else {
> + // Add on the global offset option:
> + resolver->SetOffset(offset);
> + return BreakpointResolverSP(resolver);
> + }
> +}
> +
> +StructuredData::DictionarySP BreakpointResolver::WrapOptionsDict(
> + StructuredData::DictionarySP options_dict_sp) {
> + if (!options_dict_sp || !options_dict_sp->IsValid())
> + return StructuredData::DictionarySP();
> +
> + StructuredData::DictionarySP type_dict_sp(new
> StructuredData::Dictionary());
> + type_dict_sp->AddStringItem(GetSerializationSubclassKey(),
> GetResolverName());
> + type_dict_sp->AddItem(GetSerializationSubclassOptionsKey(),
> options_dict_sp);
> +
> + // Add the m_offset to the dictionary:
> + options_dict_sp->AddIntegerItem(GetKey(OptionNames::Offset), m_offset);
> +
> + return type_dict_sp;
> +}
> +
> void BreakpointResolver::SetBreakpoint(Breakpoint *bkpt) {
> m_breakpoint = bkpt;
> }
>
> Modified: lldb/trunk/source/Breakpoint/BreakpointResolverAddress.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Breakpoint/BreakpointResolverAddress.cpp?rev=281273&r1=281272&r2=281273&view=diff
>
> ==============================================================================
> --- lldb/trunk/source/Breakpoint/BreakpointResolverAddress.cpp (original)
> +++ lldb/trunk/source/Breakpoint/BreakpointResolverAddress.cpp Mon Sep 12
> 18:10:56 2016
> @@ -17,6 +17,7 @@
> #include "lldb/Breakpoint/BreakpointLocation.h"
> #include "lldb/Core/Log.h"
> #include "lldb/Core/Module.h"
> +#include "lldb/Core/Section.h"
> #include "lldb/Core/StreamString.h"
> #include "lldb/Target/Process.h"
> #include "lldb/Target/Target.h"
> @@ -41,6 +42,62 @@ BreakpointResolverAddress::BreakpointRes
>
> BreakpointResolverAddress::~BreakpointResolverAddress() {}
>
> +BreakpointResolver *BreakpointResolverAddress::CreateFromStructuredData(
> + Breakpoint *bkpt, StructuredData::Dictionary &options_dict, Error
> &error) {
> + std::string module_name;
> + lldb::addr_t addr_offset;
> + FileSpec module_filespec;
> + bool success;
> +
> + success = options_dict.GetValueForKeyAsInteger(
> + GetKey(OptionNames::AddressOffset), addr_offset);
> + if (!success) {
> + error.SetErrorString("BRFL::CFSD: Couldn't find address offset
> entry.");
> + return nullptr;
> + }
> + Address address(addr_offset);
> +
> + success = options_dict.HasKey(GetKey(OptionNames::ModuleName));
> + if (success) {
> + success = options_dict.GetValueForKeyAsString(
> + GetKey(OptionNames::ModuleName), module_name);
> + if (!success) {
> + error.SetErrorString("BRA::CFSD: Couldn't read module name entry.");
> + return nullptr;
> + }
> + module_filespec.SetFile(module_name.c_str(), false);
> + }
> + return new BreakpointResolverAddress(bkpt, address, module_filespec);
> +}
> +
> +StructuredData::ObjectSP
> +BreakpointResolverAddress::SerializeToStructuredData() {
> + StructuredData::DictionarySP options_dict_sp(
> + new StructuredData::Dictionary());
> + SectionSP section_sp = m_addr.GetSection();
> + if (section_sp) {
> + ModuleSP module_sp = section_sp->GetModule();
> + ConstString module_name;
> + if (module_sp)
> + module_name.SetCString(module_name.GetCString());
> +
> + options_dict_sp->AddStringItem(GetKey(OptionNames::ModuleName),
> + module_name.GetCString());
> + options_dict_sp->AddIntegerItem(GetKey(OptionNames::AddressOffset),
> + m_addr.GetOffset());
> + } else {
> + options_dict_sp->AddIntegerItem(GetKey(OptionNames::AddressOffset),
> + m_addr.GetOffset());
> + if (m_module_filespec) {
> + options_dict_sp->AddStringItem(GetKey(OptionNames::ModuleName),
> + m_module_filespec.GetPath());
> + }
> + }
> +
> + return WrapOptionsDict(options_dict_sp);
> + return StructuredData::ObjectSP();
> +}
> +
> void BreakpointResolverAddress::ResolveBreakpoint(SearchFilter &filter) {
> // If the address is not section relative, then we should not try to
> // re-resolve it, it is just some
>
> Modified: lldb/trunk/source/Breakpoint/BreakpointResolverFileLine.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Breakpoint/BreakpointResolverFileLine.cpp?rev=281273&r1=281272&r2=281273&view=diff
>
> ==============================================================================
> --- lldb/trunk/source/Breakpoint/BreakpointResolverFileLine.cpp (original)
> +++ lldb/trunk/source/Breakpoint/BreakpointResolverFileLine.cpp Mon Sep 12
> 18:10:56 2016
> @@ -36,6 +36,77 @@ BreakpointResolverFileLine::BreakpointRe
>
> BreakpointResolverFileLine::~BreakpointResolverFileLine() {}
>
> +BreakpointResolver *BreakpointResolverFileLine::CreateFromStructuredData(
> + Breakpoint *bkpt, StructuredData::Dictionary &options_dict, Error
> &error) {
> + std::string filename;
> + uint32_t line_no;
> + bool check_inlines;
> + bool skip_prologue;
> + bool exact_match;
> + bool success;
> +
> + lldb::addr_t offset = 0;
> +
> + success =
> options_dict.GetValueForKeyAsString(GetKey(OptionNames::FileName),
> + filename);
> + if (!success) {
> + error.SetErrorString("BRFL::CFSD: Couldn't find filename entry.");
> + return nullptr;
> + }
> +
> + success = options_dict.GetValueForKeyAsInteger(
> + GetKey(OptionNames::LineNumber), line_no);
> + if (!success) {
> + error.SetErrorString("BRFL::CFSD: Couldn't find line number entry.");
> + return nullptr;
> + }
> +
> + success =
> options_dict.GetValueForKeyAsBoolean(GetKey(OptionNames::Inlines),
> + check_inlines);
> + if (!success) {
> + error.SetErrorString("BRFL::CFSD: Couldn't find check inlines
> entry.");
> + return nullptr;
> + }
> +
> + success = options_dict.GetValueForKeyAsBoolean(
> + GetKey(OptionNames::SkipPrologue), skip_prologue);
> + if (!success) {
> + error.SetErrorString("BRFL::CFSD: Couldn't find skip prologue
> entry.");
> + return nullptr;
> + }
> +
> + success = options_dict.GetValueForKeyAsBoolean(
> + GetKey(OptionNames::ExactMatch), exact_match);
> + if (!success) {
> + error.SetErrorString("BRFL::CFSD: Couldn't find exact match entry.");
> + return nullptr;
> + }
> +
> + FileSpec file_spec(filename.c_str(), false);
> +
> + return new BreakpointResolverFileLine(bkpt, file_spec, line_no, offset,
> + check_inlines, skip_prologue,
> + exact_match);
> +}
> +
> +StructuredData::ObjectSP
> +BreakpointResolverFileLine::SerializeToStructuredData() {
> + StructuredData::DictionarySP options_dict_sp(
> + new StructuredData::Dictionary());
> +
> + options_dict_sp->AddStringItem(GetKey(OptionNames::FileName),
> + m_file_spec.GetPath());
> + options_dict_sp->AddIntegerItem(GetKey(OptionNames::LineNumber),
> + m_line_number);
> + options_dict_sp->AddBooleanItem(GetKey(OptionNames::Inlines),
> m_inlines);
> + options_dict_sp->AddBooleanItem(GetKey(OptionNames::SkipPrologue),
> + m_skip_prologue);
> + options_dict_sp->AddBooleanItem(GetKey(OptionNames::ExactMatch),
> + m_exact_match);
> +
> + return WrapOptionsDict(options_dict_sp);
> +}
> +
> Searcher::CallbackReturn
> BreakpointResolverFileLine::SearchCallback(SearchFilter &filter,
> SymbolContext &context,
>
> Modified: lldb/trunk/source/Breakpoint/BreakpointResolverFileRegex.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Breakpoint/BreakpointResolverFileRegex.cpp?rev=281273&r1=281272&r2=281273&view=diff
>
> ==============================================================================
> --- lldb/trunk/source/Breakpoint/BreakpointResolverFileRegex.cpp (original)
> +++ lldb/trunk/source/Breakpoint/BreakpointResolverFileRegex.cpp Mon Sep
> 12 18:10:56 2016
> @@ -36,6 +36,70 @@ BreakpointResolverFileRegex::BreakpointR
>
> BreakpointResolverFileRegex::~BreakpointResolverFileRegex() {}
>
> +BreakpointResolver *BreakpointResolverFileRegex::CreateFromStructuredData(
> + Breakpoint *bkpt, StructuredData::Dictionary &options_dict, Error
> &error) {
> + bool success;
> +
> + std::string regex_string;
> + success = options_dict.GetValueForKeyAsString(
> + GetKey(OptionNames::RegexString), regex_string);
> + if (!success) {
> + error.SetErrorString("BRFR::CFSD: Couldn't find regex entry.");
> + return nullptr;
> + }
> + RegularExpression regex(regex_string.c_str());
> +
> + bool exact_match;
> + success = options_dict.GetValueForKeyAsBoolean(
> + GetKey(OptionNames::ExactMatch), exact_match);
> + if (!success) {
> + error.SetErrorString("BRFL::CFSD: Couldn't find exact match entry.");
> + return nullptr;
> + }
> +
> + // The names array is optional:
> + std::unordered_set<std::string> names_set;
> + StructuredData::Array *names_array;
> + success = options_dict.GetValueForKeyAsArray(
> + GetKey(OptionNames::SymbolNameArray), names_array);
> + if (success && names_array) {
> + size_t num_names = names_array->GetSize();
> + for (size_t i = 0; i < num_names; i++) {
> + std::string name;
> + success = names_array->GetItemAtIndexAsString(i, name);
> + if (!success) {
> + error.SetErrorStringWithFormat(
> + "BRFR::CFSD: Malformed element %zu in the names array.", i);
> + return nullptr;
> + }
> + names_set.insert(name);
> + }
> + }
> +
> + return new BreakpointResolverFileRegex(bkpt, regex, names_set,
> exact_match);
> +}
> +
> +StructuredData::ObjectSP
> +BreakpointResolverFileRegex::SerializeToStructuredData() {<
Various comments inline.
Also it would be nice if we could move towards submitting tests at the same
time we submit functionality. I'm not a fan of submitting tests at a later
date, and I believe it's also against LLVM guidelines.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/lldb-commits/attachments/20160912/8f39b8e4/attachment-0001.html>
More information about the lldb-commits
mailing list