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