1""" 2Test 'target modules dump separate-debug-info' for dwo files. 3""" 4 5import json 6import os 7 8from lldbsuite.test import lldbtest, lldbutil 9from lldbsuite.test.decorators import * 10from lldbsuite.test_event.build_exception import BuildError 11 12 13class TestDumpDWO(lldbtest.TestBase): 14 NO_DEBUG_INFO_TESTCASE = True 15 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_entry 24 result[symfile_entry["symfile"]] = dwo_dict 25 return result 26 27 def build_and_skip_if_error(self): 28 try: 29 self.build() 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 exist 40 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 output 49 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 files 60 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 output 68 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-only 75 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 exist 88 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 "Symbol file: .*?a\.out", 98 'Type: "dwo"', 99 "Dwo ID\s+Err\s+Dwo Path", 100 "0x[a-zA-Z0-9]{16}\s+.*main\.dwo", 101 "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 files 112 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 "Symbol file: .*?a\.out", 122 'Type: "dwo"', 123 "Dwo ID\s+Err\s+Dwo Path", 124 "0x[a-zA-Z0-9]{16}\s+E\s+.*main\.dwo", 125 "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 exist 136 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-demand 140 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 output 148 output = self.get_dwos_from_json_output() 149 self.assertTrue(output[exe]["a.out-main.dwo"]["loaded"]) 150 self.assertTrue(output[exe]["a.out-foo.dwo"]["loaded"]) 151