aboutsummaryrefslogtreecommitdiff
path: root/lldb/source/Breakpoint/BreakpointLocation.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lldb/source/Breakpoint/BreakpointLocation.cpp')
-rw-r--r--lldb/source/Breakpoint/BreakpointLocation.cpp176
1 files changed, 136 insertions, 40 deletions
diff --git a/lldb/source/Breakpoint/BreakpointLocation.cpp b/lldb/source/Breakpoint/BreakpointLocation.cpp
index 443d4f5..22c98ac 100644
--- a/lldb/source/Breakpoint/BreakpointLocation.cpp
+++ b/lldb/source/Breakpoint/BreakpointLocation.cpp
@@ -8,6 +8,8 @@
#include "lldb/Breakpoint/BreakpointLocation.h"
#include "lldb/Breakpoint/BreakpointID.h"
+#include "lldb/Breakpoint/BreakpointResolver.h"
+#include "lldb/Breakpoint/BreakpointResolverScripted.h"
#include "lldb/Breakpoint/StoppointCallbackContext.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Core/Module.h"
@@ -45,6 +47,13 @@ BreakpointLocation::BreakpointLocation(break_id_t loc_id, Breakpoint &owner,
SetThreadIDInternal(tid);
}
+BreakpointLocation::BreakpointLocation(break_id_t loc_id, Breakpoint &owner)
+ : m_should_resolve_indirect_functions(false), m_is_reexported(false),
+ m_is_indirect(false), m_address(LLDB_INVALID_ADDRESS), m_owner(owner),
+ m_condition_hash(0), m_loc_id(loc_id), m_hit_counter() {
+ SetThreadIDInternal(LLDB_INVALID_THREAD_ID);
+}
+
BreakpointLocation::~BreakpointLocation() {
llvm::consumeError(ClearBreakpointSite());
}
@@ -372,12 +381,43 @@ bool BreakpointLocation::ValidForThisThread(Thread &thread) {
.GetThreadSpecNoCreate());
}
+BreakpointLocationSP
+BreakpointLocation::WasHit(StoppointCallbackContext *context) {
+ // Only the BreakpointResolverScripted provides WasHit.
+ BreakpointResolverSP resolver_sp = GetBreakpoint().GetResolver();
+ BreakpointResolverScripted *scripted =
+ llvm::dyn_cast<BreakpointResolverScripted>(resolver_sp.get());
+ if (!scripted)
+ return shared_from_this();
+
+ StackFrameSP frame_sp = context->exe_ctx_ref.GetFrameSP();
+ if (!frame_sp)
+ return shared_from_this();
+
+ BreakpointLocationSP return_loc_sp =
+ scripted->WasHit(frame_sp, shared_from_this());
+ // If this is a facade location, then we won't have bumped its hit count
+ // while processing the original location hit. Do so here. We don't need
+ // to bump the breakpoint's hit count, however, since hitting the real
+ // location would have already done that.
+ // Also we have to check the enabled state here, since we would never have
+ // gotten here with a real location...
+ if (return_loc_sp && return_loc_sp->IsFacade()) {
+ if (return_loc_sp->IsEnabled())
+ return_loc_sp->m_hit_counter.Increment();
+ else
+ return {};
+ }
+ return return_loc_sp;
+}
+
// RETURNS - true if we should stop at this breakpoint, false if we
// should continue. Note, we don't check the thread spec for the breakpoint
// here, since if the breakpoint is not for this thread, then the event won't
// even get reported, so the check is redundant.
-bool BreakpointLocation::ShouldStop(StoppointCallbackContext *context) {
+bool BreakpointLocation::ShouldStop(StoppointCallbackContext *context,
+ lldb::BreakpointLocationSP &facade_loc_sp) {
bool should_stop = true;
Log *log = GetLog(LLDBLog::Breakpoints);
@@ -386,6 +426,27 @@ bool BreakpointLocation::ShouldStop(StoppointCallbackContext *context) {
if (!IsEnabled())
return false;
+ // Next check WasHit:
+ BreakpointLocationSP loc_hit_sp = WasHit(context);
+
+ if (!loc_hit_sp) {
+ // We bump the hit counts in StopInfoBreakpoint::ShouldStopSynchronous,
+ // before we call into each location's ShouldStop. So we need to undo
+ // that here.
+ UndoBumpHitCount();
+ return false;
+ }
+
+ // If the location hit was not us, it was a facade location, in which case
+ // we should use the facade location's callbacks, etc. Those will all be
+ // run in the asynchronous phase, so for now we just have to record the fact
+ // that we should treat this as a facade hit. This is strictly an out
+ // parameter, so clear it if this isn't a facade hit.
+ if (loc_hit_sp.get() != this)
+ facade_loc_sp = loc_hit_sp;
+ else
+ facade_loc_sp.reset();
+
// We only run synchronous callbacks in ShouldStop:
context->is_synchronous = true;
should_stop = InvokeCallback(context);
@@ -395,6 +456,11 @@ bool BreakpointLocation::ShouldStop(StoppointCallbackContext *context) {
GetDescription(&s, lldb::eDescriptionLevelVerbose);
LLDB_LOGF(log, "Hit breakpoint location: %s, %s.\n", s.GetData(),
should_stop ? "stopping" : "continuing");
+ if (facade_loc_sp) {
+ s.Clear();
+ facade_loc_sp->GetDescription(&s, lldb::eDescriptionLevelVerbose);
+ LLDB_LOGF(log, "Attributing to facade location: %s.\n", s.GetData());
+ }
}
return should_stop;
@@ -417,7 +483,10 @@ void BreakpointLocation::UndoBumpHitCount() {
}
bool BreakpointLocation::IsResolved() const {
- return m_bp_site_sp.get() != nullptr;
+
+ bool has_site = m_bp_site_sp.get() != nullptr;
+ // Facade locations are currently always considered resolved.
+ return has_site || IsFacade();
}
lldb::BreakpointSiteSP BreakpointLocation::GetBreakpointSite() const {
@@ -425,7 +494,9 @@ lldb::BreakpointSiteSP BreakpointLocation::GetBreakpointSite() const {
}
llvm::Error BreakpointLocation::ResolveBreakpointSite() {
- if (m_bp_site_sp)
+ // This might be a facade location, which doesn't have an address.
+ // In that case, don't attempt to make a site.
+ if (m_bp_site_sp || IsFacade())
return llvm::Error::success();
Process *process = m_owner.GetTarget().GetProcessSP().get();
@@ -454,8 +525,12 @@ bool BreakpointLocation::SetBreakpointSite(BreakpointSiteSP &bp_site_sp) {
}
llvm::Error BreakpointLocation::ClearBreakpointSite() {
- if (!m_bp_site_sp)
+ if (!m_bp_site_sp) {
+ // This might be a Facade Location, which don't have sites or addresses
+ if (IsFacade())
+ return llvm::Error::success();
return llvm::createStringError("no breakpoint site to clear");
+ }
// If the process exists, get it to remove the owner, it will remove the
// physical implementation of the breakpoint as well if there are no more
@@ -474,6 +549,17 @@ void BreakpointLocation::GetDescription(Stream *s,
lldb::DescriptionLevel level) {
SymbolContext sc;
+ // If this is a scripted breakpoint, give it a chance to describe its
+ // locations:
+ std::optional<std::string> scripted_opt;
+ BreakpointResolverSP resolver_sp = GetBreakpoint().GetResolver();
+ BreakpointResolverScripted *scripted =
+ llvm::dyn_cast<BreakpointResolverScripted>(resolver_sp.get());
+ if (scripted)
+ scripted_opt = scripted->GetLocationDescription(shared_from_this(), level);
+
+ bool is_scripted_desc = scripted_opt.has_value();
+
// If the description level is "initial" then the breakpoint is printing out
// our initial state, and we should let it decide how it wants to print our
// label.
@@ -491,7 +577,9 @@ void BreakpointLocation::GetDescription(Stream *s,
if (level == lldb::eDescriptionLevelVerbose)
s->IndentMore();
- if (m_address.IsSectionOffset()) {
+ if (is_scripted_desc) {
+ s->PutCString(scripted_opt->c_str());
+ } else if (m_address.IsSectionOffset()) {
m_address.CalculateSymbolContext(&sc);
if (level == lldb::eDescriptionLevelFull ||
@@ -566,43 +654,51 @@ void BreakpointLocation::GetDescription(Stream *s,
s->Indent();
}
- if (m_address.IsSectionOffset() &&
- (level == eDescriptionLevelFull || level == eDescriptionLevelInitial))
- s->Printf(", ");
- s->Printf("address = ");
-
- ExecutionContextScope *exe_scope = nullptr;
- Target *target = &m_owner.GetTarget();
- if (target)
- exe_scope = target->GetProcessSP().get();
- if (exe_scope == nullptr)
- exe_scope = target;
-
- if (level == eDescriptionLevelInitial)
- m_address.Dump(s, exe_scope, Address::DumpStyleLoadAddress,
- Address::DumpStyleFileAddress);
- else
- m_address.Dump(s, exe_scope, Address::DumpStyleLoadAddress,
- Address::DumpStyleModuleWithFileAddress);
-
- if (IsIndirect() && m_bp_site_sp) {
- Address resolved_address;
- resolved_address.SetLoadAddress(m_bp_site_sp->GetLoadAddress(), target);
- Symbol *resolved_symbol = resolved_address.CalculateSymbolContextSymbol();
- if (resolved_symbol) {
- if (level == eDescriptionLevelFull || level == eDescriptionLevelInitial)
- s->Printf(", ");
- else if (level == lldb::eDescriptionLevelVerbose) {
- s->EOL();
- s->Indent();
+ if (!is_scripted_desc) {
+ if (m_address.IsSectionOffset() &&
+ (level == eDescriptionLevelFull || level == eDescriptionLevelInitial))
+ s->Printf(", ");
+ s->Printf("address = ");
+
+ ExecutionContextScope *exe_scope = nullptr;
+ Target *target = &m_owner.GetTarget();
+ if (target)
+ exe_scope = target->GetProcessSP().get();
+ if (exe_scope == nullptr)
+ exe_scope = target;
+
+ if (level == eDescriptionLevelInitial)
+ m_address.Dump(s, exe_scope, Address::DumpStyleLoadAddress,
+ Address::DumpStyleFileAddress);
+ else
+ m_address.Dump(s, exe_scope, Address::DumpStyleLoadAddress,
+ Address::DumpStyleModuleWithFileAddress);
+
+ if (IsIndirect() && m_bp_site_sp) {
+ Address resolved_address;
+ resolved_address.SetLoadAddress(m_bp_site_sp->GetLoadAddress(), target);
+ Symbol *resolved_symbol = resolved_address.CalculateSymbolContextSymbol();
+ if (resolved_symbol) {
+ if (level == eDescriptionLevelFull || level == eDescriptionLevelInitial)
+ s->Printf(", ");
+ else if (level == lldb::eDescriptionLevelVerbose) {
+ s->EOL();
+ s->Indent();
+ }
+ s->Printf("indirect target = %s",
+ resolved_symbol->GetName().GetCString());
}
- s->Printf("indirect target = %s",
- resolved_symbol->GetName().GetCString());
}
}
- bool is_resolved = IsResolved();
- bool is_hardware = is_resolved && m_bp_site_sp->IsHardware();
+ // FIXME: scripted breakpoint are currently always resolved. Does this seem
+ // right? If they don't add any scripted locations, we shouldn't consider them
+ // resolved.
+ bool is_resolved = is_scripted_desc || IsResolved();
+ // A scripted breakpoint might be resolved but not have a site. Be sure to
+ // check for that.
+ bool is_hardware = !is_scripted_desc && IsResolved() && m_bp_site_sp &&
+ m_bp_site_sp->IsHardware();
if (level == lldb::eDescriptionLevelVerbose) {
s->EOL();
@@ -717,9 +813,9 @@ void BreakpointLocation::SwapLocation(BreakpointLocationSP swap_from) {
}
void BreakpointLocation::SetThreadIDInternal(lldb::tid_t thread_id) {
- if (thread_id != LLDB_INVALID_THREAD_ID)
+ if (thread_id != LLDB_INVALID_THREAD_ID) {
GetLocationOptions().SetThreadID(thread_id);
- else {
+ } else {
// If we're resetting this to an invalid thread id, then don't make an
// options pointer just to do that.
if (m_options_up != nullptr)