1""" 2Test that the FrameRecognizer for __abort_with_payload 3works properly 4""" 5 6 7import lldb 8from lldbsuite.test.decorators import * 9import lldbsuite.test.lldbutil as lldbutil 10from lldbsuite.test.lldbtest import * 11 12 13class TestAbortWithPayload(TestBase): 14 NO_DEBUG_INFO_TESTCASE = True 15 16 @skipUnlessAppleSilicon 17 def test_abort_with_payload(self): 18 """There can be many tests in a test case - describe this test here.""" 19 self.build() 20 self.abort_with_test(True) 21 22 @skipUnlessAppleSilicon 23 def test_abort_with_reason(self): 24 """There can be many tests in a test case - describe this test here.""" 25 self.build() 26 self.abort_with_test(False) 27 28 def setUp(self): 29 # Call super's setUp(). 30 TestBase.setUp(self) 31 self.main_source_file = lldb.SBFileSpec("main.c") 32 33 def abort_with_test(self, with_payload): 34 """If with_payload is True, we test the abort_with_payload call, 35 if false, we test abort_with_reason.""" 36 launch_info = lldb.SBLaunchInfo([]) 37 if not with_payload: 38 launch_info.SetArguments(["use_reason"], True) 39 (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint( 40 self, 41 "Stop here before abort", 42 self.main_source_file, 43 launch_info=launch_info, 44 ) 45 46 frame = thread.GetFrameAtIndex(0) 47 payload_str_var = frame.FindVariable("payload_string") 48 self.assertSuccess(payload_str_var.GetError(), "Got payload string var") 49 payload_var_addr = payload_str_var.unsigned 50 51 payload_size_var = frame.FindVariable("payload_string_len") 52 self.assertSuccess(payload_size_var.GetError(), "Got payload string len var") 53 payload_size_val = payload_size_var.unsigned 54 55 # Not let it run to crash: 56 process.Continue() 57 58 # At this point we should have stopped at the internal function. 59 # Make sure we selected the right thread: 60 sel_thread = process.GetSelectedThread() 61 self.assertEqual(thread, sel_thread, "Selected the original thread") 62 # Make sure the stop reason is right: 63 self.assertEqual( 64 thread.GetStopDescription(100), 65 "abort with payload or reason", 66 "Description was right", 67 ) 68 frame_0 = thread.frames[0] 69 self.assertEqual(frame_0.name, "__abort_with_payload", "Frame 0 was right") 70 71 # Now check the recognized argument values and the ExtendedCrashInformation version: 72 options = lldb.SBVariablesOptions() 73 options.SetIncludeRecognizedArguments(True) 74 options.SetIncludeArguments(False) 75 options.SetIncludeLocals(False) 76 options.SetIncludeStatics(False) 77 options.SetIncludeRuntimeSupportValues(False) 78 79 arguments = frame_0.GetVariables(options) 80 81 correct_values = { 82 "namespace": 5, 83 "code": 100, 84 "payload_addr": payload_var_addr, 85 "payload_size": payload_size_val, 86 "payload_string": '"This is a payload that happens to be a string"', 87 "reason_string": '"This is the reason string"', 88 "reason_no_quote": "This is the reason string", 89 "flags": 0x85, 90 } 91 92 # First check the recognized argument values: 93 self.assertEqual(len(arguments), 6, "Got all six values") 94 self.assertEqual(arguments[0].name, "namespace") 95 self.assertEqual( 96 arguments[0].unsigned, 97 correct_values["namespace"], 98 "Namespace value correct", 99 ) 100 101 self.assertEqual(arguments[1].name, "code") 102 self.assertEqual( 103 arguments[1].unsigned, correct_values["code"], "code value correct" 104 ) 105 106 # We always stop at __abort_with_payload, regardless of whether the caller 107 # was abort_with_reason or abort_with_payload or any future API that 108 # funnels here. Since I don't want to have to know too much about the 109 # callers, I just always report what is in the function I've 110 # 111 # add the payload ones if it is the payload not the reason function. 112 self.assertEqual(arguments[2].name, "payload_addr") 113 self.assertEqual(arguments[3].name, "payload_size") 114 if with_payload: 115 self.assertEqual( 116 arguments[2].unsigned, 117 correct_values["payload_addr"], 118 "Payload matched variable address", 119 ) 120 # We've made a payload that is a string, try to fetch that: 121 char_ptr_type = target.FindFirstType("char").GetPointerType() 122 self.assertTrue(char_ptr_type.IsValid(), "Got char ptr type") 123 124 str_val = arguments[2].Cast(char_ptr_type) 125 self.assertEqual( 126 str_val.summary, correct_values["payload_string"], "Got payload string" 127 ) 128 129 self.assertEqual( 130 arguments[3].unsigned, 131 correct_values["payload_size"], 132 "payload size value correct", 133 ) 134 else: 135 self.assertEqual( 136 arguments[2].unsigned, 0, "Got 0 payload addr for reason call" 137 ) 138 self.assertEqual( 139 arguments[3].unsigned, 0, "Got 0 payload size for reason call" 140 ) 141 142 self.assertEqual(arguments[4].name, "reason") 143 self.assertEqual( 144 arguments[4].summary, 145 correct_values["reason_string"], 146 "Reason value correct", 147 ) 148 149 self.assertEqual(arguments[5].name, "flags") 150 self.assertEqual( 151 arguments[5].unsigned, correct_values["flags"], "Flags value correct" 152 ) 153 154 # Also check that the same info was stored in the ExtendedCrashInformation dict: 155 dict = process.GetExtendedCrashInformation() 156 self.assertTrue(dict.IsValid(), "Got extended crash information dict") 157 self.assertEqual( 158 dict.GetType(), lldb.eStructuredDataTypeDictionary, "It is a dictionary" 159 ) 160 161 abort_dict = dict.GetValueForKey("abort_with_payload") 162 self.assertTrue(abort_dict.IsValid(), "Got an abort_with_payload dict") 163 self.assertEqual( 164 abort_dict.GetType(), 165 lldb.eStructuredDataTypeDictionary, 166 "It is a dictionary", 167 ) 168 169 namespace_val = abort_dict.GetValueForKey("namespace") 170 self.assertTrue(namespace_val.IsValid(), "Got a valid namespace") 171 self.assertEqual( 172 namespace_val.GetIntegerValue(0), 173 correct_values["namespace"], 174 "Namespace value correct", 175 ) 176 177 code_val = abort_dict.GetValueForKey("code") 178 self.assertTrue(code_val.IsValid(), "Got a valid code") 179 self.assertEqual( 180 code_val.GetIntegerValue(0), correct_values["code"], "Code value correct" 181 ) 182 183 if with_payload: 184 addr_val = abort_dict.GetValueForKey("payload_addr") 185 self.assertTrue(addr_val.IsValid(), "Got a payload_addr") 186 self.assertEqual( 187 addr_val.GetIntegerValue(0), 188 correct_values["payload_addr"], 189 "payload_addr right in dictionary", 190 ) 191 192 size_val = abort_dict.GetValueForKey("payload_size") 193 self.assertTrue(size_val.IsValid(), "Got a payload size value") 194 self.assertEqual( 195 size_val.GetIntegerValue(0), 196 correct_values["payload_size"], 197 "payload size right in dictionary", 198 ) 199 200 reason_val = abort_dict.GetValueForKey("reason") 201 self.assertTrue(reason_val.IsValid(), "Got a reason key") 202 self.assertEqual( 203 reason_val.GetStringValue(100), 204 correct_values["reason_no_quote"], 205 "reason right in dictionary", 206 ) 207 208 flags_val = abort_dict.GetValueForKey("flags") 209 self.assertTrue(flags_val.IsValid(), "Got a flags value") 210 self.assertEqual( 211 flags_val.GetIntegerValue(0), 212 correct_values["flags"], 213 "flags right in dictionary", 214 ) 215