134 lines
5.1 KiB
Python
134 lines
5.1 KiB
Python
import unittest2
|
|
|
|
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.assertEquals(final_reg_values, initial_reg_values)
|
|
|
|
@debugserver_test
|
|
@dsym_test
|
|
def test_grp_register_save_restore_works_with_suffix_debugserver_dsym(self):
|
|
USE_THREAD_SUFFIX = True
|
|
self.init_debugserver_test()
|
|
self.buildDsym()
|
|
self.set_inferior_startup_launch()
|
|
self.grp_register_save_restore_works(USE_THREAD_SUFFIX)
|
|
|
|
@expectedFailureLinux("https://llvm.org/bugs/show_bug.cgi?id=23251") # failing intermittently on the linux build bot
|
|
@llgs_test
|
|
@dwarf_test
|
|
def test_grp_register_save_restore_works_with_suffix_llgs_dwarf(self):
|
|
USE_THREAD_SUFFIX = True
|
|
self.init_llgs_test()
|
|
self.buildDwarf()
|
|
self.set_inferior_startup_launch()
|
|
self.grp_register_save_restore_works(USE_THREAD_SUFFIX)
|
|
|
|
@debugserver_test
|
|
@dsym_test
|
|
def test_grp_register_save_restore_works_no_suffix_debugserver_dsym(self):
|
|
USE_THREAD_SUFFIX = False
|
|
self.init_debugserver_test()
|
|
self.buildDsym()
|
|
self.set_inferior_startup_launch()
|
|
self.grp_register_save_restore_works(USE_THREAD_SUFFIX)
|
|
|
|
@llgs_test
|
|
@dwarf_test
|
|
def test_grp_register_save_restore_works_no_suffix_llgs_dwarf(self):
|
|
USE_THREAD_SUFFIX = False
|
|
self.init_llgs_test()
|
|
self.buildDwarf()
|
|
self.set_inferior_startup_launch()
|
|
self.grp_register_save_restore_works(USE_THREAD_SUFFIX)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
unittest2.main()
|