summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdrian Prantl <aprantl@apple.com>2018-08-30 15:11:00 +0000
committerAdrian Prantl <aprantl@apple.com>2018-08-30 15:11:00 +0000
commit9b6b462a3d2f916531b0bf334879aa64079d5c01 (patch)
treee3e6f68610a2538ea351bd50e7def57f4c7b9191
parent1f9877970ac2e55492547c3c5fc957205499fd23 (diff)
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 git-svn-id: https://llvm.org/svn/llvm-project/lldb/trunk@341078 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/lldb/API/SBTarget.h5
-rw-r--r--include/lldb/Breakpoint/BreakpointResolver.h6
-rw-r--r--include/lldb/Breakpoint/BreakpointResolverFileLine.h15
-rw-r--r--include/lldb/Target/Target.h2
-rw-r--r--packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_by_line_and_column/Makefile6
-rw-r--r--packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_by_line_and_column/TestBreakpointByLineAndColumn.py44
-rw-r--r--packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_by_line_and_column/main.c23
-rw-r--r--packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/TestBreakpointCommand.py4
-rw-r--r--packages/Python/lldbsuite/test/functionalities/breakpoint/serialize/TestBreakpointSerialization.py9
-rw-r--r--packages/Python/lldbsuite/test/lldbutil.py26
-rw-r--r--scripts/interface/SBTarget.i5
-rw-r--r--source/API/SBTarget.cpp11
-rw-r--r--source/Breakpoint/BreakpointResolver.cpp74
-rw-r--r--source/Breakpoint/BreakpointResolverFileLine.cpp35
-rw-r--r--source/Commands/CommandObjectBreakpoint.cpp3
-rw-r--r--source/Core/IOHandler.cpp2
-rw-r--r--source/Symbol/LineEntry.cpp14
-rw-r--r--source/Target/Target.cpp6
18 files changed, 238 insertions, 52 deletions
diff --git a/include/lldb/API/SBTarget.h b/include/lldb/API/SBTarget.h
index cc3489cee..5119f1f98 100644
--- a/include/lldb/API/SBTarget.h
+++ b/include/lldb/API/SBTarget.h
@@ -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);
diff --git a/include/lldb/Breakpoint/BreakpointResolver.h b/include/lldb/Breakpoint/BreakpointResolver.h
index 08326c380..96162105b 100644
--- a/include/lldb/Breakpoint/BreakpointResolver.h
+++ b/include/lldb/Breakpoint/BreakpointResolver.h
@@ -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;
diff --git a/include/lldb/Breakpoint/BreakpointResolverFileLine.h b/include/lldb/Breakpoint/BreakpointResolverFileLine.h
index 3464f8ea8..539591f7f 100644
--- a/include/lldb/Breakpoint/BreakpointResolverFileLine.h
+++ b/include/lldb/Breakpoint/BreakpointResolverFileLine.h
@@ -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;
diff --git a/include/lldb/Target/Target.h b/include/lldb/Target/Target.h
index 5b0bb0e09..90f07ca9d 100644
--- a/include/lldb/Target/Target.h
+++ b/include/lldb/Target/Target.h
@@ -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,
diff --git a/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_by_line_and_column/Makefile b/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_by_line_and_column/Makefile
new file mode 100644
index 000000000..6c22351dc
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_by_line_and_column/Makefile
@@ -0,0 +1,6 @@
+LEVEL = ../../../make
+
+C_SOURCES := main.c
+CFLAGS_EXTRAS += -std=c99 -gcolumn-info
+
+include $(LEVEL)/Makefile.rules
diff --git a/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_by_line_and_column/TestBreakpointByLineAndColumn.py b/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_by_line_and_column/TestBreakpointByLineAndColumn.py
new file mode 100644
index 000000000..1eb535bef
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_by_line_and_column/TestBreakpointByLineAndColumn.py
@@ -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)
diff --git a/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_by_line_and_column/main.c b/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_by_line_and_column/main.c
new file mode 100644
index 000000000..921bc3820
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_by_line_and_column/main.c
@@ -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);
+}
diff --git a/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/TestBreakpointCommand.py b/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/TestBreakpointCommand.py
index 7a2dc61b1..9ebe61b65 100644
--- a/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/TestBreakpointCommand.py
+++ b/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/TestBreakpointCommand.py
@@ -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",
diff --git a/packages/Python/lldbsuite/test/functionalities/breakpoint/serialize/TestBreakpointSerialization.py b/packages/Python/lldbsuite/test/functionalities/breakpoint/serialize/TestBreakpointSerialization.py
index c615278e8..943998a42 100644
--- a/packages/Python/lldbsuite/test/functionalities/breakpoint/serialize/TestBreakpointSerialization.py
+++ b/packages/Python/lldbsuite/test/functionalities/breakpoint/serialize/TestBreakpointSerialization.py
@@ -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)
diff --git a/packages/Python/lldbsuite/test/lldbutil.py b/packages/Python/lldbsuite/test/lldbutil.py
index dc8438333..d114aaa2b 100644
--- a/packages/Python/lldbsuite/test/lldbutil.py
+++ b/packages/Python/lldbsuite/test/lldbutil.py
@@ -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_pattern, source_spec,
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()
diff --git a/scripts/interface/SBTarget.i b/scripts/interface/SBTarget.i
index ca3cb7ee5..993c37408 100644
--- a/scripts/interface/SBTarget.i
+++ b/scripts/interface/SBTarget.i
@@ -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
diff --git a/source/API/SBTarget.cpp b/source/API/SBTarget.cpp
index 15cdb0f31..b143d6ccd 100644
--- a/source/API/SBTarget.cpp
+++ b/source/API/SBTarget.cpp
@@ -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(const SBFileSpec &sb_file_spec,
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) {
diff --git a/source/Breakpoint/BreakpointResolver.cpp b/source/Breakpoint/BreakpointResolver.cpp
index a8a3c820d..de8032d23 100644
--- a/source/Breakpoint/BreakpointResolver.cpp
+++ b/source/Breakpoint/BreakpointResolver.cpp
@@ -44,9 +44,9 @@ const char *BreakpointResolver::g_ty_to_name[] = {"FileAndLine", "Address",
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::ResolveBreakpoint(SearchFilter &filter) {
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::SetSCMatchesByLine(SearchFilter &filter,
}
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,
diff --git a/source/Breakpoint/BreakpointResolverFileLine.cpp b/source/Breakpoint/BreakpointResolverFileLine.cpp
index a846f5bf9..76223f257 100644
--- a/source/Breakpoint/BreakpointResolverFileLine.cpp
+++ b/source/Breakpoint/BreakpointResolverFileLine.cpp
@@ -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 *BreakpointResolverFileLine::CreateFromStructuredData(
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 *BreakpointResolverFileLine::CreateFromStructuredData(
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 *BreakpointResolverFileLine::CreateFromStructuredData(
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::SerializeToStructuredData() {
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::SearchCallback(SearchFilter &filter,
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 BreakpointResolverFileLine::GetDepth() {
}
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(Stream *s) const {}
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;
diff --git a/source/Commands/CommandObjectBreakpoint.cpp b/source/Commands/CommandObjectBreakpoint.cpp
index fb0553e48..96b4fc390 100644
--- a/source/Commands/CommandObjectBreakpoint.cpp
+++ b/source/Commands/CommandObjectBreakpoint.cpp
@@ -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,
diff --git a/source/Core/IOHandler.cpp b/source/Core/IOHandler.cpp
index ee7513d4a..e01d84968 100644
--- a/source/Core/IOHandler.cpp
+++ b/source/Core/IOHandler.cpp
@@ -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,
diff --git a/source/Symbol/LineEntry.cpp b/source/Symbol/LineEntry.cpp
index 21aa25575..bffcc5321 100644
--- a/source/Symbol/LineEntry.cpp
+++ b/source/Symbol/LineEntry.cpp
@@ -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 *s, bool show_fullpaths) const {
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,
diff --git a/source/Target/Target.cpp b/source/Target/Target.cpp
index d0d447609..a4e9cb68c 100644
--- a/source/Target/Target.cpp
+++ b/source/Target/Target.cpp
@@ -322,7 +322,7 @@ BreakpointSP Target::CreateSourceRegexBreakpoint(
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(const FileSpecList *containingModules,
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);
}