xref: /llvm-project/lldb/test/API/commands/target/dump-separate-debug-info/oso/TestDumpOso.py (revision 69a5869da4906f61caf59ff021559ca7d974c5f9)
1"""
2Test 'target modules dump separate-debug-info' for oso files.
3"""
4
5import json
6import os
7
8from lldbsuite.test import lldbtest, lldbutil
9from lldbsuite.test.decorators import *
10
11
12class TestDumpOso(lldbtest.TestBase):
13    NO_DEBUG_INFO_TESTCASE = True
14
15    def get_osos_from_json_output(self):
16        """Returns a dictionary of `symfile` -> {`OSO_PATH` -> oso_info object}."""
17        result = {}
18        output = json.loads(self.res.GetOutput())
19        for symfile_entry in output:
20            oso_dict = {}
21            for oso_entry in symfile_entry["separate-debug-info-files"]:
22                oso_dict[oso_entry["oso_path"]] = oso_entry
23            result[symfile_entry["symfile"]] = oso_dict
24        return result
25
26    @skipIfRemote
27    @skipUnlessDarwin
28    def test_shows_oso_loaded_json_output(self):
29        self.build(debug_info="dwarf")
30        exe = self.getBuildArtifact("a.out")
31        main_o = self.getBuildArtifact("main.o")
32        foo_o = self.getBuildArtifact("foo.o")
33
34        # Make sure o files exist
35        self.assertTrue(os.path.exists(main_o), f'Make sure "{main_o}" file exists')
36        self.assertTrue(os.path.exists(foo_o), f'Make sure "{foo_o}" file exists')
37
38        target = self.dbg.CreateTarget(exe)
39        self.assertTrue(target, lldbtest.VALID_TARGET)
40
41        self.runCmd("target modules dump separate-debug-info --json")
42
43        # Check the output
44        osos = self.get_osos_from_json_output()
45        self.assertTrue(osos[exe][main_o]["loaded"])
46        self.assertTrue(osos[exe][foo_o]["loaded"])
47
48    @skipIfRemote
49    @skipUnlessDarwin
50    def test_shows_oso_not_loaded_json_output(self):
51        self.build(debug_info="dwarf")
52        exe = self.getBuildArtifact("a.out")
53        main_o = self.getBuildArtifact("main.o")
54        foo_o = self.getBuildArtifact("foo.o")
55
56        # REMOVE the o files
57        os.unlink(main_o)
58
59        target = self.dbg.CreateTarget(exe)
60        self.assertTrue(target, lldbtest.VALID_TARGET)
61
62        self.runCmd("target modules dump separate-debug-info --json")
63
64        # Check the output
65        osos = self.get_osos_from_json_output()
66        self.assertFalse(osos[exe][main_o]["loaded"])
67        self.assertIn("error", osos[exe][main_o])
68        self.assertTrue(osos[exe][foo_o]["loaded"])
69        self.assertNotIn("error", osos[exe][foo_o])
70
71        # Check with --errors-only
72        self.runCmd("target modules dump separate-debug-info --json --errors-only")
73        output = self.get_osos_from_json_output()
74        self.assertFalse(output[exe][main_o]["loaded"])
75        self.assertIn("error", output[exe][main_o])
76        self.assertNotIn(foo_o, output[exe])
77
78    @skipIfRemote
79    @skipUnlessDarwin
80    def test_shows_oso_loaded_table_output(self):
81        self.build(debug_info="dwarf")
82        exe = self.getBuildArtifact("a.out")
83        main_o = self.getBuildArtifact("main.o")
84        foo_o = self.getBuildArtifact("foo.o")
85
86        # Make sure o files exist
87        self.assertTrue(os.path.exists(main_o), f'Make sure "{main_o}" file exists')
88        self.assertTrue(os.path.exists(foo_o), f'Make sure "{foo_o}" file exists')
89
90        target = self.dbg.CreateTarget(exe)
91        self.assertTrue(target, lldbtest.VALID_TARGET)
92
93        self.expect(
94            "target modules dump separate-debug-info",
95            patterns=[
96                "Symbol file: .*?a\.out",
97                'Type: "oso"',
98                "Mod Time\s+Err\s+Oso Path",
99                "0x[a-zA-Z0-9]{16}\s+.*main\.o",
100                "0x[a-zA-Z0-9]{16}\s+.*foo\.o",
101            ],
102        )
103
104    @skipIfRemote
105    @skipUnlessDarwin
106    def test_shows_oso_not_loaded_table_output(self):
107        self.build(debug_info="dwarf")
108        exe = self.getBuildArtifact("a.out")
109        main_o = self.getBuildArtifact("main.o")
110        foo_o = self.getBuildArtifact("foo.o")
111
112        # REMOVE the o files
113        os.unlink(main_o)
114        os.unlink(foo_o)
115
116        target = self.dbg.CreateTarget(exe)
117        self.assertTrue(target, lldbtest.VALID_TARGET)
118
119        self.expect(
120            "target modules dump separate-debug-info",
121            patterns=[
122                "Symbol file: .*?a\.out",
123                'Type: "oso"',
124                "Mod Time\s+Err\s+Oso Path",
125                "0x[a-zA-Z0-9]{16}\s+E\s+.*main\.o",
126                "0x[a-zA-Z0-9]{16}\s+E\s+.*foo\.o",
127            ],
128        )
129
130    @skipIfRemote
131    @skipUnlessDarwin
132    def test_osos_loaded_symbols_on_demand(self):
133        self.build(debug_info="dwarf")
134        exe = self.getBuildArtifact("a.out")
135        main_o = self.getBuildArtifact("main.o")
136        foo_o = self.getBuildArtifact("foo.o")
137
138        # Make sure o files exist
139        self.assertTrue(os.path.exists(main_o), f'Make sure "{main_o}" file exists')
140        self.assertTrue(os.path.exists(foo_o), f'Make sure "{foo_o}" file exists')
141
142        target = self.dbg.CreateTarget(exe)
143        self.assertTrue(target, lldbtest.VALID_TARGET)
144
145        self.runCmd("target modules dump separate-debug-info --json")
146
147        # Load symbols on-demand
148        self.runCmd("settings set symbols.load-on-demand true")
149
150        target = self.dbg.CreateTarget(exe)
151        self.assertTrue(target, lldbtest.VALID_TARGET)
152
153        self.runCmd("target modules dump separate-debug-info --json")
154
155        # Check the output
156        osos = self.get_osos_from_json_output()
157        self.assertTrue(osos[exe][main_o]["loaded"])
158        self.assertTrue(osos[exe][foo_o]["loaded"])
159