Skip to content

Commit

Permalink
Add an auto-continue flag to breakpoints & locations.
Browse files Browse the repository at this point in the history
You can get a breakpoint to auto-continue by adding "continue"
as a command, but that has the disadvantage that if you hit two
breakpoints simultaneously, the continue will force the process
to continue, and maybe even forstalling the commands on the other.
The auto-continue flag means the breakpoints can negotiate about
whether to stop.

Writing tests, I wanted to supply some commands when I made the
breakpoints, so I also added that ability.

llvm-svn: 309969
  • Loading branch information
jimingham committed Aug 3, 2017
1 parent f0cadcd commit f08f5c9
Show file tree
Hide file tree
Showing 16 changed files with 273 additions and 29 deletions.
4 changes: 4 additions & 0 deletions lldb/include/lldb/API/SBBreakpoint.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,10 @@ class LLDB_API SBBreakpoint {

const char *GetCondition();

void SetAutoContinue(bool auto_continue);

bool GetAutoContinue();

void SetThreadID(lldb::tid_t sb_thread_id);

lldb::tid_t GetThreadID();
Expand Down
4 changes: 4 additions & 0 deletions lldb/include/lldb/API/SBBreakpointLocation.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,10 @@ class LLDB_API SBBreakpointLocation {
void SetCondition(const char *condition);

const char *GetCondition();

void SetAutoContinue(bool auto_continue);

bool GetAutoContinue();

void SetScriptCallbackFunction(const char *callback_function_name);

Expand Down
12 changes: 12 additions & 0 deletions lldb/include/lldb/Breakpoint/Breakpoint.h
Original file line number Diff line number Diff line change
Expand Up @@ -420,6 +420,18 @@ class Breakpoint : public std::enable_shared_from_this<Breakpoint>,
//------------------------------------------------------------------
bool IsOneShot() const;

//------------------------------------------------------------------
/// If \a auto_continue is \b true, breakpoint will auto-continue when on hit.
//------------------------------------------------------------------
void SetAutoContinue(bool auto_continue);

//------------------------------------------------------------------
/// Check the AutoContinue state.
/// @return
/// \b true if the breakpoint is set to auto-continue, \b false otherwise.
//------------------------------------------------------------------
bool IsAutoContinue() const;

//------------------------------------------------------------------
/// Set the valid thread to be checked when the breakpoint is hit.
/// @param[in] thread_id
Expand Down
13 changes: 13 additions & 0 deletions lldb/include/lldb/Breakpoint/BreakpointLocation.h
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,19 @@ class BreakpointLocation
//------------------------------------------------------------------
bool IsEnabled() const;

//------------------------------------------------------------------
/// If \a auto_continue is \b true, set the breakpoint to continue when hit.
//------------------------------------------------------------------
void SetAutoContinue(bool auto_continue);

//------------------------------------------------------------------
/// Check the AutoContinue state.
///
/// @return
/// \b true if the breakpoint is set to auto-continue, \b false if not.
//------------------------------------------------------------------
bool IsAutoContinue() const;

//------------------------------------------------------------------
/// Return the current Ignore Count.
///
Expand Down
33 changes: 26 additions & 7 deletions lldb/include/lldb/Breakpoint/BreakpointOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,13 @@ friend class Breakpoint;

public:
enum OptionKind {
eCallback = 1 << 0,
eEnabled = 1 << 1,
eOneShot = 1 << 2,
eIgnoreCount = 1 << 3,
eThreadSpec = 1 << 4,
eCondition = 1 << 5
eCallback = 1 << 0,
eEnabled = 1 << 1,
eOneShot = 1 << 2,
eIgnoreCount = 1 << 3,
eThreadSpec = 1 << 4,
eCondition = 1 << 5,
eAutoContinue = 1 << 6
};
struct CommandData {
CommandData()
Expand Down Expand Up @@ -112,7 +113,8 @@ friend class Breakpoint;
///
//------------------------------------------------------------------
BreakpointOptions(const char *condition, bool enabled = true,
int32_t ignore = 0, bool one_shot = false);
int32_t ignore = 0, bool one_shot = false,
bool auto_continue = false);

virtual ~BreakpointOptions();

Expand Down Expand Up @@ -295,6 +297,21 @@ friend class Breakpoint;
m_set_flags.Set(eEnabled);
}

//------------------------------------------------------------------
/// Check the auto-continue state.
/// @return
/// \b true if the breakpoint is set to auto-continue, \b false otherwise.
//------------------------------------------------------------------
bool IsAutoContinue() const { return m_auto_continue; }

//------------------------------------------------------------------
/// Set the auto-continue state.
//------------------------------------------------------------------
void SetAutoContinue(bool auto_continue) {
m_auto_continue = auto_continue;
m_set_flags.Set(eAutoContinue);
}

//------------------------------------------------------------------
/// Check the One-shot state.
/// @return
Expand Down Expand Up @@ -394,6 +411,7 @@ friend class Breakpoint;
IgnoreCount,
EnabledState,
OneShotState,
AutoContinue,
LastOptionName
};
static const char *g_option_names[(size_t)OptionNames::LastOptionName];
Expand Down Expand Up @@ -424,6 +442,7 @@ friend class Breakpoint;
std::string m_condition_text; // The condition to test.
size_t m_condition_text_hash; // Its hash, so that locations know when the
// condition is updated.
bool m_auto_continue; // If set, auto-continue from breakpoint.
Flags m_set_flags; // Which options are set at this level. Drawn
// from BreakpointOptions::SetOptionsFlags.
};
Expand Down
4 changes: 3 additions & 1 deletion lldb/include/lldb/lldb-enumerations.h
Original file line number Diff line number Diff line change
Expand Up @@ -380,7 +380,8 @@ FLAGS_ENUM(BreakpointEventType){
eBreakpointEventTypeCommandChanged = (1u << 8),
eBreakpointEventTypeConditionChanged = (1u << 9),
eBreakpointEventTypeIgnoreChanged = (1u << 10),
eBreakpointEventTypeThreadChanged = (1u << 11)};
eBreakpointEventTypeThreadChanged = (1u << 11),
eBreakpointEventTypeAutoContinueChanged = (1u << 12)};

FLAGS_ENUM(WatchpointEventType){
eWatchpointEventTypeInvalidType = (1u << 0),
Expand Down Expand Up @@ -566,6 +567,7 @@ enum CommandArgumentType {
eArgTypeWatchpointIDRange,
eArgTypeWatchType,
eArgRawInput,
eArgTypeCommand,
eArgTypeLastArg // Always keep this entry as the last entry in this
// enumeration!!
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,21 @@ def classCleanup(cls):
cls.RemoveTempFile("output2.txt")

@expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24528")
def test(self):
def test_breakpoint_command_sequence(self):
"""Test a sequence of breakpoint command add, list, and delete."""
self.build()
self.breakpoint_command_sequence()

@expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24528")
def test_script_parameters(self):
"""Test a sequence of breakpoint command add, list, and delete."""
self.build()
self.breakpoint_command_script_parameters()

def test_commands_on_creation(self):
self.build()
self.breakpoint_commands_on_creation()

def setUp(self):
# Call super's setUp().
TestBase.setUp(self)
Expand Down Expand Up @@ -268,3 +277,23 @@ def breakpoint_command_script_parameters(self):

# Now remove 'output-2.txt'
os.remove('output-2.txt')

def breakpoint_commands_on_creation(self):
"""Test that setting breakpoint commands when creating the breakpoint works"""
exe = os.path.join(os.getcwd(), "a.out")
target = self.dbg.CreateTarget(exe)
self.assertTrue(target.IsValid(), "Created an invalid target.")

# Add a breakpoint.
lldbutil.run_break_set_by_file_and_line(
self, "main.c", self.line, num_expected_locations=1, loc_exact=True,
extra_options='-d bt -d "thread list" -d continue')

bkpt = target.FindBreakpointByID(1)
self.assertTrue(bkpt.IsValid(), "Couldn't find breakpoint 1")
com_list = lldb.SBStringList()
bkpt.GetCommandLineCommands(com_list)
self.assertEqual(com_list.GetSize(), 3, "Got the wrong number of commands")
self.assertEqual(com_list.GetStringAtIndex(0), "bt", "First bt")
self.assertEqual(com_list.GetStringAtIndex(1), "thread list", "Next thread list")
self.assertEqual(com_list.GetStringAtIndex(2), "continue", "Last continue")
4 changes: 4 additions & 0 deletions lldb/scripts/interface/SBBreakpoint.i
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,10 @@ public:
const char *
GetCondition ();

void SetAutoContinue(bool auto_continue);

bool GetAutoContinue();

void
SetThreadID (lldb::tid_t sb_thread_id);

Expand Down
4 changes: 4 additions & 0 deletions lldb/scripts/interface/SBBreakpointLocation.i
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,10 @@ public:
const char *
GetCondition ();

bool GetAutoContinue();

void SetAutoContinue(bool auto_continue);

%feature("docstring", "
//------------------------------------------------------------------
/// Set the callback to the given Python function name.
Expand Down
19 changes: 19 additions & 0 deletions lldb/source/API/SBBreakpoint.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,25 @@ const char *SBBreakpoint::GetCondition() {
return nullptr;
}

void SBBreakpoint::SetAutoContinue(bool auto_continue) {
BreakpointSP bkpt_sp = GetSP();
if (bkpt_sp) {
std::lock_guard<std::recursive_mutex> guard(
bkpt_sp->GetTarget().GetAPIMutex());
bkpt_sp->SetAutoContinue(auto_continue);
}
}

bool SBBreakpoint::GetAutoContinue() {
BreakpointSP bkpt_sp = GetSP();
if (bkpt_sp) {
std::lock_guard<std::recursive_mutex> guard(
bkpt_sp->GetTarget().GetAPIMutex());
return bkpt_sp->IsAutoContinue();
}
return nullptr;
}

uint32_t SBBreakpoint::GetHitCount() const {
uint32_t count = 0;
BreakpointSP bkpt_sp = GetSP();
Expand Down
19 changes: 19 additions & 0 deletions lldb/source/API/SBBreakpointLocation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,25 @@ const char *SBBreakpointLocation::GetCondition() {
return NULL;
}

void SBBreakpointLocation::SetAutoContinue(bool auto_continue) {
BreakpointLocationSP loc_sp = GetSP();
if (loc_sp) {
std::lock_guard<std::recursive_mutex> guard(
loc_sp->GetTarget().GetAPIMutex());
loc_sp->SetAutoContinue(auto_continue);
}
}

bool SBBreakpointLocation::GetAutoContinue() {
BreakpointLocationSP loc_sp = GetSP();
if (loc_sp) {
std::lock_guard<std::recursive_mutex> guard(
loc_sp->GetTarget().GetAPIMutex());
return loc_sp->IsAutoContinue();
}
return NULL;
}

void SBBreakpointLocation::SetScriptCallbackFunction(
const char *callback_function_name) {
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
Expand Down
8 changes: 8 additions & 0 deletions lldb/source/Breakpoint/Breakpoint.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,14 @@ void Breakpoint::SetOneShot(bool one_shot) {
m_options_up->SetOneShot(one_shot);
}

bool Breakpoint::IsAutoContinue() const {
return m_options_up->IsAutoContinue();
}

void Breakpoint::SetAutoContinue(bool auto_continue) {
m_options_up->SetAutoContinue(auto_continue);
}

void Breakpoint::SetThreadID(lldb::tid_t thread_id) {
if (m_options_up->GetThreadSpec()->GetTID() == thread_id)
return;
Expand Down
13 changes: 13 additions & 0 deletions lldb/source/Breakpoint/BreakpointLocation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,19 @@ void BreakpointLocation::SetEnabled(bool enabled) {
: eBreakpointEventTypeDisabled);
}

bool BreakpointLocation::IsAutoContinue() const {
if (m_options_ap
&& m_options_ap->IsOptionSet(BreakpointOptions::eAutoContinue))
return m_options_ap->IsAutoContinue();
else
return m_owner.IsAutoContinue();
}

void BreakpointLocation::SetAutoContinue(bool auto_continue) {
GetLocationOptions()->SetAutoContinue(auto_continue);
SendBreakpointLocationChangedEvent(eBreakpointEventTypeAutoContinueChanged);
}

void BreakpointLocation::SetThreadID(lldb::tid_t thread_id) {
if (thread_id != LLDB_INVALID_THREAD_ID)
GetLocationOptions()->SetThreadID(thread_id);
Expand Down
Loading

0 comments on commit f08f5c9

Please sign in to comment.