Add some more tests for breakpoint serialization.
authorJim Ingham <jingham@apple.com>
Tue, 20 Sep 2016 22:54:49 +0000 (22:54 +0000)
committerJim Ingham <jingham@apple.com>
Tue, 20 Sep 2016 22:54:49 +0000 (22:54 +0000)
Serialize breakpoint names & the hardware_requested attributes.
Also added a few missing affordances to SBBreakpoint whose absence
writing the tests pointed out.

<rdar://problem/12611863>

llvm-svn: 282036

14 files changed:
lldb/include/lldb/API/SBBreakpoint.h
lldb/include/lldb/API/SBStringList.h
lldb/include/lldb/API/SBTarget.h
lldb/include/lldb/Breakpoint/Breakpoint.h
lldb/include/lldb/Breakpoint/BreakpointOptions.h
lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/serialize/TestBreakpointSerialization.py
lldb/scripts/interface/SBBreakpoint.i
lldb/scripts/interface/SBTarget.i
lldb/source/API/SBBreakpoint.cpp
lldb/source/API/SBStringList.cpp
lldb/source/API/SBTarget.cpp
lldb/source/Breakpoint/Breakpoint.cpp
lldb/source/Breakpoint/BreakpointOptions.cpp
lldb/source/Commands/CommandObjectBreakpointCommand.cpp

index a93050a..7924229 100644 (file)
@@ -88,6 +88,10 @@ public:
 
   void SetScriptCallbackFunction(const char *callback_function_name);
 
+  void SetCommandLineCommands(SBStringList &commands);
+
+  bool GetCommandLineCommands(SBStringList &commands);
+
   SBError SetScriptCallbackBody(const char *script_body_text);
 
   bool AddName(const char *new_name);
@@ -154,7 +158,7 @@ public:
 
   SBBreakpoint GetBreakpointAtIndex(size_t idx);
 
-  SBBreakpoint  FindBreakpointByID(lldb::break_id_t);
+  SBBreakpoint FindBreakpointByID(lldb::break_id_t);
 
   void Append(const SBBreakpoint &sb_file);
 
index ac62fce..66b5172 100644 (file)
@@ -43,9 +43,12 @@ public:
 protected:
   friend class SBCommandInterpreter;
   friend class SBDebugger;
+  friend class SBBreakpoint;
 
   SBStringList(const lldb_private::StringList *lldb_strings);
 
+  void AppendList(const lldb_private::StringList &strings);
+
   const lldb_private::StringList *operator->() const;
 
   const lldb_private::StringList &operator*() const;
index c7d99b1..ac22586 100644 (file)
@@ -564,6 +564,10 @@ public:
   BreakpointCreateByLocation(const lldb::SBFileSpec &file_spec, uint32_t line,
                              lldb::addr_t offset);
 
+  lldb::SBBreakpoint
+  BreakpointCreateByLocation(const lldb::SBFileSpec &file_spec, uint32_t line,
+                             lldb::addr_t offset, SBFileSpecList &module_list);
+
   lldb::SBBreakpoint BreakpointCreateByName(const char *symbol_name,
                                             const char *module_name = nullptr);
 
index e002f71..03a92ca 100644 (file)
@@ -107,6 +107,17 @@ public:
   //------------------------------------------------------------------
   typedef enum { Exact, Regexp, Glob } MatchType;
 
+private:
+  enum class OptionNames : uint32_t { Names = 0, Hardware, LastOptionName };
+
+  static const char
+      *g_option_names[static_cast<uint32_t>(OptionNames::LastOptionName)];
+
+  static const char *GetKey(OptionNames enum_value) {
+    return g_option_names[static_cast<uint32_t>(enum_value)];
+  }
+
+public:
   class BreakpointEventData : public EventData {
   public:
     BreakpointEventData(lldb::BreakpointEventType sub_type,
index c7763bd..1b72ba0 100644 (file)
@@ -36,6 +36,9 @@ public:
   struct CommandData {
     CommandData() : user_source(), script_source(), stop_on_error(true) {}
 
+    CommandData(const StringList &user_source)
+        : user_source(user_source), script_source(), stop_on_error(true) {}
+
     ~CommandData() = default;
 
     static const char *GetSerializationKey() { return "BKPTCMDData"; }
@@ -180,6 +183,18 @@ public:
                    bool synchronous = false);
 
   //------------------------------------------------------------------
+  /// Returns the command line commands for the callback on this breakpoint.
+  ///
+  /// @param[out] command_list
+  ///    The commands will be appended to this list.
+  ///
+  /// @return
+  ///    \btrue if the command callback is a command-line callback,
+  ///    \bfalse otherwise.
+  //------------------------------------------------------------------
+  bool GetCommandLineCallbacks(StringList &command_list);
+
+  //------------------------------------------------------------------
   /// Remove the callback from this option set.
   //------------------------------------------------------------------
   void ClearCallback();
@@ -335,10 +350,10 @@ public:
   //------------------------------------------------------------------
   /// Set a callback based on BreakpointOptions::CommandData.
   /// @param[in] cmd_data
-  ///     A new'ed CommandData object.  The breakpoint will take ownership
-  ///     of this object.
+  ///     A UP holding the new'ed CommandData object.
+  ///     The breakpoint will take ownership of pointer held by this object.
   //------------------------------------------------------------------
-  void SetCommandDataCallback(std::unique_ptr<CommandData> cmd_data);
+  void SetCommandDataCallback(std::unique_ptr<CommandData> &cmd_data);
 
 protected:
   //------------------------------------------------------------------
index 3f8a393..e609d8e 100644 (file)
@@ -1,5 +1,5 @@
 """
-Test breakpoint ignore count features.
+Test breakpoint serialization.
 """
 
 from __future__ import print_function
@@ -25,34 +25,28 @@ class BreakpointSerialization(TestBase):
         self.setup_targets_and_cleanup()
         self.do_check_resolvers()
 
-    def not_test_filters(self):
+    def test_filters(self):
         """Use Python APIs to test that we serialize search filters correctly."""
         self.build()
         self.setup_targets_and_cleanup()
-        self.check_filters()
+        self.do_check_filters()
 
-    def not_test_options(self):
+    def test_options(self):
         """Use Python APIs to test that we serialize breakpoint options correctly."""
         self.build()
         self.setup_targets_and_cleanup()
-        self.check_filters()
-
-    def not_test_complex(self):
-        """Use Python APIs to test that we serialize complex breakpoints correctly."""
-        self.build()
-        self.setup_targets_and_cleanup()
-        self.check_filters()
+        self.do_check_options()
 
     def setup_targets_and_cleanup(self):
         def cleanup ():
-            #self.RemoveTempFile(self.bkpts_file_path)
+            self.RemoveTempFile(self.bkpts_file_path)
 
             if self.orig_target.IsValid():
                 self.dbg.DeleteTarget(self.orig_target)
                 self.dbg.DeleteTarget(self.copy_target)
 
         self.addTearDownHook(cleanup)
-        #self.RemoveTempFile(self.bkpts_file_path)
+        self.RemoveTempFile(self.bkpts_file_path)
 
         exe = os.path.join(os.getcwd(), "a.out")
 
@@ -70,23 +64,10 @@ class BreakpointSerialization(TestBase):
         self.bkpts_file_path = os.path.join(os.getcwd(), "breakpoints.json")
         self.bkpts_file_spec = lldb.SBFileSpec(self.bkpts_file_path)
 
-    def do_check_resolvers(self):
-        """Use Python APIs to check serialization of breakpoint resolvers"""
-
-        empty_module_list = lldb.SBFileSpecList()
-        empty_cu_list = lldb.SBFileSpecList()
-        blubby_file_spec = lldb.SBFileSpec(os.path.join(os.getcwd(), "blubby.c"))
-
-        # It isn't actually important for these purposes that these breakpoint
-        # actually have locations.
-        source_bps = lldb.SBBreakpointList(self.orig_target)
-        source_bps.Append(self.orig_target.BreakpointCreateByLocation("blubby.c", 666))
-        source_bps.Append(self.orig_target.BreakpointCreateByName("blubby", lldb.eFunctionNameTypeAuto, empty_module_list, empty_cu_list))
-        source_bps.Append(self.orig_target.BreakpointCreateByName("blubby", lldb.eFunctionNameTypeFull, empty_module_list,empty_cu_list))
-        source_bps.Append(self.orig_target.BreakpointCreateBySourceRegex("dont really care", blubby_file_spec))
+    def check_equivalence(self, source_bps):
 
         error = lldb.SBError()
-        error = self.orig_target.BreakpointsWriteToFile(self.bkpts_file_spec)
+        error = self.orig_target.BreakpointsWriteToFile(self.bkpts_file_spec, source_bps)
         self.assertTrue(error.Success(), "Failed writing breakpoints to file: %s."%(error.GetCString()))
 
         copy_bps = lldb.SBBreakpointList(self.copy_target)
@@ -116,32 +97,105 @@ class BreakpointSerialization(TestBase):
             copy_text = copy_desc.GetData()
 
             # These two should be identical.
-            print ("Source test for %d is %s."%(i, source_text))
+            # print ("Source text for %d is %s."%(i, source_text))
             self.assertTrue (source_text == copy_text, "Source and dest breakpoints are not identical: \nsource: %s\ndest: %s"%(source_text, copy_text))
 
-    def check_filters(self):
+    def do_check_resolvers(self):
+        """Use Python APIs to check serialization of breakpoint resolvers"""
+
+        empty_module_list = lldb.SBFileSpecList()
+        empty_cu_list = lldb.SBFileSpecList()
+        blubby_file_spec = lldb.SBFileSpec(os.path.join(os.getcwd(), "blubby.c"))
+
+        # It isn't actually important for these purposes that these breakpoint
+        # actually have locations.
+        source_bps = lldb.SBBreakpointList(self.orig_target)
+        source_bps.Append(self.orig_target.BreakpointCreateByLocation("blubby.c", 666))
+        # Make sure we do one breakpoint right:
+        self.check_equivalence(source_bps)
+        source_bps.Clear()
+
+        source_bps.Append(self.orig_target.BreakpointCreateByName("blubby", lldb.eFunctionNameTypeAuto, empty_module_list, empty_cu_list))
+        source_bps.Append(self.orig_target.BreakpointCreateByName("blubby", lldb.eFunctionNameTypeFull, empty_module_list,empty_cu_list))
+        source_bps.Append(self.orig_target.BreakpointCreateBySourceRegex("dont really care", blubby_file_spec))
+        
+        # And some number greater than one:
+        self.check_equivalence(source_bps)
+
+    def do_check_filters(self):
         """Use Python APIs to check serialization of breakpoint filters."""
-        exe = os.path.join(os.getcwd(), "a.out")
+        module_list = lldb.SBFileSpecList()
+        module_list.Append(lldb.SBFileSpec("SomeBinary"))
+        module_list.Append(lldb.SBFileSpec("SomeOtherBinary"))
+
+        cu_list = lldb.SBFileSpecList()
+        cu_list.Append(lldb.SBFileSpec("SomeCU.c"))
+        cu_list.Append(lldb.SBFileSpec("AnotherCU.c"))
+        cu_list.Append(lldb.SBFileSpec("ThirdCU.c"))
 
-        # Create a target by the debugger.
-        target = self.dbg.CreateTarget(exe)
-        self.assertTrue(target, VALID_TARGET)
+        blubby_file_spec = lldb.SBFileSpec(os.path.join(os.getcwd(), "blubby.c"))
 
-    def check_options(self):
+        # It isn't actually important for these purposes that these breakpoint
+        # actually have locations.
+        source_bps = lldb.SBBreakpointList(self.orig_target)
+        bkpt = self.orig_target.BreakpointCreateByLocation(blubby_file_spec, 666, 0, module_list)
+        source_bps.Append(bkpt)
+
+        # Make sure we do one right:
+        self.check_equivalence(source_bps)
+        source_bps.Clear()
+
+        bkpt = self.orig_target.BreakpointCreateByName("blubby", lldb.eFunctionNameTypeAuto, module_list, cu_list)
+        source_bps.Append(bkpt)
+        bkpt = self.orig_target.BreakpointCreateByName("blubby", lldb.eFunctionNameTypeFull, module_list, cu_list)
+        source_bps.Append(bkpt)
+        bkpt = self.orig_target.BreakpointCreateBySourceRegex("dont really care", blubby_file_spec)
+        source_bps.Append(bkpt)
+
+        # And some number greater than one:
+        self.check_equivalence(source_bps)
+
+    def do_check_options(self):
         """Use Python APIs to check serialization of breakpoint options."""
-        exe = os.path.join(os.getcwd(), "a.out")
 
-        # Create a target by the debugger.
-        target = self.dbg.CreateTarget(exe)
-        self.assertTrue(target, VALID_TARGET)
+        empty_module_list = lldb.SBFileSpecList()
+        empty_cu_list = lldb.SBFileSpecList()
+        blubby_file_spec = lldb.SBFileSpec(os.path.join(os.getcwd(), "blubby.c"))
 
-    def check_resolvers(self):
-        """Use Python APIs to check serialization of breakpoint resolvers."""
-        exe = os.path.join(os.getcwd(), "a.out")
+        # It isn't actually important for these purposes that these breakpoint
+        # actually have locations.
+        source_bps = lldb.SBBreakpointList(self.orig_target)
+
+        bkpt = self.orig_target.BreakpointCreateByLocation("blubby.c", 666)
+        bkpt.SetEnabled(False)
+        bkpt.SetOneShot(True)
+        source_bps.Append(bkpt)
+        
+        # Make sure we get one right:
+        self.check_equivalence(source_bps)
+        source_bps.Clear()
+
+        bkpt = self.orig_target.BreakpointCreateByName("blubby", lldb.eFunctionNameTypeAuto, empty_module_list, empty_cu_list)
+        bkpt.SetIgnoreCount(10)
+        source_bps.Append(bkpt)
+
+        bkpt = self.orig_target.BreakpointCreateByName("blubby", lldb.eFunctionNameTypeFull, empty_module_list,empty_cu_list)
+        bkpt.SetCondition("something != something_else")
+        bkpt.AddName("FirstName")
+        bkpt.AddName("SecondName")
+
+        source_bps.Append(bkpt)
+
+        bkpt = self.orig_target.BreakpointCreateBySourceRegex("dont really care", blubby_file_spec)
+        cmd_list = lldb.SBStringList()
+        cmd_list.AppendString("frame var")
+        cmd_list.AppendString("thread backtrace")
+
+        bkpt.SetCommandLineCommands(cmd_list)
+        source_bps.Append(bkpt)
+
+        self.check_equivalence(source_bps)
 
-        # Create a target by the debugger.
-        target = self.dbg.CreateTarget(exe)
-        self.assertTrue(target, VALID_TARGET)
 
 
         
index 9098c6e..22c4c21 100644 (file)
@@ -200,6 +200,10 @@ public:
     SBError
     SetScriptCallbackBody (const char *script_body_text);
     
+    void SetCommandLineCommands(SBStringList &commands);
+
+    bool GetCommandLineCommands(SBStringList &commands);
+    
     bool
     AddName (const char *new_name);
 
index f907dcc..f490be5 100644 (file)
@@ -589,6 +589,10 @@ public:
     BreakpointCreateByLocation (const lldb::SBFileSpec &file_spec, uint32_t line, lldb::addr_t offset);
 
     lldb::SBBreakpoint
+    BreakpointCreateByLocation (const lldb::SBFileSpec &file_spec, uint32_t line, 
+                                lldb::addr_t offset, SBFileSpecList &module_list);
+
+    lldb::SBBreakpoint
     BreakpointCreateByName (const char *symbol_name, const char *module_name = NULL);
 
     lldb::SBBreakpoint
index 7276713..7194101 100644 (file)
@@ -448,6 +448,31 @@ size_t SBBreakpoint::GetNumLocations() const {
   return num_locs;
 }
 
+void SBBreakpoint::SetCommandLineCommands(SBStringList &commands) {
+  if (!m_opaque_sp)
+    return;
+  if (commands.GetSize() == 0)
+    return;
+
+  std::lock_guard<std::recursive_mutex> guard(
+      m_opaque_sp->GetTarget().GetAPIMutex());
+  std::unique_ptr<BreakpointOptions::CommandData> cmd_data_up(
+      new BreakpointOptions::CommandData(*commands));
+
+  m_opaque_sp->GetOptions()->SetCommandDataCallback(cmd_data_up);
+}
+
+bool SBBreakpoint::GetCommandLineCommands(SBStringList &commands) {
+  if (!m_opaque_sp)
+    return false;
+  StringList command_list;
+  bool has_commands =
+      m_opaque_sp->GetOptions()->GetCommandLineCallbacks(command_list);
+  if (has_commands)
+    commands.AppendList(command_list);
+  return has_commands;
+}
+
 bool SBBreakpoint::GetDescription(SBStream &s) {
   return GetDescription(s, true);
 }
index 34465f7..075ee0d 100644 (file)
@@ -75,6 +75,12 @@ void SBStringList::AppendList(const SBStringList &strings) {
   }
 }
 
+void SBStringList::AppendList(const StringList &strings) {
+  if (!IsValid())
+    m_opaque_ap.reset(new lldb_private::StringList());
+  m_opaque_ap->AppendList(strings);
+}
+
 uint32_t SBStringList::GetSize() const {
   if (IsValid()) {
     return m_opaque_ap->GetSize();
index 66d375a..7cf9215 100644 (file)
@@ -661,6 +661,14 @@ SBTarget::BreakpointCreateByLocation(const SBFileSpec &sb_file_spec,
 SBBreakpoint
 SBTarget::BreakpointCreateByLocation(const SBFileSpec &sb_file_spec,
                                      uint32_t line, lldb::addr_t offset) {
+  SBFileSpecList empty_list;
+  return BreakpointCreateByLocation(sb_file_spec, line, offset, empty_list);
+}
+
+SBBreakpoint
+SBTarget::BreakpointCreateByLocation(const SBFileSpec &sb_file_spec,
+                                     uint32_t line, lldb::addr_t offset,
+                                     SBFileSpecList &sb_module_list) {
   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
 
   SBBreakpoint sb_bp;
@@ -673,9 +681,13 @@ SBTarget::BreakpointCreateByLocation(const SBFileSpec &sb_file_spec,
     const bool internal = false;
     const bool hardware = false;
     const LazyBool move_to_nearest_code = eLazyBoolCalculate;
-    *sb_bp = target_sp->CreateBreakpoint(NULL, *sb_file_spec, line, offset,
-                                         check_inlines, skip_prologue, internal,
-                                         hardware, move_to_nearest_code);
+    const FileSpecList *module_list = nullptr;
+    if (sb_module_list.GetSize() > 0) {
+      module_list = sb_module_list.get();
+    }
+    *sb_bp = target_sp->CreateBreakpoint(
+        module_list, *sb_file_spec, line, offset, check_inlines, skip_prologue,
+        internal, hardware, move_to_nearest_code);
   }
 
   if (log) {
index 567ceaa..a9666f4 100644 (file)
@@ -41,6 +41,9 @@ const ConstString &Breakpoint::GetEventIdentifier() {
   return g_identifier;
 }
 
+const char *Breakpoint::g_option_names[static_cast<uint32_t>(
+    Breakpoint::OptionNames::LastOptionName)]{"Names", "Hardware"};
+
 //----------------------------------------------------------------------
 // Breakpoint constructor
 //----------------------------------------------------------------------
@@ -81,6 +84,19 @@ StructuredData::ObjectSP Breakpoint::SerializeToStructuredData() {
   StructuredData::DictionarySP breakpoint_contents_sp(
       new StructuredData::Dictionary());
 
+  if (!m_name_list.empty()) {
+    StructuredData::ArraySP names_array_sp(new StructuredData::Array());
+    for (auto name : m_name_list) {
+      names_array_sp->AddItem(
+          StructuredData::StringSP(new StructuredData::String(name)));
+    }
+    breakpoint_contents_sp->AddItem(Breakpoint::GetKey(OptionNames::Names),
+                                    names_array_sp);
+  }
+
+  breakpoint_contents_sp->AddBooleanItem(
+      Breakpoint::GetKey(OptionNames::Hardware), m_hardware);
+
   StructuredData::ObjectSP resolver_dict_sp(
       m_resolver_sp->SerializeToStructuredData());
   if (!resolver_dict_sp)
@@ -172,11 +188,31 @@ lldb::BreakpointSP Breakpoint::CreateFromStructuredData(
       return result_sp;
     }
   }
+
+  bool hardware = false;
+  success = breakpoint_dict->GetValueForKeyAsBoolean(
+      Breakpoint::GetKey(OptionNames::Hardware), hardware);
+
   result_sp =
-      target.CreateBreakpoint(filter_sp, resolver_sp, false, false, true);
+      target.CreateBreakpoint(filter_sp, resolver_sp, false, hardware, true);
+
   if (result_sp && options_up) {
     result_sp->m_options_up = std::move(options_up);
   }
+
+  StructuredData::Array *names_array;
+  success = breakpoint_dict->GetValueForKeyAsArray(
+      Breakpoint::GetKey(OptionNames::Names), 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;
+      Error error;
+      success = names_array->GetItemAtIndexAsString(i, name);
+      result_sp->AddName(name.c_str(), error);
+    }
+  }
+
   return result_sp;
 }
 
index d55a344..3095f77 100644 (file)
@@ -66,26 +66,39 @@ std::unique_ptr<BreakpointOptions::CommandData>
 BreakpointOptions::CommandData::CreateFromStructuredData(
     const StructuredData::Dictionary &options_dict, Error &error) {
   std::string script_source;
-  CommandData *data = new CommandData();
+  std::unique_ptr<CommandData> data_up(new CommandData());
+  bool found_something = false;
+
   bool success = options_dict.GetValueForKeyAsBoolean(
-      GetKey(OptionNames::StopOnError), data->stop_on_error);
+      GetKey(OptionNames::StopOnError), data_up->stop_on_error);
+
+  if (success)
+    found_something = true;
 
   success = options_dict.GetValueForKeyAsString(
-      GetKey(OptionNames::ScriptSource), data->script_source);
+      GetKey(OptionNames::ScriptSource), data_up->script_source);
+
+  if (success)
+    found_something = true;
 
   StructuredData::Array *user_source;
   success = options_dict.GetValueForKeyAsArray(GetKey(OptionNames::UserSource),
                                                user_source);
   if (success) {
+    found_something = true;
     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);
+        data_up->user_source.AppendString(elem_string);
     }
   }
-  return std::unique_ptr<BreakpointOptions::CommandData>(data);
+
+  if (found_something)
+    return data_up;
+  else
+    return std::unique_ptr<BreakpointOptions::CommandData>();
 }
 
 const char *BreakpointOptions::g_option_names
@@ -200,13 +213,13 @@ std::unique_ptr<BreakpointOptions> BreakpointOptions::CreateFromStructuredData(
     return nullptr;
   }
 
-  std::unique_ptr<CommandData> cmd_data;
+  std::unique_ptr<CommandData> cmd_data_up;
   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);
+    cmd_data_up = CommandData::CreateFromStructuredData(*cmds_dict, cmds_error);
     if (cmds_error.Fail()) {
       error.SetErrorStringWithFormat(
           "Failed to deserialize breakpoint command options: %s.",
@@ -217,7 +230,8 @@ std::unique_ptr<BreakpointOptions> BreakpointOptions::CreateFromStructuredData(
 
   auto bp_options = llvm::make_unique<BreakpointOptions>(
       condition_text.c_str(), enabled, ignore_count, one_shot);
-  bp_options->SetCommandDataCallback(std::move(cmd_data));
+  if (cmd_data_up.get())
+    bp_options->SetCommandDataCallback(cmd_data_up);
   return bp_options;
 }
 
@@ -306,6 +320,20 @@ bool BreakpointOptions::HasCallback() const {
   return m_callback != BreakpointOptions::NullCallback;
 }
 
+bool BreakpointOptions::GetCommandLineCallbacks(StringList &command_list) {
+  if (!HasCallback())
+    return false;
+  if (!m_baton_is_command_baton)
+    return false;
+
+  auto cmd_baton = std::static_pointer_cast<CommandBaton>(m_callback_baton_sp);
+  CommandData *data = cmd_baton->getItem();
+  if (!data)
+    return false;
+  command_list = data->user_source;
+  return true;
+}
+
 void BreakpointOptions::SetCondition(const char *condition) {
   if (!condition)
     condition = "";
@@ -418,7 +446,7 @@ void BreakpointOptions::CommandBaton::GetDescription(
 }
 
 void BreakpointOptions::SetCommandDataCallback(
-    std::unique_ptr<CommandData> cmd_data) {
+    std::unique_ptr<CommandData> &cmd_data) {
   auto baton_sp = std::make_shared<CommandBaton>(std::move(cmd_data));
   SetCallback(BreakpointOptions::BreakpointOptionsCallbackFunction, baton_sp);
 }
index ed10a24..1850494 100644 (file)
@@ -219,7 +219,7 @@ are no syntax errors may indicate that a function was declared but never called.
 
       auto cmd_data = llvm::make_unique<BreakpointOptions::CommandData>();
       cmd_data->user_source.SplitIntoLines(line.c_str(), line.size());
-      bp_options->SetCommandDataCallback(std::move(cmd_data));
+      bp_options->SetCommandDataCallback(cmd_data);
     }
   }
 
@@ -251,7 +251,7 @@ are no syntax errors may indicate that a function was declared but never called.
       cmd_data->script_source.assign(oneliner);
       cmd_data->stop_on_error = m_options.m_stop_on_error;
 
-      bp_options->SetCommandDataCallback(std::move(cmd_data));
+      bp_options->SetCommandDataCallback(cmd_data);
     }
   }