import xml.etree.ElementTree as ET import gdbremote_testcase from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * class TestGdbRemoteLibrariesSvr4Support(gdbremote_testcase.GdbRemoteTestCaseBase): mydir = TestBase.compute_mydir(__file__) FEATURE_NAME = "qXfer:libraries-svr4:read" def setup_test(self): self.init_llgs_test() self.build() self.set_inferior_startup_launch() env = {} env[self.dylibPath] = self.getBuildDir() self.prep_debug_monitor_and_inferior(inferior_env=env) self.continue_process_and_wait_for_stop() def get_expected_libs(self): return ["libsvr4lib_a.so", 'libsvr4lib_b".so'] def has_libraries_svr4_support(self): self.add_qSupported_packets() context = self.expect_gdbremote_sequence() self.assertIsNotNone(context) features = self.parse_qSupported_response(context) return self.FEATURE_NAME in features and features[self.FEATURE_NAME] == "+" def get_libraries_svr4_data(self): # Start up llgs and inferior, and check for libraries-svr4 support. if not self.has_libraries_svr4_support(): self.skipTest("libraries-svr4 not supported") # Grab the libraries-svr4 data. self.reset_test_sequence() self.test_sequence.add_log_lines( [ "read packet: $qXfer:libraries-svr4:read::0,ffff:#00", { "direction": "send", "regex": re.compile( r"^\$([^E])(.*)#[0-9a-fA-F]{2}$", re.MULTILINE | re.DOTALL ), "capture": {1: "response_type", 2: "content_raw"}, }, ], True, ) context = self.expect_gdbremote_sequence() self.assertIsNotNone(context) # Ensure we end up with all libraries-svr4 data in one packet. self.assertEqual(context.get("response_type"), "l") # Decode binary data. content_raw = context.get("content_raw") self.assertIsNotNone(content_raw) return content_raw def get_libraries_svr4_xml(self): libraries_svr4 = self.get_libraries_svr4_data() xml_root = None try: xml_root = ET.fromstring(libraries_svr4) except xml.etree.ElementTree.ParseError: pass self.assertIsNotNone(xml_root, "Malformed libraries-svr4 XML") return xml_root def libraries_svr4_well_formed(self): xml_root = self.get_libraries_svr4_xml() self.assertEqual(xml_root.tag, "library-list-svr4") for child in xml_root: self.assertEqual(child.tag, "library") self.assertItemsEqual(child.attrib.keys(), ["name", "lm", "l_addr", "l_ld"]) def libraries_svr4_has_correct_load_addr(self): xml_root = self.get_libraries_svr4_xml() for child in xml_root: name = child.attrib.get("name") base_name = os.path.basename(name) if os.path.basename(name) not in self.get_expected_libs(): continue load_addr = int(child.attrib.get("l_addr"), 16) self.reset_test_sequence() self.add_query_memory_region_packets(load_addr) context = self.expect_gdbremote_sequence() mem_region = self.parse_memory_region_packet(context) self.assertEqual(load_addr, int(mem_region.get("start", 0), 16)) self.assertEqual( os.path.realpath(name), os.path.realpath(mem_region.get("name", "")) ) def libraries_svr4_libs_present(self): xml_root = self.get_libraries_svr4_xml() libraries_svr4_names = [] for child in xml_root: name = child.attrib.get("name") libraries_svr4_names.append(os.path.realpath(name)) for lib in self.get_expected_libs(): self.assertIn(os.path.realpath(self.getBuildDir() + "/" + lib), libraries_svr4_names) @llgs_test @skipUnlessPlatform(["linux", "android", "freebsd", "netbsd"]) def test_supports_libraries_svr4(self): self.setup_test() self.assertTrue(self.has_libraries_svr4_support()) @llgs_test @skipUnlessPlatform(["linux", "android", "freebsd", "netbsd"]) @expectedFailureNetBSD def test_libraries_svr4_well_formed(self): self.setup_test() self.libraries_svr4_well_formed() @llgs_test @skipUnlessPlatform(["linux", "android", "freebsd", "netbsd"]) @expectedFailureAll(oslist=["freebsd", "netbsd"]) def test_libraries_svr4_load_addr(self): self.setup_test() self.libraries_svr4_has_correct_load_addr() @llgs_test @skipUnlessPlatform(["linux", "android", "freebsd", "netbsd"]) @expectedFailureNetBSD def test_libraries_svr4_libs_present(self): self.setup_test() self.libraries_svr4_libs_present()