1""" 2Test getting return-values correctly when stepping out 3""" 4 5 6 7import lldb 8from lldbsuite.test.decorators import * 9from lldbsuite.test.lldbtest import * 10from lldbsuite.test import lldbutil 11 12 13class ReturnValueTestCase(TestBase): 14 15 def affected_by_pr33042(self): 16 return ("clang" in self.getCompiler() and self.isAArch64() and 17 self.getPlatform() == "linux") 18 19 def affected_by_pr44132(self): 20 return (self.getArchitecture() in ["aarch64", "arm"] and 21 self.getPlatform() in ["freebsd", "linux"]) 22 23 # ABIMacOSX_arm64 and the SysV_arm64 don't restore the storage value for memory returns on function 24 # exit, so lldb shouldn't attempt to fetch memory for those return types, as there is 25 # no easy way to guarantee that they will be correct. This is a list of the memory 26 # return functions defined in the test file: 27 arm_no_return_values = ["return_five_int", "return_one_int_one_double_one_int", 28 "return_one_short_one_double_one_short", "return_vector_size_float32_32", 29 "return_ext_vector_size_float32_8"] 30 def should_report_return_value(self, func_name): 31 abi = self.target.GetABIName() 32 if not abi in ["SysV-arm64", "ABIMacOSX_arm64", "macosx-arm"]: 33 return True 34 return not func_name in self.arm_no_return_values 35 36 @expectedFailureAll(oslist=["freebsd"], archs=["i386"], 37 bugnumber="llvm.org/pr48376") 38 @expectedFailureAll(oslist=["macosx"], archs=["i386"], bugnumber="<rdar://problem/28719652>") 39 @expectedFailureAll( 40 oslist=["linux"], 41 compiler="clang", 42 compiler_version=[ 43 "<=", 44 "3.6"], 45 archs=["i386"]) 46 @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24778") 47 @add_test_categories(['pyapi']) 48 def test_with_python(self): 49 """Test getting return values from stepping out.""" 50 self.build() 51 exe = self.getBuildArtifact("a.out") 52 (self.target, self.process, thread, inner_sint_bkpt) = lldbutil.run_to_name_breakpoint(self, "inner_sint", exe_name = exe) 53 54 error = lldb.SBError() 55 56 # inner_sint returns the variable value, so capture that here: 57 in_int = thread.GetFrameAtIndex(0).FindVariable( 58 "value").GetValueAsSigned(error) 59 self.assertSuccess(error) 60 61 thread.StepOut() 62 63 self.assertState(self.process.GetState(), lldb.eStateStopped) 64 self.assertEquals(thread.GetStopReason(), lldb.eStopReasonPlanComplete) 65 66 frame = thread.GetFrameAtIndex(0) 67 fun_name = frame.GetFunctionName() 68 self.assertEquals(fun_name, "outer_sint(int)") 69 70 return_value = thread.GetStopReturnValue() 71 self.assertTrue(return_value.IsValid()) 72 73 ret_int = return_value.GetValueAsSigned(error) 74 self.assertSuccess(error) 75 self.assertEquals(in_int, ret_int) 76 77 # Run again and we will stop in inner_sint the second time outer_sint is called. 78 # Then test stepping out two frames at once: 79 80 thread_list = lldbutil.continue_to_breakpoint(self.process, inner_sint_bkpt) 81 self.assertEquals(len(thread_list), 1) 82 thread = thread_list[0] 83 84 # We are done with the inner_sint breakpoint: 85 self.target.BreakpointDelete(inner_sint_bkpt.GetID()) 86 87 frame = thread.GetFrameAtIndex(1) 88 fun_name = frame.GetFunctionName() 89 self.assertEquals(fun_name, "outer_sint(int)") 90 in_int = frame.FindVariable("value").GetValueAsSigned(error) 91 self.assertSuccess(error) 92 93 thread.StepOutOfFrame(frame) 94 95 self.assertState(self.process.GetState(), lldb.eStateStopped) 96 self.assertEquals(thread.GetStopReason(), lldb.eStopReasonPlanComplete) 97 frame = thread.GetFrameAtIndex(0) 98 fun_name = frame.GetFunctionName() 99 self.assertEquals(fun_name, "main") 100 101 ret_value = thread.GetStopReturnValue() 102 self.assertTrue(return_value.IsValid()) 103 ret_int = ret_value.GetValueAsSigned(error) 104 self.assertSuccess(error) 105 self.assertEquals(2 * in_int, ret_int) 106 107 # Now try some simple returns that have different types: 108 inner_float_bkpt = self.target.BreakpointCreateByName( 109 "inner_float(float)", exe) 110 self.assertTrue(inner_float_bkpt, VALID_BREAKPOINT) 111 self.process.Continue() 112 thread_list = lldbutil.get_threads_stopped_at_breakpoint( 113 self.process, inner_float_bkpt) 114 self.assertEquals(len(thread_list), 1) 115 thread = thread_list[0] 116 117 self.target.BreakpointDelete(inner_float_bkpt.GetID()) 118 119 frame = thread.GetFrameAtIndex(0) 120 in_value = frame.FindVariable("value") 121 in_float = float(in_value.GetValue()) 122 thread.StepOut() 123 124 self.assertState(self.process.GetState(), lldb.eStateStopped) 125 self.assertEquals(thread.GetStopReason(), lldb.eStopReasonPlanComplete) 126 127 frame = thread.GetFrameAtIndex(0) 128 fun_name = frame.GetFunctionName() 129 self.assertEquals(fun_name, "outer_float(float)") 130 131 #return_value = thread.GetStopReturnValue() 132 #self.assertTrue(return_value.IsValid()) 133 #return_float = float(return_value.GetValue()) 134 135 #self.assertEqual(in_float, return_float) 136 137 if not self.affected_by_pr44132(): 138 self.return_and_test_struct_value("return_one_int") 139 self.return_and_test_struct_value("return_two_int") 140 self.return_and_test_struct_value("return_three_int") 141 self.return_and_test_struct_value("return_four_int") 142 if not self.affected_by_pr33042(): 143 self.return_and_test_struct_value("return_five_int") 144 self.return_and_test_struct_value("return_two_double") 145 self.return_and_test_struct_value("return_one_double_two_float") 146 self.return_and_test_struct_value("return_one_int_one_float_one_int") 147 148 self.return_and_test_struct_value("return_one_pointer") 149 self.return_and_test_struct_value("return_two_pointer") 150 self.return_and_test_struct_value("return_one_float_one_pointer") 151 self.return_and_test_struct_value("return_one_int_one_pointer") 152 self.return_and_test_struct_value("return_three_short_one_float") 153 154 self.return_and_test_struct_value("return_one_int_one_double") 155 self.return_and_test_struct_value("return_one_int_one_double_one_int") 156 self.return_and_test_struct_value( 157 "return_one_short_one_double_one_short") 158 self.return_and_test_struct_value("return_one_float_one_int_one_float") 159 self.return_and_test_struct_value("return_two_float") 160 # I am leaving out the packed test until we have a way to tell CLANG 161 # about alignment when reading DWARF for packed types. 162 #self.return_and_test_struct_value ("return_one_int_one_double_packed") 163 self.return_and_test_struct_value("return_one_int_one_long") 164 165 @expectedFailureAll(oslist=["freebsd"], archs=["i386"], 166 bugnumber="llvm.org/pr48376") 167 @expectedFailureAll(oslist=["macosx"], archs=["i386"], bugnumber="<rdar://problem/28719652>") 168 @expectedFailureAll( 169 oslist=["linux"], 170 compiler="clang", 171 compiler_version=[ 172 "<=", 173 "3.6"], 174 archs=["i386"]) 175 @expectedFailureAll(compiler=["gcc"], archs=["x86_64", "i386"]) 176 @expectedFailureAll(oslist=["windows"], archs=["i[3-6]86", "x86_64"], bugnumber="llvm.org/pr24778") 177 def test_vector_values(self): 178 self.build() 179 exe = self.getBuildArtifact("a.out") 180 error = lldb.SBError() 181 182 self.target = self.dbg.CreateTarget(exe) 183 self.assertTrue(self.target, VALID_TARGET) 184 185 main_bktp = self.target.BreakpointCreateByName("main", exe) 186 self.assertTrue(main_bktp, VALID_BREAKPOINT) 187 188 self.process = self.target.LaunchSimple( 189 None, None, self.get_process_working_directory()) 190 self.assertEqual(len(lldbutil.get_threads_stopped_at_breakpoint( 191 self.process, main_bktp)), 1) 192 self.return_and_test_struct_value("return_vector_size_float32_8") 193 self.return_and_test_struct_value("return_vector_size_float32_16") 194 if not self.affected_by_pr44132(): 195 self.return_and_test_struct_value("return_vector_size_float32_32") 196 self.return_and_test_struct_value("return_ext_vector_size_float32_2") 197 self.return_and_test_struct_value("return_ext_vector_size_float32_4") 198 if not self.affected_by_pr44132(): 199 self.return_and_test_struct_value("return_ext_vector_size_float32_8") 200 201 # limit the nested struct and class tests to only x86_64 202 @skipIf(archs=no_match(['x86_64'])) 203 @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24778") 204 def test_for_cpp_support(self): 205 self.build() 206 exe = self.getBuildArtifact("a.out") 207 (self.target, self.process, thread, inner_sint_bkpt) = lldbutil.run_to_name_breakpoint(self, "inner_sint", exe_name = exe) 208 209 error = lldb.SBError() 210 211 self.target = self.dbg.CreateTarget(exe) 212 self.assertTrue(self.target, VALID_TARGET) 213 214 main_bktp = self.target.BreakpointCreateByName("main", exe) 215 self.assertTrue(main_bktp, VALID_BREAKPOINT) 216 217 self.process = self.target.LaunchSimple( 218 None, None, self.get_process_working_directory()) 219 self.assertEqual(len(lldbutil.get_threads_stopped_at_breakpoint( 220 self.process, main_bktp)), 1) 221 # nested struct tests 222 self.return_and_test_struct_value("return_nested_one_float_three_base") 223 self.return_and_test_struct_value("return_double_nested_one_float_one_nested") 224 self.return_and_test_struct_value("return_nested_float_struct") 225 # class test 226 self.return_and_test_struct_value("return_base_class_one_char") 227 self.return_and_test_struct_value("return_nested_class_float_and_base") 228 self.return_and_test_struct_value("return_double_nested_class_float_and_nested") 229 self.return_and_test_struct_value("return_base_class") 230 self.return_and_test_struct_value("return_derived_class") 231 232 @skipIf(compiler="clang", compiler_version=['<', '7.0']) 233 def return_and_test_struct_value(self, func_name): 234 """Pass in the name of the function to return from - takes in value, returns value.""" 235 236 # Set the breakpoint, run to it, finish out. 237 bkpt = self.target.BreakpointCreateByName(func_name) 238 self.assertTrue(bkpt.GetNumResolvedLocations() > 0, "Got wrong number of locations for {0}".format(func_name)) 239 240 self.process.Continue() 241 242 thread_list = lldbutil.get_threads_stopped_at_breakpoint( 243 self.process, bkpt) 244 245 self.assertEquals(len(thread_list), 1) 246 thread = thread_list[0] 247 248 self.target.BreakpointDelete(bkpt.GetID()) 249 250 in_value = thread.GetFrameAtIndex(0).FindVariable("value") 251 252 self.assertTrue(in_value.IsValid()) 253 num_in_children = in_value.GetNumChildren() 254 255 # This is a little hokey, but if we don't get all the children now, then 256 # once we've stepped we won't be able to get them? 257 258 for idx in range(0, num_in_children): 259 in_child = in_value.GetChildAtIndex(idx) 260 in_child_str = in_child.GetValue() 261 262 thread.StepOut() 263 264 self.assertState(self.process.GetState(), lldb.eStateStopped) 265 self.assertEquals(thread.GetStopReason(), lldb.eStopReasonPlanComplete) 266 267 # Assuming all these functions step out to main. Could figure out the caller dynamically 268 # if that would add something to the test. 269 frame = thread.GetFrameAtIndex(0) 270 fun_name = frame.GetFunctionName() 271 self.assertEquals(fun_name, "main") 272 273 frame = thread.GetFrameAtIndex(0) 274 ret_value = thread.GetStopReturnValue() 275 if not self.should_report_return_value(func_name): 276 self.assertFalse(ret_value.IsValid(), "Shouldn't have gotten a value") 277 return 278 279 self.assertTrue(ret_value.IsValid()) 280 281 num_ret_children = ret_value.GetNumChildren() 282 self.assertEquals(num_in_children, num_ret_children) 283 for idx in range(0, num_ret_children): 284 in_child = in_value.GetChildAtIndex(idx) 285 ret_child = ret_value.GetChildAtIndex(idx) 286 in_child_str = in_child.GetValue() 287 ret_child_str = ret_child.GetValue() 288 289 self.assertEqual(in_child_str, ret_child_str) 290