diff --git a/lldb/packages/Python/lldbsuite/test/builders/builder.py b/lldb/packages/Python/lldbsuite/test/builders/builder.py --- a/lldb/packages/Python/lldbsuite/test/builders/builder.py +++ b/lldb/packages/Python/lldbsuite/test/builders/builder.py @@ -238,6 +238,31 @@ # False signifies that we cannot handle building with dSYM. return False + def buildDWZ(self, + sender=None, + architecture=None, + compiler=None, + dictionary=None, + testdir=None, + testname=None): + """Build the binaries with DWZ - a DWARF optimization tool.""" + commands = [] + commands.append( + self.getMake(testdir, testname) + [ + "MAKE_DSYM=NO", "DWZ=YES", + self.getArchCFlags(architecture), + self.getArchSpec(architecture), + self.getCCSpec(compiler), + self.getExtraMakeArgs(), + self.getSDKRootSpec(), + self.getModuleCacheSpec(), + self.getCmdLine(dictionary) + ]) + + self.runBuildCommands(commands, sender=sender) + # True signifies that we can handle building with DWZ. + return True + def cleanup(self, sender=None, dictionary=None): """Perform a platform-specific cleanup after the test.""" return True diff --git a/lldb/packages/Python/lldbsuite/test/dotest.py b/lldb/packages/Python/lldbsuite/test/dotest.py --- a/lldb/packages/Python/lldbsuite/test/dotest.py +++ b/lldb/packages/Python/lldbsuite/test/dotest.py @@ -871,6 +871,33 @@ configuration.skip_categories.append("fork") +def canRunDWZTests(): + from lldbsuite.test import lldbplatformutil + + platform = lldbplatformutil.getPlatform() + + if platform == "linux": + import distutils.spawn + + if not os.access("/usr/lib/rpm/sepdebugcrcfix", os.X_OK): + return False, "Unable to find /usr/lib/rpm/sepdebugcrcfix" + if distutils.spawn.find_executable("eu-strip") is None: + return False, "Unable to find executable eu-strip" + if distutils.spawn.find_executable("dwz") is None: + return False, "Unable to find executable dwz" + return True, "/usr/lib/rpm/sepdebugcrcfix, eu-strip and dwz found" + + return False, "Don't know how to build with DWZ on %s" % platform + +def checkDWZSupport(): + result, reason = canRunDWZTests() + if result: + return # dwz supported + if "dwz" in configuration.categories_list: + return # dwz category explicitly requested, let it run. + print("dwz tests will not be run because: " + reason) + configuration.skip_categories.append("dwz") + def run_suite(): # On MacOS X, check to make sure that domain for com.apple.DebugSymbols defaults # does not exist before proceeding to running the test suite. @@ -966,6 +993,7 @@ checkDebugServerSupport() checkObjcSupport() checkForkVForkSupport() + checkDWZSupport() print("Skipping the following test categories: {}".format(configuration.skip_categories)) diff --git a/lldb/packages/Python/lldbsuite/test/lldbinline.py b/lldb/packages/Python/lldbsuite/test/lldbinline.py --- a/lldb/packages/Python/lldbsuite/test/lldbinline.py +++ b/lldb/packages/Python/lldbsuite/test/lldbinline.py @@ -120,6 +120,14 @@ self.build(dictionary=self._build_dict) self.do_test() + @add_test_categories(["dwz"]) + def __test_with_dwz(self): + self.using_dsym = False + self.BuildMakefile() + self.build() + self.do_test() + __test_with_dwz.debug_info = "dwz" + def execute_user_command(self, __command): exec(__command, globals(), locals()) diff --git a/lldb/packages/Python/lldbsuite/test/lldbtest.py b/lldb/packages/Python/lldbsuite/test/lldbtest.py --- a/lldb/packages/Python/lldbsuite/test/lldbtest.py +++ b/lldb/packages/Python/lldbsuite/test/lldbtest.py @@ -1660,6 +1660,23 @@ dictionary, testdir, testname): raise Exception("Don't know how to build binary with gmodules") + def buildDWZ( + self, + architecture=None, + compiler=None, + dictionary=None): + """Platform specific way to build binaries with dwz optimizer.""" + testdir = self.mydir + testname = self.getBuildDirBasename() + if self.getDebugInfo() != "dwz": + raise Exception("NO_DEBUG_INFO_TESTCASE must build with buildDefault") + + module = builder_module() + dictionary = lldbplatformutil.finalize_build_dictionary(dictionary) + if not module.buildDWZ(self, architecture, compiler, + dictionary, testdir, testname): + raise Exception("Don't know how to build binary with dwz") + def signBinary(self, binary_path): if sys.platform.startswith("darwin"): codesign_cmd = "codesign --force --sign \"%s\" %s" % ( @@ -2649,6 +2666,8 @@ return self.buildDwo(architecture, compiler, dictionary) elif self.getDebugInfo() == "gmodules": return self.buildGModules(architecture, compiler, dictionary) + elif self.getDebugInfo() == "dwz": + return self.buildDWZ(architecture, compiler, dictionary) else: self.fail("Can't build for debug info: %s" % self.getDebugInfo()) diff --git a/lldb/packages/Python/lldbsuite/test/make/Makefile.rules b/lldb/packages/Python/lldbsuite/test/make/Makefile.rules --- a/lldb/packages/Python/lldbsuite/test/make/Makefile.rules +++ b/lldb/packages/Python/lldbsuite/test/make/Makefile.rules @@ -26,6 +26,7 @@ # SPLIT_DEBUG_SYMBOLS := YES # CROSS_COMPILE := # USE_PRIVATE_MODULE_CACHE := YES +# DWZ := YES # Uncomment line below for debugging shell commands # SHELL = /bin/sh -x @@ -198,8 +199,12 @@ override ARCHFLAG := - endif - ifeq "$(SPLIT_DEBUG_SYMBOLS)" "YES" - DSYM = $(EXE).debug + ifeq "$(DWZ)" "YES" + # DWZ always does SPLIT_DEBUG_SYMBOLS (as otherwise the dwz command fails) + else + ifeq "$(SPLIT_DEBUG_SYMBOLS)" "YES" + DSYM = $(EXE).debug + endif endif endif @@ -355,6 +360,26 @@ LDFLAGS += -pie endif +#---------------------------------------------------------------------- +# Make the DWZ symbol file from the executable if $(DWZ) = "YES" +# The dwz retry without -m is there because: +# dwz -m still succeeds even for no debug info present (missing -g): +# dwz: $(1).debug: .debug_info section not present +# But dwz -m fails if there is some debug info but none if it is big enough +# to be shared from the the common file $(1).debug.dwz: +# dwz: $(1).debug.dwz: .debug_info section not present +#---------------------------------------------------------------------- +ifeq "$(DWZ)" "YES" + dwz_strip = \ + eu-strip --remove-comment -f "$(1).debug" "$(1)" \ + && cp "$(1).debug" "$(1).debug.dup" \ + && (dwz -m "$(1).debug.dwz" -M $$(basename "$(1).debug.dwz") "$(1).debug" "$(1).debug.dup" \ + || dwz "$(1).debug") \ + && /usr/lib/rpm/sepdebugcrcfix . "$$(realpath --relative-to=$$PWD "$(1)")" +else + dwz_strip = +endif + #---------------------------------------------------------------------- # Windows specific options #---------------------------------------------------------------------- @@ -490,6 +515,7 @@ ifeq "$(DYLIB_ONLY)" "" $(EXE) : $(OBJECTS) $(DYLIB_FILENAME) $(LD) $(OBJECTS) -L. -l$(DYLIB_NAME) $(LDFLAGS) -o "$(EXE)" + $(call dwz_strip,$(EXE)) ifneq "$(CODESIGN)" "" $(CODESIGN) -s - "$(EXE)" endif @@ -499,6 +525,7 @@ else $(EXE) : $(OBJECTS) $(LD) $(OBJECTS) $(LDFLAGS) -o "$(EXE)" + $(call dwz_strip,$(EXE)) ifneq "$(CODESIGN)" "" $(CODESIGN) -s - "$(EXE)" endif @@ -559,11 +586,16 @@ endif else $(LD) $(DYLIB_OBJECTS) $(LDFLAGS) -shared -o "$(DYLIB_FILENAME)" +ifeq "$(DWZ)" "YES" + # DWZ always does SPLIT_DEBUG_SYMBOLS (as otherwise the dwz command fails) + $(call dwz_strip,$(DYLIB_FILENAME)) +else ifeq "$(SPLIT_DEBUG_SYMBOLS)" "YES" $(OBJCOPY) --only-keep-debug "$(DYLIB_FILENAME)" "$(DYLIB_FILENAME).debug" $(OBJCOPY) --strip-debug --add-gnu-debuglink="$(DYLIB_FILENAME).debug" "$(DYLIB_FILENAME)" "$(DYLIB_FILENAME)" endif endif +endif #---------------------------------------------------------------------- # Make the precompiled header and compile C++ sources against it diff --git a/lldb/packages/Python/lldbsuite/test/test_categories.py b/lldb/packages/Python/lldbsuite/test/test_categories.py --- a/lldb/packages/Python/lldbsuite/test/test_categories.py +++ b/lldb/packages/Python/lldbsuite/test/test_categories.py @@ -15,7 +15,7 @@ debug_info_categories = [ - 'dwarf', 'dwo', 'dsym', 'gmodules' + 'dwarf', 'dwo', 'dsym', 'gmodules', 'dwz' ] all_categories = { @@ -26,6 +26,7 @@ 'dsym': 'Tests that can be run with DSYM debug information', 'dwarf': 'Tests that can be run with DWARF debug information', 'dwo': 'Tests that can be run with DWO debug information', + 'dwz': 'Tests using DWZ and its DWARF partial units', 'dyntype': 'Tests related to dynamic type support', 'expression': 'Tests related to the expression parser', 'flakey': 'Flakey test cases, i.e. tests that do not reliably pass at each execution', @@ -67,6 +68,8 @@ if platform not in ["freebsd", "darwin", "macosx", "ios", "watchos", "tvos", "bridgeos"]: return False return gmodules.is_compiler_clang_with_gmodules(compiler_path) + elif category == "dwz": + return platform in ["linux"] return True diff --git a/lldb/test/API/lang/cpp/template-function/TestTemplateFunctions.py b/lldb/test/API/lang/cpp/template-function/TestTemplateFunctions.py --- a/lldb/test/API/lang/cpp/template-function/TestTemplateFunctions.py +++ b/lldb/test/API/lang/cpp/template-function/TestTemplateFunctions.py @@ -53,6 +53,6 @@ self.do_test_template_function(True) @skipIfWindows - @expectedFailureAll(debug_info=["dwarf", "gmodules", "dwo"]) + @expectedFailureAll(debug_info=["dwarf", "gmodules", "dwo", "dwz"]) def test_template_function_without_cast(self): self.do_test_template_function(False)