1""" 2Test lldb breakpoint command add/list/delete. 3""" 4 5 6 7import lldb 8from lldbsuite.test.decorators import * 9from lldbsuite.test.lldbtest import * 10from lldbsuite.test import lldbutil 11import side_effect 12 13 14class BreakpointCommandTestCase(TestBase): 15 16 NO_DEBUG_INFO_TESTCASE = True 17 18 @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24528") 19 def test_breakpoint_command_sequence(self): 20 """Test a sequence of breakpoint command add, list, and delete.""" 21 self.build() 22 self.breakpoint_command_sequence() 23 24 @skipIf(oslist=["windows"], bugnumber="llvm.org/pr44431") 25 def test_script_parameters(self): 26 """Test a sequence of breakpoint command add, list, and delete.""" 27 self.build() 28 self.breakpoint_command_script_parameters() 29 30 def test_commands_on_creation(self): 31 self.build() 32 self.breakpoint_commands_on_creation() 33 34 def setUp(self): 35 # Call super's setUp(). 36 TestBase.setUp(self) 37 # Find the line number to break inside main(). 38 self.line = line_number('main.c', '// Set break point at this line.') 39 # disable "There is a running process, kill it and restart?" prompt 40 self.runCmd("settings set auto-confirm true") 41 self.addTearDownHook( 42 lambda: self.runCmd("settings clear auto-confirm")) 43 44 def test_delete_all_breakpoints(self): 45 """Test that deleting all breakpoints works.""" 46 self.build() 47 exe = self.getBuildArtifact("a.out") 48 self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) 49 50 lldbutil.run_break_set_by_symbol(self, "main") 51 lldbutil.run_break_set_by_file_and_line( 52 self, "main.c", self.line, num_expected_locations=1, loc_exact=True) 53 54 self.runCmd("run", RUN_SUCCEEDED) 55 56 self.runCmd("breakpoint delete") 57 self.runCmd("process continue") 58 self.expect("process status", PROCESS_STOPPED, 59 patterns=['Process .* exited with status = 0']) 60 61 62 def breakpoint_command_sequence(self): 63 """Test a sequence of breakpoint command add, list, and delete.""" 64 exe = self.getBuildArtifact("a.out") 65 self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) 66 67 # Add three breakpoints on the same line. The first time we don't specify the file, 68 # since the default file is the one containing main: 69 lldbutil.run_break_set_by_file_and_line( 70 self, None, self.line, num_expected_locations=1, loc_exact=True) 71 lldbutil.run_break_set_by_file_and_line( 72 self, "main.c", self.line, num_expected_locations=1, loc_exact=True) 73 lldbutil.run_break_set_by_file_and_line( 74 self, "main.c", self.line, num_expected_locations=1, loc_exact=True) 75 # Breakpoint 4 - set at the same location as breakpoint 1 to test 76 # setting breakpoint commands on two breakpoints at a time 77 lldbutil.run_break_set_by_file_and_line( 78 self, None, self.line, num_expected_locations=1, loc_exact=True) 79 # Make sure relative path source breakpoints work as expected. We test 80 # with partial paths with and without "./" prefixes. 81 lldbutil.run_break_set_by_file_and_line( 82 self, "./main.c", self.line, 83 num_expected_locations=1, loc_exact=True) 84 lldbutil.run_break_set_by_file_and_line( 85 self, "breakpoint_command/main.c", self.line, 86 num_expected_locations=1, loc_exact=True) 87 lldbutil.run_break_set_by_file_and_line( 88 self, "./breakpoint_command/main.c", self.line, 89 num_expected_locations=1, loc_exact=True) 90 lldbutil.run_break_set_by_file_and_line( 91 self, "breakpoint/breakpoint_command/main.c", self.line, 92 num_expected_locations=1, loc_exact=True) 93 lldbutil.run_break_set_by_file_and_line( 94 self, "./breakpoint/breakpoint_command/main.c", self.line, 95 num_expected_locations=1, loc_exact=True) 96 # Test relative breakpoints with incorrect paths and make sure we get 97 # no breakpoint locations 98 lldbutil.run_break_set_by_file_and_line( 99 self, "invalid/main.c", self.line, 100 num_expected_locations=0, loc_exact=True) 101 lldbutil.run_break_set_by_file_and_line( 102 self, "./invalid/main.c", self.line, 103 num_expected_locations=0, loc_exact=True) 104 # Now add callbacks for the breakpoints just created. 105 self.runCmd( 106 "breakpoint command add -s command -o 'frame variable --show-types --scope' 1 4") 107 self.runCmd( 108 "breakpoint command add -s python -o 'import side_effect; side_effect.one_liner = \"one liner was here\"' 2") 109 110 import side_effect 111 self.runCmd("command script import --allow-reload ./bktptcmd.py") 112 113 self.runCmd( 114 "breakpoint command add --python-function bktptcmd.function 3") 115 116 # Check that the breakpoint commands are correctly set. 117 118 # The breakpoint list now only contains breakpoint 1. 119 self.expect( 120 "breakpoint list", "Breakpoints 1 & 2 created", substrs=[ 121 "2: file = 'main.c', line = %d, exact_match = 0, locations = 1" % 122 self.line], patterns=[ 123 "1: file = '.*main.c', line = %d, exact_match = 0, locations = 1" % 124 self.line]) 125 126 self.expect( 127 "breakpoint list -f", 128 "Breakpoints 1 & 2 created", 129 substrs=[ 130 "2: file = 'main.c', line = %d, exact_match = 0, locations = 1" % 131 self.line], 132 patterns=[ 133 "1: file = '.*main.c', line = %d, exact_match = 0, locations = 1" % 134 self.line, 135 "1.1: .+at main.c:%d:?[0-9]*, .+unresolved, hit count = 0" % 136 self.line, 137 "2.1: .+at main.c:%d:?[0-9]*, .+unresolved, hit count = 0" % 138 self.line]) 139 140 self.expect("breakpoint command list 1", "Breakpoint 1 command ok", 141 substrs=["Breakpoint commands:", 142 "frame variable --show-types --scope"]) 143 self.expect("breakpoint command list 2", "Breakpoint 2 command ok", 144 substrs=["Breakpoint commands (Python):", 145 "import side_effect", 146 "side_effect.one_liner"]) 147 self.expect("breakpoint command list 3", "Breakpoint 3 command ok", 148 substrs=["Breakpoint commands (Python):", 149 "bktptcmd.function(frame, bp_loc, internal_dict)"]) 150 151 self.expect("breakpoint command list 4", "Breakpoint 4 command ok", 152 substrs=["Breakpoint commands:", 153 "frame variable --show-types --scope"]) 154 155 self.runCmd("breakpoint delete 4") 156 157 # Next lets try some other breakpoint kinds. First break with a regular expression 158 # and then specify only one file. The first time we should get two locations, 159 # the second time only one: 160 161 lldbutil.run_break_set_by_regexp( 162 self, r"._MyFunction", num_expected_locations=2) 163 164 lldbutil.run_break_set_by_regexp( 165 self, 166 r"._MyFunction", 167 extra_options="-f a.c", 168 num_expected_locations=1) 169 170 lldbutil.run_break_set_by_regexp( 171 self, 172 r"._MyFunction", 173 extra_options="-f a.c -f b.c", 174 num_expected_locations=2) 175 176 # Now try a source regex breakpoint: 177 lldbutil.run_break_set_by_source_regexp( 178 self, 179 r"is about to return [12]0", 180 extra_options="-f a.c -f b.c", 181 num_expected_locations=2) 182 183 lldbutil.run_break_set_by_source_regexp( 184 self, 185 r"is about to return [12]0", 186 extra_options="-f a.c", 187 num_expected_locations=1) 188 189 # Reset our canary variables and run the program. 190 side_effect.one_liner = None 191 side_effect.bktptcmd = None 192 self.runCmd("run", RUN_SUCCEEDED) 193 194 # Check the value of canary variables. 195 self.assertEquals("one liner was here", side_effect.one_liner) 196 self.assertEquals("function was here", side_effect.bktptcmd) 197 198 # Finish the program. 199 self.runCmd("process continue") 200 201 # Remove the breakpoint command associated with breakpoint 1. 202 self.runCmd("breakpoint command delete 1") 203 204 # Remove breakpoint 2. 205 self.runCmd("breakpoint delete 2") 206 207 self.expect( 208 "breakpoint command list 1", 209 startstr="Breakpoint 1 does not have an associated command.") 210 self.expect( 211 "breakpoint command list 2", 212 error=True, 213 startstr="error: '2' is not a currently valid breakpoint ID.") 214 215 # The breakpoint list now only contains breakpoint 1. 216 self.expect( 217 "breakpoint list -f", 218 "Breakpoint 1 exists", 219 patterns=[ 220 "1: file = '.*main.c', line = %d, exact_match = 0, locations = 1, resolved = 1" % 221 self.line, 222 "hit count = 1"]) 223 224 # Not breakpoint 2. 225 self.expect( 226 "breakpoint list -f", 227 "No more breakpoint 2", 228 matching=False, 229 substrs=[ 230 "2: file = 'main.c', line = %d, exact_match = 0, locations = 1, resolved = 1" % 231 self.line]) 232 233 # Run the program again, with breakpoint 1 remaining. 234 self.runCmd("run", RUN_SUCCEEDED) 235 236 # We should be stopped again due to breakpoint 1. 237 238 # The stop reason of the thread should be breakpoint. 239 self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, 240 substrs=['stopped', 241 'stop reason = breakpoint']) 242 243 # The breakpoint should have a hit count of 2. 244 lldbutil.check_breakpoint(self, bpno = 1, expected_hit_count = 2) 245 246 def breakpoint_command_script_parameters(self): 247 """Test that the frame and breakpoint location are being properly passed to the script breakpoint command function.""" 248 exe = self.getBuildArtifact("a.out") 249 self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) 250 251 # Add a breakpoint. 252 lldbutil.run_break_set_by_file_and_line( 253 self, "main.c", self.line, num_expected_locations=1, loc_exact=True) 254 255 # Now add callbacks for the breakpoints just created. 256 self.runCmd("breakpoint command add -s python -o 'import side_effect; side_effect.frame = str(frame); side_effect.bp_loc = str(bp_loc)' 1") 257 258 # Reset canary variables and run. 259 side_effect.frame = None 260 side_effect.bp_loc = None 261 self.runCmd("run", RUN_SUCCEEDED) 262 263 self.expect(side_effect.frame, exe=False, startstr="frame #0:") 264 self.expect(side_effect.bp_loc, exe=False, 265 patterns=["1.* where = .*main .* resolved,( hardware,)? hit count = 1"]) 266 267 def breakpoint_commands_on_creation(self): 268 """Test that setting breakpoint commands when creating the breakpoint works""" 269 target = self.createTestTarget() 270 271 # Add a breakpoint. 272 lldbutil.run_break_set_by_file_and_line( 273 self, "main.c", self.line, num_expected_locations=1, loc_exact=True, 274 extra_options='-C bt -C "thread list" -C continue') 275 276 bkpt = target.FindBreakpointByID(1) 277 self.assertTrue(bkpt.IsValid(), "Couldn't find breakpoint 1") 278 com_list = lldb.SBStringList() 279 bkpt.GetCommandLineCommands(com_list) 280 self.assertEqual(com_list.GetSize(), 3, "Got the wrong number of commands") 281 self.assertEqual(com_list.GetStringAtIndex(0), "bt", "First bt") 282 self.assertEqual(com_list.GetStringAtIndex(1), "thread list", "Next thread list") 283 self.assertEqual(com_list.GetStringAtIndex(2), "continue", "Last continue") 284 285 def test_add_commands_by_breakpoint_name(self): 286 """Make sure that when you specify a breakpoint name to "break command add" 287 it gets added to all the breakpoints marked with that name.""" 288 self.build() 289 target = self.createTestTarget() 290 291 bp_ids = [] 292 bp_names = ["main", "not_here", "main"] 293 for bp_name in bp_names: 294 bp = target.BreakpointCreateByName(bp_name) 295 bp.AddName("MyBKPTS") 296 bp_ids.append(bp.GetID()) 297 # First do it with a script one-liner: 298 self.runCmd("breakpoint command add -s py -o 'print(\"some command\")' MyBKPTS") 299 for id in bp_ids: 300 self.expect("breakpoint command list {0}".format(id), 301 patterns=["some command"]) 302 # Now do the same thing with a python function: 303 import side_effect 304 self.runCmd("command script import --allow-reload ./bktptcmd.py") 305 306 self.runCmd("breakpoint command add --python-function bktptcmd.function MyBKPTS") 307 for id in bp_ids: 308 self.expect("breakpoint command list {0}".format(id), 309 patterns=["bktptcmd.function"]) 310 311 312 313 def test_breakpoint_delete_disabled(self): 314 """Test 'break delete --disabled' works""" 315 self.build() 316 target = self.createTestTarget() 317 318 bp_1 = target.BreakpointCreateByName("main") 319 bp_2 = target.BreakpointCreateByName("not_here") 320 bp_3 = target.BreakpointCreateByName("main") 321 bp_3.AddName("DeleteMeNot") 322 323 bp_1.SetEnabled(False) 324 bp_3.SetEnabled(False) 325 326 bp_id_1 = bp_1.GetID() 327 bp_id_2 = bp_2.GetID() 328 bp_id_3 = bp_3.GetID() 329 330 self.runCmd("breakpoint delete --disabled DeleteMeNot") 331 332 bp_1 = target.FindBreakpointByID(bp_id_1) 333 self.assertFalse(bp_1.IsValid(), "Didn't delete disabled breakpoint 1") 334 335 bp_2 = target.FindBreakpointByID(bp_id_2) 336 self.assertTrue(bp_2.IsValid(), "Deleted enabled breakpoint 2") 337 338 bp_3 = target.FindBreakpointByID(bp_id_3) 339 self.assertTrue(bp_3.IsValid(), "DeleteMeNot didn't protect disabled breakpoint 3") 340 341 # Reset the first breakpoint, disable it, and do this again with no protected name: 342 bp_1 = target.BreakpointCreateByName("main") 343 344 bp_1.SetEnabled(False) 345 346 bp_id_1 = bp_1.GetID() 347 348 self.runCmd("breakpoint delete --disabled") 349 350 bp_1 = target.FindBreakpointByID(bp_id_1) 351 self.assertFalse(bp_1.IsValid(), "Didn't delete disabled breakpoint 1") 352 353 bp_2 = target.FindBreakpointByID(bp_id_2) 354 self.assertTrue(bp_2.IsValid(), "Deleted enabled breakpoint 2") 355 356 bp_3 = target.FindBreakpointByID(bp_id_3) 357 self.assertFalse(bp_3.IsValid(), "Didn't delete disabled breakpoint 3") 358