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