199451b44SJordan Rupprechtimport gdbremote_testcase 299451b44SJordan Rupprechtfrom lldbsuite.test.decorators import * 399451b44SJordan Rupprechtfrom lldbsuite.test.lldbtest import * 499451b44SJordan Rupprechtfrom lldbsuite.test import lldbutil 599451b44SJordan Rupprecht 699451b44SJordan Rupprecht 72238dcc3SJonas Devlieghereclass TestGdbRemoteAuxvSupport(gdbremote_testcase.GdbRemoteTestCaseBase): 899451b44SJordan Rupprecht AUXV_SUPPORT_FEATURE_NAME = "qXfer:auxv:read" 999451b44SJordan Rupprecht 1099451b44SJordan Rupprecht def has_auxv_support(self): 114e0e79ddSPavel Labath procs = self.prep_debug_monitor_and_inferior() 1299451b44SJordan Rupprecht 1399451b44SJordan Rupprecht self.add_qSupported_packets() 1499451b44SJordan Rupprecht context = self.expect_gdbremote_sequence() 1599451b44SJordan Rupprecht self.assertIsNotNone(context) 1699451b44SJordan Rupprecht 1799451b44SJordan Rupprecht features = self.parse_qSupported_response(context) 182238dcc3SJonas Devlieghere return ( 192238dcc3SJonas Devlieghere self.AUXV_SUPPORT_FEATURE_NAME in features 202238dcc3SJonas Devlieghere and features[self.AUXV_SUPPORT_FEATURE_NAME] == "+" 212238dcc3SJonas Devlieghere ) 2299451b44SJordan Rupprecht 2399451b44SJordan Rupprecht def get_raw_auxv_data(self): 2499451b44SJordan Rupprecht # Start up llgs and inferior, and check for auxv support. 2599451b44SJordan Rupprecht if not self.has_auxv_support(): 2699451b44SJordan Rupprecht self.skipTest("auxv data not supported") 2799451b44SJordan Rupprecht 2899451b44SJordan Rupprecht # Grab pointer size for target. We'll assume that is equivalent to an unsigned long on the target. 2999451b44SJordan Rupprecht # Auxv is specified in terms of pairs of unsigned longs. 3099451b44SJordan Rupprecht self.reset_test_sequence() 3199451b44SJordan Rupprecht self.add_process_info_collection_packets() 3299451b44SJordan Rupprecht 3399451b44SJordan Rupprecht context = self.expect_gdbremote_sequence() 3499451b44SJordan Rupprecht self.assertIsNotNone(context) 3599451b44SJordan Rupprecht 3699451b44SJordan Rupprecht proc_info = self.parse_process_info_response(context) 3799451b44SJordan Rupprecht self.assertIsNotNone(proc_info) 383cc37622SDave Lee self.assertIn("ptrsize", proc_info) 3999451b44SJordan Rupprecht word_size = int(proc_info["ptrsize"]) 4099451b44SJordan Rupprecht 4199451b44SJordan Rupprecht OFFSET = 0 4299451b44SJordan Rupprecht LENGTH = 0x400 4399451b44SJordan Rupprecht 4499451b44SJordan Rupprecht # Grab the auxv data. 4599451b44SJordan Rupprecht self.reset_test_sequence() 4699451b44SJordan Rupprecht self.test_sequence.add_log_lines( 4799451b44SJordan Rupprecht [ 482238dcc3SJonas Devlieghere "read packet: $qXfer:auxv:read::{:x},{:x}:#00".format(OFFSET, LENGTH), 4999451b44SJordan Rupprecht { 5099451b44SJordan Rupprecht "direction": "send", 5199451b44SJordan Rupprecht "regex": re.compile( 522238dcc3SJonas Devlieghere r"^\$([^E])(.*)#[0-9a-fA-F]{2}$", re.MULTILINE | re.DOTALL 532238dcc3SJonas Devlieghere ), 542238dcc3SJonas Devlieghere "capture": {1: "response_type", 2: "content_raw"}, 552238dcc3SJonas Devlieghere }, 562238dcc3SJonas Devlieghere ], 572238dcc3SJonas Devlieghere True, 582238dcc3SJonas Devlieghere ) 5999451b44SJordan Rupprecht 6099451b44SJordan Rupprecht context = self.expect_gdbremote_sequence() 6199451b44SJordan Rupprecht self.assertIsNotNone(context) 6299451b44SJordan Rupprecht 6399451b44SJordan Rupprecht # Ensure we end up with all auxv data in one packet. 6499451b44SJordan Rupprecht # FIXME don't assume it all comes back in one packet. 6599451b44SJordan Rupprecht self.assertEqual(context.get("response_type"), "l") 6699451b44SJordan Rupprecht 6799451b44SJordan Rupprecht # Decode binary data. 6899451b44SJordan Rupprecht content_raw = context.get("content_raw") 6999451b44SJordan Rupprecht self.assertIsNotNone(content_raw) 7099451b44SJordan Rupprecht return (word_size, self.decode_gdbremote_binary(content_raw)) 7199451b44SJordan Rupprecht 7299451b44SJordan Rupprecht @skipIfWindows # no auxv support. 734e0e79ddSPavel Labath @skipIfDarwin 744e0e79ddSPavel Labath def test_supports_auxv(self): 7599451b44SJordan Rupprecht self.build() 7699451b44SJordan Rupprecht self.set_inferior_startup_launch() 774e0e79ddSPavel Labath self.assertTrue(self.has_auxv_support()) 7899451b44SJordan Rupprecht 794e0e79ddSPavel Labath @skipIfWindows 804e0e79ddSPavel Labath @expectedFailureNetBSD 814e0e79ddSPavel Labath def test_auxv_data_is_correct_size(self): 824e0e79ddSPavel Labath self.build() 834e0e79ddSPavel Labath self.set_inferior_startup_launch() 844e0e79ddSPavel Labath 8599451b44SJordan Rupprecht (word_size, auxv_data) = self.get_raw_auxv_data() 8699451b44SJordan Rupprecht self.assertIsNotNone(auxv_data) 8799451b44SJordan Rupprecht 8899451b44SJordan Rupprecht # Ensure auxv data is a multiple of 2*word_size (there should be two 8999451b44SJordan Rupprecht # unsigned long fields per auxv entry). 9099451b44SJordan Rupprecht self.assertEqual(len(auxv_data) % (2 * word_size), 0) 91b321b429SJonas Devlieghere self.trace("auxv contains {} entries".format(len(auxv_data) / (2 * word_size))) 9299451b44SJordan Rupprecht 9399451b44SJordan Rupprecht @skipIfWindows 9499451b44SJordan Rupprecht @expectedFailureNetBSD 954e0e79ddSPavel Labath def test_auxv_keys_look_valid(self): 9699451b44SJordan Rupprecht self.build() 9799451b44SJordan Rupprecht self.set_inferior_startup_launch() 9899451b44SJordan Rupprecht 9999451b44SJordan Rupprecht (word_size, auxv_data) = self.get_raw_auxv_data() 10099451b44SJordan Rupprecht self.assertIsNotNone(auxv_data) 10199451b44SJordan Rupprecht 10299451b44SJordan Rupprecht # Grab endian. 10399451b44SJordan Rupprecht self.reset_test_sequence() 10499451b44SJordan Rupprecht self.add_process_info_collection_packets() 10599451b44SJordan Rupprecht context = self.expect_gdbremote_sequence() 10699451b44SJordan Rupprecht self.assertIsNotNone(context) 10799451b44SJordan Rupprecht 10899451b44SJordan Rupprecht process_info = self.parse_process_info_response(context) 10999451b44SJordan Rupprecht self.assertIsNotNone(process_info) 11099451b44SJordan Rupprecht endian = process_info.get("endian") 11199451b44SJordan Rupprecht self.assertIsNotNone(endian) 11299451b44SJordan Rupprecht 11399451b44SJordan Rupprecht auxv_dict = self.build_auxv_dict(endian, word_size, auxv_data) 11499451b44SJordan Rupprecht self.assertIsNotNone(auxv_dict) 11599451b44SJordan Rupprecht 116e07e1d44SJordan Rupprecht # Verify keys look reasonable. While AUX values are most commonly 117e07e1d44SJordan Rupprecht # small (usually smaller than 50), they can sometimes be larger. 118e07e1d44SJordan Rupprecht self.trace("auxv dict: {}".format(auxv_dict)) 11999451b44SJordan Rupprecht for auxv_key in auxv_dict: 120*9c246882SJordan Rupprecht self.assertGreaterEqual(auxv_key, 1) 121*9c246882SJordan Rupprecht self.assertLessEqual(auxv_key, 2500) 12299451b44SJordan Rupprecht 12399451b44SJordan Rupprecht @skipIfWindows 12499451b44SJordan Rupprecht @expectedFailureNetBSD 1254e0e79ddSPavel Labath def test_auxv_chunked_reads_work(self): 12699451b44SJordan Rupprecht self.build() 12799451b44SJordan Rupprecht self.set_inferior_startup_launch() 12899451b44SJordan Rupprecht 12999451b44SJordan Rupprecht # Verify that multiple smaller offset,length reads of auxv data 13099451b44SJordan Rupprecht # return the same data as a single larger read. 13199451b44SJordan Rupprecht 13299451b44SJordan Rupprecht # Grab the auxv data with a single large read here. 13399451b44SJordan Rupprecht (word_size, auxv_data) = self.get_raw_auxv_data() 13499451b44SJordan Rupprecht self.assertIsNotNone(auxv_data) 13599451b44SJordan Rupprecht 13699451b44SJordan Rupprecht # Grab endian. 13799451b44SJordan Rupprecht self.reset_test_sequence() 13899451b44SJordan Rupprecht self.add_process_info_collection_packets() 13999451b44SJordan Rupprecht context = self.expect_gdbremote_sequence() 14099451b44SJordan Rupprecht self.assertIsNotNone(context) 14199451b44SJordan Rupprecht 14299451b44SJordan Rupprecht process_info = self.parse_process_info_response(context) 14399451b44SJordan Rupprecht self.assertIsNotNone(process_info) 14499451b44SJordan Rupprecht endian = process_info.get("endian") 14599451b44SJordan Rupprecht self.assertIsNotNone(endian) 14699451b44SJordan Rupprecht 14799451b44SJordan Rupprecht auxv_dict = self.build_auxv_dict(endian, word_size, auxv_data) 14899451b44SJordan Rupprecht self.assertIsNotNone(auxv_dict) 14999451b44SJordan Rupprecht 15099451b44SJordan Rupprecht iterated_auxv_data = self.read_binary_data_in_chunks( 1512238dcc3SJonas Devlieghere "qXfer:auxv:read::", 2 * word_size 1522238dcc3SJonas Devlieghere ) 15399451b44SJordan Rupprecht self.assertIsNotNone(iterated_auxv_data) 15499451b44SJordan Rupprecht 1552238dcc3SJonas Devlieghere auxv_dict_iterated = self.build_auxv_dict(endian, word_size, iterated_auxv_data) 15699451b44SJordan Rupprecht self.assertIsNotNone(auxv_dict_iterated) 15799451b44SJordan Rupprecht 15899451b44SJordan Rupprecht # Verify both types of data collection returned same content. 15999451b44SJordan Rupprecht self.assertEqual(auxv_dict_iterated, auxv_dict) 160