This should disable the failing test on the ubuntu build bots @JDevlieghere (I forgot to disable the 'baseline' test, as it tests the debugger's basic handling of DWP files, but again, the API infrastructure doesn't quite support DWP generation) https://github.com/llvm/llvm-project/pull/98344#issuecomment-2221000566
197 lines
7.3 KiB
Python
197 lines
7.3 KiB
Python
"""
|
|
Test support for the DebugInfoD network symbol acquisition protocol.
|
|
"""
|
|
import os
|
|
import shutil
|
|
import tempfile
|
|
|
|
import lldb
|
|
from lldbsuite.test.decorators import *
|
|
import lldbsuite.test.lldbutil as lldbutil
|
|
from lldbsuite.test.lldbtest import *
|
|
|
|
|
|
"""
|
|
Test support for the DebugInfoD network symbol acquisition protocol.
|
|
This file is for split-dwarf (dwp) scenarios.
|
|
|
|
1 - A split binary target with it's corresponding DWP file
|
|
2 - A stripped, split binary target with an unstripped binary and a DWP file
|
|
3 - A stripped, split binary target with an --only-keep-debug symbols file and a DWP file
|
|
"""
|
|
|
|
|
|
class DebugInfodDWPTests(TestBase):
|
|
# No need to try every flavor of debug inf.
|
|
NO_DEBUG_INFO_TESTCASE = True
|
|
|
|
@skipUnlessPlatform(["linux_freebsd_but_old_dwp_tools_on_build_bots_are_broken"])
|
|
def test_normal_stripped(self):
|
|
"""
|
|
Validate behavior with a stripped binary, no symbols or symbol locator.
|
|
"""
|
|
self.config_test(["a.out"])
|
|
self.try_breakpoint(False)
|
|
|
|
@skipUnlessPlatform(["linux_freebsd_but_old_dwp_tools_on_build_bots_are_broken"])
|
|
def test_normal_stripped_split_with_dwp(self):
|
|
"""
|
|
Validate behavior with symbols, but no symbol locator.
|
|
"""
|
|
self.config_test(["a.out", "a.out.debug", "a.out.dwp"])
|
|
self.try_breakpoint(True)
|
|
|
|
@skipUnlessPlatform(["linux_freebsd_but_old_dwp_tools_on_build_bots_are_broken"])
|
|
def test_normal_stripped_only_dwp(self):
|
|
"""
|
|
Validate behavior *with* dwp symbols only, but missing other symbols,
|
|
but no symbol locator. This shouldn't work: without the other symbols
|
|
DWO's appear mostly useless.
|
|
"""
|
|
self.config_test(["a.out", "a.out.dwp"])
|
|
self.try_breakpoint(False)
|
|
|
|
@skipIfCurlSupportMissing
|
|
@skipUnlessPlatform(["linux_freebsd_but_old_dwp_tools_on_build_bots_are_broken"])
|
|
def test_debuginfod_dwp_from_service(self):
|
|
"""
|
|
Test behavior with the unstripped binary, and DWP from the service.
|
|
"""
|
|
self.config_test(["a.out.debug"], "a.out.dwp")
|
|
self.try_breakpoint(True)
|
|
|
|
@skipIfCurlSupportMissing
|
|
@skipUnlessPlatform(["linux_freebsd_but_old_dwp_tools_on_build_bots_are_broken"])
|
|
def test_debuginfod_both_symfiles_from_service(self):
|
|
"""
|
|
Test behavior with a stripped binary, with the unstripped binary and
|
|
dwp symbols from Debuginfod.
|
|
"""
|
|
self.config_test(["a.out"], "a.out.dwp", "a.out.unstripped")
|
|
self.try_breakpoint(True)
|
|
|
|
@skipIfCurlSupportMissing
|
|
@skipUnlessPlatform(["linux_freebsd_but_old_dwp_tools_on_build_bots_are_broken"])
|
|
def test_debuginfod_both_okd_symfiles_from_service(self):
|
|
"""
|
|
Test behavior with both the only-keep-debug symbols and the dwp symbols
|
|
from Debuginfod.
|
|
"""
|
|
self.config_test(["a.out"], "a.out.dwp", "a.out.debug")
|
|
self.try_breakpoint(True)
|
|
|
|
def try_breakpoint(self, should_have_loc):
|
|
"""
|
|
This function creates a target from self.aout, sets a function-name
|
|
breakpoint, and checks to see if we have a file/line location,
|
|
as a way to validate that the symbols have been loaded.
|
|
should_have_loc specifies if we're testing that symbols have or
|
|
haven't been loaded.
|
|
"""
|
|
target = self.dbg.CreateTarget(self.aout)
|
|
self.assertTrue(target and target.IsValid(), "Target is valid")
|
|
|
|
bp = target.BreakpointCreateByName("func")
|
|
self.assertTrue(bp and bp.IsValid(), "Breakpoint is valid")
|
|
self.assertEqual(bp.GetNumLocations(), 1)
|
|
|
|
loc = bp.GetLocationAtIndex(0)
|
|
self.assertTrue(loc and loc.IsValid(), "Location is valid")
|
|
addr = loc.GetAddress()
|
|
self.assertTrue(addr and addr.IsValid(), "Loc address is valid")
|
|
line_entry = addr.GetLineEntry()
|
|
self.assertEqual(
|
|
should_have_loc,
|
|
line_entry != None and line_entry.IsValid(),
|
|
"Loc line entry is valid",
|
|
)
|
|
if should_have_loc:
|
|
self.assertEqual(line_entry.GetLine(), 4)
|
|
self.assertEqual(
|
|
line_entry.GetFileSpec().GetFilename(),
|
|
self.main_source_file.GetFilename(),
|
|
)
|
|
self.dbg.DeleteTarget(target)
|
|
shutil.rmtree(self.tmp_dir)
|
|
|
|
def config_test(self, local_files, debuginfo=None, executable=None):
|
|
"""
|
|
Set up a test with local_files[] copied to a different location
|
|
so that we control which files are, or are not, found in the file system.
|
|
Also, create a stand-alone file-system 'hosted' debuginfod server with the
|
|
provided debuginfo and executable files (if they exist)
|
|
|
|
Make the filesystem look like:
|
|
|
|
/tmp/<tmpdir>/test/[local_files]
|
|
|
|
/tmp/<tmpdir>/cache (for lldb to use as a temp cache)
|
|
|
|
/tmp/<tmpdir>/buildid/<uuid>/executable -> <executable>
|
|
/tmp/<tmpdir>/buildid/<uuid>/debuginfo -> <debuginfo>
|
|
Returns the /tmp/<tmpdir> path
|
|
"""
|
|
|
|
self.build()
|
|
|
|
uuid = self.getUUID("a.out")
|
|
if not uuid:
|
|
self.fail("Could not get UUID for a.out")
|
|
return
|
|
self.main_source_file = lldb.SBFileSpec("main.c")
|
|
self.tmp_dir = tempfile.mkdtemp()
|
|
self.test_dir = os.path.join(self.tmp_dir, "test")
|
|
os.makedirs(self.test_dir)
|
|
|
|
self.aout = ""
|
|
# Copy the files used by the test:
|
|
for f in local_files:
|
|
shutil.copy(self.getBuildArtifact(f), self.test_dir)
|
|
if self.aout == "":
|
|
self.aout = os.path.join(self.test_dir, f)
|
|
|
|
use_debuginfod = debuginfo != None or executable != None
|
|
|
|
# Populated the 'file://... mocked' Debuginfod server:
|
|
if use_debuginfod:
|
|
os.makedirs(os.path.join(self.tmp_dir, "cache"))
|
|
uuid_dir = os.path.join(self.tmp_dir, "buildid", uuid)
|
|
os.makedirs(uuid_dir)
|
|
if debuginfo:
|
|
shutil.copy(
|
|
self.getBuildArtifact(debuginfo),
|
|
os.path.join(uuid_dir, "debuginfo"),
|
|
)
|
|
if executable:
|
|
shutil.copy(
|
|
self.getBuildArtifact(executable),
|
|
os.path.join(uuid_dir, "executable"),
|
|
)
|
|
os.remove(self.getBuildArtifact("main.dwo"))
|
|
# Configure LLDB for the test:
|
|
self.runCmd(
|
|
"settings set symbols.enable-external-lookup %s"
|
|
% str(use_debuginfod).lower()
|
|
)
|
|
self.runCmd("settings clear plugin.symbol-locator.debuginfod.server-urls")
|
|
if use_debuginfod:
|
|
self.runCmd(
|
|
"settings set plugin.symbol-locator.debuginfod.cache-path %s/cache"
|
|
% self.tmp_dir
|
|
)
|
|
self.runCmd(
|
|
"settings insert-before plugin.symbol-locator.debuginfod.server-urls 0 file://%s"
|
|
% self.tmp_dir
|
|
)
|
|
|
|
def getUUID(self, filename):
|
|
try:
|
|
spec = lldb.SBModuleSpec()
|
|
spec.SetFileSpec(lldb.SBFileSpec(self.getBuildArtifact(filename)))
|
|
module = lldb.SBModule(spec)
|
|
uuid = module.GetUUIDString().replace("-", "").lower()
|
|
# Don't want lldb's fake 32 bit CRC's for this one
|
|
return uuid if len(uuid) > 8 else None
|
|
except:
|
|
return None
|