JDevlieghere updated this revision to Diff 173191.
JDevlieghere added a comment.

Update tests to use SB API.


https://reviews.llvm.org/D54221

Files:
  include/lldb/API/SBBreakpoint.h
  include/lldb/API/SBThreadPlan.h
  include/lldb/Breakpoint/Breakpoint.h
  include/lldb/Target/Target.h
  include/lldb/Target/Thread.h
  include/lldb/Target/ThreadPlan.h
  include/lldb/Target/ThreadPlanPython.h
  include/lldb/Target/ThreadPlanShouldStopHere.h
  include/lldb/Target/ThreadPlanStepInRange.h
  include/lldb/Target/ThreadPlanStepInstruction.h
  include/lldb/Target/ThreadPlanStepOut.h
  include/lldb/Target/ThreadPlanStepThrough.h
  include/lldb/Target/ThreadPlanStepUntil.h
  include/lldb/lldb-private-interfaces.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/ThreadPlan.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
@@ -57,7 +57,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 +100,7 @@
     }
   }
   m_until_points.clear();
+  m_could_not_resolve_hw_bp = false;
 }
 
 void ThreadPlanStepUntil::GetDescription(Stream *s,
@@ -127,9 +131,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
@@ -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
@@ -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
@@ -51,10 +51,18 @@
 
 void ThreadPlanStepOverRange::GetDescription(Stream *s,
                                              lldb::DescriptionLevel level) {
+  auto PrintFailureIfAny = [&]() {
+    if (m_status.Success())
+      return;
+    s->Printf(" failed (%s)", m_status.AsCString());
+  };
+
   if (level == lldb::eDescriptionLevelBrief) {
     s->Printf("step over");
+    PrintFailureIfAny();
     return;
   }
+
   s->Printf("Stepping over");
   bool printed_line_info = false;
   if (m_addr_context.line_entry.IsValid()) {
@@ -68,6 +76,8 @@
     DumpRanges(s);
   }
 
+  PrintFailureIfAny();
+
   s->PutChar('.');
 }
 
@@ -151,8 +161,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(m_status, m_stack_id,
+                                                         false, stop_others);
 
     if (new_plan_sp && log)
       log->Printf(
@@ -172,12 +182,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);
+            m_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(
+            m_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 +206,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(m_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 +297,7 @@
                               cur_pc);
 
                       new_plan_sp = m_thread.QueueThreadPlanForStepOverRange(
-                          abort_other_plans, step_range, sc,
+                          m_status, abort_other_plans, step_range, sc,
                           stop_other_threads);
                       break;
                     }
@@ -309,7 +319,7 @@
   // If we haven't figured out something to do yet, then ask the ShouldStopHere
   // callback:
   if (!new_plan_sp) {
-    new_plan_sp = CheckShouldStopHereAndQueueStepOut(frame_order);
+    new_plan_sp = CheckShouldStopHereAndQueueStepOut(frame_order, m_status);
   }
 
   if (!new_plan_sp)
@@ -323,7 +333,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(m_status.Success());
     return true;
   } else
     return false;
Index: source/Target/ThreadPlanStepOut.cpp
===================================================================
--- source/Target/ThreadPlanStepOut.cpp
+++ source/Target/ThreadPlanStepOut.cpp
@@ -133,7 +133,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 +230,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) {
@@ -281,7 +294,7 @@
         }
 
         if (done) {
-          if (InvokeShouldStopHereCallback(eFrameCompareOlder)) {
+          if (InvokeShouldStopHereCallback(eFrameCompareOlder, m_status)) {
             CalculateReturnValue();
             SetPlanComplete();
           }
@@ -343,12 +356,12 @@
   // is consult the ShouldStopHere, and we are done.
 
   if (done) {
-    if (InvokeShouldStopHereCallback(eFrameCompareOlder)) {
+    if (InvokeShouldStopHereCallback(eFrameCompareOlder, m_status)) {
       CalculateReturnValue();
       SetPlanComplete();
     } else {
       m_step_out_further_plan_sp =
-          QueueStepOutFromHerePlan(m_flags, eFrameCompareOlder);
+          QueueStepOutFromHerePlan(m_flags, eFrameCompareOlder, m_status);
       done = false;
     }
   }
Index: source/Target/ThreadPlanStepInstruction.cpp
===================================================================
--- source/Target/ThreadPlanStepInstruction.cpp
+++ source/Target/ThreadPlanStepInstruction.cpp
@@ -57,11 +57,19 @@
 
 void ThreadPlanStepInstruction::GetDescription(Stream *s,
                                                lldb::DescriptionLevel level) {
+  auto PrintFailureIfAny = [&]() {
+    if (m_status.Success())
+      return;
+    s->Printf(" failed (%s)", m_status.AsCString());
+  };
+
   if (level == lldb::eDescriptionLevelBrief) {
     if (m_step_over)
       s->Printf("instruction step over");
     else
       s->Printf("instruction step into");
+
+    PrintFailureIfAny();
   } else {
     s->Printf("Stepping one instruction past ");
     s->Address(m_instruction_addr, sizeof(addr_t));
@@ -72,6 +80,8 @@
       s->Printf(" stepping over calls");
     else
       s->Printf(" stepping into calls");
+
+    PrintFailureIfAny();
   }
 }
 
@@ -192,7 +202,8 @@
           // for now it is safer to run others.
           const bool stop_others = false;
           m_thread.QueueThreadPlanForStepOutNoShouldStop(
-              false, nullptr, true, stop_others, eVoteNo, eVoteNoOpinion, 0);
+              m_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
@@ -112,8 +112,16 @@
 
 void ThreadPlanStepInRange::GetDescription(Stream *s,
                                            lldb::DescriptionLevel level) {
+
+  auto PrintFailureIfAny = [&]() {
+    if (m_status.Success())
+      return;
+    s->Printf(" failed (%s)", m_status.AsCString());
+  };
+
   if (level == lldb::eDescriptionLevelBrief) {
     s->Printf("step in");
+    PrintFailureIfAny();
     return;
   }
 
@@ -134,6 +142,8 @@
     DumpRanges(s);
   }
 
+  PrintFailureIfAny();
+
   s->PutChar('.');
 }
 
@@ -166,7 +176,8 @@
     // ShouldStopHere plan, and otherwise we're done.
     // FIXME - This can be both a step in and a step out.  Probably should
     // record which in the m_virtual_step.
-    m_sub_plan_sp = CheckShouldStopHereAndQueueStepOut(eFrameCompareYounger);
+    m_sub_plan_sp =
+        CheckShouldStopHereAndQueueStepOut(eFrameCompareYounger, m_status);
   } else {
     // Stepping through should be done running other threads in general, since
     // we're setting a breakpoint and continuing.  So only stop others if we
@@ -185,11 +196,12 @@
       // 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(
+          m_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);
+        m_sub_plan_sp =
+            CheckShouldStopHereAndQueueStepOut(frame_order, m_status);
         if (log) {
           if (m_sub_plan_sp)
             log->Printf("ShouldStopHere found plan to step out of this frame.");
@@ -227,8 +239,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(
+          m_status, m_stack_id, false, stop_others);
 
     if (log) {
       if (m_sub_plan_sp)
@@ -240,7 +252,7 @@
     // If not, give the "should_stop" callback a chance to push a plan to get
     // us out of here. But only do that if we actually have stepped in.
     if (!m_sub_plan_sp && frame_order == eFrameCompareYounger)
-      m_sub_plan_sp = CheckShouldStopHereAndQueueStepOut(frame_order);
+      m_sub_plan_sp = CheckShouldStopHereAndQueueStepOut(frame_order, m_status);
 
     // If we've stepped in and we are going to stop here, check to see if we
     // were asked to run past the prologue, and if so do that.
@@ -288,7 +300,7 @@
             log->Printf("Pushing past prologue ");
 
           m_sub_plan_sp = m_thread.QueueThreadPlanForRunToAddress(
-              false, func_start_address, true);
+              m_status, false, func_start_address, true);
         }
       }
     }
@@ -384,15 +396,15 @@
 
 bool ThreadPlanStepInRange::DefaultShouldStopHereCallback(
     ThreadPlan *current_plan, Flags &flags, FrameComparison operation,
-    void *baton) {
+    Status &status, void *baton) {
   bool should_stop_here = true;
   StackFrame *frame = current_plan->GetThread().GetStackFrameAtIndex(0).get();
   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
 
   // First see if the ThreadPlanShouldStopHere default implementation thinks we
   // should get out of here:
   should_stop_here = ThreadPlanShouldStopHere::DefaultShouldStopHereCallback(
-      current_plan, flags, operation, baton);
+      current_plan, flags, operation, status, baton);
   if (!should_stop_here)
     return should_stop_here;
 
Index: source/Target/ThreadPlanShouldStopHere.cpp
===================================================================
--- source/Target/ThreadPlanShouldStopHere.cpp
+++ source/Target/ThreadPlanShouldStopHere.cpp
@@ -43,11 +43,11 @@
 ThreadPlanShouldStopHere::~ThreadPlanShouldStopHere() = default;
 
 bool ThreadPlanShouldStopHere::InvokeShouldStopHereCallback(
-    FrameComparison operation) {
+    FrameComparison operation, Status &status) {
   bool should_stop_here = true;
   if (m_callbacks.should_stop_here_callback) {
     should_stop_here = m_callbacks.should_stop_here_callback(
-        m_owner, m_flags, operation, m_baton);
+        m_owner, m_flags, operation, status, m_baton);
     Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
     if (log) {
       lldb::addr_t current_addr =
@@ -63,7 +63,7 @@
 
 bool ThreadPlanShouldStopHere::DefaultShouldStopHereCallback(
     ThreadPlan *current_plan, Flags &flags, FrameComparison operation,
-    void *baton) {
+    Status &status, void *baton) {
   bool should_stop_here = true;
   StackFrame *frame = current_plan->GetThread().GetStackFrameAtIndex(0).get();
   if (!frame)
@@ -100,7 +100,7 @@
 
 ThreadPlanSP ThreadPlanShouldStopHere::DefaultStepFromHereCallback(
     ThreadPlan *current_plan, Flags &flags, FrameComparison operation,
-    void *baton) {
+    Status &status, void *baton) {
   const bool stop_others = false;
   const size_t frame_index = 0;
   ThreadPlanSP return_plan_sp;
@@ -137,33 +137,34 @@
                     "Queueing StepInRange plan to step through line 0 code.");
 
       return_plan_sp = current_plan->GetThread().QueueThreadPlanForStepInRange(
-          false, range, sc, NULL, eOnlyDuringStepping, eLazyBoolCalculate,
-          eLazyBoolNo);
+          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,
+            status, false, nullptr, true, stop_others, eVoteNo, eVoteNoOpinion,
             frame_index, true);
   return return_plan_sp;
 }
 
 ThreadPlanSP ThreadPlanShouldStopHere::QueueStepOutFromHerePlan(
-    lldb_private::Flags &flags, lldb::FrameComparison operation) {
+    lldb_private::Flags &flags, lldb::FrameComparison operation,
+    Status &status) {
   ThreadPlanSP return_plan_sp;
   if (m_callbacks.step_from_here_callback) {
-    return_plan_sp =
-        m_callbacks.step_from_here_callback(m_owner, flags, operation, m_baton);
+    return_plan_sp = m_callbacks.step_from_here_callback(
+        m_owner, flags, operation, status, m_baton);
   }
   return return_plan_sp;
 }
 
 lldb::ThreadPlanSP ThreadPlanShouldStopHere::CheckShouldStopHereAndQueueStepOut(
-    lldb::FrameComparison operation) {
-  if (!InvokeShouldStopHereCallback(operation))
-    return QueueStepOutFromHerePlan(m_flags, operation);
+    lldb::FrameComparison operation, Status &status) {
+  if (!InvokeShouldStopHereCallback(operation, status))
+    return QueueStepOutFromHerePlan(m_flags, operation, status);
   else
     return ThreadPlanSP();
 }
Index: source/Target/ThreadPlanRunToAddress.cpp
===================================================================
--- source/Target/ThreadPlanRunToAddress.cpp
+++ source/Target/ThreadPlanRunToAddress.cpp
@@ -73,6 +73,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 +87,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 +136,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
@@ -35,7 +35,7 @@
 ThreadPlanPython::ThreadPlanPython(Thread &thread, const char *class_name)
     : ThreadPlan(ThreadPlan::eKindPython, "Python based Thread Plan", thread,
                  eVoteNoOpinion, eVoteNoOpinion),
-      m_class_name(class_name) {
+      m_class_name(class_name), m_did_push(false) {
   SetIsMasterPlan(true);
   SetOkayToDiscard(true);
   SetPrivate(false);
@@ -47,20 +47,22 @@
 }
 
 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)
+  if (!m_did_push)
     return true;
-  else
+
+  if (!m_implementation_sp) {
+    if (error)
+      error->Printf("Python thread plan does not have an implementation");
     return false;
+  }
+
+  return true;
 }
 
 void ThreadPlanPython::DidPush() {
   // We set up the script side in DidPush, so that it can push other plans in
   // the constructor, and doesn't have to care about the details of DidPush.
-
+  m_did_push = true;
   if (!m_class_name.empty()) {
     ScriptInterpreter *script_interp = m_thread.GetProcess()
                                            ->GetTarget()
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/ThreadPlan.cpp
===================================================================
--- source/Target/ThreadPlan.cpp
+++ source/Target/ThreadPlan.cpp
@@ -29,6 +29,7 @@
 ThreadPlan::ThreadPlan(ThreadPlanKind kind, const char *name, Thread &thread,
                        Vote stop_vote, Vote run_vote)
     : m_thread(thread), m_stop_vote(stop_vote), m_run_vote(run_vote),
+      m_takes_iteration_count(false), m_could_not_resolve_hw_bp(false),
       m_kind(kind), m_name(name), m_plan_complete_mutex(),
       m_cached_plan_explains_stop(eLazyBoolCalculate), m_plan_complete(false),
       m_plan_private(false), m_okay_to_discard(true), m_is_master_plan(false),
Index: source/Target/Thread.cpp
===================================================================
--- source/Target/Thread.cpp
+++ source/Target/Thread.cpp
@@ -266,6 +266,7 @@
                 static_cast<void *>(this), GetID());
 
   CheckInWithManager();
+
   QueueFundamentalPlan(true);
 }
 
@@ -399,13 +400,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 +1179,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) {
@@ -1346,41 +1370,43 @@
   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 +1421,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 +1465,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 +2129,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 +2163,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 +2191,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,14 +720,19 @@
                 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_sp->SetIsMasterPlan(true);
-                new_plan_sp->SetOkayToDiscard(false);
-                new_plan_sp->SetPrivate(true);
+                        new_plan_status,
+                        false, // step-over
+                        false, // abort_other_plans
+                        true   // stop_other_threads
+                        ));
+                if (new_plan_sp && new_plan_status.Success()) {
+                  new_plan_sp->SetIsMasterPlan(true);
+                  new_plan_sp->SetOkayToDiscard(false);
+                  new_plan_sp->SetPrivate(true);
+                }
                 process_sp->GetThreadList().SetSelectedThreadByID(
                     thread_sp->GetID());
                 process_sp->ResumeSynchronous(nullptr);
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,13 +161,15 @@
 
       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);
-      m_run_to_sp->SetPrivate(true);
+          status, abort_other_plans, &sc, first_insn, m_stop_others,
+          eVoteNoOpinion, eVoteNoOpinion, frame_idx);
+      if (m_run_to_sp && status.Success())
+        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,7 +799,7 @@
         result.SetStatus(eReturnStatusSuccessContinuingNoResult);
       }
     } else {
-      result.AppendError("Couldn't find thread plan to implement step type.");
+      result.SetError(new_plan_status);
       result.SetStatus(eReturnStatusFailed);
     }
     return result.Succeeded();
@@ -1194,6 +1195,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 +1275,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
@@ -143,6 +143,12 @@
 SBThreadPlan
 SBThreadPlan::QueueThreadPlanForStepOverRange(SBAddress &sb_start_address,
                                               lldb::addr_t size) {
+  SBError error;
+  return QueueThreadPlanForStepOverRange(sb_start_address, size, error);
+}
+
+SBThreadPlan SBThreadPlan::QueueThreadPlanForStepOverRange(
+    SBAddress &sb_start_address, lldb::addr_t size, SBError &error) {
   if (m_opaque_sp) {
     Address *start_address = sb_start_address.get();
     if (!start_address) {
@@ -152,17 +158,31 @@
     AddressRange range(*start_address, size);
     SymbolContext sc;
     start_address->CalculateSymbolContext(&sc);
-    return SBThreadPlan(
-        m_opaque_sp->GetThread().QueueThreadPlanForStepOverRange(
-            false, range, sc, eAllThreads));
+    Status plan_status;
+
+    SBThreadPlan plan =
+        SBThreadPlan(m_opaque_sp->GetThread().QueueThreadPlanForStepOverRange(
+            plan_status, false, range, sc, eAllThreads));
+
+    if (plan_status.Fail())
+      error.SetErrorString(plan_status.AsCString());
+
+    return plan;
   } else {
     return SBThreadPlan();
   }
 }
 
 SBThreadPlan
 SBThreadPlan::QueueThreadPlanForStepInRange(SBAddress &sb_start_address,
                                             lldb::addr_t size) {
+  SBError error;
+  return QueueThreadPlanForStepInRange(sb_start_address, size, error);
+}
+
+SBThreadPlan
+SBThreadPlan::QueueThreadPlanForStepInRange(SBAddress &sb_start_address,
+                                            lldb::addr_t size, SBError &error) {
   if (m_opaque_sp) {
     Address *start_address = sb_start_address.get();
     if (!start_address) {
@@ -172,47 +192,97 @@
     AddressRange range(*start_address, size);
     SymbolContext sc;
     start_address->CalculateSymbolContext(&sc);
-    return SBThreadPlan(m_opaque_sp->GetThread().QueueThreadPlanForStepInRange(
-        false, range, sc, NULL, eAllThreads));
+
+    Status plan_status;
+    SBThreadPlan plan =
+        SBThreadPlan(m_opaque_sp->GetThread().QueueThreadPlanForStepInRange(
+            plan_status, false, range, sc, NULL, eAllThreads));
+
+    if (plan_status.Fail())
+      error.SetErrorString(plan_status.AsCString());
+
+    return plan;
   } else {
     return SBThreadPlan();
   }
 }
 
 SBThreadPlan
 SBThreadPlan::QueueThreadPlanForStepOut(uint32_t frame_idx_to_step_to,
                                         bool first_insn) {
+  SBError error;
+  return QueueThreadPlanForStepOut(frame_idx_to_step_to, first_insn, error);
+}
+
+SBThreadPlan
+SBThreadPlan::QueueThreadPlanForStepOut(uint32_t frame_idx_to_step_to,
+                                        bool first_insn, SBError &error) {
   if (m_opaque_sp) {
     SymbolContext sc;
     sc = m_opaque_sp->GetThread().GetStackFrameAtIndex(0)->GetSymbolContext(
         lldb::eSymbolContextEverything);
-    return SBThreadPlan(m_opaque_sp->GetThread().QueueThreadPlanForStepOut(
-        false, &sc, first_insn, false, eVoteYes, eVoteNoOpinion,
-        frame_idx_to_step_to));
+
+    Status plan_status;
+    SBThreadPlan plan =
+        SBThreadPlan(m_opaque_sp->GetThread().QueueThreadPlanForStepOut(
+            plan_status, false, &sc, first_insn, false, eVoteYes,
+            eVoteNoOpinion, frame_idx_to_step_to));
+
+    if (plan_status.Fail())
+      error.SetErrorString(plan_status.AsCString());
+
+    return plan;
   } else {
     return SBThreadPlan();
   }
 }
 
 SBThreadPlan
 SBThreadPlan::QueueThreadPlanForRunToAddress(SBAddress sb_address) {
+  SBError error;
+  return QueueThreadPlanForRunToAddress(sb_address, error);
+}
+
+SBThreadPlan SBThreadPlan::QueueThreadPlanForRunToAddress(SBAddress sb_address,
+                                                          SBError &error) {
   if (m_opaque_sp) {
     Address *address = sb_address.get();
     if (!address)
       return SBThreadPlan();
 
-    return SBThreadPlan(m_opaque_sp->GetThread().QueueThreadPlanForRunToAddress(
-        false, *address, false));
+    Status plan_status;
+    SBThreadPlan plan =
+        SBThreadPlan(m_opaque_sp->GetThread().QueueThreadPlanForRunToAddress(
+            plan_status, false, *address, false));
+
+    if (plan_status.Fail())
+      error.SetErrorString(plan_status.AsCString());
+
+    return plan;
   } else {
     return SBThreadPlan();
   }
 }
 
 SBThreadPlan
 SBThreadPlan::QueueThreadPlanForStepScripted(const char *script_class_name) {
+  SBError error;
+  return QueueThreadPlanForStepScripted(script_class_name, error);
+}
+
+SBThreadPlan
+SBThreadPlan::QueueThreadPlanForStepScripted(const char *script_class_name,
+                                             SBError &error) {
   if (m_opaque_sp) {
-    return SBThreadPlan(m_opaque_sp->GetThread().QueueThreadPlanForStepScripted(
-        false, script_class_name, false));
+    Status plan_status;
+    SBThreadPlan plan =
+        SBThreadPlan(m_opaque_sp->GetThread().QueueThreadPlanForStepScripted(
+            plan_status, false, script_class_name, false));
+
+    if (plan_status.Fail())
+      error.SetErrorString(plan_status.AsCString());
+
+    return plan;
   } 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,14 +725,18 @@
     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());
+
+  if (new_plan_status.Success())
+    error = ResumeNewPlan(exe_ctx, new_plan_sp.get());
+  else
+    error.SetErrorString(new_plan_status.AsCString());
 }
 
 void SBThread::StepOut() {
@@ -759,11 +765,15 @@
   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());
+  if (new_plan_status.Success())
+    error = ResumeNewPlan(exe_ctx, new_plan_sp.get());
+  else
+    error.SetErrorString(new_plan_status.AsCString());
 }
 
 void SBThread::StepOutOfFrame(SBFrame &sb_frame) {
@@ -812,11 +822,15 @@
     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());
+  if (new_plan_status.Success())
+    error = ResumeNewPlan(exe_ctx, new_plan_sp.get());
+  else
+    error.SetErrorString(new_plan_status.AsCString());
 }
 
 void SBThread::StepInstruction(bool step_over) {
@@ -840,10 +854,14 @@
   }
 
   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());
+  if (new_plan_status.Success())
+    error = ResumeNewPlan(exe_ctx, new_plan_sp.get());
+  else
+    error.SetErrorString(new_plan_status.AsCString());
 }
 
 void SBThread::RunToAddress(lldb::addr_t addr) {
@@ -873,10 +891,14 @@
 
   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());
+  if (new_plan_status.Success())
+    error = ResumeNewPlan(exe_ctx, new_plan_sp.get());
+  else
+    error.SetErrorString(new_plan_status.AsCString());
 }
 
 SBError SBThread::StepOverUntil(lldb::SBFrame &sb_frame,
@@ -988,12 +1010,16 @@
       } 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()));
 
-      sb_error = ResumeNewPlan(exe_ctx, new_plan_sp.get());
+      if (new_plan_status.Success())
+        sb_error = ResumeNewPlan(exe_ctx, new_plan_sp.get());
+      else
+        sb_error.SetErrorString(new_plan_status.AsCString());
     }
   } else {
     sb_error.SetErrorString("this SBThread object is invalid");
@@ -1008,7 +1034,7 @@
 SBError SBThread::StepUsingScriptedThreadPlan(const char *script_class_name,
                                               bool resume_immediately) {
   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
-  SBError sb_error;
+  SBError error;
 
   std::unique_lock<std::recursive_mutex> lock;
   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
@@ -1019,37 +1045,29 @@
   }
 
   if (!exe_ctx.HasThreadScope()) {
-    sb_error.SetErrorString("this SBThread object is invalid");
-    return sb_error;
+    error.SetErrorString("this SBThread object is invalid");
+    return error;
   }
 
   Thread *thread = exe_ctx.GetThreadPtr();
-  ThreadPlanSP thread_plan_sp =
-      thread->QueueThreadPlanForStepScripted(false, script_class_name, false);
+  Status new_plan_status;
+  ThreadPlanSP new_plan_sp = thread->QueueThreadPlanForStepScripted(
+      new_plan_status, false, script_class_name, false);
 
-  if (!thread_plan_sp) {
-    sb_error.SetErrorStringWithFormat(
-        "Error queueing thread plan for class: %s", script_class_name);
-    return sb_error;
+  if (new_plan_status.Fail()) {
+    error.SetErrorString(new_plan_status.AsCString());
+    return error;
   }
 
-  if (!resume_immediately) {
-    return sb_error;
-  }
+  if (!resume_immediately)
+    return error;
 
-  if (thread_plan_sp)
-    sb_error = ResumeNewPlan(exe_ctx, thread_plan_sp.get());
-  else {
-    sb_error.SetErrorStringWithFormat(
-        "Error resuming thread plan for class: %s.", script_class_name);
-    if (log)
-      log->Printf("SBThread(%p)::StepUsingScriptedThreadPlan: Error queuing "
-                  "thread plan for class: %s",
-                  static_cast<void *>(exe_ctx.GetThreadPtr()),
-                  script_class_name);
-  }
+  if (new_plan_status.Success())
+    error = ResumeNewPlan(exe_ctx, new_plan_sp.get());
+  else
+    error.SetErrorString(new_plan_status.AsCString());
 
-  return sb_error;
+  return error;
 }
 
 SBError SBThread::JumpToLine(lldb::SBFileSpec &file_spec, uint32_t line) {
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,102 @@
+"""
+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):
+    NO_DEBUG_INFO_TESTCASE = True
+    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()
+
+        _, _, thread, _ = lldbutil.run_to_line_breakpoint(
+            self, lldb.SBFileSpec("main.c"), 1)
+
+        self.runCmd("settings set target.require-hardware-breakpoint true")
+
+        # Ensure we fail in the interpreter.
+        self.expect("thread step-in")
+        self.expect("thread step-in", error=True)
+
+        # Ensure we fail when stepping through the API.
+        error = lldb.SBError()
+        thread.StepInto('', 4, error)
+        self.assertTrue(error.Fail())
+        self.assertTrue("Could not create hardware breakpoint for thread plan"
+                        in error.GetCString())
+
+    def test_step_out(self):
+        """Test stepping out when hardware breakpoints are required."""
+        self.build()
+
+        _, _, thread, _ = lldbutil.run_to_line_breakpoint(
+            self, lldb.SBFileSpec("main.c"), 1)
+
+        self.runCmd("settings set target.require-hardware-breakpoint true")
+
+        # Ensure this fails in the command interpreter.
+        self.expect("thread step-out", error=True)
+
+        # Ensure we fail when stepping through the API.
+        error = lldb.SBError()
+        thread.StepOut(error)
+        self.assertTrue(error.Fail())
+        self.assertTrue("Could not create hardware breakpoint for thread plan"
+                        in error.GetCString())
+
+    def test_step_over(self):
+        """Test stepping over when hardware breakpoints are required."""
+        self.build()
+
+        _, _, thread, _ = lldbutil.run_to_line_breakpoint(
+            self, lldb.SBFileSpec("main.c"), 7)
+
+        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=[
+                'step over failed',
+                'Could not create hardware breakpoint for thread plan'
+            ])
+
+    def test_step_until(self):
+        """Test stepping until when hardware breakpoints are required."""
+        self.build()
+
+        _, _, thread, _ = lldbutil.run_to_line_breakpoint(
+            self, lldb.SBFileSpec("main.c"), 7)
+
+        self.runCmd("settings set target.require-hardware-breakpoint true")
+
+        self.expect("thread until 5", error=True)
+
+        # Ensure we fail when stepping through the API.
+        error = thread.StepOverUntil(lldb.SBFrame(), lldb.SBFileSpec(), 5)
+        self.assertTrue(error.Fail())
+        self.assertTrue("Could not create hardware breakpoint for thread plan"
+                        in error.GetCString())
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/lldb-private-interfaces.h
===================================================================
--- include/lldb/lldb-private-interfaces.h
+++ include/lldb/lldb-private-interfaces.h
@@ -84,10 +84,10 @@
                                            OptionValue *option_value);
 typedef bool (*ThreadPlanShouldStopHereCallback)(
     ThreadPlan *current_plan, Flags &flags, lldb::FrameComparison operation,
-    void *baton);
+    Status &status, void *baton);
 typedef lldb::ThreadPlanSP (*ThreadPlanStepFromHereCallback)(
     ThreadPlan *current_plan, Flags &flags, lldb::FrameComparison operation,
-    void *baton);
+    Status &status, void *baton);
 typedef UnwindAssembly *(*UnwindAssemblyCreateInstance)(const ArchSpec &arch);
 typedef lldb::MemoryHistorySP (*MemoryHistoryCreateInstance)(
     const lldb::ProcessSP &process_sp);
Index: include/lldb/Target/ThreadPlanStepUntil.h
===================================================================
--- include/lldb/Target/ThreadPlanStepUntil.h
+++ include/lldb/Target/ThreadPlanStepUntil.h
@@ -58,8 +58,8 @@
   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();
 
Index: include/lldb/Target/ThreadPlanStepOut.h
===================================================================
--- include/lldb/Target/ThreadPlanStepOut.h
+++ include/lldb/Target/ThreadPlanStepOut.h
@@ -79,9 +79,9 @@
   bool m_calculate_return_value;
 
   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
@@ -58,7 +58,7 @@
   static bool DefaultShouldStopHereCallback(ThreadPlan *current_plan,
                                             Flags &flags,
                                             lldb::FrameComparison operation,
-                                            void *baton);
+                                            Status &status, void *baton);
 
   bool DoWillResume(lldb::StateType resume_state, bool current_plan) override;
 
@@ -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/ThreadPlanShouldStopHere.h
===================================================================
--- include/lldb/Target/ThreadPlanShouldStopHere.h
+++ include/lldb/Target/ThreadPlanShouldStopHere.h
@@ -101,10 +101,12 @@
 
   void ClearShouldStopHereCallbacks() { m_callbacks.Clear(); }
 
-  bool InvokeShouldStopHereCallback(lldb::FrameComparison operation);
+  bool InvokeShouldStopHereCallback(lldb::FrameComparison operation,
+                                    Status &status);
 
   lldb::ThreadPlanSP
-  CheckShouldStopHereAndQueueStepOut(lldb::FrameComparison operation);
+  CheckShouldStopHereAndQueueStepOut(lldb::FrameComparison operation,
+                                     Status &status);
 
   lldb_private::Flags &GetFlags() { return m_flags; }
 
@@ -114,14 +116,16 @@
   static bool DefaultShouldStopHereCallback(ThreadPlan *current_plan,
                                             Flags &flags,
                                             lldb::FrameComparison operation,
-                                            void *baton);
+                                            Status &status, void *baton);
 
   static lldb::ThreadPlanSP
   DefaultStepFromHereCallback(ThreadPlan *current_plan, Flags &flags,
-                              lldb::FrameComparison operation, void *baton);
+                              lldb::FrameComparison operation, Status &status,
+                              void *baton);
 
   virtual lldb::ThreadPlanSP
-  QueueStepOutFromHerePlan(Flags &flags, lldb::FrameComparison operation);
+  QueueStepOutFromHerePlan(Flags &flags, lldb::FrameComparison operation,
+                           Status &status);
 
   // Implement this, and call it in the plan's constructor to set the default
   // flags.
Index: include/lldb/Target/ThreadPlanPython.h
===================================================================
--- include/lldb/Target/ThreadPlanPython.h
+++ include/lldb/Target/ThreadPlanPython.h
@@ -63,6 +63,7 @@
 private:
   std::string m_class_name;
   StructuredData::ObjectSP m_implementation_sp;
+  bool m_did_push;
 
   DISALLOW_COPY_AND_ASSIGN(ThreadPlanPython);
 };
Index: include/lldb/Target/ThreadPlan.h
===================================================================
--- include/lldb/Target/ThreadPlan.h
+++ include/lldb/Target/ThreadPlan.h
@@ -600,10 +600,12 @@
 
   bool IsUsuallyUnexplainedStopReason(lldb::StopReason);
 
+  Status m_status;
   Thread &m_thread;
   Vote m_stop_vote;
   Vote m_run_vote;
-  bool m_takes_iteration_count = false;
+  bool m_takes_iteration_count;
+  bool m_could_not_resolve_hw_bp;
   int32_t m_iteration_count = 1;
 
 private:
@@ -655,6 +657,8 @@
 
   bool OkayToDiscard() override { return false; }
 
+  const Status &GetStatus() { return m_status; }
+
 protected:
   bool DoPlanExplainsStop(Event *event_ptr) override;
 
Index: include/lldb/Target/Thread.h
===================================================================
--- include/lldb/Target/Thread.h
+++ include/lldb/Target/Thread.h
@@ -646,6 +646,9 @@
   /// Queues the plan used to step one instruction from the current PC of \a
   /// thread.
   ///
+  /// @param[out] status
+  ///     A status with an error if queuing failed.
+  ///
   /// @param[in] step_over
   ///    \b true if we step over calls to functions, false if we step in.
   ///
@@ -661,13 +664,18 @@
   ///     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
   /// function calls.
   ///
+  /// @param[out] status
+  ///     A status with an error if queuing failed.
+  ///
   /// @param[in] abort_other_plans
   ///    \b true if we discard the currently queued plans and replace them with
   ///    this one.
@@ -702,22 +710,25 @@
   ///     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);
 
   //------------------------------------------------------------------
   /// Queues the plan used to step through an address range, stepping into
   /// functions.
   ///
+  /// @param[out] status
+  ///     A status with an error if queuing failed.
+  ///
   /// @param[in] abort_other_plans
   ///    \b true if we discard the currently queued plans and replace them with
   ///    this one.
@@ -761,7 +772,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 +782,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,
@@ -781,6 +792,9 @@
   /// Queue the plan used to step out of the function at the current PC of
   /// \a thread.
   ///
+  /// @param[out] status
+  ///     A status with an error if queuing failed.
+  ///
   /// @param[in] abort_other_plans
   ///    \b true if we discard the currently queued plans and replace them with
   ///    this one.
@@ -815,8 +829,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,
@@ -829,6 +843,9 @@
   /// be used by other thread plans when they need to retain control of the step
   /// out.
   ///
+  /// @param[out] status
+  ///     A status with an error if queuing failed.
+  ///
   /// @param[in] abort_other_plans
   ///    \b true if we discard the currently queued plans and replace them with
   ///    this one.
@@ -875,16 +892,18 @@
   ///     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);
 
   //------------------------------------------------------------------
   /// Gets the plan used to step through the code that steps from a function
   /// call site at the current PC into the actual function call.
   ///
+  /// @param[out] status
+  ///     A status with an error if queuing failed.
   ///
   /// @param[in] return_stack_id
   ///    The stack id that we will return to (by setting backstop breakpoints on
@@ -904,15 +923,18 @@
   ///     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);
 
   //------------------------------------------------------------------
   /// Gets the plan used to continue from the current PC.
   /// This is a simple plan, mostly useful as a backstop when you are continuing
   /// for some particular purpose.
   ///
+  /// @param[out] status
+  ///     A status with an error if queuing failed.
+  ///
   /// @param[in] abort_other_plans
   ///    \b true if we discard the currently queued plans and replace them with
   ///    this one.
@@ -929,16 +951,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 +1063,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/SBThreadPlan.h
===================================================================
--- include/lldb/API/SBThreadPlan.h
+++ include/lldb/API/SBThreadPlan.h
@@ -79,16 +79,28 @@
   // plans...
   SBThreadPlan QueueThreadPlanForStepOverRange(SBAddress &start_address,
                                                lldb::addr_t range_size);
+  SBThreadPlan QueueThreadPlanForStepOverRange(SBAddress &start_address,
+                                               lldb::addr_t range_size,
+                                               SBError &error);
 
   SBThreadPlan QueueThreadPlanForStepInRange(SBAddress &start_address,
                                              lldb::addr_t range_size);
+  SBThreadPlan QueueThreadPlanForStepInRange(SBAddress &start_address,
+                                             lldb::addr_t range_size,
+                                             SBError &error);
 
   SBThreadPlan QueueThreadPlanForStepOut(uint32_t frame_idx_to_step_to,
                                          bool first_insn = false);
+  SBThreadPlan QueueThreadPlanForStepOut(uint32_t frame_idx_to_step_to,
+                                         bool first_insn, SBError &error);
 
   SBThreadPlan QueueThreadPlanForRunToAddress(SBAddress address);
+  SBThreadPlan QueueThreadPlanForRunToAddress(SBAddress address,
+                                              SBError &error);
 
   SBThreadPlan QueueThreadPlanForStepScripted(const char *script_class_name);
+  SBThreadPlan QueueThreadPlanForStepScripted(const char *script_class_name,
+                                              SBError &error);
 
 #ifndef SWIG
   lldb_private::ThreadPlan *get();
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
lldb-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to