1*99451b44SJordan Rupprecht""" 2*99451b44SJordan RupprechtTest setting breakpoints using a scripted resolver 3*99451b44SJordan Rupprecht""" 4*99451b44SJordan Rupprecht 5*99451b44SJordan Rupprechtimport os 6*99451b44SJordan Rupprechtimport lldb 7*99451b44SJordan Rupprechtimport lldbsuite.test.lldbutil as lldbutil 8*99451b44SJordan Rupprechtfrom lldbsuite.test.decorators import * 9*99451b44SJordan Rupprechtfrom lldbsuite.test.lldbtest import * 10*99451b44SJordan Rupprecht 11*99451b44SJordan Rupprecht 12*99451b44SJordan Rupprechtclass TestScriptedResolver(TestBase): 13*99451b44SJordan Rupprecht 14*99451b44SJordan Rupprecht mydir = TestBase.compute_mydir(__file__) 15*99451b44SJordan Rupprecht 16*99451b44SJordan Rupprecht NO_DEBUG_INFO_TESTCASE = True 17*99451b44SJordan Rupprecht 18*99451b44SJordan Rupprecht @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24528") 19*99451b44SJordan Rupprecht def test_scripted_resolver(self): 20*99451b44SJordan Rupprecht """Use a scripted resolver to set a by symbol name breakpoint""" 21*99451b44SJordan Rupprecht self.build() 22*99451b44SJordan Rupprecht self.do_test() 23*99451b44SJordan Rupprecht 24*99451b44SJordan Rupprecht @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24528") 25*99451b44SJordan Rupprecht def test_search_depths(self): 26*99451b44SJordan Rupprecht """ Make sure we are called at the right depths depending on what we return 27*99451b44SJordan Rupprecht from __get_depth__""" 28*99451b44SJordan Rupprecht self.build() 29*99451b44SJordan Rupprecht self.do_test_depths() 30*99451b44SJordan Rupprecht 31*99451b44SJordan Rupprecht @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24528") 32*99451b44SJordan Rupprecht def test_command_line(self): 33*99451b44SJordan Rupprecht """ Test setting a resolver breakpoint from the command line """ 34*99451b44SJordan Rupprecht self.build() 35*99451b44SJordan Rupprecht self.do_test_cli() 36*99451b44SJordan Rupprecht 37*99451b44SJordan Rupprecht def test_bad_command_lines(self): 38*99451b44SJordan Rupprecht """Make sure we get appropriate errors when we give invalid key/value 39*99451b44SJordan Rupprecht options""" 40*99451b44SJordan Rupprecht self.build() 41*99451b44SJordan Rupprecht self.do_test_bad_options() 42*99451b44SJordan Rupprecht 43*99451b44SJordan Rupprecht def make_target_and_import(self): 44*99451b44SJordan Rupprecht target = lldbutil.run_to_breakpoint_make_target(self) 45*99451b44SJordan Rupprecht interp = self.dbg.GetCommandInterpreter() 46*99451b44SJordan Rupprecht error = lldb.SBError() 47*99451b44SJordan Rupprecht 48*99451b44SJordan Rupprecht script_name = os.path.join(self.getSourceDir(), "resolver.py") 49*99451b44SJordan Rupprecht source_name = os.path.join(self.getSourceDir(), "main.c") 50*99451b44SJordan Rupprecht 51*99451b44SJordan Rupprecht command = "command script import " + script_name 52*99451b44SJordan Rupprecht result = lldb.SBCommandReturnObject() 53*99451b44SJordan Rupprecht interp.HandleCommand(command, result) 54*99451b44SJordan Rupprecht self.assertTrue(result.Succeeded(), "com scr imp failed: %s"%(result.GetError())) 55*99451b44SJordan Rupprecht return target 56*99451b44SJordan Rupprecht 57*99451b44SJordan Rupprecht def make_extra_args(self): 58*99451b44SJordan Rupprecht json_string = '{"symbol":"break_on_me", "test1": "value1"}' 59*99451b44SJordan Rupprecht json_stream = lldb.SBStream() 60*99451b44SJordan Rupprecht json_stream.Print(json_string) 61*99451b44SJordan Rupprecht extra_args = lldb.SBStructuredData() 62*99451b44SJordan Rupprecht error = extra_args.SetFromJSON(json_stream) 63*99451b44SJordan Rupprecht self.assertTrue(error.Success(), "Error making SBStructuredData: %s"%(error.GetCString())) 64*99451b44SJordan Rupprecht return extra_args 65*99451b44SJordan Rupprecht 66*99451b44SJordan Rupprecht def do_test(self): 67*99451b44SJordan Rupprecht """This reads in a python file and sets a breakpoint using it.""" 68*99451b44SJordan Rupprecht 69*99451b44SJordan Rupprecht target = self.make_target_and_import() 70*99451b44SJordan Rupprecht extra_args = self.make_extra_args() 71*99451b44SJordan Rupprecht 72*99451b44SJordan Rupprecht file_list = lldb.SBFileSpecList() 73*99451b44SJordan Rupprecht module_list = lldb.SBFileSpecList() 74*99451b44SJordan Rupprecht 75*99451b44SJordan Rupprecht # Make breakpoints with this resolver using different filters, first ones that will take: 76*99451b44SJordan Rupprecht right = [] 77*99451b44SJordan Rupprecht # one with no file or module spec - this one should fire: 78*99451b44SJordan Rupprecht right.append(target.BreakpointCreateFromScript("resolver.Resolver", extra_args, module_list, file_list)) 79*99451b44SJordan Rupprecht 80*99451b44SJordan Rupprecht # one with the right source file and no module - should also fire: 81*99451b44SJordan Rupprecht file_list.Append(lldb.SBFileSpec("main.c")) 82*99451b44SJordan Rupprecht right.append(target.BreakpointCreateFromScript("resolver.Resolver", extra_args, module_list, file_list)) 83*99451b44SJordan Rupprecht # Make sure the help text shows up in the "break list" output: 84*99451b44SJordan Rupprecht self.expect("break list", substrs=["I am a python breakpoint resolver"], msg="Help is listed in break list") 85*99451b44SJordan Rupprecht 86*99451b44SJordan Rupprecht # one with the right source file and right module - should also fire: 87*99451b44SJordan Rupprecht module_list.Append(lldb.SBFileSpec("a.out")) 88*99451b44SJordan Rupprecht right.append(target.BreakpointCreateFromScript("resolver.Resolver", extra_args, module_list, file_list)) 89*99451b44SJordan Rupprecht 90*99451b44SJordan Rupprecht # And one with no source file but the right module: 91*99451b44SJordan Rupprecht file_list.Clear() 92*99451b44SJordan Rupprecht right.append(target.BreakpointCreateFromScript("resolver.Resolver", extra_args, module_list, file_list)) 93*99451b44SJordan Rupprecht 94*99451b44SJordan Rupprecht # Make sure these all got locations: 95*99451b44SJordan Rupprecht for i in range (0, len(right)): 96*99451b44SJordan Rupprecht self.assertTrue(right[i].GetNumLocations() >= 1, "Breakpoint %d has no locations."%(i)) 97*99451b44SJordan Rupprecht 98*99451b44SJordan Rupprecht # Now some ones that won't take: 99*99451b44SJordan Rupprecht 100*99451b44SJordan Rupprecht module_list.Clear() 101*99451b44SJordan Rupprecht file_list.Clear() 102*99451b44SJordan Rupprecht wrong = [] 103*99451b44SJordan Rupprecht 104*99451b44SJordan Rupprecht # one with the wrong module - should not fire: 105*99451b44SJordan Rupprecht module_list.Append(lldb.SBFileSpec("noSuchModule")) 106*99451b44SJordan Rupprecht wrong.append(target.BreakpointCreateFromScript("resolver.Resolver", extra_args, module_list, file_list)) 107*99451b44SJordan Rupprecht 108*99451b44SJordan Rupprecht # one with the wrong file - also should not fire: 109*99451b44SJordan Rupprecht file_list.Clear() 110*99451b44SJordan Rupprecht module_list.Clear() 111*99451b44SJordan Rupprecht file_list.Append(lldb.SBFileSpec("noFileOfThisName.xxx")) 112*99451b44SJordan Rupprecht wrong.append(target.BreakpointCreateFromScript("resolver.Resolver", extra_args, module_list, file_list)) 113*99451b44SJordan Rupprecht 114*99451b44SJordan Rupprecht # Now make sure the CU level iteration obeys the file filters: 115*99451b44SJordan Rupprecht file_list.Clear() 116*99451b44SJordan Rupprecht module_list.Clear() 117*99451b44SJordan Rupprecht file_list.Append(lldb.SBFileSpec("no_such_file.xxx")) 118*99451b44SJordan Rupprecht wrong.append(target.BreakpointCreateFromScript("resolver.ResolverCUDepth", extra_args, module_list, file_list)) 119*99451b44SJordan Rupprecht 120*99451b44SJordan Rupprecht # And the Module filters: 121*99451b44SJordan Rupprecht file_list.Clear() 122*99451b44SJordan Rupprecht module_list.Clear() 123*99451b44SJordan Rupprecht module_list.Append(lldb.SBFileSpec("NoSuchModule.dylib")) 124*99451b44SJordan Rupprecht wrong.append(target.BreakpointCreateFromScript("resolver.ResolverCUDepth", extra_args, module_list, file_list)) 125*99451b44SJordan Rupprecht 126*99451b44SJordan Rupprecht # Now make sure the Function level iteration obeys the file filters: 127*99451b44SJordan Rupprecht file_list.Clear() 128*99451b44SJordan Rupprecht module_list.Clear() 129*99451b44SJordan Rupprecht file_list.Append(lldb.SBFileSpec("no_such_file.xxx")) 130*99451b44SJordan Rupprecht wrong.append(target.BreakpointCreateFromScript("resolver.ResolverFuncDepth", extra_args, module_list, file_list)) 131*99451b44SJordan Rupprecht 132*99451b44SJordan Rupprecht # And the Module filters: 133*99451b44SJordan Rupprecht file_list.Clear() 134*99451b44SJordan Rupprecht module_list.Clear() 135*99451b44SJordan Rupprecht module_list.Append(lldb.SBFileSpec("NoSuchModule.dylib")) 136*99451b44SJordan Rupprecht wrong.append(target.BreakpointCreateFromScript("resolver.ResolverFuncDepth", extra_args, module_list, file_list)) 137*99451b44SJordan Rupprecht 138*99451b44SJordan Rupprecht # Make sure these didn't get locations: 139*99451b44SJordan Rupprecht for i in range(0, len(wrong)): 140*99451b44SJordan Rupprecht self.assertEqual(wrong[i].GetNumLocations(), 0, "Breakpoint %d has locations."%(i)) 141*99451b44SJordan Rupprecht 142*99451b44SJordan Rupprecht # Now run to main and ensure we hit the breakpoints we should have: 143*99451b44SJordan Rupprecht 144*99451b44SJordan Rupprecht lldbutil.run_to_breakpoint_do_run(self, target, right[0]) 145*99451b44SJordan Rupprecht 146*99451b44SJordan Rupprecht # Test the hit counts: 147*99451b44SJordan Rupprecht for i in range(0, len(right)): 148*99451b44SJordan Rupprecht self.assertEqual(right[i].GetHitCount(), 1, "Breakpoint %d has the wrong hit count"%(i)) 149*99451b44SJordan Rupprecht 150*99451b44SJordan Rupprecht for i in range(0, len(wrong)): 151*99451b44SJordan Rupprecht self.assertEqual(wrong[i].GetHitCount(), 0, "Breakpoint %d has the wrong hit count"%(i)) 152*99451b44SJordan Rupprecht 153*99451b44SJordan Rupprecht def do_test_depths(self): 154*99451b44SJordan Rupprecht """This test uses a class variable in resolver.Resolver which gets set to 1 if we saw 155*99451b44SJordan Rupprecht compile unit and 2 if we only saw modules. If the search depth is module, you get passed just 156*99451b44SJordan Rupprecht the modules with no comp_unit. If the depth is comp_unit you get comp_units. So we can use 157*99451b44SJordan Rupprecht this to test that our callback gets called at the right depth.""" 158*99451b44SJordan Rupprecht 159*99451b44SJordan Rupprecht target = self.make_target_and_import() 160*99451b44SJordan Rupprecht extra_args = self.make_extra_args() 161*99451b44SJordan Rupprecht 162*99451b44SJordan Rupprecht file_list = lldb.SBFileSpecList() 163*99451b44SJordan Rupprecht module_list = lldb.SBFileSpecList() 164*99451b44SJordan Rupprecht module_list.Append(lldb.SBFileSpec("a.out")) 165*99451b44SJordan Rupprecht 166*99451b44SJordan Rupprecht # Make a breakpoint that has no __get_depth__, check that that is converted to eSearchDepthModule: 167*99451b44SJordan Rupprecht bkpt = target.BreakpointCreateFromScript("resolver.Resolver", extra_args, module_list, file_list) 168*99451b44SJordan Rupprecht self.assertTrue(bkpt.GetNumLocations() > 0, "Resolver got no locations.") 169*99451b44SJordan Rupprecht self.expect("script print(resolver.Resolver.got_files)", substrs=["2"], msg="Was only passed modules") 170*99451b44SJordan Rupprecht 171*99451b44SJordan Rupprecht # Make a breakpoint that asks for modules, check that we didn't get any files: 172*99451b44SJordan Rupprecht bkpt = target.BreakpointCreateFromScript("resolver.ResolverModuleDepth", extra_args, module_list, file_list) 173*99451b44SJordan Rupprecht self.assertTrue(bkpt.GetNumLocations() > 0, "ResolverModuleDepth got no locations.") 174*99451b44SJordan Rupprecht self.expect("script print(resolver.Resolver.got_files)", substrs=["2"], msg="Was only passed modules") 175*99451b44SJordan Rupprecht 176*99451b44SJordan Rupprecht # Make a breakpoint that asks for compile units, check that we didn't get any files: 177*99451b44SJordan Rupprecht bkpt = target.BreakpointCreateFromScript("resolver.ResolverCUDepth", extra_args, module_list, file_list) 178*99451b44SJordan Rupprecht self.assertTrue(bkpt.GetNumLocations() > 0, "ResolverCUDepth got no locations.") 179*99451b44SJordan Rupprecht self.expect("script print(resolver.Resolver.got_files)", substrs=["1"], msg="Was passed compile units") 180*99451b44SJordan Rupprecht 181*99451b44SJordan Rupprecht # Make a breakpoint that returns a bad value - we should convert that to "modules" so check that: 182*99451b44SJordan Rupprecht bkpt = target.BreakpointCreateFromScript("resolver.ResolverBadDepth", extra_args, module_list, file_list) 183*99451b44SJordan Rupprecht self.assertTrue(bkpt.GetNumLocations() > 0, "ResolverBadDepth got no locations.") 184*99451b44SJordan Rupprecht self.expect("script print(resolver.Resolver.got_files)", substrs=["2"], msg="Was only passed modules") 185*99451b44SJordan Rupprecht 186*99451b44SJordan Rupprecht # Make a breakpoint that searches at function depth: 187*99451b44SJordan Rupprecht bkpt = target.BreakpointCreateFromScript("resolver.ResolverFuncDepth", extra_args, module_list, file_list) 188*99451b44SJordan Rupprecht self.assertTrue(bkpt.GetNumLocations() > 0, "ResolverFuncDepth got no locations.") 189*99451b44SJordan Rupprecht self.expect("script print(resolver.Resolver.got_files)", substrs=["3"], msg="Was only passed modules") 190*99451b44SJordan Rupprecht self.expect("script print(resolver.Resolver.func_list)", substrs=['test_func', 'break_on_me', 'main'], msg="Saw all the functions") 191*99451b44SJordan Rupprecht 192*99451b44SJordan Rupprecht def do_test_cli(self): 193*99451b44SJordan Rupprecht target = self.make_target_and_import() 194*99451b44SJordan Rupprecht 195*99451b44SJordan Rupprecht lldbutil.run_break_set_by_script(self, "resolver.Resolver", extra_options="-k symbol -v break_on_me") 196*99451b44SJordan Rupprecht 197*99451b44SJordan Rupprecht # Make sure setting a resolver breakpoint doesn't pollute further breakpoint setting 198*99451b44SJordan Rupprecht # by checking the description of a regular file & line breakpoint to make sure it 199*99451b44SJordan Rupprecht # doesn't mention the Python Resolver function: 200*99451b44SJordan Rupprecht bkpt_no = lldbutil.run_break_set_by_file_and_line(self, "main.c", 12) 201*99451b44SJordan Rupprecht bkpt = target.FindBreakpointByID(bkpt_no) 202*99451b44SJordan Rupprecht strm = lldb.SBStream() 203*99451b44SJordan Rupprecht bkpt.GetDescription(strm, False) 204*99451b44SJordan Rupprecht used_resolver = "I am a python breakpoint resolver" in strm.GetData() 205*99451b44SJordan Rupprecht self.assertFalse(used_resolver, "Found the resolver description in the file & line breakpoint description.") 206*99451b44SJordan Rupprecht 207*99451b44SJordan Rupprecht # Also make sure the breakpoint was where we expected: 208*99451b44SJordan Rupprecht bp_loc = bkpt.GetLocationAtIndex(0) 209*99451b44SJordan Rupprecht bp_sc = bp_loc.GetAddress().GetSymbolContext(lldb.eSymbolContextEverything) 210*99451b44SJordan Rupprecht bp_se = bp_sc.GetLineEntry() 211*99451b44SJordan Rupprecht self.assertEqual(bp_se.GetLine(), 12, "Got the right line number") 212*99451b44SJordan Rupprecht self.assertEqual(bp_se.GetFileSpec().GetFilename(), "main.c", "Got the right filename") 213*99451b44SJordan Rupprecht 214*99451b44SJordan Rupprecht def do_test_bad_options(self): 215*99451b44SJordan Rupprecht target = self.make_target_and_import() 216*99451b44SJordan Rupprecht 217*99451b44SJordan Rupprecht self.expect("break set -P resolver.Resolver -k a_key", error = True, msg="Missing value at end", 218*99451b44SJordan Rupprecht substrs=['Key: "a_key" missing value']) 219*99451b44SJordan Rupprecht self.expect("break set -P resolver.Resolver -v a_value", error = True, msg="Missing key at end", 220*99451b44SJordan Rupprecht substrs=['Value: "a_value" missing matching key']) 221*99451b44SJordan Rupprecht self.expect("break set -P resolver.Resolver -v a_value -k a_key -v another_value", error = True, msg="Missing key among args", 222*99451b44SJordan Rupprecht substrs=['Value: "a_value" missing matching key']) 223*99451b44SJordan Rupprecht self.expect("break set -P resolver.Resolver -k a_key -k a_key -v another_value", error = True, msg="Missing value among args", 224*99451b44SJordan Rupprecht substrs=['Key: "a_key" missing value']) 225