1*e77ac42bSKevin Frei""" 2*e77ac42bSKevin FreiTest support for the DebugInfoD network symbol acquisition protocol. 3*e77ac42bSKevin Frei""" 4*e77ac42bSKevin Freiimport os 5*e77ac42bSKevin Freiimport shutil 6*e77ac42bSKevin Freiimport tempfile 7*e77ac42bSKevin Frei 8*e77ac42bSKevin Freiimport lldb 9*e77ac42bSKevin Freifrom lldbsuite.test.decorators import * 10*e77ac42bSKevin Freiimport lldbsuite.test.lldbutil as lldbutil 11*e77ac42bSKevin Freifrom lldbsuite.test.lldbtest import * 12*e77ac42bSKevin Frei 13*e77ac42bSKevin Frei 14*e77ac42bSKevin Frei""" 15*e77ac42bSKevin FreiTest support for the DebugInfoD network symbol acquisition protocol. 16*e77ac42bSKevin FreiThis file is for split-dwarf (dwp) scenarios. 17*e77ac42bSKevin Frei 18*e77ac42bSKevin Frei1 - A split binary target with it's corresponding DWP file 19*e77ac42bSKevin Frei2 - A stripped, split binary target with an unstripped binary and a DWP file 20*e77ac42bSKevin Frei3 - A stripped, split binary target with an --only-keep-debug symbols file and a DWP file 21*e77ac42bSKevin Frei""" 22*e77ac42bSKevin Frei 23*e77ac42bSKevin Frei 24*e77ac42bSKevin Freiclass DebugInfodDWPTests(TestBase): 25*e77ac42bSKevin Frei # No need to try every flavor of debug inf. 26*e77ac42bSKevin Frei NO_DEBUG_INFO_TESTCASE = True 27*e77ac42bSKevin Frei 28*e77ac42bSKevin Frei @skipUnlessPlatform(["linux_freebsd_but_old_dwp_tools_on_build_bots_are_broken"]) 29*e77ac42bSKevin Frei def test_normal_stripped(self): 30*e77ac42bSKevin Frei """ 31*e77ac42bSKevin Frei Validate behavior with a stripped binary, no symbols or symbol locator. 32*e77ac42bSKevin Frei """ 33*e77ac42bSKevin Frei self.config_test(["a.out"]) 34*e77ac42bSKevin Frei self.try_breakpoint(False) 35*e77ac42bSKevin Frei 36*e77ac42bSKevin Frei @skipUnlessPlatform(["linux_freebsd_but_old_dwp_tools_on_build_bots_are_broken"]) 37*e77ac42bSKevin Frei def test_normal_stripped_split_with_dwp(self): 38*e77ac42bSKevin Frei """ 39*e77ac42bSKevin Frei Validate behavior with symbols, but no symbol locator. 40*e77ac42bSKevin Frei """ 41*e77ac42bSKevin Frei self.config_test(["a.out", "a.out.debug", "a.out.dwp"]) 42*e77ac42bSKevin Frei self.try_breakpoint(True) 43*e77ac42bSKevin Frei 44*e77ac42bSKevin Frei @skipUnlessPlatform(["linux_freebsd_but_old_dwp_tools_on_build_bots_are_broken"]) 45*e77ac42bSKevin Frei def test_normal_stripped_only_dwp(self): 46*e77ac42bSKevin Frei """ 47*e77ac42bSKevin Frei Validate behavior *with* dwp symbols only, but missing other symbols, 48*e77ac42bSKevin Frei but no symbol locator. This shouldn't work: without the other symbols 49*e77ac42bSKevin Frei DWO's appear mostly useless. 50*e77ac42bSKevin Frei """ 51*e77ac42bSKevin Frei self.config_test(["a.out", "a.out.dwp"]) 52*e77ac42bSKevin Frei self.try_breakpoint(False) 53*e77ac42bSKevin Frei 54*e77ac42bSKevin Frei @skipIfCurlSupportMissing 55*e77ac42bSKevin Frei @skipUnlessPlatform(["linux_freebsd_but_old_dwp_tools_on_build_bots_are_broken"]) 56*e77ac42bSKevin Frei def test_debuginfod_dwp_from_service(self): 57*e77ac42bSKevin Frei """ 58*e77ac42bSKevin Frei Test behavior with the unstripped binary, and DWP from the service. 59*e77ac42bSKevin Frei """ 60*e77ac42bSKevin Frei self.config_test(["a.out.debug"], "a.out.dwp") 61*e77ac42bSKevin Frei self.try_breakpoint(True) 62*e77ac42bSKevin Frei 63*e77ac42bSKevin Frei @skipIfCurlSupportMissing 64*e77ac42bSKevin Frei @skipUnlessPlatform(["linux_freebsd_but_old_dwp_tools_on_build_bots_are_broken"]) 65*e77ac42bSKevin Frei def test_debuginfod_both_symfiles_from_service(self): 66*e77ac42bSKevin Frei """ 67*e77ac42bSKevin Frei Test behavior with a stripped binary, with the unstripped binary and 68*e77ac42bSKevin Frei dwp symbols from Debuginfod. 69*e77ac42bSKevin Frei """ 70*e77ac42bSKevin Frei self.config_test(["a.out"], "a.out.dwp", "a.out.unstripped") 71*e77ac42bSKevin Frei self.try_breakpoint(True) 72*e77ac42bSKevin Frei 73*e77ac42bSKevin Frei @skipIfCurlSupportMissing 74*e77ac42bSKevin Frei @skipUnlessPlatform(["linux_freebsd_but_old_dwp_tools_on_build_bots_are_broken"]) 75*e77ac42bSKevin Frei def test_debuginfod_both_okd_symfiles_from_service(self): 76*e77ac42bSKevin Frei """ 77*e77ac42bSKevin Frei Test behavior with both the only-keep-debug symbols and the dwp symbols 78*e77ac42bSKevin Frei from Debuginfod. 79*e77ac42bSKevin Frei """ 80*e77ac42bSKevin Frei self.config_test(["a.out"], "a.out.dwp", "a.out.debug") 81*e77ac42bSKevin Frei self.try_breakpoint(True) 82*e77ac42bSKevin Frei 83*e77ac42bSKevin Frei def try_breakpoint(self, should_have_loc): 84*e77ac42bSKevin Frei """ 85*e77ac42bSKevin Frei This function creates a target from self.aout, sets a function-name 86*e77ac42bSKevin Frei breakpoint, and checks to see if we have a file/line location, 87*e77ac42bSKevin Frei as a way to validate that the symbols have been loaded. 88*e77ac42bSKevin Frei should_have_loc specifies if we're testing that symbols have or 89*e77ac42bSKevin Frei haven't been loaded. 90*e77ac42bSKevin Frei """ 91*e77ac42bSKevin Frei target = self.dbg.CreateTarget(self.aout) 92*e77ac42bSKevin Frei self.assertTrue(target and target.IsValid(), "Target is valid") 93*e77ac42bSKevin Frei 94*e77ac42bSKevin Frei bp = target.BreakpointCreateByName("func") 95*e77ac42bSKevin Frei self.assertTrue(bp and bp.IsValid(), "Breakpoint is valid") 96*e77ac42bSKevin Frei self.assertEqual(bp.GetNumLocations(), 1) 97*e77ac42bSKevin Frei 98*e77ac42bSKevin Frei loc = bp.GetLocationAtIndex(0) 99*e77ac42bSKevin Frei self.assertTrue(loc and loc.IsValid(), "Location is valid") 100*e77ac42bSKevin Frei addr = loc.GetAddress() 101*e77ac42bSKevin Frei self.assertTrue(addr and addr.IsValid(), "Loc address is valid") 102*e77ac42bSKevin Frei line_entry = addr.GetLineEntry() 103*e77ac42bSKevin Frei self.assertEqual( 104*e77ac42bSKevin Frei should_have_loc, 105*e77ac42bSKevin Frei line_entry != None and line_entry.IsValid(), 106*e77ac42bSKevin Frei "Loc line entry is valid", 107*e77ac42bSKevin Frei ) 108*e77ac42bSKevin Frei if should_have_loc: 109*e77ac42bSKevin Frei self.assertEqual(line_entry.GetLine(), 4) 110*e77ac42bSKevin Frei self.assertEqual( 111*e77ac42bSKevin Frei line_entry.GetFileSpec().GetFilename(), 112*e77ac42bSKevin Frei self.main_source_file.GetFilename(), 113*e77ac42bSKevin Frei ) 114*e77ac42bSKevin Frei self.dbg.DeleteTarget(target) 115*e77ac42bSKevin Frei shutil.rmtree(self.tmp_dir) 116*e77ac42bSKevin Frei 117*e77ac42bSKevin Frei def config_test(self, local_files, debuginfo=None, executable=None): 118*e77ac42bSKevin Frei """ 119*e77ac42bSKevin Frei Set up a test with local_files[] copied to a different location 120*e77ac42bSKevin Frei so that we control which files are, or are not, found in the file system. 121*e77ac42bSKevin Frei Also, create a stand-alone file-system 'hosted' debuginfod server with the 122*e77ac42bSKevin Frei provided debuginfo and executable files (if they exist) 123*e77ac42bSKevin Frei 124*e77ac42bSKevin Frei Make the filesystem look like: 125*e77ac42bSKevin Frei 126*e77ac42bSKevin Frei /tmp/<tmpdir>/test/[local_files] 127*e77ac42bSKevin Frei 128*e77ac42bSKevin Frei /tmp/<tmpdir>/cache (for lldb to use as a temp cache) 129*e77ac42bSKevin Frei 130*e77ac42bSKevin Frei /tmp/<tmpdir>/buildid/<uuid>/executable -> <executable> 131*e77ac42bSKevin Frei /tmp/<tmpdir>/buildid/<uuid>/debuginfo -> <debuginfo> 132*e77ac42bSKevin Frei Returns the /tmp/<tmpdir> path 133*e77ac42bSKevin Frei """ 134*e77ac42bSKevin Frei 135*e77ac42bSKevin Frei self.build() 136*e77ac42bSKevin Frei 137*e77ac42bSKevin Frei uuid = self.getUUID("a.out") 138*e77ac42bSKevin Frei if not uuid: 139*e77ac42bSKevin Frei self.fail("Could not get UUID for a.out") 140*e77ac42bSKevin Frei return 141*e77ac42bSKevin Frei self.main_source_file = lldb.SBFileSpec("main.c") 142*e77ac42bSKevin Frei self.tmp_dir = tempfile.mkdtemp() 143*e77ac42bSKevin Frei self.test_dir = os.path.join(self.tmp_dir, "test") 144*e77ac42bSKevin Frei os.makedirs(self.test_dir) 145*e77ac42bSKevin Frei 146*e77ac42bSKevin Frei self.aout = "" 147*e77ac42bSKevin Frei # Copy the files used by the test: 148*e77ac42bSKevin Frei for f in local_files: 149*e77ac42bSKevin Frei shutil.copy(self.getBuildArtifact(f), self.test_dir) 150*e77ac42bSKevin Frei if self.aout == "": 151*e77ac42bSKevin Frei self.aout = os.path.join(self.test_dir, f) 152*e77ac42bSKevin Frei 153*e77ac42bSKevin Frei use_debuginfod = debuginfo != None or executable != None 154*e77ac42bSKevin Frei 155*e77ac42bSKevin Frei # Populated the 'file://... mocked' Debuginfod server: 156*e77ac42bSKevin Frei if use_debuginfod: 157*e77ac42bSKevin Frei os.makedirs(os.path.join(self.tmp_dir, "cache")) 158*e77ac42bSKevin Frei uuid_dir = os.path.join(self.tmp_dir, "buildid", uuid) 159*e77ac42bSKevin Frei os.makedirs(uuid_dir) 160*e77ac42bSKevin Frei if debuginfo: 161*e77ac42bSKevin Frei shutil.copy( 162*e77ac42bSKevin Frei self.getBuildArtifact(debuginfo), 163*e77ac42bSKevin Frei os.path.join(uuid_dir, "debuginfo"), 164*e77ac42bSKevin Frei ) 165*e77ac42bSKevin Frei if executable: 166*e77ac42bSKevin Frei shutil.copy( 167*e77ac42bSKevin Frei self.getBuildArtifact(executable), 168*e77ac42bSKevin Frei os.path.join(uuid_dir, "executable"), 169*e77ac42bSKevin Frei ) 170*e77ac42bSKevin Frei os.remove(self.getBuildArtifact("main.dwo")) 171*e77ac42bSKevin Frei # Configure LLDB for the test: 172*e77ac42bSKevin Frei self.runCmd( 173*e77ac42bSKevin Frei "settings set symbols.enable-external-lookup %s" 174*e77ac42bSKevin Frei % str(use_debuginfod).lower() 175*e77ac42bSKevin Frei ) 176*e77ac42bSKevin Frei self.runCmd("settings clear plugin.symbol-locator.debuginfod.server-urls") 177*e77ac42bSKevin Frei if use_debuginfod: 178*e77ac42bSKevin Frei self.runCmd( 179*e77ac42bSKevin Frei "settings set plugin.symbol-locator.debuginfod.cache-path %s/cache" 180*e77ac42bSKevin Frei % self.tmp_dir 181*e77ac42bSKevin Frei ) 182*e77ac42bSKevin Frei self.runCmd( 183*e77ac42bSKevin Frei "settings insert-before plugin.symbol-locator.debuginfod.server-urls 0 file://%s" 184*e77ac42bSKevin Frei % self.tmp_dir 185*e77ac42bSKevin Frei ) 186*e77ac42bSKevin Frei 187*e77ac42bSKevin Frei def getUUID(self, filename): 188*e77ac42bSKevin Frei try: 189*e77ac42bSKevin Frei spec = lldb.SBModuleSpec() 190*e77ac42bSKevin Frei spec.SetFileSpec(lldb.SBFileSpec(self.getBuildArtifact(filename))) 191*e77ac42bSKevin Frei module = lldb.SBModule(spec) 192*e77ac42bSKevin Frei uuid = module.GetUUIDString().replace("-", "").lower() 193*e77ac42bSKevin Frei # Don't want lldb's fake 32 bit CRC's for this one 194*e77ac42bSKevin Frei return uuid if len(uuid) > 8 else None 195*e77ac42bSKevin Frei except: 196*e77ac42bSKevin Frei return None 197