1# encoding: utf-8 2""" 3Test lldb's frame recognizers. 4""" 5 6import lldb 7from lldbsuite.test.decorators import * 8from lldbsuite.test.lldbtest import * 9from lldbsuite.test import lldbutil 10 11import recognizer 12 13class FrameRecognizerTestCase(TestBase): 14 15 mydir = TestBase.compute_mydir(__file__) 16 NO_DEBUG_INFO_TESTCASE = True 17 18 @skipUnlessDarwin 19 def test_frame_recognizer_1(self): 20 self.build() 21 exe = self.getBuildArtifact("a.out") 22 23 # Clear internal & plugins recognizers that get initialized at launch 24 self.runCmd("frame recognizer clear") 25 26 self.runCmd("command script import " + os.path.join(self.getSourceDir(), "recognizer.py")) 27 28 self.expect("frame recognizer list", 29 substrs=['no matching results found.']) 30 31 self.runCmd("frame recognizer add -l recognizer.MyFrameRecognizer -s a.out -n foo") 32 33 self.expect("frame recognizer list", 34 substrs=['0: recognizer.MyFrameRecognizer, module a.out, symbol foo']) 35 36 self.runCmd("frame recognizer add -l recognizer.MyOtherFrameRecognizer -s a.out -n bar -x") 37 38 self.expect( 39 "frame recognizer list", 40 substrs=[ 41 '1: recognizer.MyOtherFrameRecognizer, module a.out, symbol bar (regexp)', 42 '0: recognizer.MyFrameRecognizer, module a.out, symbol foo' 43 ]) 44 45 self.runCmd("frame recognizer delete 0") 46 47 # Test that it deleted the recognizer with id 0. 48 self.expect("frame recognizer list", 49 substrs=['1: recognizer.MyOtherFrameRecognizer, module a.out, symbol bar (regexp)']) 50 self.expect("frame recognizer list", matching=False, 51 substrs=['MyFrameRecognizer']) 52 53 # Test that an invalid index and deleting the same index again 54 # is an error and doesn't do any changes. 55 self.expect("frame recognizer delete 2", error=True, 56 substrs=["error: '2' is not a valid recognizer id."]) 57 self.expect("frame recognizer delete 0", error=True, 58 substrs=["error: '0' is not a valid recognizer id."]) 59 # Recognizers should have the same state as above. 60 self.expect("frame recognizer list", 61 substrs=['1: recognizer.MyOtherFrameRecognizer, module a.out, symbol bar (regexp)']) 62 self.expect("frame recognizer list", matching=False, 63 substrs=['MyFrameRecognizer']) 64 65 66 self.runCmd("frame recognizer clear") 67 68 self.expect("frame recognizer list", 69 substrs=['no matching results found.']) 70 71 self.runCmd("frame recognizer add -l recognizer.MyFrameRecognizer -s a.out -n foo") 72 73 target, process, thread, _ = lldbutil.run_to_name_breakpoint(self, "foo", 74 exe_name = exe) 75 frame = thread.GetSelectedFrame() 76 77 self.expect("frame variable", 78 substrs=['(int) a = 42', '(int) b = 56']) 79 80 # Recognized arguments don't show up by default... 81 variables = frame.GetVariables(lldb.SBVariablesOptions()) 82 self.assertEqual(variables.GetSize(), 0) 83 84 # ...unless you set target.display-recognized-arguments to 1... 85 self.runCmd("settings set target.display-recognized-arguments 1") 86 variables = frame.GetVariables(lldb.SBVariablesOptions()) 87 self.assertEqual(variables.GetSize(), 2) 88 89 # ...and you can reset it back to 0 to hide them again... 90 self.runCmd("settings set target.display-recognized-arguments 0") 91 variables = frame.GetVariables(lldb.SBVariablesOptions()) 92 self.assertEqual(variables.GetSize(), 0) 93 94 # ... or explicitly ask for them with SetIncludeRecognizedArguments(True). 95 opts = lldb.SBVariablesOptions() 96 opts.SetIncludeRecognizedArguments(True) 97 variables = frame.GetVariables(opts) 98 99 self.assertEqual(variables.GetSize(), 2) 100 self.assertEqual(variables.GetValueAtIndex(0).name, "a") 101 self.assertEqual(variables.GetValueAtIndex(0).signed, 42) 102 self.assertEqual(variables.GetValueAtIndex(0).GetValueType(), lldb.eValueTypeVariableArgument) 103 self.assertEqual(variables.GetValueAtIndex(1).name, "b") 104 self.assertEqual(variables.GetValueAtIndex(1).signed, 56) 105 self.assertEqual(variables.GetValueAtIndex(1).GetValueType(), lldb.eValueTypeVariableArgument) 106 107 self.expect("frame recognizer info 0", 108 substrs=['frame 0 is recognized by recognizer.MyFrameRecognizer']) 109 110 self.expect("frame recognizer info 999", error=True, 111 substrs=['no frame with index 999']) 112 113 self.expect("frame recognizer info 1", 114 substrs=['frame 1 not recognized by any recognizer']) 115 116 # FIXME: The following doesn't work yet, but should be fixed. 117 """ 118 target, process, thread, _ = lldbutil.run_to_name_breakpoint(self, "bar", 119 exe_name = exe) 120 frame = thread.GetSelectedFrame() 121 122 self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, 123 substrs=['stopped', 'stop reason = breakpoint']) 124 125 self.expect("frame variable -t", 126 substrs=['(int *) a = ']) 127 128 self.expect("frame variable -t *a", 129 substrs=['*a = 78']) 130 """ 131 132 @skipUnlessDarwin 133 def test_frame_recognizer_multi_symbol(self): 134 self.build() 135 exe = self.getBuildArtifact("a.out") 136 137 # Clear internal & plugins recognizers that get initialized at launch 138 self.runCmd("frame recognizer clear") 139 140 self.runCmd("command script import " + os.path.join(self.getSourceDir(), "recognizer.py")) 141 142 self.expect("frame recognizer list", 143 substrs=['no matching results found.']) 144 145 self.runCmd("frame recognizer add -l recognizer.MyFrameRecognizer -s a.out -n foo -n bar") 146 147 self.expect("frame recognizer list", 148 substrs=['recognizer.MyFrameRecognizer, module a.out, symbol foo, symbol bar']) 149 150 target, process, thread, _ = lldbutil.run_to_name_breakpoint(self, "foo", 151 exe_name = exe) 152 frame = thread.GetSelectedFrame() 153 154 self.expect("frame recognizer info 0", 155 substrs=['frame 0 is recognized by recognizer.MyFrameRecognizer']) 156 157 target, process, thread, _ = lldbutil.run_to_name_breakpoint(self, "bar", 158 exe_name = exe) 159 frame = thread.GetSelectedFrame() 160 161 self.expect("frame recognizer info 0", 162 substrs=['frame 0 is recognized by recognizer.MyFrameRecognizer']) 163 164 @skipUnlessDarwin 165 def test_frame_recognizer_target_specific(self): 166 self.build() 167 exe = self.getBuildArtifact("a.out") 168 169 # Clear internal & plugins recognizers that get initialized at launch 170 self.runCmd("frame recognizer clear") 171 172 # Create a target. 173 target, process, thread, _ = lldbutil.run_to_name_breakpoint(self, "foo", 174 exe_name = exe) 175 176 self.runCmd("command script import " + os.path.join(self.getSourceDir(), "recognizer.py")) 177 178 # Check that this doesn't contain our own FrameRecognizer somehow. 179 self.expect("frame recognizer list", 180 matching=False, substrs=['MyFrameRecognizer']) 181 182 # Add a frame recognizer in that target. 183 self.runCmd("frame recognizer add -l recognizer.MyFrameRecognizer -s a.out -n foo -n bar") 184 185 self.expect("frame recognizer list", 186 substrs=['recognizer.MyFrameRecognizer, module a.out, symbol foo, symbol bar']) 187 188 self.expect("frame recognizer info 0", 189 substrs=['frame 0 is recognized by recognizer.MyFrameRecognizer']) 190 191 # Create a second target. That one shouldn't have the frame recognizer. 192 target, process, thread, _ = lldbutil.run_to_name_breakpoint(self, "bar", 193 exe_name = exe) 194 195 self.expect("frame recognizer info 0", 196 substrs=['frame 0 not recognized by any recognizer']) 197 198 # Add a frame recognizer to the new target. 199 self.runCmd("frame recognizer add -l recognizer.MyFrameRecognizer -s a.out -n bar") 200 201 self.expect("frame recognizer list", 202 substrs=['recognizer.MyFrameRecognizer, module a.out, symbol bar']) 203 204 # Now the new target should also recognize the frame. 205 self.expect("frame recognizer info 0", 206 substrs=['frame 0 is recognized by recognizer.MyFrameRecognizer']) 207 208 @skipUnlessDarwin 209 def test_frame_recognizer_not_only_first_instruction(self): 210 self.build() 211 exe = self.getBuildArtifact("a.out") 212 213 # Clear internal & plugins recognizers that get initialized at launch. 214 self.runCmd("frame recognizer clear") 215 216 self.runCmd("command script import " + os.path.join(self.getSourceDir(), "recognizer.py")) 217 218 self.expect("frame recognizer list", 219 substrs=['no matching results found.']) 220 221 # Create a target. 222 target, process, thread, _ = lldbutil.run_to_name_breakpoint(self, "foo", 223 exe_name = exe) 224 225 # Move the PC one instruction further. 226 self.runCmd("next") 227 228 # Add a frame recognizer in that target. 229 self.runCmd("frame recognizer add -l recognizer.MyFrameRecognizer -s a.out -n foo -n bar") 230 231 # It's not applied to foo(), because frame's PC is not at the first instruction of the function. 232 self.expect("frame recognizer info 0", 233 substrs=['frame 0 not recognized by any recognizer']) 234 235 # Add a frame recognizer with --first-instruction-only=true. 236 self.runCmd("frame recognizer clear") 237 238 self.runCmd("frame recognizer add -l recognizer.MyFrameRecognizer -s a.out -n foo -n bar --first-instruction-only=true") 239 240 # It's not applied to foo(), because frame's PC is not at the first instruction of the function. 241 self.expect("frame recognizer info 0", 242 substrs=['frame 0 not recognized by any recognizer']) 243 244 # Now add a frame recognizer with --first-instruction-only=false. 245 self.runCmd("frame recognizer clear") 246 247 self.runCmd("frame recognizer add -l recognizer.MyFrameRecognizer -s a.out -n foo -n bar --first-instruction-only=false") 248 249 # This time it should recognize the frame. 250 self.expect("frame recognizer info 0", 251 substrs=['frame 0 is recognized by recognizer.MyFrameRecognizer']) 252 253 opts = lldb.SBVariablesOptions() 254 opts.SetIncludeRecognizedArguments(True) 255 frame = thread.GetSelectedFrame() 256 variables = frame.GetVariables(opts) 257 258 self.assertEqual(variables.GetSize(), 2) 259 self.assertEqual(variables.GetValueAtIndex(0).name, "a") 260 self.assertEqual(variables.GetValueAtIndex(0).signed, 42) 261 self.assertEqual(variables.GetValueAtIndex(0).GetValueType(), lldb.eValueTypeVariableArgument) 262 self.assertEqual(variables.GetValueAtIndex(1).name, "b") 263 self.assertEqual(variables.GetValueAtIndex(1).signed, 56) 264 self.assertEqual(variables.GetValueAtIndex(1).GetValueType(), lldb.eValueTypeVariableArgument) 265 266 @no_debug_info_test 267 def test_frame_recognizer_delete_invalid_arg(self): 268 self.expect("frame recognizer delete a", error=True, 269 substrs=["error: 'a' is not a valid recognizer id."]) 270 self.expect("frame recognizer delete \"\"", error=True, 271 substrs=["error: '' is not a valid recognizer id."]) 272 self.expect("frame recognizer delete -1", error=True, 273 substrs=["error: '-1' is not a valid recognizer id."]) 274 self.expect("frame recognizer delete 4294967297", error=True, 275 substrs=["error: '4294967297' is not a valid recognizer id."]) 276 277 @no_debug_info_test 278 def test_frame_recognizer_info_invalid_arg(self): 279 self.expect("frame recognizer info a", error=True, 280 substrs=["error: 'a' is not a valid frame index."]) 281 self.expect("frame recognizer info \"\"", error=True, 282 substrs=["error: '' is not a valid frame index."]) 283 self.expect("frame recognizer info -1", error=True, 284 substrs=["error: '-1' is not a valid frame index."]) 285 self.expect("frame recognizer info 4294967297", error=True, 286 substrs=["error: '4294967297' is not a valid frame index."]) 287 288 @no_debug_info_test 289 def test_frame_recognizer_add_invalid_arg(self): 290 self.expect("frame recognizer add -f", error=True, 291 substrs=["error: last option requires an argument"]) 292 self.expect("frame recognizer add -f -1", error=True, 293 substrs=["error: invalid boolean value '-1' passed for -f option"]) 294 self.expect("frame recognizer add -f foo", error=True, 295 substrs=["error: invalid boolean value 'foo' passed for -f option"]) 296