199451b44SJordan Rupprecht"""Test that backtraces can follow cross-object tail calls""" 299451b44SJordan Rupprecht 399451b44SJordan Rupprecht 499451b44SJordan Rupprecht 599451b44SJordan Rupprechtimport lldb 699451b44SJordan Rupprechtfrom lldbsuite.test.decorators import * 799451b44SJordan Rupprechtfrom lldbsuite.test.lldbtest import * 899451b44SJordan Rupprechtfrom lldbsuite.test import lldbutil 999451b44SJordan Rupprecht 1099451b44SJordan Rupprecht 1199451b44SJordan Rupprechtclass TestCrossObjectTailCalls(TestBase): 1299451b44SJordan Rupprecht 1399451b44SJordan Rupprecht def setUp(self): 1499451b44SJordan Rupprecht TestBase.setUp(self) 1599451b44SJordan Rupprecht 16*98e2b1a8SRaphael Isemann @skipIf(compiler="clang", compiler_version=['<', '10.0']) 1799451b44SJordan Rupprecht @skipIf(dwarf_version=['<', '4']) 1899451b44SJordan Rupprecht @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr26265") 1999451b44SJordan Rupprecht @expectedFailureAll(archs=['arm', 'aarch64'], bugnumber="llvm.org/PR44561") 2099451b44SJordan Rupprecht def test_cross_object_tail_calls(self): 2199451b44SJordan Rupprecht self.build() 2299451b44SJordan Rupprecht exe = self.getBuildArtifact("a.out") 2399451b44SJordan Rupprecht target = self.dbg.CreateTarget(exe) 2499451b44SJordan Rupprecht self.assertTrue(target, VALID_TARGET) 2599451b44SJordan Rupprecht 2699451b44SJordan Rupprecht lldbutil.run_break_set_by_source_regexp(self, '// break here', 2799451b44SJordan Rupprecht extra_options='-f Two.c') 2899451b44SJordan Rupprecht 2999451b44SJordan Rupprecht process = target.LaunchSimple( 3099451b44SJordan Rupprecht None, None, self.get_process_working_directory()) 3199451b44SJordan Rupprecht self.assertTrue(process, PROCESS_IS_VALID) 3299451b44SJordan Rupprecht 3399451b44SJordan Rupprecht # We should be stopped in the second dylib. 3499451b44SJordan Rupprecht thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonBreakpoint) 3599451b44SJordan Rupprecht 3699451b44SJordan Rupprecht # Debug helper: 3799451b44SJordan Rupprecht # self.runCmd("log enable -f /tmp/lldb.log lldb step") 3899451b44SJordan Rupprecht # self.runCmd("bt") 3999451b44SJordan Rupprecht 4099451b44SJordan Rupprecht # Check that the backtrace is what we expect: 4199451b44SJordan Rupprecht # frame #0: 0x000000010be73f94 a.out`tail_called_in_b_from_b at Two.c:7:3 [opt] 4299451b44SJordan Rupprecht # frame #1: 0x000000010be73fa0 a.out`tail_called_in_b_from_a at Two.c:8:1 [opt] [artificial] 4399451b44SJordan Rupprecht # frame #2: 0x000000010be73f80 a.out`helper_in_a at One.c:11:1 [opt] [artificial] 4499451b44SJordan Rupprecht # frame #3: 0x000000010be73f79 a.out`tail_called_in_a_from_main at One.c:10:3 [opt] 4599451b44SJordan Rupprecht # frame #4: 0x000000010be73f60 a.out`helper at main.c:11:3 [opt] [artificial] 4699451b44SJordan Rupprecht # frame #5: 0x000000010be73f59 a.out`main at main.c:10:3 [opt] 4799451b44SJordan Rupprecht expected_frames = [ 4899451b44SJordan Rupprecht ("tail_called_in_b_from_b", False), 4999451b44SJordan Rupprecht ("tail_called_in_b_from_a", True), 5099451b44SJordan Rupprecht ("helper_in_a", True), 5199451b44SJordan Rupprecht ("tail_called_in_a_from_main", False), 5299451b44SJordan Rupprecht ("helper", True), 5399451b44SJordan Rupprecht ("main", False) 5499451b44SJordan Rupprecht ] 5599451b44SJordan Rupprecht for idx, (name, is_artificial) in enumerate(expected_frames): 5699451b44SJordan Rupprecht frame = thread.GetFrameAtIndex(idx) 573cc37622SDave Lee self.assertIn(name, frame.GetDisplayFunctionName()) 5899451b44SJordan Rupprecht self.assertEqual(frame.IsArtificial(), is_artificial) 59