brintos

brintos / llvm-project-archived public Read only

0
0
Text · 6.4 KiB · 38cf5fc Raw
155 lines · python
1import lldb2import time3import unittest4from lldbsuite.test.lldbtest import *5from lldbsuite.test.decorators import *6from lldbsuite.test.gdbclientutils import *7from lldbsuite.test.lldbreverse import ReverseTestBase8from lldbsuite.test import lldbutil9 10 11class TestReverseContinueWatchpoints(ReverseTestBase):12    @skipIfRemote13    # Watchpoints don't work in single-step mode14    @skipIf(macos_version=["<", "15.0"], archs=["arm64"])15    def test_reverse_continue_watchpoint(self):16        self.reverse_continue_watchpoint_internal(async_mode=False)17 18    @skipIfRemote19    # Watchpoints don't work in single-step mode20    @skipIf(macos_version=["<", "15.0"], archs=["arm64"])21    def test_reverse_continue_watchpoint_async(self):22        self.reverse_continue_watchpoint_internal(async_mode=True)23 24    def reverse_continue_watchpoint_internal(self, async_mode):25        target, process, initial_threads, watch_addr = self.setup_recording(async_mode)26 27        error = lldb.SBError()28        wp_opts = lldb.SBWatchpointOptions()29        wp_opts.SetWatchpointTypeWrite(lldb.eWatchpointWriteTypeOnModify)30        watchpoint = target.WatchpointCreateByAddress(watch_addr, 4, wp_opts, error)31        self.assertTrue(watchpoint)32 33        watch_var = target.EvaluateExpression("*g_watched_var_ptr")34        self.assertEqual(watch_var.GetValueAsSigned(-1), 2)35 36        # Reverse-continue to the function "trigger_watchpoint".37        status = process.ContinueInDirection(lldb.eRunReverse)38        self.assertSuccess(status)39        self.expect_async_state_changes(40            async_mode, process, [lldb.eStateRunning, lldb.eStateStopped]41        )42        # We should stop at the point just before the location was modified.43        watch_var = target.EvaluateExpression("*g_watched_var_ptr")44        self.assertEqual(watch_var.GetValueAsSigned(-1), 1)45        self.expect(46            "thread list",47            STOPPED_DUE_TO_WATCHPOINT,48            substrs=["stopped", "trigger_watchpoint", "stop reason = watchpoint 1"],49        )50 51        # Stepping forward one instruction should change the value of the variable.52        initial_threads[0].StepInstruction(False)53        self.expect_async_state_changes(54            async_mode, process, [lldb.eStateRunning, lldb.eStateStopped]55        )56        watch_var = target.EvaluateExpression("*g_watched_var_ptr")57        self.assertEqual(watch_var.GetValueAsSigned(-1), 2)58        self.expect(59            "thread list",60            STOPPED_DUE_TO_WATCHPOINT,61            substrs=["stopped", "trigger_watchpoint", "stop reason = watchpoint 1"],62        )63 64    @skipIfRemote65    # Watchpoints don't work in single-step mode66    @skipIf(macos_version=["<", "15.0"], archs=["arm64"])67    @skipIf(68        oslist=["windows"],69        archs=["x86_64"],70        bugnumber="github.com/llvm/llvm-project/issues/138084",71    )72    def test_reverse_continue_skip_watchpoint(self):73        self.reverse_continue_skip_watchpoint_internal(async_mode=False)74 75    @skipIfRemote76    # Watchpoints don't work in single-step mode77    @skipIf(macos_version=["<", "15.0"], archs=["arm64"])78    @skipIf(79        oslist=["windows"],80        archs=["x86_64"],81        bugnumber="github.com/llvm/llvm-project/issues/138084",82    )83    def test_reverse_continue_skip_watchpoint_async(self):84        self.reverse_continue_skip_watchpoint_internal(async_mode=True)85 86    def reverse_continue_skip_watchpoint_internal(self, async_mode):87        target, process, initial_threads, watch_addr = self.setup_recording(async_mode)88 89        # Reverse-continue over a watchpoint whose condition is false90        # (via function call).91        # This tests that we continue in the correct direction after hitting92        # the watchpoint.93        error = lldb.SBError()94        wp_opts = lldb.SBWatchpointOptions()95        wp_opts.SetWatchpointTypeWrite(lldb.eWatchpointWriteTypeOnModify)96        watchpoint = target.WatchpointCreateByAddress(watch_addr, 4, wp_opts, error)97        self.assertTrue(watchpoint)98        watchpoint.SetCondition("false_condition()")99        status = process.ContinueInDirection(lldb.eRunReverse)100        self.expect_async_state_changes(101            async_mode, process, [lldb.eStateRunning, lldb.eStateStopped]102        )103        self.assertSuccess(status)104        self.expect(105            "thread list",106            STOPPED_DUE_TO_HISTORY_BOUNDARY,107            substrs=["stopped", "stop reason = history boundary"],108        )109 110    def setup_recording(self, async_mode):111        """112        Record execution of code between "start_recording" and "stop_recording" breakpoints.113 114        Returns with the target stopped at "stop_recording", with recording disabled,115        ready to reverse-execute.116        """117        self.build()118        target = self.dbg.CreateTarget(self.getBuildArtifact("a.out"))119        process = self.connect(target)120 121        # Record execution from the start of the function "start_recording"122        # to the start of the function "stop_recording". We want to keep the123        # interval that we record as small as possible to minimize the run-time124        # of our single-stepping recorder.125        start_recording_bkpt = target.BreakpointCreateByName("start_recording", None)126        self.assertTrue(start_recording_bkpt.GetNumLocations() > 0)127        initial_threads = lldbutil.continue_to_breakpoint(process, start_recording_bkpt)128        self.assertEqual(len(initial_threads), 1)129        target.BreakpointDelete(start_recording_bkpt.GetID())130 131        frame0 = initial_threads[0].GetFrameAtIndex(0)132        watched_var_ptr = frame0.FindValue(133            "g_watched_var_ptr", lldb.eValueTypeVariableGlobal134        )135        watch_addr = watched_var_ptr.GetValueAsUnsigned(0)136        self.assertTrue(watch_addr > 0)137 138        self.start_recording()139        stop_recording_bkpt = target.BreakpointCreateByName("stop_recording", None)140        self.assertTrue(stop_recording_bkpt.GetNumLocations() > 0)141        lldbutil.continue_to_breakpoint(process, stop_recording_bkpt)142        target.BreakpointDelete(stop_recording_bkpt.GetID())143        self.stop_recording()144 145        self.dbg.SetAsync(async_mode)146        self.expect_async_state_changes(async_mode, process, [lldb.eStateStopped])147 148        return target, process, initial_threads, watch_addr149 150    def expect_async_state_changes(self, async_mode, process, states):151        if not async_mode:152            return153        listener = self.dbg.GetListener()154        lldbutil.expect_state_changes(self, listener, process, states)155