Index: lldb/trunk/include/lldb/Breakpoint/BreakpointResolverFileLine.h =================================================================== --- lldb/trunk/include/lldb/Breakpoint/BreakpointResolverFileLine.h +++ lldb/trunk/include/lldb/Breakpoint/BreakpointResolverFileLine.h @@ -63,7 +63,7 @@ lldb::BreakpointResolverSP CopyForBreakpoint(Breakpoint &breakpoint) override; protected: - void FilterContexts(SymbolContextList &sc_list); + void FilterContexts(SymbolContextList &sc_list, bool is_relative); friend class Breakpoint; FileSpec m_file_spec; // This is the file spec we are looking for. Index: lldb/trunk/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/TestBreakpointCommand.py =================================================================== --- lldb/trunk/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/TestBreakpointCommand.py +++ lldb/trunk/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/TestBreakpointCommand.py @@ -62,7 +62,31 @@ # setting breakpoint commands on two breakpoints at a time lldbutil.run_break_set_by_file_and_line( self, None, self.line, num_expected_locations=1, loc_exact=True) - + # Make sure relative path source breakpoints work as expected. We test + # with partial paths with and without "./" prefixes. + lldbutil.run_break_set_by_file_and_line( + self, "./main.c", self.line, + num_expected_locations=1, loc_exact=True) + lldbutil.run_break_set_by_file_and_line( + self, "breakpoint_command/main.c", self.line, + num_expected_locations=1, loc_exact=True) + lldbutil.run_break_set_by_file_and_line( + self, "./breakpoint_command/main.c", self.line, + num_expected_locations=1, loc_exact=True) + lldbutil.run_break_set_by_file_and_line( + self, "breakpoint/breakpoint_command/main.c", self.line, + num_expected_locations=1, loc_exact=True) + lldbutil.run_break_set_by_file_and_line( + self, "./breakpoint/breakpoint_command/main.c", self.line, + num_expected_locations=1, loc_exact=True) + # Test relative breakpoints with incorrect paths and make sure we get + # no breakpoint locations + lldbutil.run_break_set_by_file_and_line( + self, "invalid/main.c", self.line, + num_expected_locations=0, loc_exact=True) + lldbutil.run_break_set_by_file_and_line( + self, "./invalid/main.c", self.line, + num_expected_locations=0, loc_exact=True) # Now add callbacks for the breakpoints just created. self.runCmd( "breakpoint command add -s command -o 'frame variable --show-types --scope' 1 4") Index: lldb/trunk/packages/Python/lldbsuite/test/lldbutil.py =================================================================== --- lldb/trunk/packages/Python/lldbsuite/test/lldbutil.py +++ lldb/trunk/packages/Python/lldbsuite/test/lldbutil.py @@ -576,7 +576,7 @@ if 'file' in break_results: out_file_name = break_results['file'] test.assertTrue( - file_name == out_file_name, + file_name.endswith(out_file_name), "Breakpoint file name '%s' doesn't match resultant name '%s'." % (file_name, out_file_name)) Index: lldb/trunk/source/Breakpoint/BreakpointResolverFileLine.cpp =================================================================== --- lldb/trunk/source/Breakpoint/BreakpointResolverFileLine.cpp +++ lldb/trunk/source/Breakpoint/BreakpointResolverFileLine.cpp @@ -115,15 +115,35 @@ // here is handling inlined functions -- in this case we need to make sure we // look at the declaration line of the inlined function, NOT the function it was // inlined into. -void BreakpointResolverFileLine::FilterContexts(SymbolContextList &sc_list) { +void BreakpointResolverFileLine::FilterContexts(SymbolContextList &sc_list, + bool is_relative) { if (m_exact_match) return; // Nothing to do. Contexts are precise. + llvm::StringRef relative_path; + if (is_relative) + relative_path = m_file_spec.GetNormalizedPath().GetDirectory().GetStringRef(); + Log * log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_BREAKPOINTS); for(uint32_t i = 0; i < sc_list.GetSize(); ++i) { SymbolContext sc; sc_list.GetContextAtIndex(i, sc); - if (! sc.block) + if (is_relative) { + // If the path was relative, make sure any matches match as long as the + // relative parts of the path match the path from support files + auto sc_dir = sc.line_entry.file.GetDirectory().GetStringRef(); + if (!sc_dir.endswith(relative_path)) { + // We had a relative path specified and the relative directory + // doesn't match so remove this one + LLDB_LOG(log, "removing not matching relative path {0} since it " + "doesn't end with {1}", sc_dir, relative_path); + sc_list.RemoveContextAtIndex(i); + --i; + continue; + } + } + + if (!sc.block) continue; FileSpec file; @@ -194,18 +214,23 @@ // through the match list and pull out the sets that have the same file spec // in their line_entry and treat each set separately. + FileSpec search_file_spec = m_file_spec; + const bool is_relative = m_file_spec.IsRelative(); + if (is_relative) + search_file_spec.GetDirectory().Clear(); + const size_t num_comp_units = context.module_sp->GetNumCompileUnits(); for (size_t i = 0; i < num_comp_units; i++) { CompUnitSP cu_sp(context.module_sp->GetCompileUnitAtIndex(i)); if (cu_sp) { if (filter.CompUnitPasses(*cu_sp)) - cu_sp->ResolveSymbolContext(m_file_spec, m_line_number, m_inlines, + cu_sp->ResolveSymbolContext(search_file_spec, m_line_number, m_inlines, m_exact_match, eSymbolContextEverything, sc_list); } } - FilterContexts(sc_list); + FilterContexts(sc_list, is_relative); StreamString s; s.Printf("for %s:%d ", m_file_spec.GetFilename().AsCString(""),