[Lldb-commits] [lldb] r281520 - Add SB API's for writing breakpoints to & creating the from a file.

Jim Ingham via lldb-commits lldb-commits at lists.llvm.org
Wed Sep 14 12:07:35 PDT 2016


Author: jingham
Date: Wed Sep 14 14:07:35 2016
New Revision: 281520

URL: http://llvm.org/viewvc/llvm-project?rev=281520&view=rev
Log:
Add SB API's for writing breakpoints to & creating the from a file.

Moved the guts of the code from CommandObjectBreakpoint to Target (should
have done it that way in the first place.)  Added an SBBreakpointList class
so there's a way to specify which breakpoints to serialize and to report the
deserialized breakpoints.

<rdar://problem/12611863> 

Modified:
    lldb/trunk/include/lldb/API/SBBreakpoint.h
    lldb/trunk/include/lldb/API/SBTarget.h
    lldb/trunk/include/lldb/Core/StructuredData.h
    lldb/trunk/include/lldb/Target/Target.h
    lldb/trunk/scripts/interface/SBBreakpoint.i
    lldb/trunk/scripts/interface/SBTarget.i
    lldb/trunk/source/API/SBBreakpoint.cpp
    lldb/trunk/source/API/SBTarget.cpp
    lldb/trunk/source/Commands/CommandObjectBreakpoint.cpp
    lldb/trunk/source/Core/StructuredData.cpp
    lldb/trunk/source/Target/Target.cpp

Modified: lldb/trunk/include/lldb/API/SBBreakpoint.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/API/SBBreakpoint.h?rev=281520&r1=281519&r2=281520&view=diff
==============================================================================
--- lldb/trunk/include/lldb/API/SBBreakpoint.h (original)
+++ lldb/trunk/include/lldb/API/SBBreakpoint.h Wed Sep 14 14:07:35 2016
@@ -119,6 +119,7 @@ public:
   GetNumBreakpointLocationsFromEvent(const lldb::SBEvent &event_sp);
 
 private:
+  friend class SBBreakpointList;
   friend class SBBreakpointLocation;
   friend class SBTarget;
 
@@ -139,6 +140,35 @@ private:
   lldb::BreakpointSP m_opaque_sp;
 };
 
+class SBBreakpointListImpl;
+
+class LLDB_API SBBreakpointList {
+public:
+  SBBreakpointList(SBTarget &target);
+
+  ~SBBreakpointList();
+
+  size_t GetSize() const;
+
+  SBBreakpoint GetBreakpointAtIndex(size_t idx);
+
+  void Append(const SBBreakpoint &sb_file);
+
+  bool AppendIfUnique(const SBBreakpoint &sb_file);
+
+  void AppendByID(lldb::break_id_t id);
+
+  void Clear();
+
+protected:
+  friend class SBTarget;
+
+  void CopyToBreakpointIDList(lldb_private::BreakpointIDList &bp_id_list);
+
+private:
+  std::shared_ptr<SBBreakpointListImpl> m_opaque_sp;
+};
+
 } // namespace lldb
 
 #endif // LLDB_SBBreakpoint_h_

Modified: lldb/trunk/include/lldb/API/SBTarget.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/API/SBTarget.h?rev=281520&r1=281519&r2=281520&view=diff
==============================================================================
--- lldb/trunk/include/lldb/API/SBTarget.h (original)
+++ lldb/trunk/include/lldb/API/SBTarget.h Wed Sep 14 14:07:35 2016
@@ -16,6 +16,7 @@
 // Project includes
 #include "lldb/API/SBAddress.h"
 #include "lldb/API/SBAttachInfo.h"
+#include "lldb/API/SBBreakpoint.h"
 #include "lldb/API/SBBroadcaster.h"
 #include "lldb/API/SBDefines.h"
 #include "lldb/API/SBFileSpec.h"
@@ -641,6 +642,18 @@ public:
 
   lldb::SBBreakpoint BreakpointCreateBySBAddress(SBAddress &address);
 
+  // Reads in breakpoints from source_file, returning the newly created
+  // breakpoints in new_bps.
+  lldb::SBError BreakpointsCreateFromFile(SBFileSpec &source_file,
+                                          SBBreakpointList &new_bps);
+
+  // Writes all breakpoints to dest_file.
+  lldb::SBError BreakpointsWriteToFile(SBFileSpec &dest_file);
+
+  // Writes the breakpoints in bkpt_list to dest_file
+  lldb::SBError BreakpointsWriteToFile(SBFileSpec &dest_file,
+                                       SBBreakpointList &bkpt_list);
+
   uint32_t GetNumBreakpoints() const;
 
   lldb::SBBreakpoint GetBreakpointAtIndex(uint32_t idx) const;
@@ -741,6 +754,7 @@ public:
 protected:
   friend class SBAddress;
   friend class SBBlock;
+  friend class SBBreakpointListImpl;
   friend class SBDebugger;
   friend class SBExecutionContext;
   friend class SBFunction;

Modified: lldb/trunk/include/lldb/Core/StructuredData.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/StructuredData.h?rev=281520&r1=281519&r2=281520&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Core/StructuredData.h (original)
+++ lldb/trunk/include/lldb/Core/StructuredData.h Wed Sep 14 14:07:35 2016
@@ -552,7 +552,7 @@ public:
 
   static ObjectSP ParseJSON(std::string json_text);
 
-  static ObjectSP ParseJSONFromFile(FileSpec &file, Error &error);
+  static ObjectSP ParseJSONFromFile(const FileSpec &file, Error &error);
 };
 
 } // namespace lldb_private

Modified: lldb/trunk/include/lldb/Target/Target.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Target/Target.h?rev=281520&r1=281519&r2=281520&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Target/Target.h (original)
+++ lldb/trunk/include/lldb/Target/Target.h Wed Sep 14 14:07:35 2016
@@ -678,6 +678,12 @@ public:
 
   bool IgnoreWatchpointByID(lldb::watch_id_t watch_id, uint32_t ignore_count);
 
+  Error SerializeBreakpointsToFile(const FileSpec &file,
+                                   const BreakpointIDList &bp_ids);
+
+  Error CreateBreakpointsFromFile(const FileSpec &file,
+                                  BreakpointIDList &new_bps);
+
   //------------------------------------------------------------------
   /// Get \a load_addr as a callable code load address for this target
   ///
@@ -1191,10 +1197,10 @@ protected:
   Debugger &m_debugger;
   lldb::PlatformSP m_platform_sp; ///< The platform for this target.
   std::recursive_mutex m_mutex; ///< An API mutex that is used by the lldb::SB*
-                                ///classes make the SB interface thread safe
+                                /// classes make the SB interface thread safe
   ArchSpec m_arch;
   ModuleList m_images; ///< The list of images for this process (shared
-                       ///libraries and anything dynamically loaded).
+                       /// libraries and anything dynamically loaded).
   SectionLoadHistory m_section_load_history;
   BreakpointList m_breakpoint_list;
   BreakpointList m_internal_breakpoint_list;

Modified: lldb/trunk/scripts/interface/SBBreakpoint.i
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/scripts/interface/SBBreakpoint.i?rev=281520&r1=281519&r2=281520&view=diff
==============================================================================
--- lldb/trunk/scripts/interface/SBBreakpoint.i (original)
+++ lldb/trunk/scripts/interface/SBBreakpoint.i Wed Sep 14 14:07:35 2016
@@ -263,4 +263,29 @@ public:
     
 };
 
+class SBBreakpointListImpl;
+
+class LLDB_API SBBreakpointList
+{
+public:
+  SBBreakpointList(SBTarget &target);
+    
+  ~SBBreakpointList();
+
+  size_t GetSize() const;
+  
+  SBBreakpoint
+  GetBreakpointAtIndex(size_t idx);
+
+  void Append(const SBBreakpoint &sb_bkpt);
+
+  bool AppendIfUnique(const SBBreakpoint &sb_bkpt);
+
+  void AppendByID (lldb::break_id_t id);
+
+  void Clear();
+private:
+  std::shared_ptr<SBBreakpointListImpl> m_opaque_sp;
+};
+
 } // namespace lldb

Modified: lldb/trunk/scripts/interface/SBTarget.i
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/scripts/interface/SBTarget.i?rev=281520&r1=281519&r2=281520&view=diff
==============================================================================
--- lldb/trunk/scripts/interface/SBTarget.i (original)
+++ lldb/trunk/scripts/interface/SBTarget.i Wed Sep 14 14:07:35 2016
@@ -713,6 +713,16 @@ public:
     bool
     DeleteAllBreakpoints ();
 
+    lldb::SBError
+    BreakpointsCreateFromFile(SBFileSpec &source_file, 
+                              SBBreakpointList &bkpt_list);
+
+    lldb::SBError
+    BreakpointsWriteToFile(SBFileSpec &dest_file);
+      
+    lldb::SBError
+    BreakpointsWriteToFile(SBFileSpec &dest_file, SBBreakpointList &bkpt_list);
+
     uint32_t
     GetNumWatchpoints () const;
     

Modified: lldb/trunk/source/API/SBBreakpoint.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/API/SBBreakpoint.cpp?rev=281520&r1=281519&r2=281520&view=diff
==============================================================================
--- lldb/trunk/source/API/SBBreakpoint.cpp (original)
+++ lldb/trunk/source/API/SBBreakpoint.cpp Wed Sep 14 14:07:35 2016
@@ -21,6 +21,7 @@
 #include "lldb/API/SBThread.h"
 
 #include "lldb/Breakpoint/Breakpoint.h"
+#include "lldb/Breakpoint/BreakpointIDList.h"
 #include "lldb/Breakpoint/BreakpointLocation.h"
 #include "lldb/Breakpoint/StoppointCallbackContext.h"
 #include "lldb/Core/Address.h"
@@ -678,3 +679,128 @@ SBBreakpoint::GetNumBreakpointLocationsF
             event.GetSP()));
   return num_locations;
 }
+
+// This is simple collection of breakpoint id's and their target.
+class lldb::SBBreakpointListImpl {
+public:
+  SBBreakpointListImpl(SBTarget &target) : m_target_wp() {
+    if (target.IsValid())
+      m_target_wp = target.GetSP();
+  }
+
+  ~SBBreakpointListImpl() = default;
+
+  size_t GetSize() { return m_break_ids.size(); }
+
+  BreakpointSP GetBreakpointAtIndex(size_t idx) {
+    if (idx >= m_break_ids.size())
+      return BreakpointSP();
+    TargetSP target_sp = m_target_wp.lock();
+    if (!target_sp)
+      return BreakpointSP();
+    lldb::break_id_t bp_id = m_break_ids[idx];
+    return target_sp->GetBreakpointList().FindBreakpointByID(bp_id);
+  }
+
+  bool Append(Breakpoint &bkpt) {
+    TargetSP target_sp = m_target_wp.lock();
+    if (!target_sp)
+      return false;
+    if (bkpt.GetTargetSP() != target_sp)
+      return false;
+    m_break_ids.push_back(bkpt.GetID());
+    return true;
+  }
+
+  bool AppendIfUnique(Breakpoint &bkpt) {
+    TargetSP target_sp = m_target_wp.lock();
+    if (!target_sp)
+      return false;
+    if (bkpt.GetTargetSP() != target_sp)
+      return false;
+    lldb::break_id_t bp_id = bkpt.GetID();
+    if (find(m_break_ids.begin(), m_break_ids.end(), bp_id) ==
+        m_break_ids.end())
+      return false;
+
+    m_break_ids.push_back(bkpt.GetID());
+    return true;
+  }
+
+  bool AppendByID(lldb::break_id_t id) {
+    TargetSP target_sp = m_target_wp.lock();
+    if (!target_sp)
+      return false;
+    if (id == LLDB_INVALID_BREAK_ID)
+      return false;
+    m_break_ids.push_back(id);
+    return true;
+  }
+
+  void Clear() { m_break_ids.clear(); }
+
+  void CopyToBreakpointIDList(lldb_private::BreakpointIDList &bp_list) {
+    for (lldb::break_id_t id : m_break_ids) {
+      bp_list.AddBreakpointID(BreakpointID(id));
+    }
+  }
+
+  TargetSP GetTarget() { return m_target_wp.lock(); }
+
+private:
+  std::vector<lldb::break_id_t> m_break_ids;
+  TargetWP m_target_wp;
+};
+
+SBBreakpointList::SBBreakpointList(SBTarget &target)
+    : m_opaque_sp(new lldb::SBBreakpointListImpl(target)) {}
+
+SBBreakpointList::~SBBreakpointList() {}
+
+size_t SBBreakpointList::GetSize() const {
+  if (!m_opaque_sp)
+    return 0;
+  else
+    return m_opaque_sp->GetSize();
+}
+
+SBBreakpoint SBBreakpointList::GetBreakpointAtIndex(size_t idx) {
+  if (!m_opaque_sp)
+    return SBBreakpoint();
+
+  BreakpointSP bkpt_sp = m_opaque_sp->GetBreakpointAtIndex(idx);
+  return SBBreakpoint(bkpt_sp);
+}
+
+void SBBreakpointList::Append(const SBBreakpoint &sb_bkpt) {
+  if (!sb_bkpt.IsValid())
+    return;
+  if (!m_opaque_sp)
+    return;
+  m_opaque_sp->Append(*sb_bkpt.get());
+}
+
+void SBBreakpointList::AppendByID(lldb::break_id_t id) {
+  if (!m_opaque_sp)
+    return;
+  m_opaque_sp->AppendByID(id);
+}
+
+bool SBBreakpointList::AppendIfUnique(const SBBreakpoint &sb_bkpt) {
+  if (!sb_bkpt.IsValid())
+    return false;
+  if (!m_opaque_sp)
+    return false;
+  return m_opaque_sp->AppendIfUnique(*sb_bkpt.get());
+}
+
+void SBBreakpointList::Clear() {
+  if (m_opaque_sp)
+    m_opaque_sp->Clear();
+}
+
+void SBBreakpointList::CopyToBreakpointIDList(
+    lldb_private::BreakpointIDList &bp_id_list) {
+  if (m_opaque_sp)
+    m_opaque_sp->CopyToBreakpointIDList(bp_id_list);
+}

Modified: lldb/trunk/source/API/SBTarget.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/API/SBTarget.cpp?rev=281520&r1=281519&r2=281520&view=diff
==============================================================================
--- lldb/trunk/source/API/SBTarget.cpp (original)
+++ lldb/trunk/source/API/SBTarget.cpp Wed Sep 14 14:07:35 2016
@@ -1097,6 +1097,58 @@ bool SBTarget::DeleteAllBreakpoints() {
   return false;
 }
 
+lldb::SBError SBTarget::BreakpointsCreateFromFile(SBFileSpec &source_file,
+                                                  SBBreakpointList &new_bps) {
+  SBError sberr;
+  TargetSP target_sp(GetSP());
+  if (!target_sp) {
+    sberr.SetErrorString(
+        "BreakpointCreateFromFile called with invalid target.");
+    return sberr;
+  }
+  std::lock_guard<std::recursive_mutex> guard(target_sp->GetAPIMutex());
+
+  BreakpointIDList bp_ids;
+  sberr.ref() = target_sp->CreateBreakpointsFromFile(source_file.ref(), bp_ids);
+  if (sberr.Fail())
+    return sberr;
+
+  size_t num_bkpts = bp_ids.GetSize();
+  for (size_t i = 0; i < num_bkpts; i++) {
+    BreakpointID bp_id = bp_ids.GetBreakpointIDAtIndex(i);
+    new_bps.AppendByID(bp_id.GetBreakpointID());
+  }
+  return sberr;
+}
+
+lldb::SBError SBTarget::BreakpointsWriteToFile(SBFileSpec &dest_file) {
+  SBError sberr;
+  TargetSP target_sp(GetSP());
+  if (!target_sp) {
+    sberr.SetErrorString("BreakpointWriteToFile called with invalid target.");
+    return sberr;
+  }
+  SBBreakpointList bkpt_list(*this);
+  return BreakpointsWriteToFile(dest_file, bkpt_list);
+}
+
+lldb::SBError SBTarget::BreakpointsWriteToFile(SBFileSpec &dest_file,
+                                               SBBreakpointList &bkpt_list) {
+  SBError sberr;
+  TargetSP target_sp(GetSP());
+  if (!target_sp) {
+    sberr.SetErrorString("BreakpointWriteToFile called with invalid target.");
+    return sberr;
+  }
+
+  std::lock_guard<std::recursive_mutex> guard(target_sp->GetAPIMutex());
+  BreakpointIDList bp_id_list;
+  bkpt_list.CopyToBreakpointIDList(bp_id_list);
+  sberr.ref() =
+      target_sp->SerializeBreakpointsToFile(dest_file.ref(), bp_id_list);
+  return sberr;
+}
+
 uint32_t SBTarget::GetNumWatchpoints() const {
   TargetSP target_sp(GetSP());
   if (target_sp) {

Modified: lldb/trunk/source/Commands/CommandObjectBreakpoint.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Commands/CommandObjectBreakpoint.cpp?rev=281520&r1=281519&r2=281520&view=diff
==============================================================================
--- lldb/trunk/source/Commands/CommandObjectBreakpoint.cpp (original)
+++ lldb/trunk/source/Commands/CommandObjectBreakpoint.cpp Wed Sep 14 14:07:35 2016
@@ -2155,57 +2155,16 @@ protected:
       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;
-    }
+    BreakpointIDList new_bps;
+    Error error = target->CreateBreakpointsFromFile(input_spec, new_bps);
 
-    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());
+    if (!error.Success()) {
+      result.AppendError(error.AsCString());
       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);
-      }
-    }
+    // FIXME: Report the newly created breakpoints.
     return result.Succeeded();
   }
 
@@ -2295,78 +2254,26 @@ protected:
       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;
-
+    BreakpointIDList valid_bp_ids;
+    if (command.GetArgumentCount() > 0) {
       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);
-          }
-        }
+      if (!result.Succeeded()) {
+        result.SetStatus(eReturnStatusFailed);
+        return false;
       }
     }
-
-    break_store_sp->Dump(out_file, false);
-    out_file.PutChar('\n');
-
+    Error error = target->SerializeBreakpointsToFile(
+        FileSpec(m_options.m_filename.c_str(), true), valid_bp_ids);
+    if (!error.Success()) {
+      result.AppendErrorWithFormat("error serializing breakpoints: %s.",
+                                   error.AsCString());
+      result.SetStatus(eReturnStatusFailed);
+    }
     return result.Succeeded();
   }
 

Modified: lldb/trunk/source/Core/StructuredData.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/StructuredData.cpp?rev=281520&r1=281519&r2=281520&view=diff
==============================================================================
--- lldb/trunk/source/Core/StructuredData.cpp (original)
+++ lldb/trunk/source/Core/StructuredData.cpp Wed Sep 14 14:07:35 2016
@@ -31,8 +31,8 @@ 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
+StructuredData::ParseJSONFromFile(const FileSpec &input_spec, Error &error) {
   StructuredData::ObjectSP return_sp;
   if (!input_spec.Exists()) {
     error.SetErrorStringWithFormat("input file %s does not exist.",

Modified: lldb/trunk/source/Target/Target.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/Target.cpp?rev=281520&r1=281519&r2=281520&view=diff
==============================================================================
--- lldb/trunk/source/Target/Target.cpp (original)
+++ lldb/trunk/source/Target/Target.cpp Wed Sep 14 14:07:35 2016
@@ -15,6 +15,7 @@
 #include "Plugins/ExpressionParser/Clang/ClangASTSource.h"
 #include "Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.h"
 #include "Plugins/ExpressionParser/Clang/ClangPersistentVariables.h"
+#include "lldb/Breakpoint/BreakpointIDList.h"
 #include "lldb/Breakpoint/BreakpointResolver.h"
 #include "lldb/Breakpoint/BreakpointResolverAddress.h"
 #include "lldb/Breakpoint/BreakpointResolverFileLine.h"
@@ -794,6 +795,127 @@ bool Target::EnableBreakpointByID(break_
   return false;
 }
 
+Error Target::SerializeBreakpointsToFile(const FileSpec &file,
+                                         const BreakpointIDList &bp_ids) {
+  Error error;
+
+  if (!file) {
+    error.SetErrorString("Invalid FileSpec.");
+    return error;
+  }
+
+  std::string path(file.GetPath());
+  StreamFile out_file(path.c_str(),
+                      File::OpenOptions::eOpenOptionTruncate |
+                          File::OpenOptions::eOpenOptionWrite |
+                          File::OpenOptions::eOpenOptionCanCreate |
+                          File::OpenOptions::eOpenOptionCloseOnExec,
+                      lldb::eFilePermissionsFileDefault);
+  if (!out_file.GetFile().IsValid()) {
+    error.SetErrorStringWithFormat("Unable to open output file: %s.",
+                                   path.c_str());
+    return error;
+  }
+
+  std::unique_lock<std::recursive_mutex> lock;
+  GetBreakpointList().GetListMutex(lock);
+
+  StructuredData::ArraySP break_store_sp(new StructuredData::Array());
+  if (bp_ids.GetSize() == 0) {
+    const BreakpointList &breakpoints = 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 {
+
+    std::unordered_set<lldb::break_id_t> processed_bkpts;
+    const size_t count = bp_ids.GetSize();
+    for (size_t i = 0; i < count; ++i) {
+      BreakpointID cur_bp_id = 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 = 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) {
+          error.SetErrorStringWithFormat("Unable to serialize breakpoint %d",
+                                         bp_id);
+          return error;
+        }
+        break_store_sp->AddItem(bkpt_save_sp);
+      }
+    }
+  }
+
+  break_store_sp->Dump(out_file, false);
+  out_file.PutChar('\n');
+  return error;
+}
+
+Error Target::CreateBreakpointsFromFile(const FileSpec &file,
+                                        BreakpointIDList &new_bps) {
+  std::unique_lock<std::recursive_mutex> lock;
+  GetBreakpointList().GetListMutex(lock);
+
+  Error error;
+  StructuredData::ObjectSP input_data_sp =
+      StructuredData::ParseJSONFromFile(file, error);
+  if (!error.Success()) {
+    return error;
+  } else if (!input_data_sp || !input_data_sp->IsValid()) {
+    error.SetErrorStringWithFormat("Invalid JSON from input file: %s.",
+                                   file.GetPath().c_str());
+    return error;
+  }
+
+  StructuredData::Array *bkpt_array = input_data_sp->GetAsArray();
+  if (!bkpt_array) {
+    error.SetErrorStringWithFormat(
+        "Invalid breakpoint data from input file: %s.", file.GetPath().c_str());
+    return error;
+  }
+
+  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) {
+      error.SetErrorStringWithFormat(
+          "Invalid breakpoint data for element %zu from input file: %s.", i,
+          file.GetPath().c_str());
+      return error;
+    }
+    StructuredData::ObjectSP bkpt_data_sp =
+        bkpt_dict->GetValueForKey(Breakpoint::GetSerializationKey());
+    BreakpointSP bkpt_sp =
+        Breakpoint::CreateFromStructuredData(*this, bkpt_data_sp, error);
+    if (!error.Success()) {
+      error.SetErrorStringWithFormat(
+          "Error restoring breakpoint %zu from %s: %s.", i,
+          file.GetPath().c_str(), error.AsCString());
+      return error;
+    }
+    new_bps.AddBreakpointID(BreakpointID(bkpt_sp->GetID()));
+  }
+  return error;
+}
+
 // The flag 'end_to_end', default to true, signifies that the operation is
 // performed end to end, for both the debugger and the debuggee.
 




More information about the lldb-commits mailing list