"""
Test that we can backtrace correctly with 'noreturn' functions on the stack
"""

from __future__ import print_function


import os
import time
import lldb
from lldbsuite.test.decorators import *
from lldbsuite.test.lldbtest import *
from lldbsuite.test import lldbutil


class NoreturnUnwind(TestBase):
    mydir = TestBase.compute_mydir(__file__)

    @skipIfWindows  # clang-cl does not support gcc style attributes.
    # clang does not preserve LR in noreturn functions, making unwinding impossible
    @skipIf(compiler="clang", archs=['arm'], oslist=['linux'])
    @expectedFailureAll(bugnumber="llvm.org/pr33452", triple='^mips')
    def test(self):
        """Test that we can backtrace correctly with 'noreturn' functions on the stack"""
        self.build()
        self.setTearDownCleanup()

        exe = self.getBuildArtifact("a.out")
        target = self.dbg.CreateTarget(exe)
        self.assertTrue(target, VALID_TARGET)

        process = target.LaunchSimple(
            None, None, self.get_process_working_directory())

        if not process:
            self.fail("SBTarget.Launch() failed")

        if process.GetState() != lldb.eStateStopped:
            self.fail("Process should be in the 'stopped' state, "
                      "instead the actual state is: '%s'" %
                      lldbutil.state_type_to_str(process.GetState()))

        thread = process.GetThreadAtIndex(0)
        abort_frame_number = 0
        for f in thread.frames:
            # Some C libraries mangle the abort symbol into __GI_abort.
            if f.GetFunctionName() in ["abort", "__GI_abort"]:
                break
            abort_frame_number = abort_frame_number + 1

        if self.TraceOn():
            print("Backtrace once we're stopped:")
            for f in thread.frames:
                print("  %d %s" % (f.GetFrameID(), f.GetFunctionName()))

        # I'm going to assume that abort() ends up calling/invoking another
        # function before halting the process.  In which case if abort_frame_number
        # equals 0, we didn't find abort() in the backtrace.
        if abort_frame_number == len(thread.frames):
            self.fail("Unable to find abort() in backtrace.")

        func_c_frame_number = abort_frame_number + 1
        if thread.GetFrameAtIndex(
                func_c_frame_number).GetFunctionName() != "func_c":
            self.fail("Did not find func_c() above abort().")

        # This depends on whether we see the func_b inlined function in the backtrace
        # or not.  I'm not interested in testing that aspect of the backtrace here
        # right now.

        if thread.GetFrameAtIndex(
                func_c_frame_number +
                1).GetFunctionName() == "func_b":
            func_a_frame_number = func_c_frame_number + 2
        else:
            func_a_frame_number = func_c_frame_number + 1

        if thread.GetFrameAtIndex(
                func_a_frame_number).GetFunctionName() != "func_a":
            self.fail("Did not find func_a() above func_c().")

        main_frame_number = func_a_frame_number + 1

        if thread.GetFrameAtIndex(
                main_frame_number).GetFunctionName() != "main":
            self.fail("Did not find main() above func_a().")
