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