199451b44SJordan Rupprechtimport gdbremote_testcase
299451b44SJordan Rupprechtfrom lldbsuite.test.decorators import *
399451b44SJordan Rupprechtfrom lldbsuite.test.lldbtest import *
499451b44SJordan Rupprechtfrom lldbsuite.test import lldbutil
599451b44SJordan Rupprecht
699451b44SJordan Rupprecht
799451b44SJordan Rupprechtclass TestGdbRemoteRegisterState(gdbremote_testcase.GdbRemoteTestCaseBase):
899451b44SJordan Rupprecht    """Test QSaveRegisterState/QRestoreRegisterState support."""
999451b44SJordan Rupprecht
1099451b44SJordan Rupprecht    def grp_register_save_restore_works(self, with_suffix):
1199451b44SJordan Rupprecht        # Start up the process, use thread suffix, grab main thread id.
1299451b44SJordan Rupprecht        inferior_args = ["message:main entered", "sleep:5"]
1399451b44SJordan Rupprecht        procs = self.prep_debug_monitor_and_inferior(
1499451b44SJordan Rupprecht            inferior_args=inferior_args)
1599451b44SJordan Rupprecht
1699451b44SJordan Rupprecht        self.add_process_info_collection_packets()
1799451b44SJordan Rupprecht        self.add_register_info_collection_packets()
1899451b44SJordan Rupprecht        if with_suffix:
1999451b44SJordan Rupprecht            self.add_thread_suffix_request_packets()
2099451b44SJordan Rupprecht        self.add_threadinfo_collection_packets()
2199451b44SJordan Rupprecht
2299451b44SJordan Rupprecht        context = self.expect_gdbremote_sequence()
2399451b44SJordan Rupprecht        self.assertIsNotNone(context)
2499451b44SJordan Rupprecht
2599451b44SJordan Rupprecht        # Gather process info.
2699451b44SJordan Rupprecht        process_info = self.parse_process_info_response(context)
2799451b44SJordan Rupprecht        endian = process_info.get("endian")
2899451b44SJordan Rupprecht        self.assertIsNotNone(endian)
2999451b44SJordan Rupprecht
3099451b44SJordan Rupprecht        # Gather register info.
3199451b44SJordan Rupprecht        reg_infos = self.parse_register_info_packets(context)
3299451b44SJordan Rupprecht        self.assertIsNotNone(reg_infos)
3399451b44SJordan Rupprecht        self.add_lldb_register_index(reg_infos)
3499451b44SJordan Rupprecht
3599451b44SJordan Rupprecht        # Pull out the register infos that we think we can bit flip
3699451b44SJordan Rupprecht        # successfully.
3799451b44SJordan Rupprecht        gpr_reg_infos = [
3899451b44SJordan Rupprecht            reg_info for reg_info in reg_infos if self.is_bit_flippable_register(reg_info)]
3999451b44SJordan Rupprecht        self.assertTrue(len(gpr_reg_infos) > 0)
4099451b44SJordan Rupprecht
4199451b44SJordan Rupprecht        # Gather thread info.
4299451b44SJordan Rupprecht        if with_suffix:
4399451b44SJordan Rupprecht            threads = self.parse_threadinfo_packets(context)
4499451b44SJordan Rupprecht            self.assertIsNotNone(threads)
4599451b44SJordan Rupprecht            thread_id = threads[0]
4699451b44SJordan Rupprecht            self.assertIsNotNone(thread_id)
47b321b429SJonas Devlieghere            self.trace("Running on thread: 0x{:x}".format(thread_id))
4899451b44SJordan Rupprecht        else:
4999451b44SJordan Rupprecht            thread_id = None
5099451b44SJordan Rupprecht
5199451b44SJordan Rupprecht        # Save register state.
5299451b44SJordan Rupprecht        self.reset_test_sequence()
5399451b44SJordan Rupprecht        self.add_QSaveRegisterState_packets(thread_id)
5499451b44SJordan Rupprecht
5599451b44SJordan Rupprecht        context = self.expect_gdbremote_sequence()
5699451b44SJordan Rupprecht        self.assertIsNotNone(context)
5799451b44SJordan Rupprecht
5899451b44SJordan Rupprecht        (success, state_id) = self.parse_QSaveRegisterState_response(context)
5999451b44SJordan Rupprecht        self.assertTrue(success)
6099451b44SJordan Rupprecht        self.assertIsNotNone(state_id)
61b321b429SJonas Devlieghere        self.trace("saved register state id: {}".format(state_id))
6299451b44SJordan Rupprecht
6399451b44SJordan Rupprecht        # Remember initial register values.
6499451b44SJordan Rupprecht        initial_reg_values = self.read_register_values(
6599451b44SJordan Rupprecht            gpr_reg_infos, endian, thread_id=thread_id)
66b321b429SJonas Devlieghere        self.trace("initial_reg_values: {}".format(initial_reg_values))
6799451b44SJordan Rupprecht
6899451b44SJordan Rupprecht        # Flip gpr register values.
6999451b44SJordan Rupprecht        (successful_writes, failed_writes) = self.flip_all_bits_in_each_register_value(
7099451b44SJordan Rupprecht            gpr_reg_infos, endian, thread_id=thread_id)
71b321b429SJonas Devlieghere        self.trace("successful writes: {}, failed writes: {}".format(successful_writes, failed_writes))
7299451b44SJordan Rupprecht        self.assertTrue(successful_writes > 0)
7399451b44SJordan Rupprecht
7499451b44SJordan Rupprecht        flipped_reg_values = self.read_register_values(
7599451b44SJordan Rupprecht            gpr_reg_infos, endian, thread_id=thread_id)
76b321b429SJonas Devlieghere        self.trace("flipped_reg_values: {}".format(flipped_reg_values))
7799451b44SJordan Rupprecht
7899451b44SJordan Rupprecht        # Restore register values.
7999451b44SJordan Rupprecht        self.reset_test_sequence()
8099451b44SJordan Rupprecht        self.add_QRestoreRegisterState_packets(state_id, thread_id)
8199451b44SJordan Rupprecht
8299451b44SJordan Rupprecht        context = self.expect_gdbremote_sequence()
8399451b44SJordan Rupprecht        self.assertIsNotNone(context)
8499451b44SJordan Rupprecht
8599451b44SJordan Rupprecht        # Verify registers match initial register values.
8699451b44SJordan Rupprecht        final_reg_values = self.read_register_values(
8799451b44SJordan Rupprecht            gpr_reg_infos, endian, thread_id=thread_id)
88b321b429SJonas Devlieghere        self.trace("final_reg_values: {}".format(final_reg_values))
8999451b44SJordan Rupprecht        self.assertIsNotNone(final_reg_values)
9099451b44SJordan Rupprecht        self.assertEqual(final_reg_values, initial_reg_values)
9199451b44SJordan Rupprecht
92*0a8a2453SPavel Labath    def test_grp_register_save_restore_works_with_suffix(self):
9399451b44SJordan Rupprecht        USE_THREAD_SUFFIX = True
9499451b44SJordan Rupprecht        self.build()
9599451b44SJordan Rupprecht        self.set_inferior_startup_launch()
9699451b44SJordan Rupprecht        self.grp_register_save_restore_works(USE_THREAD_SUFFIX)
9799451b44SJordan Rupprecht
98*0a8a2453SPavel Labath    def test_grp_register_save_restore_works_no_suffix(self):
9999451b44SJordan Rupprecht        USE_THREAD_SUFFIX = False
10099451b44SJordan Rupprecht        self.build()
10199451b44SJordan Rupprecht        self.set_inferior_startup_launch()
10299451b44SJordan Rupprecht        self.grp_register_save_restore_works(USE_THREAD_SUFFIX)
103