| """ | |
| Test the WasHit feature of scripted breakpoints | |
| """ | |
| import os | |
| import lldb | |
| import lldbsuite.test.lldbutil as lldbutil | |
| from lldbsuite.test.decorators import * | |
| from lldbsuite.test.lldbtest import * | |
| class TestWasHit(TestBase): | |
| NO_DEBUG_INFO_TESTCASE = True | |
| @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24528") | |
| def test_was_hit_resolver(self): | |
| """Use facade breakpoints to emulate hitting some locations""" | |
| self.build() | |
| self.do_test() | |
| def make_target_and_import(self): | |
| target = lldbutil.run_to_breakpoint_make_target(self) | |
| self.import_resolver_script() | |
| return target | |
| def import_resolver_script(self): | |
| interp = self.dbg.GetCommandInterpreter() | |
| error = lldb.SBError() | |
| script_name = os.path.join(self.getSourceDir(), "bkpt_resolver.py") | |
| command = "command script import " + script_name | |
| self.runCmd(command) | |
| def make_extra_args(self, sym_name, num_locs, loc_to_miss): | |
| return f" -k symbol -v {sym_name} -k num_locs -v {num_locs} -k loc_to_miss -v {loc_to_miss} " | |
| def do_test(self): | |
| """This reads in a python file and sets a breakpoint using it.""" | |
| target = self.make_target_and_import() | |
| extra_args = self.make_extra_args("stop_symbol", 4, 2) | |
| bkpt_no = lldbutil.run_break_set_by_script( | |
| self, "bkpt_resolver.FacadeExample", extra_args, 4 | |
| ) | |
| # Make sure the help text shows up in the "break list" output: | |
| self.expect( | |
| "break list", | |
| substrs=["I am a facade resolver - sym: stop_symbol - num_locs: 4"], | |
| msg="Help is listed in break list", | |
| ) | |
| bkpt = target.FindBreakpointByID(bkpt_no) | |
| self.assertTrue(bkpt.IsValid(), "Found the right breakpoint") | |
| # Now continue. We should hit locations 1, 3 and 4: | |
| (target, process, thread, bkpt) = lldbutil.run_to_breakpoint_do_run( | |
| self, target, bkpt | |
| ) | |
| # This location should be bkpt_no.1: | |
| self.assertEqual( | |
| thread.stop_reason_data[0], bkpt_no, "Hit the right breakpoint" | |
| ) | |
| self.assertEqual(thread.stop_reason_data[1], 1, "First location hit is 1") | |
| # Check that we did increment our global: | |
| values = target.FindGlobalVariables("g_change_me", 2, lldb.eSymbolTypeCode) | |
| self.assertEqual(values.GetSize(), 1, "Got the change me global") | |
| change_me = values.GetValueAtIndex(0) | |
| change_me_value = 1 | |
| self.assertEqual( | |
| change_me.signed, change_me_value, "g_change_me had the right value" | |
| ) | |
| for loc in [3, 4]: | |
| process.Continue() | |
| self.assertEqual( | |
| thread.stop_reason, lldb.eStopReasonBreakpoint, "Hit breakpoint" | |
| ) | |
| self.assertEqual( | |
| thread.stop_reason_data[0], bkpt_no, "Hit the right breakpoint" | |
| ) | |
| self.assertEqual( | |
| thread.stop_reason_data[1], loc, f"Hit the right location: {loc}" | |
| ) | |
| change_me_value += 1 | |
| self.assertEqual( | |
| change_me.signed, change_me_value, "g_change_me was updated correctly" | |
| ) | |
| # At this point we should have hit three of the four locations, and not location 1.2. | |
| # Check that that is true, and that the descriptions for the location are the ones | |
| # the resolver provided. | |
| self.assertEqual(bkpt.hit_count, 3, "Hit three locations") | |
| for loc_id in range(1, 4): | |
| bkpt_loc = bkpt.FindLocationByID(loc_id) | |
| self.assertTrue(bkpt_loc.IsValid(), f"{loc_id} was invalid.") | |
| if loc_id != 2: | |
| self.assertEqual( | |
| bkpt_loc.hit_count, 1, f"Loc {loc_id} hit count was wrong" | |
| ) | |
| else: | |
| self.assertEqual(bkpt_loc.hit_count, 0, "We didn't skip loc 2") | |
| stream = lldb.SBStream() | |
| self.assertTrue( | |
| bkpt_loc.GetDescription(stream, lldb.eDescriptionLevelFull), | |
| f"Didn't get description for {loc_id}", | |
| ) | |
| self.assertIn( | |
| f"Location index: {loc_id}", | |
| stream.GetData(), | |
| f"Wrong desciption for {loc_id}", | |
| ) |