1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
|
from __future__ import print_function
import use_lldb_suite
import gdbremote_testcase
from lldbtest import *
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":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)
|