aboutsummaryrefslogtreecommitdiff
path: root/source/Breakpoint/BreakpointResolver.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'source/Breakpoint/BreakpointResolver.cpp')
-rw-r--r--source/Breakpoint/BreakpointResolver.cpp144
1 files changed, 144 insertions, 0 deletions
diff --git a/source/Breakpoint/BreakpointResolver.cpp b/source/Breakpoint/BreakpointResolver.cpp
index b22fa1e6dbcc..33b0ff40e35f 100644
--- a/source/Breakpoint/BreakpointResolver.cpp
+++ b/source/Breakpoint/BreakpointResolver.cpp
@@ -23,9 +23,12 @@
#include "lldb/Core/StreamString.h"
#include "lldb/Symbol/SymbolContext.h"
#include "lldb/Target/Target.h"
+#include "lldb/Symbol/CompileUnit.h"
+#include "lldb/Symbol/Function.h"
#include "lldb/lldb-private-log.h"
using namespace lldb_private;
+using namespace lldb;
//----------------------------------------------------------------------
// BreakpointResolver:
@@ -59,3 +62,144 @@ BreakpointResolver::ResolveBreakpoint (SearchFilter &filter)
filter.Search (*this);
}
+void
+BreakpointResolver::SetSCMatchesByLine (SearchFilter &filter, SymbolContextList &sc_list, bool skip_prologue, const char *log_ident)
+{
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS));
+
+ while (sc_list.GetSize() > 0)
+ {
+ SymbolContextList tmp_sc_list;
+ unsigned current_idx = 0;
+ SymbolContext sc;
+ bool first_entry = true;
+
+ FileSpec match_file_spec;
+ uint32_t closest_line_number = UINT32_MAX;
+
+ // Pull out the first entry, and all the others that match its file spec, and stuff them in the tmp list.
+ while (current_idx < sc_list.GetSize())
+ {
+ bool matches;
+
+ sc_list.GetContextAtIndex (current_idx, sc);
+ if (first_entry)
+ {
+ match_file_spec = sc.line_entry.file;
+ matches = true;
+ first_entry = false;
+ }
+ else
+ matches = (sc.line_entry.file == match_file_spec);
+
+ if (matches)
+ {
+ tmp_sc_list.Append (sc);
+ sc_list.RemoveContextAtIndex(current_idx);
+
+ // ResolveSymbolContext will always return a number that is >= the line number you pass in.
+ // So the smaller line number is always better.
+ if (sc.line_entry.line < closest_line_number)
+ closest_line_number = sc.line_entry.line;
+ }
+ else
+ current_idx++;
+ }
+
+ // Okay, we've found the closest line number match, now throw away all the others:
+
+ current_idx = 0;
+ while (current_idx < tmp_sc_list.GetSize())
+ {
+ if (tmp_sc_list.GetContextAtIndex(current_idx, sc))
+ {
+ if (sc.line_entry.line != closest_line_number)
+ tmp_sc_list.RemoveContextAtIndex(current_idx);
+ else
+ current_idx++;
+ }
+ }
+
+ // Next go through and see if there are line table entries that are contiguous, and if so keep only the
+ // first of the contiguous range:
+
+ current_idx = 0;
+ std::map<Block *, lldb::addr_t> blocks_with_breakpoints;
+
+ while (current_idx < tmp_sc_list.GetSize())
+ {
+ if (tmp_sc_list.GetContextAtIndex(current_idx, sc))
+ {
+ if (blocks_with_breakpoints.find (sc.block) != blocks_with_breakpoints.end())
+ tmp_sc_list.RemoveContextAtIndex(current_idx);
+ else
+ {
+ blocks_with_breakpoints.insert (std::pair<Block *, lldb::addr_t>(sc.block, sc.line_entry.range.GetBaseAddress().GetFileAddress()));
+ current_idx++;
+ }
+ }
+ }
+
+ // and make breakpoints out of the closest line number match.
+
+ uint32_t tmp_sc_list_size = tmp_sc_list.GetSize();
+
+ for (uint32_t i = 0; i < tmp_sc_list_size; i++)
+ {
+ if (tmp_sc_list.GetContextAtIndex(i, sc))
+ {
+ Address line_start = sc.line_entry.range.GetBaseAddress();
+ if (line_start.IsValid())
+ {
+ if (filter.AddressPasses(line_start))
+ {
+ // If the line number is before the prologue end, move it there...
+ bool skipped_prologue = false;
+ if (skip_prologue)
+ {
+ if (sc.function)
+ {
+ Address prologue_addr(sc.function->GetAddressRange().GetBaseAddress());
+ if (prologue_addr.IsValid() && (line_start == prologue_addr))
+ {
+ const uint32_t prologue_byte_size = sc.function->GetPrologueByteSize();
+ if (prologue_byte_size)
+ {
+ prologue_addr.Slide(prologue_byte_size);
+
+ if (filter.AddressPasses(prologue_addr))
+ {
+ skipped_prologue = true;
+ line_start = prologue_addr;
+ }
+ }
+ }
+ }
+ }
+
+ BreakpointLocationSP bp_loc_sp (m_breakpoint->AddLocation(line_start));
+ if (log && bp_loc_sp && !m_breakpoint->IsInternal())
+ {
+ StreamString s;
+ bp_loc_sp->GetDescription (&s, lldb::eDescriptionLevelVerbose);
+ log->Printf ("Added location (skipped prologue: %s): %s \n", skipped_prologue ? "yes" : "no", s.GetData());
+ }
+ }
+ else if (log)
+ {
+ log->Printf ("Breakpoint %s at file address 0x%" PRIx64 " didn't pass the filter.\n",
+ log_ident ? log_ident : "",
+ line_start.GetFileAddress());
+ }
+ }
+ else
+ {
+ if (log)
+ log->Printf ("error: Unable to set breakpoint %s at file address 0x%" PRIx64 "\n",
+ log_ident ? log_ident : "",
+ line_start.GetFileAddress());
+ }
+ }
+ }
+ }
+}