Add the ability to deserialize only breakpoints matching a given name.

Also tests for this and the ThreadSpec serialization.

llvm-svn: 282207
This commit is contained in:
Jim Ingham 2016-09-22 22:20:28 +00:00
parent fcee2d8001
commit 3acdf38519
9 changed files with 264 additions and 12 deletions

View File

@ -646,15 +646,66 @@ public:
lldb::SBBreakpoint BreakpointCreateBySBAddress(SBAddress &address);
// Reads in breakpoints from source_file, returning the newly created
// breakpoints in new_bps.
//------------------------------------------------------------------
/// Read breakpoints from source_file and return the newly created
/// breakpoints in bkpt_list.
///
/// @param[in] source_file
/// The file from which to read the breakpoints.
///
/// @param[out] bkpt_list
/// A list of the newly created breakpoints.
///
/// @return
/// An SBError detailing any errors in reading in the breakpoints.
//------------------------------------------------------------------
lldb::SBError BreakpointsCreateFromFile(SBFileSpec &source_file,
SBBreakpointList &new_bps);
// Writes all breakpoints to dest_file.
//------------------------------------------------------------------
/// Read breakpoints from source_file and return the newly created
/// breakpoints in bkpt_list.
///
/// @param[in] source_file
/// The file from which to read the breakpoints.
///
/// @param[in] matching_names
/// Only read in breakpoints whose names match one of the names in this
/// list.
///
/// @param[out] bkpt_list
/// A list of the newly created breakpoints.
///
/// @return
/// An SBError detailing any errors in reading in the breakpoints.
//------------------------------------------------------------------
lldb::SBError BreakpointsCreateFromFile(SBFileSpec &source_file,
SBStringList &matching_names,
SBBreakpointList &new_bps);
//------------------------------------------------------------------
/// Write breakpoints to dest_file.
///
/// @param[in] dest_file
/// The file to which to write the breakpoints.
///
/// @return
/// An SBError detailing any errors in writing in the breakpoints.
//------------------------------------------------------------------
lldb::SBError BreakpointsWriteToFile(SBFileSpec &dest_file);
// Writes the breakpoints in bkpt_list to dest_file
//------------------------------------------------------------------
/// Write breakpoints listed in bkpt_list to dest_file.
///
/// @param[in] dest_file
/// The file to which to write the breakpoints.
///
/// @param[in] bkpt_list
/// Only write breakpoints from this list.
///
/// @return
/// An SBError detailing any errors in writing in the breakpoints.
//------------------------------------------------------------------
lldb::SBError BreakpointsWriteToFile(SBFileSpec &dest_file,
SBBreakpointList &bkpt_list);

View File

@ -180,6 +180,10 @@ public:
static lldb::BreakpointSP CreateFromStructuredData(
Target &target, StructuredData::ObjectSP &data_object_sp, Error &error);
static bool
SerializedBreakpointMatchesNames(StructuredData::ObjectSP &bkpt_object_sp,
std::vector<std::string> &names);
virtual StructuredData::ObjectSP SerializeToStructuredData();
static const char *GetSerializationKey() { return "Breakpoint"; }

View File

@ -684,6 +684,10 @@ public:
Error CreateBreakpointsFromFile(const FileSpec &file,
BreakpointIDList &new_bps);
Error CreateBreakpointsFromFile(const FileSpec &file,
std::vector<std::string> &names,
BreakpointIDList &new_bps);
//------------------------------------------------------------------
/// Get \a load_addr as a callable code load address for this target
///

View File

@ -37,6 +37,12 @@ class BreakpointSerialization(TestBase):
self.setup_targets_and_cleanup()
self.do_check_options()
def test_name_filters(self):
"""Use python APIs to test that reading in by name works correctly."""
self.build()
self.setup_targets_and_cleanup()
self.do_check_names()
def setup_targets_and_cleanup(self):
def cleanup ():
self.RemoveTempFile(self.bkpts_file_path)
@ -50,7 +56,7 @@ class BreakpointSerialization(TestBase):
exe = os.path.join(os.getcwd(), "a.out")
# Create a targets we are making breakpoint in and copying to:
# Create the targets we are making breakpoints in and copying them to:
self.orig_target = self.dbg.CreateTarget(exe)
self.assertTrue(self.orig_target, VALID_TARGET)
@ -169,6 +175,7 @@ class BreakpointSerialization(TestBase):
bkpt = self.orig_target.BreakpointCreateByLocation("blubby.c", 666)
bkpt.SetEnabled(False)
bkpt.SetOneShot(True)
bkpt.SetThreadID(10)
source_bps.Append(bkpt)
# Make sure we get one right:
@ -177,10 +184,12 @@ class BreakpointSerialization(TestBase):
bkpt = self.orig_target.BreakpointCreateByName("blubby", lldb.eFunctionNameTypeAuto, empty_module_list, empty_cu_list)
bkpt.SetIgnoreCount(10)
bkpt.SetThreadName("grubby")
source_bps.Append(bkpt)
bkpt = self.orig_target.BreakpointCreateByName("blubby", lldb.eFunctionNameTypeFull, empty_module_list,empty_cu_list)
bkpt.SetCondition("something != something_else")
bkpt.SetQueueName("grubby")
bkpt.AddName("FirstName")
bkpt.AddName("SecondName")
@ -196,6 +205,30 @@ class BreakpointSerialization(TestBase):
self.check_equivalence(source_bps)
def do_check_names(self):
bkpt = self.orig_target.BreakpointCreateByLocation("blubby.c", 666)
good_bkpt_name = "GoodBreakpoint"
write_bps = lldb.SBBreakpointList(self.orig_target)
bkpt.AddName(good_bkpt_name)
write_bps.Append(bkpt)
error = lldb.SBError()
error = self.orig_target.BreakpointsWriteToFile(self.bkpts_file_spec, write_bps)
self.assertTrue(error.Success(), "Failed writing breakpoints to file: %s."%(error.GetCString()))
copy_bps = lldb.SBBreakpointList(self.copy_target)
names_list = lldb.SBStringList()
names_list.AppendString("NoSuchName")
error = self.copy_target.BreakpointsCreateFromFile(self.bkpts_file_spec, names_list, copy_bps)
self.assertTrue(error.Success(), "Failed reading breakpoints from file: %s"%(error.GetCString()))
self.assertTrue(copy_bps.GetSize() == 0, "Found breakpoints with a nonexistent name.")
names_list.AppendString(good_bkpt_name)
error = self.copy_target.BreakpointsCreateFromFile(self.bkpts_file_spec, names_list, copy_bps)
self.assertTrue(error.Success(), "Failed reading breakpoints from file: %s"%(error.GetCString()))
self.assertTrue(copy_bps.GetSize() == 1, "Found the matching breakpoint.")

View File

@ -720,13 +720,76 @@ public:
bool
DeleteAllBreakpoints ();
%feature("docstring", "
//------------------------------------------------------------------
/// Read breakpoints from source_file and return the newly created
/// breakpoints in bkpt_list.
///
/// @param[in] source_file
/// The file from which to read the breakpoints
///
/// @param[out] bkpt_list
/// A list of the newly created breakpoints.
///
/// @return
/// An SBError detailing any errors in reading in the breakpoints.
//------------------------------------------------------------------
") BreakpointsCreateFromFile;
lldb::SBError
BreakpointsCreateFromFile(SBFileSpec &source_file,
SBBreakpointList &bkpt_list);
%feature("docstring", "
//------------------------------------------------------------------
/// Read breakpoints from source_file and return the newly created
/// breakpoints in bkpt_list.
///
/// @param[in] source_file
/// The file from which to read the breakpoints
///
/// @param[in] matching_names
/// Only read in breakpoints whose names match one of the names in this
/// list.
///
/// @param[out] bkpt_list
/// A list of the newly created breakpoints.
///
/// @return
/// An SBError detailing any errors in reading in the breakpoints.
//------------------------------------------------------------------
") BreakpointsCreateFromFile;
lldb::SBError BreakpointsCreateFromFile(SBFileSpec &source_file,
SBStringList &matching_names,
SBBreakpointList &new_bps);
%feature("docstring", "
//------------------------------------------------------------------
/// Write breakpoints to dest_file.
///
/// @param[in] dest_file
/// The file to which to write the breakpoints.
///
/// @return
/// An SBError detailing any errors in writing in the breakpoints.
//------------------------------------------------------------------
") BreakpointsCreateFromFile;
lldb::SBError
BreakpointsWriteToFile(SBFileSpec &dest_file);
%feature("docstring", "
//------------------------------------------------------------------
/// Write breakpoints listed in bkpt_list to dest_file.
///
/// @param[in] dest_file
/// The file to which to write the breakpoints.
///
/// @param[in] bkpt_list
/// Only write breakpoints from this list.
///
/// @return
/// An SBError detailing any errors in writing in the breakpoints.
//------------------------------------------------------------------
") BreakpointsCreateFromFile;
lldb::SBError
BreakpointsWriteToFile(SBFileSpec &dest_file, SBBreakpointList &bkpt_list);

View File

@ -1128,6 +1128,13 @@ bool SBTarget::DeleteAllBreakpoints() {
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 @@ lldb::SBError SBTarget::BreakpointsCreateFromFile(SBFileSpec &source_file,
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;

View File

@ -216,6 +216,41 @@ lldb::BreakpointSP Breakpoint::CreateFromStructuredData(
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();
}

View File

@ -2077,10 +2077,11 @@ public:
//-------------------------------------------------------------------------
// 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 @@ public:
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 @@ public:
void OptionParsingStarting(ExecutionContext *execution_context) override {
m_filename.clear();
m_names.clear();
}
llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
@ -2141,6 +2153,7 @@ public:
// Instance variables to hold the values for command options.
std::string m_filename;
std::vector<std::string> m_names;
};
protected:
@ -2152,16 +2165,38 @@ protected:
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();
}

View File

@ -869,6 +869,13 @@ Error Target::SerializeBreakpointsToFile(const FileSpec &file,
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 @@ Error Target::CreateBreakpointsFromFile(const FileSpec &file,
}
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 @@ Error Target::CreateBreakpointsFromFile(const FileSpec &file,
}
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()) {