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 def grp_register_save_restore_works(self, with_suffix): 11 # Start up the process, use thread suffix, grab main thread id. 12 inferior_args = ["message:main entered", "sleep:5"] 13 procs = self.prep_debug_monitor_and_inferior( 14 inferior_args=inferior_args) 15 16 self.add_process_info_collection_packets() 17 self.add_register_info_collection_packets() 18 if with_suffix: 19 self.add_thread_suffix_request_packets() 20 self.add_threadinfo_collection_packets() 21 22 context = self.expect_gdbremote_sequence() 23 self.assertIsNotNone(context) 24 25 # Gather process info. 26 process_info = self.parse_process_info_response(context) 27 endian = process_info.get("endian") 28 self.assertIsNotNone(endian) 29 30 # Gather register info. 31 reg_infos = self.parse_register_info_packets(context) 32 self.assertIsNotNone(reg_infos) 33 self.add_lldb_register_index(reg_infos) 34 35 # Pull out the register infos that we think we can bit flip 36 # successfully. 37 gpr_reg_infos = [ 38 reg_info for reg_info in reg_infos if self.is_bit_flippable_register(reg_info)] 39 self.assertTrue(len(gpr_reg_infos) > 0) 40 41 # Gather thread info. 42 if with_suffix: 43 threads = self.parse_threadinfo_packets(context) 44 self.assertIsNotNone(threads) 45 thread_id = threads[0] 46 self.assertIsNotNone(thread_id) 47 self.trace("Running on thread: 0x{:x}".format(thread_id)) 48 else: 49 thread_id = None 50 51 # Save register state. 52 self.reset_test_sequence() 53 self.add_QSaveRegisterState_packets(thread_id) 54 55 context = self.expect_gdbremote_sequence() 56 self.assertIsNotNone(context) 57 58 (success, state_id) = self.parse_QSaveRegisterState_response(context) 59 self.assertTrue(success) 60 self.assertIsNotNone(state_id) 61 self.trace("saved register state id: {}".format(state_id)) 62 63 # Remember initial register values. 64 initial_reg_values = self.read_register_values( 65 gpr_reg_infos, endian, thread_id=thread_id) 66 self.trace("initial_reg_values: {}".format(initial_reg_values)) 67 68 # Flip gpr register values. 69 (successful_writes, failed_writes) = self.flip_all_bits_in_each_register_value( 70 gpr_reg_infos, endian, thread_id=thread_id) 71 self.trace("successful writes: {}, failed writes: {}".format(successful_writes, failed_writes)) 72 self.assertTrue(successful_writes > 0) 73 74 flipped_reg_values = self.read_register_values( 75 gpr_reg_infos, endian, thread_id=thread_id) 76 self.trace("flipped_reg_values: {}".format(flipped_reg_values)) 77 78 # Restore register values. 79 self.reset_test_sequence() 80 self.add_QRestoreRegisterState_packets(state_id, thread_id) 81 82 context = self.expect_gdbremote_sequence() 83 self.assertIsNotNone(context) 84 85 # Verify registers match initial register values. 86 final_reg_values = self.read_register_values( 87 gpr_reg_infos, endian, thread_id=thread_id) 88 self.trace("final_reg_values: {}".format(final_reg_values)) 89 self.assertIsNotNone(final_reg_values) 90 self.assertEqual(final_reg_values, initial_reg_values) 91 92 def test_grp_register_save_restore_works_with_suffix(self): 93 USE_THREAD_SUFFIX = True 94 self.build() 95 self.set_inferior_startup_launch() 96 self.grp_register_save_restore_works(USE_THREAD_SUFFIX) 97 98 def test_grp_register_save_restore_works_no_suffix(self): 99 USE_THREAD_SUFFIX = False 100 self.build() 101 self.set_inferior_startup_launch() 102 self.grp_register_save_restore_works(USE_THREAD_SUFFIX) 103