# encoding: utf-8 """ Test lldb's frame recognizers. """ import lldb from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * from lldbsuite.test import lldbutil import recognizer class FrameRecognizerTestCase(TestBase): NO_DEBUG_INFO_TESTCASE = True @skipUnlessDarwin def test_frame_recognizer_1(self): self.build() exe = self.getBuildArtifact("a.out") # Clear internal & plugins recognizers that get initialized at launch self.runCmd("frame recognizer clear") self.runCmd( "command script import " + os.path.join(self.getSourceDir(), "recognizer.py") ) self.expect("frame recognizer list", substrs=["no matching results found."]) self.runCmd( "frame recognizer add -l recognizer.MyFrameRecognizer -s a.out -n foo" ) self.expect( "frame recognizer list", substrs=["0: recognizer.MyFrameRecognizer, module a.out, symbol foo"], ) self.runCmd( "frame recognizer add -l recognizer.MyOtherFrameRecognizer -s a.out -n bar -x" ) self.expect( "frame recognizer list", substrs=[ "1: recognizer.MyOtherFrameRecognizer, module a.out, symbol bar (regexp)", "0: recognizer.MyFrameRecognizer, module a.out, symbol foo", ], ) self.runCmd("frame recognizer delete 0") # Test that it deleted the recognizer with id 0. self.expect( "frame recognizer list", substrs=[ "1: recognizer.MyOtherFrameRecognizer, module a.out, symbol bar (regexp)" ], ) self.expect( "frame recognizer list", matching=False, substrs=["MyFrameRecognizer"] ) # Test that an invalid index and deleting the same index again # is an error and doesn't do any changes. self.expect( "frame recognizer delete 2", error=True, substrs=["error: '2' is not a valid recognizer id."], ) self.expect( "frame recognizer delete 0", error=True, substrs=["error: '0' is not a valid recognizer id."], ) # Recognizers should have the same state as above. self.expect( "frame recognizer list", substrs=[ "1: recognizer.MyOtherFrameRecognizer, module a.out, symbol bar (regexp)" ], ) self.expect( "frame recognizer list", matching=False, substrs=["MyFrameRecognizer"] ) self.runCmd("frame recognizer clear") self.expect("frame recognizer list", substrs=["no matching results found."]) self.runCmd( "frame recognizer add -l recognizer.MyFrameRecognizer -s a.out -n foo" ) target, process, thread, _ = lldbutil.run_to_name_breakpoint( self, "foo", exe_name=exe ) frame = thread.GetSelectedFrame() self.expect("frame variable", substrs=["(int) a = 42", "(int) b = 56"]) # Recognized arguments don't show up by default... variables = frame.GetVariables(lldb.SBVariablesOptions()) self.assertEqual(variables.GetSize(), 0) # ...unless you set target.display-recognized-arguments to 1... self.runCmd("settings set target.display-recognized-arguments 1") variables = frame.GetVariables(lldb.SBVariablesOptions()) self.assertEqual(variables.GetSize(), 2) # ...and you can reset it back to 0 to hide them again... self.runCmd("settings set target.display-recognized-arguments 0") variables = frame.GetVariables(lldb.SBVariablesOptions()) self.assertEqual(variables.GetSize(), 0) # ... or explicitly ask for them with SetIncludeRecognizedArguments(True). opts = lldb.SBVariablesOptions() opts.SetIncludeRecognizedArguments(True) variables = frame.GetVariables(opts) self.assertEqual(variables.GetSize(), 2) self.assertEqual(variables.GetValueAtIndex(0).name, "a") self.assertEqual(variables.GetValueAtIndex(0).signed, 42) self.assertEqual( variables.GetValueAtIndex(0).GetValueType(), lldb.eValueTypeVariableArgument ) self.assertEqual(variables.GetValueAtIndex(1).name, "b") self.assertEqual(variables.GetValueAtIndex(1).signed, 56) self.assertEqual( variables.GetValueAtIndex(1).GetValueType(), lldb.eValueTypeVariableArgument ) self.expect( "frame recognizer info 0", substrs=["frame 0 is recognized by recognizer.MyFrameRecognizer"], ) self.expect( "frame recognizer info 999", error=True, substrs=["no frame with index 999"] ) self.expect( "frame recognizer info 1", substrs=["frame 1 not recognized by any recognizer"], ) # FIXME: The following doesn't work yet, but should be fixed. """ target, process, thread, _ = lldbutil.run_to_name_breakpoint(self, "bar", exe_name = exe) frame = thread.GetSelectedFrame() self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, substrs=['stopped', 'stop reason = breakpoint']) self.expect("frame variable -t", substrs=['(int *) a = ']) self.expect("frame variable -t *a", substrs=['*a = 78']) """ @skipUnlessDarwin def test_frame_recognizer_multi_symbol(self): self.build() exe = self.getBuildArtifact("a.out") # Clear internal & plugins recognizers that get initialized at launch self.runCmd("frame recognizer clear") self.runCmd( "command script import " + os.path.join(self.getSourceDir(), "recognizer.py") ) self.expect("frame recognizer list", substrs=["no matching results found."]) self.runCmd( "frame recognizer add -l recognizer.MyFrameRecognizer -s a.out -n foo -n bar" ) self.expect( "frame recognizer list", substrs=[ "recognizer.MyFrameRecognizer, module a.out, symbol foo, symbol bar" ], ) target, process, thread, _ = lldbutil.run_to_name_breakpoint( self, "foo", exe_name=exe ) frame = thread.GetSelectedFrame() self.expect( "frame recognizer info 0", substrs=["frame 0 is recognized by recognizer.MyFrameRecognizer"], ) target, process, thread, _ = lldbutil.run_to_name_breakpoint( self, "bar", exe_name=exe ) frame = thread.GetSelectedFrame() self.expect( "frame recognizer info 0", substrs=["frame 0 is recognized by recognizer.MyFrameRecognizer"], ) @skipUnlessDarwin def test_frame_recognizer_target_specific(self): self.build() exe = self.getBuildArtifact("a.out") # Clear internal & plugins recognizers that get initialized at launch self.runCmd("frame recognizer clear") # Create a target. target, process, thread, _ = lldbutil.run_to_name_breakpoint( self, "foo", exe_name=exe ) self.runCmd( "command script import " + os.path.join(self.getSourceDir(), "recognizer.py") ) # Check that this doesn't contain our own FrameRecognizer somehow. self.expect( "frame recognizer list", matching=False, substrs=["MyFrameRecognizer"] ) # Add a frame recognizer in that target. self.runCmd( "frame recognizer add -l recognizer.MyFrameRecognizer -s a.out -n foo -n bar" ) self.expect( "frame recognizer list", substrs=[ "recognizer.MyFrameRecognizer, module a.out, symbol foo, symbol bar" ], ) self.expect( "frame recognizer info 0", substrs=["frame 0 is recognized by recognizer.MyFrameRecognizer"], ) # Create a second target. That one shouldn't have the frame recognizer. target, process, thread, _ = lldbutil.run_to_name_breakpoint( self, "bar", exe_name=exe ) self.expect( "frame recognizer info 0", substrs=["frame 0 not recognized by any recognizer"], ) # Add a frame recognizer to the new target. self.runCmd( "frame recognizer add -l recognizer.MyFrameRecognizer -s a.out -n bar" ) self.expect( "frame recognizer list", substrs=["recognizer.MyFrameRecognizer, module a.out, symbol bar"], ) # Now the new target should also recognize the frame. self.expect( "frame recognizer info 0", substrs=["frame 0 is recognized by recognizer.MyFrameRecognizer"], ) @skipUnlessDarwin def test_frame_recognizer_not_only_first_instruction(self): self.build() exe = self.getBuildArtifact("a.out") # Clear internal & plugins recognizers that get initialized at launch. self.runCmd("frame recognizer clear") self.runCmd( "command script import " + os.path.join(self.getSourceDir(), "recognizer.py") ) self.expect("frame recognizer list", substrs=["no matching results found."]) # Create a target. target, process, thread, _ = lldbutil.run_to_name_breakpoint( self, "foo", exe_name=exe ) # Move the PC one instruction further. self.runCmd("next") # Add a frame recognizer in that target. self.runCmd( "frame recognizer add -l recognizer.MyFrameRecognizer -s a.out -n foo -n bar" ) # It's not applied to foo(), because frame's PC is not at the first instruction of the function. self.expect( "frame recognizer info 0", substrs=["frame 0 not recognized by any recognizer"], ) # Add a frame recognizer with --first-instruction-only=true. self.runCmd("frame recognizer clear") self.runCmd( "frame recognizer add -l recognizer.MyFrameRecognizer -s a.out -n foo -n bar --first-instruction-only=true" ) # It's not applied to foo(), because frame's PC is not at the first instruction of the function. self.expect( "frame recognizer info 0", substrs=["frame 0 not recognized by any recognizer"], ) # Now add a frame recognizer with --first-instruction-only=false. self.runCmd("frame recognizer clear") self.runCmd( "frame recognizer add -l recognizer.MyFrameRecognizer -s a.out -n foo -n bar --first-instruction-only=false" ) # This time it should recognize the frame. self.expect( "frame recognizer info 0", substrs=["frame 0 is recognized by recognizer.MyFrameRecognizer"], ) opts = lldb.SBVariablesOptions() opts.SetIncludeRecognizedArguments(True) frame = thread.GetSelectedFrame() variables = frame.GetVariables(opts) self.assertEqual(variables.GetSize(), 2) self.assertEqual(variables.GetValueAtIndex(0).name, "a") self.assertEqual(variables.GetValueAtIndex(0).signed, 42) self.assertEqual( variables.GetValueAtIndex(0).GetValueType(), lldb.eValueTypeVariableArgument ) self.assertEqual(variables.GetValueAtIndex(1).name, "b") self.assertEqual(variables.GetValueAtIndex(1).signed, 56) self.assertEqual( variables.GetValueAtIndex(1).GetValueType(), lldb.eValueTypeVariableArgument ) @no_debug_info_test def test_frame_recognizer_delete_invalid_arg(self): self.expect( "frame recognizer delete a", error=True, substrs=["error: 'a' is not a valid recognizer id."], ) self.expect( 'frame recognizer delete ""', error=True, substrs=["error: '' is not a valid recognizer id."], ) self.expect( "frame recognizer delete -1", error=True, substrs=["error: '-1' is not a valid recognizer id."], ) self.expect( "frame recognizer delete 4294967297", error=True, substrs=["error: '4294967297' is not a valid recognizer id."], ) @no_debug_info_test def test_frame_recognizer_info_invalid_arg(self): self.expect( "frame recognizer info a", error=True, substrs=["error: 'a' is not a valid frame index."], ) self.expect( 'frame recognizer info ""', error=True, substrs=["error: '' is not a valid frame index."], ) self.expect( "frame recognizer info -1", error=True, substrs=["error: '-1' is not a valid frame index."], ) self.expect( "frame recognizer info 4294967297", error=True, substrs=["error: '4294967297' is not a valid frame index."], ) @no_debug_info_test def test_frame_recognizer_add_invalid_arg(self): self.expect( "frame recognizer add -f", error=True, substrs=["error: last option requires an argument"], ) self.expect( "frame recognizer add -f -1", error=True, substrs=["error: invalid boolean value '-1' passed for -f option"], ) self.expect( "frame recognizer add -f foo", error=True, substrs=["error: invalid boolean value 'foo' passed for -f option"], )