509 lines · python
1# encoding: utf-82"""3Test lldb's frame recognizers.4"""5 6import lldb7from lldbsuite.test.decorators import *8from lldbsuite.test.lldbtest import *9from lldbsuite.test import lldbutil10 11import recognizer12 13 14class FrameRecognizerTestCase(TestBase):15 NO_DEBUG_INFO_TESTCASE = True16 17 def test_frame_recognizer_1(self):18 self.build()19 exe = self.getBuildArtifact("a.out")20 target, process, thread, _ = lldbutil.run_to_name_breakpoint(21 self, "foo", exe_name=exe22 )23 frame = thread.selected_frame24 25 # Clear internal & plugins recognizers that get initialized at launch26 self.runCmd("frame recognizer clear")27 28 self.runCmd(29 "command script import "30 + os.path.join(self.getSourceDir(), "recognizer.py")31 )32 33 self.expect("frame recognizer list", substrs=["no matching results found."])34 35 self.runCmd(36 "frame recognizer add -l recognizer.MyFrameRecognizer -s a.out -n foo"37 )38 39 self.expect(40 "frame recognizer list",41 substrs=[42 "0: recognizer.MyFrameRecognizer, module a.out, demangled symbol foo"43 ],44 )45 46 self.runCmd(47 "frame recognizer add -l recognizer.MyOtherFrameRecognizer -s a.out -n bar -x"48 )49 50 self.expect(51 "frame recognizer list",52 substrs=[53 "1: recognizer.MyOtherFrameRecognizer, module a.out, demangled symbol regex bar",54 "0: recognizer.MyFrameRecognizer, module a.out, demangled symbol foo",55 ],56 )57 58 self.runCmd("frame recognizer delete 0")59 60 # Test that it deleted the recognizer with id 0.61 self.expect(62 "frame recognizer list",63 substrs=[64 "1: recognizer.MyOtherFrameRecognizer, module a.out, demangled symbol regex bar"65 ],66 )67 self.expect(68 "frame recognizer list", matching=False, substrs=["MyFrameRecognizer"]69 )70 71 # Test that an invalid index and deleting the same index again72 # is an error and doesn't do any changes.73 self.expect(74 "frame recognizer delete 2",75 error=True,76 substrs=["error: '2' is not a valid recognizer id."],77 )78 self.expect(79 "frame recognizer delete 0",80 error=True,81 substrs=["error: '0' is not a valid recognizer id."],82 )83 # Recognizers should have the same state as above.84 self.expect(85 "frame recognizer list",86 substrs=[87 "1: recognizer.MyOtherFrameRecognizer, module a.out, demangled symbol regex bar"88 ],89 )90 self.expect(91 "frame recognizer list", matching=False, substrs=["MyFrameRecognizer"]92 )93 94 self.runCmd("frame recognizer clear")95 96 self.expect("frame recognizer list", substrs=["no matching results found."])97 98 self.runCmd(99 "frame recognizer add -l recognizer.MyFrameRecognizer -s a.out -n foo"100 )101 102 self.expect("frame variable", substrs=["(int) a = 42", "(int) b = 56"])103 104 # Recognized arguments don't show up by default...105 variables = frame.GetVariables(lldb.SBVariablesOptions())106 self.assertEqual(variables.GetSize(), 0)107 108 # ...unless you set target.display-recognized-arguments to 1...109 self.runCmd("settings set target.display-recognized-arguments 1")110 variables = frame.GetVariables(lldb.SBVariablesOptions())111 self.assertEqual(variables.GetSize(), 2)112 113 # ...and you can reset it back to 0 to hide them again...114 self.runCmd("settings set target.display-recognized-arguments 0")115 variables = frame.GetVariables(lldb.SBVariablesOptions())116 self.assertEqual(variables.GetSize(), 0)117 118 # ... or explicitly ask for them with SetIncludeRecognizedArguments(True).119 opts = lldb.SBVariablesOptions()120 opts.SetIncludeRecognizedArguments(True)121 variables = frame.GetVariables(opts)122 123 self.assertEqual(variables.GetSize(), 2)124 self.assertEqual(variables.GetValueAtIndex(0).name, "a")125 self.assertEqual(variables.GetValueAtIndex(0).signed, 42)126 self.assertEqual(127 variables.GetValueAtIndex(0).GetValueType(), lldb.eValueTypeVariableArgument128 )129 self.assertEqual(variables.GetValueAtIndex(1).name, "b")130 self.assertEqual(variables.GetValueAtIndex(1).signed, 56)131 self.assertEqual(132 variables.GetValueAtIndex(1).GetValueType(), lldb.eValueTypeVariableArgument133 )134 135 self.expect(136 "frame recognizer info 0",137 substrs=["frame 0 is recognized by recognizer.MyFrameRecognizer"],138 )139 140 self.expect(141 "frame recognizer info 999", error=True, substrs=["no frame with index 999"]142 )143 144 self.expect(145 "frame recognizer info 1",146 substrs=["frame 1 not recognized by any recognizer"],147 )148 149 # FIXME: The following doesn't work yet, but should be fixed.150 """151 target, process, thread, _ = lldbutil.run_to_name_breakpoint(self, "bar",152 exe_name = exe)153 frame = thread.GetSelectedFrame()154 155 self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT,156 substrs=['stopped', 'stop reason = breakpoint'])157 158 self.expect("frame variable -t",159 substrs=['(int *) a = '])160 161 self.expect("frame variable -t *a",162 substrs=['*a = 78'])163 """164 165 def test_frame_recognizer_hiding(self):166 self.build()167 168 target, process, thread, _ = lldbutil.run_to_name_breakpoint(self, "nested")169 frame = thread.selected_frame170 171 # Sanity check.172 self.expect(173 "thread backtrace", patterns=["frame.*nested", "frame.*baz", "frame.*main"]174 )175 176 self.expect("frame recognizer clear")177 self.expect(178 "command script import "179 + os.path.join(self.getSourceDir(), "recognizer.py")180 )181 182 self.expect(183 "frame recognizer add -l recognizer.BazFrameRecognizer -f false -s a.out -n baz"184 )185 186 self.expect(187 "frame recognizer list",188 substrs=["0: recognizer.BazFrameRecognizer"],189 )190 191 # Now main should be hidden.192 self.expect("thread backtrace", matching=False, patterns=["frame.*baz"])193 self.assertFalse(frame.IsHidden())194 frame = thread.SetSelectedFrame(1)195 self.assertIn("baz", frame.name)196 self.assertTrue(frame.IsHidden())197 198 # Test StepOut.199 frame = thread.SetSelectedFrame(0)200 thread.StepOut()201 frame = thread.GetSelectedFrame()202 self.assertIn("main", frame.name)203 204 def test_frame_recognizer_multi_symbol(self):205 self.build()206 exe = self.getBuildArtifact("a.out")207 208 # Clear internal & plugins recognizers that get initialized at launch209 self.runCmd("frame recognizer clear")210 211 self.runCmd(212 "command script import "213 + os.path.join(self.getSourceDir(), "recognizer.py")214 )215 216 self.expect("frame recognizer list", substrs=["no matching results found."])217 218 self.runCmd(219 "frame recognizer add -l recognizer.MyFrameRecognizer -s a.out -n foo -n bar"220 )221 222 self.expect(223 "frame recognizer list",224 substrs=[225 "recognizer.MyFrameRecognizer, module a.out, demangled symbol foo, bar"226 ],227 )228 229 target, process, thread, _ = lldbutil.run_to_name_breakpoint(230 self, "foo", exe_name=exe231 )232 233 self.expect(234 "frame recognizer info 0",235 substrs=["frame 0 is recognized by recognizer.MyFrameRecognizer"],236 )237 238 target, process, thread, _ = lldbutil.run_to_name_breakpoint(239 self, "bar", exe_name=exe240 )241 242 self.expect(243 "frame recognizer info 0",244 substrs=["frame 0 is recognized by recognizer.MyFrameRecognizer"],245 )246 247 def test_frame_recognizer_target_specific(self):248 self.build()249 exe = self.getBuildArtifact("a.out")250 251 # Clear internal & plugins recognizers that get initialized at launch252 self.runCmd("frame recognizer clear")253 254 # Create a target.255 target, process, thread, _ = lldbutil.run_to_name_breakpoint(256 self, "foo", exe_name=exe257 )258 259 self.runCmd(260 "command script import "261 + os.path.join(self.getSourceDir(), "recognizer.py")262 )263 264 # Check that this doesn't contain our own FrameRecognizer somehow.265 self.expect(266 "frame recognizer list", matching=False, substrs=["MyFrameRecognizer"]267 )268 269 # Add a frame recognizer in that target.270 self.runCmd(271 "frame recognizer add -l recognizer.MyFrameRecognizer -s a.out -n foo -n bar"272 )273 274 self.expect(275 "frame recognizer list",276 substrs=[277 "recognizer.MyFrameRecognizer, module a.out, demangled symbol foo, bar"278 ],279 )280 281 self.expect(282 "frame recognizer info 0",283 substrs=["frame 0 is recognized by recognizer.MyFrameRecognizer"],284 )285 286 # Create a second target. That one shouldn't have the frame recognizer.287 target, process, thread, _ = lldbutil.run_to_name_breakpoint(288 self, "bar", exe_name=exe289 )290 291 self.expect(292 "frame recognizer info 0",293 substrs=["frame 0 not recognized by any recognizer"],294 )295 296 # Add a frame recognizer to the new target.297 self.runCmd(298 "frame recognizer add -l recognizer.MyFrameRecognizer -s a.out -n bar"299 )300 301 self.expect(302 "frame recognizer list",303 substrs=[304 "recognizer.MyFrameRecognizer, module a.out, demangled symbol bar"305 ],306 )307 308 # Now the new target should also recognize the frame.309 self.expect(310 "frame recognizer info 0",311 substrs=["frame 0 is recognized by recognizer.MyFrameRecognizer"],312 )313 314 def test_frame_recognizer_not_only_first_instruction(self):315 self.build()316 exe = self.getBuildArtifact("a.out")317 318 # Clear internal & plugins recognizers that get initialized at launch.319 self.runCmd("frame recognizer clear")320 321 self.runCmd(322 "command script import "323 + os.path.join(self.getSourceDir(), "recognizer.py")324 )325 326 self.expect("frame recognizer list", substrs=["no matching results found."])327 328 # Create a target.329 target, process, thread, _ = lldbutil.run_to_name_breakpoint(330 self, "foo", exe_name=exe331 )332 333 # Move the PC one instruction further.334 self.runCmd("next")335 336 # Add a frame recognizer in that target.337 self.runCmd(338 "frame recognizer add -l recognizer.MyFrameRecognizer -s a.out -n foo -n bar"339 )340 341 # It's not applied to foo(), because frame's PC is not at the first instruction of the function.342 self.expect(343 "frame recognizer info 0",344 substrs=["frame 0 not recognized by any recognizer"],345 )346 347 # Add a frame recognizer with --first-instruction-only=true.348 self.runCmd("frame recognizer clear")349 350 self.runCmd(351 "frame recognizer add -l recognizer.MyFrameRecognizer -s a.out -n foo -n bar --first-instruction-only=true"352 )353 354 # It's not applied to foo(), because frame's PC is not at the first instruction of the function.355 self.expect(356 "frame recognizer info 0",357 substrs=["frame 0 not recognized by any recognizer"],358 )359 360 # Now add a frame recognizer with --first-instruction-only=false.361 self.runCmd("frame recognizer clear")362 363 self.runCmd(364 "frame recognizer add -l recognizer.MyFrameRecognizer -s a.out -n foo -n bar --first-instruction-only=false"365 )366 367 # This time it should recognize the frame.368 self.expect(369 "frame recognizer info 0",370 substrs=["frame 0 is recognized by recognizer.MyFrameRecognizer"],371 )372 373 opts = lldb.SBVariablesOptions()374 opts.SetIncludeRecognizedArguments(True)375 frame = thread.selected_frame376 variables = frame.GetVariables(opts)377 378 self.assertEqual(variables.GetSize(), 2)379 self.assertEqual(variables.GetValueAtIndex(0).name, "a")380 self.assertEqual(variables.GetValueAtIndex(0).signed, 42)381 self.assertEqual(382 variables.GetValueAtIndex(0).GetValueType(), lldb.eValueTypeVariableArgument383 )384 self.assertEqual(variables.GetValueAtIndex(1).name, "b")385 self.assertEqual(variables.GetValueAtIndex(1).signed, 56)386 self.assertEqual(387 variables.GetValueAtIndex(1).GetValueType(), lldb.eValueTypeVariableArgument388 )389 390 def test_frame_recognizer_disable(self):391 self.build()392 exe = self.getBuildArtifact("a.out")393 target, process, thread, _ = lldbutil.run_to_name_breakpoint(394 self, "foo", exe_name=exe395 )396 397 # Clear internal & plugins recognizers that get initialized at launch.398 self.runCmd("frame recognizer clear")399 400 self.runCmd(401 "command script import "402 + os.path.join(self.getSourceDir(), "recognizer.py")403 )404 405 # Add a frame recognizer in that target.406 self.runCmd(407 "frame recognizer add -l recognizer.MyFrameRecognizer -s a.out -n foo -n bar"408 )409 410 # The frame is recognized411 self.expect(412 "frame recognizer info 0",413 substrs=["frame 0 is recognized by recognizer.MyFrameRecognizer"],414 )415 416 # Disable the recognizer417 self.runCmd("frame recognizer disable 0")418 419 self.expect(420 "frame recognizer list",421 substrs=[422 "0: [disabled] recognizer.MyFrameRecognizer, module a.out, demangled symbol foo"423 ],424 )425 426 self.expect(427 "frame recognizer info 0",428 substrs=["frame 0 not recognized by any recognizer"],429 )430 431 # Re-enable the recognizer432 self.runCmd("frame recognizer enable 0")433 434 self.expect(435 "frame recognizer list",436 substrs=[437 "0: recognizer.MyFrameRecognizer, module a.out, demangled symbol foo"438 ],439 )440 441 self.expect(442 "frame recognizer info 0",443 substrs=["frame 0 is recognized by recognizer.MyFrameRecognizer"],444 )445 446 @no_debug_info_test447 def test_frame_recognizer_delete_invalid_arg(self):448 self.expect(449 "frame recognizer delete a",450 error=True,451 substrs=["error: 'a' is not a valid recognizer id."],452 )453 self.expect(454 'frame recognizer delete ""',455 error=True,456 substrs=["error: '' is not a valid recognizer id."],457 )458 self.expect(459 "frame recognizer delete -1",460 error=True,461 substrs=["error: '-1' is not a valid recognizer id."],462 )463 self.expect(464 "frame recognizer delete 4294967297",465 error=True,466 substrs=["error: '4294967297' is not a valid recognizer id."],467 )468 469 @no_debug_info_test470 def test_frame_recognizer_info_invalid_arg(self):471 self.expect(472 "frame recognizer info a",473 error=True,474 substrs=["error: 'a' is not a valid frame index."],475 )476 self.expect(477 'frame recognizer info ""',478 error=True,479 substrs=["error: '' is not a valid frame index."],480 )481 self.expect(482 "frame recognizer info -1",483 error=True,484 substrs=["error: '-1' is not a valid frame index."],485 )486 self.expect(487 "frame recognizer info 4294967297",488 error=True,489 substrs=["error: '4294967297' is not a valid frame index."],490 )491 492 @no_debug_info_test493 def test_frame_recognizer_add_invalid_arg(self):494 self.expect(495 "frame recognizer add -f",496 error=True,497 substrs=["error: last option requires an argument"],498 )499 self.expect(500 "frame recognizer add -f -1",501 error=True,502 substrs=["error: invalid boolean value '-1' passed for -f option"],503 )504 self.expect(505 "frame recognizer add -f foo",506 error=True,507 substrs=["error: invalid boolean value 'foo' passed for -f option"],508 )509