1import gdbremote_testcase 2from lldbsuite.test.decorators import * 3from lldbsuite.test.lldbtest import * 4from lldbsuite.test import lldbutil 5 6class TestGdbRemoteAuxvSupport(gdbremote_testcase.GdbRemoteTestCaseBase): 7 8 mydir = TestBase.compute_mydir(__file__) 9 10 AUXV_SUPPORT_FEATURE_NAME = "qXfer:auxv:read" 11 12 def has_auxv_support(self): 13 procs = self.prep_debug_monitor_and_inferior() 14 15 self.add_qSupported_packets() 16 context = self.expect_gdbremote_sequence() 17 self.assertIsNotNone(context) 18 19 features = self.parse_qSupported_response(context) 20 return self.AUXV_SUPPORT_FEATURE_NAME in features and features[ 21 self.AUXV_SUPPORT_FEATURE_NAME] == "+" 22 23 def get_raw_auxv_data(self): 24 # Start up llgs and inferior, and check for auxv support. 25 if not self.has_auxv_support(): 26 self.skipTest("auxv data not supported") 27 28 # Grab pointer size for target. We'll assume that is equivalent to an unsigned long on the target. 29 # Auxv is specified in terms of pairs of unsigned longs. 30 self.reset_test_sequence() 31 self.add_process_info_collection_packets() 32 33 context = self.expect_gdbremote_sequence() 34 self.assertIsNotNone(context) 35 36 proc_info = self.parse_process_info_response(context) 37 self.assertIsNotNone(proc_info) 38 self.assertIn("ptrsize", proc_info) 39 word_size = int(proc_info["ptrsize"]) 40 41 OFFSET = 0 42 LENGTH = 0x400 43 44 # Grab the auxv data. 45 self.reset_test_sequence() 46 self.test_sequence.add_log_lines( 47 [ 48 "read packet: $qXfer:auxv:read::{:x},{:x}:#00".format( 49 OFFSET, 50 LENGTH), 51 { 52 "direction": "send", 53 "regex": re.compile( 54 r"^\$([^E])(.*)#[0-9a-fA-F]{2}$", 55 re.MULTILINE | re.DOTALL), 56 "capture": { 57 1: "response_type", 58 2: "content_raw"}}], 59 True) 60 61 context = self.expect_gdbremote_sequence() 62 self.assertIsNotNone(context) 63 64 # Ensure we end up with all auxv data in one packet. 65 # FIXME don't assume it all comes back in one packet. 66 self.assertEqual(context.get("response_type"), "l") 67 68 # Decode binary data. 69 content_raw = context.get("content_raw") 70 self.assertIsNotNone(content_raw) 71 return (word_size, self.decode_gdbremote_binary(content_raw)) 72 73 @skipIfWindows # no auxv support. 74 @skipIfDarwin 75 def test_supports_auxv(self): 76 self.build() 77 self.set_inferior_startup_launch() 78 self.assertTrue(self.has_auxv_support()) 79 80 @skipIfWindows 81 @expectedFailureNetBSD 82 def test_auxv_data_is_correct_size(self): 83 self.build() 84 self.set_inferior_startup_launch() 85 86 (word_size, auxv_data) = self.get_raw_auxv_data() 87 self.assertIsNotNone(auxv_data) 88 89 # Ensure auxv data is a multiple of 2*word_size (there should be two 90 # unsigned long fields per auxv entry). 91 self.assertEqual(len(auxv_data) % (2 * word_size), 0) 92 self.trace("auxv contains {} entries".format(len(auxv_data) / (2*word_size))) 93 94 @skipIfWindows 95 @expectedFailureNetBSD 96 def test_auxv_keys_look_valid(self): 97 self.build() 98 self.set_inferior_startup_launch() 99 100 (word_size, auxv_data) = self.get_raw_auxv_data() 101 self.assertIsNotNone(auxv_data) 102 103 # Grab endian. 104 self.reset_test_sequence() 105 self.add_process_info_collection_packets() 106 context = self.expect_gdbremote_sequence() 107 self.assertIsNotNone(context) 108 109 process_info = self.parse_process_info_response(context) 110 self.assertIsNotNone(process_info) 111 endian = process_info.get("endian") 112 self.assertIsNotNone(endian) 113 114 auxv_dict = self.build_auxv_dict(endian, word_size, auxv_data) 115 self.assertIsNotNone(auxv_dict) 116 117 # Verify keys look reasonable. 118 for auxv_key in auxv_dict: 119 self.assertTrue(auxv_key >= 1) 120 self.assertTrue(auxv_key <= 1000) 121 self.trace("auxv dict: {}".format(auxv_dict)) 122 123 @skipIfWindows 124 @expectedFailureNetBSD 125 def test_auxv_chunked_reads_work(self): 126 self.build() 127 self.set_inferior_startup_launch() 128 129 # Verify that multiple smaller offset,length reads of auxv data 130 # return the same data as a single larger read. 131 132 # Grab the auxv data with a single large read here. 133 (word_size, auxv_data) = self.get_raw_auxv_data() 134 self.assertIsNotNone(auxv_data) 135 136 # Grab endian. 137 self.reset_test_sequence() 138 self.add_process_info_collection_packets() 139 context = self.expect_gdbremote_sequence() 140 self.assertIsNotNone(context) 141 142 process_info = self.parse_process_info_response(context) 143 self.assertIsNotNone(process_info) 144 endian = process_info.get("endian") 145 self.assertIsNotNone(endian) 146 147 auxv_dict = self.build_auxv_dict(endian, word_size, auxv_data) 148 self.assertIsNotNone(auxv_dict) 149 150 iterated_auxv_data = self.read_binary_data_in_chunks( 151 "qXfer:auxv:read::", 2 * word_size) 152 self.assertIsNotNone(iterated_auxv_data) 153 154 auxv_dict_iterated = self.build_auxv_dict( 155 endian, word_size, iterated_auxv_data) 156 self.assertIsNotNone(auxv_dict_iterated) 157 158 # Verify both types of data collection returned same content. 159 self.assertEqual(auxv_dict_iterated, auxv_dict) 160