forked from OSchip/llvm-project
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:
parent
fcee2d8001
commit
3acdf38519
|
@ -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);
|
||||
|
||||
|
|
|
@ -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"; }
|
||||
|
|
|
@ -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
|
||||
///
|
||||
|
|
|
@ -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.")
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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()) {
|
||||
|
|
Loading…
Reference in New Issue