Add setting to require hardware breakpoints.

When debugging read-only memory we cannot use software breakpoint. We
already have support for hardware breakpoints and users can specify them
with `-H`. However, there's no option to force LLDB to use hardware
breakpoints internally, for example while stepping.

This patch adds a setting target.require-hardware-breakpoint that forces
LLDB to always use hardware breakpoints. Because hardware breakpoints
are a limited resource and can fail to resolve, this patch also extends
error handling in thread plans, where breakpoints are used for stepping.

Differential revision: https://reviews.llvm.org/D54221

llvm-svn: 346920
diff --git a/lldb/source/API/SBBreakpoint.cpp b/lldb/source/API/SBBreakpoint.cpp
index 11afa99..b672007 100644
--- a/lldb/source/API/SBBreakpoint.cpp
+++ b/lldb/source/API/SBBreakpoint.cpp
@@ -688,6 +688,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.
diff --git a/lldb/source/API/SBThread.cpp b/lldb/source/API/SBThread.cpp
index b7af459..a38b9f6 100644
--- a/lldb/source/API/SBThread.cpp
+++ b/lldb/source/API/SBThread.cpp
@@ -657,6 +657,7 @@
   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()) {
@@ -664,10 +665,10 @@
       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, avoid_no_debug);
     } else {
       new_plan_sp = thread->QueueThreadPlanForStepSingleInstruction(
-          true, abort_other_plans, stop_other_threads);
+          true, abort_other_plans, stop_other_threads, new_plan_status);
     }
   }
   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));
@@ -724,13 +726,17 @@
         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, 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);
+        false, abort_other_plans, stop_other_threads, new_plan_status);
   }
-  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));
+      eVoteNoOpinion, 0, new_plan_status, 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()));
+      eVoteNoOpinion, frame_sp->GetFrameIndex(), new_plan_status));
 
-  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(
+      step_over, true, true, new_plan_status));
 
-  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));
+      abort_other_plans, target_addr, stop_other_threads, new_plan_status));
 
-  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],
           step_over_until_addrs.size(), stop_other_threads,
-          frame_sp->GetFrameIndex()));
+          frame_sp->GetFrameIndex(), new_plan_status));
 
-      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(
+      false, script_class_name, false, new_plan_status);
 
-  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) {
diff --git a/lldb/source/API/SBThreadPlan.cpp b/lldb/source/API/SBThreadPlan.cpp
index c15c39a..fc54f5b 100644
--- a/lldb/source/API/SBThreadPlan.cpp
+++ b/lldb/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,9 +158,16 @@
     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(
+            false, range, sc, eAllThreads, plan_status));
+
+    if (plan_status.Fail())
+      error.SetErrorString(plan_status.AsCString());
+
+    return plan;
   } else {
     return SBThreadPlan();
   }
@@ -163,6 +176,13 @@
 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,8 +192,16 @@
     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(
+            false, range, sc, NULL, eAllThreads, plan_status));
+
+    if (plan_status.Fail())
+      error.SetErrorString(plan_status.AsCString());
+
+    return plan;
   } else {
     return SBThreadPlan();
   }
@@ -182,13 +210,28 @@
 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(
+            false, &sc, first_insn, false, eVoteYes, eVoteNoOpinion,
+            frame_idx_to_step_to, plan_status));
+
+    if (plan_status.Fail())
+      error.SetErrorString(plan_status.AsCString());
+
+    return plan;
   } else {
     return SBThreadPlan();
   }
@@ -196,13 +239,26 @@
 
 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(
+            false, *address, false, plan_status));
+
+    if (plan_status.Fail())
+      error.SetErrorString(plan_status.AsCString());
+
+    return plan;
   } else {
     return SBThreadPlan();
   }
@@ -210,9 +266,23 @@
 
 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(
+            false, script_class_name, false, plan_status));
+
+    if (plan_status.Fail())
+      error.SetErrorString(plan_status.AsCString());
+
+    return plan;
   } else {
     return SBThreadPlan();
   }