from __future__ import print_function import gdbremote_testcase from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * from lldbsuite.test import lldbutil class TestGdbRemoteRegisterState(gdbremote_testcase.GdbRemoteTestCaseBase): """Test QSaveRegisterState/QRestoreRegisterState support.""" mydir = TestBase.compute_mydir(__file__) def grp_register_save_restore_works(self, with_suffix): # Start up the process, use thread suffix, grab main thread id. inferior_args = ["message:main entered", "sleep:5"] procs = self.prep_debug_monitor_and_inferior( inferior_args=inferior_args) self.add_process_info_collection_packets() self.add_register_info_collection_packets() if with_suffix: self.add_thread_suffix_request_packets() self.add_threadinfo_collection_packets() self.test_sequence.add_log_lines([ # Start the inferior... "read packet: $c#63", # ... match output.... {"type": "output_match", "regex": self.maybe_strict_output_regex( r"message:main entered\r\n")}, ], True) # ... then interrupt. self.add_interrupt_packets() context = self.expect_gdbremote_sequence() self.assertIsNotNone(context) # Gather process info. process_info = self.parse_process_info_response(context) endian = process_info.get("endian") self.assertIsNotNone(endian) # Gather register info. reg_infos = self.parse_register_info_packets(context) self.assertIsNotNone(reg_infos) self.add_lldb_register_index(reg_infos) # Pull out the register infos that we think we can bit flip # successfully. gpr_reg_infos = [ reg_info for reg_info in reg_infos if self.is_bit_flippable_register(reg_info)] self.assertTrue(len(gpr_reg_infos) > 0) # Gather thread info. if with_suffix: threads = self.parse_threadinfo_packets(context) self.assertIsNotNone(threads) thread_id = threads[0] self.assertIsNotNone(thread_id) # print("Running on thread: 0x{:x}".format(thread_id)) else: thread_id = None # Save register state. self.reset_test_sequence() self.add_QSaveRegisterState_packets(thread_id) context = self.expect_gdbremote_sequence() self.assertIsNotNone(context) (success, state_id) = self.parse_QSaveRegisterState_response(context) self.assertTrue(success) self.assertIsNotNone(state_id) # print("saved register state id: {}".format(state_id)) # Remember initial register values. initial_reg_values = self.read_register_values( gpr_reg_infos, endian, thread_id=thread_id) # print("initial_reg_values: {}".format(initial_reg_values)) # Flip gpr register values. (successful_writes, failed_writes) = self.flip_all_bits_in_each_register_value( gpr_reg_infos, endian, thread_id=thread_id) # print("successful writes: {}, failed writes: {}".format(successful_writes, failed_writes)) self.assertTrue(successful_writes > 0) flipped_reg_values = self.read_register_values( gpr_reg_infos, endian, thread_id=thread_id) # print("flipped_reg_values: {}".format(flipped_reg_values)) # Restore register values. self.reset_test_sequence() self.add_QRestoreRegisterState_packets(state_id, thread_id) context = self.expect_gdbremote_sequence() self.assertIsNotNone(context) # Verify registers match initial register values. final_reg_values = self.read_register_values( gpr_reg_infos, endian, thread_id=thread_id) # print("final_reg_values: {}".format(final_reg_values)) self.assertIsNotNone(final_reg_values) self.assertEqual(final_reg_values, initial_reg_values) @debugserver_test def test_grp_register_save_restore_works_with_suffix_debugserver(self): USE_THREAD_SUFFIX = True self.init_debugserver_test() self.build() self.set_inferior_startup_launch() self.grp_register_save_restore_works(USE_THREAD_SUFFIX) @llgs_test def test_grp_register_save_restore_works_with_suffix_llgs(self): USE_THREAD_SUFFIX = True self.init_llgs_test() self.build() self.set_inferior_startup_launch() self.grp_register_save_restore_works(USE_THREAD_SUFFIX) @debugserver_test def test_grp_register_save_restore_works_no_suffix_debugserver(self): USE_THREAD_SUFFIX = False self.init_debugserver_test() self.build() self.set_inferior_startup_launch() self.grp_register_save_restore_works(USE_THREAD_SUFFIX) @llgs_test def test_grp_register_save_restore_works_no_suffix_llgs(self): USE_THREAD_SUFFIX = False self.init_llgs_test() self.build() self.set_inferior_startup_launch() self.grp_register_save_restore_works(USE_THREAD_SUFFIX)