1 import gdbremote_testcase
2 from lldbsuite
.test
.decorators
import *
3 from lldbsuite
.test
.lldbtest
import *
4 from lldbsuite
.test
import lldbutil
7 class TestGdbRemoteRegisterState(gdbremote_testcase
.GdbRemoteTestCaseBase
):
8 """Test QSaveRegisterState/QRestoreRegisterState support."""
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
)
15 self
.add_process_info_collection_packets()
16 self
.add_register_info_collection_packets()
18 self
.add_thread_suffix_request_packets()
19 self
.add_threadinfo_collection_packets()
21 context
= self
.expect_gdbremote_sequence()
22 self
.assertIsNotNone(context
)
24 # Gather process info.
25 process_info
= self
.parse_process_info_response(context
)
26 endian
= process_info
.get("endian")
27 self
.assertIsNotNone(endian
)
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
)
34 # Pull out the register infos that we think we can bit flip
38 for reg_info
in reg_infos
39 if self
.is_bit_flippable_register(reg_info
)
41 self
.assertTrue(len(gpr_reg_infos
) > 0)
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
))
53 # Save register state.
54 self
.reset_test_sequence()
55 self
.add_QSaveRegisterState_packets(thread_id
)
57 context
= self
.expect_gdbremote_sequence()
58 self
.assertIsNotNone(context
)
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
))
65 # Remember initial register values.
66 initial_reg_values
= self
.read_register_values(
67 gpr_reg_infos
, endian
, thread_id
=thread_id
69 self
.trace("initial_reg_values: {}".format(initial_reg_values
))
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
76 "successful writes: {}, failed writes: {}".format(
77 successful_writes
, failed_writes
80 self
.assertTrue(successful_writes
> 0)
82 flipped_reg_values
= self
.read_register_values(
83 gpr_reg_infos
, endian
, thread_id
=thread_id
85 self
.trace("flipped_reg_values: {}".format(flipped_reg_values
))
87 # Restore register values.
88 self
.reset_test_sequence()
89 self
.add_QRestoreRegisterState_packets(state_id
, thread_id
)
91 context
= self
.expect_gdbremote_sequence()
92 self
.assertIsNotNone(context
)
94 # Verify registers match initial register values.
95 final_reg_values
= self
.read_register_values(
96 gpr_reg_infos
, endian
, thread_id
=thread_id
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
)
102 def test_grp_register_save_restore_works_with_suffix(self
):
103 USE_THREAD_SUFFIX
= True
105 self
.set_inferior_startup_launch()
106 self
.grp_register_save_restore_works(USE_THREAD_SUFFIX
)
108 def test_grp_register_save_restore_works_no_suffix(self
):
109 USE_THREAD_SUFFIX
= False
111 self
.set_inferior_startup_launch()
112 self
.grp_register_save_restore_works(USE_THREAD_SUFFIX
)