199451b44SJordan Rupprecht""" 299451b44SJordan RupprechtTest setting breakpoints using a scripted resolver 399451b44SJordan Rupprecht""" 499451b44SJordan Rupprecht 599451b44SJordan Rupprechtimport os 699451b44SJordan Rupprechtimport lldb 799451b44SJordan Rupprechtimport lldbsuite.test.lldbutil as lldbutil 899451b44SJordan Rupprechtfrom lldbsuite.test.decorators import * 999451b44SJordan Rupprechtfrom lldbsuite.test.lldbtest import * 1099451b44SJordan Rupprecht 1199451b44SJordan Rupprecht 1299451b44SJordan Rupprechtclass TestScriptedResolver(TestBase): 1399451b44SJordan Rupprecht 1499451b44SJordan Rupprecht mydir = TestBase.compute_mydir(__file__) 1599451b44SJordan Rupprecht 1699451b44SJordan Rupprecht NO_DEBUG_INFO_TESTCASE = True 1799451b44SJordan Rupprecht 1899451b44SJordan Rupprecht @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24528") 1999451b44SJordan Rupprecht def test_scripted_resolver(self): 2099451b44SJordan Rupprecht """Use a scripted resolver to set a by symbol name breakpoint""" 2199451b44SJordan Rupprecht self.build() 2299451b44SJordan Rupprecht self.do_test() 2399451b44SJordan Rupprecht 2499451b44SJordan Rupprecht @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24528") 2599451b44SJordan Rupprecht def test_search_depths(self): 2699451b44SJordan Rupprecht """ Make sure we are called at the right depths depending on what we return 2799451b44SJordan Rupprecht from __get_depth__""" 2899451b44SJordan Rupprecht self.build() 2999451b44SJordan Rupprecht self.do_test_depths() 3099451b44SJordan Rupprecht 3199451b44SJordan Rupprecht @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24528") 3299451b44SJordan Rupprecht def test_command_line(self): 3399451b44SJordan Rupprecht """ Test setting a resolver breakpoint from the command line """ 3499451b44SJordan Rupprecht self.build() 3599451b44SJordan Rupprecht self.do_test_cli() 3699451b44SJordan Rupprecht 3799451b44SJordan Rupprecht def test_bad_command_lines(self): 3899451b44SJordan Rupprecht """Make sure we get appropriate errors when we give invalid key/value 3999451b44SJordan Rupprecht options""" 4099451b44SJordan Rupprecht self.build() 4199451b44SJordan Rupprecht self.do_test_bad_options() 4299451b44SJordan Rupprecht 43*185ef697STatyana Krasnukha @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24528") 44*185ef697STatyana Krasnukha def test_copy_from_dummy_target(self): 45*185ef697STatyana Krasnukha """Make sure we don't crash during scripted breakpoint copy from dummy target""" 46*185ef697STatyana Krasnukha self.build() 47*185ef697STatyana Krasnukha self.do_test_copy_from_dummy_target() 48*185ef697STatyana Krasnukha 4999451b44SJordan Rupprecht def make_target_and_import(self): 50*185ef697STatyana Krasnukha target = self.make_target() 51*185ef697STatyana Krasnukha self.import_resolver_script() 52*185ef697STatyana Krasnukha return target 53*185ef697STatyana Krasnukha 54*185ef697STatyana Krasnukha def make_target(self): 55*185ef697STatyana Krasnukha return lldbutil.run_to_breakpoint_make_target(self) 56*185ef697STatyana Krasnukha 57*185ef697STatyana Krasnukha def import_resolver_script(self): 5899451b44SJordan Rupprecht interp = self.dbg.GetCommandInterpreter() 5999451b44SJordan Rupprecht error = lldb.SBError() 6099451b44SJordan Rupprecht 6199451b44SJordan Rupprecht script_name = os.path.join(self.getSourceDir(), "resolver.py") 6299451b44SJordan Rupprecht source_name = os.path.join(self.getSourceDir(), "main.c") 6399451b44SJordan Rupprecht 6499451b44SJordan Rupprecht command = "command script import " + script_name 6599451b44SJordan Rupprecht result = lldb.SBCommandReturnObject() 6699451b44SJordan Rupprecht interp.HandleCommand(command, result) 6799451b44SJordan Rupprecht self.assertTrue(result.Succeeded(), "com scr imp failed: %s"%(result.GetError())) 6899451b44SJordan Rupprecht 6999451b44SJordan Rupprecht def make_extra_args(self): 7099451b44SJordan Rupprecht json_string = '{"symbol":"break_on_me", "test1": "value1"}' 7199451b44SJordan Rupprecht json_stream = lldb.SBStream() 7299451b44SJordan Rupprecht json_stream.Print(json_string) 7399451b44SJordan Rupprecht extra_args = lldb.SBStructuredData() 7499451b44SJordan Rupprecht error = extra_args.SetFromJSON(json_stream) 7599451b44SJordan Rupprecht self.assertTrue(error.Success(), "Error making SBStructuredData: %s"%(error.GetCString())) 7699451b44SJordan Rupprecht return extra_args 7799451b44SJordan Rupprecht 7899451b44SJordan Rupprecht def do_test(self): 7999451b44SJordan Rupprecht """This reads in a python file and sets a breakpoint using it.""" 8099451b44SJordan Rupprecht 8199451b44SJordan Rupprecht target = self.make_target_and_import() 8299451b44SJordan Rupprecht extra_args = self.make_extra_args() 8399451b44SJordan Rupprecht 8499451b44SJordan Rupprecht file_list = lldb.SBFileSpecList() 8599451b44SJordan Rupprecht module_list = lldb.SBFileSpecList() 8699451b44SJordan Rupprecht 8799451b44SJordan Rupprecht # Make breakpoints with this resolver using different filters, first ones that will take: 8899451b44SJordan Rupprecht right = [] 8999451b44SJordan Rupprecht # one with no file or module spec - this one should fire: 9099451b44SJordan Rupprecht right.append(target.BreakpointCreateFromScript("resolver.Resolver", extra_args, module_list, file_list)) 9199451b44SJordan Rupprecht 9299451b44SJordan Rupprecht # one with the right source file and no module - should also fire: 9399451b44SJordan Rupprecht file_list.Append(lldb.SBFileSpec("main.c")) 9499451b44SJordan Rupprecht right.append(target.BreakpointCreateFromScript("resolver.Resolver", extra_args, module_list, file_list)) 9599451b44SJordan Rupprecht # Make sure the help text shows up in the "break list" output: 9699451b44SJordan Rupprecht self.expect("break list", substrs=["I am a python breakpoint resolver"], msg="Help is listed in break list") 9799451b44SJordan Rupprecht 9899451b44SJordan Rupprecht # one with the right source file and right module - should also fire: 9999451b44SJordan Rupprecht module_list.Append(lldb.SBFileSpec("a.out")) 10099451b44SJordan Rupprecht right.append(target.BreakpointCreateFromScript("resolver.Resolver", extra_args, module_list, file_list)) 10199451b44SJordan Rupprecht 10299451b44SJordan Rupprecht # And one with no source file but the right module: 10399451b44SJordan Rupprecht file_list.Clear() 10499451b44SJordan Rupprecht right.append(target.BreakpointCreateFromScript("resolver.Resolver", extra_args, module_list, file_list)) 10599451b44SJordan Rupprecht 10699451b44SJordan Rupprecht # Make sure these all got locations: 10799451b44SJordan Rupprecht for i in range (0, len(right)): 10899451b44SJordan Rupprecht self.assertTrue(right[i].GetNumLocations() >= 1, "Breakpoint %d has no locations."%(i)) 10999451b44SJordan Rupprecht 11099451b44SJordan Rupprecht # Now some ones that won't take: 11199451b44SJordan Rupprecht 11299451b44SJordan Rupprecht module_list.Clear() 11399451b44SJordan Rupprecht file_list.Clear() 11499451b44SJordan Rupprecht wrong = [] 11599451b44SJordan Rupprecht 11699451b44SJordan Rupprecht # one with the wrong module - should not fire: 11799451b44SJordan Rupprecht module_list.Append(lldb.SBFileSpec("noSuchModule")) 11899451b44SJordan Rupprecht wrong.append(target.BreakpointCreateFromScript("resolver.Resolver", extra_args, module_list, file_list)) 11999451b44SJordan Rupprecht 12099451b44SJordan Rupprecht # one with the wrong file - also should not fire: 12199451b44SJordan Rupprecht file_list.Clear() 12299451b44SJordan Rupprecht module_list.Clear() 12399451b44SJordan Rupprecht file_list.Append(lldb.SBFileSpec("noFileOfThisName.xxx")) 12499451b44SJordan Rupprecht wrong.append(target.BreakpointCreateFromScript("resolver.Resolver", extra_args, module_list, file_list)) 12599451b44SJordan Rupprecht 12699451b44SJordan Rupprecht # Now make sure the CU level iteration obeys the file filters: 12799451b44SJordan Rupprecht file_list.Clear() 12899451b44SJordan Rupprecht module_list.Clear() 12999451b44SJordan Rupprecht file_list.Append(lldb.SBFileSpec("no_such_file.xxx")) 13099451b44SJordan Rupprecht wrong.append(target.BreakpointCreateFromScript("resolver.ResolverCUDepth", extra_args, module_list, file_list)) 13199451b44SJordan Rupprecht 13299451b44SJordan Rupprecht # And the Module filters: 13399451b44SJordan Rupprecht file_list.Clear() 13499451b44SJordan Rupprecht module_list.Clear() 13599451b44SJordan Rupprecht module_list.Append(lldb.SBFileSpec("NoSuchModule.dylib")) 13699451b44SJordan Rupprecht wrong.append(target.BreakpointCreateFromScript("resolver.ResolverCUDepth", extra_args, module_list, file_list)) 13799451b44SJordan Rupprecht 13899451b44SJordan Rupprecht # Now make sure the Function level iteration obeys the file filters: 13999451b44SJordan Rupprecht file_list.Clear() 14099451b44SJordan Rupprecht module_list.Clear() 14199451b44SJordan Rupprecht file_list.Append(lldb.SBFileSpec("no_such_file.xxx")) 14299451b44SJordan Rupprecht wrong.append(target.BreakpointCreateFromScript("resolver.ResolverFuncDepth", extra_args, module_list, file_list)) 14399451b44SJordan Rupprecht 14499451b44SJordan Rupprecht # And the Module filters: 14599451b44SJordan Rupprecht file_list.Clear() 14699451b44SJordan Rupprecht module_list.Clear() 14799451b44SJordan Rupprecht module_list.Append(lldb.SBFileSpec("NoSuchModule.dylib")) 14899451b44SJordan Rupprecht wrong.append(target.BreakpointCreateFromScript("resolver.ResolverFuncDepth", extra_args, module_list, file_list)) 14999451b44SJordan Rupprecht 15099451b44SJordan Rupprecht # Make sure these didn't get locations: 15199451b44SJordan Rupprecht for i in range(0, len(wrong)): 15299451b44SJordan Rupprecht self.assertEqual(wrong[i].GetNumLocations(), 0, "Breakpoint %d has locations."%(i)) 15399451b44SJordan Rupprecht 15499451b44SJordan Rupprecht # Now run to main and ensure we hit the breakpoints we should have: 15599451b44SJordan Rupprecht 15699451b44SJordan Rupprecht lldbutil.run_to_breakpoint_do_run(self, target, right[0]) 15799451b44SJordan Rupprecht 15899451b44SJordan Rupprecht # Test the hit counts: 15999451b44SJordan Rupprecht for i in range(0, len(right)): 16099451b44SJordan Rupprecht self.assertEqual(right[i].GetHitCount(), 1, "Breakpoint %d has the wrong hit count"%(i)) 16199451b44SJordan Rupprecht 16299451b44SJordan Rupprecht for i in range(0, len(wrong)): 16399451b44SJordan Rupprecht self.assertEqual(wrong[i].GetHitCount(), 0, "Breakpoint %d has the wrong hit count"%(i)) 16499451b44SJordan Rupprecht 16599451b44SJordan Rupprecht def do_test_depths(self): 16699451b44SJordan Rupprecht """This test uses a class variable in resolver.Resolver which gets set to 1 if we saw 16799451b44SJordan Rupprecht compile unit and 2 if we only saw modules. If the search depth is module, you get passed just 16899451b44SJordan Rupprecht the modules with no comp_unit. If the depth is comp_unit you get comp_units. So we can use 16999451b44SJordan Rupprecht this to test that our callback gets called at the right depth.""" 17099451b44SJordan Rupprecht 17199451b44SJordan Rupprecht target = self.make_target_and_import() 17299451b44SJordan Rupprecht extra_args = self.make_extra_args() 17399451b44SJordan Rupprecht 17499451b44SJordan Rupprecht file_list = lldb.SBFileSpecList() 17599451b44SJordan Rupprecht module_list = lldb.SBFileSpecList() 17699451b44SJordan Rupprecht module_list.Append(lldb.SBFileSpec("a.out")) 17799451b44SJordan Rupprecht 17899451b44SJordan Rupprecht # Make a breakpoint that has no __get_depth__, check that that is converted to eSearchDepthModule: 17999451b44SJordan Rupprecht bkpt = target.BreakpointCreateFromScript("resolver.Resolver", extra_args, module_list, file_list) 18099451b44SJordan Rupprecht self.assertTrue(bkpt.GetNumLocations() > 0, "Resolver got no locations.") 18199451b44SJordan Rupprecht self.expect("script print(resolver.Resolver.got_files)", substrs=["2"], msg="Was only passed modules") 18299451b44SJordan Rupprecht 18399451b44SJordan Rupprecht # Make a breakpoint that asks for modules, check that we didn't get any files: 18499451b44SJordan Rupprecht bkpt = target.BreakpointCreateFromScript("resolver.ResolverModuleDepth", extra_args, module_list, file_list) 18599451b44SJordan Rupprecht self.assertTrue(bkpt.GetNumLocations() > 0, "ResolverModuleDepth got no locations.") 18699451b44SJordan Rupprecht self.expect("script print(resolver.Resolver.got_files)", substrs=["2"], msg="Was only passed modules") 18799451b44SJordan Rupprecht 18899451b44SJordan Rupprecht # Make a breakpoint that asks for compile units, check that we didn't get any files: 18999451b44SJordan Rupprecht bkpt = target.BreakpointCreateFromScript("resolver.ResolverCUDepth", extra_args, module_list, file_list) 19099451b44SJordan Rupprecht self.assertTrue(bkpt.GetNumLocations() > 0, "ResolverCUDepth got no locations.") 19199451b44SJordan Rupprecht self.expect("script print(resolver.Resolver.got_files)", substrs=["1"], msg="Was passed compile units") 19299451b44SJordan Rupprecht 19399451b44SJordan Rupprecht # Make a breakpoint that returns a bad value - we should convert that to "modules" so check that: 19499451b44SJordan Rupprecht bkpt = target.BreakpointCreateFromScript("resolver.ResolverBadDepth", extra_args, module_list, file_list) 19599451b44SJordan Rupprecht self.assertTrue(bkpt.GetNumLocations() > 0, "ResolverBadDepth got no locations.") 19699451b44SJordan Rupprecht self.expect("script print(resolver.Resolver.got_files)", substrs=["2"], msg="Was only passed modules") 19799451b44SJordan Rupprecht 19899451b44SJordan Rupprecht # Make a breakpoint that searches at function depth: 19999451b44SJordan Rupprecht bkpt = target.BreakpointCreateFromScript("resolver.ResolverFuncDepth", extra_args, module_list, file_list) 20099451b44SJordan Rupprecht self.assertTrue(bkpt.GetNumLocations() > 0, "ResolverFuncDepth got no locations.") 20199451b44SJordan Rupprecht self.expect("script print(resolver.Resolver.got_files)", substrs=["3"], msg="Was only passed modules") 20299451b44SJordan Rupprecht self.expect("script print(resolver.Resolver.func_list)", substrs=['test_func', 'break_on_me', 'main'], msg="Saw all the functions") 20399451b44SJordan Rupprecht 20499451b44SJordan Rupprecht def do_test_cli(self): 20599451b44SJordan Rupprecht target = self.make_target_and_import() 20699451b44SJordan Rupprecht 20799451b44SJordan Rupprecht lldbutil.run_break_set_by_script(self, "resolver.Resolver", extra_options="-k symbol -v break_on_me") 20899451b44SJordan Rupprecht 20999451b44SJordan Rupprecht # Make sure setting a resolver breakpoint doesn't pollute further breakpoint setting 21099451b44SJordan Rupprecht # by checking the description of a regular file & line breakpoint to make sure it 21199451b44SJordan Rupprecht # doesn't mention the Python Resolver function: 21299451b44SJordan Rupprecht bkpt_no = lldbutil.run_break_set_by_file_and_line(self, "main.c", 12) 21399451b44SJordan Rupprecht bkpt = target.FindBreakpointByID(bkpt_no) 21499451b44SJordan Rupprecht strm = lldb.SBStream() 21599451b44SJordan Rupprecht bkpt.GetDescription(strm, False) 21699451b44SJordan Rupprecht used_resolver = "I am a python breakpoint resolver" in strm.GetData() 21799451b44SJordan Rupprecht self.assertFalse(used_resolver, "Found the resolver description in the file & line breakpoint description.") 21899451b44SJordan Rupprecht 21999451b44SJordan Rupprecht # Also make sure the breakpoint was where we expected: 22099451b44SJordan Rupprecht bp_loc = bkpt.GetLocationAtIndex(0) 22199451b44SJordan Rupprecht bp_sc = bp_loc.GetAddress().GetSymbolContext(lldb.eSymbolContextEverything) 22299451b44SJordan Rupprecht bp_se = bp_sc.GetLineEntry() 22399451b44SJordan Rupprecht self.assertEqual(bp_se.GetLine(), 12, "Got the right line number") 22499451b44SJordan Rupprecht self.assertEqual(bp_se.GetFileSpec().GetFilename(), "main.c", "Got the right filename") 22599451b44SJordan Rupprecht 22699451b44SJordan Rupprecht def do_test_bad_options(self): 22799451b44SJordan Rupprecht target = self.make_target_and_import() 22899451b44SJordan Rupprecht 22999451b44SJordan Rupprecht self.expect("break set -P resolver.Resolver -k a_key", error = True, msg="Missing value at end", 23099451b44SJordan Rupprecht substrs=['Key: "a_key" missing value']) 23199451b44SJordan Rupprecht self.expect("break set -P resolver.Resolver -v a_value", error = True, msg="Missing key at end", 23299451b44SJordan Rupprecht substrs=['Value: "a_value" missing matching key']) 23399451b44SJordan Rupprecht self.expect("break set -P resolver.Resolver -v a_value -k a_key -v another_value", error = True, msg="Missing key among args", 23499451b44SJordan Rupprecht substrs=['Value: "a_value" missing matching key']) 23599451b44SJordan Rupprecht self.expect("break set -P resolver.Resolver -k a_key -k a_key -v another_value", error = True, msg="Missing value among args", 23699451b44SJordan Rupprecht substrs=['Key: "a_key" missing value']) 237*185ef697STatyana Krasnukha 238*185ef697STatyana Krasnukha def do_test_copy_from_dummy_target(self): 239*185ef697STatyana Krasnukha # Import breakpoint scripted resolver. 240*185ef697STatyana Krasnukha self.import_resolver_script() 241*185ef697STatyana Krasnukha 242*185ef697STatyana Krasnukha # Create a scripted breakpoint. 243*185ef697STatyana Krasnukha self.runCmd("breakpoint set -P resolver.Resolver -k symbol -v break_on_me", 244*185ef697STatyana Krasnukha BREAKPOINT_CREATED) 245*185ef697STatyana Krasnukha 246*185ef697STatyana Krasnukha # This is the function to remove breakpoints from the dummy target 247*185ef697STatyana Krasnukha # to get a clean state for the next test case. 248*185ef697STatyana Krasnukha def cleanup(): 249*185ef697STatyana Krasnukha self.runCmd('breakpoint delete -D -f', check=False) 250*185ef697STatyana Krasnukha self.runCmd('breakpoint list', check=False) 251*185ef697STatyana Krasnukha 252*185ef697STatyana Krasnukha # Execute the cleanup function during test case tear down. 253*185ef697STatyana Krasnukha self.addTearDownHook(cleanup) 254*185ef697STatyana Krasnukha 255*185ef697STatyana Krasnukha # Check that target creating doesn't crash. 256*185ef697STatyana Krasnukha target = self.make_target() 257