xref: /llvm-project/lldb/test/API/tools/lldb-server/TestGdbRemoteAuxvSupport.py (revision 9c2468821ec51defd09c246fea4a47886fff8c01)
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