215 lines · python
1"""2Test that the FrameRecognizer for __abort_with_payload3works properly4"""5 6 7import lldb8from lldbsuite.test.decorators import *9import lldbsuite.test.lldbutil as lldbutil10from lldbsuite.test.lldbtest import *11 12 13class TestAbortWithPayload(TestBase):14 NO_DEBUG_INFO_TESTCASE = True15 16 @skipUnlessAppleSilicon17 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 @skipUnlessAppleSilicon23 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.unsigned50 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.unsigned54 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.stop_description,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 caller107 # was abort_with_reason or abort_with_payload or any future API that108 # funnels here. Since I don't want to have to know too much about the109 # 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