| """ |
| 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=[ |
| "Symbol file: .*?a\.out", |
| 'Type: "dwo"', |
| "Dwo ID\s+Err\s+Dwo Path", |
| "0x[a-zA-Z0-9]{16}\s+.*main\.dwo", |
| "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=[ |
| "Symbol file: .*?a\.out", |
| 'Type: "dwo"', |
| "Dwo ID\s+Err\s+Dwo Path", |
| "0x[a-zA-Z0-9]{16}\s+E\s+.*main\.dwo", |
| "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"]) |