diff --git a/llvm/docs/CommandGuide/dsymutil.rst b/llvm/docs/CommandGuide/dsymutil.rst --- a/llvm/docs/CommandGuide/dsymutil.rst +++ b/llvm/docs/CommandGuide/dsymutil.rst @@ -50,6 +50,11 @@ Print this help output. +.. option:: --keep-function-for-static + + Make a static variable keep the enclosing function even if it would have been + omitted otherwise. + .. option:: --minimize, -z When used when creating a dSYM file, this option will suppress the emission of diff --git a/llvm/include/llvm/DWARFLinker/DWARFLinker.h b/llvm/include/llvm/DWARFLinker/DWARFLinker.h --- a/llvm/include/llvm/DWARFLinker/DWARFLinker.h +++ b/llvm/include/llvm/DWARFLinker/DWARFLinker.h @@ -281,6 +281,11 @@ /// update existing DWARF info(for the linked binary). void setUpdate(bool Update) { Options.Update = Update; } + /// Set whether to keep the enclosing function for a static variable. + void setKeepFunctionForStatic(bool KeepFunctionForStatic) { + Options.KeepFunctionForStatic = KeepFunctionForStatic; + } + /// Use specified number of threads for parallel files linking. void setNumThreads(unsigned NumThreads) { Options.Threads = NumThreads; } @@ -782,6 +787,10 @@ /// Update bool Update = false; + /// Whether we want a static variable to force us to keep its enclosing + /// function. + bool KeepFunctionForStatic = false; + /// Number of threads. unsigned Threads = 1; diff --git a/llvm/lib/DWARFLinker/DWARFLinker.cpp b/llvm/lib/DWARFLinker/DWARFLinker.cpp --- a/llvm/lib/DWARFLinker/DWARFLinker.cpp +++ b/llvm/lib/DWARFLinker/DWARFLinker.cpp @@ -434,13 +434,15 @@ return Flags | TF_Keep; } - // See if there is a relocation to a valid debug map entry inside - // this variable's location. The order is important here. We want to - // always check if the variable has a valid relocation, so that the - // DIEInfo is filled. However, we don't want a static variable in a - // function to force us to keep the enclosing function. - if (!RelocMgr.hasLiveMemoryLocation(DIE, MyInfo) || - (Flags & TF_InFunctionScope)) + // See if there is a relocation to a valid debug map entry inside this + // variable's location. The order is important here. We want to always check + // if the variable has a valid relocation, so that the DIEInfo is filled. + // However, we don't want a static variable in a function to force us to keep + // the enclosing function, unless requested explicitly. + const bool HasLiveMemoryLocation = + RelocMgr.hasLiveMemoryLocation(DIE, MyInfo); + if (!HasLiveMemoryLocation || ((Flags & TF_InFunctionScope) && + !LLVM_UNLIKELY(Options.KeepFunctionForStatic))) return Flags; if (Options.Verbose) { diff --git a/llvm/test/tools/dsymutil/Inputs/private/tmp/keep_func/main.o b/llvm/test/tools/dsymutil/Inputs/private/tmp/keep_func/main.o new file mode 100644 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 GIT binary patch literal 0 Hc$@ + +static void Foo(void) +{ + typedef struct { + int x1; + int x2; + } FOO_VAR_TYPE; + static FOO_VAR_TYPE MyDummyVar __attribute__((aligned(4), used, section("TAD_VIRTUAL, TAD_DUMMY_DATA"), nocommon)); + printf("Foo called"); +} + +int main() +{ + Foo(); + return 1; +} + +$ clang++ -O2 -g main.cpp -c -o main.o +$ clang++ main.o -o main.out + +RUN: dsymutil -oso-prepend-path %p/../Inputs %p/../Inputs/private/tmp/keep_func/main.out -o %t.omit.dSYM +RUN: dsymutil -oso-prepend-path %p/../Inputs %p/../Inputs/private/tmp/keep_func/main.out -o %t.keep.dSYM -keep-function-for-static +RUN: llvm-dwarfdump %t.omit.dSYM | FileCheck %s --check-prefix OMIT +RUN: llvm-dwarfdump %t.keep.dSYM | FileCheck %s --check-prefix KEEP + +KEEP: DW_AT_name ("MyDummyVar") +KEEP: DW_AT_name ("FOO_VAR_TYPE") +KEEP: DW_AT_name ("x1") +KEEP: DW_AT_name ("x2") + +OMIT-NOT: DW_AT_name ("MyDummyVar") +OMIT-NOT: DW_AT_name ("FOO_VAR_TYPE") +OMIT-NOT: DW_AT_name ("x1") +OMIT-NOT: DW_AT_name ("x2") diff --git a/llvm/test/tools/dsymutil/cmdline.test b/llvm/test/tools/dsymutil/cmdline.test --- a/llvm/test/tools/dsymutil/cmdline.test +++ b/llvm/test/tools/dsymutil/cmdline.test @@ -11,6 +11,7 @@ CHECK: -flat CHECK: -gen-reproducer CHECK: -help +CHECK: -keep-function-for-static CHECK: -no-odr CHECK: -no-output CHECK: -no-swiftmodule-timestamp diff --git a/llvm/tools/dsymutil/DwarfLinkerForBinary.cpp b/llvm/tools/dsymutil/DwarfLinkerForBinary.cpp --- a/llvm/tools/dsymutil/DwarfLinkerForBinary.cpp +++ b/llvm/tools/dsymutil/DwarfLinkerForBinary.cpp @@ -325,6 +325,7 @@ GeneralLinker.setNumThreads(Options.Threads); GeneralLinker.setAccelTableKind(Options.TheAccelTableKind); GeneralLinker.setPrependPath(Options.PrependPath); + GeneralLinker.setKeepFunctionForStatic(Options.KeepFunctionForStatic); if (Options.Translator) GeneralLinker.setStringsTranslator(TranslationLambda); GeneralLinker.setWarningHandler( diff --git a/llvm/tools/dsymutil/LinkUtils.h b/llvm/tools/dsymutil/LinkUtils.h --- a/llvm/tools/dsymutil/LinkUtils.h +++ b/llvm/tools/dsymutil/LinkUtils.h @@ -42,6 +42,10 @@ /// Do not check swiftmodule timestamp bool NoTimestamp = false; + /// Whether we want a static variable to force us to keep its enclosing + /// function. + bool KeepFunctionForStatic = false; + /// Number of threads. unsigned Threads = 1; diff --git a/llvm/tools/dsymutil/Options.td b/llvm/tools/dsymutil/Options.td --- a/llvm/tools/dsymutil/Options.td +++ b/llvm/tools/dsymutil/Options.td @@ -24,6 +24,10 @@ HelpText<"Enable verbose mode.">, Group; +def keep_func_for_static: F<"keep-function-for-static">, + HelpText<"Make a static variable keep the enclosing function even if it would have been omitted otherwise.">, + Group; + def statistics: F<"statistics">, HelpText<"Print statistics about the contribution of each object file to " "the linked debug info. This prints a table after linking with the " diff --git a/llvm/tools/dsymutil/dsymutil.cpp b/llvm/tools/dsymutil/dsymutil.cpp --- a/llvm/tools/dsymutil/dsymutil.cpp +++ b/llvm/tools/dsymutil/dsymutil.cpp @@ -91,6 +91,7 @@ bool InputIsYAMLDebugMap = false; bool PaperTrailWarnings = false; bool Verify = false; + bool ForceKeepFunctionForStatic = false; std::string SymbolMap; std::string OutputFile; std::string Toolchain; @@ -230,6 +231,8 @@ Options.LinkOpts.Update = Args.hasArg(OPT_update); Options.LinkOpts.Verbose = Args.hasArg(OPT_verbose); Options.LinkOpts.Statistics = Args.hasArg(OPT_statistics); + Options.LinkOpts.KeepFunctionForStatic = + Args.hasArg(OPT_keep_func_for_static); if (opt::Arg *ReproducerPath = Args.getLastArg(OPT_use_reproducer)) { Options.ReproMode = ReproducerMode::Use;