diff options
| author | Jim Ingham <jingham@apple.com> | 2016-09-14 19:07:35 +0000 |
|---|---|---|
| committer | Jim Ingham <jingham@apple.com> | 2016-09-14 19:07:35 +0000 |
| commit | 01f166647195b7ffff11d270648a679fb7b65bf1 (patch) | |
| tree | 368f3c232731851a4f0a9b3d5e5038669aed6af0 /lldb/source/Target/Target.cpp | |
| parent | db30877477e0c6434fd4a62ada3cd7916a79efa5 (diff) | |
| download | bcm5719-llvm-01f166647195b7ffff11d270648a679fb7b65bf1.tar.gz bcm5719-llvm-01f166647195b7ffff11d270648a679fb7b65bf1.zip | |
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>
llvm-svn: 281520
Diffstat (limited to 'lldb/source/Target/Target.cpp')
| -rw-r--r-- | lldb/source/Target/Target.cpp | 122 |
1 files changed, 122 insertions, 0 deletions
diff --git a/lldb/source/Target/Target.cpp b/lldb/source/Target/Target.cpp index bd8ae563319..0b612c6ddae 100644 --- a/lldb/source/Target/Target.cpp +++ b/lldb/source/Target/Target.cpp @@ -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_id_t break_id) { 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. |

