1import gdbremote_testcase
2from lldbsuite.test.decorators import *
3from lldbsuite.test.lldbtest import *
4from lldbsuite.test import lldbutil
5
6
7class TestGdbRemoteRegisterState(gdbremote_testcase.GdbRemoteTestCaseBase):
8    """Test QSaveRegisterState/QRestoreRegisterState support."""
9
10    mydir = TestBase.compute_mydir(__file__)
11
12    @skipIfDarwinEmbedded # <rdar://problem/34539270> lldb-server tests not updated to work on ios etc yet
13    def grp_register_save_restore_works(self, with_suffix):
14        # Start up the process, use thread suffix, grab main thread id.
15        inferior_args = ["message:main entered", "sleep:5"]
16        procs = self.prep_debug_monitor_and_inferior(
17            inferior_args=inferior_args)
18
19        self.add_process_info_collection_packets()
20        self.add_register_info_collection_packets()
21        if with_suffix:
22            self.add_thread_suffix_request_packets()
23        self.add_threadinfo_collection_packets()
24
25        context = self.expect_gdbremote_sequence()
26        self.assertIsNotNone(context)
27
28        # Gather process info.
29        process_info = self.parse_process_info_response(context)
30        endian = process_info.get("endian")
31        self.assertIsNotNone(endian)
32
33        # Gather register info.
34        reg_infos = self.parse_register_info_packets(context)
35        self.assertIsNotNone(reg_infos)
36        self.add_lldb_register_index(reg_infos)
37
38        # Pull out the register infos that we think we can bit flip
39        # successfully.
40        gpr_reg_infos = [
41            reg_info for reg_info in reg_infos if self.is_bit_flippable_register(reg_info)]
42        self.assertTrue(len(gpr_reg_infos) > 0)
43
44        # Gather thread info.
45        if with_suffix:
46            threads = self.parse_threadinfo_packets(context)
47            self.assertIsNotNone(threads)
48            thread_id = threads[0]
49            self.assertIsNotNone(thread_id)
50            self.trace("Running on thread: 0x{:x}".format(thread_id))
51        else:
52            thread_id = None
53
54        # Save register state.
55        self.reset_test_sequence()
56        self.add_QSaveRegisterState_packets(thread_id)
57
58        context = self.expect_gdbremote_sequence()
59        self.assertIsNotNone(context)
60
61        (success, state_id) = self.parse_QSaveRegisterState_response(context)
62        self.assertTrue(success)
63        self.assertIsNotNone(state_id)
64        self.trace("saved register state id: {}".format(state_id))
65
66        # Remember initial register values.
67        initial_reg_values = self.read_register_values(
68            gpr_reg_infos, endian, thread_id=thread_id)
69        self.trace("initial_reg_values: {}".format(initial_reg_values))
70
71        # Flip gpr register values.
72        (successful_writes, failed_writes) = self.flip_all_bits_in_each_register_value(
73            gpr_reg_infos, endian, thread_id=thread_id)
74        self.trace("successful writes: {}, failed writes: {}".format(successful_writes, failed_writes))
75        self.assertTrue(successful_writes > 0)
76
77        flipped_reg_values = self.read_register_values(
78            gpr_reg_infos, endian, thread_id=thread_id)
79        self.trace("flipped_reg_values: {}".format(flipped_reg_values))
80
81        # Restore register values.
82        self.reset_test_sequence()
83        self.add_QRestoreRegisterState_packets(state_id, thread_id)
84
85        context = self.expect_gdbremote_sequence()
86        self.assertIsNotNone(context)
87
88        # Verify registers match initial register values.
89        final_reg_values = self.read_register_values(
90            gpr_reg_infos, endian, thread_id=thread_id)
91        self.trace("final_reg_values: {}".format(final_reg_values))
92        self.assertIsNotNone(final_reg_values)
93        self.assertEqual(final_reg_values, initial_reg_values)
94
95    @debugserver_test
96    def test_grp_register_save_restore_works_with_suffix_debugserver(self):
97        USE_THREAD_SUFFIX = True
98        self.init_debugserver_test()
99        self.build()
100        self.set_inferior_startup_launch()
101        self.grp_register_save_restore_works(USE_THREAD_SUFFIX)
102
103    @llgs_test
104    def test_grp_register_save_restore_works_with_suffix_llgs(self):
105        USE_THREAD_SUFFIX = True
106        self.init_llgs_test()
107        self.build()
108        self.set_inferior_startup_launch()
109        self.grp_register_save_restore_works(USE_THREAD_SUFFIX)
110
111    @debugserver_test
112    def test_grp_register_save_restore_works_no_suffix_debugserver(self):
113        USE_THREAD_SUFFIX = False
114        self.init_debugserver_test()
115        self.build()
116        self.set_inferior_startup_launch()
117        self.grp_register_save_restore_works(USE_THREAD_SUFFIX)
118
119    @llgs_test
120    def test_grp_register_save_restore_works_no_suffix_llgs(self):
121        USE_THREAD_SUFFIX = False
122        self.init_llgs_test()
123        self.build()
124        self.set_inferior_startup_launch()
125        self.grp_register_save_restore_works(USE_THREAD_SUFFIX)
126