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