summaryrefslogtreecommitdiffstats
path: root/lldb/test/tools/lldb-gdbserver/TestLldbGdbServer.py
diff options
context:
space:
mode:
authorTodd Fiala <todd.fiala@gmail.com>2014-05-19 22:35:24 +0000
committerTodd Fiala <todd.fiala@gmail.com>2014-05-19 22:35:24 +0000
commit62b2317fd878cf321ccf7e24bca840abf0c81358 (patch)
tree99ff02d7c18435ba18146ed35cb2a6fcda37b8c0 /lldb/test/tools/lldb-gdbserver/TestLldbGdbServer.py
parent1be902c02f1d98e89bb173447d4ee5faf04433e1 (diff)
downloadbcm5719-llvm-62b2317fd878cf321ccf7e24bca840abf0c81358.tar.gz
bcm5719-llvm-62b2317fd878cf321ccf7e24bca840abf0c81358.zip
Added gdb remote protocol tests across all qRegisterInfo responses.
Added support for gdb remote protocol capture/playback where there is a query/multiple-response pattern. The new playback entry supports: - a general query command (key: next_query or query) - an optional first-query command if that differs from the subsequent queries (key: first_query) - an end regex for matching anything that would signify that the query/multi-response iteration has come to an end. An assumption is that the end regex is not a content package we care about aside from ending the iteration. (key: end_regex) - an optional 0-based index appended to the end of the query command (key: append_iteration_suffix), default: False. - a key used to collect responses from the query. Any response from the gdb remote that doesn't match the end-of-iteration regex is captured in the playback context dictionary using the key specified. That key will be an array, where each array entry is one of the responses from the query/multi-response iteration. (key: save_key). - a runaway response value, defaulting to 10k, where if this many responses is captured, assume the ending condition regex is invalid, or the debug monitor is doing something goofy that is going to blow out memory or time. (key: runaway_response_count, default: 10000) See the lldbgdbserverutils.MultiResponseGdbRemoteEntry class for details. A MultiResponseGdbRemoteEntry is added by adding an element to the GdbRemoteTestSequence (via GdbRemoteTestSequence.add_log_lines), using a dictionary, where the "type" key is set to "multi_response", and the rest of the keys in the dictionary entry are set to the keys documented for MultiResponseGdbRemoteEntry. Added helper functions to add the required entry to grab all qRegisterInfo responses. Added another helper to parse the qRegisterInfo response packets into an array of dictionaries, where each key:value in the dictionary comes from the register info response packet. Added a test to verify that a generic register exists for the program counter, frame pointer, stack pointer and cpu flags across all register info responses. Added a test to verify that at least one register set exists across all register info responses. llvm-svn: 209170
Diffstat (limited to 'lldb/test/tools/lldb-gdbserver/TestLldbGdbServer.py')
-rw-r--r--lldb/test/tools/lldb-gdbserver/TestLldbGdbServer.py172
1 files changed, 155 insertions, 17 deletions
diff --git a/lldb/test/tools/lldb-gdbserver/TestLldbGdbServer.py b/lldb/test/tools/lldb-gdbserver/TestLldbGdbServer.py
index 90f1ba2d36c..104bc8daae0 100644
--- a/lldb/test/tools/lldb-gdbserver/TestLldbGdbServer.py
+++ b/lldb/test/tools/lldb-gdbserver/TestLldbGdbServer.py
@@ -131,6 +131,21 @@ class LldbGdbServerTestCase(TestBase):
{ "direction":"send", "regex":r"^\$pid:([0-9a-fA-F]+);", "capture":{1:"pid"} }],
True)
+ def add_register_info_collection_packets(self):
+ self.test_sequence.add_log_lines(
+ [ { "type":"multi_response", "query":"qRegisterInfo", "append_iteration_suffix":True,
+ "end_regex":re.compile(r"^\$(E\d+)?#[0-9a-fA-F]{2}$"),
+ "save_key":"reg_info_responses" } ],
+ True)
+
+ def parse_register_info_packets(self, context):
+ """Return an array of register info dictionaries, one per register info."""
+ reg_info_responses = context.get("reg_info_responses")
+ self.assertIsNotNone(reg_info_responses)
+
+ # Parse register infos.
+ return [parse_reg_info_response(reg_info_response) for reg_info_response in reg_info_responses]
+
def expect_gdbremote_sequence(self):
return expect_lldb_gdbserver_replay(self, self.sock, self.test_sequence, self._TIMEOUT_SECONDS, self.logger)
@@ -149,24 +164,18 @@ class LldbGdbServerTestCase(TestBase):
"invalidate-regs"
]
- def assert_valid_reg_info_packet(self, reginfo_packet):
- keyval_pairs = reginfo_packet.split(";")
- self.assertTrue(len(keyval_pairs) >= 5)
-
- values = {}
- for kv in keyval_pairs:
- (key, val) = kv.split(':')
- values[key] = val
- # Ensure key is something we expect.
+ def assert_valid_reg_info(self, reg_info):
+ # Assert we know about all the reginfo keys parsed.
+ for key in reg_info:
self.assertTrue(key in self._KNOWN_REGINFO_KEYS)
# Check the bare-minimum expected set of register info keys.
- self.assertTrue("name" in values)
- self.assertTrue("bitsize" in values)
- self.assertTrue("offset" in values)
- self.assertTrue("encoding" in values)
- self.assertTrue("format" in values)
-
+ self.assertTrue("name" in reg_info)
+ self.assertTrue("bitsize" in reg_info)
+ self.assertTrue("offset" in reg_info)
+ self.assertTrue("encoding" in reg_info)
+ self.assertTrue("format" in reg_info)
+
@debugserver_test
def test_exe_starts_debugserver(self):
@@ -574,8 +583,10 @@ class LldbGdbServerTestCase(TestBase):
# Run the stream
context = self.expect_gdbremote_sequence()
self.assertIsNotNone(context)
- self.assertIsNotNone(context.get("reginfo_0"))
- self.assert_valid_reg_info_packet(context.get("reginfo_0"))
+
+ reg_info_packet = context.get("reginfo_0")
+ self.assertIsNotNone(reg_info_packet)
+ self.assert_valid_reg_info(parse_reg_info_response(reg_info_packet))
@debugserver_test
@dsym_test
@@ -592,5 +603,132 @@ class LldbGdbServerTestCase(TestBase):
self.buildDwarf()
self.qRegisterInfo_returns_one_valid_result()
+ def qRegisterInfo_returns_all_valid_results(self):
+ server = self.start_server()
+ self.assertIsNotNone(server)
+
+ # Build launch args.
+ launch_args = [os.path.abspath('a.out')]
+
+ # Build the expected protocol stream.
+ self.add_no_ack_remote_stream()
+ self.add_verified_launch_packets(launch_args)
+ self.add_register_info_collection_packets()
+
+ # Run the stream.
+ context = self.expect_gdbremote_sequence()
+ self.assertIsNotNone(context)
+
+ # Validate that each register info returned validates.
+ for reg_info in self.parse_register_info_packets(context):
+ self.assert_valid_reg_info(reg_info)
+
+ @debugserver_test
+ @dsym_test
+ def test_qRegisterInfo_returns_all_valid_results_debugserver_dsym(self):
+ self.init_debugserver_test()
+ self.buildDsym()
+ self.qRegisterInfo_returns_all_valid_results()
+
+ @llgs_test
+ @dwarf_test
+ @unittest2.expectedFailure()
+ def test_qRegisterInfo_returns_all_valid_results_llgs_dwarf(self):
+ self.init_llgs_test()
+ self.buildDwarf()
+ self.qRegisterInfo_returns_all_valid_results()
+
+ def qRegisterInfo_contains_required_generics(self):
+ server = self.start_server()
+ self.assertIsNotNone(server)
+
+ # Build launch args
+ launch_args = [os.path.abspath('a.out')]
+
+ # Build the expected protocol stream
+ self.add_no_ack_remote_stream()
+ self.add_verified_launch_packets(launch_args)
+ self.add_register_info_collection_packets()
+
+ # Run the packet stream.
+ context = self.expect_gdbremote_sequence()
+ self.assertIsNotNone(context)
+
+ # Gather register info entries.
+ reg_infos = self.parse_register_info_packets(context)
+
+ # Collect all generics found.
+ generic_regs = { reg_info['generic']:1 for reg_info in reg_infos if 'generic' in reg_info }
+
+ # Ensure we have a program counter register.
+ self.assertTrue('pc' in generic_regs)
+
+ # Ensure we have a frame pointer register.
+ self.assertTrue('fp' in generic_regs)
+
+ # Ensure we have a stack pointer register.
+ self.assertTrue('sp' in generic_regs)
+
+ # Ensure we have a flags register.
+ self.assertTrue('flags' in generic_regs)
+
+
+ @debugserver_test
+ @dsym_test
+ def test_qRegisterInfo_contains_required_generics_debugserver_dsym(self):
+ self.init_debugserver_test()
+ self.buildDsym()
+ self.qRegisterInfo_contains_required_generics()
+
+ @llgs_test
+ @dwarf_test
+ @unittest2.expectedFailure()
+ def test_qRegisterInfo_contains_required_generics_llgs_dwarf(self):
+ self.init_llgs_test()
+ self.buildDwarf()
+ self.qRegisterInfo_contains_required_generics()
+
+
+ def qRegisterInfo_contains_at_least_one_register_set(self):
+ server = self.start_server()
+ self.assertIsNotNone(server)
+
+ # Build launch args
+ launch_args = [os.path.abspath('a.out')]
+
+ # Build the expected protocol stream
+ self.add_no_ack_remote_stream()
+ self.add_verified_launch_packets(launch_args)
+ self.add_register_info_collection_packets()
+
+ # Run the packet stream.
+ context = self.expect_gdbremote_sequence()
+ self.assertIsNotNone(context)
+
+ # Gather register info entries.
+ reg_infos = self.parse_register_info_packets(context)
+
+ # Collect all generics found.
+ register_sets = { reg_info['set']:1 for reg_info in reg_infos if 'set' in reg_info }
+ self.assertTrue(len(register_sets) >= 1)
+
+
+ @debugserver_test
+ @dsym_test
+ def test_qRegisterInfo_contains_at_least_one_register_set_debugserver_dsym(self):
+ self.init_debugserver_test()
+ self.buildDsym()
+ self.qRegisterInfo_contains_at_least_one_register_set()
+
+
+ @llgs_test
+ @dwarf_test
+ @unittest2.expectedFailure()
+ def test_qRegisterInfo_contains_at_least_one_register_set_llgs_dwarf(self):
+ self.init_llgs_test()
+ self.buildDwarf()
+ self.qRegisterInfo_contains_at_least_one_register_set()
+
+
if __name__ == '__main__':
unittest2.main()
OpenPOWER on IntegriCloud