2 Test that we can backtrace correctly with 'noreturn' functions on the stack
5 from __future__ import print_function
11 from lldbsuite.test.decorators import *
12 from lldbsuite.test.lldbtest import *
13 from lldbsuite.test import lldbutil
16 class NoreturnUnwind(TestBase):
17 mydir = TestBase.compute_mydir(__file__)
19 @skipIfWindows # clang-cl does not support gcc style attributes.
20 # clang does not preserve LR in noreturn functions, making unwinding impossible
21 @skipIf(compiler="clang", archs=['arm'], oslist=['linux'])
22 @expectedFailureAll(bugnumber="llvm.org/pr33452", triple='^mips')
24 """Test that we can backtrace correctly with 'noreturn' functions on the stack"""
26 self.setTearDownCleanup()
28 exe = self.getBuildArtifact("a.out")
29 target = self.dbg.CreateTarget(exe)
30 self.assertTrue(target, VALID_TARGET)
32 process = target.LaunchSimple(
33 None, None, self.get_process_working_directory())
36 self.fail("SBTarget.Launch() failed")
38 if process.GetState() != lldb.eStateStopped:
39 self.fail("Process should be in the 'stopped' state, "
40 "instead the actual state is: '%s'" %
41 lldbutil.state_type_to_str(process.GetState()))
43 thread = process.GetThreadAtIndex(0)
44 abort_frame_number = 0
45 for f in thread.frames:
46 # Some C libraries mangle the abort symbol into __GI_abort.
47 if f.GetFunctionName() in ["abort", "__GI_abort"]:
49 abort_frame_number = abort_frame_number + 1
52 print("Backtrace once we're stopped:")
53 for f in thread.frames:
54 print(" %d %s" % (f.GetFrameID(), f.GetFunctionName()))
56 # I'm going to assume that abort() ends up calling/invoking another
57 # function before halting the process. In which case if abort_frame_number
58 # equals 0, we didn't find abort() in the backtrace.
59 if abort_frame_number == len(thread.frames):
60 self.fail("Unable to find abort() in backtrace.")
62 func_c_frame_number = abort_frame_number + 1
63 if thread.GetFrameAtIndex(
64 func_c_frame_number).GetFunctionName() != "func_c":
65 self.fail("Did not find func_c() above abort().")
67 # This depends on whether we see the func_b inlined function in the backtrace
68 # or not. I'm not interested in testing that aspect of the backtrace here
71 if thread.GetFrameAtIndex(
73 1).GetFunctionName() == "func_b":
74 func_a_frame_number = func_c_frame_number + 2
76 func_a_frame_number = func_c_frame_number + 1
78 if thread.GetFrameAtIndex(
79 func_a_frame_number).GetFunctionName() != "func_a":
80 self.fail("Did not find func_a() above func_c().")
82 main_frame_number = func_a_frame_number + 1
84 if thread.GetFrameAtIndex(
85 main_frame_number).GetFunctionName() != "main":
86 self.fail("Did not find main() above func_a().")