xref: /llvm-project/lldb/test/API/tools/lldb-server/libraries-svr4/TestGdbRemoteLibrariesSvr4Support.py (revision facb767e5b78a024d70585b24254c769473b6b54)
1import xml.etree.ElementTree as ET
2import gdbremote_testcase
3from lldbsuite.test.decorators import *
4from lldbsuite.test.lldbtest import *
5
6
7# Windows does not allow quotes in file names.
8@skipIf(hostoslist=["windows"])
9@skipIfRemote
10class TestGdbRemoteLibrariesSvr4Support(gdbremote_testcase.GdbRemoteTestCaseBase):
11    FEATURE_NAME = "qXfer:libraries-svr4:read"
12
13    def setup_test(self):
14        self.build()
15        self.set_inferior_startup_launch()
16        env = {}
17        env[self.dylibPath] = self.getBuildDir()
18        self.prep_debug_monitor_and_inferior(inferior_env=env)
19        self.continue_process_and_wait_for_stop()
20
21    def get_expected_libs(self):
22        return ["libsvr4lib_a.so", 'libsvr4lib_b".so']
23
24    def has_libraries_svr4_support(self):
25        self.add_qSupported_packets()
26        context = self.expect_gdbremote_sequence()
27        self.assertIsNotNone(context)
28        features = self.parse_qSupported_response(context)
29        return self.FEATURE_NAME in features and features[self.FEATURE_NAME] == "+"
30
31    def get_libraries_svr4_data(self):
32        # Start up llgs and inferior, and check for libraries-svr4 support.
33        if not self.has_libraries_svr4_support():
34            self.skipTest("libraries-svr4 not supported")
35
36        # Grab the libraries-svr4 data.
37        self.reset_test_sequence()
38        self.test_sequence.add_log_lines(
39            [
40                "read packet: $qXfer:libraries-svr4:read::0,ffff:#00",
41                {
42                    "direction": "send",
43                    "regex": re.compile(
44                        r"^\$([^E])(.*)#[0-9a-fA-F]{2}$", re.MULTILINE | re.DOTALL
45                    ),
46                    "capture": {1: "response_type", 2: "content_raw"},
47                },
48            ],
49            True,
50        )
51
52        context = self.expect_gdbremote_sequence()
53        self.assertIsNotNone(context)
54
55        # Ensure we end up with all libraries-svr4 data in one packet.
56        self.assertEqual(context.get("response_type"), "l")
57
58        # Decode binary data.
59        content_raw = context.get("content_raw")
60        self.assertIsNotNone(content_raw)
61        return content_raw
62
63    def get_libraries_svr4_xml(self):
64        libraries_svr4 = self.get_libraries_svr4_data()
65        xml_root = None
66        try:
67            xml_root = ET.fromstring(libraries_svr4)
68        except xml.etree.ElementTree.ParseError:
69            pass
70        self.assertIsNotNone(xml_root, "Malformed libraries-svr4 XML")
71        return xml_root
72
73    def libraries_svr4_well_formed(self):
74        xml_root = self.get_libraries_svr4_xml()
75        self.assertEqual(xml_root.tag, "library-list-svr4")
76        for child in xml_root:
77            self.assertEqual(child.tag, "library")
78            self.assertCountEqual(child.attrib.keys(), ["name", "lm", "l_addr", "l_ld"])
79
80    def libraries_svr4_has_correct_load_addr(self):
81        xml_root = self.get_libraries_svr4_xml()
82        for child in xml_root:
83            name = child.attrib.get("name")
84            base_name = os.path.basename(name)
85            if os.path.basename(name) not in self.get_expected_libs():
86                continue
87            load_addr = int(child.attrib.get("l_addr"), 16)
88            self.reset_test_sequence()
89            self.add_query_memory_region_packets(load_addr)
90            context = self.expect_gdbremote_sequence()
91            mem_region = self.parse_memory_region_packet(context)
92            self.assertEqual(load_addr, int(mem_region.get("start", 0), 16))
93            self.assertEqual(
94                os.path.realpath(name), os.path.realpath(mem_region.get("name", ""))
95            )
96
97    def libraries_svr4_libs_present(self):
98        xml_root = self.get_libraries_svr4_xml()
99        libraries_svr4_names = []
100        for child in xml_root:
101            name = child.attrib.get("name")
102            libraries_svr4_names.append(os.path.realpath(name))
103        for lib in self.get_expected_libs():
104            self.assertIn(
105                os.path.realpath(self.getBuildDir() + "/" + lib), libraries_svr4_names
106            )
107
108    @skipUnlessPlatform(["linux", "android", "freebsd", "netbsd"])
109    def test_supports_libraries_svr4(self):
110        self.setup_test()
111        self.assertTrue(self.has_libraries_svr4_support())
112
113    @skipUnlessPlatform(["linux", "android", "freebsd", "netbsd"])
114    @expectedFailureNetBSD
115    def test_libraries_svr4_well_formed(self):
116        self.setup_test()
117        self.libraries_svr4_well_formed()
118
119    @skipUnlessPlatform(["linux", "android", "freebsd", "netbsd"])
120    @expectedFailureNetBSD
121    def test_libraries_svr4_load_addr(self):
122        self.setup_test()
123        self.libraries_svr4_has_correct_load_addr()
124
125    @skipUnlessPlatform(["linux", "android", "freebsd", "netbsd"])
126    @expectedFailureNetBSD
127    def test_libraries_svr4_libs_present(self):
128        self.setup_test()
129        self.libraries_svr4_libs_present()
130