Add the ability to deserialize only breakpoints matching a given name.
Also tests for this and the ThreadSpec serialization.
llvm-svn: 282207
diff --git a/lldb/source/API/SBTarget.cpp b/lldb/source/API/SBTarget.cpp
index 8616d22..54ed098 100644
--- a/lldb/source/API/SBTarget.cpp
+++ b/lldb/source/API/SBTarget.cpp
@@ -1128,6 +1128,13 @@
lldb::SBError SBTarget::BreakpointsCreateFromFile(SBFileSpec &source_file,
SBBreakpointList &new_bps) {
+ SBStringList empty_name_list;
+ return BreakpointsCreateFromFile(source_file, empty_name_list, new_bps);
+}
+
+lldb::SBError SBTarget::BreakpointsCreateFromFile(SBFileSpec &source_file,
+ SBStringList &matching_names,
+ SBBreakpointList &new_bps) {
SBError sberr;
TargetSP target_sp(GetSP());
if (!target_sp) {
@@ -1138,7 +1145,14 @@
std::lock_guard<std::recursive_mutex> guard(target_sp->GetAPIMutex());
BreakpointIDList bp_ids;
- sberr.ref() = target_sp->CreateBreakpointsFromFile(source_file.ref(), bp_ids);
+
+ std::vector<std::string> name_vector;
+ size_t num_names = matching_names.GetSize();
+ for (size_t i = 0; i < num_names; i++)
+ name_vector.push_back(matching_names.GetStringAtIndex(i));
+
+ sberr.ref() = target_sp->CreateBreakpointsFromFile(source_file.ref(),
+ name_vector, bp_ids);
if (sberr.Fail())
return sberr;
diff --git a/lldb/source/Breakpoint/Breakpoint.cpp b/lldb/source/Breakpoint/Breakpoint.cpp
index a9666f4..9f4376c 100644
--- a/lldb/source/Breakpoint/Breakpoint.cpp
+++ b/lldb/source/Breakpoint/Breakpoint.cpp
@@ -216,6 +216,41 @@
return result_sp;
}
+bool Breakpoint::SerializedBreakpointMatchesNames(
+ StructuredData::ObjectSP &bkpt_object_sp, std::vector<std::string> &names) {
+ if (!bkpt_object_sp)
+ return false;
+
+ StructuredData::Dictionary *bkpt_dict = bkpt_object_sp->GetAsDictionary();
+ if (!bkpt_dict)
+ return false;
+
+ if (names.empty())
+ return true;
+
+ StructuredData::Array *names_array;
+
+ bool success =
+ bkpt_dict->GetValueForKeyAsArray(GetKey(OptionNames::Names), names_array);
+ // If there are no names, it can't match these names;
+ if (!success)
+ return false;
+
+ size_t num_names = names_array->GetSize();
+ std::vector<std::string>::iterator begin = names.begin();
+ std::vector<std::string>::iterator end = names.end();
+
+ for (size_t i = 0; i < num_names; i++) {
+ std::string name;
+ if (names_array->GetItemAtIndexAsString(i, name)) {
+ if (std::find(begin, end, name) != end) {
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
const lldb::TargetSP Breakpoint::GetTargetSP() {
return m_target.shared_from_this();
}
diff --git a/lldb/source/Commands/CommandObjectBreakpoint.cpp b/lldb/source/Commands/CommandObjectBreakpoint.cpp
index 13235d7..1e90b57 100644
--- a/lldb/source/Commands/CommandObjectBreakpoint.cpp
+++ b/lldb/source/Commands/CommandObjectBreakpoint.cpp
@@ -2077,10 +2077,11 @@
//-------------------------------------------------------------------------
// CommandObjectBreakpointRead
//-------------------------------------------------------------------------
-#pragma mark Modify::CommandOptions
+#pragma mark Read::CommandOptions
static OptionDefinition g_breakpoint_read_options[] = {
// 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." },
+ { LLDB_OPT_SET_ALL, true, "file", 'f', OptionParser::eRequiredArgument, nullptr, nullptr, CommandCompletions::eDiskFileCompletion, eArgTypeFilename, "The file from which to read the breakpoints." },
+ {LLDB_OPT_SET_ALL, false, "breakpoint-name", 'N', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBreakpointName, "Only read in breakpoints with this name."},
// clang-format on
};
@@ -2121,6 +2122,16 @@
case 'f':
m_filename.assign(option_arg);
break;
+ case 'N': {
+ Error name_error;
+ if (!BreakpointID::StringIsBreakpointName(llvm::StringRef(option_arg),
+ name_error)) {
+ error.SetErrorStringWithFormat("Invalid breakpoint name: %s",
+ name_error.AsCString());
+ }
+ m_names.push_back(option_arg);
+ break;
+ }
default:
error.SetErrorStringWithFormat("unrecognized option '%c'",
short_option);
@@ -2132,6 +2143,7 @@
void OptionParsingStarting(ExecutionContext *execution_context) override {
m_filename.clear();
+ m_names.clear();
}
llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
@@ -2141,6 +2153,7 @@
// Instance variables to hold the values for command options.
std::string m_filename;
+ std::vector<std::string> m_names;
};
protected:
@@ -2152,16 +2165,38 @@
return false;
}
+ std::unique_lock<std::recursive_mutex> lock;
+ target->GetBreakpointList().GetListMutex(lock);
+
FileSpec input_spec(m_options.m_filename, true);
BreakpointIDList new_bps;
- Error error = target->CreateBreakpointsFromFile(input_spec, new_bps);
+ Error error = target->CreateBreakpointsFromFile(input_spec,
+ m_options.m_names, new_bps);
if (!error.Success()) {
result.AppendError(error.AsCString());
result.SetStatus(eReturnStatusFailed);
return false;
}
- // FIXME: Report the newly created breakpoints.
+
+ Stream &output_stream = result.GetOutputStream();
+
+ size_t num_breakpoints = new_bps.GetSize();
+ if (num_breakpoints == 0) {
+ result.AppendMessage("No breakpoints added.");
+ } else {
+ // No breakpoint selected; show info about all currently set breakpoints.
+ result.AppendMessage("New breakpoints:");
+ for (size_t i = 0; i < num_breakpoints; ++i) {
+ BreakpointID bp_id = new_bps.GetBreakpointIDAtIndex(i);
+ Breakpoint *bp = target->GetBreakpointList()
+ .FindBreakpointByID(bp_id.GetBreakpointID())
+ .get();
+ if (bp)
+ bp->GetDescription(&output_stream, lldb::eDescriptionLevelInitial,
+ false);
+ }
+ }
return result.Succeeded();
}
diff --git a/lldb/source/Target/Target.cpp b/lldb/source/Target/Target.cpp
index 0b612c6..d73cc84 100644
--- a/lldb/source/Target/Target.cpp
+++ b/lldb/source/Target/Target.cpp
@@ -869,6 +869,13 @@
Error Target::CreateBreakpointsFromFile(const FileSpec &file,
BreakpointIDList &new_bps) {
+ std::vector<std::string> no_names;
+ return CreateBreakpointsFromFile(file, no_names, new_bps);
+}
+
+Error Target::CreateBreakpointsFromFile(const FileSpec &file,
+ std::vector<std::string> &names,
+ BreakpointIDList &new_bps) {
std::unique_lock<std::recursive_mutex> lock;
GetBreakpointList().GetListMutex(lock);
@@ -891,6 +898,8 @@
}
size_t num_bkpts = bkpt_array->GetSize();
+ size_t num_names = names.size();
+
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:
@@ -903,6 +912,10 @@
}
StructuredData::ObjectSP bkpt_data_sp =
bkpt_dict->GetValueForKey(Breakpoint::GetSerializationKey());
+ if (num_names &&
+ !Breakpoint::SerializedBreakpointMatchesNames(bkpt_data_sp, names))
+ continue;
+
BreakpointSP bkpt_sp =
Breakpoint::CreateFromStructuredData(*this, bkpt_data_sp, error);
if (!error.Success()) {