""" Test 'target modules dump separate-debug-info' for dwo files. """ import json import os from lldbsuite.test import lldbtest, lldbutil from lldbsuite.test.decorators import * from lldbsuite.test_event.build_exception import BuildError class TestDumpDWO(lldbtest.TestBase): NO_DEBUG_INFO_TESTCASE = True def get_dwos_from_json_output(self): """Returns a dictionary of `symfile` -> {`dwo_name` -> dwo_info object}.""" result = {} output = json.loads(self.res.GetOutput()) for symfile_entry in output: dwo_dict = {} for dwo_entry in symfile_entry["separate-debug-info-files"]: dwo_dict[dwo_entry["dwo_name"]] = dwo_entry result[symfile_entry["symfile"]] = dwo_dict return result def build_and_skip_if_error(self): try: self.build() except BuildError as e: self.skipTest(f"Skipping test due to build exception: {e}") def test_dwos_loaded_json_output(self): self.build_and_skip_if_error() exe = self.getBuildArtifact("a.out") main_dwo = self.getBuildArtifact("a.out-main.dwo") foo_dwo = self.getBuildArtifact("a.out-foo.dwo") # Make sure dwo files exist self.assertTrue(os.path.exists(main_dwo), f'Make sure "{main_dwo}" file exists') self.assertTrue(os.path.exists(foo_dwo), f'Make sure "{foo_dwo}" file exists') target = self.dbg.CreateTarget(exe) self.assertTrue(target, lldbtest.VALID_TARGET) self.runCmd("target modules dump separate-debug-info --json") # Check the output output = self.get_dwos_from_json_output() self.assertTrue(output[exe]["a.out-main.dwo"]["loaded"]) self.assertTrue(output[exe]["a.out-foo.dwo"]["loaded"]) def test_dwos_not_loaded_json_output(self): self.build_and_skip_if_error() exe = self.getBuildArtifact("a.out") main_dwo = self.getBuildArtifact("a.out-main.dwo") foo_dwo = self.getBuildArtifact("a.out-foo.dwo") # REMOVE one of the dwo files os.unlink(main_dwo) target = self.dbg.CreateTarget(exe) self.assertTrue(target, lldbtest.VALID_TARGET) self.runCmd("target modules dump separate-debug-info --json") # Check the output output = self.get_dwos_from_json_output() self.assertFalse(output[exe]["a.out-main.dwo"]["loaded"]) self.assertIn("error", output[exe]["a.out-main.dwo"]) self.assertTrue(output[exe]["a.out-foo.dwo"]["loaded"]) self.assertNotIn("error", output[exe]["a.out-foo.dwo"]) # Check with --errors-only self.runCmd("target modules dump separate-debug-info --json --errors-only") output = self.get_dwos_from_json_output() self.assertFalse(output[exe]["a.out-main.dwo"]["loaded"]) self.assertIn("error", output[exe]["a.out-main.dwo"]) self.assertNotIn("a.out-foo.dwo", output[exe]) def test_dwos_loaded_table_output(self): self.build_and_skip_if_error() exe = self.getBuildArtifact("a.out") main_dwo = self.getBuildArtifact("a.out-main.dwo") foo_dwo = self.getBuildArtifact("a.out-foo.dwo") # Make sure dwo files exist self.assertTrue(os.path.exists(main_dwo), f'Make sure "{main_dwo}" file exists') self.assertTrue(os.path.exists(foo_dwo), f'Make sure "{foo_dwo}" file exists') target = self.dbg.CreateTarget(exe) self.assertTrue(target, lldbtest.VALID_TARGET) self.expect( "target modules dump separate-debug-info", patterns=[ r"Symbol file: .*?a\.out", 'Type: "dwo"', r"Dwo ID\s+Err\s+Dwo Path", r"0x[a-zA-Z0-9]{16}\s+.*main\.dwo", r"0x[a-zA-Z0-9]{16}\s+.*foo\.dwo", ], ) def test_dwos_not_loaded_table_output(self): self.build_and_skip_if_error() exe = self.getBuildArtifact("a.out") main_dwo = self.getBuildArtifact("a.out-main.dwo") foo_dwo = self.getBuildArtifact("a.out-foo.dwo") # REMOVE the dwo files os.unlink(main_dwo) os.unlink(foo_dwo) target = self.dbg.CreateTarget(exe) self.assertTrue(target, lldbtest.VALID_TARGET) self.expect( "target modules dump separate-debug-info", patterns=[ r"Symbol file: .*?a\.out", 'Type: "dwo"', r"Dwo ID\s+Err\s+Dwo Path", r"0x[a-zA-Z0-9]{16}\s+E\s+.*main\.dwo", r"0x[a-zA-Z0-9]{16}\s+E\s+.*foo\.dwo", ], ) def test_dwos_loaded_symbols_on_demand(self): self.build_and_skip_if_error() exe = self.getBuildArtifact("a.out") main_dwo = self.getBuildArtifact("a.out-main.dwo") foo_dwo = self.getBuildArtifact("a.out-foo.dwo") # Make sure dwo files exist self.assertTrue(os.path.exists(main_dwo), f'Make sure "{main_dwo}" file exists') self.assertTrue(os.path.exists(foo_dwo), f'Make sure "{foo_dwo}" file exists') # Load symbols on-demand self.runCmd("settings set symbols.load-on-demand true") target = self.dbg.CreateTarget(exe) self.assertTrue(target, lldbtest.VALID_TARGET) self.runCmd("target modules dump separate-debug-info --json") # Check the output output = self.get_dwos_from_json_output() self.assertTrue(output[exe]["a.out-main.dwo"]["loaded"]) self.assertTrue(output[exe]["a.out-foo.dwo"]["loaded"])