[Lldb-commits] [lldb] r281273 - This is the main part of a change to add breakpoint save and restore to lldb.

Jim Ingham via lldb-commits lldb-commits at lists.llvm.org
Mon Sep 12 16:10:57 PDT 2016


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);
+
+    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;
+
   //------------------------------------------------------------------
   // 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);
 
   virtual ~BreakpointOptions();
 
+  static BreakpointOptions *
+  CreateFromStructuredData(StructuredData::Dictionary &data_dict, Error &error);
+
+  virtual StructuredData::ObjectSP SerializeToStructuredData();
+
+  static const char *GetSerializationKey() { return "BKPTOptions"; }
+
   //------------------------------------------------------------------
   // 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 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"; }
+
+  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 &regex,
       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);
+
   // 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()) {
+        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);
 };
 
 } // 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;
+
+  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()));
+  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(); }
 
 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;
 
-  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();
 }
 
 void Breakpoint::SetQueueName(const char *queue_name) {
-  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 {
-  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) {
-  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();
 }
 
 // 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) {
+    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) {
+    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;
+}
+
+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)
+      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) {
+  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() {
+  StructuredData::DictionarySP options_dict_sp(
+      new StructuredData::Dictionary());
+
+  options_dict_sp->AddStringItem(GetKey(OptionNames::RegexString),
+                                 m_regex.GetText());
+  options_dict_sp->AddBooleanItem(GetKey(OptionNames::ExactMatch),
+                                  m_exact_match);
+  if (!m_function_names.empty()) {
+    StructuredData::ArraySP names_array_sp(new StructuredData::Array());
+    for (std::string name : m_function_names) {
+      StructuredData::StringSP item(new StructuredData::String(name));
+      names_array_sp->AddItem(item);
+    }
+    options_dict_sp->AddItem(GetKey(OptionNames::LineNumber), names_array_sp);
+  }
+
+  return WrapOptionsDict(options_dict_sp);
+}
+
 Searcher::CallbackReturn
 BreakpointResolverFileRegex::SearchCallback(SearchFilter &filter,
                                             SymbolContext &context,

Modified: lldb/trunk/source/Breakpoint/BreakpointResolverName.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Breakpoint/BreakpointResolverName.cpp?rev=281273&r1=281272&r2=281273&view=diff
==============================================================================
--- lldb/trunk/source/Breakpoint/BreakpointResolverName.cpp (original)
+++ lldb/trunk/source/Breakpoint/BreakpointResolverName.cpp Mon Sep 12 18:10:56 2016
@@ -80,19 +80,6 @@ BreakpointResolverName::BreakpointResolv
       m_match_type(Breakpoint::Regexp), m_language(language),
       m_skip_prologue(skip_prologue) {}
 
-BreakpointResolverName::BreakpointResolverName(
-    Breakpoint *bkpt, const char *class_name, const char *method,
-    Breakpoint::MatchType type, lldb::addr_t offset, bool skip_prologue)
-    : BreakpointResolver(bkpt, BreakpointResolver::NameResolver, offset),
-      m_class_name(class_name), m_regex(), m_match_type(type),
-      m_language(eLanguageTypeUnknown), m_skip_prologue(skip_prologue) {
-  Module::LookupInfo lookup;
-  lookup.SetName(ConstString(method));
-  lookup.SetLookupName(lookup.GetName());
-  lookup.SetNameTypeMask(eFunctionNameTypeMethod);
-  m_lookups.push_back(lookup);
-}
-
 BreakpointResolverName::~BreakpointResolverName() = default;
 
 BreakpointResolverName::BreakpointResolverName(
@@ -103,6 +90,132 @@ BreakpointResolverName::BreakpointResolv
       m_regex(rhs.m_regex), m_match_type(rhs.m_match_type),
       m_language(rhs.m_language), m_skip_prologue(rhs.m_skip_prologue) {}
 
+BreakpointResolver *BreakpointResolverName::CreateFromStructuredData(
+    Breakpoint *bkpt, StructuredData::Dictionary &options_dict, Error &error) {
+  LanguageType language = eLanguageTypeUnknown;
+  std::string language_name;
+  bool success = options_dict.GetValueForKeyAsString(
+      GetKey(OptionNames::LanguageName), language_name);
+  if (success) {
+    language = Language::GetLanguageTypeFromString(language_name.c_str());
+    if (language == eLanguageTypeUnknown) {
+      error.SetErrorStringWithFormat("BRN::CFSD: Unknown language: %s.",
+                                     language_name.c_str());
+      return nullptr;
+    }
+  }
+
+  lldb::addr_t offset = 0;
+  success =
+      options_dict.GetValueForKeyAsInteger(GetKey(OptionNames::Offset), offset);
+  if (!success) {
+    error.SetErrorStringWithFormat("BRN::CFSD: Missing offset entry.");
+    return nullptr;
+  }
+
+  bool skip_prologue;
+  success = options_dict.GetValueForKeyAsBoolean(
+      GetKey(OptionNames::SkipPrologue), skip_prologue);
+  if (!success) {
+    error.SetErrorStringWithFormat("BRN::CFSD: Missing Skip prologue entry.");
+    return nullptr;
+  }
+
+  std::string regex_text;
+  success = options_dict.GetValueForKeyAsString(
+      GetKey(OptionNames::RegexString), regex_text);
+  if (success) {
+    RegularExpression regex(regex_text.c_str());
+    return new BreakpointResolverName(bkpt, regex, language, offset,
+                                      skip_prologue);
+  } else {
+    StructuredData::Array *names_array;
+    success = options_dict.GetValueForKeyAsArray(
+        GetKey(OptionNames::SymbolNameArray), names_array);
+    if (!success) {
+      error.SetErrorStringWithFormat("BRN::CFSD: Missing symbol names entry.");
+      return nullptr;
+    }
+    StructuredData::Array *names_mask_array;
+    success = options_dict.GetValueForKeyAsArray(
+        GetKey(OptionNames::NameMaskArray), names_mask_array);
+    if (!success) {
+      error.SetErrorStringWithFormat(
+          "BRN::CFSD: Missing symbol names mask entry.");
+      return nullptr;
+    }
+
+    size_t num_elem = names_array->GetSize();
+    if (num_elem != names_mask_array->GetSize()) {
+      error.SetErrorString(
+          "BRN::CFSD: names and names mask arrays have different sizes.");
+      return nullptr;
+    }
+
+    if (num_elem == 0) {
+      error.SetErrorString(
+          "BRN::CFSD: no name entry in a breakpoint by name breakpoint.");
+      return nullptr;
+    }
+    std::vector<std::string> names;
+    std::vector<uint32_t> name_masks;
+    for (size_t i = 0; i < num_elem; i++) {
+      uint32_t name_mask;
+      std::string name;
+
+      success = names_array->GetItemAtIndexAsString(i, name);
+      if (!success) {
+        error.SetErrorString("BRN::CFSD: name entry is not a string.");
+        return nullptr;
+      }
+      success = names_mask_array->GetItemAtIndexAsInteger(i, name_mask);
+      if (!success) {
+        error.SetErrorString("BRN::CFSD: name mask entry is not an integer.");
+        return nullptr;
+      }
+      names.push_back(name);
+      name_masks.push_back(name_mask);
+    }
+
+    BreakpointResolverName *resolver = new BreakpointResolverName(
+        bkpt, names[0].c_str(), name_masks[0], language,
+        Breakpoint::MatchType::Exact, offset, skip_prologue);
+    for (size_t i = 1; i < num_elem; i++) {
+      resolver->AddNameLookup(ConstString(names[i]), name_masks[i]);
+    }
+    return resolver;
+  }
+}
+
+StructuredData::ObjectSP BreakpointResolverName::SerializeToStructuredData() {
+  StructuredData::DictionarySP options_dict_sp(
+      new StructuredData::Dictionary());
+
+  if (m_regex.IsValid()) {
+    options_dict_sp->AddStringItem(GetKey(OptionNames::RegexString),
+                                   m_regex.GetText());
+  } else {
+    StructuredData::ArraySP names_sp(new StructuredData::Array());
+    StructuredData::ArraySP name_masks_sp(new StructuredData::Array());
+    for (auto lookup : m_lookups) {
+      names_sp->AddItem(StructuredData::StringSP(
+          new StructuredData::String(lookup.GetName().AsCString())));
+      name_masks_sp->AddItem(StructuredData::IntegerSP(
+          new StructuredData::Integer(lookup.GetNameTypeMask())));
+    }
+    options_dict_sp->AddItem(GetKey(OptionNames::SymbolNameArray), names_sp);
+    options_dict_sp->AddItem(GetKey(OptionNames::NameMaskArray), name_masks_sp);
+  }
+  if (m_language != eLanguageTypeUnknown)
+    options_dict_sp->AddStringItem(
+        GetKey(OptionNames::LanguageName),
+        Language::GetNameForLanguageType(m_language));
+  options_dict_sp->AddBooleanItem(GetKey(OptionNames::SkipPrologue),
+                                  m_skip_prologue);
+
+  return WrapOptionsDict(options_dict_sp);
+}
+
 void BreakpointResolverName::AddNameLookup(const ConstString &name,
                                            uint32_t name_type_mask) {
   ObjCLanguage::MethodName objc_method(name.GetCString(), false);

Modified: lldb/trunk/source/Commands/CommandObjectBreakpoint.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Commands/CommandObjectBreakpoint.cpp?rev=281273&r1=281272&r2=281273&view=diff
==============================================================================
--- lldb/trunk/source/Commands/CommandObjectBreakpoint.cpp (original)
+++ lldb/trunk/source/Commands/CommandObjectBreakpoint.cpp Mon Sep 12 18:10:56 2016
@@ -523,25 +523,26 @@ protected:
 
     case eSetTypeFunctionRegexp: // Breakpoint by regular expression function
                                  // name
-    {
-      RegularExpression regexp(m_options.m_func_regexp.c_str());
-      if (!regexp.IsValid()) {
-        char err_str[1024];
-        regexp.GetErrorAsCString(err_str, sizeof(err_str));
-        result.AppendErrorWithFormat(
-            "Function name regular expression could not be compiled: \"%s\"",
-            err_str);
-        result.SetStatus(eReturnStatusFailed);
-        return false;
-      }
+      {
+        RegularExpression regexp(m_options.m_func_regexp.c_str());
+        if (!regexp.IsValid()) {
+          char err_str[1024];
+          regexp.GetErrorAsCString(err_str, sizeof(err_str));
+          result.AppendErrorWithFormat(
+              "Function name regular expression could not be compiled: \"%s\"",
+              err_str);
+          result.SetStatus(eReturnStatusFailed);
+          return false;
+        }
 
-      bp = target
-               ->CreateFuncRegexBreakpoint(
-                   &(m_options.m_modules), &(m_options.m_filenames), regexp,
-                   m_options.m_language, m_options.m_skip_prologue, internal,
-                   m_options.m_hardware)
-               .get();
-    } break;
+        bp = target
+                 ->CreateFuncRegexBreakpoint(
+                     &(m_options.m_modules), &(m_options.m_filenames), regexp,
+                     m_options.m_language, m_options.m_skip_prologue, internal,
+                     m_options.m_hardware)
+                 .get();
+      }
+      break;
     case eSetTypeSourceRegexp: // Breakpoint by regexp on source text.
     {
       const size_t num_files = m_options.m_filenames.GetSize();
@@ -2058,7 +2059,7 @@ private:
 };
 
 //-------------------------------------------------------------------------
-// CommandObjectMultiwordBreakpoint
+// CommandObjectBreakpointName
 //-------------------------------------------------------------------------
 class CommandObjectBreakpointName : public CommandObjectMultiword {
 public:
@@ -2082,6 +2083,307 @@ public:
 };
 
 //-------------------------------------------------------------------------
+// CommandObjectBreakpointRead
+//-------------------------------------------------------------------------
+#pragma mark Restore
+
+class CommandObjectBreakpointRead : public CommandObjectParsed {
+public:
+  CommandObjectBreakpointRead(CommandInterpreter &interpreter)
+      : CommandObjectParsed(interpreter, "breakpoint read",
+                            "Read and set the breakpoints previously saved to "
+                            "a file with \"breakpoint write\".  ",
+                            nullptr),
+        m_options() {
+    CommandArgumentEntry arg;
+    CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
+                                      eArgTypeBreakpointIDRange);
+    // Add the entry for the first argument for this command to the object's
+    // arguments vector.
+    m_arguments.push_back(arg);
+  }
+
+  ~CommandObjectBreakpointRead() override = default;
+
+  Options *GetOptions() override { return &m_options; }
+
+  class CommandOptions : public Options {
+  public:
+    CommandOptions() : Options() {}
+
+    ~CommandOptions() override = default;
+
+    Error SetOptionValue(uint32_t option_idx, const char *option_arg,
+                         ExecutionContext *execution_context) override {
+      Error error;
+      const int short_option = m_getopt_table[option_idx].val;
+
+      switch (short_option) {
+      case 'f':
+        m_filename.assign(option_arg);
+        break;
+      default:
+        error.SetErrorStringWithFormat("unrecognized option '%c'",
+                                       short_option);
+        break;
+      }
+
+      return error;
+    }
+
+    void OptionParsingStarting(ExecutionContext *execution_context) override {
+      m_filename.clear();
+    }
+
+    const OptionDefinition *GetDefinitions() override { return g_option_table; }
+
+    // Options table: Required for subclasses of Options.
+
+    static OptionDefinition g_option_table[];
+
+    // Instance variables to hold the values for command options.
+
+    std::string m_filename;
+  };
+
+protected:
+  bool DoExecute(Args &command, CommandReturnObject &result) override {
+    Target *target = GetSelectedOrDummyTarget();
+    if (target == nullptr) {
+      result.AppendError("Invalid target.  No existing target or breakpoints.");
+      result.SetStatus(eReturnStatusFailed);
+      return false;
+    }
+
+    std::unique_lock<std::recursive_mutex> lock;
+    target->GetBreakpointList().GetListMutex(lock);
+
+    FileSpec input_spec(m_options.m_filename, true);
+    Error error;
+    StructuredData::ObjectSP input_data_sp =
+        StructuredData::ParseJSONFromFile(input_spec, error);
+    if (!error.Success()) {
+      result.AppendErrorWithFormat("Error reading data from input file: %s.",
+                                   error.AsCString());
+      result.SetStatus(eReturnStatusFailed);
+      return false;
+    } else if (!input_data_sp || !input_data_sp->IsValid()) {
+      result.AppendErrorWithFormat("Invalid JSON from input file: %s.",
+                                   input_spec.GetPath().c_str());
+      result.SetStatus(eReturnStatusFailed);
+      return false;
+    }
+
+    StructuredData::Array *bkpt_array = input_data_sp->GetAsArray();
+    if (!bkpt_array) {
+      result.AppendErrorWithFormat(
+          "Invalid breakpoint data from input file: %s.",
+          input_spec.GetPath().c_str());
+      result.SetStatus(eReturnStatusFailed);
+      return false;
+    }
+
+    size_t num_bkpts = bkpt_array->GetSize();
+    for (size_t i = 0; i < num_bkpts; i++) {
+      StructuredData::ObjectSP bkpt_object_sp = bkpt_array->GetItemAtIndex(i);
+      // Peel off the breakpoint key, and feed the rest to the Breakpoint:
+      StructuredData::Dictionary *bkpt_dict = bkpt_object_sp->GetAsDictionary();
+      if (!bkpt_dict) {
+        result.AppendErrorWithFormat(
+            "Invalid breakpoint data for element %zu from input file: %s.", i,
+            input_spec.GetPath().c_str());
+        result.SetStatus(eReturnStatusFailed);
+        return false;
+      }
+      StructuredData::ObjectSP bkpt_data_sp =
+          bkpt_dict->GetValueForKey(Breakpoint::GetSerializationKey());
+      BreakpointSP bkpt_sp =
+          Breakpoint::CreateFromStructuredData(*target, bkpt_data_sp, error);
+      if (!error.Success()) {
+        result.AppendErrorWithFormat(
+            "Error restoring breakpoint %zu from %s: %s.", i,
+            input_spec.GetPath().c_str(), error.AsCString());
+        result.SetStatus(eReturnStatusFailed);
+      }
+    }
+    return result.Succeeded();
+  }
+
+private:
+  CommandOptions m_options;
+};
+
+#pragma mark Modify::CommandOptions
+OptionDefinition CommandObjectBreakpointRead::CommandOptions::g_option_table[] =
+    {
+        // clang-format off
+  {LLDB_OPT_SET_ALL, true, "file", 'f', OptionParser::eRequiredArgument, nullptr, nullptr, CommandCompletions::eDiskFileCompletion, eArgTypeFilename,    "The file from which to read the breakpoints."},
+  {0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr}
+        // clang-format on
+};
+
+//-------------------------------------------------------------------------
+// CommandObjectBreakpointWrite
+//-------------------------------------------------------------------------
+#pragma mark Save
+class CommandObjectBreakpointWrite : public CommandObjectParsed {
+public:
+  CommandObjectBreakpointWrite(CommandInterpreter &interpreter)
+      : CommandObjectParsed(interpreter, "breakpoint write",
+                            "Write the breakpoints listed to a file that can "
+                            "be read in with \"breakpoint read\".  "
+                            "If given no arguments, writes all breakpoints.",
+                            nullptr),
+        m_options() {
+    CommandArgumentEntry arg;
+    CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
+                                      eArgTypeBreakpointIDRange);
+    // Add the entry for the first argument for this command to the object's
+    // arguments vector.
+    m_arguments.push_back(arg);
+  }
+
+  ~CommandObjectBreakpointWrite() override = default;
+
+  Options *GetOptions() override { return &m_options; }
+
+  class CommandOptions : public Options {
+  public:
+    CommandOptions() : Options() {}
+
+    ~CommandOptions() override = default;
+
+    Error SetOptionValue(uint32_t option_idx, const char *option_arg,
+                         ExecutionContext *execution_context) override {
+      Error error;
+      const int short_option = m_getopt_table[option_idx].val;
+
+      switch (short_option) {
+      case 'f':
+        m_filename.assign(option_arg);
+        break;
+      default:
+        error.SetErrorStringWithFormat("unrecognized option '%c'",
+                                       short_option);
+        break;
+      }
+
+      return error;
+    }
+
+    void OptionParsingStarting(ExecutionContext *execution_context) override {
+      m_filename.clear();
+    }
+
+    const OptionDefinition *GetDefinitions() override { return g_option_table; }
+
+    // Options table: Required for subclasses of Options.
+
+    static OptionDefinition g_option_table[];
+
+    // Instance variables to hold the values for command options.
+
+    std::string m_filename;
+  };
+
+protected:
+  bool DoExecute(Args &command, CommandReturnObject &result) override {
+    Target *target = GetSelectedOrDummyTarget();
+    if (target == nullptr) {
+      result.AppendError("Invalid target.  No existing target or breakpoints.");
+      result.SetStatus(eReturnStatusFailed);
+      return false;
+    }
+
+    // Before we do anything else make sure we can actually write to this file:
+    StreamFile out_file(m_options.m_filename.c_str(),
+                        File::OpenOptions::eOpenOptionTruncate |
+                            File::OpenOptions::eOpenOptionWrite |
+                            File::OpenOptions::eOpenOptionCanCreate |
+                            File::OpenOptions::eOpenOptionCloseOnExec,
+                        lldb::eFilePermissionsFileDefault);
+    if (!out_file.GetFile().IsValid()) {
+      result.AppendErrorWithFormat("Unable to open output file: %s.",
+                                   m_options.m_filename.c_str());
+      result.SetStatus(eReturnStatusFailed);
+      return false;
+    }
+
+    std::unique_lock<std::recursive_mutex> lock;
+    target->GetBreakpointList().GetListMutex(lock);
+
+    StructuredData::ArraySP break_store_sp(new StructuredData::Array());
+
+    if (command.GetArgumentCount() == 0) {
+      const BreakpointList &breakpoints = target->GetBreakpointList();
+
+      size_t num_breakpoints = breakpoints.GetSize();
+      for (size_t i = 0; i < num_breakpoints; i++) {
+        Breakpoint *bp = breakpoints.GetBreakpointAtIndex(i).get();
+        StructuredData::ObjectSP bkpt_save_sp = bp->SerializeToStructuredData();
+        // If a breakpoint can't serialize it, just ignore it for now:
+        if (bkpt_save_sp)
+          break_store_sp->AddItem(bkpt_save_sp);
+      }
+    } else {
+
+      BreakpointIDList valid_bp_ids;
+
+      CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs(
+          command, target, result, &valid_bp_ids);
+
+      if (result.Succeeded()) {
+        std::unordered_set<lldb::break_id_t> processed_bkpts;
+        const size_t count = valid_bp_ids.GetSize();
+        for (size_t i = 0; i < count; ++i) {
+          BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
+          lldb::break_id_t bp_id = cur_bp_id.GetBreakpointID();
+
+          if (bp_id != LLDB_INVALID_BREAK_ID) {
+            // Only do each breakpoint once:
+            std::pair<std::unordered_set<lldb::break_id_t>::iterator, bool>
+                insert_result = processed_bkpts.insert(bp_id);
+            if (!insert_result.second)
+              continue;
+
+            Breakpoint *bp = target->GetBreakpointByID(bp_id).get();
+            StructuredData::ObjectSP bkpt_save_sp =
+                bp->SerializeToStructuredData();
+            // If the user explicitly asked to serialize a breakpoint, and we
+            // can't, then
+            // raise an error:
+            if (!bkpt_save_sp) {
+              result.AppendErrorWithFormat("Unable to serialize breakpoint %d",
+                                           bp_id);
+              result.SetStatus(eReturnStatusFailed);
+              return false;
+            }
+            break_store_sp->AddItem(bkpt_save_sp);
+          }
+        }
+      }
+    }
+
+    break_store_sp->Dump(out_file, false);
+    out_file.PutChar('\n');
+
+    return result.Succeeded();
+  }
+
+private:
+  CommandOptions m_options;
+};
+
+#pragma mark Modify::CommandOptions
+OptionDefinition
+    CommandObjectBreakpointWrite::CommandOptions::g_option_table[] = {
+        // clang-format off
+  {LLDB_OPT_SET_ALL, true, "file", 'f', OptionParser::eRequiredArgument, nullptr, nullptr, CommandCompletions::eDiskFileCompletion, eArgTypeFilename,    "The file into which to write the breakpoints."},
+  {0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr}
+        // clang-format on
+};
+
+//-------------------------------------------------------------------------
 // CommandObjectMultiwordBreakpoint
 //-------------------------------------------------------------------------
 #pragma mark MultiwordBreakpoint
@@ -2110,6 +2412,10 @@ CommandObjectMultiwordBreakpoint::Comman
       new CommandObjectBreakpointModify(interpreter));
   CommandObjectSP name_command_object(
       new CommandObjectBreakpointName(interpreter));
+  CommandObjectSP write_command_object(
+      new CommandObjectBreakpointWrite(interpreter));
+  CommandObjectSP read_command_object(
+      new CommandObjectBreakpointRead(interpreter));
 
   list_command_object->SetCommandName("breakpoint list");
   enable_command_object->SetCommandName("breakpoint enable");
@@ -2120,6 +2426,8 @@ CommandObjectMultiwordBreakpoint::Comman
   command_command_object->SetCommandName("breakpoint command");
   modify_command_object->SetCommandName("breakpoint modify");
   name_command_object->SetCommandName("breakpoint name");
+  write_command_object->SetCommandName("breakpoint write");
+  read_command_object->SetCommandName("breakpoint read");
 
   LoadSubCommand("list", list_command_object);
   LoadSubCommand("enable", enable_command_object);
@@ -2130,6 +2438,8 @@ CommandObjectMultiwordBreakpoint::Comman
   LoadSubCommand("command", command_command_object);
   LoadSubCommand("modify", modify_command_object);
   LoadSubCommand("name", name_command_object);
+  LoadSubCommand("write", write_command_object);
+  LoadSubCommand("read", read_command_object);
 }
 
 CommandObjectMultiwordBreakpoint::~CommandObjectMultiwordBreakpoint() = default;

Modified: lldb/trunk/source/Commands/CommandObjectBreakpointCommand.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Commands/CommandObjectBreakpointCommand.cpp?rev=281273&r1=281272&r2=281273&view=diff
==============================================================================
--- lldb/trunk/source/Commands/CommandObjectBreakpointCommand.cpp (original)
+++ lldb/trunk/source/Commands/CommandObjectBreakpointCommand.cpp Mon Sep 12 18:10:56 2016
@@ -215,14 +215,10 @@ are no syntax errors may indicate that a
       if (!bp_options)
         continue;
 
-      std::unique_ptr<BreakpointOptions::CommandData> data_ap(
-          new BreakpointOptions::CommandData());
-      if (data_ap) {
-        data_ap->user_source.SplitIntoLines(line.c_str(), line.size());
-        BatonSP baton_sp(
-            new BreakpointOptions::CommandBaton(data_ap.release()));
-        bp_options->SetCallback(BreakpointOptionsCallbackFunction, baton_sp);
-      }
+      BreakpointOptions::CommandData *cmd_data =
+          new BreakpointOptions::CommandData();
+      cmd_data->user_source.SplitIntoLines(line.c_str(), line.size());
+      bp_options->SetCommandDataCallback(cmd_data);
     }
   }
 
@@ -242,8 +238,8 @@ are no syntax errors may indicate that a
   SetBreakpointCommandCallback(std::vector<BreakpointOptions *> &bp_options_vec,
                                const char *oneliner) {
     for (auto bp_options : bp_options_vec) {
-      std::unique_ptr<BreakpointOptions::CommandData> data_ap(
-          new BreakpointOptions::CommandData());
+      BreakpointOptions::CommandData *cmd_data =
+          new BreakpointOptions::CommandData();
 
       // It's necessary to set both user_source and script_source to the
       // oneliner.
@@ -251,57 +247,14 @@ are no syntax errors may indicate that a
       // command list)
       // while the latter is used for Python to interpret during the actual
       // callback.
-      data_ap->user_source.AppendString(oneliner);
-      data_ap->script_source.assign(oneliner);
-      data_ap->stop_on_error = m_options.m_stop_on_error;
+      cmd_data->user_source.AppendString(oneliner);
+      cmd_data->script_source.assign(oneliner);
+      cmd_data->stop_on_error = m_options.m_stop_on_error;
 
-      BatonSP baton_sp(new BreakpointOptions::CommandBaton(data_ap.release()));
-      bp_options->SetCallback(BreakpointOptionsCallbackFunction, baton_sp);
+      bp_options->SetCommandDataCallback(cmd_data);
     }
   }
 
-  static bool 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;
-
-    BreakpointOptions::CommandData *data =
-        (BreakpointOptions::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;
-  }
-
   class CommandOptions : public Options {
   public:
     CommandOptions()

Modified: lldb/trunk/source/Core/SearchFilter.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/SearchFilter.cpp?rev=281273&r1=281272&r2=281273&view=diff
==============================================================================
--- lldb/trunk/source/Core/SearchFilter.cpp (original)
+++ lldb/trunk/source/Core/SearchFilter.cpp Mon Sep 12 18:10:56 2016
@@ -21,14 +21,37 @@
 using namespace lldb;
 using namespace lldb_private;
 
+const char *SearchFilter::g_ty_to_name[] = {"Unconstrained", "Exception",
+                                            "Module",        "Modules",
+                                            "ModulesAndCU",  "Unknown"};
+
+const char
+    *SearchFilter::g_option_names[SearchFilter::OptionNames::LastOptionName] = {
+        "ModuleList", "CUList"};
+
+const char *SearchFilter::FilterTyToName(enum FilterTy type) {
+  if (type > LastKnownFilterType)
+    return g_ty_to_name[UnknownFilter];
+
+  return g_ty_to_name[type];
+}
+
+SearchFilter::FilterTy SearchFilter::NameToFilterTy(const char *name) {
+  for (size_t i = 0; i < LastKnownFilterType; i++) {
+    if (strcmp(name, g_ty_to_name[i]) == 0)
+      return (FilterTy)i;
+  }
+  return UnknownFilter;
+}
+
 Searcher::Searcher() = default;
 
 Searcher::~Searcher() = default;
 
 void Searcher::GetDescription(Stream *s) {}
 
-SearchFilter::SearchFilter(const TargetSP &target_sp)
-    : m_target_sp(target_sp) {}
+SearchFilter::SearchFilter(const TargetSP &target_sp, unsigned char filterType)
+    : m_target_sp(target_sp), SubclassID(filterType) {}
 
 SearchFilter::SearchFilter(const SearchFilter &rhs) = default;
 
@@ -36,6 +59,65 @@ SearchFilter &SearchFilter::operator=(co
 
 SearchFilter::~SearchFilter() = default;
 
+SearchFilter *SearchFilter::CreateFromStructuredData(
+    Target &target, StructuredData::Dictionary &filter_dict, Error &error) {
+  SearchFilter *result = nullptr;
+  if (!filter_dict.IsValid()) {
+    error.SetErrorString("Can't deserialize from an invalid data object.");
+    return result;
+  }
+
+  std::string subclass_name;
+
+  bool success = filter_dict.GetValueForKeyAsString(
+      GetSerializationSubclassKey(), subclass_name);
+  if (!success) {
+    error.SetErrorStringWithFormat("Filter data missing subclass key");
+    return result;
+  }
+
+  FilterTy filter_type = NameToFilterTy(subclass_name.c_str());
+  if (filter_type == UnknownFilter) {
+    error.SetErrorStringWithFormat("Unknown filter type: %s.",
+                                   subclass_name.c_str());
+    return result;
+  }
+
+  StructuredData::Dictionary *subclass_options = nullptr;
+  success = filter_dict.GetValueForKeyAsDictionary(
+      GetSerializationSubclassOptionsKey(), subclass_options);
+  if (!success || !subclass_options || !subclass_options->IsValid()) {
+    error.SetErrorString("Filter data missing subclass options key.");
+    return result;
+  }
+
+  switch (filter_type) {
+  case Unconstrained:
+    result = SearchFilterForUnconstrainedSearches::CreateFromStructuredData(
+        target, *subclass_options, error);
+    break;
+  case ByModule:
+    result = SearchFilterByModule::CreateFromStructuredData(
+        target, *subclass_options, error);
+    break;
+  case ByModules:
+    result = SearchFilterByModuleList::CreateFromStructuredData(
+        target, *subclass_options, error);
+    break;
+  case ByModulesAndCU:
+    result = SearchFilterByModuleListAndCU::CreateFromStructuredData(
+        target, *subclass_options, error);
+    break;
+  case Exception:
+    error.SetErrorString("Can't serialize exception breakpoints yet.");
+    break;
+  default:
+    llvm_unreachable("Should never get an uresolvable filter type.");
+  }
+
+  return result;
+}
+
 bool SearchFilter::ModulePasses(const FileSpec &spec) { return true; }
 
 bool SearchFilter::ModulePasses(const ModuleSP &module_sp) { return true; }
@@ -62,6 +144,34 @@ lldb::SearchFilterSP SearchFilter::CopyF
 }
 
 //----------------------------------------------------------------------
+// Helper functions for serialization.
+//----------------------------------------------------------------------
+
+StructuredData::DictionarySP
+SearchFilter::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(), GetFilterName());
+  type_dict_sp->AddItem(GetSerializationSubclassOptionsKey(), options_dict_sp);
+
+  return type_dict_sp;
+}
+
+void SearchFilter::SerializeFileSpecList(
+    StructuredData::DictionarySP &options_dict_sp, OptionNames name,
+    FileSpecList &file_list) {
+  StructuredData::ArraySP module_array_sp(new StructuredData::Array());
+  size_t num_modules = file_list.GetSize();
+  for (size_t i = 0; i < num_modules; i++) {
+    module_array_sp->AddItem(StructuredData::StringSP(
+        new StructuredData::String(file_list.GetFileSpecAtIndex(i).GetPath())));
+  }
+  options_dict_sp->AddItem(GetKey(name), module_array_sp);
+}
+
+//----------------------------------------------------------------------
 // UTILITY Functions to help iterate down through the elements of the
 // SymbolContext.
 //----------------------------------------------------------------------
@@ -202,6 +312,18 @@ Searcher::CallbackReturn SearchFilter::D
 //  Selects a shared library matching a given file spec, consulting the targets
 //  "black list".
 //----------------------------------------------------------------------
+SearchFilter *SearchFilterForUnconstrainedSearches::CreateFromStructuredData(
+    Target &target, StructuredData::Dictionary &data_dict, Error &error) {
+  // No options for an unconstrained search.
+  return new SearchFilterForUnconstrainedSearches(target.shared_from_this());
+}
+
+StructuredData::ObjectSP
+SearchFilterForUnconstrainedSearches::SerializeToStructuredData() {
+  // The options dictionary is an empty dictionary:
+  StructuredData::DictionarySP result_sp(new StructuredData::Dictionary());
+  return WrapOptionsDict(result_sp);
+}
 
 bool SearchFilterForUnconstrainedSearches::ModulePasses(
     const FileSpec &module_spec) {
@@ -234,7 +356,7 @@ lldb::SearchFilterSP SearchFilterForUnco
 
 SearchFilterByModule::SearchFilterByModule(const lldb::TargetSP &target_sp,
                                            const FileSpec &module)
-    : SearchFilter(target_sp), m_module_spec(module) {}
+    : SearchFilter(target_sp, FilterTy::ByModule), m_module_spec(module) {}
 
 SearchFilterByModule::SearchFilterByModule(const SearchFilterByModule &rhs) =
     default;
@@ -325,6 +447,44 @@ SearchFilterByModule::DoCopyForBreakpoin
   return ret_sp;
 }
 
+SearchFilter *SearchFilterByModule::CreateFromStructuredData(
+    Target &target, StructuredData::Dictionary &data_dict, Error &error) {
+  StructuredData::Array *modules_array;
+  bool success = data_dict.GetValueForKeyAsArray(GetKey(OptionNames::ModList),
+                                                 modules_array);
+  if (!success) {
+    error.SetErrorString("SFBM::CFSD: Could not find the module list key.");
+    return nullptr;
+  }
+
+  size_t num_modules = modules_array->GetSize();
+  if (num_modules > 1) {
+    error.SetErrorString(
+        "SFBM::CFSD: Only one modules allowed for SearchFilterByModule.");
+    return nullptr;
+  }
+
+  std::string module;
+  success = modules_array->GetItemAtIndexAsString(0, module);
+  if (!success) {
+    error.SetErrorString("SFBM::CFSD: filter module item not a string.");
+    return nullptr;
+  }
+  FileSpec module_spec(module.c_str(), false);
+
+  return new SearchFilterByModule(target.shared_from_this(), module_spec);
+}
+
+StructuredData::ObjectSP SearchFilterByModule::SerializeToStructuredData() {
+  StructuredData::DictionarySP options_dict_sp(
+      new StructuredData::Dictionary());
+  StructuredData::ArraySP module_array_sp(new StructuredData::Array());
+  module_array_sp->AddItem(StructuredData::StringSP(
+      new StructuredData::String(m_module_spec.GetPath())));
+  options_dict_sp->AddItem(GetKey(OptionNames::ModList), module_array_sp);
+  return WrapOptionsDict(options_dict_sp);
+}
+
 //----------------------------------------------------------------------
 //  SearchFilterByModuleList:
 //  Selects a shared library matching a given file spec
@@ -332,7 +492,13 @@ SearchFilterByModule::DoCopyForBreakpoin
 
 SearchFilterByModuleList::SearchFilterByModuleList(
     const lldb::TargetSP &target_sp, const FileSpecList &module_list)
-    : SearchFilter(target_sp), m_module_spec_list(module_list) {}
+    : SearchFilter(target_sp, FilterTy::ByModules),
+      m_module_spec_list(module_list) {}
+
+SearchFilterByModuleList::SearchFilterByModuleList(
+    const lldb::TargetSP &target_sp, const FileSpecList &module_list,
+    enum FilterTy filter_ty)
+    : SearchFilter(target_sp, filter_ty), m_module_spec_list(module_list) {}
 
 SearchFilterByModuleList::SearchFilterByModuleList(
     const SearchFilterByModuleList &rhs) = default;
@@ -456,6 +622,45 @@ SearchFilterByModuleList::DoCopyForBreak
   return ret_sp;
 }
 
+SearchFilter *SearchFilterByModuleList::CreateFromStructuredData(
+    Target &target, StructuredData::Dictionary &data_dict, Error &error) {
+  StructuredData::Array *modules_array;
+  bool success = data_dict.GetValueForKeyAsArray(GetKey(OptionNames::ModList),
+                                                 modules_array);
+  if (!success) {
+    error.SetErrorString("SFBM::CFSD: Could not find the module list key.");
+    return nullptr;
+  }
+
+  size_t num_modules = modules_array->GetSize();
+  FileSpecList modules;
+  for (size_t i = 0; i < num_modules; i++) {
+    std::string module;
+    success = modules_array->GetItemAtIndexAsString(i, module);
+    if (!success) {
+      error.SetErrorStringWithFormat(
+          "SFBM::CFSD: filter module item %zu not a string.", i);
+      return nullptr;
+    }
+    modules.Append(FileSpec(module.c_str(), false));
+  }
+
+  return new SearchFilterByModuleList(target.shared_from_this(), modules);
+}
+
+void SearchFilterByModuleList::SerializeUnwrapped(
+    StructuredData::DictionarySP &options_dict_sp) {
+  SerializeFileSpecList(options_dict_sp, OptionNames::ModList,
+                        m_module_spec_list);
+}
+
+StructuredData::ObjectSP SearchFilterByModuleList::SerializeToStructuredData() {
+  StructuredData::DictionarySP options_dict_sp(
+      new StructuredData::Dictionary());
+  SerializeUnwrapped(options_dict_sp);
+  return WrapOptionsDict(options_dict_sp);
+}
+
 //----------------------------------------------------------------------
 //  SearchFilterByModuleListAndCU:
 //  Selects a shared library matching a given file spec
@@ -464,7 +669,8 @@ SearchFilterByModuleList::DoCopyForBreak
 SearchFilterByModuleListAndCU::SearchFilterByModuleListAndCU(
     const lldb::TargetSP &target_sp, const FileSpecList &module_list,
     const FileSpecList &cu_list)
-    : SearchFilterByModuleList(target_sp, module_list),
+    : SearchFilterByModuleList(target_sp, module_list,
+                               FilterTy::ByModulesAndCU),
       m_cu_spec_list(cu_list) {}
 
 SearchFilterByModuleListAndCU::SearchFilterByModuleListAndCU(
@@ -482,6 +688,63 @@ operator=(const SearchFilterByModuleList
 
 SearchFilterByModuleListAndCU::~SearchFilterByModuleListAndCU() = default;
 
+SearchFilter *SearchFilterByModuleListAndCU::CreateFromStructuredData(
+    Target &target, StructuredData::Dictionary &data_dict, Error &error) {
+  StructuredData::Array *modules_array;
+  bool success = data_dict.GetValueForKeyAsArray(GetKey(OptionNames::ModList),
+                                                 modules_array);
+  if (!success) {
+    error.SetErrorString("SFBM::CFSD: Could not find the module list key.");
+    return nullptr;
+  }
+
+  size_t num_modules = modules_array->GetSize();
+  FileSpecList modules;
+  for (size_t i = 0; i < num_modules; i++) {
+    std::string module;
+    success = modules_array->GetItemAtIndexAsString(i, module);
+    if (!success) {
+      error.SetErrorStringWithFormat(
+          "SFBM::CFSD: filter module item %zu not a string.", i);
+      return nullptr;
+    }
+    modules.Append(FileSpec(module.c_str(), false));
+  }
+
+  StructuredData::Array *cus_array;
+  success =
+      data_dict.GetValueForKeyAsArray(GetKey(OptionNames::CUList), cus_array);
+  if (!success) {
+    error.SetErrorString("SFBM::CFSD: Could not find the CU list key.");
+    return nullptr;
+  }
+
+  size_t num_cus = cus_array->GetSize();
+  FileSpecList cus;
+  for (size_t i = 0; i < num_cus; i++) {
+    std::string cu;
+    success = modules_array->GetItemAtIndexAsString(i, cu);
+    if (!success) {
+      error.SetErrorStringWithFormat(
+          "SFBM::CFSD: filter cu item %zu not a string.", i);
+      return nullptr;
+    }
+    cus.Append(FileSpec(cu.c_str(), false));
+  }
+
+  return new SearchFilterByModuleListAndCU(target.shared_from_this(), modules,
+                                           cus);
+}
+
+StructuredData::ObjectSP
+SearchFilterByModuleListAndCU::SerializeToStructuredData() {
+  StructuredData::DictionarySP options_dict_sp(
+      new StructuredData::Dictionary());
+  SearchFilterByModuleList::SerializeUnwrapped(options_dict_sp);
+  SerializeFileSpecList(options_dict_sp, OptionNames::CUList, m_cu_spec_list);
+  return WrapOptionsDict(options_dict_sp);
+}
+
 bool SearchFilterByModuleListAndCU::AddressPasses(Address &address) {
   return true;
 }

Modified: lldb/trunk/source/Core/StructuredData.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/StructuredData.cpp?rev=281273&r1=281272&r2=281273&view=diff
==============================================================================
--- lldb/trunk/source/Core/StructuredData.cpp (original)
+++ lldb/trunk/source/Core/StructuredData.cpp Mon Sep 12 18:10:56 2016
@@ -14,7 +14,11 @@
 #include <inttypes.h>
 #include <stdlib.h>
 
+#include "lldb/Core/DataBuffer.h"
+#include "lldb/Core/Error.h"
 #include "lldb/Core/StreamString.h"
+#include "lldb/Host/File.h"
+#include "lldb/Host/FileSpec.h"
 #include "lldb/Host/StringConvert.h"
 #include "lldb/Utility/JSON.h"
 
@@ -27,6 +31,44 @@ static StructuredData::ObjectSP ParseJSO
 static StructuredData::ObjectSP ParseJSONObject(JSONParser &json_parser);
 static StructuredData::ObjectSP ParseJSONArray(JSONParser &json_parser);
 
+StructuredData::ObjectSP StructuredData::ParseJSONFromFile(FileSpec &input_spec,
+                                                           Error &error) {
+  StructuredData::ObjectSP return_sp;
+  if (!input_spec.Exists()) {
+    error.SetErrorStringWithFormat("input file %s does not exist.",
+                                   input_spec.GetPath().c_str());
+    return return_sp;
+  }
+
+  File input_file(nullptr, File::OpenOptions::eOpenOptionRead,
+                  lldb::eFilePermissionsUserRead);
+  std::string input_path = input_spec.GetPath();
+  error =
+      input_file.Open(input_path.c_str(), File::OpenOptions::eOpenOptionRead,
+                      lldb::eFilePermissionsUserRead);
+
+  if (!error.Success()) {
+    error.SetErrorStringWithFormat("could not open input file: %s - %s.",
+                                   input_spec.GetPath().c_str(),
+                                   error.AsCString());
+    return return_sp;
+  }
+
+  lldb::DataBufferSP input_data;
+  size_t num_bytes = SIZE_T_MAX;
+  off_t offset = 0;
+  error = input_file.Read(num_bytes, offset, true, input_data);
+  if (!error.Success()) {
+    error.SetErrorStringWithFormat("could not read input file: %s - %s.",
+                                   input_spec.GetPath().c_str(),
+                                   error.AsCString());
+    return return_sp;
+  }
+  JSONParser json_parser((char *)input_data->GetBytes());
+  return_sp = ParseJSONValue(json_parser);
+  return return_sp;
+}
+
 static StructuredData::ObjectSP ParseJSONObject(JSONParser &json_parser) {
   // The "JSONParser::Token::ObjectStart" token should have already been
   // consumed

Modified: lldb/trunk/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp?rev=281273&r1=281272&r2=281273&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp (original)
+++ lldb/trunk/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp Mon Sep 12 18:10:56 2016
@@ -420,7 +420,7 @@ void ScriptInterpreterPython::IOHandlerI
         if (GenerateBreakpointCommandCallbackData(data_ap->user_source,
                                                   data_ap->script_source)
                 .Success()) {
-          BatonSP baton_sp(
+          BreakpointOptions::CommandBatonSP baton_sp(
               new BreakpointOptions::CommandBaton(data_ap.release()));
           bp_options->SetCallback(
               ScriptInterpreterPython::BreakpointCallbackFunction, baton_sp);
@@ -1050,11 +1050,11 @@ bool ScriptInterpreterPython::ExecuteOne
       }
       case eScriptReturnTypeCharStrOrNone: // char* or NULL if py_return ==
                                            // Py_None
-      {
-        const char format[3] = "z";
-        success = PyArg_Parse(py_return.get(), format, (char **)ret_value);
-        break;
-      }
+        {
+          const char format[3] = "z";
+          success = PyArg_Parse(py_return.get(), format, (char **)ret_value);
+          break;
+        }
       case eScriptReturnTypeBool: {
         const char format[2] = "b";
         success = PyArg_Parse(py_return.get(), format, (bool *)ret_value);
@@ -1251,7 +1251,8 @@ Error ScriptInterpreterPython::SetBreakp
   Error error = GenerateBreakpointCommandCallbackData(data_ap->user_source,
                                                       data_ap->script_source);
   if (error.Success()) {
-    BatonSP baton_sp(new BreakpointOptions::CommandBaton(data_ap.release()));
+    BreakpointOptions::CommandBatonSP baton_sp(
+        new BreakpointOptions::CommandBaton(data_ap.release()));
     bp_options->SetCallback(ScriptInterpreterPython::BreakpointCallbackFunction,
                             baton_sp);
     return error;

Modified: lldb/trunk/source/Target/LanguageRuntime.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/LanguageRuntime.cpp?rev=281273&r1=281272&r2=281273&view=diff
==============================================================================
--- lldb/trunk/source/Target/LanguageRuntime.cpp (original)
+++ lldb/trunk/source/Target/LanguageRuntime.cpp Mon Sep 12 18:10:56 2016
@@ -23,80 +23,83 @@
 using namespace lldb;
 using namespace lldb_private;
 
-class ExceptionSearchFilter : public SearchFilter {
-public:
-  ExceptionSearchFilter(const lldb::TargetSP &target_sp,
-                        lldb::LanguageType language,
-                        bool update_module_list = true)
-      : SearchFilter(target_sp), m_language(language),
-        m_language_runtime(nullptr), m_filter_sp() {
-    if (update_module_list)
-      UpdateModuleListIfNeeded();
-  }
-
-  ~ExceptionSearchFilter() override = default;
-
-  bool ModulePasses(const lldb::ModuleSP &module_sp) override {
-    UpdateModuleListIfNeeded();
-    if (m_filter_sp)
-      return m_filter_sp->ModulePasses(module_sp);
-    return false;
-  }
-
-  bool ModulePasses(const FileSpec &spec) override {
-    UpdateModuleListIfNeeded();
-    if (m_filter_sp)
-      return m_filter_sp->ModulePasses(spec);
-    return false;
-  }
-
-  void Search(Searcher &searcher) override {
-    UpdateModuleListIfNeeded();
-    if (m_filter_sp)
-      m_filter_sp->Search(searcher);
-  }
-
-  void GetDescription(Stream *s) override {
+ExceptionSearchFilter::ExceptionSearchFilter(const lldb::TargetSP &target_sp,
+                                             lldb::LanguageType language,
+                                             bool update_module_list)
+    : SearchFilter(target_sp, FilterTy::Exception), m_language(language),
+      m_language_runtime(nullptr), m_filter_sp() {
+  if (update_module_list)
     UpdateModuleListIfNeeded();
-    if (m_filter_sp)
-      m_filter_sp->GetDescription(s);
-  }
-
-protected:
-  LanguageType m_language;
-  LanguageRuntime *m_language_runtime;
-  SearchFilterSP m_filter_sp;
-
-  SearchFilterSP DoCopyForBreakpoint(Breakpoint &breakpoint) override {
-    return SearchFilterSP(
-        new ExceptionSearchFilter(TargetSP(), m_language, false));
-  }
+}
 
-  void UpdateModuleListIfNeeded() {
-    ProcessSP process_sp(m_target_sp->GetProcessSP());
-    if (process_sp) {
-      bool refreash_filter = !m_filter_sp;
-      if (m_language_runtime == nullptr) {
-        m_language_runtime = process_sp->GetLanguageRuntime(m_language);
+bool ExceptionSearchFilter::ModulePasses(const lldb::ModuleSP &module_sp) {
+  UpdateModuleListIfNeeded();
+  if (m_filter_sp)
+    return m_filter_sp->ModulePasses(module_sp);
+  return false;
+}
+
+bool ExceptionSearchFilter::ModulePasses(const FileSpec &spec) {
+  UpdateModuleListIfNeeded();
+  if (m_filter_sp)
+    return m_filter_sp->ModulePasses(spec);
+  return false;
+}
+
+void ExceptionSearchFilter::Search(Searcher &searcher) {
+  UpdateModuleListIfNeeded();
+  if (m_filter_sp)
+    m_filter_sp->Search(searcher);
+}
+
+void ExceptionSearchFilter::GetDescription(Stream *s) {
+  UpdateModuleListIfNeeded();
+  if (m_filter_sp)
+    m_filter_sp->GetDescription(s);
+}
+
+void ExceptionSearchFilter::UpdateModuleListIfNeeded() {
+  ProcessSP process_sp(m_target_sp->GetProcessSP());
+  if (process_sp) {
+    bool refreash_filter = !m_filter_sp;
+    if (m_language_runtime == nullptr) {
+      m_language_runtime = process_sp->GetLanguageRuntime(m_language);
+      refreash_filter = true;
+    } else {
+      LanguageRuntime *language_runtime =
+          process_sp->GetLanguageRuntime(m_language);
+      if (m_language_runtime != language_runtime) {
+        m_language_runtime = language_runtime;
         refreash_filter = true;
-      } else {
-        LanguageRuntime *language_runtime =
-            process_sp->GetLanguageRuntime(m_language);
-        if (m_language_runtime != language_runtime) {
-          m_language_runtime = language_runtime;
-          refreash_filter = true;
-        }
       }
+    }
 
-      if (refreash_filter && m_language_runtime) {
-        m_filter_sp = m_language_runtime->CreateExceptionSearchFilter();
-      }
-    } else {
-      m_filter_sp.reset();
-      m_language_runtime = nullptr;
+    if (refreash_filter && m_language_runtime) {
+      m_filter_sp = m_language_runtime->CreateExceptionSearchFilter();
     }
-  }
-};
+  } else {
+    m_filter_sp.reset();
+    m_language_runtime = nullptr;
+  }
+}
+
+SearchFilterSP
+ExceptionSearchFilter::DoCopyForBreakpoint(Breakpoint &breakpoint) {
+  return SearchFilterSP(
+      new ExceptionSearchFilter(TargetSP(), m_language, false));
+}
+
+SearchFilter *ExceptionSearchFilter::CreateFromStructuredData(
+    Target &target, StructuredData::Dictionary &data_dict, Error &error) {
+  SearchFilter *result = nullptr;
+  return result;
+}
+
+StructuredData::ObjectSP ExceptionSearchFilter::SerializeToStructuredData() {
+  StructuredData::ObjectSP result_sp;
+
+  return result_sp;
+}
 
 // The Target is the one that knows how to create breakpoints, so this function
 // is meant to be used either by the target or internally in




More information about the lldb-commits mailing list