labath created this revision. move-to-nearest-code needs special treatment to avoid creating superfluous breakpoints in case multiple compilation units. It already had code to handle the case when the compilation units are in the same module, but it still did not properly handle the case when the compilation units are in different modules.
This fixes the issue by manually iterating over the modules (instead of just CUs) to make sure we aggregate the matches properly. https://reviews.llvm.org/D30817 Files: packages/Python/lldbsuite/test/functionalities/breakpoint/move_nearest/Makefile packages/Python/lldbsuite/test/functionalities/breakpoint/move_nearest/TestMoveNearest.py packages/Python/lldbsuite/test/functionalities/breakpoint/move_nearest/foo.cpp packages/Python/lldbsuite/test/functionalities/breakpoint/move_nearest/foo.h packages/Python/lldbsuite/test/functionalities/breakpoint/move_nearest/main.cpp source/Breakpoint/BreakpointResolverFileLine.cpp
Index: source/Breakpoint/BreakpointResolverFileLine.cpp =================================================================== --- source/Breakpoint/BreakpointResolverFileLine.cpp +++ source/Breakpoint/BreakpointResolverFileLine.cpp @@ -17,6 +17,7 @@ #include "lldb/Core/Module.h" #include "lldb/Symbol/CompileUnit.h" #include "lldb/Symbol/Function.h" +#include "lldb/Target/Target.h" #include "lldb/Utility/Log.h" #include "lldb/Utility/StreamString.h" @@ -112,40 +113,49 @@ BreakpointResolverFileLine::SearchCallback(SearchFilter &filter, SymbolContext &context, Address *addr, bool containing) { + SymbolContextList sc_list; assert(m_breakpoint != NULL); // There is a tricky bit here. You can have two compilation units that - // #include the same file, and - // in one of them the function at m_line_number is used (and so code and a - // line entry for it is generated) but in the - // other it isn't. If we considered the CU's independently, then in the - // second inclusion, we'd move the breakpoint - // to the next function that actually generated code in the header file. That - // would end up being confusing. - // So instead, we do the CU iterations by hand here, then scan through the - // complete list of matches, and figure out - // the closest line number match, and only set breakpoints on that match. + // #include the same file, and in one of them the function at m_line_number is + // used (and so code and a line entry for it is generated) but in the other it + // isn't. If we considered the CU's independently, then in the second + // inclusion, we'd move the breakpoint to the next function that actually + // generated code in the header file. That would end up being confusing. So + // instead, we do the CU iterations by hand here, then scan through the + // complete list of matches, and figure out the closest line number match, and + // only set breakpoints on that match. // Note also that if file_spec only had a file name and not a directory, there - // may be many different file spec's in - // the resultant list. The closest line match for one will not be right for - // some totally different file. - // So we go through the match list and pull out the sets that have the same - // file spec in their line_entry - // and treat each set separately. - - 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, - m_exact_match, eSymbolContextEverything, - sc_list); + // may be many different file spec's in the resultant list. The closest line + // match for one will not be right for some totally different file. So we go + // through the match list and pull out the sets that have the same file spec + // in their line_entry and treat each set separately. + const ModuleList &target_images = context.target_sp->GetImages(); + std::lock_guard<std::recursive_mutex> guard(target_images.GetMutex()); + + size_t n_modules = target_images.GetSize(); + for (size_t i = 0; i < n_modules; i++) { + // If this is the last level supplied, then call the callback directly, + // otherwise descend. + ModuleSP module_sp(target_images.GetModuleAtIndexUnlocked(i)); + if (!filter.ModulePasses(module_sp)) + continue; + + const size_t num_comp_units = module_sp->GetNumCompileUnits(); + for (size_t i = 0; i < num_comp_units; i++) { + CompUnitSP cu_sp(module_sp->GetCompileUnitAtIndex(i)); + if (! cu_sp || !filter.CompUnitPasses(*cu_sp)) + continue; + + cu_sp->ResolveSymbolContext(m_file_spec, m_line_number, m_inlines, + m_exact_match, eSymbolContextEverything, + sc_list); } } + StreamString s; s.Printf("for %s:%d ", m_file_spec.GetFilename().AsCString("<Unknown>"), m_line_number); @@ -156,7 +166,7 @@ } Searcher::Depth BreakpointResolverFileLine::GetDepth() { - return Searcher::eDepthModule; + return Searcher::eDepthTarget; } void BreakpointResolverFileLine::GetDescription(Stream *s) { Index: packages/Python/lldbsuite/test/functionalities/breakpoint/move_nearest/main.cpp =================================================================== --- /dev/null +++ packages/Python/lldbsuite/test/functionalities/breakpoint/move_nearest/main.cpp @@ -0,0 +1,5 @@ +#include "foo.h" + +int call_foo2() { return foo2(); } + +int main() { return call_foo1() + call_foo2(); } Index: packages/Python/lldbsuite/test/functionalities/breakpoint/move_nearest/foo.h =================================================================== --- /dev/null +++ packages/Python/lldbsuite/test/functionalities/breakpoint/move_nearest/foo.h @@ -0,0 +1,5 @@ +LLDB_TEST_API inline int foo1() { return 1; } // !BR1 +LLDB_TEST_API inline int foo2() { return 2; } // !BR2 + +LLDB_TEST_API extern int call_foo1(); +LLDB_TEST_API extern int call_foo2(); Index: packages/Python/lldbsuite/test/functionalities/breakpoint/move_nearest/foo.cpp =================================================================== --- /dev/null +++ packages/Python/lldbsuite/test/functionalities/breakpoint/move_nearest/foo.cpp @@ -0,0 +1,3 @@ +#include "foo.h" + +int call_foo1() { return foo1(); } Index: packages/Python/lldbsuite/test/functionalities/breakpoint/move_nearest/TestMoveNearest.py =================================================================== --- /dev/null +++ packages/Python/lldbsuite/test/functionalities/breakpoint/move_nearest/TestMoveNearest.py @@ -0,0 +1,49 @@ +"""Test that types defined in shared libraries work correctly.""" + +from __future__ import print_function + + +import unittest2 +import lldb +from lldbsuite.test.lldbtest import * +import lldbsuite.test.lldbutil as lldbutil + + +class TestMoveNearest(TestBase): + + mydir = TestBase.compute_mydir(__file__) + NO_DEBUG_INFO_TESTCASE = True + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number to break inside main(). + self.source = 'foo.h' + self.line1 = line_number(self.source, '// !BR1') + self.line2 = line_number(self.source, '// !BR2') + + def tearDown(self): + self.runCmd("settings clear target.move-to-nearest-code") + TestBase.tearDown(self) + + def test(self): + """Test that target.move-to-nearest code setting behaves properly in the + presence of multiple modules""" + + self.build() + target = self.dbg.CreateTarget("a.out") + self.assertTrue(target, VALID_TARGET) + + # Regardless of the setting value the breakpoint should have exactly one + # location + self.runCmd("settings set target.move-to-nearest-code true") + lldbutil.run_break_set_by_file_and_line(self, self.source, self.line1, + loc_exact=True) + lldbutil.run_break_set_by_file_and_line(self, self.source, self.line2, + loc_exact=True) + + self.runCmd("settings set target.move-to-nearest-code false") + lldbutil.run_break_set_by_file_and_line(self, self.source, self.line1, + loc_exact=True) + lldbutil.run_break_set_by_file_and_line(self, self.source, self.line2, + loc_exact=True) Index: packages/Python/lldbsuite/test/functionalities/breakpoint/move_nearest/Makefile =================================================================== --- /dev/null +++ packages/Python/lldbsuite/test/functionalities/breakpoint/move_nearest/Makefile @@ -0,0 +1,8 @@ +LEVEL = ../../../make + +DYLIB_NAME := foo +DYLIB_CXX_SOURCES := foo.cpp +CXX_SOURCES := main.cpp +CFLAGS_EXTRAS += -fPIC + +include $(LEVEL)/Makefile.rules
_______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits