""" Test lldb breakpoint ids. """ import lldb from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * from lldbsuite.test import lldbutil class TestCPPBreakpointLocations(TestBase): @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24764") def test(self): self.do_test(dict()) @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24764") @skipIf(compiler=no_match("clang")) @skipIf(compiler_version=["<", "15.0"]) def test_simple_template_names(self): self.do_test(dict(CFLAGS_EXTRAS="-gsimple-template-names")) def do_test(self, debug_flags): self.build(dictionary=debug_flags) self.breakpoint_id_tests() def verify_breakpoint_locations(self, target, bp_dict): name = bp_dict["name"] names = bp_dict["loc_names"] bp = target.BreakpointCreateByName(name) self.assertEquals( bp.GetNumLocations(), len(names), "Make sure we find the right number of breakpoint locations for {}".format( name ), ) bp_loc_names = list() for bp_loc in bp: bp_loc_names.append(bp_loc.GetAddress().GetFunction().GetName()) for name in names: found = name in bp_loc_names if not found: print("Didn't find '%s' in: %s" % (name, bp_loc_names)) self.assertTrue(found, "Make sure we find all required locations") def breakpoint_id_tests(self): # Create a target by the debugger. exe = self.getBuildArtifact("a.out") target = self.dbg.CreateTarget(exe) self.assertTrue(target, VALID_TARGET) bp_dicts = [ { "name": "func1", "loc_names": ["a::c::func1()", "aa::cc::func1()", "b::c::func1()"], }, { "name": "func2", "loc_names": ["a::c::func2()", "aa::cc::func2()", "c::d::func2()"], }, { "name": "func3", "loc_names": [ "a::c::func3()", "aa::cc::func3()", "b::c::func3()", "c::d::func3()", ], }, {"name": "c::func1", "loc_names": ["a::c::func1()", "b::c::func1()"]}, {"name": "c::func2", "loc_names": ["a::c::func2()"]}, {"name": "c::func3", "loc_names": ["a::c::func3()", "b::c::func3()"]}, {"name": "a::c::func1", "loc_names": ["a::c::func1()"]}, {"name": "b::c::func1", "loc_names": ["b::c::func1()"]}, {"name": "c::d::func2", "loc_names": ["c::d::func2()"]}, {"name": "a::c::func1()", "loc_names": ["a::c::func1()"]}, {"name": "b::c::func1()", "loc_names": ["b::c::func1()"]}, {"name": "c::d::func2()", "loc_names": ["c::d::func2()"]}, # Template cases {"name": "func", "loc_names": []}, {"name": "Foo::func", "loc_names": []}, {"name": "ns::Foo::func", "loc_names": []}, {"name": "func", "loc_names": ["auto ns::Foo::func()"]}, { "name": "Foo::func", "loc_names": ["auto ns::Foo::func()"], }, { "name": "ns::Foo::func", "loc_names": ["auto ns::Foo::func()"], }, { "name": "func", "loc_names": [ "auto ns::Foo::func()", "auto ns::Foo::func>()", ], }, {"name": "operator", "loc_names": []}, { "name": "ns::Foo::operator bool", "loc_names": ["ns::Foo::operator bool()"], }, { "name": "operator a::c", "loc_names": ["ns::Foo::operator a::c()"], }, { "name": "operator ns::Foo", "loc_names": ["ns::Foo::operator ns::Foo>()"], }, {"name": "operator<<", "loc_names": []}, { "name": "operator<<", "loc_names": ["void ns::Foo::operator<<(int)"], }, { "name": "ns::Foo::operator<<", "loc_names": [ "void ns::Foo::operator<<(int)", "void ns::Foo::operator<<>(ns::Foo)", ], }, {"name": "g", "loc_names": []}, {"name": "g", "loc_names": ["void ns::g()"]}, {"name": "g", "loc_names": ["void ns::g()"]}, {"name": "g", "loc_names": ["void ns::g()", "void ns::g()"]}, {"name": "ns::g", "loc_names": []}, {"name": "ns::g", "loc_names": ["void ns::g()"]}, {"name": "ns::g", "loc_names": ["void ns::g()"]}, {"name": "ns::g", "loc_names": ["void ns::g()", "void ns::g()"]}, ] for bp_dict in bp_dicts: self.verify_breakpoint_locations(target, bp_dict) @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24764") def test_destructors(self): self.build() exe = self.getBuildArtifact("a.out") target = self.dbg.CreateTarget(exe) # Don't skip prologue, so we can check the breakpoint address more # easily self.runCmd("settings set target.skip-prologue false") try: names = ["~c", "c::~c", "c::~c()"] loc_names = {"a::c::~c()", "b::c::~c()"} # TODO: For windows targets we should put windows mangled names # here symbols = ["_ZN1a1cD1Ev", "_ZN1a1cD2Ev", "_ZN1b1cD1Ev", "_ZN1b1cD2Ev"] for name in names: bp = target.BreakpointCreateByName(name) bp_loc_names = { bp_loc.GetAddress().GetFunction().GetName() for bp_loc in bp } self.assertEquals( bp_loc_names, loc_names, "Breakpoint set on the correct symbol" ) bp_addresses = {bp_loc.GetLoadAddress() for bp_loc in bp} symbol_addresses = set() for symbol in symbols: sc_list = target.FindSymbols(symbol, lldb.eSymbolTypeCode) self.assertEquals(sc_list.GetSize(), 1, "Found symbol " + symbol) symbol = sc_list.GetContextAtIndex(0).GetSymbol() symbol_addresses.add( symbol.GetStartAddress().GetLoadAddress(target) ) self.assertEquals( symbol_addresses, bp_addresses, "Breakpoint set on correct address" ) finally: self.runCmd("settings clear target.skip-prologue")