212 lines
		
	
	
		
			7.6 KiB
		
	
	
	
		
			Python
		
	
	
	
			
		
		
	
	
			212 lines
		
	
	
		
			7.6 KiB
		
	
	
	
		
			Python
		
	
	
	
| import unittest2
 | |
| 
 | |
| import gdbremote_testcase
 | |
| from lldbtest import *
 | |
| 
 | |
| class TestGdbRemoteAuxvSupport(gdbremote_testcase.GdbRemoteTestCaseBase):
 | |
| 
 | |
|     AUXV_SUPPORT_FEATURE_NAME = "qXfer:auxv:read"
 | |
| 
 | |
|     def has_auxv_support(self):
 | |
|         inferior_args = ["message:main entered", "sleep:5"]
 | |
|         procs = self.prep_debug_monitor_and_inferior(inferior_args=inferior_args)
 | |
| 
 | |
|         # Don't do anything until we match the launched inferior main entry output.
 | |
|         # Then immediately interrupt the process.
 | |
|         # This prevents auxv data being asked for before it's ready and leaves
 | |
|         # us in a stopped state.
 | |
|         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()
 | |
|         self.add_qSupported_packets()
 | |
| 
 | |
|         context = self.expect_gdbremote_sequence()
 | |
|         self.assertIsNotNone(context)
 | |
| 
 | |
|         features = self.parse_qSupported_response(context)
 | |
|         return self.AUXV_SUPPORT_FEATURE_NAME in features and features[self.AUXV_SUPPORT_FEATURE_NAME] == "+"
 | |
| 
 | |
|     def get_raw_auxv_data(self):
 | |
|         # Start up llgs and inferior, and check for auxv support.
 | |
|         if not self.has_auxv_support():
 | |
|             self.skipTest("auxv data not supported")
 | |
| 
 | |
|         # Grab pointer size for target.  We'll assume that is equivalent to an unsigned long on the target.
 | |
|         # Auxv is specified in terms of pairs of unsigned longs.
 | |
|         self.reset_test_sequence()
 | |
|         self.add_process_info_collection_packets()
 | |
| 
 | |
|         context = self.expect_gdbremote_sequence()
 | |
|         self.assertIsNotNone(context)
 | |
| 
 | |
|         proc_info = self.parse_process_info_response(context)
 | |
|         self.assertIsNotNone(proc_info)
 | |
|         self.assertTrue("ptrsize" in proc_info)
 | |
|         word_size = int(proc_info["ptrsize"])
 | |
| 
 | |
|         OFFSET = 0
 | |
|         LENGTH = 0x400
 | |
| 
 | |
|         # Grab the auxv data.
 | |
|         self.reset_test_sequence()
 | |
|         self.test_sequence.add_log_lines([
 | |
|             "read packet: $qXfer:auxv:read::{:x},{:x}:#00".format(OFFSET, LENGTH),
 | |
|             {"direction":"send", "regex":re.compile(r"^\$([^E])(.*)#[0-9a-fA-F]{2}$", re.MULTILINE|re.DOTALL), "capture":{1:"response_type", 2:"content_raw"} }
 | |
|             ], True)
 | |
| 
 | |
|         context = self.expect_gdbremote_sequence()
 | |
|         self.assertIsNotNone(context)
 | |
| 
 | |
|         # Ensure we end up with all auxv data in one packet.
 | |
|         # FIXME don't assume it all comes back in one packet.
 | |
|         self.assertEquals(context.get("response_type"), "l")
 | |
| 
 | |
|         # Decode binary data.
 | |
|         content_raw = context.get("content_raw")
 | |
|         self.assertIsNotNone(content_raw)
 | |
|         return (word_size, self.decode_gdbremote_binary(content_raw))
 | |
| 
 | |
|     def supports_auxv(self):
 | |
|         # When non-auxv platforms support llgs, skip the test on platforms
 | |
|         # that don't support auxv.
 | |
|         self.assertTrue(self.has_auxv_support())
 | |
| 
 | |
|     #
 | |
|     # We skip the "supports_auxv" test on debugserver.  The rest of the tests
 | |
|     # appropriately skip the auxv tests if the support flag is not present
 | |
|     # in the qSupported response, so the debugserver test bits are still there
 | |
|     # in case debugserver code one day does have auxv support and thus those
 | |
|     # tests don't get skipped.
 | |
|     #
 | |
| 
 | |
|     @llgs_test
 | |
|     @dwarf_test
 | |
|     def test_supports_auxv_llgs_dwarf(self):
 | |
|         self.init_llgs_test()
 | |
|         self.buildDwarf()
 | |
|         self.set_inferior_startup_launch()
 | |
|         self.supports_auxv()
 | |
| 
 | |
|     def auxv_data_is_correct_size(self):
 | |
|         (word_size, auxv_data) = self.get_raw_auxv_data()
 | |
|         self.assertIsNotNone(auxv_data)
 | |
| 
 | |
|         # Ensure auxv data is a multiple of 2*word_size (there should be two unsigned long fields per auxv entry).
 | |
|         self.assertEquals(len(auxv_data) % (2*word_size), 0)
 | |
|         # print "auxv contains {} entries".format(len(auxv_data) / (2*word_size))
 | |
| 
 | |
|     @debugserver_test
 | |
|     @dsym_test
 | |
|     def test_auxv_data_is_correct_size_debugserver_dsym(self):
 | |
|         self.init_debugserver_test()
 | |
|         self.buildDsym()
 | |
|         self.set_inferior_startup_launch()
 | |
|         self.auxv_data_is_correct_size()
 | |
| 
 | |
|     @llgs_test
 | |
|     @dwarf_test
 | |
|     @expectedFailureLinux('llvm.org/pr22930') # fails 2/34 builds on lldb-x86_64-ubuntu-14.04-cmake
 | |
|     def test_auxv_data_is_correct_size_llgs_dwarf(self):
 | |
|         self.init_llgs_test()
 | |
|         self.buildDwarf()
 | |
|         self.set_inferior_startup_launch()
 | |
|         self.auxv_data_is_correct_size()
 | |
| 
 | |
|     def auxv_keys_look_valid(self):
 | |
|         (word_size, auxv_data) = self.get_raw_auxv_data()
 | |
|         self.assertIsNotNone(auxv_data)
 | |
| 
 | |
|         # Grab endian.
 | |
|         self.reset_test_sequence()
 | |
|         self.add_process_info_collection_packets()
 | |
|         context = self.expect_gdbremote_sequence()
 | |
|         self.assertIsNotNone(context)
 | |
| 
 | |
|         process_info = self.parse_process_info_response(context)
 | |
|         self.assertIsNotNone(process_info)
 | |
|         endian = process_info.get("endian")
 | |
|         self.assertIsNotNone(endian)
 | |
| 
 | |
|         auxv_dict = self.build_auxv_dict(endian, word_size, auxv_data)
 | |
|         self.assertIsNotNone(auxv_dict)
 | |
| 
 | |
|         # Verify keys look reasonable.
 | |
|         for auxv_key in auxv_dict:
 | |
|             self.assertTrue(auxv_key >= 1)
 | |
|             self.assertTrue(auxv_key <= 1000)
 | |
|         # print "auxv dict: {}".format(auxv_dict)
 | |
| 
 | |
|     @debugserver_test
 | |
|     @dsym_test
 | |
|     def test_auxv_keys_look_valid_debugserver_dsym(self):
 | |
|         self.init_debugserver_test()
 | |
|         self.buildDsym()
 | |
|         self.set_inferior_startup_launch()
 | |
|         self.auxv_keys_look_valid()
 | |
| 
 | |
|     @llgs_test
 | |
|     @dwarf_test
 | |
|     @expectedFailureLinux('http://llvm.org/pr23545') # build failure 1/365 dosep builds
 | |
|     def test_auxv_keys_look_valid_llgs_dwarf(self):
 | |
|         self.init_llgs_test()
 | |
|         self.buildDwarf()
 | |
|         self.set_inferior_startup_launch()
 | |
|         self.auxv_keys_look_valid()
 | |
| 
 | |
|     def auxv_chunked_reads_work(self):
 | |
|         # Verify that multiple smaller offset,length reads of auxv data
 | |
|         # return the same data as a single larger read.
 | |
| 
 | |
|         # Grab the auxv data with a single large read here.
 | |
|         (word_size, auxv_data) = self.get_raw_auxv_data()
 | |
|         self.assertIsNotNone(auxv_data)
 | |
| 
 | |
|         # Grab endian.
 | |
|         self.reset_test_sequence()
 | |
|         self.add_process_info_collection_packets()
 | |
|         context = self.expect_gdbremote_sequence()
 | |
|         self.assertIsNotNone(context)
 | |
| 
 | |
|         process_info = self.parse_process_info_response(context)
 | |
|         self.assertIsNotNone(process_info)
 | |
|         endian = process_info.get("endian")
 | |
|         self.assertIsNotNone(endian)
 | |
| 
 | |
|         auxv_dict = self.build_auxv_dict(endian, word_size, auxv_data)
 | |
|         self.assertIsNotNone(auxv_dict)
 | |
| 
 | |
|         iterated_auxv_data = self.read_binary_data_in_chunks("qXfer:auxv:read::", 2*word_size)
 | |
|         self.assertIsNotNone(iterated_auxv_data)
 | |
| 
 | |
|         auxv_dict_iterated = self.build_auxv_dict(endian, word_size, iterated_auxv_data)
 | |
|         self.assertIsNotNone(auxv_dict_iterated)
 | |
| 
 | |
|         # Verify both types of data collection returned same content.
 | |
|         self.assertEquals(auxv_dict_iterated, auxv_dict)
 | |
| 
 | |
|     @debugserver_test
 | |
|     @dsym_test
 | |
|     def test_auxv_chunked_reads_work_debugserver_dsym(self):
 | |
|         self.init_debugserver_test()
 | |
|         self.buildDsym()
 | |
|         self.set_inferior_startup_launch()
 | |
|         self.auxv_chunked_reads_work()
 | |
| 
 | |
|     @llgs_test
 | |
|     @dwarf_test
 | |
|     @expectedFailureLinux('llvm.org/pr22930') # fails 1/34 builds on lldb-x86_64-ubuntu-14.04-cmake
 | |
|     def test_auxv_chunked_reads_work_llgs_dwarf(self):
 | |
|         self.init_llgs_test()
 | |
|         self.buildDwarf()
 | |
|         self.set_inferior_startup_launch()
 | |
|         self.auxv_chunked_reads_work()
 | |
| 
 | |
| 
 | |
| if __name__ == '__main__':
 | |
|     unittest2.main()
 |