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