160 lines · python
1import gdbremote_testcase2from lldbsuite.test.decorators import *3from lldbsuite.test.lldbtest import *4from lldbsuite.test import lldbutil5 6 7class TestGdbRemoteAuxvSupport(gdbremote_testcase.GdbRemoteTestCaseBase):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 (19 self.AUXV_SUPPORT_FEATURE_NAME in features20 and features[self.AUXV_SUPPORT_FEATURE_NAME] == "+"21 )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 = 042 LENGTH = 0x40043 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(OFFSET, LENGTH),49 {50 "direction": "send",51 "regex": re.compile(52 r"^\$([^E])(.*)#[0-9a-fA-F]{2}$", re.MULTILINE | re.DOTALL53 ),54 "capture": {1: "response_type", 2: "content_raw"},55 },56 ],57 True,58 )59 60 context = self.expect_gdbremote_sequence()61 self.assertIsNotNone(context)62 63 # Ensure we end up with all auxv data in one packet.64 # FIXME don't assume it all comes back in one packet.65 self.assertEqual(context.get("response_type"), "l")66 67 # Decode binary data.68 content_raw = context.get("content_raw")69 self.assertIsNotNone(content_raw)70 return (word_size, self.decode_gdbremote_binary(content_raw))71 72 @skipIfWindows # no auxv support.73 @skipIfDarwin74 def test_supports_auxv(self):75 self.build()76 self.set_inferior_startup_launch()77 self.assertTrue(self.has_auxv_support())78 79 @skipIfWindows80 @expectedFailureNetBSD81 def test_auxv_data_is_correct_size(self):82 self.build()83 self.set_inferior_startup_launch()84 85 (word_size, auxv_data) = self.get_raw_auxv_data()86 self.assertIsNotNone(auxv_data)87 88 # Ensure auxv data is a multiple of 2*word_size (there should be two89 # unsigned long fields per auxv entry).90 self.assertEqual(len(auxv_data) % (2 * word_size), 0)91 self.trace("auxv contains {} entries".format(len(auxv_data) / (2 * word_size)))92 93 @skipIfWindows94 @expectedFailureNetBSD95 def test_auxv_keys_look_valid(self):96 self.build()97 self.set_inferior_startup_launch()98 99 (word_size, auxv_data) = self.get_raw_auxv_data()100 self.assertIsNotNone(auxv_data)101 102 # Grab endian.103 self.reset_test_sequence()104 self.add_process_info_collection_packets()105 context = self.expect_gdbremote_sequence()106 self.assertIsNotNone(context)107 108 process_info = self.parse_process_info_response(context)109 self.assertIsNotNone(process_info)110 endian = process_info.get("endian")111 self.assertIsNotNone(endian)112 113 auxv_dict = self.build_auxv_dict(endian, word_size, auxv_data)114 self.assertIsNotNone(auxv_dict)115 116 # Verify keys look reasonable. While AUX values are most commonly117 # small (usually smaller than 50), they can sometimes be larger.118 self.trace("auxv dict: {}".format(auxv_dict))119 for auxv_key in auxv_dict:120 self.assertGreaterEqual(auxv_key, 1)121 self.assertLessEqual(auxv_key, 2500)122 123 @skipIfWindows124 @expectedFailureNetBSD125 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 data130 # 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_size152 )153 self.assertIsNotNone(iterated_auxv_data)154 155 auxv_dict_iterated = self.build_auxv_dict(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