[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