blob: 98569d2b8c66fbac7c2bd72c399ee9062336ff76 [file] [log] [blame] [edit]
import os
import shutil
import lldb
from lldbsuite.test.decorators import *
from lldbsuite.test.lldbtest import *
"""
Test debug symbol acquisition from a local SymStore repository. This can work
cross-platform and for arbitrary debug info formats. We only support PDB
currently.
"""
class MockedSymStore:
"""
Context Manager to populate a file structure equivalent to SymStore.exe
"""
def __init__(self, test, exe, pdb):
self._test = test
self._exe = exe
self._pdb = pdb
def get_key_pdb(self, exe):
"""
Module UUID: 12345678-1234-5678-9ABC-DEF012345678-00000001
To SymStore key: 12345678123456789ABCDEF0123456781
"""
spec = lldb.SBModuleSpec()
spec.SetFileSpec(lldb.SBFileSpec(self._test.getBuildArtifact(exe)))
module = lldb.SBModule(spec)
raw = module.GetUUIDString().replace("-", "").upper()
if len(raw) != 40:
raise RuntimeError("Unexpected number of bytes in embedded UUID")
guid_hex = raw[:32]
age = int(raw[32:], 16)
return guid_hex + str(age)
def __enter__(self):
"""
Mock local symstore directory tree, move PDB there and report path.
"""
key = None
if self._test.getDebugInfo() == "pdb":
key = self.get_key_pdb(self._exe)
self._test.assertIsNotNone(key)
symstore_dir = self._test.getBuildArtifact("symstore")
pdb_dir = os.path.join(symstore_dir, self._pdb, key)
os.makedirs(pdb_dir, exist_ok=True)
shutil.move(
self._test.getBuildArtifact(self._pdb),
os.path.join(pdb_dir, self._pdb),
)
return symstore_dir
def __exit__(self, *exc_info):
"""
Reset settings
"""
self._test.runCmd("settings clear plugin.symbol-locator.symstore")
class SymStoreLocalTests(TestBase):
SHARED_BUILD_TESTCASE = False
TEST_WITH_PDB_DEBUG_INFO = True
def build_inferior(self):
if self.getDebugInfo() != "pdb":
self.skipTest("Non-PDB debug info variants not yet supported")
self.build()
exe_file = "a.out"
sym_file = "a.pdb"
self.assertTrue(os.path.isfile(self.getBuildArtifact(exe_file)))
self.assertTrue(os.path.isfile(self.getBuildArtifact(sym_file)))
return exe_file, sym_file
def try_breakpoint(self, exe, should_have_loc, ext_lookup=True):
enable = "true" if ext_lookup else "false"
self.runCmd(f"settings set symbols.enable-external-lookup {enable}")
target = self.dbg.CreateTarget(self.getBuildArtifact(exe))
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 if should_have_loc else 0)
self.dbg.DeleteTarget(target)
def test_no_symstore_url(self):
"""
Check that breakpoint doesn't resolve without SymStore.
"""
exe, sym = self.build_inferior()
with MockedSymStore(self, exe, sym):
self.try_breakpoint(exe, should_have_loc=False)
def test_external_lookup_off(self):
"""
Check that breakpoint doesn't resolve with external lookup disabled.
"""
exe, sym = self.build_inferior()
with MockedSymStore(self, exe, sym) as symstore_dir:
self.runCmd(
f"settings set plugin.symbol-locator.symstore.urls {symstore_dir}"
)
self.try_breakpoint(exe, ext_lookup=False, should_have_loc=False)
def test_local_dir(self):
"""
Check that breakpoint resolves with local SymStore.
"""
exe, sym = self.build_inferior()
with MockedSymStore(self, exe, sym) as symstore_dir:
self.runCmd(
f"settings set plugin.symbol-locator.symstore.urls {symstore_dir}"
)
self.try_breakpoint(exe, should_have_loc=True)