| """Test the LLDB module cache funcionality.""" | |
| import glob | |
| import lldb | |
| from lldbsuite.test.decorators import * | |
| from lldbsuite.test.lldbtest import * | |
| from lldbsuite.test import lldbutil | |
| import os | |
| import time | |
| class ModuleCacheTestcaseBSD(TestBase): | |
| SHARED_BUILD_TESTCASE = False | |
| def setUp(self): | |
| # Call super's setUp(). | |
| TestBase.setUp(self) | |
| # Find the line number in a(int) to break at. | |
| self.line_a = line_number("a.c", "// Set file and line breakpoint inside a().") | |
| self.line_b = line_number("b.c", "// Set file and line breakpoint inside b().") | |
| self.line_c = line_number("c.c", "// Set file and line breakpoint inside c().") | |
| self.cache_dir = os.path.join(self.getBuildDir(), "lldb-module-cache") | |
| # Set the lldb module cache directory to a directory inside the build | |
| # artifacts directory so no other tests are interfered with. | |
| self.runCmd( | |
| 'settings set symbols.lldb-index-cache-path "%s"' % (self.cache_dir) | |
| ) | |
| self.runCmd("settings set symbols.enable-lldb-index-cache true") | |
| self.build() | |
| def get_module_cache_files(self, basename): | |
| module_cache_glob = os.path.join( | |
| self.cache_dir, "llvmcache-*%s*symtab*" % (basename) | |
| ) | |
| return glob.glob(module_cache_glob) | |
| # Requires no dSYM, so we let the Makefile make the right stuff for us | |
| @no_debug_info_test | |
| @skipUnlessDarwin | |
| def test(self): | |
| """ | |
| This test has been modified to make sure .o files that don't have | |
| UUIDs are not cached after discovering build systems that play with | |
| modification times of .o files that the modification times are not | |
| unique enough to ensure the .o file within the .a file are the right | |
| files as this was causing older cache files to be accepted for new | |
| updated .o files. | |
| ELF .o files do calculate a UUID from the contents of the file, | |
| which is expensive, but no one loads .o files into a debug sessions | |
| when using ELF files. Mach-o .o files do not have UUID values and do | |
| no calculate one as they _are_ used during debug sessions when no | |
| dSYM file is generated. If we can find a way to uniquely and cheaply | |
| create UUID values for mach-o .o files in the future, this test will | |
| be updated to test this functionality. This test will now make sure | |
| there are no cache entries for any .o files in BSD archives. | |
| The old test case description is below in case we enable caching for | |
| .o files again: | |
| Test module cache functionality for bsd archive object files. | |
| This will test that if we enable the module cache, we have a | |
| corresponding cache entry for the .o files in libfoo.a. | |
| The static library has two entries for "a.o": | |
| - one from a.c | |
| - one from c.c which had c.o renamed to a.o and then put into the | |
| libfoo.a as an extra .o file with different contents from the | |
| original a.o | |
| We do this to test that we can correctly cache duplicate .o files | |
| that appear in .a files. | |
| This test only works on darwin because of the way DWARF is stored | |
| where the debug map will refer to .o files inside of .a files. | |
| """ | |
| exe = self.getBuildArtifact("a.out") | |
| # Create a module with no dependencies. | |
| target = self.createTestTarget(load_dependent_modules=False) | |
| self.runCmd("breakpoint set -f a.c -l %d" % (self.line_a)) | |
| self.runCmd("breakpoint set -f b.c -l %d" % (self.line_b)) | |
| self.runCmd("breakpoint set -f c.c -l %d" % (self.line_c)) | |
| # Get the executable module and get the number of symbols to make | |
| # sure the symbol table gets parsed and cached. The module cache is | |
| # enabled in the setUp() function. | |
| main_module = target.GetModuleAtIndex(0) | |
| self.assertTrue(main_module.IsValid()) | |
| # Make sure the symbol table gets loaded and cached | |
| main_module.GetNumSymbols() | |
| a_o_cache_files = self.get_module_cache_files("libfoo.a(a.o)") | |
| b_o_cache_files = self.get_module_cache_files("libfoo.a(b.o)") | |
| # We expect the directory for a.o to have two cache directories: | |
| # - 1 for the a.o with a earlier mod time | |
| # - 1 for the a.o that was renamed from c.o that should be 2 seconds older | |
| # self.assertEqual(len(a_o_cache_files), 2, | |
| # "make sure there are two files in the module cache directory (%s) for libfoo.a(a.o)" % (self.cache_dir)) | |
| # self.assertEqual(len(b_o_cache_files), 1, | |
| # "make sure there are two files in the module cache directory (%s) for libfoo.a(b.o)" % (self.cache_dir)) | |
| # We are no longer caching .o files in the lldb index cache. If we ever | |
| # re-enable this functionality, we can uncomment out the above lines of | |
| # code. | |
| self.assertEqual( | |
| len(a_o_cache_files), | |
| 0, | |
| "make sure there are no files in the module cache directory (%s) for libfoo.a(a.o)" | |
| % (self.cache_dir), | |
| ) | |
| self.assertEqual( | |
| len(b_o_cache_files), | |
| 0, | |
| "make sure there are no files in the module cache directory (%s) for libfoo.a(b.o)" | |
| % (self.cache_dir), | |
| ) |