220 lines · python
1"""2Test 'target modules dump separate-debug-info' for dwo files.3"""4 5import json6import os7 8from lldbsuite.test import lldbtest, lldbutil9from lldbsuite.test.decorators import *10from lldbsuite.test_event.build_exception import BuildError11 12 13class TestDumpDWO(lldbtest.TestBase):14 NO_DEBUG_INFO_TESTCASE = True15 16 def get_dwos_from_json_output(self):17 """Returns a dictionary of `symfile` -> {`dwo_name` -> dwo_info object}."""18 result = {}19 output = json.loads(self.res.GetOutput())20 for symfile_entry in output:21 dwo_dict = {}22 for dwo_entry in symfile_entry["separate-debug-info-files"]:23 dwo_dict[dwo_entry["dwo_name"]] = dwo_entry24 result[symfile_entry["symfile"]] = dwo_dict25 return result26 27 def build_and_skip_if_error(self, debug_info=None):28 try:29 self.build(debug_info=debug_info)30 except BuildError as e:31 self.skipTest(f"Skipping test due to build exception: {e}")32 33 def test_dwos_loaded_json_output(self):34 self.build_and_skip_if_error()35 exe = self.getBuildArtifact("a.out")36 main_dwo = self.getBuildArtifact("a.out-main.dwo")37 foo_dwo = self.getBuildArtifact("a.out-foo.dwo")38 39 # Make sure dwo files exist40 self.assertTrue(os.path.exists(main_dwo), f'Make sure "{main_dwo}" file exists')41 self.assertTrue(os.path.exists(foo_dwo), f'Make sure "{foo_dwo}" file exists')42 43 target = self.dbg.CreateTarget(exe)44 self.assertTrue(target, lldbtest.VALID_TARGET)45 46 self.runCmd("target modules dump separate-debug-info --json")47 48 # Check the output49 output = self.get_dwos_from_json_output()50 self.assertTrue(output[exe]["a.out-main.dwo"]["loaded"])51 self.assertTrue(output[exe]["a.out-foo.dwo"]["loaded"])52 53 def test_dwos_not_loaded_json_output(self):54 self.build_and_skip_if_error()55 exe = self.getBuildArtifact("a.out")56 main_dwo = self.getBuildArtifact("a.out-main.dwo")57 foo_dwo = self.getBuildArtifact("a.out-foo.dwo")58 59 # REMOVE one of the dwo files60 os.unlink(main_dwo)61 62 target = self.dbg.CreateTarget(exe)63 self.assertTrue(target, lldbtest.VALID_TARGET)64 65 self.runCmd("target modules dump separate-debug-info --json")66 67 # Check the output68 output = self.get_dwos_from_json_output()69 self.assertFalse(output[exe]["a.out-main.dwo"]["loaded"])70 self.assertIn("error", output[exe]["a.out-main.dwo"])71 self.assertTrue(output[exe]["a.out-foo.dwo"]["loaded"])72 self.assertNotIn("error", output[exe]["a.out-foo.dwo"])73 74 # Check with --errors-only75 self.runCmd("target modules dump separate-debug-info --json --errors-only")76 output = self.get_dwos_from_json_output()77 self.assertFalse(output[exe]["a.out-main.dwo"]["loaded"])78 self.assertIn("error", output[exe]["a.out-main.dwo"])79 self.assertNotIn("a.out-foo.dwo", output[exe])80 81 def test_dwos_loaded_table_output(self):82 self.build_and_skip_if_error()83 exe = self.getBuildArtifact("a.out")84 main_dwo = self.getBuildArtifact("a.out-main.dwo")85 foo_dwo = self.getBuildArtifact("a.out-foo.dwo")86 87 # Make sure dwo files exist88 self.assertTrue(os.path.exists(main_dwo), f'Make sure "{main_dwo}" file exists')89 self.assertTrue(os.path.exists(foo_dwo), f'Make sure "{foo_dwo}" file exists')90 91 target = self.dbg.CreateTarget(exe)92 self.assertTrue(target, lldbtest.VALID_TARGET)93 94 self.expect(95 "target modules dump separate-debug-info",96 patterns=[97 r"Symbol file: .*?a\.out",98 'Type: "dwo"',99 r"Dwo ID\s+Err\s+Dwo Path",100 r"0x[a-zA-Z0-9]{16}\s+.*main\.dwo",101 r"0x[a-zA-Z0-9]{16}\s+.*foo\.dwo",102 ],103 )104 105 def test_dwos_not_loaded_table_output(self):106 self.build_and_skip_if_error()107 exe = self.getBuildArtifact("a.out")108 main_dwo = self.getBuildArtifact("a.out-main.dwo")109 foo_dwo = self.getBuildArtifact("a.out-foo.dwo")110 111 # REMOVE the dwo files112 os.unlink(main_dwo)113 os.unlink(foo_dwo)114 115 target = self.dbg.CreateTarget(exe)116 self.assertTrue(target, lldbtest.VALID_TARGET)117 118 self.expect(119 "target modules dump separate-debug-info",120 patterns=[121 r"Symbol file: .*?a\.out",122 'Type: "dwo"',123 r"Dwo ID\s+Err\s+Dwo Path",124 r"0x[a-zA-Z0-9]{16}\s+E\s+.*main\.dwo",125 r"0x[a-zA-Z0-9]{16}\s+E\s+.*foo\.dwo",126 ],127 )128 129 def test_dwos_loaded_symbols_on_demand(self):130 self.build_and_skip_if_error()131 exe = self.getBuildArtifact("a.out")132 main_dwo = self.getBuildArtifact("a.out-main.dwo")133 foo_dwo = self.getBuildArtifact("a.out-foo.dwo")134 135 # Make sure dwo files exist136 self.assertTrue(os.path.exists(main_dwo), f'Make sure "{main_dwo}" file exists')137 self.assertTrue(os.path.exists(foo_dwo), f'Make sure "{foo_dwo}" file exists')138 139 # Load symbols on-demand140 self.runCmd("settings set symbols.load-on-demand true")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 # Check the output148 output = self.get_dwos_from_json_output()149 self.assertFalse(output[exe]["a.out-main.dwo"]["loaded"])150 self.assertFalse(output[exe]["a.out-foo.dwo"]["loaded"])151 # Set a breakpoint in main(). All DWO files should be loaded now152 self.runCmd("b main")153 self.runCmd("target modules dump separate-debug-info --json")154 output = self.get_dwos_from_json_output()155 self.assertTrue(output[exe]["a.out-main.dwo"]["loaded"])156 self.assertTrue(output[exe]["a.out-foo.dwo"]["loaded"])157 158 def test_dwos_load_json_with_debug_names_default(self):159 """160 Test that DWO files are lazily loaded, and target module dump gives the expected output.161 """162 # Build with split DWARF, debug_names, and gpubnames163 self.build_and_skip_if_error(debug_info=["debug_names"])164 exe = self.getBuildArtifact("a.out")165 166 main_dwo = self.getBuildArtifact("a.out-main.dwo")167 foo_dwo = self.getBuildArtifact("a.out-foo.dwo")168 169 # Make sure dwo files exist170 self.assertTrue(os.path.exists(main_dwo), f'Make sure "{main_dwo}" file exists')171 self.assertTrue(os.path.exists(foo_dwo), f'Make sure "{foo_dwo}" file exists')172 173 target = self.dbg.CreateTarget(exe)174 self.assertTrue(target, lldbtest.VALID_TARGET)175 176 self.runCmd("target modules dump separate-debug-info --j")177 178 # Check the output179 output = self.get_dwos_from_json_output()180 self.assertFalse(output[exe]["a.out-main.dwo"]["loaded"])181 self.assertFalse(output[exe]["a.out-foo.dwo"]["loaded"])182 183 # Set a breakpoint in main(). a.out-main.dwo should be loaded now184 self.runCmd("b main")185 self.runCmd("target modules dump separate-debug-info --j")186 output = self.get_dwos_from_json_output()187 self.assertTrue(output[exe]["a.out-main.dwo"]["loaded"])188 self.assertFalse(output[exe]["a.out-foo.dwo"]["loaded"])189 190 # Set a breakpoint in foo(). a.out-foo.dwo should be loaded now191 self.runCmd("b foo")192 self.runCmd("target modules dump separate-debug-info --j")193 output = self.get_dwos_from_json_output()194 self.assertTrue(output[exe]["a.out-main.dwo"]["loaded"])195 self.assertTrue(output[exe]["a.out-foo.dwo"]["loaded"])196 197 def test_dwos_load_json_with_debug_names_force_load_all(self):198 """199 Test that DWO files are lazily loaded, and target module dump gives the expected output.200 """201 # Build with split DWARF, debug_names, and gpubnames202 self.build_and_skip_if_error(debug_info=["debug_names"])203 exe = self.getBuildArtifact("a.out")204 205 main_dwo = self.getBuildArtifact("a.out-main.dwo")206 foo_dwo = self.getBuildArtifact("a.out-foo.dwo")207 208 # Make sure dwo files exist209 self.assertTrue(os.path.exists(main_dwo), f'Make sure "{main_dwo}" file exists')210 self.assertTrue(os.path.exists(foo_dwo), f'Make sure "{foo_dwo}" file exists')211 212 target = self.dbg.CreateTarget(exe)213 self.assertTrue(target, lldbtest.VALID_TARGET)214 215 self.runCmd("target modules dump separate-debug-info --j --f")216 217 output = self.get_dwos_from_json_output()218 self.assertTrue(output[exe]["a.out-main.dwo"]["loaded"])219 self.assertTrue(output[exe]["a.out-foo.dwo"]["loaded"])220