[Lldb-commits] [lldb] r341078 - Support setting a breakpoint by FileSpec+Line+Column in the SBAPI.

Adrian Prantl via lldb-commits lldb-commits at lists.llvm.org
Thu Aug 30 08:11:00 PDT 2018


Author: adrian
Date: Thu Aug 30 08:11:00 2018
New Revision: 341078

URL: http://llvm.org/viewvc/llvm-project?rev=341078&view=rev
Log:
Support setting a breakpoint by FileSpec+Line+Column in the SBAPI.

This patch extends the SBAPI to allow for setting a breakpoint not
only at a specific line, but also at a specific (minimum) column. When
a column is specified, it will try to find an exact match or the
closest match on the same line that comes after the specified
location.

Differential Revision: https://reviews.llvm.org/D51461

Added:
    lldb/trunk/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_by_line_and_column/
    lldb/trunk/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_by_line_and_column/Makefile
    lldb/trunk/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_by_line_and_column/TestBreakpointByLineAndColumn.py
    lldb/trunk/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_by_line_and_column/main.c
Modified:
    lldb/trunk/include/lldb/API/SBTarget.h
    lldb/trunk/include/lldb/Breakpoint/BreakpointResolver.h
    lldb/trunk/include/lldb/Breakpoint/BreakpointResolverFileLine.h
    lldb/trunk/include/lldb/Target/Target.h
    lldb/trunk/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/TestBreakpointCommand.py
    lldb/trunk/packages/Python/lldbsuite/test/functionalities/breakpoint/serialize/TestBreakpointSerialization.py
    lldb/trunk/packages/Python/lldbsuite/test/lldbutil.py
    lldb/trunk/scripts/interface/SBTarget.i
    lldb/trunk/source/API/SBTarget.cpp
    lldb/trunk/source/Breakpoint/BreakpointResolver.cpp
    lldb/trunk/source/Breakpoint/BreakpointResolverFileLine.cpp
    lldb/trunk/source/Commands/CommandObjectBreakpoint.cpp
    lldb/trunk/source/Core/IOHandler.cpp
    lldb/trunk/source/Symbol/LineEntry.cpp
    lldb/trunk/source/Target/Target.cpp

Modified: lldb/trunk/include/lldb/API/SBTarget.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/API/SBTarget.h?rev=341078&r1=341077&r2=341078&view=diff
==============================================================================
--- lldb/trunk/include/lldb/API/SBTarget.h (original)
+++ lldb/trunk/include/lldb/API/SBTarget.h Thu Aug 30 08:11:00 2018
@@ -580,6 +580,11 @@ public:
   BreakpointCreateByLocation(const lldb::SBFileSpec &file_spec, uint32_t line,
                              lldb::addr_t offset, SBFileSpecList &module_list);
 
+  lldb::SBBreakpoint
+  BreakpointCreateByLocation(const lldb::SBFileSpec &file_spec, uint32_t line,
+                             uint32_t column, lldb::addr_t offset,
+                             SBFileSpecList &module_list);
+
   lldb::SBBreakpoint BreakpointCreateByName(const char *symbol_name,
                                             const char *module_name = nullptr);
 

Modified: lldb/trunk/include/lldb/Breakpoint/BreakpointResolver.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Breakpoint/BreakpointResolver.h?rev=341078&r1=341077&r2=341078&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Breakpoint/BreakpointResolver.h (original)
+++ lldb/trunk/include/lldb/Breakpoint/BreakpointResolver.h Thu Aug 30 08:11:00 2018
@@ -200,6 +200,7 @@ protected:
     Inlines,
     LanguageName,
     LineNumber,
+    Column,
     ModuleName,
     NameMaskArray,
     Offset,
@@ -224,8 +225,11 @@ protected:
   /// number that matches, and then filter down the matching addresses to
   /// unique entries, and skip the prologue if asked to do so, and then set
   /// breakpoint locations in this breakpoint for all the resultant addresses.
+  /// When \p column is nonzero the \p line and \p column args are used to
+  /// filter the results to find the first breakpoint >= (line, column).
   void SetSCMatchesByLine(SearchFilter &filter, SymbolContextList &sc_list,
-                          bool skip_prologue, llvm::StringRef log_ident);
+                          bool skip_prologue, llvm::StringRef log_ident,
+                          uint32_t line = 0, uint32_t column = 0);
   void SetSCMatchesByLine(SearchFilter &, SymbolContextList &, bool,
                           const char *) = delete;
 

Modified: lldb/trunk/include/lldb/Breakpoint/BreakpointResolverFileLine.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Breakpoint/BreakpointResolverFileLine.h?rev=341078&r1=341077&r2=341078&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Breakpoint/BreakpointResolverFileLine.h (original)
+++ lldb/trunk/include/lldb/Breakpoint/BreakpointResolverFileLine.h Thu Aug 30 08:11:00 2018
@@ -28,9 +28,9 @@ namespace lldb_private {
 class BreakpointResolverFileLine : public BreakpointResolver {
 public:
   BreakpointResolverFileLine(Breakpoint *bkpt, const FileSpec &resolver,
-                             uint32_t line_no, lldb::addr_t m_offset,
-                             bool check_inlines, bool skip_prologue,
-                             bool exact_match);
+                             uint32_t line_no, uint32_t column,
+                             lldb::addr_t m_offset, bool check_inlines,
+                             bool skip_prologue, bool exact_match);
 
   static BreakpointResolver *
   CreateFromStructuredData(Breakpoint *bkpt,
@@ -65,10 +65,11 @@ protected:
   void FilterContexts(SymbolContextList &sc_list, bool is_relative);
 
   friend class Breakpoint;
-  FileSpec m_file_spec;   // This is the file spec we are looking for.
-  uint32_t m_line_number; // This is the line number that we are looking for.
-  bool m_inlines; // This determines whether the resolver looks for inlined
-                  // functions or not.
+  FileSpec m_file_spec;   ///< This is the file spec we are looking for.
+  uint32_t m_line_number; ///< This is the line number that we are looking for.
+  uint32_t m_column;      ///< This is the column that we are looking for.
+  bool m_inlines; ///< This determines whether the resolver looks for inlined
+                  ///< functions or not.
   bool m_skip_prologue;
   bool m_exact_match;
 

Modified: lldb/trunk/include/lldb/Target/Target.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Target/Target.h?rev=341078&r1=341077&r2=341078&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Target/Target.h (original)
+++ lldb/trunk/include/lldb/Target/Target.h Thu Aug 30 08:11:00 2018
@@ -557,7 +557,7 @@ public:
   // module it is nullptr
   lldb::BreakpointSP CreateBreakpoint(const FileSpecList *containingModules,
                                       const FileSpec &file, uint32_t line_no,
-                                      lldb::addr_t offset,
+                                      uint32_t column, lldb::addr_t offset,
                                       LazyBool check_inlines,
                                       LazyBool skip_prologue, bool internal,
                                       bool request_hardware,

Added: lldb/trunk/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_by_line_and_column/Makefile
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_by_line_and_column/Makefile?rev=341078&view=auto
==============================================================================
--- lldb/trunk/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_by_line_and_column/Makefile (added)
+++ lldb/trunk/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_by_line_and_column/Makefile Thu Aug 30 08:11:00 2018
@@ -0,0 +1,6 @@
+LEVEL = ../../../make
+
+C_SOURCES := main.c
+CFLAGS_EXTRAS += -std=c99 -gcolumn-info
+
+include $(LEVEL)/Makefile.rules

Added: lldb/trunk/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_by_line_and_column/TestBreakpointByLineAndColumn.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_by_line_and_column/TestBreakpointByLineAndColumn.py?rev=341078&view=auto
==============================================================================
--- lldb/trunk/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_by_line_and_column/TestBreakpointByLineAndColumn.py (added)
+++ lldb/trunk/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_by_line_and_column/TestBreakpointByLineAndColumn.py Thu Aug 30 08:11:00 2018
@@ -0,0 +1,44 @@
+"""
+Test setting a breakpoint by line and column.
+"""
+
+from __future__ import print_function
+
+
+import os
+import time
+import re
+import lldb
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+
+
+class BreakpointByLineAndColumnTestCase(TestBase):
+
+    mydir = TestBase.compute_mydir(__file__)
+
+    def testBreakpointByLineAndColumn(self):
+        self.build()
+        main_c = lldb.SBFileSpec("main.c")
+        _, _, _, breakpoint = lldbutil.run_to_line_breakpoint(self,
+                                                              main_c, 20, 50)
+        self.expect("fr v did_call", substrs='1')
+        in_then = False
+        for i in range(breakpoint.GetNumLocations()):
+            b_loc = breakpoint.GetLocationAtIndex(i).GetAddress().GetLineEntry()
+            self.assertEqual(b_loc.GetLine(), 20)
+            in_then |= b_loc.GetColumn() == 50
+        self.assertTrue(in_then)
+
+    def testBreakpointByLine(self):
+        self.build()
+        main_c = lldb.SBFileSpec("main.c")
+        _, _, _, breakpoint = lldbutil.run_to_line_breakpoint(self, main_c, 20)
+        self.expect("fr v did_call", substrs='0')
+        in_condition = False
+        for i in range(breakpoint.GetNumLocations()):
+            b_loc = breakpoint.GetLocationAtIndex(i).GetAddress().GetLineEntry()
+            self.assertEqual(b_loc.GetLine(), 20)
+            in_condition |= b_loc.GetColumn() < 30
+        self.assertTrue(in_condition)

Added: lldb/trunk/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_by_line_and_column/main.c
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_by_line_and_column/main.c?rev=341078&view=auto
==============================================================================
--- lldb/trunk/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_by_line_and_column/main.c (added)
+++ lldb/trunk/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_by_line_and_column/main.c Thu Aug 30 08:11:00 2018
@@ -0,0 +1,23 @@
+//===-- main.c --------------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+int square(int x)
+{
+  return x * x;
+}
+
+int main (int argc, char const *argv[])
+{
+  int did_call = 0;
+
+  // Line 20.                                    v Column 50.
+  if(square(argc+1) != 0) { did_call = 1; return square(argc); }
+  //                                             ^
+  return square(0);
+}

Modified: lldb/trunk/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/TestBreakpointCommand.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/TestBreakpointCommand.py?rev=341078&r1=341077&r2=341078&view=diff
==============================================================================
--- lldb/trunk/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/TestBreakpointCommand.py (original)
+++ lldb/trunk/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/TestBreakpointCommand.py Thu Aug 30 08:11:00 2018
@@ -133,9 +133,9 @@ class BreakpointCommandTestCase(TestBase
             patterns=[
                 "1: file = '.*main.c', line = %d, exact_match = 0, locations = 1" %
                 self.line,
-                "1.1: .+at main.c:%d, .+unresolved, hit count = 0" %
+                "1.1: .+at main.c:%d:?[0-9]*, .+unresolved, hit count = 0" %
                 self.line,
-                "2.1: .+at main.c:%d, .+unresolved, hit count = 0" %
+                "2.1: .+at main.c:%d:?[0-9]*, .+unresolved, hit count = 0" %
                 self.line])
 
         self.expect("breakpoint command list 1", "Breakpoint 1 command ok",

Modified: lldb/trunk/packages/Python/lldbsuite/test/functionalities/breakpoint/serialize/TestBreakpointSerialization.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/packages/Python/lldbsuite/test/functionalities/breakpoint/serialize/TestBreakpointSerialization.py?rev=341078&r1=341077&r2=341078&view=diff
==============================================================================
--- lldb/trunk/packages/Python/lldbsuite/test/functionalities/breakpoint/serialize/TestBreakpointSerialization.py (original)
+++ lldb/trunk/packages/Python/lldbsuite/test/functionalities/breakpoint/serialize/TestBreakpointSerialization.py Thu Aug 30 08:11:00 2018
@@ -180,7 +180,8 @@ class BreakpointSerialization(TestBase):
         # actually have locations.
         source_bps = lldb.SBBreakpointList(self.orig_target)
 
-        bkpt = self.orig_target.BreakpointCreateByLocation("blubby.c", 666)
+        bkpt = self.orig_target.BreakpointCreateByLocation(
+            lldb.SBFileSpec("blubby.c"), 666, 333, 0, lldb.SBFileSpecList())
         bkpt.SetEnabled(False)
         bkpt.SetOneShot(True)
         bkpt.SetThreadID(10)
@@ -226,7 +227,8 @@ class BreakpointSerialization(TestBase):
         all_bps = lldb.SBBreakpointList(self.orig_target)
         source_bps = lldb.SBBreakpointList(self.orig_target)
 
-        bkpt = self.orig_target.BreakpointCreateByLocation("blubby.c", 666)
+        bkpt = self.orig_target.BreakpointCreateByLocation(
+            lldb.SBFileSpec("blubby.c"), 666, 333, 0, lldb.SBFileSpecList())
         bkpt.SetEnabled(False)
         bkpt.SetOneShot(True)
         bkpt.SetThreadID(10)
@@ -260,7 +262,8 @@ class BreakpointSerialization(TestBase):
         self.check_equivalence(all_bps)
 
     def do_check_names(self):
-        bkpt = self.orig_target.BreakpointCreateByLocation("blubby.c", 666)
+        bkpt = self.orig_target.BreakpointCreateByLocation(
+            lldb.SBFileSpec("blubby.c"), 666, 333, 0, lldb.SBFileSpecList())
         good_bkpt_name = "GoodBreakpoint"
         write_bps = lldb.SBBreakpointList(self.orig_target)
         bkpt.AddName(good_bkpt_name)

Modified: lldb/trunk/packages/Python/lldbsuite/test/lldbutil.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/packages/Python/lldbsuite/test/lldbutil.py?rev=341078&r1=341077&r2=341078&view=diff
==============================================================================
--- lldb/trunk/packages/Python/lldbsuite/test/lldbutil.py (original)
+++ lldb/trunk/packages/Python/lldbsuite/test/lldbutil.py Thu Aug 30 08:11:00 2018
@@ -511,7 +511,7 @@ def run_break_set_command(test, command)
     patterns = [
         r"^Breakpoint (?P<bpno>[0-9]+): (?P<num_locations>[0-9]+) locations\.$",
         r"^Breakpoint (?P<bpno>[0-9]+): (?P<num_locations>no) locations \(pending\)\.",
-        r"^Breakpoint (?P<bpno>[0-9]+): where = (?P<module>.*)`(?P<symbol>[+\-]{0,1}[^+]+)( \+ (?P<offset>[0-9]+)){0,1}( \[inlined\] (?P<inline_symbol>.*)){0,1} at (?P<file>[^:]+):(?P<line_no>[0-9]+), address = (?P<address>0x[0-9a-fA-F]+)$",
+        r"^Breakpoint (?P<bpno>[0-9]+): where = (?P<module>.*)`(?P<symbol>[+\-]{0,1}[^+]+)( \+ (?P<offset>[0-9]+)){0,1}( \[inlined\] (?P<inline_symbol>.*)){0,1} at (?P<file>[^:]+):(?P<line_no>[0-9]+)(?P<column>(:[0-9]+)?), address = (?P<address>0x[0-9a-fA-F]+)$",
         r"^Breakpoint (?P<bpno>[0-9]+): where = (?P<module>.*)`(?P<symbol>.*)( \+ (?P<offset>[0-9]+)){0,1}, address = (?P<address>0x[0-9a-fA-F]+)$"]
     match_object = test.match(command, patterns)
     break_results = match_object.groupdict()
@@ -819,9 +819,31 @@ def run_to_source_breakpoint(test, bkpt_
     breakpoint = target.BreakpointCreateBySourceRegex(
             bkpt_pattern, source_spec, bkpt_module)
     test.assertTrue(breakpoint.GetNumLocations() > 0,
-                    'No locations found for source breakpoint: "%s", file: "%s", dir: "%s"'%(bkpt_pattern, source_spec.GetFilename(), source_spec.GetDirectory()))
+        'No locations found for source breakpoint: "%s", file: "%s", dir: "%s"'
+        %(bkpt_pattern, source_spec.GetFilename(), source_spec.GetDirectory()))
     return run_to_breakpoint_do_run(test, target, breakpoint, launch_info)
 
+def run_to_line_breakpoint(test, source_spec, line_number, column = 0,
+                           launch_info = None, exe_name = "a.out",
+                           bkpt_module = None,
+                           in_cwd = True):
+    """Start up a target, using exe_name as the executable, and run it to
+       a breakpoint set by (source_spec, line_number(, column)).
+
+       The rest of the behavior is the same as run_to_name_breakpoint.
+    """
+
+    target = run_to_breakpoint_make_target(test, exe_name, in_cwd)
+    # Set the breakpoints
+    breakpoint = target.BreakpointCreateByLocation(
+        source_spec, line_number, column, 0, lldb.SBFileSpecList())
+    test.assertTrue(breakpoint.GetNumLocations() > 0,
+        'No locations found for line breakpoint: "%s:%d(:%d)", dir: "%s"'
+        %(source_spec.GetFilename(), line_number, column,
+          source_spec.GetDirectory()))
+    return run_to_breakpoint_do_run(test, target, breakpoint, launch_info)
+
+
 def continue_to_breakpoint(process, bkpt):
     """ Continues the process, if it stops, returns the threads stopped at bkpt; otherwise, returns None"""
     process.Continue()

Modified: lldb/trunk/scripts/interface/SBTarget.i
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/scripts/interface/SBTarget.i?rev=341078&r1=341077&r2=341078&view=diff
==============================================================================
--- lldb/trunk/scripts/interface/SBTarget.i (original)
+++ lldb/trunk/scripts/interface/SBTarget.i Thu Aug 30 08:11:00 2018
@@ -624,6 +624,11 @@ public:
                                 lldb::addr_t offset, SBFileSpecList &module_list);
 
     lldb::SBBreakpoint
+    BreakpointCreateByLocation (const lldb::SBFileSpec &file_spec, uint32_t line,
+                                uint32_t column, lldb::addr_t offset,
+                                SBFileSpecList &module_list);
+
+    lldb::SBBreakpoint
     BreakpointCreateByName (const char *symbol_name, const char *module_name = NULL);
 
     lldb::SBBreakpoint

Modified: lldb/trunk/source/API/SBTarget.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/API/SBTarget.cpp?rev=341078&r1=341077&r2=341078&view=diff
==============================================================================
--- lldb/trunk/source/API/SBTarget.cpp (original)
+++ lldb/trunk/source/API/SBTarget.cpp Thu Aug 30 08:11:00 2018
@@ -693,6 +693,13 @@ SBBreakpoint
 SBTarget::BreakpointCreateByLocation(const SBFileSpec &sb_file_spec,
                                      uint32_t line, lldb::addr_t offset,
                                      SBFileSpecList &sb_module_list) {
+  return BreakpointCreateByLocation(sb_file_spec, line, 0, offset,
+                                    sb_module_list);
+}
+
+SBBreakpoint SBTarget::BreakpointCreateByLocation(
+    const SBFileSpec &sb_file_spec, uint32_t line, uint32_t column,
+    lldb::addr_t offset, SBFileSpecList &sb_module_list) {
   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
 
   SBBreakpoint sb_bp;
@@ -710,8 +717,8 @@ SBTarget::BreakpointCreateByLocation(con
       module_list = sb_module_list.get();
     }
     sb_bp = target_sp->CreateBreakpoint(
-        module_list, *sb_file_spec, line, offset, check_inlines, skip_prologue,
-        internal, hardware, move_to_nearest_code);
+        module_list, *sb_file_spec, line, column, offset, check_inlines,
+        skip_prologue, internal, hardware, move_to_nearest_code);
   }
 
   if (log) {

Modified: lldb/trunk/source/Breakpoint/BreakpointResolver.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Breakpoint/BreakpointResolver.cpp?rev=341078&r1=341077&r2=341078&view=diff
==============================================================================
--- lldb/trunk/source/Breakpoint/BreakpointResolver.cpp (original)
+++ lldb/trunk/source/Breakpoint/BreakpointResolver.cpp Thu Aug 30 08:11:00 2018
@@ -44,9 +44,9 @@ const char *BreakpointResolver::g_ty_to_
 
 const char *BreakpointResolver::g_option_names[static_cast<uint32_t>(
     BreakpointResolver::OptionNames::LastOptionName)] = {
-    "AddressOffset", "Exact",        "FileName",   "Inlines", "Language",
-    "LineNumber",    "ModuleName",   "NameMask",   "Offset",  "Regex",
-    "SectionName",   "SkipPrologue", "SymbolNames"};
+    "AddressOffset", "Exact",       "FileName",     "Inlines",    "Language",
+    "LineNumber",    "Column",      "ModuleName",   "NameMask",   "Offset",
+    "Regex",         "SectionName", "SkipPrologue", "SymbolNames"};
 
 const char *BreakpointResolver::ResolverTyToName(enum ResolverTy type) {
   if (type > LastKnownResolverType)
@@ -176,18 +176,37 @@ void BreakpointResolver::ResolveBreakpoi
   filter.Search(*this);
 }
 
+namespace {
+struct SourceLoc {
+  uint32_t line = UINT32_MAX;
+  uint32_t column;
+  SourceLoc(uint32_t l, uint32_t c) : line(l), column(c ? c : UINT32_MAX) {}
+  SourceLoc(const SymbolContext &sc)
+      : line(sc.line_entry.line),
+        column(sc.line_entry.column ? sc.line_entry.column : UINT32_MAX) {}
+};
+
+bool operator<(const SourceLoc a, const SourceLoc b) {
+  if (a.line < b.line)
+    return true;
+  if (a.line > b.line)
+    return false;
+  uint32_t a_col = a.column ? a.column : UINT32_MAX;
+  uint32_t b_col = b.column ? b.column : UINT32_MAX;
+  return a_col < b_col;
+}
+} // namespace
+
 void BreakpointResolver::SetSCMatchesByLine(SearchFilter &filter,
                                             SymbolContextList &sc_list,
                                             bool skip_prologue,
-                                            llvm::StringRef log_ident) {
+                                            llvm::StringRef log_ident,
+                                            uint32_t line, uint32_t column) {
   llvm::SmallVector<SymbolContext, 16> all_scs;
   for (uint32_t i = 0; i < sc_list.GetSize(); ++i)
     all_scs.push_back(sc_list[i]);
 
   while (all_scs.size()) {
-    // ResolveSymbolContext will always return a number that is >= the
-    // line number you pass in. So the smaller line number is always
-    // better.
     uint32_t closest_line = UINT32_MAX;
 
     // Move all the elements with a matching file spec to the end.
@@ -202,12 +221,41 @@ void BreakpointResolver::SetSCMatchesByL
           }
           return true;
         });
-    
-    // Within, remove all entries with a larger line number.
-    auto worklist_end = std::remove_if(
-        worklist_begin, all_scs.end(), [&](const SymbolContext &sc) {
-          return closest_line != sc.line_entry.line;
-        });
+
+    // (worklist_begin, worklist_end) now contains all entries for one filespec.
+    auto worklist_end = all_scs.end();
+
+    if (column) {
+      // If a column was requested, do a more precise match and only
+      // return the first location that comes after or at the
+      // requested location.
+      SourceLoc requested(line, column);
+      // First, filter out all entries left of the requested column.
+      worklist_end = std::remove_if(
+          worklist_begin, worklist_end,
+          [&](const SymbolContext &sc) { return SourceLoc(sc) < requested; });
+      // Sort the remaining entries by (line, column).
+      std::sort(worklist_begin, worklist_end,
+                [](const SymbolContext &a, const SymbolContext &b) {
+                  return SourceLoc(a) < SourceLoc(b);
+                });
+
+      // Filter out all locations with a source location after the closest match.
+      if (worklist_begin != worklist_end)
+        worklist_end = std::remove_if(
+            worklist_begin, worklist_end, [&](const SymbolContext &sc) {
+              return SourceLoc(*worklist_begin) < SourceLoc(sc);
+            });
+    } else {
+      // Remove all entries with a larger line number.
+      // ResolveSymbolContext will always return a number that is >=
+      // the line number you pass in. So the smaller line number is
+      // always better.
+      worklist_end = std::remove_if(worklist_begin, worklist_end,
+                                    [&](const SymbolContext &sc) {
+                                      return closest_line != sc.line_entry.line;
+                                    });
+    }
 
     // Sort by file address.
     std::sort(worklist_begin, worklist_end,

Modified: lldb/trunk/source/Breakpoint/BreakpointResolverFileLine.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Breakpoint/BreakpointResolverFileLine.cpp?rev=341078&r1=341077&r2=341078&view=diff
==============================================================================
--- lldb/trunk/source/Breakpoint/BreakpointResolverFileLine.cpp (original)
+++ lldb/trunk/source/Breakpoint/BreakpointResolverFileLine.cpp Thu Aug 30 08:11:00 2018
@@ -28,11 +28,12 @@ using namespace lldb_private;
 //----------------------------------------------------------------------
 BreakpointResolverFileLine::BreakpointResolverFileLine(
     Breakpoint *bkpt, const FileSpec &file_spec, uint32_t line_no,
-    lldb::addr_t offset, bool check_inlines, bool skip_prologue,
-    bool exact_match)
+    uint32_t column, lldb::addr_t offset, bool check_inlines,
+    bool skip_prologue, bool exact_match)
     : BreakpointResolver(bkpt, BreakpointResolver::FileLineResolver, offset),
-      m_file_spec(file_spec), m_line_number(line_no), m_inlines(check_inlines),
-      m_skip_prologue(skip_prologue), m_exact_match(exact_match) {}
+      m_file_spec(file_spec), m_line_number(line_no), m_column(column),
+      m_inlines(check_inlines), m_skip_prologue(skip_prologue),
+      m_exact_match(exact_match) {}
 
 BreakpointResolverFileLine::~BreakpointResolverFileLine() {}
 
@@ -41,6 +42,7 @@ BreakpointResolver *BreakpointResolverFi
     Status &error) {
   llvm::StringRef filename;
   uint32_t line_no;
+  uint32_t column;
   bool check_inlines;
   bool skip_prologue;
   bool exact_match;
@@ -62,6 +64,13 @@ BreakpointResolver *BreakpointResolverFi
     return nullptr;
   }
 
+  success =
+      options_dict.GetValueForKeyAsInteger(GetKey(OptionNames::Column), column);
+  if (!success) {
+    // Backwards compatibility.
+    column = 0;
+  }
+
   success = options_dict.GetValueForKeyAsBoolean(GetKey(OptionNames::Inlines),
                                                  check_inlines);
   if (!success) {
@@ -85,8 +94,8 @@ BreakpointResolver *BreakpointResolverFi
 
   FileSpec file_spec(filename, false);
 
-  return new BreakpointResolverFileLine(bkpt, file_spec, line_no, offset,
-                                        check_inlines, skip_prologue,
+  return new BreakpointResolverFileLine(bkpt, file_spec, line_no, column,
+                                        offset, check_inlines, skip_prologue,
                                         exact_match);
 }
 
@@ -99,6 +108,8 @@ BreakpointResolverFileLine::SerializeToS
                                  m_file_spec.GetPath());
   options_dict_sp->AddIntegerItem(GetKey(OptionNames::LineNumber),
                                   m_line_number);
+  options_dict_sp->AddIntegerItem(GetKey(OptionNames::Column),
+                                  m_column);
   options_dict_sp->AddBooleanItem(GetKey(OptionNames::Inlines), m_inlines);
   options_dict_sp->AddBooleanItem(GetKey(OptionNames::SkipPrologue),
                                   m_skip_prologue);
@@ -240,7 +251,8 @@ BreakpointResolverFileLine::SearchCallba
   s.Printf("for %s:%d ", m_file_spec.GetFilename().AsCString("<Unknown>"),
            m_line_number);
 
-  SetSCMatchesByLine(filter, sc_list, m_skip_prologue, s.GetString());
+  SetSCMatchesByLine(filter, sc_list, m_skip_prologue, s.GetString(),
+                     m_line_number, m_column);
 
   return Searcher::eCallbackReturnContinue;
 }
@@ -250,8 +262,11 @@ Searcher::Depth BreakpointResolverFileLi
 }
 
 void BreakpointResolverFileLine::GetDescription(Stream *s) {
-  s->Printf("file = '%s', line = %u, exact_match = %d",
-            m_file_spec.GetPath().c_str(), m_line_number, m_exact_match);
+  s->Printf("file = '%s', line = %u, ", m_file_spec.GetPath().c_str(),
+            m_line_number);
+  if (m_column)
+    s->Printf("column = %u, ", m_column);
+  s->Printf("exact_match = %d", m_exact_match);
 }
 
 void BreakpointResolverFileLine::Dump(Stream *s) const {}
@@ -259,7 +274,7 @@ void BreakpointResolverFileLine::Dump(St
 lldb::BreakpointResolverSP
 BreakpointResolverFileLine::CopyForBreakpoint(Breakpoint &breakpoint) {
   lldb::BreakpointResolverSP ret_sp(new BreakpointResolverFileLine(
-      &breakpoint, m_file_spec, m_line_number, m_offset, m_inlines,
+      &breakpoint, m_file_spec, m_line_number, m_column, m_offset, m_inlines,
       m_skip_prologue, m_exact_match));
 
   return ret_sp;

Modified: lldb/trunk/source/Commands/CommandObjectBreakpoint.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Commands/CommandObjectBreakpoint.cpp?rev=341078&r1=341077&r2=341078&view=diff
==============================================================================
--- lldb/trunk/source/Commands/CommandObjectBreakpoint.cpp (original)
+++ lldb/trunk/source/Commands/CommandObjectBreakpoint.cpp Thu Aug 30 08:11:00 2018
@@ -696,7 +696,8 @@ protected:
 
       bp_sp = target->CreateBreakpoint(&(m_options.m_modules), 
                                        file,
-                                       m_options.m_line_num, 
+                                       m_options.m_line_num,
+                                       m_options.m_column,
                                        m_options.m_offset_addr,
                                        check_inlines, 
                                        m_options.m_skip_prologue,

Modified: lldb/trunk/source/Core/IOHandler.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/IOHandler.cpp?rev=341078&r1=341077&r2=341078&view=diff
==============================================================================
--- lldb/trunk/source/Core/IOHandler.cpp (original)
+++ lldb/trunk/source/Core/IOHandler.cpp Thu Aug 30 08:11:00 2018
@@ -4340,6 +4340,7 @@ public:
               m_file_sp->GetFileSpec(), // Source file
               m_selected_line +
                   1, // Source line number (m_selected_line is zero based)
+              0,     // Unspecified column.
               0,     // No offset
               eLazyBoolCalculate,  // Check inlines using global setting
               eLazyBoolCalculate,  // Skip prologue using global setting,
@@ -4379,6 +4380,7 @@ public:
               m_file_sp->GetFileSpec(), // Source file
               m_selected_line +
                   1, // Source line number (m_selected_line is zero based)
+              0,     // No column specified.
               0,     // No offset
               eLazyBoolCalculate,  // Check inlines using global setting
               eLazyBoolCalculate,  // Skip prologue using global setting,

Modified: lldb/trunk/source/Symbol/LineEntry.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Symbol/LineEntry.cpp?rev=341078&r1=341077&r2=341078&view=diff
==============================================================================
--- lldb/trunk/source/Symbol/LineEntry.cpp (original)
+++ lldb/trunk/source/Symbol/LineEntry.cpp Thu Aug 30 08:11:00 2018
@@ -50,7 +50,6 @@ bool LineEntry::IsValid() const {
 }
 
 bool LineEntry::DumpStopContext(Stream *s, bool show_fullpaths) const {
-  bool result = false;
   if (file) {
     if (show_fullpaths)
       file.Dump(s);
@@ -59,14 +58,15 @@ bool LineEntry::DumpStopContext(Stream *
 
     if (line)
       s->PutChar(':');
-    result = true;
   }
-  if (line)
+  if (line) {
     s->Printf("%u", line);
-  else
-    result = false;
-
-  return result;
+    if (column) {
+      s->PutChar(':');
+      s->Printf("%u", column);
+    }
+  }
+  return file || line;
 }
 
 bool LineEntry::Dump(Stream *s, Target *target, bool show_file,

Modified: lldb/trunk/source/Target/Target.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/Target.cpp?rev=341078&r1=341077&r2=341078&view=diff
==============================================================================
--- lldb/trunk/source/Target/Target.cpp (original)
+++ lldb/trunk/source/Target/Target.cpp Thu Aug 30 08:11:00 2018
@@ -322,7 +322,7 @@ BreakpointSP Target::CreateSourceRegexBr
 
 BreakpointSP Target::CreateBreakpoint(const FileSpecList *containingModules,
                                       const FileSpec &file, uint32_t line_no,
-                                      lldb::addr_t offset,
+                                      uint32_t column, lldb::addr_t offset,
                                       LazyBool check_inlines,
                                       LazyBool skip_prologue, bool internal,
                                       bool hardware,
@@ -366,8 +366,8 @@ BreakpointSP Target::CreateBreakpoint(co
     move_to_nearest_code = GetMoveToNearestCode() ? eLazyBoolYes : eLazyBoolNo;
 
   BreakpointResolverSP resolver_sp(new BreakpointResolverFileLine(
-      nullptr, remapped_file, line_no, offset, check_inlines, skip_prologue,
-      !static_cast<bool>(move_to_nearest_code)));
+      nullptr, remapped_file, line_no, column, offset, check_inlines,
+      skip_prologue, !static_cast<bool>(move_to_nearest_code)));
   return CreateBreakpoint(filter_sp, resolver_sp, internal, hardware, true);
 }
 




More information about the lldb-commits mailing list