Skip to content

Commit

Permalink
Add setting to require hardware breakpoints.
Browse files Browse the repository at this point in the history
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
  • Loading branch information
JDevlieghere committed Nov 15, 2018
1 parent df14b94 commit e103ae9
Show file tree
Hide file tree
Showing 41 changed files with 666 additions and 234 deletions.
2 changes: 2 additions & 0 deletions lldb/include/lldb/API/SBBreakpoint.h
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,8 @@ class LLDB_API SBBreakpoint {
static uint32_t
GetNumBreakpointLocationsFromEvent(const lldb::SBEvent &event_sp);

bool IsHardware() const;

// Can only be called from a ScriptedBreakpointResolver...
SBError
AddLocation(SBAddress &address);
Expand Down
12 changes: 12 additions & 0 deletions lldb/include/lldb/API/SBThreadPlan.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,16 +79,28 @@ class LLDB_API SBThreadPlan {
// 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();
Expand Down
8 changes: 8 additions & 0 deletions lldb/include/lldb/Breakpoint/Breakpoint.h
Original file line number Diff line number Diff line change
Expand Up @@ -498,6 +498,14 @@ class Breakpoint : public std::enable_shared_from_this<Breakpoint>,
//------------------------------------------------------------------
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.
///
Expand Down
4 changes: 4 additions & 0 deletions lldb/include/lldb/Target/Target.h
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,10 @@ class TargetProperties : public Properties {

bool GetUseModernTypeLookup() const;

void SetRequireHardwareBreakpoints(bool b);

bool GetRequireHardwareBreakpoints() const;

private:
//------------------------------------------------------------------
// Callbacks for m_launch_info.
Expand Down
71 changes: 46 additions & 25 deletions lldb/include/lldb/Target/Thread.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ class ThreadProperties : public Properties {
bool GetStepInAvoidsNoDebug() const;

bool GetStepOutAvoidsNoDebug() const;

uint64_t GetMaxBacktraceDepth() const;
};

Expand Down Expand Up @@ -494,9 +494,9 @@ class Thread : public std::enable_shared_from_this<Thread>,

// If stop_format is true, this will be the form used when we print stop
// info. If false, it will be the form we use for thread list and co.
void DumpUsingSettingsFormat(Stream &strm, uint32_t frame_idx,
void DumpUsingSettingsFormat(Stream &strm, uint32_t frame_idx,
bool stop_format);

bool GetDescription(Stream &s, lldb::DescriptionLevel level,
bool print_json_thread, bool print_json_stopinfo);

Expand Down Expand Up @@ -653,12 +653,16 @@ class Thread : public std::enable_shared_from_this<Thread>,
/// @param[in] stop_other_threads
/// \b true if we will stop other threads while we single step this one.
///
/// @param[out] status
/// A status with an error if queuing failed.
///
/// @return
/// 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);
bool step_over, bool abort_other_plans, bool stop_other_threads,
Status &status);

//------------------------------------------------------------------
/// Queues the plan used to step through an address range, stepping over
Expand Down Expand Up @@ -688,6 +692,9 @@ class Thread : public std::enable_shared_from_this<Thread>,
/// @param[in] stop_other_threads
/// \b true if we will stop other threads while we single step this one.
///
/// @param[out] status
/// A status with an error if queuing failed.
///
/// @param[in] step_out_avoids_code_without_debug_info
/// If eLazyBoolYes, if the step over steps out it will continue to step
/// out till it comes to a frame with debug info.
Expand All @@ -700,6 +707,7 @@ class Thread : public std::enable_shared_from_this<Thread>,
virtual lldb::ThreadPlanSP QueueThreadPlanForStepOverRange(
bool abort_other_plans, const AddressRange &range,
const SymbolContext &addr_context, lldb::RunMode stop_other_threads,
Status &status,
LazyBool step_out_avoids_code_without_debug_info = eLazyBoolCalculate);

// Helper function that takes a LineEntry to step, insted of an AddressRange.
Expand All @@ -708,6 +716,7 @@ class Thread : public std::enable_shared_from_this<Thread>,
virtual lldb::ThreadPlanSP QueueThreadPlanForStepOverRange(
bool abort_other_plans, const LineEntry &line_entry,
const SymbolContext &addr_context, lldb::RunMode stop_other_threads,
Status &status,
LazyBool step_out_avoids_code_without_debug_info = eLazyBoolCalculate);

//------------------------------------------------------------------
Expand Down Expand Up @@ -742,6 +751,9 @@ class Thread : public std::enable_shared_from_this<Thread>,
/// @param[in] stop_other_threads
/// \b true if we will stop other threads while we single step this one.
///
/// @param[out] status
/// A status with an error if queuing failed.
///
/// @param[in] step_in_avoids_code_without_debug_info
/// If eLazyBoolYes we will step out if we step into code with no debug
/// info.
Expand All @@ -759,7 +771,7 @@ class Thread : public std::enable_shared_from_this<Thread>,
virtual lldb::ThreadPlanSP QueueThreadPlanForStepInRange(
bool abort_other_plans, const AddressRange &range,
const SymbolContext &addr_context, const char *step_in_target,
lldb::RunMode stop_other_threads,
lldb::RunMode stop_other_threads, Status &status,
LazyBool step_in_avoids_code_without_debug_info = eLazyBoolCalculate,
LazyBool step_out_avoids_code_without_debug_info = eLazyBoolCalculate);

Expand All @@ -769,7 +781,7 @@ class Thread : public std::enable_shared_from_this<Thread>,
virtual lldb::ThreadPlanSP QueueThreadPlanForStepInRange(
bool abort_other_plans, const LineEntry &line_entry,
const SymbolContext &addr_context, const char *step_in_target,
lldb::RunMode stop_other_threads,
lldb::RunMode stop_other_threads, Status &status,
LazyBool step_in_avoids_code_without_debug_info = eLazyBoolCalculate,
LazyBool step_out_avoids_code_without_debug_info = eLazyBoolCalculate);

Expand Down Expand Up @@ -801,6 +813,9 @@ class Thread : public std::enable_shared_from_this<Thread>,
/// @param[in] run_vote
/// See standard meanings for the stop & run votes in ThreadPlan.h.
///
/// @param[out] status
/// A status with an error if queuing failed.
///
/// @param[in] step_out_avoids_code_without_debug_info
/// If eLazyBoolYes, if the step over steps out it will continue to step
/// out till it comes to a frame with debug info.
Expand All @@ -812,10 +827,8 @@ class Thread : public std::enable_shared_from_this<Thread>,
//------------------------------------------------------------------
virtual lldb::ThreadPlanSP QueueThreadPlanForStepOut(
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 stop_other_threads, Vote stop_vote, Vote run_vote,
uint32_t frame_idx, Status &status,
LazyBool step_out_avoids_code_without_debug_info = eLazyBoolCalculate);

//------------------------------------------------------------------
Expand Down Expand Up @@ -846,9 +859,15 @@ class Thread : public std::enable_shared_from_this<Thread>,
/// \b true if we will stop other threads while we single step this one.
///
/// @param[in] stop_vote
///
/// @param[in] run_vote
/// See standard meanings for the stop & run votes in ThreadPlan.h.
///
/// @param[in] frame_idx
///
/// @param[out] status
/// A status with an error if queuing failed.
///
/// @param[in] continue_to_next_branch
/// Normally this will enqueue a plan that will put a breakpoint on the
/// return address and continue
Expand All @@ -872,16 +891,13 @@ class Thread : public std::enable_shared_from_this<Thread>,
//------------------------------------------------------------------
virtual lldb::ThreadPlanSP QueueThreadPlanForStepOutNoShouldStop(
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);
bool stop_other_threads, Vote stop_vote, Vote run_vote,
uint32_t frame_idx, Status &status, 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[in] return_stack_id
/// The stack id that we will return to (by setting backstop breakpoints on
/// the return
Expand All @@ -895,14 +911,17 @@ class Thread : public std::enable_shared_from_this<Thread>,
/// @param[in] stop_other_threads
/// \b true if we will stop other threads while we single step this one.
///
/// @param[out] status
/// A status with an error if queuing failed.
///
/// @return
/// A shared pointer to the newly queued thread plan, or nullptr if the
/// plan could not be queued.
//------------------------------------------------------------------
virtual lldb::ThreadPlanSP
QueueThreadPlanForStepThrough(StackID &return_stack_id,
bool abort_other_plans,
bool stop_other_threads);
bool abort_other_plans, bool stop_other_threads,
Status &status);

//------------------------------------------------------------------
/// Gets the plan used to continue from the current PC.
Expand All @@ -920,22 +939,24 @@ class Thread : public std::enable_shared_from_this<Thread>,
/// @param[in] stop_other_threads
/// \b true if we will stop other threads while we single step this one.
///
/// @param[out] status
/// A status with an error if queuing failed.
///
/// @return
/// A shared pointer to the newly queued thread plan, or nullptr if the
/// plan could not be queued.
//------------------------------------------------------------------
virtual lldb::ThreadPlanSP
QueueThreadPlanForRunToAddress(bool abort_other_plans, Address &target_addr,
bool stop_other_threads);
bool stop_other_threads, Status &status);

virtual lldb::ThreadPlanSP
QueueThreadPlanForStepUntil(bool abort_other_plans,
lldb::addr_t *address_list, size_t num_addresses,
bool stop_others, uint32_t frame_idx);
virtual lldb::ThreadPlanSP QueueThreadPlanForStepUntil(
bool abort_other_plans, lldb::addr_t *address_list, size_t num_addresses,
bool stop_others, uint32_t frame_idx, Status &status);

virtual lldb::ThreadPlanSP
QueueThreadPlanForStepScripted(bool abort_other_plans, const char *class_name,
bool stop_other_threads);
bool stop_other_threads, Status &status);

//------------------------------------------------------------------
// Thread Plan accessors:
Expand Down Expand Up @@ -1021,7 +1042,7 @@ class Thread : public std::enable_shared_from_this<Thread>,
/// false otherwise.
//------------------------------------------------------------------
bool CompletedPlanOverridesBreakpoint();

//------------------------------------------------------------------
/// Queues a generic thread plan.
///
Expand All @@ -1036,7 +1057,7 @@ class Thread : public std::enable_shared_from_this<Thread>,
/// @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
Expand Down
6 changes: 5 additions & 1 deletion lldb/include/lldb/Target/ThreadPlan.h
Original file line number Diff line number Diff line change
Expand Up @@ -596,10 +596,12 @@ class ThreadPlan : public std::enable_shared_from_this<ThreadPlan>,

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:
Expand Down Expand Up @@ -651,6 +653,8 @@ class ThreadPlanNull : public ThreadPlan {

bool OkayToDiscard() override { return false; }

const Status &GetStatus() { return m_status; }

protected:
bool DoPlanExplainsStop(Event *event_ptr) override;

Expand Down
1 change: 1 addition & 0 deletions lldb/include/lldb/Target/ThreadPlanPython.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ class ThreadPlanPython : public ThreadPlan {
private:
std::string m_class_name;
StructuredData::ObjectSP m_implementation_sp;
bool m_did_push;

DISALLOW_COPY_AND_ASSIGN(ThreadPlanPython);
};
Expand Down
14 changes: 9 additions & 5 deletions lldb/include/lldb/Target/ThreadPlanShouldStopHere.h
Original file line number Diff line number Diff line change
Expand Up @@ -97,10 +97,12 @@ class ThreadPlanShouldStopHere {

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; }

Expand All @@ -110,14 +112,16 @@ class ThreadPlanShouldStopHere {
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.
Expand Down
6 changes: 3 additions & 3 deletions lldb/include/lldb/Target/ThreadPlanStepInRange.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ class ThreadPlanStepInRange : public ThreadPlanStepRange,
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;

Expand All @@ -76,11 +76,11 @@ class ThreadPlanStepInRange : public ThreadPlanStepRange,
friend lldb::ThreadPlanSP Thread::QueueThreadPlanForStepOverRange(
bool abort_other_plans, const AddressRange &range,
const SymbolContext &addr_context, lldb::RunMode stop_others,
LazyBool avoid_code_without_debug_info);
Status &status, LazyBool avoid_code_without_debug_info);
friend lldb::ThreadPlanSP Thread::QueueThreadPlanForStepInRange(
bool abort_other_plans, const AddressRange &range,
const SymbolContext &addr_context, const char *step_in_target,
lldb::RunMode stop_others,
lldb::RunMode stop_others, Status &status,
LazyBool step_in_avoids_code_without_debug_info,
LazyBool step_out_avoids_code_without_debug_info);

Expand Down
3 changes: 2 additions & 1 deletion lldb/include/lldb/Target/ThreadPlanStepInstruction.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@ class ThreadPlanStepInstruction : public ThreadPlan {

private:
friend lldb::ThreadPlanSP Thread::QueueThreadPlanForStepSingleInstruction(
bool step_over, bool abort_other_plans, bool stop_other_threads);
bool step_over, bool abort_other_plans, bool stop_other_threads,
Status &status);

lldb::addr_t m_instruction_addr;
bool m_stop_other_threads;
Expand Down
2 changes: 1 addition & 1 deletion lldb/include/lldb/Target/ThreadPlanStepOut.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ class ThreadPlanStepOut : public ThreadPlan, public ThreadPlanShouldStopHere {
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, 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
Expand Down
Loading

0 comments on commit e103ae9

Please sign in to comment.