Add the ability to append breakpoints to the save file.

llvm-svn: 282212
This commit is contained in:
Jim Ingham 2016-09-22 23:42:42 +00:00
parent be0ed59cdc
commit 2d3628e1f0
7 changed files with 113 additions and 16 deletions

View File

@ -703,11 +703,17 @@ public:
/// @param[in] bkpt_list
/// Only write breakpoints from this list.
///
/// @param[in] append
/// If \btrue, append the breakpoints in bkpt_list to the others
/// serialized in dest_file. If dest_file doesn't exist, then a new
/// file will be created and the breakpoints in bkpt_list written to it.
///
/// @return
/// An SBError detailing any errors in writing in the breakpoints.
//------------------------------------------------------------------
lldb::SBError BreakpointsWriteToFile(SBFileSpec &dest_file,
SBBreakpointList &bkpt_list);
SBBreakpointList &bkpt_list,
bool append = false);
uint32_t GetNumBreakpoints() const;

View File

@ -679,7 +679,7 @@ public:
bool IgnoreWatchpointByID(lldb::watch_id_t watch_id, uint32_t ignore_count);
Error SerializeBreakpointsToFile(const FileSpec &file,
const BreakpointIDList &bp_ids);
const BreakpointIDList &bp_ids, bool append);
Error CreateBreakpointsFromFile(const FileSpec &file,
BreakpointIDList &new_bps);

View File

@ -37,6 +37,12 @@ class BreakpointSerialization(TestBase):
self.setup_targets_and_cleanup()
self.do_check_options()
def test_appending(self):
"""Use Python APIs to test that we serialize breakpoint options correctly."""
self.build()
self.setup_targets_and_cleanup()
self.do_check_appending()
def test_name_filters(self):
"""Use python APIs to test that reading in by name works correctly."""
self.build()
@ -70,11 +76,13 @@ class BreakpointSerialization(TestBase):
self.bkpts_file_path = os.path.join(os.getcwd(), "breakpoints.json")
self.bkpts_file_spec = lldb.SBFileSpec(self.bkpts_file_path)
def check_equivalence(self, source_bps):
def check_equivalence(self, source_bps, do_write = True):
error = lldb.SBError()
error = self.orig_target.BreakpointsWriteToFile(self.bkpts_file_spec, source_bps)
self.assertTrue(error.Success(), "Failed writing breakpoints to file: %s."%(error.GetCString()))
if (do_write):
error = self.orig_target.BreakpointsWriteToFile(self.bkpts_file_spec, source_bps)
self.assertTrue(error.Success(), "Failed writing breakpoints to file: %s."%(error.GetCString()))
copy_bps = lldb.SBBreakpointList(self.copy_target)
error = self.copy_target.BreakpointsCreateFromFile(self.bkpts_file_spec, copy_bps)
@ -205,6 +213,52 @@ class BreakpointSerialization(TestBase):
self.check_equivalence(source_bps)
def do_check_appending(self):
"""Use Python APIs to check appending to already serialized options."""
empty_module_list = lldb.SBFileSpecList()
empty_cu_list = lldb.SBFileSpecList()
blubby_file_spec = lldb.SBFileSpec(os.path.join(os.getcwd(), "blubby.c"))
# It isn't actually important for these purposes that these breakpoint
# actually have locations.
all_bps = lldb.SBBreakpointList(self.orig_target)
source_bps = lldb.SBBreakpointList(self.orig_target)
bkpt = self.orig_target.BreakpointCreateByLocation("blubby.c", 666)
bkpt.SetEnabled(False)
bkpt.SetOneShot(True)
bkpt.SetThreadID(10)
source_bps.Append(bkpt)
all_bps.Append(bkpt)
error = lldb.SBError()
error = self.orig_target.BreakpointsWriteToFile(self.bkpts_file_spec, source_bps)
self.assertTrue(error.Success(), "Failed writing breakpoints to file: %s."%(error.GetCString()))
source_bps.Clear()
bkpt = self.orig_target.BreakpointCreateByName("blubby", lldb.eFunctionNameTypeAuto, empty_module_list, empty_cu_list)
bkpt.SetIgnoreCount(10)
bkpt.SetThreadName("grubby")
source_bps.Append(bkpt)
all_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")
source_bps.Append(bkpt)
all_bps.Append(bkpt)
error = self.orig_target.BreakpointsWriteToFile(self.bkpts_file_spec, source_bps, True)
self.assertTrue(error.Success(), "Failed appending breakpoints to file: %s."%(error.GetCString()))
self.check_equivalence(all_bps)
def do_check_names(self):
bkpt = self.orig_target.BreakpointCreateByLocation("blubby.c", 666)
good_bkpt_name = "GoodBreakpoint"

View File

@ -786,12 +786,19 @@ public:
/// @param[in] bkpt_list
/// Only write breakpoints from this list.
///
/// @param[in] append
/// If \btrue, append the breakpoints in bkpt_list to the others
/// serialized in dest_file. If dest_file doesn't exist, then a new
/// file will be created and the breakpoints in bkpt_list written to it.
///
/// @return
/// An SBError detailing any errors in writing in the breakpoints.
//------------------------------------------------------------------
") BreakpointsCreateFromFile;
lldb::SBError
BreakpointsWriteToFile(SBFileSpec &dest_file, SBBreakpointList &bkpt_list);
BreakpointsWriteToFile(SBFileSpec &dest_file,
SBBreakpointList &bkpt_list,
bool append = false);
uint32_t
GetNumWatchpoints () const;

View File

@ -1176,7 +1176,8 @@ lldb::SBError SBTarget::BreakpointsWriteToFile(SBFileSpec &dest_file) {
}
lldb::SBError SBTarget::BreakpointsWriteToFile(SBFileSpec &dest_file,
SBBreakpointList &bkpt_list) {
SBBreakpointList &bkpt_list,
bool append) {
SBError sberr;
TargetSP target_sp(GetSP());
if (!target_sp) {
@ -1187,8 +1188,8 @@ lldb::SBError SBTarget::BreakpointsWriteToFile(SBFileSpec &dest_file,
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);
sberr.ref() = target_sp->SerializeBreakpointsToFile(dest_file.ref(),
bp_id_list, append);
return sberr;
}

View File

@ -2210,7 +2210,8 @@ private:
#pragma mark Write::CommandOptions
static OptionDefinition g_breakpoint_write_options[] = {
// clang-format off
{ LLDB_OPT_SET_ALL, true, "file", 'f', OptionParser::eRequiredArgument, nullptr, nullptr, CommandCompletions::eDiskFileCompletion, eArgTypeFilename, "The file into which to write the breakpoints." },
{ LLDB_OPT_SET_ALL, true, "file", 'f', OptionParser::eRequiredArgument, nullptr, nullptr, CommandCompletions::eDiskFileCompletion, eArgTypeFilename, "The file into which to write the breakpoints." },
{ LLDB_OPT_SET_ALL, false, "append",'a', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Append to saved breakpoints file if it exists."},
// clang-format on
};
@ -2251,6 +2252,9 @@ public:
case 'f':
m_filename.assign(option_arg);
break;
case 'a':
m_append = true;
break;
default:
error.SetErrorStringWithFormat("unrecognized option '%c'",
short_option);
@ -2262,6 +2266,7 @@ public:
void OptionParsingStarting(ExecutionContext *execution_context) override {
m_filename.clear();
m_append = false;
}
llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
@ -2271,6 +2276,7 @@ public:
// Instance variables to hold the values for command options.
std::string m_filename;
bool m_append = false;
};
protected:
@ -2296,7 +2302,8 @@ protected:
}
}
Error error = target->SerializeBreakpointsToFile(
FileSpec(m_options.m_filename.c_str(), true), valid_bp_ids);
FileSpec(m_options.m_filename.c_str(), true), valid_bp_ids,
m_options.m_append);
if (!error.Success()) {
result.AppendErrorWithFormat("error serializing breakpoints: %s.",
error.AsCString());

View File

@ -796,7 +796,8 @@ bool Target::EnableBreakpointByID(break_id_t break_id) {
}
Error Target::SerializeBreakpointsToFile(const FileSpec &file,
const BreakpointIDList &bp_ids) {
const BreakpointIDList &bp_ids,
bool append) {
Error error;
if (!file) {
@ -805,6 +806,28 @@ Error Target::SerializeBreakpointsToFile(const FileSpec &file,
}
std::string path(file.GetPath());
StructuredData::ObjectSP input_data_sp;
StructuredData::ArraySP break_store_sp;
StructuredData::Array *break_store_ptr = nullptr;
if (append) {
input_data_sp = StructuredData::ParseJSONFromFile(file, error);
if (error.Success()) {
break_store_ptr = input_data_sp->GetAsArray();
if (!break_store_ptr) {
error.SetErrorStringWithFormat(
"Tried to append to invalid input file %s", path.c_str());
return error;
}
}
}
if (!break_store_ptr) {
break_store_sp.reset(new StructuredData::Array());
break_store_ptr = break_store_sp.get();
}
StreamFile out_file(path.c_str(),
File::OpenOptions::eOpenOptionTruncate |
File::OpenOptions::eOpenOptionWrite |
@ -820,7 +843,6 @@ Error Target::SerializeBreakpointsToFile(const FileSpec &file,
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();
@ -830,7 +852,7 @@ Error Target::SerializeBreakpointsToFile(const FileSpec &file,
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);
break_store_ptr->AddItem(bkpt_save_sp);
}
} else {
@ -857,12 +879,12 @@ Error Target::SerializeBreakpointsToFile(const FileSpec &file,
bp_id);
return error;
}
break_store_sp->AddItem(bkpt_save_sp);
break_store_ptr->AddItem(bkpt_save_sp);
}
}
}
break_store_sp->Dump(out_file, false);
break_store_ptr->Dump(out_file, false);
out_file.PutChar('\n');
return error;
}