JDevlieghere updated this revision to Diff 173021.
JDevlieghere added a comment.
Remove `ValidatePlan` implementation for `ThreadPlanPython` as I believe it's
bogus.
https://reviews.llvm.org/D54221
Files:
include/lldb/API/SBBreakpoint.h
include/lldb/Breakpoint/Breakpoint.h
include/lldb/Target/Target.h
include/lldb/Target/Thread.h
include/lldb/Target/ThreadPlanBase.h
include/lldb/Target/ThreadPlanRunToAddress.h
include/lldb/Target/ThreadPlanStepInRange.h
include/lldb/Target/ThreadPlanStepInstruction.h
include/lldb/Target/ThreadPlanStepOut.h
include/lldb/Target/ThreadPlanStepRange.h
include/lldb/Target/ThreadPlanStepThrough.h
include/lldb/Target/ThreadPlanStepUntil.h
packages/Python/lldbsuite/test/functionalities/breakpoint/require_hw_breakpoints/Makefile
packages/Python/lldbsuite/test/functionalities/breakpoint/require_hw_breakpoints/TestRequireHWBreakpoints.py
packages/Python/lldbsuite/test/functionalities/breakpoint/require_hw_breakpoints/main.c
packages/Python/lldbsuite/test/functionalities/step_scripted/TestStepScripted.py
scripts/interface/SBBreakpoint.i
source/API/SBBreakpoint.cpp
source/API/SBThread.cpp
source/API/SBThreadPlan.cpp
source/Breakpoint/Breakpoint.cpp
source/Commands/CommandObjectThread.cpp
source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.cpp
source/Target/Process.cpp
source/Target/StopInfo.cpp
source/Target/Target.cpp
source/Target/Thread.cpp
source/Target/ThreadPlanCallOnFunctionExit.cpp
source/Target/ThreadPlanPython.cpp
source/Target/ThreadPlanRunToAddress.cpp
source/Target/ThreadPlanShouldStopHere.cpp
source/Target/ThreadPlanStepInRange.cpp
source/Target/ThreadPlanStepInstruction.cpp
source/Target/ThreadPlanStepOut.cpp
source/Target/ThreadPlanStepOverRange.cpp
source/Target/ThreadPlanStepRange.cpp
source/Target/ThreadPlanStepThrough.cpp
source/Target/ThreadPlanStepUntil.cpp
Index: source/Target/ThreadPlanStepUntil.cpp
===================================================================
--- source/Target/ThreadPlanStepUntil.cpp
+++ source/Target/ThreadPlanStepUntil.cpp
@@ -39,7 +39,8 @@
m_return_bp_id(LLDB_INVALID_BREAK_ID),
m_return_addr(LLDB_INVALID_ADDRESS), m_stepped_out(false),
m_should_stop(false), m_ran_analyze(false), m_explains_stop(false),
- m_until_points(), m_stop_others(stop_others) {
+ m_until_points(), m_stop_others(stop_others),
+ m_could_not_resolve_hw_bp(false) {
// Stash away our "until" addresses:
TargetSP target_sp(m_thread.CalculateTarget());
@@ -57,7 +58,10 @@
m_return_addr = return_frame_sp->GetStackID().GetPC();
Breakpoint *return_bp =
target_sp->CreateBreakpoint(m_return_addr, true, false).get();
+
if (return_bp != nullptr) {
+ if (return_bp->IsHardware() && !return_bp->HasResolvedLocations())
+ m_could_not_resolve_hw_bp = true;
return_bp->SetThreadID(thread_id);
m_return_bp_id = return_bp->GetID();
return_bp->SetBreakpointKind("until-return-backstop");
@@ -97,6 +101,7 @@
}
}
m_until_points.clear();
+ m_could_not_resolve_hw_bp = false;
}
void ThreadPlanStepUntil::GetDescription(Stream *s,
@@ -127,9 +132,16 @@
}
bool ThreadPlanStepUntil::ValidatePlan(Stream *error) {
- if (m_return_bp_id == LLDB_INVALID_BREAK_ID)
+ if (m_could_not_resolve_hw_bp) {
+ if (error)
+ error->PutCString(
+ "Could not create hardware breakpoint for thread plan.");
+ return false;
+ } else if (m_return_bp_id == LLDB_INVALID_BREAK_ID) {
+ if (error)
+ error->PutCString("Could not create return breakpoint.");
return false;
- else {
+ } else {
until_collection::iterator pos, end = m_until_points.end();
for (pos = m_until_points.begin(); pos != end; pos++) {
if (!LLDB_BREAK_ID_IS_VALID((*pos).second))
Index: source/Target/ThreadPlanStepThrough.cpp
===================================================================
--- source/Target/ThreadPlanStepThrough.cpp
+++ source/Target/ThreadPlanStepThrough.cpp
@@ -40,7 +40,7 @@
eVoteNoOpinion, eVoteNoOpinion),
m_start_address(0), m_backstop_bkpt_id(LLDB_INVALID_BREAK_ID),
m_backstop_addr(LLDB_INVALID_ADDRESS), m_return_stack_id(m_stack_id),
- m_stop_others(stop_others) {
+ m_stop_others(stop_others), m_could_not_resolve_hw_bp(false) {
LookForPlanToStepThroughFromCurrentPC();
// If we don't get a valid step through plan, don't bother to set up a
@@ -62,7 +62,10 @@
->GetTarget()
.CreateBreakpoint(m_backstop_addr, true, false)
.get();
+
if (return_bp != nullptr) {
+ if (return_bp->IsHardware() && !return_bp->HasResolvedLocations())
+ m_could_not_resolve_hw_bp = true;
return_bp->SetThreadID(m_thread.GetID());
m_backstop_bkpt_id = return_bp->GetID();
return_bp->SetBreakpointKind("step-through-backstop");
@@ -139,7 +142,26 @@
}
bool ThreadPlanStepThrough::ValidatePlan(Stream *error) {
- return m_sub_plan_sp.get() != nullptr;
+ if (m_could_not_resolve_hw_bp) {
+ if (error)
+ error->PutCString(
+ "Could not create hardware breakpoint for thread plan.");
+ return false;
+ }
+
+ if (m_backstop_bkpt_id == LLDB_INVALID_BREAK_ID) {
+ if (error)
+ error->PutCString("Could not create backstop breakpoint.");
+ return false;
+ }
+
+ if (!m_sub_plan_sp.get()) {
+ if (error)
+ error->PutCString("Does not have a subplan.");
+ return false;
+ }
+
+ return true;
}
bool ThreadPlanStepThrough::DoPlanExplainsStop(Event *event_ptr) {
@@ -215,6 +237,7 @@
if (m_backstop_bkpt_id != LLDB_INVALID_BREAK_ID) {
m_thread.GetProcess()->GetTarget().RemoveBreakpointByID(m_backstop_bkpt_id);
m_backstop_bkpt_id = LLDB_INVALID_BREAK_ID;
+ m_could_not_resolve_hw_bp = false;
}
}
Index: source/Target/ThreadPlanStepRange.cpp
===================================================================
--- source/Target/ThreadPlanStepRange.cpp
+++ source/Target/ThreadPlanStepRange.cpp
@@ -45,7 +45,7 @@
m_addr_context(addr_context), m_address_ranges(),
m_stop_others(stop_others), m_stack_id(), m_parent_stack_id(),
m_no_more_plans(false), m_first_run_event(true), m_use_fast_step(false),
- m_given_ranges_only(given_ranges_only) {
+ m_given_ranges_only(given_ranges_only), m_could_not_resolve_hw_bp(false) {
m_use_fast_step = GetTarget().GetUseFastStepping();
AddRange(range);
m_stack_id = m_thread.GetStackFrameAtIndex(0)->GetStackID();
@@ -61,7 +61,15 @@
SetNextBranchBreakpoint();
}
-bool ThreadPlanStepRange::ValidatePlan(Stream *error) { return true; }
+bool ThreadPlanStepRange::ValidatePlan(Stream *error) {
+ if (m_could_not_resolve_hw_bp) {
+ if (error)
+ error->PutCString(
+ "Could not create hardware breakpoint for thread plan.");
+ return false;
+ }
+ return true;
+}
Vote ThreadPlanStepRange::ShouldReportStop(Event *event_ptr) {
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
@@ -285,6 +293,7 @@
m_next_branch_bp_sp->GetID());
GetTarget().RemoveBreakpointByID(m_next_branch_bp_sp->GetID());
m_next_branch_bp_sp.reset();
+ m_could_not_resolve_hw_bp = false;
}
}
@@ -335,6 +344,11 @@
m_next_branch_bp_sp =
GetTarget().CreateBreakpoint(run_to_address, is_internal, false);
if (m_next_branch_bp_sp) {
+
+ if (m_next_branch_bp_sp->IsHardware() &&
+ !m_next_branch_bp_sp->HasResolvedLocations())
+ m_could_not_resolve_hw_bp = true;
+
if (log) {
lldb::break_id_t bp_site_id = LLDB_INVALID_BREAK_ID;
BreakpointLocationSP bp_loc =
@@ -351,8 +365,10 @@
run_to_address.GetLoadAddress(
&m_thread.GetProcess()->GetTarget()));
}
+
m_next_branch_bp_sp->SetThreadID(m_thread.GetID());
m_next_branch_bp_sp->SetBreakpointKind("next-branch-location");
+
return true;
} else
return false;
Index: source/Target/ThreadPlanStepOverRange.cpp
===================================================================
--- source/Target/ThreadPlanStepOverRange.cpp
+++ source/Target/ThreadPlanStepOverRange.cpp
@@ -139,6 +139,7 @@
// forcing running one thread.
bool stop_others = (m_stop_others == lldb::eOnlyThisThread);
ThreadPlanSP new_plan_sp;
+ Status new_plan_status;
FrameComparison frame_order = CompareCurrentFrameToStartFrame();
if (frame_order == eFrameCompareOlder) {
@@ -151,8 +152,8 @@
// because the trampoline confused the backtracer. As below, we step
// through first, and then try to figure out how to get back out again.
- new_plan_sp =
- m_thread.QueueThreadPlanForStepThrough(m_stack_id, false, stop_others);
+ new_plan_sp = m_thread.QueueThreadPlanForStepThrough(
+ new_plan_status, m_stack_id, false, stop_others);
if (new_plan_sp && log)
log->Printf(
@@ -172,12 +173,12 @@
older_frame_sp->GetSymbolContext(eSymbolContextEverything);
if (IsEquivalentContext(older_context)) {
new_plan_sp = m_thread.QueueThreadPlanForStepOutNoShouldStop(
- false, nullptr, true, stop_others, eVoteNo, eVoteNoOpinion, 0,
- true);
+ new_plan_status, false, nullptr, true, stop_others, eVoteNo,
+ eVoteNoOpinion, 0, true);
break;
} else {
- new_plan_sp = m_thread.QueueThreadPlanForStepThrough(m_stack_id, false,
- stop_others);
+ new_plan_sp = m_thread.QueueThreadPlanForStepThrough(
+ new_plan_status, m_stack_id, false, stop_others);
// If we found a way through, then we should stop recursing.
if (new_plan_sp)
break;
@@ -196,8 +197,8 @@
// we are in a stub then it's likely going to be hard to get out from
// here. It is probably easiest to step into the stub, and then it will
// be straight-forward to step out.
- new_plan_sp = m_thread.QueueThreadPlanForStepThrough(m_stack_id, false,
- stop_others);
+ new_plan_sp = m_thread.QueueThreadPlanForStepThrough(
+ new_plan_status, m_stack_id, false, stop_others);
} else {
// The current clang (at least through 424) doesn't always get the
// address range for the DW_TAG_inlined_subroutines right, so that when
@@ -287,7 +288,7 @@
cur_pc);
new_plan_sp = m_thread.QueueThreadPlanForStepOverRange(
- abort_other_plans, step_range, sc,
+ new_plan_status, abort_other_plans, step_range, sc,
stop_other_threads);
break;
}
@@ -323,7 +324,7 @@
if (!new_plan_sp) {
// For efficiencies sake, we know we're done here so we don't have to do
// this calculation again in MischiefManaged.
- SetPlanComplete();
+ SetPlanComplete(new_plan_status.Success());
return true;
} else
return false;
Index: source/Target/ThreadPlanStepOut.cpp
===================================================================
--- source/Target/ThreadPlanStepOut.cpp
+++ source/Target/ThreadPlanStepOut.cpp
@@ -47,7 +47,8 @@
m_return_bp_id(LLDB_INVALID_BREAK_ID),
m_return_addr(LLDB_INVALID_ADDRESS), m_stop_others(stop_others),
m_immediate_step_from_function(nullptr),
- m_calculate_return_value(gather_return_value) {
+ m_calculate_return_value(gather_return_value),
+ m_could_not_resolve_hw_bp(false) {
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
SetFlagsToDefault();
SetupAvoidNoDebug(step_out_avoids_code_without_debug_info);
@@ -133,7 +134,10 @@
Breakpoint *return_bp = m_thread.CalculateTarget()
->CreateBreakpoint(m_return_addr, true, false)
.get();
+
if (return_bp != nullptr) {
+ if (return_bp->IsHardware() && !return_bp->HasResolvedLocations())
+ m_could_not_resolve_hw_bp = true;
return_bp->SetThreadID(m_thread.GetID());
m_return_bp_id = return_bp->GetID();
return_bp->SetBreakpointKind("step-out");
@@ -227,14 +231,24 @@
bool ThreadPlanStepOut::ValidatePlan(Stream *error) {
if (m_step_out_to_inline_plan_sp)
return m_step_out_to_inline_plan_sp->ValidatePlan(error);
- else if (m_step_through_inline_plan_sp)
+
+ if (m_step_through_inline_plan_sp)
return m_step_through_inline_plan_sp->ValidatePlan(error);
- else if (m_return_bp_id == LLDB_INVALID_BREAK_ID) {
+
+ if (m_could_not_resolve_hw_bp) {
+ if (error)
+ error->PutCString(
+ "Could not create hardware breakpoint for thread plan.");
+ return false;
+ }
+
+ if (m_return_bp_id == LLDB_INVALID_BREAK_ID) {
if (error)
error->PutCString("Could not create return address breakpoint.");
return false;
- } else
- return true;
+ }
+
+ return true;
}
bool ThreadPlanStepOut::DoPlanExplainsStop(Event *event_ptr) {
Index: source/Target/ThreadPlanStepInstruction.cpp
===================================================================
--- source/Target/ThreadPlanStepInstruction.cpp
+++ source/Target/ThreadPlanStepInstruction.cpp
@@ -191,8 +191,10 @@
// StepInstruction should probably have the tri-state RunMode, but
// for now it is safer to run others.
const bool stop_others = false;
+ Status status;
m_thread.QueueThreadPlanForStepOutNoShouldStop(
- false, nullptr, true, stop_others, eVoteNo, eVoteNoOpinion, 0);
+ status, false, nullptr, true, stop_others, eVoteNo,
+ eVoteNoOpinion, 0);
return false;
} else {
if (log) {
Index: source/Target/ThreadPlanStepInRange.cpp
===================================================================
--- source/Target/ThreadPlanStepInRange.cpp
+++ source/Target/ThreadPlanStepInRange.cpp
@@ -168,6 +168,7 @@
// record which in the m_virtual_step.
m_sub_plan_sp = CheckShouldStopHereAndQueueStepOut(eFrameCompareYounger);
} else {
+ Status sub_plan_status;
// Stepping through should be done running other threads in general, since
// we're setting a breakpoint and continuing. So only stop others if we
// are explicitly told to do so.
@@ -185,8 +186,8 @@
// I'm going to make the assumption that you wouldn't RETURN to a
// trampoline. So if we are in a trampoline we think the frame is older
// because the trampoline confused the backtracer.
- m_sub_plan_sp = m_thread.QueueThreadPlanForStepThrough(m_stack_id, false,
- stop_others);
+ m_sub_plan_sp = m_thread.QueueThreadPlanForStepThrough(
+ sub_plan_status, m_stack_id, false, stop_others);
if (!m_sub_plan_sp) {
// Otherwise check the ShouldStopHere for step out:
m_sub_plan_sp = CheckShouldStopHereAndQueueStepOut(frame_order);
@@ -227,8 +228,8 @@
// We may have set the plan up above in the FrameIsOlder section:
if (!m_sub_plan_sp)
- m_sub_plan_sp = m_thread.QueueThreadPlanForStepThrough(m_stack_id, false,
- stop_others);
+ m_sub_plan_sp = m_thread.QueueThreadPlanForStepThrough(
+ sub_plan_status, m_stack_id, false, stop_others);
if (log) {
if (m_sub_plan_sp)
@@ -288,7 +289,7 @@
log->Printf("Pushing past prologue ");
m_sub_plan_sp = m_thread.QueueThreadPlanForRunToAddress(
- false, func_start_address, true);
+ sub_plan_status, false, func_start_address, true);
}
}
}
Index: source/Target/ThreadPlanShouldStopHere.cpp
===================================================================
--- source/Target/ThreadPlanShouldStopHere.cpp
+++ source/Target/ThreadPlanShouldStopHere.cpp
@@ -103,6 +103,7 @@
void *baton) {
const bool stop_others = false;
const size_t frame_index = 0;
+ Status return_plan_status;
ThreadPlanSP return_plan_sp;
// If we are stepping through code at line number 0, then we need to step
// over this range. Otherwise we will step out.
@@ -137,16 +138,16 @@
"Queueing StepInRange plan to step through line 0 code.");
return_plan_sp = current_plan->GetThread().QueueThreadPlanForStepInRange(
- false, range, sc, NULL, eOnlyDuringStepping, eLazyBoolCalculate,
- eLazyBoolNo);
+ return_plan_status, false, range, sc, NULL, eOnlyDuringStepping,
+ eLazyBoolCalculate, eLazyBoolNo);
}
}
if (!return_plan_sp)
return_plan_sp =
current_plan->GetThread().QueueThreadPlanForStepOutNoShouldStop(
- false, nullptr, true, stop_others, eVoteNo, eVoteNoOpinion,
- frame_index, true);
+ return_plan_status, false, nullptr, true, stop_others, eVoteNo,
+ eVoteNoOpinion, frame_index, true);
return return_plan_sp;
}
Index: source/Target/ThreadPlanRunToAddress.cpp
===================================================================
--- source/Target/ThreadPlanRunToAddress.cpp
+++ source/Target/ThreadPlanRunToAddress.cpp
@@ -30,7 +30,8 @@
bool stop_others)
: ThreadPlan(ThreadPlan::eKindRunToAddress, "Run to address plan", thread,
eVoteNoOpinion, eVoteNoOpinion),
- m_stop_others(stop_others), m_addresses(), m_break_ids() {
+ m_stop_others(stop_others), m_addresses(), m_break_ids(),
+ m_could_not_resolve_hw_bp(false) {
m_addresses.push_back(
address.GetOpcodeLoadAddress(m_thread.CalculateTarget().get()));
SetInitialBreakpoints();
@@ -41,7 +42,8 @@
bool stop_others)
: ThreadPlan(ThreadPlan::eKindRunToAddress, "Run to address plan", thread,
eVoteNoOpinion, eVoteNoOpinion),
- m_stop_others(stop_others), m_addresses(), m_break_ids() {
+ m_stop_others(stop_others), m_addresses(), m_break_ids(),
+ m_could_not_resolve_hw_bp(false) {
m_addresses.push_back(
m_thread.CalculateTarget()->GetOpcodeLoadAddress(address));
SetInitialBreakpoints();
@@ -73,6 +75,8 @@
->CreateBreakpoint(m_addresses[i], true, false)
.get();
if (breakpoint != nullptr) {
+ if (breakpoint->IsHardware() && !breakpoint->HasResolvedLocations())
+ m_could_not_resolve_hw_bp = true;
m_break_ids[i] = breakpoint->GetID();
breakpoint->SetThreadID(m_thread.GetID());
breakpoint->SetBreakpointKind("run-to-address");
@@ -85,6 +89,7 @@
for (size_t i = 0; i < num_break_ids; i++) {
m_thread.CalculateTarget()->RemoveBreakpointByID(m_break_ids[i]);
}
+ m_could_not_resolve_hw_bp = false;
}
void ThreadPlanRunToAddress::GetDescription(Stream *s,
@@ -133,10 +138,15 @@
}
bool ThreadPlanRunToAddress::ValidatePlan(Stream *error) {
+ if (m_could_not_resolve_hw_bp) {
+ if (error)
+ error->Printf("Could not set hardware breakpoint(s)");
+ return false;
+ }
+
// If we couldn't set the breakpoint for some reason, then this won't work.
bool all_bps_good = true;
size_t num_break_ids = m_break_ids.size();
-
for (size_t i = 0; i < num_break_ids; i++) {
if (m_break_ids[i] == LLDB_INVALID_BREAK_ID) {
all_bps_good = false;
Index: source/Target/ThreadPlanPython.cpp
===================================================================
--- source/Target/ThreadPlanPython.cpp
+++ source/Target/ThreadPlanPython.cpp
@@ -46,16 +46,7 @@
// to make it go away?
}
-bool ThreadPlanPython::ValidatePlan(Stream *error) {
- // I have to postpone setting up the implementation till after the constructor
- // because I need to call
- // shared_from_this, which you can't do in the constructor. So I'll do it
- // here.
- if (m_implementation_sp)
- return true;
- else
- return false;
-}
+bool ThreadPlanPython::ValidatePlan(Stream *error) { return true; }
void ThreadPlanPython::DidPush() {
// We set up the script side in DidPush, so that it can push other plans in
Index: source/Target/ThreadPlanCallOnFunctionExit.cpp
===================================================================
--- source/Target/ThreadPlanCallOnFunctionExit.cpp
+++ source/Target/ThreadPlanCallOnFunctionExit.cpp
@@ -27,7 +27,9 @@
// completes.
// Set stop vote to eVoteNo.
+ Status status;
m_step_out_threadplan_sp = GetThread().QueueThreadPlanForStepOut(
+ status,
false, // abort other plans
nullptr, // addr_context
true, // first instruction
@@ -37,7 +39,7 @@
// run state broadcasting
0, // frame_idx
eLazyBoolCalculate // avoid code w/o debinfo
- );
+ );
}
// -------------------------------------------------------------------------
Index: source/Target/Thread.cpp
===================================================================
--- source/Target/Thread.cpp
+++ source/Target/Thread.cpp
@@ -266,7 +266,9 @@
static_cast<void *>(this), GetID());
CheckInWithManager();
- QueueFundamentalPlan(true);
+
+ Status status;
+ QueueFundamentalPlan(status, true);
}
Thread::~Thread() {
@@ -399,13 +401,14 @@
m_stop_info_sp ->IsValid() &&
m_stop_info_stop_id == stop_id;
bool have_valid_completed_plan = completed_plan_sp && completed_plan_sp->PlanSucceeded();
+ bool plan_failed = completed_plan_sp && !completed_plan_sp->PlanSucceeded();
bool plan_overrides_trace =
have_valid_stop_info && have_valid_completed_plan
&& (m_stop_info_sp->GetStopReason() == eStopReasonTrace);
- if (have_valid_stop_info && !plan_overrides_trace) {
+ if (have_valid_stop_info && !plan_overrides_trace && !plan_failed) {
return m_stop_info_sp;
- } else if (have_valid_completed_plan) {
+ } else if (completed_plan_sp) {
return StopInfo::CreateStopReasonWithPlan(
completed_plan_sp, GetReturnValueObject(), GetExpressionVariable());
} else {
@@ -1177,12 +1180,34 @@
return nullptr;
}
-void Thread::QueueThreadPlan(ThreadPlanSP &thread_plan_sp,
- bool abort_other_plans) {
+Status Thread::QueueThreadPlan(ThreadPlanSP &thread_plan_sp,
+ bool abort_other_plans) {
+ Status status;
+ StreamString s;
+ if (!thread_plan_sp->ValidatePlan(&s)) {
+ DiscardThreadPlansUpToPlan(thread_plan_sp);
+ thread_plan_sp.reset();
+ status.SetErrorString(s.GetString());
+ return status;
+ }
+
if (abort_other_plans)
DiscardThreadPlans(true);
PushPlan(thread_plan_sp);
+
+ // This seems a little funny, but I don't want to have to split up the
+ // constructor and the DidPush in the scripted plan, that seems annoying.
+ // That means the constructor has to be in DidPush. So I have to validate the
+ // plan AFTER pushing it, and then take it off again...
+ if (!thread_plan_sp->ValidatePlan(&s)) {
+ DiscardThreadPlansUpToPlan(thread_plan_sp);
+ thread_plan_sp.reset();
+ status.SetErrorString(s.GetString());
+ return status;
+ }
+
+ return status;
}
void Thread::EnableTracer(bool value, bool single_stepping) {
@@ -1340,47 +1365,50 @@
return error;
}
-ThreadPlanSP Thread::QueueFundamentalPlan(bool abort_other_plans) {
+ThreadPlanSP Thread::QueueFundamentalPlan(Status &status,
+ bool abort_other_plans) {
ThreadPlanSP thread_plan_sp(new ThreadPlanBase(*this));
- QueueThreadPlan(thread_plan_sp, abort_other_plans);
+ status = QueueThreadPlan(thread_plan_sp, abort_other_plans);
return thread_plan_sp;
}
-ThreadPlanSP Thread::QueueThreadPlanForStepSingleInstruction(
- bool step_over, bool abort_other_plans, bool stop_other_threads) {
+ThreadPlanSP
+Thread::QueueThreadPlanForStepSingleInstruction(Status &status, bool step_over,
+ bool abort_other_plans,
+ bool stop_other_threads) {
ThreadPlanSP thread_plan_sp(new ThreadPlanStepInstruction(
*this, step_over, stop_other_threads, eVoteNoOpinion, eVoteNoOpinion));
- QueueThreadPlan(thread_plan_sp, abort_other_plans);
+ status = QueueThreadPlan(thread_plan_sp, abort_other_plans);
return thread_plan_sp;
}
ThreadPlanSP Thread::QueueThreadPlanForStepOverRange(
- bool abort_other_plans, const AddressRange &range,
+ Status &status, bool abort_other_plans, const AddressRange &range,
const SymbolContext &addr_context, lldb::RunMode stop_other_threads,
LazyBool step_out_avoids_code_withoug_debug_info) {
ThreadPlanSP thread_plan_sp;
thread_plan_sp.reset(new ThreadPlanStepOverRange(
*this, range, addr_context, stop_other_threads,
step_out_avoids_code_withoug_debug_info));
- QueueThreadPlan(thread_plan_sp, abort_other_plans);
+ status = QueueThreadPlan(thread_plan_sp, abort_other_plans);
return thread_plan_sp;
}
// Call the QueueThreadPlanForStepOverRange method which takes an address
// range.
ThreadPlanSP Thread::QueueThreadPlanForStepOverRange(
- bool abort_other_plans, const LineEntry &line_entry,
+ Status &status, bool abort_other_plans, const LineEntry &line_entry,
const SymbolContext &addr_context, lldb::RunMode stop_other_threads,
LazyBool step_out_avoids_code_withoug_debug_info) {
return QueueThreadPlanForStepOverRange(
- abort_other_plans, line_entry.GetSameLineContiguousAddressRange(),
+ status, abort_other_plans, line_entry.GetSameLineContiguousAddressRange(),
addr_context, stop_other_threads,
step_out_avoids_code_withoug_debug_info);
}
ThreadPlanSP Thread::QueueThreadPlanForStepInRange(
- bool abort_other_plans, const AddressRange &range,
+ Status &status, bool abort_other_plans, const AddressRange &range,
const SymbolContext &addr_context, const char *step_in_target,
lldb::RunMode stop_other_threads,
LazyBool step_in_avoids_code_without_debug_info,
@@ -1395,44 +1423,40 @@
if (step_in_target)
plan->SetStepInTarget(step_in_target);
- QueueThreadPlan(thread_plan_sp, abort_other_plans);
+ status = QueueThreadPlan(thread_plan_sp, abort_other_plans);
return thread_plan_sp;
}
// Call the QueueThreadPlanForStepInRange method which takes an address range.
ThreadPlanSP Thread::QueueThreadPlanForStepInRange(
- bool abort_other_plans, const LineEntry &line_entry,
+ Status &status, bool abort_other_plans, const LineEntry &line_entry,
const SymbolContext &addr_context, const char *step_in_target,
lldb::RunMode stop_other_threads,
LazyBool step_in_avoids_code_without_debug_info,
LazyBool step_out_avoids_code_without_debug_info) {
return QueueThreadPlanForStepInRange(
- abort_other_plans, line_entry.GetSameLineContiguousAddressRange(),
+ status, abort_other_plans, line_entry.GetSameLineContiguousAddressRange(),
addr_context, step_in_target, stop_other_threads,
step_in_avoids_code_without_debug_info,
step_out_avoids_code_without_debug_info);
}
ThreadPlanSP Thread::QueueThreadPlanForStepOut(
- bool abort_other_plans, SymbolContext *addr_context, bool first_insn,
- bool stop_other_threads, Vote stop_vote, Vote run_vote, uint32_t frame_idx,
- LazyBool step_out_avoids_code_without_debug_info) {
+ Status &status, bool abort_other_plans, SymbolContext *addr_context,
+ bool first_insn, bool stop_other_threads, Vote stop_vote, Vote run_vote,
+ uint32_t frame_idx, LazyBool step_out_avoids_code_without_debug_info) {
ThreadPlanSP thread_plan_sp(new ThreadPlanStepOut(
*this, addr_context, first_insn, stop_other_threads, stop_vote, run_vote,
frame_idx, step_out_avoids_code_without_debug_info));
- if (thread_plan_sp->ValidatePlan(nullptr)) {
- QueueThreadPlan(thread_plan_sp, abort_other_plans);
- return thread_plan_sp;
- } else {
- return ThreadPlanSP();
- }
+ status = QueueThreadPlan(thread_plan_sp, abort_other_plans);
+ return thread_plan_sp;
}
ThreadPlanSP Thread::QueueThreadPlanForStepOutNoShouldStop(
- bool abort_other_plans, SymbolContext *addr_context, bool first_insn,
- bool stop_other_threads, Vote stop_vote, Vote run_vote, uint32_t frame_idx,
- bool continue_to_next_branch) {
+ Status &status, bool abort_other_plans, SymbolContext *addr_context,
+ bool first_insn, bool stop_other_threads, Vote stop_vote, Vote run_vote,
+ uint32_t frame_idx, bool continue_to_next_branch) {
const bool calculate_return_value =
false; // No need to calculate the return value here.
ThreadPlanSP thread_plan_sp(new ThreadPlanStepOut(
@@ -1443,59 +1467,52 @@
static_cast<ThreadPlanStepOut *>(thread_plan_sp.get());
new_plan->ClearShouldStopHereCallbacks();
- if (thread_plan_sp->ValidatePlan(nullptr)) {
- QueueThreadPlan(thread_plan_sp, abort_other_plans);
- return thread_plan_sp;
- } else {
- return ThreadPlanSP();
- }
+ status = QueueThreadPlan(thread_plan_sp, abort_other_plans);
+ return thread_plan_sp;
}
-ThreadPlanSP Thread::QueueThreadPlanForStepThrough(StackID &return_stack_id,
+ThreadPlanSP Thread::QueueThreadPlanForStepThrough(Status &status,
+ StackID &return_stack_id,
bool abort_other_plans,
bool stop_other_threads) {
ThreadPlanSP thread_plan_sp(
new ThreadPlanStepThrough(*this, return_stack_id, stop_other_threads));
if (!thread_plan_sp || !thread_plan_sp->ValidatePlan(nullptr))
return ThreadPlanSP();
- QueueThreadPlan(thread_plan_sp, abort_other_plans);
+ status = QueueThreadPlan(thread_plan_sp, abort_other_plans);
return thread_plan_sp;
}
-ThreadPlanSP Thread::QueueThreadPlanForRunToAddress(bool abort_other_plans,
+ThreadPlanSP Thread::QueueThreadPlanForRunToAddress(Status &status,
+ bool abort_other_plans,
Address &target_addr,
bool stop_other_threads) {
ThreadPlanSP thread_plan_sp(
new ThreadPlanRunToAddress(*this, target_addr, stop_other_threads));
- QueueThreadPlan(thread_plan_sp, abort_other_plans);
+
+ status = QueueThreadPlan(thread_plan_sp, abort_other_plans);
return thread_plan_sp;
}
-ThreadPlanSP Thread::QueueThreadPlanForStepUntil(bool abort_other_plans,
- lldb::addr_t *address_list,
- size_t num_addresses,
- bool stop_other_threads,
- uint32_t frame_idx) {
+ThreadPlanSP Thread::QueueThreadPlanForStepUntil(
+ Status &status, bool abort_other_plans, lldb::addr_t *address_list,
+ size_t num_addresses, bool stop_other_threads, uint32_t frame_idx) {
ThreadPlanSP thread_plan_sp(new ThreadPlanStepUntil(
*this, address_list, num_addresses, stop_other_threads, frame_idx));
- QueueThreadPlan(thread_plan_sp, abort_other_plans);
+
+ status = QueueThreadPlan(thread_plan_sp, abort_other_plans);
return thread_plan_sp;
}
-lldb::ThreadPlanSP Thread::QueueThreadPlanForStepScripted(
- bool abort_other_plans, const char *class_name, bool stop_other_threads) {
+lldb::ThreadPlanSP
+Thread::QueueThreadPlanForStepScripted(Status &status, bool abort_other_plans,
+ const char *class_name,
+ bool stop_other_threads) {
ThreadPlanSP thread_plan_sp(new ThreadPlanPython(*this, class_name));
- QueueThreadPlan(thread_plan_sp, abort_other_plans);
- // This seems a little funny, but I don't want to have to split up the
- // constructor and the DidPush in the scripted plan, that seems annoying.
- // That means the constructor has to be in DidPush. So I have to validate the
- // plan AFTER pushing it, and then take it off again...
- if (!thread_plan_sp->ValidatePlan(nullptr)) {
- DiscardThreadPlansUpToPlan(thread_plan_sp);
- return ThreadPlanSP();
- } else
- return thread_plan_sp;
+
+ status = QueueThreadPlan(thread_plan_sp, abort_other_plans);
+ return thread_plan_sp;
}
uint32_t Thread::GetIndexID() const { return m_index_id; }
@@ -2114,12 +2131,12 @@
if (source_step && frame_sp && frame_sp->HasDebugInformation()) {
SymbolContext sc(frame_sp->GetSymbolContext(eSymbolContextEverything));
new_plan_sp = QueueThreadPlanForStepInRange(
- abort_other_plans, sc.line_entry, sc, nullptr, run_mode,
+ error, abort_other_plans, sc.line_entry, sc, nullptr, run_mode,
step_in_avoids_code_without_debug_info,
step_out_avoids_code_without_debug_info);
} else {
new_plan_sp = QueueThreadPlanForStepSingleInstruction(
- false, abort_other_plans, run_mode);
+ error, false, abort_other_plans, run_mode);
}
new_plan_sp->SetIsMasterPlan(true);
@@ -2148,11 +2165,11 @@
if (source_step && frame_sp && frame_sp->HasDebugInformation()) {
SymbolContext sc(frame_sp->GetSymbolContext(eSymbolContextEverything));
new_plan_sp = QueueThreadPlanForStepOverRange(
- abort_other_plans, sc.line_entry, sc, run_mode,
+ error, abort_other_plans, sc.line_entry, sc, run_mode,
step_out_avoids_code_without_debug_info);
} else {
new_plan_sp = QueueThreadPlanForStepSingleInstruction(
- true, abort_other_plans, run_mode);
+ error, true, abort_other_plans, run_mode);
}
new_plan_sp->SetIsMasterPlan(true);
@@ -2176,8 +2193,8 @@
const bool abort_other_plans = false;
ThreadPlanSP new_plan_sp(QueueThreadPlanForStepOut(
- abort_other_plans, nullptr, first_instruction, stop_other_threads,
- eVoteYes, eVoteNoOpinion, 0));
+ error, abort_other_plans, nullptr, first_instruction,
+ stop_other_threads, eVoteYes, eVoteNoOpinion, 0));
new_plan_sp->SetIsMasterPlan(true);
new_plan_sp->SetOkayToDiscard(false);
Index: source/Target/Target.cpp
===================================================================
--- source/Target/Target.cpp
+++ source/Target/Target.cpp
@@ -631,7 +631,8 @@
bool resolve_indirect_symbols) {
BreakpointSP bp_sp;
if (filter_sp && resolver_sp) {
- bp_sp.reset(new Breakpoint(*this, filter_sp, resolver_sp, request_hardware,
+ const bool hardware = request_hardware || GetRequireHardwareBreakpoints();
+ bp_sp.reset(new Breakpoint(*this, filter_sp, resolver_sp, hardware,
resolve_indirect_symbols));
resolver_sp->SetBreakpoint(bp_sp.get());
AddBreakpoint(bp_sp, internal);
@@ -3133,6 +3134,7 @@
// class TargetProperties
//--------------------------------------------------------------
+// clang-format off
static constexpr OptionEnumValueElement g_dynamic_value_types[] = {
{eNoDynamicValues, "no-dynamic-values",
"Don't calculate the dynamic type of values"},
@@ -3360,7 +3362,10 @@
nullptr, {}, "If true, LLDB will show variables that are meant to "
"support the operation of a language's runtime support."},
{"non-stop-mode", OptionValue::eTypeBoolean, false, 0, nullptr, {},
- "Disable lock-step debugging, instead control threads independently."}};
+ "Disable lock-step debugging, instead control threads independently."},
+ {"require-hardware-breakpoint", OptionValue::eTypeBoolean, false, 0,
+ nullptr, {}, "Require all breakpoints to be hardware breakpoints."}};
+// clang-format on
enum {
ePropertyDefaultArch,
@@ -3405,7 +3410,8 @@
ePropertyTrapHandlerNames,
ePropertyDisplayRuntimeSupportValues,
ePropertyNonStopModeEnabled,
- ePropertyExperimental
+ ePropertyRequireHardwareBreakpoints,
+ ePropertyExperimental,
};
class TargetOptionValueProperties : public OptionValueProperties {
@@ -4003,6 +4009,17 @@
SetDisableSTDIO(launch_info.GetFlags().Test(lldb::eLaunchFlagDisableSTDIO));
}
+bool TargetProperties::GetRequireHardwareBreakpoints() const {
+ const uint32_t idx = ePropertyRequireHardwareBreakpoints;
+ return m_collection_sp->GetPropertyAtIndexAsBoolean(
+ nullptr, idx, g_properties[idx].default_uint_value != 0);
+}
+
+void TargetProperties::SetRequireHardwareBreakpoints(bool b) {
+ const uint32_t idx = ePropertyRequireHardwareBreakpoints;
+ m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, b);
+}
+
void TargetProperties::Arg0ValueChangedCallback(void *target_property_ptr,
OptionValue *) {
TargetProperties *this_ =
Index: source/Target/StopInfo.cpp
===================================================================
--- source/Target/StopInfo.cpp
+++ source/Target/StopInfo.cpp
@@ -720,11 +720,14 @@
StopInfoSP stored_stop_info_sp = thread_sp->GetStopInfo();
assert(stored_stop_info_sp.get() == this);
+ Status new_plan_status;
ThreadPlanSP new_plan_sp(
thread_sp->QueueThreadPlanForStepSingleInstruction(
- false, // step-over
- false, // abort_other_plans
- true)); // stop_other_threads
+ new_plan_status,
+ false, // step-over
+ false, // abort_other_plans
+ true // stop_other_threads
+ ));
new_plan_sp->SetIsMasterPlan(true);
new_plan_sp->SetOkayToDiscard(false);
new_plan_sp->SetPrivate(true);
@@ -1042,6 +1045,8 @@
if (m_description.empty()) {
StreamString strm;
m_plan_sp->GetDescription(&strm, eDescriptionLevelBrief);
+ if (!m_plan_sp->PlanSucceeded())
+ strm << " (FAILED)";
m_description = strm.GetString();
}
return m_description.c_str();
Index: source/Target/Process.cpp
===================================================================
--- source/Target/Process.cpp
+++ source/Target/Process.cpp
@@ -1924,7 +1924,7 @@
owner->SetBreakpointSite(bp_site_sp);
return m_breakpoint_site_list.Add(bp_site_sp);
} else {
- if (show_error) {
+ if (show_error || use_hardware) {
// Report error for setting breakpoint...
GetTarget().GetDebugger().GetErrorFile()->Printf(
"warning: failed to set breakpoint site at 0x%" PRIx64
Index: source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.cpp
===================================================================
--- source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.cpp
+++ source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.cpp
@@ -161,12 +161,13 @@
SymbolContext sc = m_thread.GetStackFrameAtIndex(0)->GetSymbolContext(
eSymbolContextEverything);
+ Status status;
const bool abort_other_plans = false;
const bool first_insn = true;
const uint32_t frame_idx = 0;
m_run_to_sp = m_thread.QueueThreadPlanForStepOutNoShouldStop(
- abort_other_plans, &sc, first_insn, m_stop_others, eVoteNoOpinion,
- eVoteNoOpinion, frame_idx);
+ status, abort_other_plans, &sc, first_insn, m_stop_others,
+ eVoteNoOpinion, eVoteNoOpinion, frame_idx);
m_run_to_sp->SetPrivate(true);
return false;
}
Index: source/Commands/CommandObjectThread.cpp
===================================================================
--- source/Commands/CommandObjectThread.cpp
+++ source/Commands/CommandObjectThread.cpp
@@ -654,6 +654,7 @@
bool_stop_other_threads = true;
ThreadPlanSP new_plan_sp;
+ Status new_plan_status;
if (m_step_type == eStepTypeInto) {
StackFrame *frame = thread->GetStackFrameAtIndex(0).get();
@@ -700,7 +701,7 @@
}
new_plan_sp = thread->QueueThreadPlanForStepInRange(
- abort_other_plans, range,
+ new_plan_status, abort_other_plans, range,
frame->GetSymbolContext(eSymbolContextEverything),
m_options.m_step_in_target.c_str(), stop_other_threads,
m_options.m_step_in_avoid_no_debug,
@@ -713,33 +714,33 @@
}
} else
new_plan_sp = thread->QueueThreadPlanForStepSingleInstruction(
- false, abort_other_plans, bool_stop_other_threads);
+ new_plan_status, false, abort_other_plans, bool_stop_other_threads);
} else if (m_step_type == eStepTypeOver) {
StackFrame *frame = thread->GetStackFrameAtIndex(0).get();
if (frame->HasDebugInformation())
new_plan_sp = thread->QueueThreadPlanForStepOverRange(
- abort_other_plans,
+ new_plan_status, abort_other_plans,
frame->GetSymbolContext(eSymbolContextEverything).line_entry,
frame->GetSymbolContext(eSymbolContextEverything),
stop_other_threads, m_options.m_step_out_avoid_no_debug);
else
new_plan_sp = thread->QueueThreadPlanForStepSingleInstruction(
- true, abort_other_plans, bool_stop_other_threads);
+ new_plan_status, true, abort_other_plans, bool_stop_other_threads);
} else if (m_step_type == eStepTypeTrace) {
new_plan_sp = thread->QueueThreadPlanForStepSingleInstruction(
- false, abort_other_plans, bool_stop_other_threads);
+ new_plan_status, false, abort_other_plans, bool_stop_other_threads);
} else if (m_step_type == eStepTypeTraceOver) {
new_plan_sp = thread->QueueThreadPlanForStepSingleInstruction(
- true, abort_other_plans, bool_stop_other_threads);
+ new_plan_status, true, abort_other_plans, bool_stop_other_threads);
} else if (m_step_type == eStepTypeOut) {
new_plan_sp = thread->QueueThreadPlanForStepOut(
- abort_other_plans, nullptr, false, bool_stop_other_threads, eVoteYes,
- eVoteNoOpinion, thread->GetSelectedFrameIndex(),
- m_options.m_step_out_avoid_no_debug);
+ new_plan_status, abort_other_plans, nullptr, false,
+ bool_stop_other_threads, eVoteYes, eVoteNoOpinion,
+ thread->GetSelectedFrameIndex(), m_options.m_step_out_avoid_no_debug);
} else if (m_step_type == eStepTypeScripted) {
new_plan_sp = thread->QueueThreadPlanForStepScripted(
- abort_other_plans, m_options.m_class_name.c_str(),
+ new_plan_status, abort_other_plans, m_options.m_class_name.c_str(),
bool_stop_other_threads);
} else {
result.AppendError("step type is not supported");
@@ -798,6 +799,7 @@
result.SetStatus(eReturnStatusSuccessContinuingNoResult);
}
} else {
+ result.SetError(new_plan_status);
result.AppendError("Couldn't find thread plan to implement step type.");
result.SetStatus(eReturnStatusFailed);
}
@@ -1194,6 +1196,7 @@
}
ThreadPlanSP new_plan_sp;
+ Status new_plan_status;
if (frame->HasDebugInformation()) {
// Finally we got here... Translate the given line number to a bunch
@@ -1273,14 +1276,21 @@
}
new_plan_sp = thread->QueueThreadPlanForStepUntil(
- abort_other_plans, &address_list.front(), address_list.size(),
- m_options.m_stop_others, m_options.m_frame_idx);
- // User level plans should be master plans so they can be interrupted
- // (e.g. by hitting a breakpoint) and other plans executed by the user
- // (stepping around the breakpoint) and then a "continue" will resume
- // the original plan.
- new_plan_sp->SetIsMasterPlan(true);
- new_plan_sp->SetOkayToDiscard(false);
+ new_plan_status, abort_other_plans, &address_list.front(),
+ address_list.size(), m_options.m_stop_others,
+ m_options.m_frame_idx);
+ if (new_plan_sp) {
+ // User level plans should be master plans so they can be interrupted
+ // (e.g. by hitting a breakpoint) and other plans executed by the
+ // user (stepping around the breakpoint) and then a "continue" will
+ // resume the original plan.
+ new_plan_sp->SetIsMasterPlan(true);
+ new_plan_sp->SetOkayToDiscard(false);
+ } else {
+ result.SetError(new_plan_status);
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
} else {
result.AppendErrorWithFormat(
"Frame index %u of thread %u has no debug information.\n",
Index: source/Breakpoint/Breakpoint.cpp
===================================================================
--- source/Breakpoint/Breakpoint.cpp
+++ source/Breakpoint/Breakpoint.cpp
@@ -857,6 +857,10 @@
return m_locations.GetNumResolvedLocations();
}
+bool Breakpoint::HasResolvedLocations() const {
+ return GetNumResolvedLocations() > 0;
+}
+
size_t Breakpoint::GetNumLocations() const { return m_locations.GetSize(); }
bool Breakpoint::AddName(llvm::StringRef new_name) {
Index: source/API/SBThreadPlan.cpp
===================================================================
--- source/API/SBThreadPlan.cpp
+++ source/API/SBThreadPlan.cpp
@@ -152,9 +152,10 @@
AddressRange range(*start_address, size);
SymbolContext sc;
start_address->CalculateSymbolContext(&sc);
+ Status plan_status;
return SBThreadPlan(
m_opaque_sp->GetThread().QueueThreadPlanForStepOverRange(
- false, range, sc, eAllThreads));
+ plan_status, false, range, sc, eAllThreads));
} else {
return SBThreadPlan();
}
@@ -172,8 +173,9 @@
AddressRange range(*start_address, size);
SymbolContext sc;
start_address->CalculateSymbolContext(&sc);
+ Status plan_status;
return SBThreadPlan(m_opaque_sp->GetThread().QueueThreadPlanForStepInRange(
- false, range, sc, NULL, eAllThreads));
+ plan_status, false, range, sc, NULL, eAllThreads));
} else {
return SBThreadPlan();
}
@@ -184,10 +186,11 @@
bool first_insn) {
if (m_opaque_sp) {
SymbolContext sc;
+ Status status;
sc = m_opaque_sp->GetThread().GetStackFrameAtIndex(0)->GetSymbolContext(
lldb::eSymbolContextEverything);
return SBThreadPlan(m_opaque_sp->GetThread().QueueThreadPlanForStepOut(
- false, &sc, first_insn, false, eVoteYes, eVoteNoOpinion,
+ status, false, &sc, first_insn, false, eVoteYes, eVoteNoOpinion,
frame_idx_to_step_to));
} else {
return SBThreadPlan();
@@ -201,18 +204,20 @@
if (!address)
return SBThreadPlan();
+ Status status;
return SBThreadPlan(m_opaque_sp->GetThread().QueueThreadPlanForRunToAddress(
- false, *address, false));
+ status, false, *address, false));
} else {
return SBThreadPlan();
}
}
SBThreadPlan
SBThreadPlan::QueueThreadPlanForStepScripted(const char *script_class_name) {
if (m_opaque_sp) {
+ Status status;
return SBThreadPlan(m_opaque_sp->GetThread().QueueThreadPlanForStepScripted(
- false, script_class_name, false));
+ status, false, script_class_name, false));
} else {
return SBThreadPlan();
}
Index: source/API/SBThread.cpp
===================================================================
--- source/API/SBThread.cpp
+++ source/API/SBThread.cpp
@@ -657,17 +657,18 @@
bool abort_other_plans = false;
StackFrameSP frame_sp(thread->GetStackFrameAtIndex(0));
+ Status new_plan_status;
ThreadPlanSP new_plan_sp;
if (frame_sp) {
if (frame_sp->HasDebugInformation()) {
const LazyBool avoid_no_debug = eLazyBoolCalculate;
SymbolContext sc(frame_sp->GetSymbolContext(eSymbolContextEverything));
new_plan_sp = thread->QueueThreadPlanForStepOverRange(
- abort_other_plans, sc.line_entry, sc, stop_other_threads,
- avoid_no_debug);
+ new_plan_status, abort_other_plans, sc.line_entry, sc,
+ stop_other_threads, avoid_no_debug);
} else {
new_plan_sp = thread->QueueThreadPlanForStepSingleInstruction(
- true, abort_other_plans, stop_other_threads);
+ new_plan_status, true, abort_other_plans, stop_other_threads);
}
}
error = ResumeNewPlan(exe_ctx, new_plan_sp.get());
@@ -707,6 +708,7 @@
Thread *thread = exe_ctx.GetThreadPtr();
StackFrameSP frame_sp(thread->GetStackFrameAtIndex(0));
ThreadPlanSP new_plan_sp;
+ Status new_plan_status;
if (frame_sp && frame_sp->HasDebugInformation()) {
SymbolContext sc(frame_sp->GetSymbolContext(eSymbolContextEverything));
@@ -723,12 +725,12 @@
const LazyBool step_in_avoids_code_without_debug_info =
eLazyBoolCalculate;
new_plan_sp = thread->QueueThreadPlanForStepInRange(
- abort_other_plans, range, sc, target_name, stop_other_threads,
- step_in_avoids_code_without_debug_info,
+ new_plan_status, abort_other_plans, range, sc, target_name,
+ stop_other_threads, step_in_avoids_code_without_debug_info,
step_out_avoids_code_without_debug_info);
} else {
new_plan_sp = thread->QueueThreadPlanForStepSingleInstruction(
- false, abort_other_plans, stop_other_threads);
+ new_plan_status, false, abort_other_plans, stop_other_threads);
}
error = ResumeNewPlan(exe_ctx, new_plan_sp.get());
}
@@ -759,9 +761,10 @@
Thread *thread = exe_ctx.GetThreadPtr();
const LazyBool avoid_no_debug = eLazyBoolCalculate;
+ Status new_plan_status;
ThreadPlanSP new_plan_sp(thread->QueueThreadPlanForStepOut(
- abort_other_plans, NULL, false, stop_other_threads, eVoteYes,
- eVoteNoOpinion, 0, avoid_no_debug));
+ new_plan_status, abort_other_plans, NULL, false, stop_other_threads,
+ eVoteYes, eVoteNoOpinion, 0, avoid_no_debug));
error = ResumeNewPlan(exe_ctx, new_plan_sp.get());
}
@@ -812,9 +815,10 @@
return;
}
+ Status new_plan_status;
ThreadPlanSP new_plan_sp(thread->QueueThreadPlanForStepOut(
- abort_other_plans, NULL, false, stop_other_threads, eVoteYes,
- eVoteNoOpinion, frame_sp->GetFrameIndex()));
+ new_plan_status, abort_other_plans, NULL, false, stop_other_threads,
+ eVoteYes, eVoteNoOpinion, frame_sp->GetFrameIndex()));
error = ResumeNewPlan(exe_ctx, new_plan_sp.get());
}
@@ -840,8 +844,9 @@
}
Thread *thread = exe_ctx.GetThreadPtr();
- ThreadPlanSP new_plan_sp(
- thread->QueueThreadPlanForStepSingleInstruction(step_over, true, true));
+ Status new_plan_status;
+ ThreadPlanSP new_plan_sp(thread->QueueThreadPlanForStepSingleInstruction(
+ new_plan_status, step_over, true, true));
error = ResumeNewPlan(exe_ctx, new_plan_sp.get());
}
@@ -873,8 +878,9 @@
Thread *thread = exe_ctx.GetThreadPtr();
+ Status new_plan_status;
ThreadPlanSP new_plan_sp(thread->QueueThreadPlanForRunToAddress(
- abort_other_plans, target_addr, stop_other_threads));
+ new_plan_status, abort_other_plans, target_addr, stop_other_threads));
error = ResumeNewPlan(exe_ctx, new_plan_sp.get());
}
@@ -988,8 +994,9 @@
} else
sb_error.SetErrorString("step until target not in current function");
} else {
+ Status new_plan_status;
ThreadPlanSP new_plan_sp(thread->QueueThreadPlanForStepUntil(
- abort_other_plans, &step_over_until_addrs[0],
+ new_plan_status, abort_other_plans, &step_over_until_addrs[0],
step_over_until_addrs.size(), stop_other_threads,
frame_sp->GetFrameIndex()));
@@ -1024,12 +1031,14 @@
}
Thread *thread = exe_ctx.GetThreadPtr();
- ThreadPlanSP thread_plan_sp =
- thread->QueueThreadPlanForStepScripted(false, script_class_name, false);
+ Status thread_plan_status;
+ ThreadPlanSP thread_plan_sp = thread->QueueThreadPlanForStepScripted(
+ thread_plan_status, false, script_class_name, false);
if (!thread_plan_sp) {
sb_error.SetErrorStringWithFormat(
- "Error queueing thread plan for class: %s", script_class_name);
+ "Error queueing thread plan for class: %s: %s", script_class_name,
+ thread_plan_status.AsCString());
return sb_error;
}
@@ -1041,7 +1050,8 @@
sb_error = ResumeNewPlan(exe_ctx, thread_plan_sp.get());
else {
sb_error.SetErrorStringWithFormat(
- "Error resuming thread plan for class: %s.", script_class_name);
+ "Error resuming thread plan for class: %s: %s", script_class_name,
+ thread_plan_status.AsCString());
if (log)
log->Printf("SBThread(%p)::StepUsingScriptedThreadPlan: Error queuing "
"thread plan for class: %s",
Index: source/API/SBBreakpoint.cpp
===================================================================
--- source/API/SBBreakpoint.cpp
+++ source/API/SBBreakpoint.cpp
@@ -692,6 +692,13 @@
return num_locations;
}
+bool SBBreakpoint::IsHardware() const {
+ BreakpointSP bkpt_sp = GetSP();
+ if (bkpt_sp)
+ return bkpt_sp->IsHardware();
+ return false;
+}
+
BreakpointSP SBBreakpoint::GetSP() const { return m_opaque_wp.lock(); }
// This is simple collection of breakpoint id's and their target.
Index: scripts/interface/SBBreakpoint.i
===================================================================
--- scripts/interface/SBBreakpoint.i
+++ scripts/interface/SBBreakpoint.i
@@ -251,6 +251,9 @@
static uint32_t
GetNumBreakpointLocationsFromEvent (const lldb::SBEvent &event_sp);
+ bool
+ IsHardware ();
+
%pythoncode %{
class locations_access(object):
Index: packages/Python/lldbsuite/test/functionalities/step_scripted/TestStepScripted.py
===================================================================
--- packages/Python/lldbsuite/test/functionalities/step_scripted/TestStepScripted.py
+++ packages/Python/lldbsuite/test/functionalities/step_scripted/TestStepScripted.py
@@ -35,7 +35,7 @@
self.assertEqual("foo", frame.GetFunctionName())
err = thread.StepUsingScriptedThreadPlan(name)
- self.assertTrue(err.Success(), "Failed to step out")
+ self.assertTrue(err.Success(), err.GetCString())
frame = thread.GetFrameAtIndex(0)
self.assertEqual("main", frame.GetFunctionName())
Index: packages/Python/lldbsuite/test/functionalities/breakpoint/require_hw_breakpoints/main.c
===================================================================
--- /dev/null
+++ packages/Python/lldbsuite/test/functionalities/breakpoint/require_hw_breakpoints/main.c
@@ -0,0 +1,9 @@
+int break_on_me() {
+ int i = 10;
+ i++;
+ return i;
+}
+
+int main() {
+ return break_on_me();
+}
Index: packages/Python/lldbsuite/test/functionalities/breakpoint/require_hw_breakpoints/TestRequireHWBreakpoints.py
===================================================================
--- /dev/null
+++ packages/Python/lldbsuite/test/functionalities/breakpoint/require_hw_breakpoints/TestRequireHWBreakpoints.py
@@ -0,0 +1,107 @@
+"""
+Test require hardware breakpoints.
+"""
+
+from __future__ import print_function
+
+import os
+import time
+import lldb
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+
+
+class BreakpointLocationsTestCase(TestBase):
+
+ mydir = TestBase.compute_mydir(__file__)
+
+ def test_breakpoint(self):
+ """Test regular breakpoints when hardware breakpoints are required."""
+ self.build()
+ exe = self.getBuildArtifact("a.out")
+ target = self.dbg.CreateTarget(exe)
+
+ self.runCmd("settings set target.require-hardware-breakpoint true")
+
+ breakpoint = target.BreakpointCreateByLocation("main.c", 1)
+ self.assertTrue(breakpoint.IsHardware())
+
+ def test_step_range(self):
+ """Test stepping when hardware breakpoints are required."""
+ self.build()
+ exe = self.getBuildArtifact("a.out")
+ target = self.dbg.CreateTarget(exe)
+
+ breakpoint = target.BreakpointCreateByLocation("main.c", 1)
+
+ self.runCmd("run")
+
+ stepping_thread = lldbutil.get_one_thread_stopped_at_breakpoint(
+ target.GetProcess(), breakpoint)
+ self.assertTrue(stepping_thread.IsValid(),
+ "We stopped at the right breakpoint")
+
+ self.runCmd("settings set target.require-hardware-breakpoint true")
+
+ self.expect("thread step-in")
+ self.expect("thread step-in", error=True)
+
+ def test_step_out(self):
+ """Test stepping out when hardware breakpoints are required."""
+ self.build()
+ exe = self.getBuildArtifact("a.out")
+ target = self.dbg.CreateTarget(exe)
+
+ breakpoint = target.BreakpointCreateByLocation("main.c", 1)
+
+ self.runCmd("run")
+
+ stepping_thread = lldbutil.get_one_thread_stopped_at_breakpoint(
+ target.GetProcess(), breakpoint)
+ self.assertTrue(stepping_thread.IsValid(),
+ "We stopped at the right breakpoint")
+
+ self.runCmd("settings set target.require-hardware-breakpoint true")
+
+ self.expect("thread step-out", error=True)
+
+ def test_step_over(self):
+ """Test stepping over when hardware breakpoints are required."""
+ self.build()
+ exe = self.getBuildArtifact("a.out")
+ target = self.dbg.CreateTarget(exe)
+
+ breakpoint = target.BreakpointCreateByLocation("main.c", 7)
+
+ self.runCmd("run")
+
+ stepping_thread = lldbutil.get_one_thread_stopped_at_breakpoint(
+ target.GetProcess(), breakpoint)
+ self.assertTrue(stepping_thread.IsValid(),
+ "We stopped at the right breakpoint")
+
+ self.runCmd("settings set target.require-hardware-breakpoint true")
+
+ # Step over doesn't fail immediately but fails later on.
+ self.expect("thread step-over")
+ self.expect("process status", substrs=['stop reason = step over (FAILED)'])
+
+ def test_step_until(self):
+ """Test stepping until when hardware breakpoints are required."""
+ self.build()
+ exe = self.getBuildArtifact("a.out")
+ target = self.dbg.CreateTarget(exe)
+
+ breakpoint = target.BreakpointCreateByLocation("main.c", 7)
+
+ self.runCmd("run")
+
+ stepping_thread = lldbutil.get_one_thread_stopped_at_breakpoint(
+ target.GetProcess(), breakpoint)
+ self.assertTrue(stepping_thread.IsValid(),
+ "We stopped at the right breakpoint")
+
+ self.runCmd("settings set target.require-hardware-breakpoint true")
+
+ self.expect("thread until 5", error=True)
Index: packages/Python/lldbsuite/test/functionalities/breakpoint/require_hw_breakpoints/Makefile
===================================================================
--- /dev/null
+++ packages/Python/lldbsuite/test/functionalities/breakpoint/require_hw_breakpoints/Makefile
@@ -0,0 +1,9 @@
+LEVEL = ../../../make
+
+C_SOURCES := main.c
+
+ifneq (,$(findstring icc,$(CC)))
+ CFLAGS += -debug inline-debug-info
+endif
+
+include $(LEVEL)/Makefile.rules
Index: include/lldb/Target/ThreadPlanStepUntil.h
===================================================================
--- include/lldb/Target/ThreadPlanStepUntil.h
+++ include/lldb/Target/ThreadPlanStepUntil.h
@@ -54,12 +54,13 @@
typedef std::map<lldb::addr_t, lldb::break_id_t> until_collection;
until_collection m_until_points;
bool m_stop_others;
+ bool m_could_not_resolve_hw_bp;
void Clear();
friend lldb::ThreadPlanSP Thread::QueueThreadPlanForStepUntil(
- bool abort_other_plans, lldb::addr_t *address_list, size_t num_addresses,
- bool stop_others, uint32_t frame_idx);
+ Status &status, bool abort_other_plans, lldb::addr_t *address_list,
+ size_t num_addresses, bool stop_others, uint32_t frame_idx);
// Need an appropriate marker for the current stack so we can tell step out
// from step in.
Index: include/lldb/Target/ThreadPlanStepThrough.h
===================================================================
--- include/lldb/Target/ThreadPlanStepThrough.h
+++ include/lldb/Target/ThreadPlanStepThrough.h
@@ -44,11 +44,9 @@
bool HitOurBackstopBreakpoint();
private:
- friend lldb::ThreadPlanSP
-
- Thread::QueueThreadPlanForStepThrough(StackID &return_stack_id,
- bool abort_other_plans,
- bool stop_others);
+ friend lldb::ThreadPlanSP Thread::QueueThreadPlanForStepThrough(
+ Status &status, StackID &return_stack_id, bool abort_other_plans,
+ bool stop_others);
void ClearBackstopBreakpoint();
@@ -58,6 +56,7 @@
lldb::addr_t m_backstop_addr;
StackID m_return_stack_id;
bool m_stop_others;
+ bool m_could_not_resolve_hw_bp;
DISALLOW_COPY_AND_ASSIGN(ThreadPlanStepThrough);
};
Index: include/lldb/Target/ThreadPlanStepRange.h
===================================================================
--- include/lldb/Target/ThreadPlanStepRange.h
+++ include/lldb/Target/ThreadPlanStepRange.h
@@ -81,6 +81,7 @@
lldb::BreakpointSP m_next_branch_bp_sp;
bool m_use_fast_step;
bool m_given_ranges_only;
+ bool m_could_not_resolve_hw_bp;
private:
std::vector<lldb::DisassemblerSP> m_instruction_ranges;
Index: include/lldb/Target/ThreadPlanStepOut.h
===================================================================
--- include/lldb/Target/ThreadPlanStepOut.h
+++ include/lldb/Target/ThreadPlanStepOut.h
@@ -77,11 +77,12 @@
std::vector<lldb::StackFrameSP> m_stepped_past_frames;
lldb::ValueObjectSP m_return_valobj_sp;
bool m_calculate_return_value;
+ bool m_could_not_resolve_hw_bp;
friend lldb::ThreadPlanSP Thread::QueueThreadPlanForStepOut(
- bool abort_other_plans, SymbolContext *addr_context, bool first_insn,
- bool stop_others, Vote stop_vote, Vote run_vote, uint32_t frame_idx,
- LazyBool step_out_avoids_code_without_debug_info);
+ Status &status, bool abort_other_plans, SymbolContext *addr_context,
+ bool first_insn, bool stop_others, Vote stop_vote, Vote run_vote,
+ uint32_t frame_idx, LazyBool step_out_avoids_code_without_debug_info);
void SetupAvoidNoDebug(LazyBool step_out_avoids_code_without_debug_info);
// Need an appropriate marker for the current stack so we can tell step out
Index: include/lldb/Target/ThreadPlanStepInstruction.h
===================================================================
--- include/lldb/Target/ThreadPlanStepInstruction.h
+++ include/lldb/Target/ThreadPlanStepInstruction.h
@@ -43,7 +43,8 @@
private:
friend lldb::ThreadPlanSP Thread::QueueThreadPlanForStepSingleInstruction(
- bool step_over, bool abort_other_plans, bool stop_other_threads);
+ Status &status, bool step_over, bool abort_other_plans,
+ bool stop_other_threads);
lldb::addr_t m_instruction_addr;
bool m_stop_other_threads;
Index: include/lldb/Target/ThreadPlanStepInRange.h
===================================================================
--- include/lldb/Target/ThreadPlanStepInRange.h
+++ include/lldb/Target/ThreadPlanStepInRange.h
@@ -78,11 +78,11 @@
private:
friend lldb::ThreadPlanSP Thread::QueueThreadPlanForStepOverRange(
- bool abort_other_plans, const AddressRange &range,
+ Status &status, bool abort_other_plans, const AddressRange &range,
const SymbolContext &addr_context, lldb::RunMode stop_others,
LazyBool avoid_code_without_debug_info);
friend lldb::ThreadPlanSP Thread::QueueThreadPlanForStepInRange(
- bool abort_other_plans, const AddressRange &range,
+ Status &status, bool abort_other_plans, const AddressRange &range,
const SymbolContext &addr_context, const char *step_in_target,
lldb::RunMode stop_others,
LazyBool step_in_avoids_code_without_debug_info,
Index: include/lldb/Target/ThreadPlanRunToAddress.h
===================================================================
--- include/lldb/Target/ThreadPlanRunToAddress.h
+++ include/lldb/Target/ThreadPlanRunToAddress.h
@@ -63,6 +63,7 @@
// TODO: Would it be useful to have multiple addresses?
std::vector<lldb::break_id_t> m_break_ids; // This is the breakpoint we are
// using to stop us at m_address.
+ bool m_could_not_resolve_hw_bp;
DISALLOW_COPY_AND_ASSIGN(ThreadPlanRunToAddress);
};
Index: include/lldb/Target/ThreadPlanBase.h
===================================================================
--- include/lldb/Target/ThreadPlanBase.h
+++ include/lldb/Target/ThreadPlanBase.h
@@ -52,7 +52,7 @@
private:
friend lldb::ThreadPlanSP
- Thread::QueueFundamentalPlan(bool abort_other_plans);
+ Thread::QueueFundamentalPlan(Status &status, bool abort_other_plans);
DISALLOW_COPY_AND_ASSIGN(ThreadPlanBase);
};
Index: include/lldb/Target/Thread.h
===================================================================
--- include/lldb/Target/Thread.h
+++ include/lldb/Target/Thread.h
@@ -640,7 +640,8 @@
/// A shared pointer to the newly queued thread plan, or nullptr if the
/// plan could not be queued.
//------------------------------------------------------------------
- virtual lldb::ThreadPlanSP QueueFundamentalPlan(bool abort_other_plans);
+ virtual lldb::ThreadPlanSP QueueFundamentalPlan(Status &status,
+ bool abort_other_plans);
//------------------------------------------------------------------
/// Queues the plan used to step one instruction from the current PC of \a
@@ -661,8 +662,10 @@
/// A shared pointer to the newly queued thread plan, or nullptr if the
/// plan could not be queued.
//------------------------------------------------------------------
- virtual lldb::ThreadPlanSP QueueThreadPlanForStepSingleInstruction(
- bool step_over, bool abort_other_plans, bool stop_other_threads);
+ virtual lldb::ThreadPlanSP
+ QueueThreadPlanForStepSingleInstruction(Status &status, bool step_over,
+ bool abort_other_plans,
+ bool stop_other_threads);
//------------------------------------------------------------------
/// Queues the plan used to step through an address range, stepping over
@@ -702,15 +705,15 @@
/// plan could not be queued.
//------------------------------------------------------------------
virtual lldb::ThreadPlanSP QueueThreadPlanForStepOverRange(
- bool abort_other_plans, const AddressRange &range,
+ Status &status, bool abort_other_plans, const AddressRange &range,
const SymbolContext &addr_context, lldb::RunMode stop_other_threads,
LazyBool step_out_avoids_code_without_debug_info = eLazyBoolCalculate);
// Helper function that takes a LineEntry to step, insted of an AddressRange.
// This may combine multiple LineEntries of the same source line number to
// step over a longer address range in a single operation.
virtual lldb::ThreadPlanSP QueueThreadPlanForStepOverRange(
- bool abort_other_plans, const LineEntry &line_entry,
+ Status &status, bool abort_other_plans, const LineEntry &line_entry,
const SymbolContext &addr_context, lldb::RunMode stop_other_threads,
LazyBool step_out_avoids_code_without_debug_info = eLazyBoolCalculate);
@@ -761,7 +764,7 @@
/// plan could not be queued.
//------------------------------------------------------------------
virtual lldb::ThreadPlanSP QueueThreadPlanForStepInRange(
- bool abort_other_plans, const AddressRange &range,
+ Status &status, bool abort_other_plans, const AddressRange &range,
const SymbolContext &addr_context, const char *step_in_target,
lldb::RunMode stop_other_threads,
LazyBool step_in_avoids_code_without_debug_info = eLazyBoolCalculate,
@@ -771,7 +774,7 @@
// This may combine multiple LineEntries of the same source line number to
// step over a longer address range in a single operation.
virtual lldb::ThreadPlanSP QueueThreadPlanForStepInRange(
- bool abort_other_plans, const LineEntry &line_entry,
+ Status &status, bool abort_other_plans, const LineEntry &line_entry,
const SymbolContext &addr_context, const char *step_in_target,
lldb::RunMode stop_other_threads,
LazyBool step_in_avoids_code_without_debug_info = eLazyBoolCalculate,
@@ -815,8 +818,8 @@
/// plan could not be queued.
//------------------------------------------------------------------
virtual lldb::ThreadPlanSP QueueThreadPlanForStepOut(
- bool abort_other_plans, SymbolContext *addr_context, bool first_insn,
- bool stop_other_threads,
+ Status &status, bool abort_other_plans, SymbolContext *addr_context,
+ bool first_insn, bool stop_other_threads,
Vote stop_vote, // = eVoteYes,
Vote run_vote, // = eVoteNoOpinion);
uint32_t frame_idx,
@@ -875,8 +878,8 @@
/// plan could not be queued.
//------------------------------------------------------------------
virtual lldb::ThreadPlanSP QueueThreadPlanForStepOutNoShouldStop(
- bool abort_other_plans, SymbolContext *addr_context, bool first_insn,
- bool stop_other_threads,
+ Status &status, bool abort_other_plans, SymbolContext *addr_context,
+ bool first_insn, bool stop_other_threads,
Vote stop_vote, // = eVoteYes,
Vote run_vote, // = eVoteNoOpinion);
uint32_t frame_idx, bool continue_to_next_branch = false);
@@ -904,7 +907,7 @@
/// plan could not be queued.
//------------------------------------------------------------------
virtual lldb::ThreadPlanSP
- QueueThreadPlanForStepThrough(StackID &return_stack_id,
+ QueueThreadPlanForStepThrough(Status &status, StackID &return_stack_id,
bool abort_other_plans,
bool stop_other_threads);
@@ -929,16 +932,17 @@
/// plan could not be queued.
//------------------------------------------------------------------
virtual lldb::ThreadPlanSP
- QueueThreadPlanForRunToAddress(bool abort_other_plans, Address &target_addr,
- bool stop_other_threads);
+ QueueThreadPlanForRunToAddress(Status &status, bool abort_other_plans,
+ Address &target_addr, bool stop_other_threads);
virtual lldb::ThreadPlanSP
- QueueThreadPlanForStepUntil(bool abort_other_plans,
+ QueueThreadPlanForStepUntil(Status &status, bool abort_other_plans,
lldb::addr_t *address_list, size_t num_addresses,
bool stop_others, uint32_t frame_idx);
virtual lldb::ThreadPlanSP
- QueueThreadPlanForStepScripted(bool abort_other_plans, const char *class_name,
+ QueueThreadPlanForStepScripted(Status &status, bool abort_other_plans,
+ const char *class_name,
bool stop_other_threads);
//------------------------------------------------------------------
@@ -1040,7 +1044,7 @@
/// @return
/// A pointer to the last completed plan.
//------------------------------------------------------------------
- void QueueThreadPlan(lldb::ThreadPlanSP &plan_sp, bool abort_other_plans);
+ Status QueueThreadPlan(lldb::ThreadPlanSP &plan_sp, bool abort_other_plans);
//------------------------------------------------------------------
/// Discards the plans queued on the plan stack of the current thread. This
Index: include/lldb/Target/Target.h
===================================================================
--- include/lldb/Target/Target.h
+++ include/lldb/Target/Target.h
@@ -202,6 +202,10 @@
bool GetUseModernTypeLookup() const;
+ void SetRequireHardwareBreakpoints(bool b);
+
+ bool GetRequireHardwareBreakpoints() const;
+
private:
//------------------------------------------------------------------
// Callbacks for m_launch_info.
Index: include/lldb/Breakpoint/Breakpoint.h
===================================================================
--- include/lldb/Breakpoint/Breakpoint.h
+++ include/lldb/Breakpoint/Breakpoint.h
@@ -502,6 +502,14 @@
//------------------------------------------------------------------
size_t GetNumResolvedLocations() const;
+ //------------------------------------------------------------------
+ /// Return whether this breakpoint has any resolved locations.
+ ///
+ /// @return
+ /// True if GetNumResolvedLocations > 0
+ //------------------------------------------------------------------
+ bool HasResolvedLocations() const;
+
//------------------------------------------------------------------
/// Return the number of breakpoint locations.
///
Index: include/lldb/API/SBBreakpoint.h
===================================================================
--- include/lldb/API/SBBreakpoint.h
+++ include/lldb/API/SBBreakpoint.h
@@ -129,6 +129,8 @@
static uint32_t
GetNumBreakpointLocationsFromEvent(const lldb::SBEvent &event_sp);
+ bool IsHardware() const;
+
// Can only be called from a ScriptedBreakpointResolver...
SBError
AddLocation(SBAddress &address);
_______________________________________________
lldb-commits mailing list
[email protected]
http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits