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